drizzle group – Identi.ca
Join us – you know you want to.
Keep up to date with what’s happenning in Drizzle land.
Doing something with Drizzle? just add “!drizzle” to your identi.ca update.
drizzle group – Identi.ca
Join us – you know you want to.
Keep up to date with what’s happenning in Drizzle land.
Doing something with Drizzle? just add “!drizzle” to your identi.ca update.
See also: MySQL Bug 43151
The MySQL Manual proudly states that you don’t get implicit default values if strict mode.
mysql> set sql_mode='STRICT_ALL_TABLES'; Query OK, 0 rows affected (0.00 sec) mysql> create table t1 (a int, b int, c int, d int, e int, f int, g int, h int,i int, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM; Query OK, 0 rows affected (0.03 sec) mysql> show create table t1\G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', `c` int(11) NOT NULL default '0', `d` int(11) NOT NULL default '0', `e` int(11) NOT NULL default '0', `f` int(11) NOT NULL default '0', `g` int(11) NOT NULL default '0', `h` int(11) NOT NULL default '0', `i` int(11) NOT NULL default '0', PRIMARY KEY (`a`,`b`,`c`,`d`,`e`,`f`,`g`,`i`,`h`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 1 row in set (0.00 sec) mysql> insert into t1 (a) values (1); Query OK, 1 row affected (0.00 sec)
Which means your getting a default value you never specified.
In my latest Drizzle patch, we no longer give you what you didn’t ask for (an implicit default).
You can still (of course) specify an explicit default (and I’ve done this in some of our test cases).
Just noticed that the Drizzle list has had more messages since June last year (2008) than the mysql internals@ list has had since March 2006.
Well… kinda… (and nobody make fun of me for using my MythTV box as a testing ground for SQL against MySQL).
myth@orpheus:~$ mysql -u root test Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2496 Server version: 5.0.51a-3ubuntu5.4-log (Ubuntu) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> create table t1 (a tinytext default 'fail'); ERROR 1101 (42000): BLOB/TEXT column 'a' can't have a default value mysql> create table t1 (a tinytext default ''); Query OK, 0 rows affected, 1 warning (0.07 sec) mysql> show warnings; +---------+------+-------------------------------------------------+ | Level | Code | Message | +---------+------+-------------------------------------------------+ | Warning | 1101 | BLOB/TEXT column 'a' can't have a default value | +---------+------+-------------------------------------------------+ 1 row in set (0.00 sec)
I increasingly enclose the API part of “Storage Engine API” in quotes as it does score a rather large number on the API Design Rusty levels (Coined by Rusty Russell). I give it a 15 (out of 18. lower is better) in this case “The obvious use is wrong”.
The ideas is that your handler gets called to write a row (the amazingly named handler::write_row()). It’s passed a buffer which is the row to be stored. An engine that uses the MySQL row format (lets say, ARCHIVE) will simply pack the row and write it out.
Unless there is a TIMESTAMP field with auto set on insert. Up until now (and still now in MySQL) the engine had to check if this was the case and make sure the timestamp field was updated.
To remove this particular bonghit is actually a really small patch, which Jay recently got merged:
~drizzle-developers/drizzle/development : revision 873.1.16
Hopefully somebody does this soon for MySQL as well.
It’s no secret that I love linux.conf.au. My first was linux.conf.au 2003, in Perth and I’ve been to every one since (there are at least two people who’ve been to every single one, including CALU as it was called in 1999).
I’ve been on the board of Linux Australia for some insane proportion of the years since then (joining in 2003). Linux Australia is the not-for-profit community organisation that puts on linux.conf.au. It’s all volunteers and amazingly enough we have more than one group of people wanting to put on linux.conf.au each year!
This year, we Marched South to Hobart.
Here I detail what I saw, what I wish I saw and whatever else comes to mind.
Ran into Bdale while checking in. Short flight down. A million and one people on the plane and on the ground that I knew. It must be linux.conf.au.
Seeing way too many awesome people I know, checking into accommodation (oh my, what a hill), registering for conf, beer and then off to a “ghosts of conferences past” dinner – where a few people who had organised previous linux.conf.au’s were hastily gathered together to chat to part of the 2010 team.
Oh, that’s right – I’m running the OSDB Miniconf :)
First up, Monty Taylor spoke on “NDB/Bindings – Use the MySQL Cluster Direct API from languages you actually like for fun and profit”. Possibly taking the prize for the longest talk title of the conference. The NDB API is not SQL, it’s what the MySQL server (and one day, when Monty and I get around to it, Drizzle) translates SQL into for NDB. That being said, you can (pretty much always) write NDB API code that dramatically outperforms equivilent SQL (for a variety of reasons). Monty maintains the NDB/Bindings project that lets you use languages other than C++ for the NDB API.
At the same time as Monty was speaking, I wish I’d been able to fork() and go and see “Is Parallel Programming Hard, And, If So, Why?” by Paul McKenney and Michael Still talking about MythNetTV (pull RSS feeds of video in as MythTV programs).
After morning tea, we were meant to have “InnoDB scaling up and performance” by Bruce Huang, but he was a no-show. Hint: if you don’t want bad things to be said about you by conference organisers, either show up or let them know you’re not able to make it.
Instead, we led a crazy Q&A type session around the room which was a whole lot of fun. Really a “ask the experts” meets running up-and-down stairs with a microphone.
Next up, Arjen Lentz who runs Open Query spoke on “OurDelta: Builds for MySQL”. The best way to describe OurDelta is a “distribution of MySQL”. It’s the MySQL server plus a bunch of patches provided by various people that haven’t yet made it into the main source tree (for any number of reasons).
At the same time (if you’ve never been to linux.conf.au, you’ll find that you often want to be in at least 3 places at once) I would have really liked to see “MythTV Internals by Nigel Pearson” (I co-wrote Practical MythTV with Michael Still, which is having a “second edition” in wiki form over at http://www.mythtvbook.com/) as well as the panel on geek parenting as this may be something I’m one day faced with.
Up next: Russell Coker filled in for Kaigai (same talk, different speaker) to talk on The Security-Enhanced PostgreSQL – “System-wide consistency” in access controls. I found this quite interesting and different approaches to database security are worth looking at. Modern applications (read: web applications) don’t map their uses to database users at all. There are usually two users on the database server: the super user and the user that the app uses. It would be nice to have a good solution for those who want it.
Again, If I had the ability to be in two places at once, I would have also seen “How I Learned To Stop Worrying And Love ACPI” by the extremely handsome Matthew Garrett.
Monty Widenius (blog here – and yes, we have two Monty’s now… which does cause confusion) talking about the Maria storage engine. Maria is based on MyISAM, but adding crash safety and transactions (among other things).
Again, if I was able to be in several places at once I would have also seen Rusty‘s “Large CPUmasks”, Nathan Scott talking about “System level performance management with PCP” and Bdale’s “Collaborating Successfully with large corporations”.
An awesome start to the conference.
Filed GCC bug 39228:
#include <stdio.h> #include <math.h> int main() { Â Â Â Â Â Â Â double a= 10.0; Â Â Â Â Â Â Â double b= 1e+308; Â Â Â Â Â Â Â printf("%d %d %dn", isinf(a*b), __builtin_isinf(a*b), __isinf(a*b)); Â Â Â Â Â Â Â return 0; }
mtaylor@drizzle-dev:~$ gcc -o test test.c
mtaylor@drizzle-dev:~$ ./test
0 0 1
mtaylor@drizzle-dev:~$ gcc -o test test.c -std=c99
mtaylor@drizzle-dev:~$ ./test
1 0 1
mtaylor@drizzle-dev:~$ gcc -o test test.c  -mfpmath=sse -march=pentium4
mtaylor@drizzle-dev:~$ ./test
1 1 1
mtaylor@drizzle-dev:~$ g++ -o test test.c
mtaylor@drizzle-dev:~$ ./test
1 0 1
Originally I found the simple isinf() case to be different on x86 than x86-64, ppc32 and sparc (32 and 64).
After more research, I found that x86-64 uses the sse instructions to do it (and using sse is the only way for __builtin_isinf() to produce correct results). For the g++ built version, it calls __isinf() instead of inlining (and as can be seen, the __isinf() version is always correct).
Specifically, it’s because the optimised 387 code is doing the math in double extended precision inside the FPU. 10.0*1e308 fits in 80bits but not in 64bit. Any code that forces it to be stored and loaded gets the correct result too. e.g.
mtaylor@drizzle-dev:~$ cat test-simple.c
#include <stdio.h> #include <math.h> int main() {        double a= 10.0;        double b= 1e+308;    volatile   double c= a*b;        printf("%dn", isinf(c));        return 0; }
mtaylor@drizzle-dev:~$ gcc -o test-simple test-simple.c
mtaylor@drizzle-dev:~$ ./test-simple
1
With this code you can easily see the load and store:
 8048407:      dc 0d 18 85 04 08      fmull 0x8048518 804840d:      dd 5d f0               fstpl -0x10(%ebp)  8048410:      dd 45 f0               fldl  -0x10(%ebp)  8048413:      d9 e5                  fxam
While if you remove volatile, the load and store doesn’t happen (at least on -O3, on -O0 it hasn’t been optimised away):
 8048407:      dc 0d 18 85 04 08      fmull 0x8048518  804840d:      c7 44 24 04 10 85 04   movl  $0x8048510,0x4(%esp)  8048414:      08  8048415:      c7 04 24 01 00 00 00   movl  $0x1,(%esp)  804841c:      d9 e5                  fxam
This is also a regression from 4.2.4 as it just calls isinf() and doesn’t expand the 387 code inline. My guess is the 387 optimisation was added in 4.3.
Recommended fix: store and load in the 387 version so to operate on same precision as elsewhere.
Now I just have to make a patch I like that makes Drizzle behave because of this (showed up as a failure in the SQL func_math test) and then submit to MySQL as well… as this may happen there if “correctly” built.
#include <stdio.h> #include <math.h> int main() { double a= 10.0; double b= 1e+308; printf("%dn",isinf(a * b)); return 0; }
Prints 1 on: 64bit intel, 32bit PowerPC, 32bit SPARC, 64bit Sparc. But prints zero on 32bit intel.
Oh, but if you build that with g++ instead of gcc on 32bit Intel, you get 1.
It’s fortunate that I’m watching Veronica Mars again with a mate; a more-than-you-think amount of detective work is required to understand the relationship (and format) of the TABLE_SHARE, the FRM file and HA_CREATE_INFO. Oh, also you’ll need drizzled/base.h and drizzled/structs.h and drizzled/table_share.h is also a good one to have open.
The FRM file is really a FoRM file from UNIREG (see copies of really old mysql docs around the place or even better, the links off Sheeri‘s blog post). Also, Jan has some thoughts on FRM too and Thava has a scary frmdump php script.
I have to agree completely with Jan:
It contains interesting nuggets like unireg_check (or unireg_type, depending on where you read) that does:
enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL, CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD, BIT_FIELD, TIMESTAMP_OLD_FIELD, CAPITALIZE, BLOB_FIELD, TIMESTAMP_DN_FIELD, TIMESTAMP_UN_FIELD, TIMESTAMP_DNUN_FIELD};
But really only the timestamp things… which should be default magic, but it’s somewhere tied in (Jay had thoughts last time I spoke to him… hopefully going away soon). A bunch of these aren’t ever used and are just relics from UNIREG. In fact… I went and removed what wasn’t needed and just ended up with:
 enum utype { NONE,                NEXT_NUMBER,                TIMESTAMP_OLD_FIELD,                TIMESTAMP_DN_FIELD, TIMESTAMP_UN_FIELD, TIMESTAMP_DNUN_FIELD};
