diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 740241fa210e72e240ee94b41e40e8e7567352ff..5b7d068d0c1b494ee82cd8010f84d26483da491d 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -638,23 +638,24 @@ row_sel_get_clust_rec( if (!node->read_view) { /* Try to place a lock on the index record */ - /* If innodb_locks_unsafe_for_binlog option is used, - we lock only the record, i.e. next-key locking is - not used. - */ - if ( srv_locks_unsafe_for_binlog ) - { - err = lock_clust_rec_read_check_and_lock(0, clust_rec, - index,node->row_lock_mode, LOCK_REC_NOT_GAP, thr); - } - else - { - err = lock_clust_rec_read_check_and_lock(0, clust_rec, index, - node->row_lock_mode, LOCK_ORDINARY, thr); - - } - - if (err != DB_SUCCESS) { + /* If innodb_locks_unsafe_for_binlog option is used, + we lock only the record, i.e. next-key locking is + not used. + */ + + if (srv_locks_unsafe_for_binlog) { + err = lock_clust_rec_read_check_and_lock(0, + clust_rec, + index, node->row_lock_mode, + LOCK_REC_NOT_GAP, thr); + } else { + err = lock_clust_rec_read_check_and_lock(0, + clust_rec, + index, node->row_lock_mode, + LOCK_ORDINARY, thr); + } + + if (err != DB_SUCCESS) { return(err); } @@ -1205,22 +1206,24 @@ rec_loop: if (!consistent_read) { - /* If innodb_locks_unsafe_for_binlog option is used, - we lock only the record, i.e. next-key locking is - not used. - */ - - if ( srv_locks_unsafe_for_binlog ) - { - err = sel_set_rec_lock(page_rec_get_next(rec), index, - node->row_lock_mode, LOCK_REC_NOT_GAP, thr); - } - else - { - err = sel_set_rec_lock(page_rec_get_next(rec), index, - node->row_lock_mode, LOCK_ORDINARY, thr); - } - if (err != DB_SUCCESS) { + /* If innodb_locks_unsafe_for_binlog option is used, + we lock only the record, i.e. next-key locking is + not used. + */ + + if (srv_locks_unsafe_for_binlog) { + err = sel_set_rec_lock(page_rec_get_next(rec), + index, + node->row_lock_mode, + LOCK_REC_NOT_GAP, thr); + } else { + err = sel_set_rec_lock(page_rec_get_next(rec), + index, + node->row_lock_mode, + LOCK_ORDINARY, thr); + } + + if (err != DB_SUCCESS) { /* Note that in this case we will store in pcur the PREDECESSOR of the record we are waiting the lock for */ @@ -1245,21 +1248,18 @@ rec_loop: if (!consistent_read) { /* Try to place a lock on the index record */ - /* If innodb_locks_unsafe_for_binlog option is used, - we lock only the record, i.e. next-key locking is - not used. - */ + /* If innodb_locks_unsafe_for_binlog option is used, + we lock only the record, i.e. next-key locking is + not used. + */ - if ( srv_locks_unsafe_for_binlog ) - { - err = sel_set_rec_lock(rec, index, node->row_lock_mode, + if (srv_locks_unsafe_for_binlog) { + err = sel_set_rec_lock(rec, index, node->row_lock_mode, LOCK_REC_NOT_GAP, thr); - } - else - { - err = sel_set_rec_lock(rec, index, node->row_lock_mode, + } else { + err = sel_set_rec_lock(rec, index, node->row_lock_mode, LOCK_ORDINARY, thr); - } + } if (err != DB_SUCCESS) { @@ -3209,8 +3209,7 @@ rec_loop: we do not lock gaps. Supremum record is really a gap and therefore we do not set locks there. */ - if ( srv_locks_unsafe_for_binlog == FALSE ) - { + if (srv_locks_unsafe_for_binlog == FALSE) { err = sel_set_rec_lock(rec, index, prebuilt->select_lock_type, LOCK_ORDINARY, thr); @@ -3312,11 +3311,18 @@ rec_loop: if (prebuilt->select_lock_type != LOCK_NONE && set_also_gap_locks) { - /* Try to place a lock on the index record */ - err = sel_set_rec_lock(rec, index, + /* Try to place a gap lock on the index + record only if innodb_locks_unsafe_for_binlog + option is not set */ + + if (srv_locks_unsafe_for_binlog == FALSE) { + + err = sel_set_rec_lock(rec, index, prebuilt->select_lock_type, LOCK_GAP, thr); + } + if (err != DB_SUCCESS) { goto lock_wait_or_error; @@ -3338,11 +3344,18 @@ rec_loop: if (prebuilt->select_lock_type != LOCK_NONE && set_also_gap_locks) { - /* Try to place a lock on the index record */ - err = sel_set_rec_lock(rec, index, + /* Try to place a gap lock on the index + record only if innodb_locks_unsafe_for_binlog + option is not set */ + + if (srv_locks_unsafe_for_binlog == FALSE) { + + err = sel_set_rec_lock(rec, index, prebuilt->select_lock_type, LOCK_GAP, thr); + } + if (err != DB_SUCCESS) { goto lock_wait_or_error; @@ -3376,19 +3389,16 @@ rec_loop: prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr); } else { - /* If innodb_locks_unsafe_for_binlog option is used, - we lock only the record, i.e. next-key locking is - not used. - */ - if ( srv_locks_unsafe_for_binlog ) - { - err = sel_set_rec_lock(rec, index, + /* If innodb_locks_unsafe_for_binlog option is used, + we lock only the record, i.e. next-key locking is + not used. */ + + if (srv_locks_unsafe_for_binlog) { + err = sel_set_rec_lock(rec, index, prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr); - } - else - { - err = sel_set_rec_lock(rec, index, + } else { + err = sel_set_rec_lock(rec, index, prebuilt->select_lock_type, LOCK_ORDINARY, thr); } diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 31b14f9b8229bfa8b2f2c39ea5ede55867b5c35c..d155a14bb604966224d6f656abc07db3248b6f7d 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -529,6 +529,7 @@ show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t1 1 a 1 a A NULL NULL NULL YES BTREE disabled create table t2 (a int); +set @@rand_seed1=31415926,@@rand_seed2=2718281828; insert t1 select * from t2; show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment diff --git a/mysql-test/r/ndb_index_unique.result b/mysql-test/r/ndb_index_unique.result index af9b84022ed57c358265829955a2f592da73c240..31b258c0a6fd4adf4a2cf462cc6141d2e05e3d03 100644 --- a/mysql-test/r/ndb_index_unique.result +++ b/mysql-test/r/ndb_index_unique.result @@ -44,6 +44,51 @@ a b c 7 8 3 8 2 3 drop table t1; +CREATE TABLE t1 ( +a int unsigned NOT NULL PRIMARY KEY, +b int unsigned, +c int unsigned, +UNIQUE bc(b,c) +) engine = ndb; +insert into t1 values(1,1,1),(2,NULL,2),(3,NULL,NULL),(4,4,NULL); +select * from t1 use index (bc) where b IS NULL order by a; +a b c +2 NULL 2 +3 NULL NULL +select * from t1 use index (bc)order by a; +a b c +1 1 1 +2 NULL 2 +3 NULL NULL +4 4 NULL +select * from t1 use index (bc) order by a; +a b c +1 1 1 +2 NULL 2 +3 NULL NULL +4 4 NULL +select * from t1 use index (PRIMARY) where b IS NULL order by a; +a b c +2 NULL 2 +3 NULL NULL +select * from t1 use index (bc) where b IS NULL order by a; +a b c +2 NULL 2 +3 NULL NULL +select * from t1 use index (bc) where b IS NULL and c IS NULL order by a; +a b c +select * from t1 use index (bc) where b IS NULL and c = 2 order by a; +a b c +select * from t1 use index (bc) where b < 4 order by a; +a b c +1 1 1 +select * from t1 use index (bc) where b IS NOT NULL order by a; +a b c +1 1 1 +4 4 NULL +insert into t1 values(5,1,1); +ERROR 23000: Duplicate entry '5' for key 1 +drop table t1; CREATE TABLE t2 ( a int unsigned NOT NULL PRIMARY KEY, b int unsigned not null, @@ -87,6 +132,13 @@ a b c 7 8 3 8 2 3 drop table t2; +CREATE TABLE t2 ( +a int unsigned NOT NULL PRIMARY KEY, +b int unsigned not null, +c int unsigned, +UNIQUE USING HASH (b, c) +) engine=ndbcluster; +ERROR 42000: Column 'c' is used with UNIQUE or INDEX but is not defined as NOT NULL CREATE TABLE t3 ( a int unsigned NOT NULL, b int unsigned not null, diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 32d482f5a3220817ce10725e2ca6e855c201393b..53b92fe50f177f3aaf31723a821f5d0ec09de449 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1990,3 +1990,18 @@ ac 700 NULL drop tables t1,t2; +create table t1 (a int not null, b int not null, c int, primary key (a,b)); +insert into t1 values (1,1,1), (2,2,2), (3,3,3); +set @b:= 0; +explain select sum(a) from t1 where b > @b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 8 NULL 3 Using where; Using index +set @a:= (select sum(a) from t1 where b > @b); +explain select a from t1 where c=2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where +do @a:= (select sum(a) from t1 where b > @b); +explain select a from t1 where c=2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where +drop table t1; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index f9081e8769b6e809cd5dacd9e4736a2ba89860ce..c8ed7910b76bb0089a08b710eac3e54f18be5e74 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -498,11 +498,12 @@ alter table t1 disable keys; show keys from t1; create table t2 (a int); let $i=1000; +set @@rand_seed1=31415926,@@rand_seed2=2718281828; --disable_query_log while ($i) { dec $i; - eval insert t2 values (rand()*100000); + insert t2 values (rand()*100000); } --enable_query_log insert t1 select * from t2; diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test index fd7fe0e60d8f37deba18ef2b21b5fc2389e1993e..6551732adbae7d10ef45b04208152b65bc6dfdec 100644 --- a/mysql-test/t/ndb_autodiscover.test +++ b/mysql-test/t/ndb_autodiscover.test @@ -199,7 +199,7 @@ insert into t4 values (1, "Automatic"); select * from t4; # Remove the table from NDB -system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t4 > /dev/null ; +system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t4 > /dev/null ; # # Test that correct error is returned @@ -230,7 +230,7 @@ select * from t4; flush tables; # Remove the table from NDB -system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t4 > /dev/null ; +system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t4 > /dev/null ; SHOW TABLES; @@ -264,8 +264,8 @@ insert into t8 values (8, "myisam table 8"); insert into t9 values (9); # Remove t3, t5 from NDB -system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t3 > /dev/null ; -system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t5 > /dev/null ; +system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t3 > /dev/null ; +system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t5 > /dev/null ; # Remove t6, t7 from disk system rm var/master-data/test/t6.frm > /dev/null ; system rm var/master-data/test/t7.frm > /dev/null ; @@ -306,8 +306,8 @@ insert into t8 values (8, "myisam table 8"); insert into t9 values (9); # Remove t3, t5 from NDB -system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t3 > /dev/null ; -system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t5 > /dev/null ; +system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t3 > /dev/null ; +system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t5 > /dev/null ; # Remove t6, t7 from disk system rm var/master-data/test/t6.frm > /dev/null ; system rm var/master-data/test/t7.frm > /dev/null ; @@ -479,4 +479,4 @@ create table t10 ( insert into t10 values (1, 'kalle'); ---exec $NDB_TOOLS_DIR/ndb_drop_table -d test `$NDB_TOOLS_DIR/ndb_show_tables | grep BLOB` > /dev/null 2>&1 || true +--exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test `$NDB_TOOLS_DIR/ndb_show_tables --no-defaults | grep BLOB` > /dev/null 2>&1 || true diff --git a/mysql-test/t/ndb_index_unique.test b/mysql-test/t/ndb_index_unique.test index bdb239497631d4833f10d444b8e2ffd030f29748..397a2c45a9fc4911979052f99af5272716a810a9 100644 --- a/mysql-test/t/ndb_index_unique.test +++ b/mysql-test/t/ndb_index_unique.test @@ -30,6 +30,32 @@ select * from t1 order by a; drop table t1; +# +# Indexing NULL values +# + +CREATE TABLE t1 ( + a int unsigned NOT NULL PRIMARY KEY, + b int unsigned, + c int unsigned, + UNIQUE bc(b,c) +) engine = ndb; + +insert into t1 values(1,1,1),(2,NULL,2),(3,NULL,NULL),(4,4,NULL); +select * from t1 use index (bc) where b IS NULL order by a; + +select * from t1 use index (bc)order by a; +select * from t1 use index (bc) order by a; +select * from t1 use index (PRIMARY) where b IS NULL order by a; +select * from t1 use index (bc) where b IS NULL order by a; +select * from t1 use index (bc) where b IS NULL and c IS NULL order by a; +select * from t1 use index (bc) where b IS NULL and c = 2 order by a; +select * from t1 use index (bc) where b < 4 order by a; +select * from t1 use index (bc) where b IS NOT NULL order by a; +-- error 1062 +insert into t1 values(5,1,1); +drop table t1; + # # Show use of UNIQUE USING HASH indexes @@ -58,6 +84,14 @@ select * from t2 order by a; drop table t2; +-- error 1121 +CREATE TABLE t2 ( + a int unsigned NOT NULL PRIMARY KEY, + b int unsigned not null, + c int unsigned, + UNIQUE USING HASH (b, c) +) engine=ndbcluster; + # # Show use of PRIMARY KEY USING HASH indexes # diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index e0f6fcbf5154d720d286d2b843e4e6e7b45ecec0..19bfaa6194a0f5c917502ab4a81ef76355d89d16 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1282,3 +1282,22 @@ INSERT INTO `t2` VALUES (6,5,12,7,'a'),(12,0,0,7,'a'),(12,1,0,7,'a'),(12,5,5,7,' SELECT b.sc FROM (SELECT (SELECT a.access FROM t1 a WHERE a.map = op.map AND a.slave = op.pid AND a.master = 1) ac FROM t2 op WHERE op.id = 12 AND op.map = 0) b; SELECT b.ac FROM (SELECT (SELECT a.access FROM t1 a WHERE a.map = op.map AND a.slave = op.pid AND a.master = 1) ac FROM t2 op WHERE op.id = 12 AND op.map = 0) b; drop tables t1,t2; + +# +# Test for bug #6462. "Same request on same data returns different +# results." a.k.a. "Proper cleanup of subqueries is missing for +# SET and DO statements". +# +create table t1 (a int not null, b int not null, c int, primary key (a,b)); +insert into t1 values (1,1,1), (2,2,2), (3,3,3); +set @b:= 0; +# Let us check that subquery will use covering index +explain select sum(a) from t1 where b > @b; +# This should not crash -debug server due to failing assertion +set @a:= (select sum(a) from t1 where b > @b); +# And this should not falsely report index usage +explain select a from t1 where c=2; +# Same for DO statement +do @a:= (select sum(a) from t1 where b > @b); +explain select a from t1 where c=2; +drop table t1; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 6f7940caf75faacb0144d1d95535b1a61ea7ce6f..cf7b66c5f03b8d582b4aa5cb64b37f859ecadc72 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -796,7 +796,8 @@ int ha_ndbcluster::build_index_list(TABLE *tab, enum ILBP phase) error= create_unique_index(unique_index_name, key_info); break; case UNIQUE_INDEX: - error= create_unique_index(unique_index_name, key_info); + if (!(error= check_index_fields_not_null(i))) + error= create_unique_index(unique_index_name, key_info); break; case ORDERED_INDEX: error= create_ordered_index(index_name, key_info); @@ -848,6 +849,26 @@ NDB_INDEX_TYPE ha_ndbcluster::get_index_type_from_table(uint inx) const ORDERED_INDEX); } +int ha_ndbcluster::check_index_fields_not_null(uint inx) +{ + KEY* key_info= table->key_info + inx; + KEY_PART_INFO* key_part= key_info->key_part; + KEY_PART_INFO* end= key_part+key_info->key_parts; + DBUG_ENTER("check_index_fields_not_null"); + + for (; key_part != end; key_part++) + { + Field* field= key_part->field; + if (field->maybe_null()) + { + my_printf_error(ER_NULL_COLUMN_IN_INDEX,ER(ER_NULL_COLUMN_IN_INDEX), + MYF(0),field->field_name); + DBUG_RETURN(ER_NULL_COLUMN_IN_INDEX); + } + } + + DBUG_RETURN(0); +} void ha_ndbcluster::release_metadata() { diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 6b878681c05d4740160fce7d6c425f59a122aebf..f6c712620c15576fc0d0c7dc6f945df7d1092c08 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -160,7 +160,8 @@ class ha_ndbcluster: public handler void release_metadata(); NDB_INDEX_TYPE get_index_type(uint idx_no) const; NDB_INDEX_TYPE get_index_type_from_table(uint index_no) const; - + int check_index_fields_not_null(uint index_no); + int pk_read(const byte *key, uint key_len, byte *buf); int complemented_pk_read(const byte *old_data, byte *new_data); int peek_row(); diff --git a/sql/set_var.cc b/sql/set_var.cc index f1973b53e49a50099366f579253f49e78718f00a..2031ac1541222ed3e2e5b30f8fe20371b2c4982b 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2733,13 +2733,18 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list) while ((var=it++)) { if ((error=var->check(thd))) - DBUG_RETURN(error); + goto err; } - if (thd->net.report_error) - DBUG_RETURN(1); - it.rewind(); - while ((var=it++)) - error|= var->update(thd); // Returns 0, -1 or 1 + if (!thd->net.report_error) + { + it.rewind(); + while ((var= it++)) + error|= var->update(thd); // Returns 0, -1 or 1 + } + else + error= 1; +err: + free_underlaid_joins(thd, &thd->lex->select_lex); DBUG_RETURN(error); } diff --git a/sql/sql_do.cc b/sql/sql_do.cc index 25a8359f3d2e0bbe0b5bc07647f88a5ba4c4230c..0d4529fb29e2a902c49f3abb064963bfe8c52243 100644 --- a/sql/sql_do.cc +++ b/sql/sql_do.cc @@ -29,6 +29,7 @@ int mysql_do(THD *thd, List<Item> &values) DBUG_RETURN(-1); while ((value = li++)) value->val_int(); + free_underlaid_joins(thd, &thd->lex->select_lex); thd->clear_error(); // DO always is OK send_ok(thd); DBUG_RETURN(0); diff --git a/strings/uca-dump.c b/strings/uca-dump.c index c9642598c3cda3b821caa45336338df272f3907e..db5cb7e999aa957ace902db8a08a91a914dda610 100644 --- a/strings/uca-dump.c +++ b/strings/uca-dump.c @@ -218,7 +218,6 @@ int main(int ac, char **av) */ if (ndefs == MY_UCA_NCHARS) { - printf("/* Don't dump w=%d pg=%3X: ndefs=%d */\n",w, page, ndefs); continue; } switch (maxnum) @@ -263,7 +262,17 @@ int main(int ac, char **av) for (i=0; i < maxnum; i++) { - printf("0x%04X",(int)weight[i]); + /* + Invert weights for secondary level to + sort upper case letters before their + lower case counter part. + */ + int tmp= weight[i]; + if (w == 2 && tmp) + tmp= (int)(0x100 - weight[i]); + + + printf("0x%04X", tmp); if ((offs+1 != MY_UCA_NCHARS) || (i+1!=maxnum)) printf(","); nchars++; @@ -281,7 +290,7 @@ int main(int ac, char **av) printf("};\n\n"); } - printf("uchar ucal%s[%d]={\n", pname[w], MY_UCA_NPAGES); + printf("uchar uca_length%s[%d]={\n", pname[w], MY_UCA_NPAGES); for (page=0; page < MY_UCA_NPAGES; page++) { printf("%d%s%s",pagemaxlen[page],page<MY_UCA_NPAGES-1?",":"",(page+1) % 16 ? "":"\n"); @@ -289,7 +298,7 @@ int main(int ac, char **av) printf("};\n"); - printf("uint16 *ucaw%s[%d]={\n", pname[w], MY_UCA_NPAGES); + printf("uint16 *uca_weight%s[%d]={\n", pname[w], MY_UCA_NPAGES); for (page=0; page < MY_UCA_NPAGES; page++) { const char *comma= page < MY_UCA_NPAGES-1 ? "," : "";