From: Dmitry Lenev Date: February 2 2011 1:18pm Subject: bzr push into mysql-5.1 branch (Dmitry.Lenev:3571 to 3572) Bug#58650 List-Archive: http://lists.mysql.com/commits/130216 X-Bug: 58650 Message-Id: <20110202131835.D174C74047A@bandersnatch> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3572 Dmitry Lenev 2011-02-02 Fix for bug #58650 "Failing assertion: primary_key_no == -1 || primary_key_no == 0". Attempt to create InnoDB table with non-nullable column of geometry type having an unique key with length 12 on it and with some other candidate key led to server crash due to assertion failure in both non-debug and debug builds. The problem was that such a non-candidate key could have been sorted as the first key in table/.FRM, before any legit candidate keys. This resulted in assertion failure in InnoDB engine which assumes that primary key should either be the first key in table/.FRM or should not exist at all. The reason behind such an incorrect sorting was an wrong value of Create_field::key_length member for geometry field (which was set to its pack_length == 12) which confused code in mysql_prepare_create_table(), so it would skip marking such key as a key with partial segments. This patch fixes the problem by ensuring that this member gets the same value of Create_field::key_length member as for other blob fields (from which geometry field class is inherited), and as result unique keys on geometry fields are correctly marked as having partial segments. @ mysql-test/include/gis_keys.inc Added test case for bug #58650 "Failing assertion: primary_key_no == -1 || primary_key_no == 0". @ mysql-test/r/gis.result Added test case for bug #58650 "Failing assertion: primary_key_no == -1 || primary_key_no == 0". @ mysql-test/suite/innodb/r/innodb_gis.result Added test case for bug #58650 "Failing assertion: primary_key_no == -1 || primary_key_no == 0". @ mysql-test/suite/innodb_plugin/r/innodb_gis.result Added test case for bug #58650 "Failing assertion: primary_key_no == -1 || primary_key_no == 0". @ sql/field.cc Changed Create_field::create_length_to_internal_length() to correctly set Create_field::key_length member for geometry fields. Similar to the blob types key_length for such fields should be the same as length and not field's packed length (which is always 12 for geometry). As result of this change code handling table creation now always correctly identifies btree/unique keys on geometry fields as partial keys, so such keys can't be erroneously treated as candidate keys and sorted in keys array in .FRM before legit candidate keys. This fixes bug #58650 "Failing assertion: primary_key_no == -1 || primary_key_no == 0" in which incorrect candidate key sorting led to assertion failure in InnoDB code. modified: mysql-test/include/gis_keys.inc mysql-test/r/gis.result mysql-test/suite/innodb/r/innodb_gis.result mysql-test/suite/innodb_plugin/r/innodb_gis.result sql/field.cc 3571 Ole John Aske 2011-02-01 Fix for bug#57030: ('BETWEEN' evaluation is incorrect') Root cause for this bug is that the optimizer try to detect& optimize the special case: ' BETWEEN c1 AND c1' and handle this as the condition ' = c1' This was implemented inside add_key_field(.. *field, *value[]...) which assumed field to refer key Field, and value[] to refer a [low...high] constant pair. value[0] and value[1] was then compared for equality. In a 'normal' BETWEEN condition of the form ' BETWEEN val1 and val2' the BETWEEN operation is represented with an argementlist containing the values [, val1, val2] - add_key_field() is then called with parameters field=, *value=val1. However, if the BETWEEN predicate specified: 1) ' BETWEEN AND the 'field' and 'value' arguments to add_key_field() had to be swapped. This was implemented by trying to cheat add_key_field() to handle it like: 2) ' GE AND LE' As we didn't really replace the BETWEEN operation with 'ge' and 'le', add_key_field() still handled it as a 'BETWEEN' and compared the (swapped) arguments and for equality. If they was equal, the condition 1) was incorrectly 'optimized' to: 3) ' EQ ' This fix moves this optimization of ' BETWEEN c1 AND c1' into add_key_fields() which then calls add_key_equal_fields() to collect key equality / comparison for the key fields in the BETWEEN condition. modified: mysql-test/r/range.result mysql-test/t/range.test sql/sql_select.cc === modified file 'mysql-test/include/gis_keys.inc' --- a/mysql-test/include/gis_keys.inc 2007-11-01 14:03:09 +0000 +++ b/mysql-test/include/gis_keys.inc 2011-02-02 13:17:48 +0000 @@ -44,3 +44,19 @@ SELECT COUNT(*) FROM t2 IGNORE INDEX(p) DROP TABLE t1, t2; --echo End of 5.0 tests + + +--echo # +--echo # Test for bug #58650 "Failing assertion: primary_key_no == -1 || +--echo # primary_key_no == 0". +--echo # +--disable_warnings +drop table if exists t1; +--enable_warnings +--echo # The minimal test case. +create table t1 (a int not null, b linestring not null, unique key b (b(12)), unique key a (a)); +drop table t1; +--echo # The original test case. +create table t1 (a int not null, b linestring not null, unique key b (b(12))); +create unique index a on t1(a); +drop table t1; === modified file 'mysql-test/r/gis.result' --- a/mysql-test/r/gis.result 2011-01-12 13:02:41 +0000 +++ b/mysql-test/r/gis.result 2011-02-02 13:17:48 +0000 @@ -960,6 +960,18 @@ COUNT(*) 2 DROP TABLE t1, t2; End of 5.0 tests +# +# Test for bug #58650 "Failing assertion: primary_key_no == -1 || +# primary_key_no == 0". +# +drop table if exists t1; +# The minimal test case. +create table t1 (a int not null, b linestring not null, unique key b (b(12)), unique key a (a)); +drop table t1; +# The original test case. +create table t1 (a int not null, b linestring not null, unique key b (b(12))); +create unique index a on t1(a); +drop table t1; create table `t1` (`col002` point)engine=myisam; insert into t1 values (),(),(); select min(`col002`) from t1 union select `col002` from t1; === modified file 'mysql-test/suite/innodb/r/innodb_gis.result' --- a/mysql-test/suite/innodb/r/innodb_gis.result 2010-06-03 09:50:32 +0000 +++ b/mysql-test/suite/innodb/r/innodb_gis.result 2011-02-02 13:17:48 +0000 @@ -585,5 +585,17 @@ COUNT(*) 2 DROP TABLE t1, t2; End of 5.0 tests +# +# Test for bug #58650 "Failing assertion: primary_key_no == -1 || +# primary_key_no == 0". +# +drop table if exists t1; +# The minimal test case. +create table t1 (a int not null, b linestring not null, unique key b (b(12)), unique key a (a)); +drop table t1; +# The original test case. +create table t1 (a int not null, b linestring not null, unique key b (b(12))); +create unique index a on t1(a); +drop table t1; create table t1 (g geometry not null, spatial gk(g)) engine=innodb; ERROR HY000: The used table type doesn't support SPATIAL indexes === modified file 'mysql-test/suite/innodb_plugin/r/innodb_gis.result' --- a/mysql-test/suite/innodb_plugin/r/innodb_gis.result 2010-06-03 09:48:59 +0000 +++ b/mysql-test/suite/innodb_plugin/r/innodb_gis.result 2011-02-02 13:17:48 +0000 @@ -585,5 +585,17 @@ COUNT(*) 2 DROP TABLE t1, t2; End of 5.0 tests +# +# Test for bug #58650 "Failing assertion: primary_key_no == -1 || +# primary_key_no == 0". +# +drop table if exists t1; +# The minimal test case. +create table t1 (a int not null, b linestring not null, unique key b (b(12)), unique key a (a)); +drop table t1; +# The original test case. +create table t1 (a int not null, b linestring not null, unique key b (b(12))); +create unique index a on t1(a); +drop table t1; create table t1 (g geometry not null, spatial gk(g)) engine=innodb; ERROR HY000: The used table type doesn't support SPATIAL indexes === modified file 'sql/field.cc' --- a/sql/field.cc 2010-12-28 23:47:05 +0000 +++ b/sql/field.cc 2011-02-02 13:17:48 +0000 @@ -9476,6 +9476,7 @@ void Create_field::create_length_to_inte case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_STRING: case MYSQL_TYPE_VARCHAR: No bundle (reason: useless for push emails).