Showing posts with label UDF. Show all posts
Showing posts with label UDF. Show all posts

Monday, November 01, 2010

Book review: MySQL 5.1 plugin development

MySQL 5.1 Plugin Development MySQL 5.1 Plugin Development,
by Sergei Golubchik and Andrew Hutchings.
Packt Publishing, 2010.
Executive summary: Highly recommended. If you want to develop MySQL extensions, buy this book. It's a must, written by two expert professionals who probably know more than anyone else on this matter. The book is full of practical examples explained with the theoretical information necessary to make it stick.

This book fills a gap in the world of MySQL documentation. Although the MySQL docs are extensive and thorough, to the point that sometimes you wished that the writers were less verbose and stick more to the topic, when it comes to the plugin architecture, there are still more some unanswered questions. I guess that the ones who have implemented MySQL extensions so far have read the code, more than the documentation.
But, back to the point. The void is filled now, and in such a wonderful way! I have to disclose that I was the reviewer of this book, and while this fact puts me in a conflicting position when it comes to a review, it has also given me inner reason for praise, beyond the experience of a regular reader. The people who have worked with me will know that I am hard to please, and so my review was peppered with suggestions for improvements that, I admit it, made the authors' life quite difficult. I mostly complained that some of the examples proposed for each chapter were not enough useful and interesting. In short, there was not enough incentive for the reader to start coding immediately. I am glad to report that the authors were very responsive, and, rather than being annoyed by my demands, did work enthusiastically at the examples in the book until they became a true gem in this category. This book will surprise you for its practical approach, when it guides you through the examples, until you end up with a working extension.
The first chapter is probably the part that will save many hours of attempts to everyone who wants to build a plugin. In that chapter the authors explain how to build the different types of plugins in several operating systems. If you have ever tried to build a plugin, you will appreciate this chapter.
The book's body covers every type of plugin that you can create in MySQL, from the classic UDF to the more recent storage engine. For each chapter, you will have code ready to compile and try on your own, and the line-by-line explanation of what that code does, and why it was written the way it is.
Whenever the code is less than intuitive, the authors take care of it with additional theoretical and practical explanation, making sure that the reader is fully informed on the topic, and can complete the task effectively.
Summing up, this is not a book for the idle reader. It's a a practical help for the doers, the ones who want to get the job done, and need guidance through the maze of the MySQL plugin protocol.

Update. There is also a review at Slashdot.

Wednesday, January 20, 2010

Multi dimensional cubes in MySQL through Gearman


MySQL cubes with Gearman

I gave two presentations about Gearman at the Linux.conf.au. As part of the preparation for these talks, I created several sample applications. One of them, about remote replication administration, I will cover in a separate post. The most amazing one, which I cover here, is a quick and painless solution for multiple level crosstabs in MySQL.

