Hacking MySQL: SIGNAL support (I)

I’ve been looking for an open source project to collaborate for some time now, and given the time I’m spending with MySQL lately and the expertise I’m gaining thanks to MySQL training, it looked like an obvious choice.

During the last advanced bootcamp, Tobias found bug #27894, which apparently was a simple fix. Dates in binlog were formatted as 736 instead of 070306 (for 2007-03-06). During the bootcamp I used my lonely nights at the hotel and came up with a patch, and some days later my first contribution was going into the main MySQL code.

The problem

Now I had to find something bigger. One of the things that most annoys me of MySQL is the lack of some way to abort a procedure or trigger: there is no raise method. To generate a custom error you have to do hacks like:

SELECT `

Error: Invalid firmware series for this model

` INTO dummy FROM model;

The solution

There is a SIGNAL command in the SQL:2003 standard which does the job, but it’s not implemented (yet) in MySQL. The syntax, according to the manual is as follows:

SIGNAL signal_value [ SET signal_information_list ]

signal_value:
    condition_name
  | sqlstate_value

signal_information_list:
    [ signal_information_list , ] signal_information_item

signal_information_item:
    condition_name = condition_value

condition_name:
    CLASS_ORIGIN
  | SUBCLASS_ORIGIN
  | CONSTRAINT_CATALOG
  | CONSTRAINT_SCHEMA
  | CONSTRAINT_NAME
  | CATALOG_NAME
  | SCHEMA_NAME
  | TABLE_NAME
  | COLUMN_NAME
  | CURSOR_NAME
  | MESSAGE_TEXT

In this first part I’ll cover the basics: just the SIGNAL command with a fixed generic error, enough to get rid of the dirty hacks.

The implementation

Getting used to foreign code always takes some level of difficulty, but when you have to deal with grammars and parsers it’s all crazy fun. First, we have to add a symbol for our new command

sql/lex.h

In this file, we have a symbols[] array where we have to add SIGNAL. Since it seems to be sorted in alphabetic order, we’ll put our line between SHUTDOWN and SIGNED:

   { "SHUTDOWN",    SYM(SHUTDOWN)},
   { "SIGNAL",    SYM(SIGNAL_SYM)},
   { "SIGNED",    SYM(SIGNED_SYM)},

sql/share/errmsg.txt

Before we get our hands dirty with the parser file, let’s get our custom error prepared. I took a look at the SQLSTATE error messages and I found the 38503 (Exception generated from user-defined function/procedure) enough related to this.

In this file we have a series of error constants with their corresponding error messages in various languages. Since our new error will be related to stored procedures, I decided to put with the rest of SP-related errors:

 ER_SP_CASE_NOT_FOUND 20000
         eng "Case not found for CASE statement"
         ger "Fall für CASE-Anweisung nicht gefunden"
 ER_SP_SIGNAL 38503
         eng "Exception generated from user-defined function/procedure"
 ER_FPARSER_TOO_BIG_FILE
         eng "Configuration file '%-.64s' is too big"
         ger "Konfigurationsdatei '%-.64s' ist zu groß"

sql/sql_yacc.yy

And finally to the point. Here we have to declare that we’ll be using the SIGNAL_SYM which we defined at sql/lex.h as a token.

 %token  SHUTDOWN
 %token  SIGNAL_SYM
 %token  SIGNED_SYM

Then, in the sp_proc_stmt label (look for sp_proc_stmt: at the beginning of a line), we add sp_proc_stmt_signal as another possibility (we’ll define this in a minute):

 	| sp_proc_stmt_iterate
 	| sp_proc_stmt_signal
 	| sp_proc_stmt_open

And finally, between the sp_proc_stmt_iterate and the sp_proc_stmt_open definition we add our code:

sp_proc_stmt_signal:
    SIGNAL_SYM
  	{
            LEX *lex= Lex;
	    sp_head *sp= lex->sphead;
	    sp_instr_error *i;

	    i= new sp_instr_error(sp->instructions(), lex->spcont, ER_SP_SIGNAL);
	    sp->add_instr(i);
	  }