Which does seem a bit nicer. The fact that TIMESTAMP_OLD_FIELD is used as in interim value is, wel, scary. At least with a smaller set of possiblities it will be easier to convert into the proto format.
A hint of a brighter future is in the comment there:
/* We use three additional unireg types for TIMESTAMP to overcome limitation of current binary format of .frm file. We'd like to be able to support NOW() as default and on update value for such fields but unable to hold this info anywhere except unireg_check field. This issue will be resolved in more clean way with transition to new text based .frm format. See also comment for Field_timestamp::Field_timestamp(). */
Hrrm… a text based FRM? That would be much nicer to read the code for. Unfortunately, it doesn’t really exist. Some FRMs are text in MySQL, but not ones to do with tables. You can look at the FRM for a VIEW in a text editor and see the SQL quite easily (the file format is text).
So I can’t go look at any nice text based format code – it’s all uint2korr() and friends. Yes folks, this is about the only place left in the code with function names in Swedish. What does korr mean? “accurate, correct, correctly”. If you look at korr.h, you’ll see that it’s just for storing in machine independent format: low byte first.
My favourite korr functions:
It also (as Jan showed) does the whole layout on a 80 column terminal for you! This functionality is going, going gone in Drizzle and won’t be coming back.
There’s also an “empty record on start of formfile” (see make_empty_rec in unireg.cc). This bit is going to cause me some pain relatively soon. Not so much for writing something like it out (default values can be easily put in the proto) but by then constructing it on open (with some careful footing around the issue of the egg coming before the chicken).
Incidently, when discussing with Daniel Stone about this (and explaining all the weirdness) it did cause him to exclaim “omg, it’s XKB!” – so that probably helps the X hackers in the room to relate.
The biggest test in moving from FRM to proto is to only rewrite this part of the code – the TABLE_SHARE, field, Create_foo etc have sooo many bits I want to change/fix. Going down the rat-hole into an endless cycle of fixing is always a possibility. Sometimes (like with unireg_type) the cleanup lets me really discover what the code is doing, so that’s being done (but will go away “soon”).
For such a long worked on feature, with such potential – I find the resistence to publishing a source tree curious (my comments on the topic have been moderated away but others have asked too). I could go and grep through the commits list searching for things (hint: look for mysql-6.0-perf), and then start to re-construct a tree; but I have more important things to do (yes, Brian, like FRM patches :)
Instead of re-inventing the wheel in Drizzle for a performance schema like interface, it’d be great to go with existing work. Evaluating the code as it’s coming along is important.
I also have concerns about the code itself:
So stuck waiting for some code to look at to answer the questions (random commits on the commits list doesn’t really do it like the finished product – i really hate commit lists).
So I can’t currently comment on the performance schema work much at all, nor if it’s useful to Drizzle. Hopefully will soon.
Dear Lazyweb,
any idea where I can get one of these in .au?
thxbye.
Some database engines have a fundamental concept of a row id. The row id is everything you need to know to locate a row. Common uses include secondary indexes (key is what’s indexed, value is rowid which you then use to lookup the row).
One design is the InnoDB method of having secondary indexes have the value in the index be the primary key of the row. Another is to store the rowid instead. Usually (or often… or sometimes…) rowid is much smaller than the pkey of the row. This is how innodb can answer some queries just out of the index. If it used rowid, it may involve more IO to answer the query. All this is irrelevant if you never want just the primary key from a secondary index.
Some engines are designed from the start to have rowid, others it’s added later (e.g. NDB).
Anyway… all beside the point. Did you know you can do this in mysql or drizzle:
drizzle> create table t1 (a int primary key); Query OK, 0 rows affected (0.02 sec) drizzle> insert into t1 (a) values (1); Query OK, 1 row affected (0.01 sec) drizzle> select _rowid from t1; +--------+ | _rowid | +--------+ | 1 | +--------+ 1 row in set (0.00 sec)
Is that the rowid from the engine? No (although at least NDB will let you select the real ROWID through a pseudo column through NDBAPI). Quoting from the MySQL manual:
If a
PRIMARY KEY
orUNIQUE
index consists of only one column that has an integer type, you can also refer to the column as_rowid
inSELECT
statements.
Unfortunately, this isn’t correct… as this lovely bit of “oh my, what an excellent way to obfuscate my database app!” shows:
drizzle> create table t1 (a int primary key, b varchar(100));
Query OK, 0 rows affected (0.02 sec)
drizzle> insert into t1 values (1,”foo”);
Query OK, 1 row affected (0.00 sec)
drizzle> update t1 set b=”foobar!” where _rowid=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
drizzle> select * from t1;
+—+———+
| a | b |
+—+———+
| 1 | foobar! |
+—+———+
1 row in set (0.00 sec)
So how is this implemented? In two places: in sql_base.cc find_field_in_table() and in table.cc during FRM parsing (this is how I found it). We can even do things Oracle can’t (insert, update and delete):
drizzle> update t1 set a=2 where _rowid=1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 drizzle> select * from t1; +---+---------+ | a | b | +---+---------+ | 2 | foobar! | +---+---------+ 1 row in set (0.00 sec) drizzle> update t1 set _rowid=3 where _rowid=2; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 drizzle> select * from t1; +---+---------+ | a | b | +---+---------+ | 3 | foobar! | +---+---------+ 1 row in set (0.00 sec)
SQLite also has something similar (see the autoinc docs).
I do wonder if anybody uses this functionality. It’s even tested (I was quite shocked at this) in the auto_increment and heap_auto_increment tests.
Vegan sausage rolls (found via vegan about town). Quite yummy.