Some background is needed. Crosstabs (also called data cubes or pivot tables, have been one of my favorite hacks for long time. In 2001 I wrote an article about a simple way of doing single level crosstabs. A few years later, I developed a Perl module that generates multiple levels of data cubes in most any database systems. Since then, I have received countless requests to convert this module to PHP, Python, Java, and I have always declined, for lack of time or abilities.
In the coming years, I tackled the same problem using MySQL Proxy and some SQL hacks. Both attempts were not completely satisfactory. The options offered by the Perl module are simply too hard to replicate to any other system.
When I started using Gearman, I realized that I could use the original Perl module through a Gearman worker, without converting to any other language. The idea is to write a simple worker that accepts some parameters and runs the Perl module to return a crosstab query to the client. The query being the most complicated thing to generate, the architecture could look like the image below.

To take the idea one step further, I used the Gearman UDF for MySQL, which makes the crosstab function available at the SQL level, thus being transparent no matter which programming language the client uses, and without need of using the Gearman API.

In this scenario, what you need to do is just querying the worker (through the UDF), with a simple string of parameters.

mysql> set @q = (select gman_do('crosstab',
'from=all_personnel;op=sum salary;rows=country;cols=gender'));

mysql> prepare q from @q; execute q;
+---------+-------+-------+-------+
| country | m | f | total |
+---------+-------+-------+-------+
| Germany | 16000 | 11000 | 27000 |
| Italy | 6000 | 6000 | 12000 |
| UK | 10500 | NULL | 10500 |
| zzzz | 32500 | 17000 | 49500 |
+---------+-------+-------+-------+

Here's a taste of a 2 levels cube:
set @q = (select gman_do('crosstab','from=all_personnel;op=count salary;rows=country,location;cols=department,gender'));
Query OK, 0 rows affected (0.03 sec)

prepare q from @q; execute q;Query OK, 0 rows affected (0.00 sec)
Statement prepared

+---------+----------+--------+--------+------+---------+---------+-------+-------+-------+-----+-------+
| country | location | pers#m | pers#f | pers | sales#m | sales#f | sales | dev#m | dev#f | dev | total |
+---------+----------+--------+--------+------+---------+---------+-------+-------+-------+-----+-------+
| Germany | Berlin | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 2 |
| Germany | Bonn | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 |
| Germany | Munich | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 2 |
| Germany | zzzz | 1 | 1 | 2 | 1 | 1 | 2 | 1 | 0 | 1 | 5 |
| Italy | Rome | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 2 |
| Italy | zzzz | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 2 |
| UK | London | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 2 |
| UK | zzzz | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 2 |
| zzzz | zzzz | 3 | 1 | 4 | 2 | 1 | 3 | 1 | 1 | 2 | 9 |
+---------+----------+--------+--------+------+---------+---------+-------+-------+-------+-----+-------+

It would be nice to actually format the result in a more human readable way, like this one, but it will require some more work.

+---------+----------+--------------+-----------------+-------------+-------+
| country | location | pers |sales | dev | total |
| | +---+---+------+----+----+-------+---+---+-----+-------+
| | | m | f | pers | m | f | sales | m | f | dev | total |
+---------+----------+---+---+------+----+----+-------+---+---+-----+-------+
| Germany | Berlin | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 2 |
| Germany | Bonn | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 |
| Germany | Munich | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 2 |
| Germany | total | 1 | 1 | 2 | 1 | 1 | 2 | 1 | 0 | 1 | 5 |
+---------+----------+---+---+------+----+----+-------+---+---+-----+-------+
| Italy | Rome | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 2 |
| Italy | total | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 2 |
+---------+----------+---+---+------+----+----+-------+---+---+-----+-------+
| UK | London | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 2 |
| UK | total | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 2 |
+---------+----------+---+---+------+----+----+-------+---+---+-----+-------+
| total | total | 3 | 1 | 4 | 2 | 1 | 3 | 1 | 1 | 2 | 9 |
+---------+----------+---+---+------+----+----+-------+---+---+-----+-------+

To make the above examples work, what's missing is the worker. You can try the sample crosstab worker from MySQL Forge.

Thursday, November 12, 2009

Gearman for MySQL


Gearman for MySQL
If you haven't yet heard about Gearman, it's time to have a look at it. Its distributed client server architecture are a perfect match for today's cloud oriented applications.
When talking about Gearman, much stress is often given on its scalability features, such as map/reduce and distributed loads. But Gearman has also a distinctive advantage in the feature department, because of its design that I like to describe as cooperation of the fittest.
While a traditional application is written entirely in a given language, or it must find ways of integrating multiple languages parts, Gearman encourages easy cooperation between parts written in different languages, eliminating the need for library translation, and allowing the best implementation of a feature to be used by another part of the application.
Today, November 12, at 14:00 UTC, there will be a MySQL University presentation on Gearman for MySQL.
One of the components created by Gearman enthusiasts is a MySQL Gearman UDF. Using this extension, you can easily define functions in any language you are familiar with, and then call that function from MySQL. Some examples shown in the presentation include shell access, regular expressions enhancements, storing results incrementally in a file, using language-specific library extensions, and your imagination can do the rest.
Using this sample worker code, you can then call the UDF function from MySQL with something like thge following:

select gman_do('reverse','abcd') as test;
+------+
| test |
+------+
| dcba |
+------+

SELECT gman_do('shell',
concat(' ls -lh ',
(select variable_value from information_schema.global_variables
where variable_name = "datadir" )))\G

total 40976
-rw-rw---- 1 gmax staff 5.0M Nov 11 13:34 ib_logfile0
-rw-rw---- 1 gmax staff 5.0M Nov 11 13:34 ib_logfile1
-rw-rw---- 1 gmax staff 10M Nov 11 13:34 ibdata1
-rw-rw---- 1 gmax staff 1.2K Nov 11 13:34 msandbox.err
drwx------ 2 gmax staff 2.4K Nov 11 13:34 mysql
-rw-rw---- 1 gmax staff 6B Nov 11 13:34 mysql_sandbox5140.pid
drwx------ 2 gmax staff 68B Nov 11 13:34 test


select gman_do('eval','2 * 3') ;
+-------------------------+
| gman_do('eval','2 * 3') |
+-------------------------+
| 6 |
+-------------------------+


select gman_do('eval',
concat('$_="',host,'";tr/a-z/b-za/; $_'))
as test from mysql.user;
+-------------+
| test |
+-------------+
| % |
| mpdbmiptu |
+-------------+