This basically tells the parser to expect the SIGNAL_SYM token (SIGNAL) with no arguments, and generate an error with our new error code (ER_SP_SIGNAL). As you might see there’s some extra code which I copied directly from similar definitions, which I’ll refer to as parser magic (anyone willing to explain what sphead and lex variables are will be very welcome)

Conclusion

This one wasn’t so extremely difficult if you had some previous experience with Bison, but the next part can be more interesting, since I guess we’ll have to add some more functions than sp_instr_error to be able to show custom error messages. Also, we’ll have to prepare some test cases to verify our newly created behaviour.

I hope this helps someone trying to contribute to MySQL. If you want to try this at home you can follow the article or apply the patch

Live from the MySQL Users Conference

As some of you may now, I’ve been on the Bay Area for 10 days now, and I’m getting used to this. I took part on an Advanced Bootcamp last week to be able to deliver some new MySQL courses at Warp

I don’t have much pictures from the conference (I actually have a lot, but most of them are blurry or with bad lighting), but here’s a little sample from my last week.

MySQL instructors
MySQL Instructors at the Bootcamp

Mickos and Kawasaki
Mårten Mickos (CEO of MySQL) and Guy Kawasaki (VC and blogger) on stage at the opening Keynote

Ego-post

Being well positioned in a search engine Google might be the key if we’re talking about businesses. When we are talking about a personal blog like this, with no direct revenue related to visits, I can’t find more benefits than the confort of being able to told people to directly google my name instead of giving them the whole address.

But today I noticed some black spots on my Google search (Jorge Bernal). First, it seems to be an actor called like me, and a Bernal familiy which is not mine.

But the thing that keeps me worried is the Jorge Bernal mugshot. Anyone who knows me can realize that the guy in that photo is not me, but still. I was really nervous last Sunday when I was at the customs office in Minneapolis Airport, knowing that there was a murderer in the US with my same name.

To whom may it concern: I do not kill people. My only killings are -9, if you know what I mean

I love cool companies

Well, actually what I love is that small embedded jokes that bring that smile at the end of the day, like the Qt Blog, which has this pearl as slogan:

The blog where it’s OK to feed the Trolls

For those of you who need some context, the company behind Qt is called trolltech. If you still don’t get it try searching for don’t feed the troll

Wet google maps

Coincidence? No, serendipity. Last week I was on the bus going back home. This usually takes half an hour so I don’t have much to do except listen to music and think in absurd things like this.

I wondered what would happen if you ask google maps for directions from one place to another if there’s no road between those two. Hector got the answer today. Say you want to go from the new Warp HQ to the MySQL HQ (BTW, I’ve been there today and the sakila dolphin plush is awesome). No problem at all, google knows the way

Spain to US

So, swim across the Atlantic Ocean, cool! But there’s more, if you look at the Drive details it’ll give you estimates of how much will take you to get there.

Spain to US (detail)

After some experiments shortening the path, let’s say the distance is about 5500 km and Google says it’ll take you 29 days to get there. If you do the math you’ll find that you’ll need to swim at an average of almost 8 km/h (that’s 5mph) for almost a month (without any stops, and presumably no food). So, unless you are David Meca on tons of steroids you won’t make it. Just for reference, when this world record swimmer crossed the strait of Gibraltar, he did an average of 0.5 km/h for 2.5 hours.

Update: while reading another post on boingboing about the same topic, I got the insight for the old USENET acronym YMMV: your mileage may vary.

Planet apologies

Note: This is a dedicated post to Planet Warp readers

You might have noticed the sudden appearance of some posts in the planet feed. Quique told me this morning that his posts weren’t appearing on the planet, so I checked it and found that planet was crashing with something like DBNOTFOUND error (sorry I can’t remember the exact string). The issue was fixed by removing the cache directory and running planet.py again.

After that I discovered some really funny posts…

NeoOffice gone nuts

Yesterday, I read about the release of NeoOffice 2.1. NeoOffice is a port of our beloved OpenOffice.org for MacOSX.

The new version is quite nice. It has a look’n'feel way more consistent with the rest of the OS (it uses native libraries) and it’s like twice faster. But there is somethin quite strange:

NeoOffice gone nuts

I think I may not have the Bitstream Vera Sans typeface. The really bizarre thing is that switching off bold gets me a sans font, but turning it on gets me that gothic font.