From 05750704a83bc3388e007145e16907c0b61abaa2 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Jun 2006 16:01:54 +0500 Subject: [PATCH 01/23] Fix for bug #12728: Very strange behaviour of ELT mysql-test/r/func_str.result: Fix for bug #12728: Very strange behaviour of ELT - test case mysql-test/t/func_str.test: Fix for bug #12728: Very strange behaviour of ELT - test result sql/item_strfunc.cc: Fix for bug #12728: Very strange behaviour of ELT - Item_func_elt::eq() introduced: check 'item' member as well (to distinguish for instance elt(1, 'a', 'b') and elt(2, 'a', 'b') sql/item_strfunc.h: Fix for bug #12728: Very strange behaviour of ELT - Item_func_elt::eq() introduced: check 'item' member as well (to distinguish for instance elt(1, 'a', 'b') and elt(2, 'a', 'b') --- mysql-test/r/func_str.result | 7 +++++++ mysql-test/t/func_str.test | 8 ++++++++ sql/item_strfunc.cc | 11 +++++++++++ sql/item_strfunc.h | 1 + 4 files changed, 27 insertions(+) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 6fefbb16353..1feda854014 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -436,3 +436,10 @@ id aes_decrypt(str, 'bar') 1 foo 2 NULL DROP TABLE t1, t2; +create table t1(a varchar(8), primary key(a)); +insert into t1 values('bar'), ('foo'); +select a from t1 where a=elt(1, 'foo', 'bar') or a=elt(2, 'foo', 'bar'); +a +bar +foo +drop table t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 81d5daaf0ba..0e7ab70940a 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -254,3 +254,11 @@ SELECT t1.id, aes_decrypt(str, 'bar') FROM t1, t2 WHERE t1.id = t2.id DROP TABLE t1, t2; +# +# Bug #12728: strange elt() behavior +# + +create table t1(a varchar(8), primary key(a)); +insert into t1 values('bar'), ('foo'); +select a from t1 where a=elt(1, 'foo', 'bar') or a=elt(2, 'foo', 'bar'); +drop table t1; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index f070382e5c1..2ea693e94a3 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1599,6 +1599,17 @@ String *Item_func_elt::val_str(String *str) } +bool Item_func_elt::eq(const Item *par_item, bool binary_cmp) const +{ + /* + We can use (Item_func_elt*) typecast here because the check is done + in the Item_func::eq(). + */ + return Item_func::eq(par_item, binary_cmp) && + item->eq(((Item_func_elt*) par_item)->item, binary_cmp); +} + + void Item_func_make_set::split_sum_func(List &fields) { if (item->with_sum_func && item->type() != SUM_FUNC_ITEM) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index ece15484fd9..482a941c55b 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -372,6 +372,7 @@ public: void fix_length_and_dec(); void update_used_tables(); const char *func_name() const { return "elt"; } + bool eq(const Item *par_item, bool binary_cmp) const; unsigned int size_of() { return sizeof(*this);} }; From 95939476ab600f2e19ac6780fc985b0500b60b9c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Jun 2006 13:03:29 +0500 Subject: [PATCH 02/23] Fix for bug #20496: func_time.test failure mysql-test/r/func_time.result: Fix for bug #20496: func_time.test failure - floating point calculations removed. mysql-test/t/func_time.test: Fix for bug #20496: func_time.test failure - floating point calculations removed. --- mysql-test/r/func_time.result | 13 ++++++++++--- mysql-test/t/func_time.test | 6 ++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index e7a00b71961..c90a4258036 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -671,7 +671,14 @@ select f1 from t1 where makedate(2006,2) between date(f1) and date(f3); f1 2006-01-02 drop table t1; -select now() - now() + 0, curtime() - curtime() + 0, +create table t1 select now() - now(), curtime() - curtime(), sec_to_time(1) + 0, from_unixtime(1) + 0; -now() - now() + 0 curtime() - curtime() + 0 sec_to_time(1) + 0 from_unixtime(1) + 0 -0.000000 0.000000 1.000000 19700101030001.000000 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `now() - now()` double(23,6) NOT NULL default '0.000000', + `curtime() - curtime()` double(23,6) NOT NULL default '0.000000', + `sec_to_time(1) + 0` double(23,6) default NULL, + `from_unixtime(1) + 0` double(23,6) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 23e3b9d982a..d69545712c8 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -347,7 +347,9 @@ drop table t1; # Bug #16546 # -select now() - now() + 0, curtime() - curtime() + 0, - sec_to_time(1) + 0, from_unixtime(1) + 0; +create table t1 select now() - now(), curtime() - curtime(), + sec_to_time(1) + 0, from_unixtime(1) + 0; +show create table t1; +drop table t1; # End of 4.1 tests From 124cb126fa65fc1099256be5e269277bde815703 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Jun 2006 13:22:42 +0300 Subject: [PATCH 03/23] * Bug #9676: INSERT INTO x SELECT .. FROM x LIMIT 1; slows down with big tables Currently in INSERT ... SELECT ... LIMIT ... the compiler uses a temporary table to store the results of SELECT ... LIMIT .. and then uses that table as a source for INSERT. The problem is that in some cases it actually skips the LIMIT clause in doing that and materializes the whole SELECT result set regardless of the LIMIT. This fix is limiting the process of filling up the temp table with only that much rows that will be actually used by propagating the LIMIT value. mysql-test/r/insert_select.result: * Bug #9676: INSERT INTO x SELECT .. FROM x LIMIT 1; slows down with big tables - a test demonstrating the code path mysql-test/t/insert_select.test: * Bug #9676: INSERT INTO x SELECT .. FROM x LIMIT 1; slows down with big tables - a test demonstrating the code path sql/sql_select.cc: * Bug #9676: INSERT INTO x SELECT .. FROM x LIMIT 1; slows down with big tables - pass through the real LIMIT number if the temp table is created for buffering results. - set the counter for all the cases when the temp table is not used for grouping --- mysql-test/r/insert_select.result | 4 ++++ mysql-test/t/insert_select.test | 13 +++++++++++++ sql/sql_select.cc | 12 ++++++++---- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 028b40ac3b6..1d7aef256e1 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -686,3 +686,7 @@ ERROR 42S22: Unknown column 'z' in 'field list' insert into t1(x,y) select x,z from t2 on duplicate key update x=values(t2.x); ERROR 42S02: Unknown table 't2' in field list drop table t1,t2; +CREATE TABLE t1 (a int PRIMARY KEY); +INSERT INTO t1 values (1), (2); +INSERT INTO t1 SELECT a + 2 FROM t1 LIMIT 1; +DROP TABLE t1; diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 48acdf1cbc5..fcea489fcff 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -226,4 +226,17 @@ insert into t1(x,y) select x,z from t2 on duplicate key update x=values(z); insert into t1(x,y) select x,z from t2 on duplicate key update x=values(t2.x); drop table t1,t2; +# +# Bug #9676: INSERT INTO x SELECT .. FROM x LIMIT 1; slows down with big +# tables +# + +#Note: not an exsaustive test : just a check of the code path. +CREATE TABLE t1 (a int PRIMARY KEY); +INSERT INTO t1 values (1), (2); + +INSERT INTO t1 SELECT a + 2 FROM t1 LIMIT 1; + +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5a7e9e52aed..709ff9726bb 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -888,8 +888,9 @@ JOIN::optimize() group_list ? 0 : select_distinct, group_list && simple_group, select_options, - (order == 0 || skip_sort_order) ? select_limit : - HA_POS_ERROR, + (order == 0 || skip_sort_order || + test(select_options & OPTION_BUFFER_RESULT)) ? + select_limit : HA_POS_ERROR, (char *) ""))) DBUG_RETURN(1); @@ -5530,6 +5531,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, keyinfo->key_length+= key_part_info->length; } } + else + { + set_if_smaller(table->max_rows, rows_limit); + param->end_write_records= rows_limit; + } if (distinct && field_count != param->hidden_field_count) { @@ -5544,8 +5550,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, null_pack_length-=hidden_null_pack_length; keyinfo->key_parts= ((field_count-param->hidden_field_count)+ test(null_pack_length)); - set_if_smaller(table->max_rows, rows_limit); - param->end_write_records= rows_limit; table->distinct=1; table->keys=1; if (blob_count) From b7e27e80d9dc065d2ecc49aad371a71ad3a824a4 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Jun 2006 17:34:12 +0300 Subject: [PATCH 04/23] Bug #18080: INSERT ... SELECT ... JOIN results in ambiguous field list error There was an incomplete reset of the name resolution context, that caused INSERT ... SELECT ... JOIN statements to resolve not by joint row type calculated for the join. Removed the redundant re-initialization of the context, because mysql_insert_select_prepare() now correctly saves/restores the context. mysql-test/r/insert_select.result: Bug #18080: INSERT ... SELECT ... JOIN results in ambiguous field list error - testsuite for the bug mysql-test/t/insert_select.test: Bug #18080: INSERT ... SELECT ... JOIN results in ambiguous field list error - testsuite for the bug sql/sql_parse.cc: Bug #18080: INSERT ... SELECT ... JOIN results in ambiguous field list error - remove an incomplete reset of the context because the mentioned function correctly saves/restores the context. --- mysql-test/r/insert_select.result | 5 +++++ mysql-test/t/insert_select.test | 9 +++++++++ sql/sql_parse.cc | 9 --------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 434dddb3049..62450997260 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -686,3 +686,8 @@ ERROR 42S22: Unknown column 'z' in 'field list' insert into t1(x,y) select x,z from t2 on duplicate key update x=values(t2.x); ERROR 42S22: Unknown column 't2.x' in 'field list' drop table t1,t2; +CREATE TABLE t1 (x int, y int); +CREATE TABLE t2 (z int, y int); +CREATE TABLE t3 (a int, b int); +INSERT INTO t3 (SELECT x, y FROM t1 JOIN t2 USING (y) WHERE z = 1); +DROP TABLE IF EXISTS t1,t2,t3; diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 5dd6f338865..0e1d48fe9f5 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -225,3 +225,12 @@ insert into t1(x,y) select x,z from t2 on duplicate key update x=values(t2.x); drop table t1,t2; # End of 4.1 tests + +# +# Bug #18080: INSERT ... SELECT ... JOIN results in ambiguous field list error +# +CREATE TABLE t1 (x int, y int); +CREATE TABLE t2 (z int, y int); +CREATE TABLE t3 (a int, b int); +INSERT INTO t3 (SELECT x, y FROM t1 JOIN t2 USING (y) WHERE z = 1); +DROP TABLE IF EXISTS t1,t2,t3; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ba5c2ebf484..28b2abfc883 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3333,15 +3333,6 @@ end_with_restore_list: &lex->value_list, lex->duplicates, lex->ignore))) { - /* - Skip first table, which is the table we are inserting in. - Below we set context.table_list again because the call above to - mysql_insert_select_prepare() calls resolve_in_table_list_only(), - which in turn resets context.table_list and - context.first_name_resolution_table. - */ - select_lex->context.table_list= - select_lex->context.first_name_resolution_table= second_table; res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE); /* Invalidate the table in the query cache if something changed From 7751eeaf3c928cc799f5ce3f4766e44367a70910 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Jun 2006 11:28:59 +0300 Subject: [PATCH 05/23] wrong merge of bug9676 from 4.1 to 5.0 corrected --- sql/sql_select.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a243f22e7ee..fe4993fddbf 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8817,7 +8817,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, } else { - set_if_smaller(table->max_rows, rows_limit); + set_if_smaller(table->s->max_rows, rows_limit); param->end_write_records= rows_limit; } From dad508ea1a23aff53a9c9edde80c2caa1b9cf460 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Jun 2006 20:46:45 +0200 Subject: [PATCH 06/23] Bug#19437 (Connection refused by server: "2002 Can't connect... /master.sock"): Clearing active VIO before calling mysql_close() in the slave I/O thread. sql/slave.cc: Clearing active VIO before calling mysql_close() in the slave I/O thread. --- sql/slave.cc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sql/slave.cc b/sql/slave.cc index caeefc1ad3c..2b31d722f26 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1653,6 +1653,15 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name, if (connect_to_master(thd, mysql, mi)) { my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql)); + /* + We need to clear the active VIO since, theoretically, somebody + might issue an awake() on this thread. If we are then in the + middle of closing and destroying the VIO inside the + mysql_close(), we will have a problem. + */ +#ifdef SIGNAL_WITH_VIO_CLOSE + thd->clear_active_vio(); +#endif mysql_close(mysql); DBUG_RETURN(1); } @@ -3709,6 +3718,17 @@ err: VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (mysql) { + /* + Here we need to clear the active VIO before closing the + connection with the master. The reason is that THD::awake() + might be called from terminate_slave_thread() because somebody + issued a STOP SLAVE. If that happends, the close_active_vio() + can be called in the middle of closing the VIO associated with + the 'mysql' object, causing a crash. + */ +#ifdef SIGNAL_WITH_VIO_CLOSE + thd->clear_active_vio(); +#endif mysql_close(mysql); mi->mysql=0; } From 3e7d68b11cd65dac087e2a634a8f007a295c6528 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Jun 2006 23:05:55 +0400 Subject: [PATCH 07/23] select.result: Added test case for bug#18759 Incorrect string to numeric conversion. select.test: Added test case for bug#18759 Incorrect string to numeric conversion. item_cmpfunc.cc: Cleanup after fix for bug#18360 removal sql/item_cmpfunc.cc: Cleanup after fix for bug#18360 removal mysql-test/t/select.test: Added test case for bug#18759 Incorrect string to numeric conversion. mysql-test/r/select.result: Added test case for bug#18759 Incorrect string to numeric conversion. --- mysql-test/r/select.result | 6 ++++++ mysql-test/t/select.test | 19 +++++++++++++++++++ sql/item_cmpfunc.cc | 3 ++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 7808e787e39..c7df11ab018 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2738,3 +2738,9 @@ ERROR HY000: Key 'a' doesn't exist in table 't1' EXPLAIN SELECT * FROM t1 FORCE INDEX (a); ERROR HY000: Key 'a' doesn't exist in table 't1' DROP TABLE t1; +CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL); +INSERT INTO t1 VALUES (10); +SELECT i='1e+01',i=1e+01, i in (1e+01), i in ('1e+01') FROM t1; +i='1e+01' i=1e+01 i in (1e+01) i in ('1e+01') +0 1 1 1 +DROP TABLE t1; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index f7b5a2fbcb6..4cdfc220350 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2278,4 +2278,23 @@ EXPLAIN SELECT * FROM t1 FORCE INDEX (a); DROP TABLE t1; +# +# Bug #18759 "Incorrect string to numeric conversion" +# +# This test is here so that the behavior will not be changed to 4.1 +# and not to 5.0 either. In 4.1 and 5.0 sending an integer as a string +# will be converted internally to real (double) value and it is not +# as accurate as bigint (longlong) for integers. Thus the results may +# vary. In 5.1 internally it is decimal, which is a string type and +# will be more accurate. Due to rather big changes needed to fix this +# in 4.1 or 5.0 it is not desired to do it in the stable versions. +# +# This test is here only to make sure that behavior is not changed in +# 4.1 and 5.0 +# +CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL); +INSERT INTO t1 VALUES (10); +SELECT i='1e+01',i=1e+01, i in (1e+01), i in ('1e+01') FROM t1; +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5055b5f4197..f14efc7187b 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -136,7 +136,8 @@ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) } continue; } - if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM) + if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM && + items[i]->result_type() != INT_RESULT) { field= ((Item_field *)items[i]->real_item())->field; break; From 406a7ba99209dd65a6974f2689fc92541ccf4450 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jun 2006 01:14:53 +0400 Subject: [PATCH 08/23] field.cc, field.h: Additional fix for #16377 for bigendian platforms sql_select.cc, select.result, select.test: After merge fix mysql-test/t/select.test: After merge fix mysql-test/r/select.result: After merge fix sql/sql_select.cc: After merge fix sql/field.h: Additional fix for #16377 for bigendian platforms sql/field.cc: Additional fix for #16377 for bigendian platforms --- mysql-test/r/select.result | 12 +++++------ mysql-test/t/select.test | 2 +- sql/field.cc | 44 +++++++++++++++++++------------------- sql/field.h | 2 +- sql/sql_select.cc | 2 +- 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index a9381f7c942..e6c590489a0 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2730,6 +2730,12 @@ ERROR HY000: Key 'a' doesn't exist in table 't1' EXPLAIN SELECT * FROM t1 FORCE INDEX (a); ERROR HY000: Key 'a' doesn't exist in table 't1' DROP TABLE t1; +CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL); +INSERT INTO t1 VALUES (10); +SELECT i='1e+01',i=1e+01, i in (1e+01,1e+01), i in ('1e+01','1e+01') FROM t1; +i='1e+01' i=1e+01 i in (1e+01,1e+01) i in ('1e+01','1e+01') +0 1 1 1 +DROP TABLE t1; CREATE TABLE t1 ( K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '', K4N4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '0000', @@ -3389,9 +3395,3 @@ a t1.b + 0 t1.c + 0 a t2.b + 0 c d 1 0 1 1 0 1 NULL 2 0 1 NULL NULL NULL NULL drop table t1,t2; -CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL); -INSERT INTO t1 VALUES (10); -SELECT i='1e+01',i=1e+01, i in (1e+01), i in ('1e+01') FROM t1; -i='1e+01' i=1e+01 i in (1e+01) i in ('1e+01') -0 1 1 1 -DROP TABLE t1; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 707892a5b16..b75d0dd8bb6 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2301,7 +2301,7 @@ DROP TABLE t1; # CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL); INSERT INTO t1 VALUES (10); -SELECT i='1e+01',i=1e+01, i in (1e+01), i in ('1e+01') FROM t1; +SELECT i='1e+01',i=1e+01, i in (1e+01,1e+01), i in ('1e+01','1e+01') FROM t1; DROP TABLE t1; # End of 4.1 tests diff --git a/sql/field.cc b/sql/field.cc index 33fc5ab3128..7c25e4ad9f7 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4566,7 +4566,7 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs) } #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int4store(ptr,tmp); } @@ -4632,7 +4632,7 @@ int Field_timestamp::store(longlong nr, bool unsigned_val) nr, MYSQL_TIMESTAMP_DATETIME, 1); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int4store(ptr,timestamp); } @@ -4656,7 +4656,7 @@ longlong Field_timestamp::val_int(void) THD *thd= table ? table->in_use : current_thd; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) temp=uint4korr(ptr); else #endif @@ -4686,7 +4686,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr) val_buffer->length(field_length); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) temp=uint4korr(ptr); else #endif @@ -4751,7 +4751,7 @@ bool Field_timestamp::get_date(TIME *ltime, uint fuzzydate) long temp; THD *thd= table ? table->in_use : current_thd; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) temp=uint4korr(ptr); else #endif @@ -4788,7 +4788,7 @@ int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr) { int32 a,b; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { a=sint4korr(a_ptr); b=sint4korr(b_ptr); @@ -4806,7 +4806,7 @@ int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr) void Field_timestamp::sort_string(char *to,uint length __attribute__((unused))) { #ifdef WORDS_BIGENDIAN - if (!table->s->db_low_byte_first) + if (!table || !table->s->db_low_byte_first) { to[0] = ptr[0]; to[1] = ptr[1]; @@ -4836,7 +4836,7 @@ void Field_timestamp::set_time() long tmp= (long) thd->query_start(); set_notnull(); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int4store(ptr,tmp); } @@ -5238,7 +5238,7 @@ int Field_date::store(const char *from, uint len,CHARSET_INFO *cs) from, len, MYSQL_TIMESTAMP_DATE, 1); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int4store(ptr,tmp); } @@ -5299,7 +5299,7 @@ int Field_date::store(longlong nr, bool unsigned_val) MYSQL_TIMESTAMP_DATETIME, 1); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int4store(ptr, nr); } @@ -5325,7 +5325,7 @@ double Field_date::val_real(void) { int32 j; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) j=sint4korr(ptr); else #endif @@ -5338,7 +5338,7 @@ longlong Field_date::val_int(void) { int32 j; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) j=sint4korr(ptr); else #endif @@ -5354,7 +5354,7 @@ String *Field_date::val_str(String *val_buffer, val_buffer->alloc(field_length); int32 tmp; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) tmp=sint4korr(ptr); else #endif @@ -5372,7 +5372,7 @@ int Field_date::cmp(const char *a_ptr, const char *b_ptr) { int32 a,b; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { a=sint4korr(a_ptr); b=sint4korr(b_ptr); @@ -5390,7 +5390,7 @@ int Field_date::cmp(const char *a_ptr, const char *b_ptr) void Field_date::sort_string(char *to,uint length __attribute__((unused))) { #ifdef WORDS_BIGENDIAN - if (!table->s->db_low_byte_first) + if (!table || !table->s->db_low_byte_first) { to[0] = ptr[0]; to[1] = ptr[1]; @@ -5630,7 +5630,7 @@ int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs) from, len, MYSQL_TIMESTAMP_DATETIME, 1); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int8store(ptr,tmp); } @@ -5683,7 +5683,7 @@ int Field_datetime::store(longlong nr, bool unsigned_val) MYSQL_TIMESTAMP_DATETIME, 1); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int8store(ptr,nr); } @@ -5712,7 +5712,7 @@ int Field_datetime::store_time(TIME *ltime,timestamp_type type) set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); } #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int8store(ptr,tmp); } @@ -5739,7 +5739,7 @@ longlong Field_datetime::val_int(void) { longlong j; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) j=sint8korr(ptr); else #endif @@ -5759,7 +5759,7 @@ String *Field_datetime::val_str(String *val_buffer, int part3; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) tmp=sint8korr(ptr); else #endif @@ -5824,7 +5824,7 @@ int Field_datetime::cmp(const char *a_ptr, const char *b_ptr) { longlong a,b; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { a=sint8korr(a_ptr); b=sint8korr(b_ptr); @@ -5842,7 +5842,7 @@ int Field_datetime::cmp(const char *a_ptr, const char *b_ptr) void Field_datetime::sort_string(char *to,uint length __attribute__((unused))) { #ifdef WORDS_BIGENDIAN - if (!table->s->db_low_byte_first) + if (!table || !table->s->db_low_byte_first) { to[0] = ptr[0]; to[1] = ptr[1]; diff --git a/sql/field.h b/sql/field.h index e7b7aa45c27..ed13372df71 100644 --- a/sql/field.h +++ b/sql/field.h @@ -813,7 +813,7 @@ public: if ((*null_value= is_null())) return 0; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) return sint4korr(ptr); #endif long tmp; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7d7975436a5..9f317842d98 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8817,7 +8817,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, } else { - set_if_smaller(table->max_rows, rows_limit); + set_if_smaller(table->s->max_rows, rows_limit); param->end_write_records= rows_limit; } From e9452db1c1b7fb534a44590312d6608640675350 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jun 2006 01:50:20 +0400 Subject: [PATCH 09/23] Fix for bug#19634 "Re-execution of multi-delete which involve trigger/stored function crashes server". Attempts to execute prepared multi-delete statement which involved trigger or stored function caused server crashes (the same happened for such statements included in stored procedures in cases when one tried to execute them more than once). The problem was caused by yet another incorrect usage of check_table_access() routine (the latter assumes that table list which it gets as argument corresponds to value LEX::query_tables_own_last). We solve this problem by juggling with LEX::query_tables_own_last value when we call check_table_access() for LEX::auxilliary_table_list (better solution is too intrusive and should be done in 5.1). mysql-test/r/sp-prelocking.result: Added test for bug#19634 "Re-execution of multi-delete which involve trigger/ stored function crashes server". mysql-test/t/sp-prelocking.test: Added test for bug#19634 "Re-execution of multi-delete which involve trigger/ stored function crashes server". sql/sql_parse.cc: To call safely check_table_access() for LEX::auxilliary_table_list we have to juggle with LEX::query_tables_own_last value. --- mysql-test/r/sp-prelocking.result | 18 ++++++++++++++ mysql-test/t/sp-prelocking.test | 31 ++++++++++++++++++++++++ sql/sql_parse.cc | 40 +++++++++++++++++++++++++++---- 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/sp-prelocking.result b/mysql-test/r/sp-prelocking.result index 2335513b28a..7d8dd862748 100644 --- a/mysql-test/r/sp-prelocking.result +++ b/mysql-test/r/sp-prelocking.result @@ -237,3 +237,21 @@ deallocate prepare stmt; drop table t1; drop view v1, v2, v3; drop function bug15683; +drop table if exists t1, t2, t3; +drop function if exists bug19634; +create table t1 (id int, data int); +create table t2 (id int); +create table t3 (data int); +create function bug19634() returns int return (select count(*) from t3); +prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id and bug19634()"; +execute stmt; +execute stmt; +deallocate prepare stmt; +create trigger t1_bi before delete on t1 for each row insert into t3 values (old.data); +prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id"; +execute stmt; +execute stmt; +deallocate prepare stmt; +drop function bug19634; +drop table t1, t2, t3; +End of 5.0 tests diff --git a/mysql-test/t/sp-prelocking.test b/mysql-test/t/sp-prelocking.test index a7215462afb..b94de6236d3 100644 --- a/mysql-test/t/sp-prelocking.test +++ b/mysql-test/t/sp-prelocking.test @@ -272,3 +272,34 @@ drop table t1; drop view v1, v2, v3; drop function bug15683; + +# +# Bug#19634 "Re-execution of multi-delete which involve trigger/stored +# function crashes server" +# +--disable_warnings +drop table if exists t1, t2, t3; +drop function if exists bug19634; +--enable_warnings +create table t1 (id int, data int); +create table t2 (id int); +create table t3 (data int); +create function bug19634() returns int return (select count(*) from t3); +prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id and bug19634()"; +# This should not crash server +execute stmt; +execute stmt; +deallocate prepare stmt; + +create trigger t1_bi before delete on t1 for each row insert into t3 values (old.data); +prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id"; + +execute stmt; +execute stmt; +deallocate prepare stmt; + +drop function bug19634; +drop table t1, t2, t3; + + +--echo End of 5.0 tests diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ba5c2ebf484..7ed96250240 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5202,8 +5202,26 @@ bool check_global_access(THD *thd, ulong want_access) /* - Check the privilege for all used tables. Table privileges are cached - in the table list for GRANT checking + Check the privilege for all used tables. + + SYNOPSYS + check_table_access() + thd Thread context + want_access Privileges requested + tables List of tables to be checked + no_errors FALSE/TRUE - report/don't report error to + the client (using my_error() call). + + NOTES + Table privileges are cached in the table list for GRANT checking. + This functions assumes that table list used and + thd->lex->query_tables_own_last value correspond to each other + (the latter should be either 0 or point to next_global member + of one of elements of this table list). + + RETURN VALUE + FALSE - OK + TRUE - Access denied */ bool @@ -7068,14 +7086,28 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) SELECT_LEX *select_lex= &thd->lex->select_lex; TABLE_LIST *aux_tables= (TABLE_LIST *)thd->lex->auxilliary_table_list.first; + TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last; DBUG_ENTER("multi_delete_precheck"); /* sql_yacc guarantees that tables and aux_tables are not zero */ DBUG_ASSERT(aux_tables != 0); if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) || - check_table_access(thd,SELECT_ACL, tables,0) || - check_table_access(thd,DELETE_ACL, aux_tables,0)) + check_table_access(thd, SELECT_ACL, tables, 0)) DBUG_RETURN(TRUE); + + /* + Since aux_tables list is not part of LEX::query_tables list we + have to juggle with LEX::query_tables_own_last value to be able + call check_table_access() safely. + */ + thd->lex->query_tables_own_last= 0; + if (check_table_access(thd, DELETE_ACL, aux_tables, 0)) + { + thd->lex->query_tables_own_last= save_query_tables_own_last; + DBUG_RETURN(TRUE); + } + thd->lex->query_tables_own_last= save_query_tables_own_last; + if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where) { my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, From 0baf2087a2bdc87aca5c64be8097f978e5228c10 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jun 2006 02:21:10 +0400 Subject: [PATCH 10/23] Remove deadcode in select_dumpvar::send_data() --- sql/sql_class.cc | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 678048226af..06082a57964 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1853,15 +1853,10 @@ bool select_dumpvar::send_data(List &items) Item_func_set_user_var *xx; Item_splocal *yy; my_var *zz; - DBUG_ENTER("send_data"); - if (unit->offset_limit_cnt) - { // using limit offset,count - unit->offset_limit_cnt--; - DBUG_RETURN(0); - } + DBUG_ENTER("select_dumpvar::send_data"); if (unit->offset_limit_cnt) - { // Using limit offset,count + { // using limit offset,count unit->offset_limit_cnt--; DBUG_RETURN(0); } From 72cb1d5049c781ed82f0f0859df74383d0d62824 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jun 2006 02:23:18 +0300 Subject: [PATCH 11/23] Fix for Bug#18246 "compilation error with tcp_wrapper" sql/mysqld.cc: Fix for Bug#18246 "compilation error with tcp_wrapper" Added wrapper functions. --- include/Makefile.am | 2 +- include/my_libwrap.h | 19 +++++++++++++++++++ mysys/Makefile.am | 2 +- mysys/my_libwrap.c | 39 +++++++++++++++++++++++++++++++++++++++ sql/mysqld.cc | 6 +++--- 5 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 include/my_libwrap.h create mode 100644 mysys/my_libwrap.c diff --git a/include/Makefile.am b/include/Makefile.am index 07c32e3127b..2dbea3fe07f 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -31,7 +31,7 @@ noinst_HEADERS = config-win.h config-os2.h config-netware.h \ my_aes.h my_tree.h hash.h thr_alarm.h \ thr_lock.h t_ctype.h violite.h md5.h base64.h \ mysql_version.h.in my_handler.h my_time.h decimal.h \ - my_user.h + my_user.h my_libwrap.h # mysql_version.h are generated CLEANFILES = mysql_version.h my_config.h readline openssl diff --git a/include/my_libwrap.h b/include/my_libwrap.h new file mode 100644 index 00000000000..a5cc9879e4f --- /dev/null +++ b/include/my_libwrap.h @@ -0,0 +1,19 @@ +/* Copyright (C) 2000 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +extern void my_fromhost(struct request_info *req); +extern int my_hosts_access(struct request_info *req); +extern char *my_eval_client(struct request_info *req); diff --git a/mysys/Makefile.am b/mysys/Makefile.am index d046b2fa3f8..bc84f44cd29 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -56,7 +56,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ my_gethostbyname.c rijndael.c my_aes.c sha1.c \ my_handler.c my_netware.c my_largepage.c \ my_memmem.c \ - my_windac.c my_access.c base64.c + my_windac.c my_access.c base64.c my_libwrap.c EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ thr_mutex.c thr_rwlock.c libmysys_a_LIBADD = @THREAD_LOBJECTS@ diff --git a/mysys/my_libwrap.c b/mysys/my_libwrap.c new file mode 100644 index 00000000000..29a0ecf3fc6 --- /dev/null +++ b/mysys/my_libwrap.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include +#ifdef HAVE_LIBWRAP +#include +#include +#ifdef NEED_SYS_SYSLOG_H +#include +#endif /* NEED_SYS_SYSLOG_H */ +#endif + +void my_fromhost(struct request_info *req) +{ + fromhost(req); +} + +int my_hosts_access(struct request_info *req) +{ + hosts_access(req); +} + +char *my_eval_client(struct request_info *req) +{ + eval_client(req); +} diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d7a38d6b715..262a5352ed9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4072,8 +4072,8 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) struct request_info req; signal(SIGCHLD, SIG_DFL); request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL); - fromhost(&req); - if (!hosts_access(&req)) + my_fromhost(&req); + if (!my_hosts_access(&req)) { /* This may be stupid but refuse() includes an exit(0) @@ -4081,7 +4081,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) clean_exit() - same stupid thing ... */ syslog(deny_severity, "refused connect from %s", - eval_client(&req)); + my_eval_client(&req)); /* C++ sucks (the gibberish in front just translates the supplied From 6c787151613ad1d443b43389d534861b8bf757e4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jun 2006 12:12:46 +0300 Subject: [PATCH 12/23] Bug #20482: failure on Create join view with sources views/tables in different schemas The function check_one_table_access() called to check access to tables in SELECT/INSERT/UPDATE was doing additional checks/modifications that don't hold in the context of setup_tables_and_check_access(). That's why the check_one_table() was split into two : the functionality needed by setup_tables_and_check_access() into check_single_table_access() and the rest of the functionality stays in check_one_table_access() that is made to call the new check_single_table_access() function. mysql-test/r/view_grant.result: Bug #20482: failure on Create join view with sources views/tables in different schemas - test suite for the bug mysql-test/t/view_grant.test: Bug #20482: failure on Create join view with sources views/tables in different schemas - test suite for the bug sql/mysql_priv.h: Bug #20482: failure on Create join view with sources views/tables in different schemas - check_one_table_access split into 2 sql/sql_base.cc: Bug #20482: failure on Create join view with sources views/tables in different schemas - the new sub-function called sql/sql_parse.cc: Bug #20482: failure on Create join view with sources views/tables in different schemas - check_one_table_access() split into two : check_single_table_access() to actually check access to the table(ro) and check_one_table_access() that calls check_single_table_access() and checks also the tables belonging to sub selects or implicitly opened tables. --- mysql-test/r/view_grant.result | 12 ++++++++++ mysql-test/t/view_grant.test | 21 ++++++++++++++++++ sql/mysql_priv.h | 2 ++ sql/sql_base.cc | 2 +- sql/sql_parse.cc | 40 ++++++++++++++++++++++++++-------- 5 files changed, 67 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index f6559e6f838..11161d0c844 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -618,3 +618,15 @@ ERROR HY000: There is no 'no-such-user'@'localhost' registered DROP VIEW v; DROP TABLE t1; USE test; +CREATE DATABASE test1; +CREATE DATABASE test2; +CREATE TABLE test1.t0 (a VARCHAR(20)); +CREATE TABLE test2.t1 (a VARCHAR(20)); +CREATE VIEW test2.t3 AS SELECT * FROM test1.t0; +CREATE OR REPLACE VIEW test.v1 AS +SELECT ta.a AS col1, tb.a AS col2 FROM test2.t3 ta, test2.t1 tb; +DROP VIEW test.v1; +DROP VIEW test2.t3; +DROP TABLE test2.t1, test1.t0; +DROP DATABASE test2; +DROP DATABASE test1; diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 4663a667d25..9d23bfa6197 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -807,3 +807,24 @@ SELECT * FROM v; DROP VIEW v; DROP TABLE t1; USE test; + +# +# BUG#20482: failure on Create join view with sources views/tables +# in different schemas +# +--disable_warnings +CREATE DATABASE test1; +CREATE DATABASE test2; +--enable_warnings + +CREATE TABLE test1.t0 (a VARCHAR(20)); +CREATE TABLE test2.t1 (a VARCHAR(20)); +CREATE VIEW test2.t3 AS SELECT * FROM test1.t0; +CREATE OR REPLACE VIEW test.v1 AS + SELECT ta.a AS col1, tb.a AS col2 FROM test2.t3 ta, test2.t1 tb; + +DROP VIEW test.v1; +DROP VIEW test2.t3; +DROP TABLE test2.t1, test1.t0; +DROP DATABASE test2; +DROP DATABASE test1; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6d39f2f7440..3bb371b6004 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -513,6 +513,8 @@ class THD; void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0); bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables); +bool check_single_table_access(THD *thd, ulong privilege, + TABLE_LIST *tables); bool check_routine_access(THD *thd,ulong want_access,char *db,char *name, bool is_proc, bool no_errors); bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7fe626c8f2d..f01ab4cf74f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4545,7 +4545,7 @@ bool setup_tables_and_check_access(THD *thd, for (; leaves_tmp; leaves_tmp= leaves_tmp->next_leaf) if (leaves_tmp->belong_to_view && - check_one_table_access(thd, want_access, leaves_tmp)) + check_single_table_access(thd, want_access, leaves_tmp)) { tables->hide_view_error(thd); return TRUE; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 37e45e999b3..6ec8bd65a90 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4978,11 +4978,10 @@ error: /* - Check grants for commands which work only with one table and all other - tables belonging to subselects or implicitly opened tables. + Check grants for commands which work only with one table. SYNOPSIS - check_one_table_access() + check_single_table_access() thd Thread handler privilege requested privilege all_tables global table list of query @@ -4992,7 +4991,8 @@ error: 1 - access denied, error is sent to client */ -bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) +bool check_single_table_access(THD *thd, ulong privilege, + TABLE_LIST *all_tables) { Security_context * backup_ctx= thd->security_ctx; @@ -5010,19 +5010,41 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) goto deny; thd->security_ctx= backup_ctx; + return 0; + +deny: + thd->security_ctx= backup_ctx; + return 1; +} + +/* + Check grants for commands which work only with one table and all other + tables belonging to subselects or implicitly opened tables. + + SYNOPSIS + check_one_table_access() + thd Thread handler + privilege requested privilege + all_tables global table list of query + + RETURN + 0 - OK + 1 - access denied, error is sent to client +*/ + +bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) +{ + if (check_single_table_access (thd,privilege,all_tables)) + return 1; /* Check rights on tables of subselects and implictly opened tables */ TABLE_LIST *subselects_tables; if ((subselects_tables= all_tables->next_global)) { if ((check_table_access(thd, SELECT_ACL, subselects_tables, 0))) - goto deny; + return 1; } return 0; - -deny: - thd->security_ctx= backup_ctx; - return 1; } From ea3392fb976298d4e4451daaeab6d064c77df741 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jun 2006 13:01:00 +0300 Subject: [PATCH 13/23] manual merge mysql-test/r/view_grant.result: merged mysql-test/t/view_grant.test: merged --- mysql-test/r/view_grant.result | 29 ++++++++++++++++++++++++++ mysql-test/t/view_grant.test | 38 ++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 11161d0c844..0431957f602 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -618,6 +618,35 @@ ERROR HY000: There is no 'no-such-user'@'localhost' registered DROP VIEW v; DROP TABLE t1; USE test; +CREATE USER mysqltest_db1@localhost identified by 'PWD'; +GRANT ALL ON mysqltest_db1.* TO mysqltest_db1@localhost WITH GRANT OPTION; +CREATE SCHEMA mysqltest_db1 ; +USE mysqltest_db1 ; +CREATE TABLE t1 (f1 INTEGER); +CREATE VIEW view1 AS +SELECT * FROM t1; +SHOW CREATE VIEW view1; +View Create View +view1 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_db1`@`localhost` SQL SECURITY DEFINER VIEW `view1` AS select `t1`.`f1` AS `f1` from `t1` +CREATE VIEW view2 AS +SELECT * FROM view1; +# Here comes a suspicious warning +SHOW CREATE VIEW view2; +View Create View +view2 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_db1`@`localhost` SQL SECURITY DEFINER VIEW `view2` AS select `view1`.`f1` AS `f1` from `view1` +# But the view view2 is usable +SELECT * FROM view2; +f1 +CREATE VIEW view3 AS +SELECT * FROM view2; +SELECT * from view3; +f1 +DROP VIEW mysqltest_db1.view3; +DROP VIEW mysqltest_db1.view2; +DROP VIEW mysqltest_db1.view1; +DROP TABLE mysqltest_db1.t1; +DROP SCHEMA mysqltest_db1; +DROP USER mysqltest_db1@localhost; CREATE DATABASE test1; CREATE DATABASE test2; CREATE TABLE test1.t0 (a VARCHAR(20)); diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 9d23bfa6197..429a2af6bac 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -808,6 +808,44 @@ DROP VIEW v; DROP TABLE t1; USE test; +# +# Bug#20363: Create view on just created view is now denied +# +eval CREATE USER mysqltest_db1@localhost identified by 'PWD'; +eval GRANT ALL ON mysqltest_db1.* TO mysqltest_db1@localhost WITH GRANT OPTION; + +# The session with the non root user is needed. +--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK +connect (session1,localhost,mysqltest_db1,PWD,test); + +CREATE SCHEMA mysqltest_db1 ; +USE mysqltest_db1 ; + +CREATE TABLE t1 (f1 INTEGER); + +CREATE VIEW view1 AS +SELECT * FROM t1; +SHOW CREATE VIEW view1; + +CREATE VIEW view2 AS +SELECT * FROM view1; +--echo # Here comes a suspicious warning +SHOW CREATE VIEW view2; +--echo # But the view view2 is usable +SELECT * FROM view2; + +CREATE VIEW view3 AS +SELECT * FROM view2; + +SELECT * from view3; + +connection default; +DROP VIEW mysqltest_db1.view3; +DROP VIEW mysqltest_db1.view2; +DROP VIEW mysqltest_db1.view1; +DROP TABLE mysqltest_db1.t1; +DROP SCHEMA mysqltest_db1; +DROP USER mysqltest_db1@localhost; # # BUG#20482: failure on Create join view with sources views/tables # in different schemas From dce98ec42d7cc4f3a38773b10f9a320e89221ce1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jun 2006 12:52:59 +0200 Subject: [PATCH 14/23] BUG#20578 Backport Valgrind suppression from mysql-5.1: D 1.4 05/11/23 22:44:54+02:00 monty@mysql.com 5 4 12/0/154 P mysql-test/valgrind.supp C Remove warning that may happens becasue threads dies in different order mysql-test/valgrind.supp: Add suppression for Valgrind warning. --- mysql-test/valgrind.supp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 65c5a82db36..24426727968 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -133,6 +133,18 @@ fun:gzflush } +# +# Warning from my_thread_init becasue mysqld dies before kill thread exists +# + +{ + my_thread_init kill thread memory loss second + Memcheck:Leak + fun:calloc + fun:my_thread_init + fun:kill_server_thread +} + # # Leaks reported in _dl_* internal functions on Linux amd64 / glibc2.3.2. # From 5c0cdea62341da75f0560216af1b363b156ed1ab Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jun 2006 17:30:59 +0500 Subject: [PATCH 15/23] BUG#20357 - Got error 124 from storage engine using MIN and MAX functions in queries Using MAX()/MIN() on table with disabled indexes (by ALTER TABLE) results in error 124 (wrong index) from storage engine. The problem was that optimizer use disabled index to optimize MAX()/MIN(). Normally it must skip disabled index and perform table scan. This patch skips disabled indexes for min/max optimization. mysql-test/r/myisam.result: Test case for BUG#20357. mysql-test/t/myisam.test: Test case for BUG#20357. sql/opt_sum.cc: Skip disabled/ignored indexes for min/max optimization. --- mysql-test/r/myisam.result | 13 +++++++++++++ mysql-test/t/myisam.test | 12 ++++++++++++ sql/opt_sum.cc | 6 ++++++ 3 files changed, 31 insertions(+) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 3b4519e5444..91a5bb08c0f 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -748,3 +748,16 @@ select count(id1) from t1 where id2 = 10; count(id1) 5 drop table t1; +CREATE TABLE t1(a TINYINT, KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 VALUES(1); +SELECT MAX(a) FROM t1 IGNORE INDEX(a); +MAX(a) +1 +ALTER TABLE t1 DISABLE KEYS; +SELECT MAX(a) FROM t1; +MAX(a) +1 +SELECT MAX(a) FROM t1 IGNORE INDEX(a); +MAX(a) +1 +DROP TABLE t1; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 7e4cc324b12..06f913111d3 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -705,4 +705,16 @@ select count(*) from t1 where id2 = 10; select count(id1) from t1 where id2 = 10; drop table t1; +# +# BUG##20357 - Got error 124 from storage engine using MIN and MAX functions +# in queries +# +CREATE TABLE t1(a TINYINT, KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 VALUES(1); +SELECT MAX(a) FROM t1 IGNORE INDEX(a); +ALTER TABLE t1 DISABLE KEYS; +SELECT MAX(a) FROM t1; +SELECT MAX(a) FROM t1 IGNORE INDEX(a); +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index cfb5b3695a3..63373a8579a 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -673,6 +673,12 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref, { KEY_PART_INFO *part,*part_end; key_part_map key_part_to_use= 0; + /* + Perform a check if index is not disabled by ALTER TABLE + or IGNORE INDEX. + */ + if (!table->keys_in_use_for_query.is_set(idx)) + continue; uint jdx= 0; *prefix_len= 0; for (part= keyinfo->key_part, part_end= part+keyinfo->key_parts ; From fa83f8baa094ed45330afa0e2516eeb31e803b27 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jun 2006 16:41:07 +0200 Subject: [PATCH 16/23] added missing MYSQLTEST_VARDIR declaration --- mysql-test/mysql-test-run.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index fb3484c212e..93f741aecff 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -171,7 +171,8 @@ BASEDIR=`pwd` cd $CWD MYSQL_TEST_DIR=$BASEDIR/mysql-test MYSQL_TEST_WINDIR=$MYSQL_TEST_DIR -export MYSQL_TEST_DIR MYSQL_TEST_WINDIR +MYSQLTEST_VARDIR=$MYSQL_TEST_DIR/var +export MYSQL_TEST_DIR MYSQL_TEST_WINDIR MYSQLTEST_VARDIR STD_DATA=$MYSQL_TEST_DIR/std_data hostname=`hostname` # Installed in the mysql privilege table From e8e52a6a2557f3a6e6e3d50841eb545c9cf8d0cc Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jun 2006 18:35:19 +0300 Subject: [PATCH 17/23] Cleanup to patch for Bug#18246, "compilation error with tcp_wrapper" include/my_libwrap.h: Changed includes to the header file. mysys/my_libwrap.c: Added comment and .c file now takes needed includes from the corresponding .h file. sql/mysqld.cc: Include this block from my_libwra.h now. Moved two variables out of the otherwise same block. --- include/my_libwrap.h | 9 +++++++++ mysys/my_libwrap.c | 15 +++++++++------ sql/mysqld.cc | 13 +++---------- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/include/my_libwrap.h b/include/my_libwrap.h index a5cc9879e4f..6437cbaed84 100644 --- a/include/my_libwrap.h +++ b/include/my_libwrap.h @@ -14,6 +14,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifdef HAVE_LIBWRAP +#include +#include +#ifdef NEED_SYS_SYSLOG_H +#include +#endif /* NEED_SYS_SYSLOG_H */ + extern void my_fromhost(struct request_info *req); extern int my_hosts_access(struct request_info *req); extern char *my_eval_client(struct request_info *req); + +#endif /* HAVE_LIBWRAP */ diff --git a/mysys/my_libwrap.c b/mysys/my_libwrap.c index 29a0ecf3fc6..be8adbab0a1 100644 --- a/mysys/my_libwrap.c +++ b/mysys/my_libwrap.c @@ -14,14 +14,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* + This is needed to be able to compile with original libwrap header + files that don't have the prototypes +*/ + #include +#include + #ifdef HAVE_LIBWRAP -#include -#include -#ifdef NEED_SYS_SYSLOG_H -#include -#endif /* NEED_SYS_SYSLOG_H */ -#endif void my_fromhost(struct request_info *req) { @@ -37,3 +38,5 @@ char *my_eval_client(struct request_info *req) { eval_client(req); } + +#endif /* HAVE_LIBWRAP */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 262a5352ed9..b73cd350012 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -120,16 +120,7 @@ extern "C" { // Because of SCO 3.2V4.2 #include #endif /* __WIN__ */ -#ifdef HAVE_LIBWRAP -#include -#include -#ifdef NEED_SYS_SYSLOG_H -#include -#endif /* NEED_SYS_SYSLOG_H */ -int allow_severity = LOG_INFO; -int deny_severity = LOG_WARNING; - -#endif /* HAVE_LIBWRAP */ +#include #ifdef HAVE_SYS_MMAN_H #include @@ -591,6 +582,8 @@ static const char* default_dbug_option; #endif #ifdef HAVE_LIBWRAP const char *libwrapName= NULL; +int allow_severity = LOG_INFO; +int deny_severity = LOG_WARNING; #endif #ifdef HAVE_QUERY_CACHE static ulong query_cache_limit= 0; From 822e8866c7009d8d7bd25300f1cc4c09c110c640 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Jun 2006 00:29:04 +0400 Subject: [PATCH 18/23] Fixed bug #14896. This bug in Field_string::cmp resulted in a wrong comparison with keys in partial indexes over multi-byte character fields. Given field a is declared as a varchar(16) collate utf8_unicode_ci INDEX(a(4)) gives us an example of such an index. Wrong key comparisons could lead to wrong result sets if the selected query execution plan used a range scan by a partial index over a utf8 character field. This also caused wrong results in many other cases. mysql-test/t/ctype_utf8.test: Added test cases for bug #14896. mysql-test/r/ctype_utf8.result: Added test cases for bug #14896. sql/field.cc: Fixed bug #14896. This bug in Field_string::cmp resulted in a wrong comparison with keys in partial indexes over multi-byte character fields. Given field a is declared as a varchar(16) collate utf8_unicode_ci INDEX(a(4)) gives us an example of such an index. Wrong key comparisons could lead to wrong result sets if the selected query execution plan used a range scan by a partial index over a utf8 character field. This also caused wrong results in many other cases. --- mysql-test/r/ctype_utf8.result | 40 ++++++++++++++++++++++++++++++++++ mysql-test/t/ctype_utf8.test | 26 ++++++++++++++++++++++ sql/field.cc | 20 ++++++----------- 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 69d7577ee77..cc271176dfc 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1124,3 +1124,43 @@ check table t1; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; +SET NAMES utf8; +CREATE TABLE t1 (id int PRIMARY KEY, +a varchar(16) collate utf8_unicode_ci NOT NULL default '', +b int, +f varchar(128) default 'XXX', +INDEX (a(4)) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +INSERT INTO t1(id, a, b) VALUES +(1, 'cccc', 50), (2, 'cccc', 70), (3, 'cccc', 30), +(4, 'cccc', 30), (5, 'cccc', 20), (6, 'bbbbbb', 40), +(7, 'dddd', 30), (8, 'aaaa', 10), (9, 'aaaa', 50), +(10, 'eeeee', 40), (11, 'bbbbbb', 60); +SELECT id, a, b FROM t1; +id a b +1 cccc 50 +2 cccc 70 +3 cccc 30 +4 cccc 30 +5 cccc 20 +6 bbbbbb 40 +7 dddd 30 +8 aaaa 10 +9 aaaa 50 +10 eeeee 40 +11 bbbbbb 60 +SELECT id, a, b FROM t1 WHERE a BETWEEN 'aaaa' AND 'bbbbbb'; +id a b +8 aaaa 10 +9 aaaa 50 +6 bbbbbb 40 +11 bbbbbb 60 +SELECT id, a FROM t1 WHERE a='bbbbbb'; +id a +6 bbbbbb +11 bbbbbb +SELECT id, a FROM t1 WHERE a='bbbbbb' ORDER BY b; +id a +6 bbbbbb +11 bbbbbb +DROP TABLE t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 5044f7979f1..9b8e6590999 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -926,4 +926,30 @@ INSERT INTO t1 VALUES('uUABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbb check table t1; drop table t1; +# +# Bug#14896: Comparison with a key in a partial index over mb chararacter field +# + +SET NAMES utf8; +CREATE TABLE t1 (id int PRIMARY KEY, + a varchar(16) collate utf8_unicode_ci NOT NULL default '', + b int, + f varchar(128) default 'XXX', + INDEX (a(4)) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +INSERT INTO t1(id, a, b) VALUES + (1, 'cccc', 50), (2, 'cccc', 70), (3, 'cccc', 30), + (4, 'cccc', 30), (5, 'cccc', 20), (6, 'bbbbbb', 40), + (7, 'dddd', 30), (8, 'aaaa', 10), (9, 'aaaa', 50), + (10, 'eeeee', 40), (11, 'bbbbbb', 60); + +SELECT id, a, b FROM t1; + +SELECT id, a, b FROM t1 WHERE a BETWEEN 'aaaa' AND 'bbbbbb'; + +SELECT id, a FROM t1 WHERE a='bbbbbb'; +SELECT id, a FROM t1 WHERE a='bbbbbb' ORDER BY b; + +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/field.cc b/sql/field.cc index ec4d4b4e4f5..3cb0c0d3a7c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5072,17 +5072,6 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr) { uint a_len, b_len; - if (field_charset->strxfrm_multiply > 1) - { - /* - We have to remove end space to be able to compare multi-byte-characters - like in latin_de 'ae' and 0xe4 - */ - return field_charset->coll->strnncollsp(field_charset, - (const uchar*) a_ptr, field_length, - (const uchar*) b_ptr, - field_length); - } if (field_charset->mbmaxlen != 1) { uint char_len= field_length/field_charset->mbmaxlen; @@ -5091,8 +5080,13 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr) } else a_len= b_len= field_length; - return my_strnncoll(field_charset,(const uchar*) a_ptr, a_len, - (const uchar*) b_ptr, b_len); + /* + We have to remove end space to be able to compare multi-byte-characters + like in latin_de 'ae' and 0xe4 + */ + return field_charset->coll->strnncollsp(field_charset, + (const uchar*) a_ptr, a_len, + (const uchar*) b_ptr, b_len); } From 15ac64063197f00a7343fb99613554788cca10b0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Jun 2006 19:15:03 +0400 Subject: [PATCH 19/23] Bug#15811: extremely long time for mysql client to execute long INSERT The problem was in redundant calls to strlen() in string functions, where we may then return after checking only the small number of characters. No test case is provided since it's a performance fix. strings/ctype-mb.c: Do not use strlen() where arbitrary horizon of at least CHARSET_INFO::mbmaxlen character is sufficient. --- strings/ctype-mb.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index a3e10ba7650..0d73c7d1e51 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -24,12 +24,12 @@ void my_caseup_str_mb(CHARSET_INFO * cs, char *str) { register uint32 l; - register char *end=str+strlen(str); /* BAR TODO: remove strlen() call */ register uchar *map=cs->to_upper; while (*str) { - if ((l=my_ismbchar(cs, str,end))) + /* Pointing after the '\0' is safe here. */ + if ((l=my_ismbchar(cs, str, str + cs->mbmaxlen))) str+=l; else { @@ -42,12 +42,12 @@ void my_caseup_str_mb(CHARSET_INFO * cs, char *str) void my_casedn_str_mb(CHARSET_INFO * cs, char *str) { register uint32 l; - register char *end=str+strlen(str); register uchar *map=cs->to_lower; while (*str) { - if ((l=my_ismbchar(cs, str,end))) + /* Pointing after the '\0' is safe here. */ + if ((l=my_ismbchar(cs, str, str + cs->mbmaxlen))) str+=l; else { @@ -101,15 +101,18 @@ uint my_casedn_mb(CHARSET_INFO * cs, char *src, uint srclen, return srclen; } +/* + my_strcasecmp_mb() returns 0 if strings are equal, non-zero otherwise. + */ int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t) { register uint32 l; - register const char *end=s+strlen(s); register uchar *map=cs->to_upper; - while (smbmaxlen))) { while (l--) if (*s++ != *t++) @@ -120,7 +123,8 @@ int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t) else if (map[(uchar) *s++] != map[(uchar) *t++]) return 1; } - return *t; + /* At least one of '*s' and '*t' is zero here. */ + return (*t != *s); } From 67fd3c4a53f585f8e33b5094822cf639a27483de Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Jun 2006 19:29:48 +0400 Subject: [PATCH 20/23] A fix and a test case for Bug#15217 "Using a SP cursor on a table created with PREPARE fails with weird error". More generally, re-executing a stored procedure with a complex SP cursor query could lead to a crash. The cause of the problem was that SP cursor queries were not optimized properly at first execution: their parse tree belongs to sp_instr_cpush, not sp_instr_copen, and thus the tree was tagged "EXECUTED" when the cursor was declared, not when it was opened. This led to loss of optimization transformations performed at first execution, as sp_instr_copen saw that the query is already "EXECUTED" and therefore either not ran first-execution related blocks or wrongly rolled back the transformations caused by first-execution code. The fix is to update the state of the parsed tree only when the tree is executed, as opposed to when the instruction containing the tree is executed. Assignment if i->state is moved to reset_lex_and_exec_core. mysql-test/r/sp.result: Test results fixed (Bug#15217) mysql-test/t/sp.test: Add a test case for Bug#15217 sql/sp_head.cc: Move assignment of stmt_arena->state to reset_lex_and_exec_core --- mysql-test/r/sp.result | 21 +++++++++++++++++++++ mysql-test/t/sp.test | 27 +++++++++++++++++++++++++++ sql/sp_head.cc | 4 +++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index ff378f1f43b..d3874c769fa 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4990,4 +4990,25 @@ CALL bug18037_p2()| DROP FUNCTION bug18037_f1| DROP PROCEDURE bug18037_p1| DROP PROCEDURE bug18037_p2| +drop table if exists t3| +drop procedure if exists bug15217| +create table t3 as select 1| +create procedure bug15217() +begin +declare var1 char(255); +declare cur1 cursor for select * from t3; +open cur1; +fetch cur1 into var1; +select concat('data was: /', var1, '/'); +close cur1; +end | +call bug15217()| +concat('data was: /', var1, '/') +data was: /1/ +flush tables | +call bug15217()| +concat('data was: /', var1, '/') +data was: /1/ +drop table t3| +drop procedure bug15217| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 1d21a5da187..66498198157 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -5888,6 +5888,33 @@ DROP FUNCTION bug18037_f1| DROP PROCEDURE bug18037_p1| DROP PROCEDURE bug18037_p2| +# +# Bug#15217 "Using a SP cursor on a table created with PREPARE fails with +# weird error". Check that the code that is supposed to work at +# the first execution of a stored procedure actually works for +# sp_instr_copen. + +--disable_warnings +drop table if exists t3| +drop procedure if exists bug15217| +--enable_warnings +create table t3 as select 1| +create procedure bug15217() +begin + declare var1 char(255); + declare cur1 cursor for select * from t3; + open cur1; + fetch cur1 into var1; + select concat('data was: /', var1, '/'); + close cur1; +end | +# Returns expected result +call bug15217()| +flush tables | +# Returns error with garbage as column name +call bug15217()| +drop table t3| +drop procedure bug15217| # # BUG#NNNN: New bug synopsis diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 3b29a841966..ef2f895c8b2 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1075,7 +1075,6 @@ sp_head::execute(THD *thd) thd->net.no_send_error= 0; if (i->free_list) cleanup_items(i->free_list); - i->state= Query_arena::EXECUTED; /* If we've set thd->user_var_events_alloc to mem_root of this SP @@ -2210,6 +2209,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, m_lex->mark_as_requiring_prelocking(NULL); } thd->rollback_item_tree_changes(); + /* Update the state of the active arena. */ + thd->stmt_arena->state= Query_arena::EXECUTED; + /* Unlike for PS we should not call Item's destructors for newly created From 92ad3d5bd7fbfc64b083824f28470eebca5cd199 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Jun 2006 00:37:31 +0200 Subject: [PATCH 21/23] mysql.spec.sh: Disable the simplistic auto dependency scan for test/bench (bug#20078) support-files/mysql.spec.sh: Disable the simplistic auto dependency scan for test/bench (bug#20078) --- support-files/mysql.spec.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 9656851dc9c..854ad2e7ce7 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -148,6 +148,7 @@ Summary: MySQL - Benchmarks and test system Group: Applications/Databases Provides: mysql-bench Obsoletes: mysql-bench +AutoReqProv: no %description bench This package contains MySQL benchmark scripts and data. From 89e415950cf3b40b15e493cb72784f6ad3dc2b64 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Jun 2006 13:19:30 +0500 Subject: [PATCH 22/23] Bug#11228: DESC shows arbitrary column as "PRI" An UNIQUE KEY consisting of NOT NULL columns was displayed as PRIMARY KEY in "DESC t1". According to the code, that was intentional behaviour for some reasons unknown to me. This code was written before bitkeeper time, so I cannot check who and why made this. After discussing on dev-public, a decision was made to remove this code mysql-test/r/key.result: Adding test case. mysql-test/t/key.test: Adding test case. sql/table.cc: Removing old wrong code --- mysql-test/r/key.result | 10 ++++++++++ mysql-test/t/key.test | 11 +++++++++++ sql/table.cc | 21 --------------------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index f0a7afa239f..0bc241c0d19 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -326,6 +326,16 @@ alter table t1 add key (c1,c1,c2); ERROR 42S21: Duplicate column name 'c1' drop table t1; create table t1 ( +i1 INT NOT NULL, +i2 INT NOT NULL, +UNIQUE i1idx (i1), +UNIQUE i2idx (i2)); +desc t1; +Field Type Null Key Default Extra +i1 int(11) UNI 0 +i2 int(11) UNI 0 +drop table t1; +create table t1 ( c1 int, c2 varchar(20) not null, primary key (c1), diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index 85728582c75..796e36cb608 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -321,6 +321,17 @@ alter table t1 add key (c1,c2,c1); alter table t1 add key (c1,c1,c2); drop table t1; +# +# Bug#11228: DESC shows arbitrary column as "PRI" +# +create table t1 ( + i1 INT NOT NULL, + i2 INT NOT NULL, + UNIQUE i1idx (i1), + UNIQUE i2idx (i2)); +desc t1; +drop table t1; + # # Bug#12565 - ERROR 1034 when running simple UPDATE or DELETE # on large MyISAM table diff --git a/sql/table.cc b/sql/table.cc index 8ac64ac198d..513f42665a6 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -567,27 +567,6 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, if (outparam->key_info[key].flags & HA_FULLTEXT) outparam->key_info[key].algorithm= HA_KEY_ALG_FULLTEXT; - if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME)) - { - /* - If the UNIQUE key doesn't have NULL columns and is not a part key - declare this as a primary key. - */ - primary_key=key; - for (i=0 ; i < keyinfo->key_parts ;i++) - { - uint fieldnr= key_part[i].fieldnr; - if (!fieldnr || - outparam->field[fieldnr-1]->null_ptr || - outparam->field[fieldnr-1]->key_length() != - key_part[i].length) - { - primary_key=MAX_KEY; // Can't be used - break; - } - } - } - for (i=0 ; i < keyinfo->key_parts ; key_part++,i++) { if (new_field_pack_flag <= 1) From 907acc785da95878f0ff7eb6a5b88b5b18e713a8 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Jun 2006 19:36:54 +0400 Subject: [PATCH 23/23] key.result: After merge fix mysql-test/r/key.result: After merge fix --- mysql-test/r/key.result | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index 6c05a3dde8b..a6f05143b3e 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -336,8 +336,8 @@ UNIQUE i1idx (i1), UNIQUE i2idx (i2)); desc t1; Field Type Null Key Default Extra -i1 int(11) UNI 0 -i2 int(11) UNI 0 +i1 int(11) NO UNI +i2 int(11) NO UNI drop table t1; create table t1 ( c1 int,