From 3f4d396dc33a68252f8db838d14192186f4ce342 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Dec 2003 12:32:02 +0200 Subject: [PATCH 01/36] Fixed bug in table level privilege GRANT handling. (Bug #2178) Portability fixes mysql-test/r/rpl_until.result: Portability fix mysql-test/t/rpl_until.test: Portability fix sql/slave.cc: Write UNTIL position to logs (for debugging) sql/slave.h: Write UNTIL position to logs (for debugging) sql/sql_acl.cc: Fixed bug in table level privilege GRANT handling. (Bug #2178) --- mysql-test/r/rpl_until.result | 2 +- mysql-test/t/rpl_until.test | 6 +++--- sql/slave.cc | 2 +- sql/slave.h | 5 +++++ sql/sql_acl.cc | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result index c179351551d..82b1ed233ec 100644 --- a/mysql-test/r/rpl_until.result +++ b/mysql-test/r/rpl_until.result @@ -31,7 +31,7 @@ n 4 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 332 master-bin.000001 Yes No 0 0 244 649 Master master-bin.000001 244 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 # master-bin.000001 Yes No 0 0 244 # Master master-bin.000001 244 No # start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; select * from t1; n diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index 9bc4ea4e7b1..4508fbea194 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -29,7 +29,7 @@ sleep 2; # here table should be still not deleted select * from t1; --replace_result $MASTER_MYPORT MASTER_MYPORT ---replace_column 1 # 33 # +--replace_column 1 # 9 # 23 # 33 # show slave status; # this should fail right after start @@ -59,9 +59,9 @@ stop slave; # this should stop immideately start slave until master_log_file='master-bin.000001', master_log_pos=561; -sleep 2; +--real-sleep 2; # here the sql slave thread should be stopped ---replace_result $MASTER_MYPORT MASTER_MYPORT +--replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004 --replace_column 1 # 9 # 23 # 33 # show slave status; diff --git a/sql/slave.cc b/sql/slave.cc index d2a7d397fa7..36d8975a127 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2682,7 +2682,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) rli->is_until_satisfied()) { sql_print_error("Slave SQL thread stopped because it reached its" - " UNTIL position"); + " UNTIL position %ld", (long) rli->until_pos()); /* Setting abort_slave flag because we do not want additional message about error in query execution to be printed. diff --git a/sql/slave.h b/sql/slave.h index e42b93a47ef..d92c44dd2ba 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -324,6 +324,11 @@ typedef struct st_relay_log_info /* Check if UNTIL condition is satisfied. See slave.cc for more. */ bool is_until_satisfied(); + inline ulonglong until_pos() + { + return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos : + group_relay_log_pos); + } } RELAY_LOG_INFO; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 01820917ce9..3f70cc1323b 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2543,7 +2543,7 @@ my_bool grant_init(THD *org_thd) do { GRANT_TABLE *mem_check; - if (!(mem_check=new GRANT_TABLE(t_table,c_table)) || mem_check->ok()) + if (!(mem_check=new GRANT_TABLE(t_table,c_table)) || !mem_check->ok()) { /* This could only happen if we are out memory */ grant_option= FALSE; /* purecov: deadcode */ From 43abc597b8854c44465a8a936febe780f223628c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Jan 2004 23:51:17 +0100 Subject: [PATCH 02/36] Code cleanup Fixed bug in optimizer where it didn't choose right table order in some cases myisam/mi_delete.c: Remove not needed include errno.h myisam/mi_delete_table.c: Remove not needed include errno.h myisam/mi_extra.c: Remove not needed include errno.h myisam/mi_locking.c: Remove not needed include errno.h myisam/mi_log.c: Remove not needed include errno.h myisam/mi_page.c: Remove not needed include errno.h myisam/mi_rename.c: Remove not needed include errno.h myisam/mi_update.c: Remove not needed include errno.h myisam/mi_write.c: Remove not needed include errno.h mysql-test/r/subselect.result: Update of test after optimzier fix mysys/charset.c: Code cleanup sql/item_cmpfunc.cc: Removed not needed comment Indentation cleanup sql/item_cmpfunc.h: Indentation cleanup sql/mysqld.cc: Updated comment for expire_logs_days sql/set_var.cc: Remved duplicate code sql/sql_select.cc: Fixed bug in optimizer where it didn't choose right table order in some cases (Bug found and fixed by Igor) --- myisam/mi_delete.c | 4 ---- myisam/mi_delete_table.c | 3 --- myisam/mi_extra.c | 3 --- myisam/mi_locking.c | 3 --- myisam/mi_log.c | 1 - myisam/mi_page.c | 3 --- myisam/mi_rename.c | 3 --- myisam/mi_update.c | 5 ----- myisam/mi_write.c | 4 ---- mysql-test/r/subselect.result | 4 ++-- mysys/charset.c | 13 +++++++------ sql/item_cmpfunc.cc | 15 ++++----------- sql/item_cmpfunc.h | 6 +++--- sql/mysqld.cc | 2 +- sql/set_var.cc | 10 ---------- sql/sql_select.cc | 21 +++++++++++++++++---- 16 files changed, 34 insertions(+), 66 deletions(-) diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index a55d5b2a5ca..19cfc050ea1 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -20,10 +20,6 @@ #include "rt_index.h" #include -#ifdef __WIN__ -#include -#endif - static int d_search(MI_INFO *info,MI_KEYDEF *keyinfo,uint comp_flag, uchar *key,uint key_length,my_off_t page,uchar *anc_buff); static int del(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,uchar *anc_buff, diff --git a/myisam/mi_delete_table.c b/myisam/mi_delete_table.c index 6d842d7e6a4..6843881568d 100644 --- a/myisam/mi_delete_table.c +++ b/myisam/mi_delete_table.c @@ -19,9 +19,6 @@ */ #include "fulltext.h" -#ifdef __WIN__ -#include -#endif int mi_delete_table(const char *name) { diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c index 10f52f1e39a..ce072d7d57e 100644 --- a/myisam/mi_extra.c +++ b/myisam/mi_extra.c @@ -18,9 +18,6 @@ #ifdef HAVE_MMAP #include #endif -#ifdef __WIN__ -#include -#endif /* Set options and buffers to optimize table handling diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index 67ccca52d08..816748d459a 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -22,9 +22,6 @@ */ #include "myisamdef.h" -#ifdef __WIN__ -#include -#endif /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */ diff --git a/myisam/mi_log.c b/myisam/mi_log.c index 1dcfd5250d2..13842c56828 100644 --- a/myisam/mi_log.c +++ b/myisam/mi_log.c @@ -21,7 +21,6 @@ #include "myisamdef.h" #if defined(MSDOS) || defined(__WIN__) -#include #include #ifndef __WIN__ #include diff --git a/myisam/mi_page.c b/myisam/mi_page.c index c70209c2da6..16713c87e10 100644 --- a/myisam/mi_page.c +++ b/myisam/mi_page.c @@ -17,9 +17,6 @@ /* Read and write key blocks */ #include "myisamdef.h" -#ifdef __WIN__ -#include -#endif /* Fetch a key-page in memory */ diff --git a/myisam/mi_rename.c b/myisam/mi_rename.c index db44b8fe28f..8380ee1bfad 100644 --- a/myisam/mi_rename.c +++ b/myisam/mi_rename.c @@ -19,9 +19,6 @@ */ #include "fulltext.h" -#ifdef __WIN__ -#include -#endif int mi_rename(const char *old_name, const char *new_name) { diff --git a/myisam/mi_update.c b/myisam/mi_update.c index d1d41ac351a..f62be133ed9 100644 --- a/myisam/mi_update.c +++ b/myisam/mi_update.c @@ -19,11 +19,6 @@ #include "fulltext.h" #include "rt_index.h" -#ifdef __WIN__ -#include -#endif - - int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec) { int flag,key_changed,save_errno; diff --git a/myisam/mi_write.c b/myisam/mi_write.c index d13ba6c2c4e..4b7a22dac84 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -20,10 +20,6 @@ #include "rt_index.h" #include -#ifdef __WIN__ -#include -#endif - #define MAX_POINTER_LENGTH 8 /* Functions declared in this file */ diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 672a39299dd..edc8e56f442 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1340,8 +1340,8 @@ a explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index -2 DEPENDENT SUBQUERY t3 index a a 5 NULL 3 Using index -2 DEPENDENT SUBQUERY t1 ref a a 10 func,test.t3.a 1000 Using where; Using index +2 DEPENDENT SUBQUERY t1 ref a a 5 func 1001 Using where; Using index +2 DEPENDENT SUBQUERY t3 index a a 5 NULL 3 Using where; Using index Warnings: Note 1003 select high_priority test.t2.a AS `a` from test.t2 where (test.t2.a,(select 1 AS `Not_used` from test.t1 join test.t3 where ((test.t1.b = test.t3.a) and ((test.t2.a) = test.t1.a)) limit 1)) insert into t1 values (3,31); diff --git a/mysys/charset.c b/mysys/charset.c index f8c8237c88b..fec0778213f 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -533,14 +533,15 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) */ pthread_mutex_lock(&THR_LOCK_charset); - cs= all_charsets[cs_number]; - - if (cs && !(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED)) + if ((cs= all_charsets[cs_number])) { - strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS); - my_read_charset_file(buf,flags); + if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED)) + { + strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS); + my_read_charset_file(buf,flags); + } + cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL; } - cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL; pthread_mutex_unlock(&THR_LOCK_charset); return cs; } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a79ef21e97a..5b27091321c 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1658,26 +1658,19 @@ Item_cond::Item_cond(THD *thd, Item_cond &item) and_tables_cache(item.and_tables_cache) { /* - here should be following text: - - List_iterator_fast li(item.list); - while(Item *it= li++) - list.push_back(it); - - but it do not need, - because this constructor used only for AND/OR and - argument list will be copied by copy_andor_arguments call + item->list will be copied by copy_andor_arguments() call */ - } + void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item) { List_iterator_fast li(item->list); - while(Item *it= li++) + while (Item *it= li++) list.push_back(it->copy_andor_structure(thd)); } + bool Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 541bc47557d..f5cd608ebad 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -919,8 +919,8 @@ public: Item* copy_andor_structure(THD *thd) { Item_cond_and *item; - if((item= new Item_cond_and(thd, *this))) - item->copy_andor_arguments(thd, this); + if ((item= new Item_cond_and(thd, *this))) + item->copy_andor_arguments(thd, this); return item; } Item *neg_transformer(); @@ -940,7 +940,7 @@ public: Item* copy_andor_structure(THD *thd) { Item_cond_or *item; - if((item= new Item_cond_or(thd, *this))) + if ((item= new Item_cond_or(thd, *this))) item->copy_andor_arguments(thd, this); return item; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e81113f6111..6387e99ca05 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4619,7 +4619,7 @@ The minimum value for this variable is 4096.", (gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, {"expire_logs_days", OPT_EXPIRE_LOGS_DAYS, - "Logs will be rotated after expire-log-days days ", + "Binary logs will be rotated after expire-log-days days ", (gptr*) &expire_logs_days, (gptr*) &expire_logs_days, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 99, 0, 1, 0}, diff --git a/sql/set_var.cc b/sql/set_var.cc index c8b11eb0f58..ecb85440068 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2629,11 +2629,6 @@ ulong fix_sql_mode(ulong sql_mode) MODE_IGNORE_SPACE | MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS); - if (sql_mode & MODE_MSSQL) - sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | - MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | - MODE_NO_FIELD_OPTIONS); if (sql_mode & MODE_POSTGRESQL) sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | @@ -2644,11 +2639,6 @@ ulong fix_sql_mode(ulong sql_mode) MODE_IGNORE_SPACE | MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS); - if (sql_mode & MODE_DB2) - sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | - MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | - MODE_NO_FIELD_OPTIONS); if (sql_mode & MODE_MAXDB) sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a1f6abfd53a..92cdd12ad37 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2688,22 +2688,35 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, do { uint keypart=keyuse->keypart; - uint found_part_ref_or_null= KEY_OPTIMIZE_REF_OR_NULL; + table_map best_part_found_ref= 0; + double best_prev_record_reads= DBL_MAX; do { if (!(rest_tables & keyuse->used_tables) && !(found_ref_or_null & keyuse->optimize)) { found_part|=keyuse->keypart_map; - found_ref|= keyuse->used_tables; + double tmp= prev_record_reads(join, + (found_ref | + keyuse->used_tables)); + if (tmp < best_prev_record_reads) + { + best_part_found_ref= keyuse->used_tables; + best_prev_record_reads= tmp; + } if (rec > keyuse->ref_table_rows) rec= keyuse->ref_table_rows; - found_part_ref_or_null&= keyuse->optimize; + /* + If there is one 'key_column IS NULL' expression, we can + use this ref_or_null optimsation of this field + */ + found_ref_or_null|= (keyuse->optimize & + KEY_OPTIMIZE_REF_OR_NULL); } keyuse++; - found_ref_or_null|= found_part_ref_or_null; } while (keyuse->table == table && keyuse->key == key && keyuse->keypart == keypart); + found_ref|= best_part_found_ref; } while (keyuse->table == table && keyuse->key == key); /* From 68c0a299876b01dbf72cd948708afef4a2c27b47 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 1 Feb 2004 15:30:32 +0200 Subject: [PATCH 03/36] now all tables of query are locked in one place (including derived tables) fixed BUG#2120 and other problem with EXPLAINing derived tables mysql-test/r/derived.result: correct tables names & Co in derived tables test case for BUG#2120 mysql-test/t/derived.test: test case for BUG#2120 sql/mysql_priv.h: derived tables processing moved after open/locking all tables (in open_and_lock_tables) sql/repl_failsafe.cc: correct initialization of TABLE_LIST sql/sql_acl.cc: used simple table opening without derived table processing to avoid unneeded initialization of SELECT_LEX sql/sql_base.cc: derived tables processing moved after open/locking all tables (in open_and_lock_tables) sql/sql_delete.cc: all tables processing is done during opening sql/sql_derived.cc: derived tables processing moved after open/locking all tables (in open_and_lock_tables) to sutisfy "all query tables locking" at the moment sql/sql_insert.cc: all tables processing is done during opening correct initialization of TABLE_LIST sql/sql_lex.cc: now table list will be created for whole query layout fix correct check of updated table in subqueries sql/sql_lex.h: now table list will be created for whole query correct check of updated table in subqueries sql/sql_olap.cc: THIS FUNCTION IS USED NOWHERE it will be good to remove it at all (handle_olaps) sql/sql_parse.cc: derived tables processing moved after open/locking all tables (in open_and_lock_tables) sql/sql_prepare.cc: new creating list parameters all tables processing is done during opening sql/sql_select.cc: all tables processing is done during opening sql/sql_select.h: now it used only within file where is defined sql/sql_udf.cc: used simple table opening without derived table processing to avoid unneeded initialization of SELECT_LEX sql/sql_update.cc: all tables processing is done during opening --- mysql-test/r/derived.result | 23 +++- mysql-test/t/derived.test | 9 ++ sql/mysql_priv.h | 4 +- sql/repl_failsafe.cc | 2 +- sql/sql_acl.cc | 10 +- sql/sql_base.cc | 69 ++++++++-- sql/sql_delete.cc | 1 - sql/sql_derived.cc | 247 +++++++++++++++++------------------- sql/sql_insert.cc | 4 +- sql/sql_lex.cc | 86 +++++++++++-- sql/sql_lex.h | 9 +- sql/sql_olap.cc | 12 -- sql/sql_parse.cc | 74 ++++------- sql/sql_prepare.cc | 3 +- sql/sql_select.cc | 1 - sql/sql_select.h | 1 - sql/sql_udf.cc | 2 +- sql/sql_update.cc | 2 - 18 files changed, 311 insertions(+), 248 deletions(-) diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 170c393524b..a89494645fa 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -59,7 +59,7 @@ explain select * from t1 as x1, (select * from t1) as x2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY x1 ALL NULL NULL NULL NULL 4 1 PRIMARY ALL NULL NULL NULL NULL 4 -2 DERIVED x1 ALL NULL NULL NULL NULL 4 +2 DERIVED t1 ALL NULL NULL NULL NULL 4 drop table if exists t2,t3; select * from (select 1) as a; 1 @@ -141,7 +141,7 @@ a t explain select count(*) from t1 as tt1, (select * from t1) as tt2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -2 DERIVED tt1 ALL NULL NULL NULL NULL 10000 +2 DERIVED t1 index NULL a 4 NULL 10000 Using index drop table t1; SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b; (SELECT * FROM (SELECT 1 as a) as a ) @@ -189,13 +189,13 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY m2 ALL NULL NULL NULL NULL 9 1 PRIMARY ALL NULL NULL NULL NULL 6 Using where 2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort -2 DERIVED m2 index NULL PRIMARY 3 NULL 9 Using index +2 DERIVED m1 index NULL PRIMARY 3 NULL 9 Using index explain SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY m2 ALL NULL NULL NULL NULL 9 1 PRIMARY ALL NULL NULL NULL NULL 6 Using where 2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort -2 DERIVED m2 index NULL PRIMARY 3 NULL 9 Using index +2 DERIVED m1 index NULL PRIMARY 3 NULL 9 Using index drop table t1,t2; SELECT a.x FROM (SELECT 1 AS x) AS a HAVING a.x = 1; x @@ -229,8 +229,8 @@ explain select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 2 1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 THEMAX.E2 1 Using where -2 DERIVED t1 ALL NULL NULL NULL NULL 2 Using where -3 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 2 Using where +2 DERIVED A index NULL PRIMARY 4 NULL 2 Using where; Using index +3 DEPENDENT SUBQUERY B index NULL PRIMARY 4 NULL 2 Using where; Using index drop table t1; create table t1 (a int); insert into t1 values (1),(2); @@ -298,3 +298,14 @@ INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00 select 497, TMP.ID, NULL from (select 497 as ID, MAX(t3.DATA) as DATA from t1 join t2 on (t1.ObjectID = t2.ID) join t3 on (t1.ObjectID = t3.ID) group by t2.ParID order by DATA DESC) as TMP; 497 ID NULL drop table t1, t2, t3; +CREATE TABLE t1 (name char(1) default NULL, val int(5) default NULL); +INSERT INTO t1 VALUES ('a',1), ('a',2), ('a',2), ('a',2), ('a',3), ('a',6), ('a',7), ('a',11), ('a',11), ('a',12), ('a',13), ('a',13), ('a',20), ('b',2), ('b',3), ('b',4), ('b',5); +SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name; +name median +a 7.0000 +b 3.5000 +explain SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 3 Using temporary; Using filesort +2 DERIVED x ALL NULL NULL NULL NULL 17 Using temporary; Using filesort +2 DERIVED y ALL NULL NULL NULL NULL 17 Using where diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index 154fc4b3834..b412555f1e8 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -183,3 +183,12 @@ CREATE TABLE t3 ( INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00),(1009,1.25),(1010,1.50),(1011,1.75); select 497, TMP.ID, NULL from (select 497 as ID, MAX(t3.DATA) as DATA from t1 join t2 on (t1.ObjectID = t2.ID) join t3 on (t1.ObjectID = t3.ID) group by t2.ParID order by DATA DESC) as TMP; drop table t1, t2, t3; + + +# +# explain derived +# +CREATE TABLE t1 (name char(1) default NULL, val int(5) default NULL); +INSERT INTO t1 VALUES ('a',1), ('a',2), ('a',2), ('a',2), ('a',3), ('a',6), ('a',7), ('a',11), ('a',11), ('a',12), ('a',13), ('a',13), ('a',20), ('b',2), ('b',3), ('b',4), ('b',5); +SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name; +explain SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index e7faaf1767d..c1365baaf0a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -481,14 +481,13 @@ int mysql_select(THD *thd, Item ***rref_pointer_array, SELECT_LEX *select_lex); void free_underlaid_joins(THD *thd, SELECT_LEX *select); void fix_tables_pointers(SELECT_LEX *select_lex); -void fix_tables_pointers(SELECT_LEX_UNIT *select_lex); int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result); int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type, select_result *result); int mysql_union(THD *thd, LEX *lex, select_result *result, SELECT_LEX_UNIT *unit); -int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); +int mysql_handle_derived(LEX *lex); Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item ***copy_func, Field **from_field, bool group,bool modify_item); @@ -676,6 +675,7 @@ int setup_ftfuncs(SELECT_LEX* select); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); void wait_for_refresh(THD *thd); int open_tables(THD *thd,TABLE_LIST *tables); +int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables); int open_and_lock_tables(THD *thd,TABLE_LIST *tables); int lock_tables(THD *thd,TABLE_LIST *tables); TABLE *open_temporary_table(THD *thd, const char *path, const char *db, diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 81ea9d9e2ac..d125c95e839 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -732,7 +732,7 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db, int error; if (table_rules_on) { - table.next= 0; + bzero((char*) &table, sizeof(table)); //just for safe table.db= (char*) db; table.real_name= (char*) table_name; table.updating= 1; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 77131a37869..8ef6a32a430 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2247,7 +2247,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, } #endif - if (open_and_lock_tables(thd,tables)) + if (simple_open_n_lock_tables(thd,tables)) { // Should never happen close_thread_tables(thd); /* purecov: deadcode */ DBUG_RETURN(-1); /* purecov: deadcode */ @@ -2395,7 +2395,7 @@ int mysql_grant(THD *thd, const char *db, List &list, } /* open the mysql.user and mysql.db tables */ - + bzero((char*) &tables,sizeof(tables)); tables[0].alias=tables[0].real_name=(char*) "user"; tables[1].alias=tables[1].real_name=(char*) "db"; tables[0].next=tables+1; @@ -2421,7 +2421,7 @@ int mysql_grant(THD *thd, const char *db, List &list, } #endif - if (open_and_lock_tables(thd,tables)) + if (simple_open_n_lock_tables(thd,tables)) { // This should never happen close_thread_tables(thd); /* purecov: deadcode */ DBUG_RETURN(-1); /* purecov: deadcode */ @@ -2517,7 +2517,7 @@ my_bool grant_init(THD *org_thd) thd->store_globals(); thd->db= my_strdup("mysql",MYF(0)); thd->db_length=5; // Safety - bzero((char*) &tables,sizeof(tables)); + bzero((char*) &tables, sizeof(tables)); tables[0].alias=tables[0].real_name= (char*) "tables_priv"; tables[1].alias=tables[1].real_name= (char*) "columns_priv"; tables[0].next=tables+1; @@ -3376,7 +3376,7 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables) } #endif - if (open_and_lock_tables(thd, tables)) + if (simple_open_n_lock_tables(thd, tables)) { // This should never happen close_thread_tables(thd); DBUG_RETURN(-1); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 3125c392751..5707b58299f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1305,6 +1305,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, goto err; // Can't repair the table TABLE_LIST table_list; + bzero((char*) &table_list, sizeof(table_list)); // just for safe table_list.db=(char*) db; table_list.real_name=(char*) name; table_list.next=0; @@ -1372,11 +1373,13 @@ int open_tables(THD *thd,TABLE_LIST *start) thd->proc_info="Opening tables"; for (tables=start ; tables ; tables=tables->next) { + if (tables->derived) + continue; if (!tables->table && - !(tables->table=open_table(thd, - tables->db, - tables->real_name, - tables->alias, &refresh))) + !(tables->table= open_table(thd, + tables->db, + tables->real_name, + tables->alias, &refresh))) { if (refresh) // Refresh in progress { @@ -1522,15 +1525,47 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) /* - Open all tables in list and locks them for read. - The lock will automaticly be freed by close_thread_tables() + Open all tables in list and locks them for read without derived + tables processing. + + SYNOPSIS + simple_open_n_lock_tables() + thd - thread handler + tables - list of tables for open&locking + + NOTE + The lock will automaticly be freed by close_thread_tables() */ -int open_and_lock_tables(THD *thd,TABLE_LIST *tables) +int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables) { - if (open_tables(thd,tables) || lock_tables(thd,tables)) - return -1; /* purecov: inspected */ - return 0; + DBUG_ENTER("open_n_lock_tables"); + if (open_tables(thd, tables) || lock_tables(thd, tables)) + DBUG_RETURN(-1); /* purecov: inspected */ + DBUG_RETURN(0); +} + + +/* + Open all tables in list, locks them and process derived tables + tables processing. + + SYNOPSIS + simple_open_n_lock_tables() + thd - thread handler + tables - list of tables for open&locking + + NOTE + The lock will automaticly be freed by close_thread_tables() +*/ + +int open_and_lock_tables(THD *thd, TABLE_LIST *tables) +{ + DBUG_ENTER("open_and_lock_tables"); + if (open_tables(thd, tables) || lock_tables(thd, tables)) + DBUG_RETURN(-1); /* purecov: inspected */ + fix_tables_pointers(thd->lex->all_selects_list); + DBUG_RETURN(mysql_handle_derived(thd->lex)); } @@ -1563,12 +1598,18 @@ int lock_tables(THD *thd,TABLE_LIST *tables) DBUG_ASSERT(thd->lock == 0); // You must lock everything at once uint count=0; for (table = tables ; table ; table=table->next) - count++; + { + if (!table->derived) + count++; + } TABLE **start,**ptr; if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*)*count))) return -1; for (table = tables ; table ; table=table->next) - *(ptr++)= table->table; + { + if (!table->derived) + *(ptr++)= table->table; + } if (!(thd->lock=mysql_lock_tables(thd,start,count))) return -1; /* purecov: inspected */ } @@ -1576,7 +1617,8 @@ int lock_tables(THD *thd,TABLE_LIST *tables) { for (table = tables ; table ; table=table->next) { - if (check_lock_and_start_stmt(thd, table->table, table->lock_type)) + if (!table->derived && + check_lock_and_start_stmt(thd, table->table, table->lock_type)) { ha_rollback_stmt(thd); return -1; @@ -2165,6 +2207,7 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Ensure that we have access right to all columns */ if (!(table->grant.privilege & SELECT_ACL) && + !tables->derived && check_grant_all_columns(thd,SELECT_ACL,table)) DBUG_RETURN(-1); #endif diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 9ac7b7596fe..2204466b9d1 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -43,7 +43,6 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order, if ((open_and_lock_tables(thd, table_list))) DBUG_RETURN(-1); - fix_tables_pointers(thd->lex->all_selects_list); table= table_list->table; table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); thd->proc_info="init"; diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 374e56ecdd4..8fa5694714c 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -25,6 +25,49 @@ #include "sql_select.h" #include "sql_acl.h" +int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); + +/* + Resolve derived tables in all queries + + SYNOPSIS + mysql_handle_derived() + lex LEX for this thread + + RETURN + 0 ok + -1 Error + 1 Error and error message given +*/ +int +mysql_handle_derived(LEX *lex) +{ + int res= 0; + if (lex->derived_tables) + { + for (SELECT_LEX *sl= lex->all_selects_list; + sl; + sl= sl->next_select_in_list()) + { + for (TABLE_LIST *cursor= sl->get_table_list(); + cursor; + cursor= cursor->next) + { + if (cursor->derived && (res=mysql_derived(lex->thd, lex, + cursor->derived, + cursor))) + { + if (res < 0 || lex->thd->net.report_error) + send_error(lex->thd, lex->thd->killed ? ER_SERVER_SHUTDOWN : 0); + return 1; + } + } + } + } + return 0; +} + + /* Resolve derived tables in all queries @@ -49,9 +92,6 @@ Derived tables is stored in thd->derived_tables and freed in close_thread_tables() - TODO - Move creation of derived tables in open_and_lock_tables() - RETURN 0 ok 1 Error @@ -72,143 +112,87 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, bool is_subsel= first_select->first_inner_unit() ? 1: 0; SELECT_LEX *save_current_select= lex->current_select; DBUG_ENTER("mysql_derived"); - - /* - In create_total_list, derived tables have to be treated in case of - EXPLAIN, This is because unit/node is not deleted in that - case. Current code in this function has to be improved to - recognize better when this function is called from derived tables - and when from other functions. - */ - if ((is_union || is_subsel) && unit->create_total_list(thd, lex, &tables, 1)) - DBUG_RETURN(-1); - /* - We have to do access checks here as this code is executed before any - sql command is started to execute. - */ -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (tables) - res= check_table_access(thd,SELECT_ACL, tables,0); - else - res= check_access(thd, SELECT_ACL, any_db,0,0,0); - if (res) - DBUG_RETURN(1); -#endif + if (!(derived_result= new select_union(0))) + DBUG_RETURN(1); // out of memory - if (!(res=open_and_lock_tables(thd,tables))) - { - if (is_union || is_subsel) - { - /* - The following code is a re-do of fix_tables_pointers() found - in sql_select.cc for UNION's within derived tables. The only - difference is in navigation, as in derived tables we care for - this level only. + // st_select_lex_unit::prepare correctly work for single select + if ((res= unit->prepare(thd, derived_result, 0))) + goto exit; - */ - fix_tables_pointers(unit); - } - - if (!(derived_result= new select_union(0))) - DBUG_RETURN(1); // out of memory - - // st_select_lex_unit::prepare correctly work for single select - if ((res= unit->prepare(thd, derived_result, 0))) - goto exit; - - /* - This is done in order to redo all field optimisations when any of the - involved tables is used in the outer query - */ - if (tables) - { - for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next) - cursor->table->clear_query_id= 1; - } - derived_result->tmp_table_param.init(); - derived_result->tmp_table_param.field_count= unit->types.elements; - /* - Temp table is created so that it hounours if UNION without ALL is to be - processed - */ - if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param, - unit->types, (ORDER*) 0, - is_union && !unit->union_option, 1, - (first_select->options | thd->options | - TMP_TABLE_ALL_COLUMNS), - HA_POS_ERROR, - org_table_list->alias))) - { - res= -1; - goto exit; - } - derived_result->set_table(table); + derived_result->tmp_table_param.init(); + derived_result->tmp_table_param.field_count= unit->types.elements; + /* + Temp table is created so that it hounours if UNION without ALL is to be + processed + */ + if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param, + unit->types, (ORDER*) 0, + is_union && !unit->union_option, 1, + (first_select->options | thd->options | + TMP_TABLE_ALL_COLUMNS), + HA_POS_ERROR, + org_table_list->alias))) + { + res= -1; + goto exit; + } + derived_result->set_table(table); - if (is_union) - res= mysql_union(thd, lex, derived_result, unit); + + if (is_union) + res= mysql_union(thd, lex, derived_result, unit); + else + { + unit->offset_limit_cnt= first_select->offset_limit; + unit->select_limit_cnt= first_select->select_limit+ + first_select->offset_limit; + if (unit->select_limit_cnt < first_select->select_limit) + unit->select_limit_cnt= HA_POS_ERROR; + if (unit->select_limit_cnt == HA_POS_ERROR) + first_select->options&= ~OPTION_FOUND_ROWS; + + lex->current_select= first_select; + res= mysql_select(thd, &first_select->ref_pointer_array, + (TABLE_LIST*) first_select->table_list.first, + first_select->with_wild, + first_select->item_list, first_select->where, + (first_select->order_list.elements+ + first_select->group_list.elements), + (ORDER *) first_select->order_list.first, + (ORDER *) first_select->group_list.first, + first_select->having, (ORDER*) NULL, + (first_select->options | thd->options | + SELECT_NO_UNLOCK), + derived_result, unit, first_select); + } + + if (!res) + { + /* + Here we entirely fix both TABLE_LIST and list of SELECT's as + there were no derived tables + */ + if (derived_result->flush()) + res= 1; else { - unit->offset_limit_cnt= first_select->offset_limit; - unit->select_limit_cnt= first_select->select_limit+ - first_select->offset_limit; - if (unit->select_limit_cnt < first_select->select_limit) - unit->select_limit_cnt= HA_POS_ERROR; - if (unit->select_limit_cnt == HA_POS_ERROR) - first_select->options&= ~OPTION_FOUND_ROWS; - - lex->current_select= first_select; - res= mysql_select(thd, &first_select->ref_pointer_array, - (TABLE_LIST*) first_select->table_list.first, - first_select->with_wild, - first_select->item_list, first_select->where, - (first_select->order_list.elements+ - first_select->group_list.elements), - (ORDER *) first_select->order_list.first, - (ORDER *) first_select->group_list.first, - first_select->having, (ORDER*) NULL, - (first_select->options | thd->options | - SELECT_NO_UNLOCK), - derived_result, unit, first_select); - } - - if (!res) - { - /* - Here we entirely fix both TABLE_LIST and list of SELECT's as - there were no derived tables - */ - if (derived_result->flush()) - res= 1; - else + org_table_list->real_name= table->real_name; + org_table_list->table= table; + if (org_table_list->table_list) { - org_table_list->real_name=table->real_name; - org_table_list->table=table; - table->derived_select_number= first_select->select_number; - table->tmp_table= TMP_TABLE; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - org_table_list->grant.privilege= SELECT_ACL; -#endif - if (lex->describe) - { - // to fix a problem in EXPLAIN - if (tables) - { - for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next) - if (cursor->table_list) - cursor->table_list->table=cursor->table; - } - } - else - { - unit->exclude_tree(); - unit->cleanup(); - } - org_table_list->db= (char *)""; - // Force read of table stats in the optimizer - table->file->info(HA_STATUS_VARIABLE); + org_table_list->table_list->real_name= table->real_name; + org_table_list->table_list->table= table; } + table->derived_select_number= first_select->select_number; + table->tmp_table= TMP_TABLE; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + org_table_list->grant.privilege= SELECT_ACL; +#endif + org_table_list->db= (char *)""; + // Force read of table stats in the optimizer + table->file->info(HA_STATUS_VARIABLE); } if (res) @@ -223,7 +207,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, exit: delete derived_result; lex->current_select= save_current_select; - close_thread_tables(thd, 0, 1); } DBUG_RETURN(res); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index c2f3e737daf..342089987dc 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -188,7 +188,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, res= open_and_lock_tables(thd, table_list); if (res) DBUG_RETURN(-1); - fix_tables_pointers(thd->lex->all_selects_list); table= table_list->table; thd->proc_info="init"; @@ -646,7 +645,8 @@ public: thd.command=COM_DELAYED_INSERT; thd.lex->current_select= 0; /* for my_message_sql */ - bzero((char*) &thd.net,sizeof(thd.net)); // Safety + bzero((char*) &thd.net, sizeof(thd.net)); // Safety + bzero((char*) &table_list, sizeof(table_list)); // Safety thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT; thd.host_or_ip= ""; bzero((char*) &info,sizeof(info)); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 65c958093bd..62f255ea178 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1286,12 +1286,10 @@ bool st_select_lex::test_limit() !0 - error */ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex, - TABLE_LIST **result_arg, - bool check_derived) + TABLE_LIST **result_arg) { *result_arg= 0; - res= create_total_list_n_last_return(thd_arg, lex, &result_arg, - check_derived); + res= create_total_list_n_last_return(thd_arg, lex, &result_arg); return res; } @@ -1303,8 +1301,7 @@ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex, thd THD pointer lex pointer on LEX stricture result pointer on pointer on result list of tables pointer - check_derived force derived table chacking (used for creating - table list for derived query) + DESCRIPTION This is used for UNION & subselect to create a new table list of all used tables. @@ -1318,8 +1315,7 @@ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex, bool st_select_lex_unit:: create_total_list_n_last_return(THD *thd_arg, st_lex *lex, - TABLE_LIST ***result_arg, - bool check_derived) + TABLE_LIST ***result_arg) { TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first; TABLE_LIST **new_table_list= *result_arg, *aux; @@ -1345,15 +1341,12 @@ create_total_list_n_last_return(THD *thd_arg, return 1; } - if (sl->linkage == DERIVED_TABLE_TYPE && !check_derived) - goto end; - for (SELECT_LEX_UNIT *inner= sl->first_inner_unit(); inner; inner= inner->next_unit()) { if (inner->create_total_list_n_last_return(thd, lex, - &slave_list_last, 0)) + &slave_list_last)) return 1; } @@ -1400,63 +1393,75 @@ end: return 0; } + st_select_lex_unit* st_select_lex_unit::master_unit() { return this; } + st_select_lex* st_select_lex_unit::outer_select() { return (st_select_lex*) master; } + bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc) { return add_to_list(thd, order_list, item, asc); } + bool st_select_lex::add_item_to_list(THD *thd, Item *item) { return item_list.push_back(item); } + bool st_select_lex::add_group_to_list(THD *thd, Item *item, bool asc) { return add_to_list(thd, group_list, item, asc); } + bool st_select_lex::add_ftfunc_to_list(Item_func_match *func) { return !func || ftfunc_list->push_back(func); // end of memory? } + st_select_lex_unit* st_select_lex::master_unit() { return (st_select_lex_unit*) master; } + st_select_lex* st_select_lex::outer_select() { return (st_select_lex*) master->get_master(); } + bool st_select_lex::set_braces(bool value) { braces= value; return 0; } + bool st_select_lex::inc_in_sum_expr() { in_sum_expr++; return 0; } + uint st_select_lex::get_in_sum_expr() { return in_sum_expr; } + TABLE_LIST* st_select_lex::get_table_list() { return (TABLE_LIST*) table_list.first; @@ -1467,21 +1472,25 @@ List* st_select_lex::get_item_list() return &item_list; } + List* st_select_lex::get_use_index() { return use_index_ptr; } + List* st_select_lex::get_ignore_index() { return ignore_index_ptr; } + ulong st_select_lex::get_table_join_options() { return table_join_options; } + bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) { if (ref_pointer_array) @@ -1493,6 +1502,58 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) order_group_num)* 5)) == 0; } + +/* + Find db.table which will be updated in this unit + + SYNOPSIS + st_select_lex_unit::check_updateable() + db - data base name + table - real table name + + RETURN + 1 - found + 0 - OK (table did not found) +*/ +bool st_select_lex_unit::check_updateable(char *db, char *table) +{ + for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) + if (sl->check_updateable(db, table)) + return 1; + return 0; +} + + +/* + Find db.table which will be updated in this select and + underlayed ones (except derived tables) + + SYNOPSIS + st_select_lex::check_updateable() + db - data base name + table - real table name + + RETURN + 1 - found + 0 - OK (table did not found) +*/ +bool st_select_lex::check_updateable(char *db, char *table) +{ + if (find_real_table_in_list(get_table_list(), db, table)) + return 1; + + for (SELECT_LEX_UNIT *un= first_inner_unit(); + un; + un= un->next_unit()) + { + if (un->first_select()->linkage != DERIVED_TABLE_TYPE && + un->check_updateable(db, table)) + return 1; + } + return 0; +} + + void st_select_lex_unit::print(String *str) { for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) @@ -1535,6 +1596,7 @@ void st_select_lex::print_order(String *str, ORDER *order) } } + void st_select_lex::print_limit(THD *thd, String *str) { if (!thd) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index bcbd60e9716..b1f0b63b5cd 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -336,8 +336,7 @@ public: uint union_option; void init_query(); - bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result, - bool check_current_derived); + bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result); st_select_lex_unit* master_unit(); st_select_lex* outer_select(); st_select_lex* first_select() { return (st_select_lex*) slave; } @@ -355,14 +354,15 @@ public: int exec(); int cleanup(); + bool check_updateable(char *db, char *table); void print(String *str); + friend void mysql_init_query(THD *thd); friend int subselect_union_engine::exec(); private: bool create_total_list_n_last_return(THD *thd, st_lex *lex, - TABLE_LIST ***result, - bool check_current_derived); + TABLE_LIST ***result); }; typedef class st_select_lex_unit SELECT_LEX_UNIT; @@ -497,6 +497,7 @@ public: init_select(); } bool setup_ref_array(THD *thd, uint order_group_num); + bool check_updateable(char *db, char *table); void print(THD *thd, String *str); static void print_order(String *str, ORDER *order); void print_limit(THD *thd, String *str); diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc index 1d16771c1a4..efc4cf0921d 100644 --- a/sql/sql_olap.cc +++ b/sql/sql_olap.cc @@ -143,18 +143,6 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex) int count=select_lex->group_list.elements; int sl_return=0; -// a fix for UNION's - for (TABLE_LIST *cursor= (TABLE_LIST *)select_lex->table_list.first; - cursor; - cursor=cursor->next) - { - if (cursor->do_redirect) - { - //Sinisa TODO: there are function for this purpose: fix_tables_pointers - cursor->table= cursor->table_list->table; - cursor->do_redirect= 0; - } - } lex->last_selects=select_lex; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cbf091069d6..dbce5cf75a4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1789,34 +1789,9 @@ mysql_execute_command(THD *thd) #endif } #endif /* !HAVE_REPLICATION */ - /* - TODO: make derived tables processing 'inside' SELECT processing. - TODO: solve problem with depended derived tables in subselects - */ - if (lex->derived_tables) - { - for (SELECT_LEX *sl= lex->all_selects_list; - sl; - sl= sl->next_select_in_list()) - { - for (TABLE_LIST *cursor= sl->get_table_list(); - cursor; - cursor= cursor->next) - { - if (cursor->derived && (res=mysql_derived(thd, lex, - cursor->derived, - cursor))) - { - if (res < 0 || thd->net.report_error) - send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); - DBUG_VOID_RETURN; - } - } - } - } if (&lex->select_lex != lex->all_selects_list && lex->sql_command != SQLCOM_CREATE_TABLE && - lex->unit.create_total_list(thd, lex, &tables, 0)) + lex->unit.create_total_list(thd, lex, &tables)) DBUG_VOID_RETURN; /* @@ -1875,7 +1850,6 @@ mysql_execute_command(THD *thd) } else thd->send_explain_fields(result); - fix_tables_pointers(lex->all_selects_list); res= mysql_explain_union(thd, &thd->lex->unit, result); MYSQL_LOCK *save_lock= thd->lock; thd->lock= (MYSQL_LOCK *)0; @@ -1918,7 +1892,6 @@ mysql_execute_command(THD *thd) (res= open_and_lock_tables(thd,tables)))) break; - fix_tables_pointers(lex->all_selects_list); res= mysql_do(thd, *lex->insert_list); if (thd->net.report_error) res= -1; @@ -2127,7 +2100,7 @@ mysql_execute_command(THD *thd) lex->select_lex.table_list.first= (byte*) (tables); create_table->next= 0; if (&lex->select_lex != lex->all_selects_list && - lex->unit.create_total_list(thd, lex, &tables, 0)) + lex->unit.create_total_list(thd, lex, &tables)) DBUG_VOID_RETURN; ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? @@ -2342,6 +2315,8 @@ mysql_execute_command(THD *thd) if (grant_option) { TABLE_LIST old_list,new_list; + bzero((char*) &old_list, sizeof(old_list)); + bzero((char*) &new_list, sizeof(new_list)); // Safety old_list=table[0]; new_list=table->next[0]; old_list.next=new_list.next=0; @@ -2673,23 +2648,15 @@ mysql_execute_command(THD *thd) } if (!walk) { - if (lex->derived_tables) - { - // are we trying to delete derived table? - for (walk= (TABLE_LIST*) tables; walk; walk= walk->next) - { - if (!strcmp(auxi->real_name,walk->alias) && - walk->derived) - { - net_printf(thd, ER_NON_UPDATABLE_TABLE, - auxi->real_name, "DELETE"); - goto error; - } - } - } net_printf(thd, ER_NONUNIQ_TABLE, auxi->real_name); goto error; } + if (walk->derived) + { + net_printf(thd, ER_NON_UPDATABLE_TABLE, + auxi->real_name, "DELETE"); + goto error; + } walk->lock_type= auxi->lock_type; auxi->table_list= walk; // Remember corresponding table } @@ -2703,21 +2670,27 @@ mysql_execute_command(THD *thd) break; /* Fix tables-to-be-deleted-from list to point at opened tables */ for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next) - auxi->table= auxi->table_list->table; - if (&lex->select_lex != lex->all_selects_list) { - for (TABLE_LIST *t= select_lex->get_table_list(); - t; t= t->next) + auxi->table= auxi->table_list->table; + /* + Multi-delete can't be constucted over-union => we always have + single SELECT on top and have to check underlayed SELECTs of it + */ + for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit(); + un; + un= un->next_unit()) { - if (find_real_table_in_list(t->table_list->next, t->db, t->real_name)) + if (un->first_select()->linkage != DERIVED_TABLE_TYPE && + un->check_updateable(auxi->table_list->db, + auxi->table_list->real_name)) { - my_error(ER_UPDATE_TABLE_USED, MYF(0), t->real_name); + my_error(ER_UPDATE_TABLE_USED, MYF(0), auxi->table_list->real_name); res= -1; break; } } } - fix_tables_pointers(lex->all_selects_list); + if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables, table_count))) { @@ -2962,7 +2935,6 @@ mysql_execute_command(THD *thd) if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) || (res= open_and_lock_tables(thd,tables)))) break; - fix_tables_pointers(lex->all_selects_list); if (!(res= sql_set_variables(thd, &lex->var_list))) send_ok(thd); if (thd->net.report_error) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index de0d0c8aca8..1d5233d5803 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -733,7 +733,7 @@ static bool mysql_test_select_fields(Prepared_statement *stmt, DBUG_RETURN(1); #endif if ((&lex->select_lex != lex->all_selects_list && - lex->unit.create_total_list(thd, lex, &tables, 0))) + lex->unit.create_total_list(thd, lex, &tables))) DBUG_RETURN(1); if (open_and_lock_tables(thd, tables)) @@ -746,7 +746,6 @@ static bool mysql_test_select_fields(Prepared_statement *stmt, } else { - fix_tables_pointers(lex->all_selects_list); if (!result && !(result= new select_send())) { send_error(thd, ER_OUT_OF_RESOURCES); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f6e7a474eca..9ad7ba606be 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -175,7 +175,6 @@ int handle_select(THD *thd, LEX *lex, select_result *result) register SELECT_LEX *select_lex = &lex->select_lex; DBUG_ENTER("handle_select"); - fix_tables_pointers(lex->all_selects_list); if (select_lex->next_select()) res=mysql_union(thd, lex, result, &lex->unit); else diff --git a/sql/sql_select.h b/sql/sql_select.h index 7cc71117914..aa1d7673176 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -427,7 +427,6 @@ public: bool cp_buffer_from_ref(TABLE_REF *ref); bool error_if_full_join(JOIN *join); -void relink_tables(SELECT_LEX *select_lex); int report_error(TABLE *table, int error); int safe_index_read(JOIN_TAB *tab); COND *eliminate_not_funcs(COND *cond); diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 337f2540a39..6e8aae54b23 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -149,7 +149,7 @@ void udf_init() tables.lock_type = TL_READ; tables.db=new_thd->db; - if (open_and_lock_tables(new_thd, &tables)) + if (simple_open_n_lock_tables(new_thd, &tables)) { DBUG_PRINT("error",("Can't open udf table")); sql_print_error("Can't open mysql/func table"); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 8ee00f2bca6..45f7a73f6b5 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -79,7 +79,6 @@ int mysql_update(THD *thd, if ((open_and_lock_tables(thd, table_list))) DBUG_RETURN(-1); thd->proc_info="init"; - fix_tables_pointers(thd->lex->all_selects_list); table= table_list->table; table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); @@ -431,7 +430,6 @@ int mysql_multi_update(THD *thd, #endif if ((res=open_and_lock_tables(thd,table_list))) DBUG_RETURN(res); - fix_tables_pointers(thd->lex->all_selects_list); select_lex->select_limit= HA_POS_ERROR; From 1f739ca45eb009de8dadd4503374bc4a5c6bf5c0 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 1 Feb 2004 20:07:44 +0200 Subject: [PATCH 04/36] make JOIN::prepare, JOIN::optimize only once for EXPLAIN of derived table (BUG#2120 sfter merge) mysql-test/r/derived.result: correct results of derived tble EXPLAIN test of "Using Index" with derived tables mysql-test/t/derived.test: test of "Using Index" with derived tables sql/mysql_priv.h: way to force derived table save JOIN after execution sql/sql_derived.cc: way to force derived table save JOIN after execution sql/sql_lex.h: way to force derived table save JOIN after execution sql/sql_select.cc: make JOIN::prepare, JOIN::optimize only once for EXPLAIN of derived table --- mysql-test/r/derived.result | 21 ++++++++++++++++----- mysql-test/t/derived.test | 10 ++++++++++ sql/mysql_priv.h | 4 +++- sql/sql_derived.cc | 9 +++++++++ sql/sql_lex.h | 1 + sql/sql_select.cc | 18 ++++++++---------- 6 files changed, 47 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index a89494645fa..dea4dd9b4c2 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -141,7 +141,7 @@ a t explain select count(*) from t1 as tt1, (select * from t1) as tt2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -2 DERIVED t1 index NULL a 4 NULL 10000 Using index +2 DERIVED t1 ALL NULL NULL NULL NULL 10000 drop table t1; SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b; (SELECT * FROM (SELECT 1 as a) as a ) @@ -189,13 +189,13 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY m2 ALL NULL NULL NULL NULL 9 1 PRIMARY ALL NULL NULL NULL NULL 6 Using where 2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort -2 DERIVED m1 index NULL PRIMARY 3 NULL 9 Using index +2 DERIVED m1 eq_ref PRIMARY PRIMARY 3 test.mp.mat_id 1 explain SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY m2 ALL NULL NULL NULL NULL 9 1 PRIMARY ALL NULL NULL NULL NULL 6 Using where 2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort -2 DERIVED m1 index NULL PRIMARY 3 NULL 9 Using index +2 DERIVED m1 eq_ref PRIMARY PRIMARY 3 test.mp.mat_id 1 drop table t1,t2; SELECT a.x FROM (SELECT 1 AS x) AS a HAVING a.x = 1; x @@ -229,8 +229,8 @@ explain select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 2 1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 THEMAX.E2 1 Using where -2 DERIVED A index NULL PRIMARY 4 NULL 2 Using where; Using index -3 DEPENDENT SUBQUERY B index NULL PRIMARY 4 NULL 2 Using where; Using index +2 DERIVED A ALL NULL NULL NULL NULL 2 Using where +3 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 2 Using where drop table t1; create table t1 (a int); insert into t1 values (1),(2); @@ -309,3 +309,14 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 3 Using temporary; Using filesort 2 DERIVED x ALL NULL NULL NULL NULL 17 Using temporary; Using filesort 2 DERIVED y ALL NULL NULL NULL NULL 17 Using where +drop table t1; +create table t2 (a int, b int, primary key (a)); +insert into t2 values (1,7),(2,7); +explain select a from t2 where a>1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 2 Using where; Using index +explain select a from (select a from t2 where a>1) tt; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY system NULL NULL NULL NULL 1 +2 DERIVED t2 range PRIMARY PRIMARY 4 NULL 2 Using where; Using index +drop table t2; diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index b412555f1e8..988ef30d1dc 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -192,3 +192,13 @@ CREATE TABLE t1 (name char(1) default NULL, val int(5) default NULL); INSERT INTO t1 VALUES ('a',1), ('a',2), ('a',2), ('a',2), ('a',3), ('a',6), ('a',7), ('a',11), ('a',11), ('a',12), ('a',13), ('a',13), ('a',20), ('b',2), ('b',3), ('b',4), ('b',5); SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name; explain SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name; +drop table t1; + +# +# "Using index" in explain +# +create table t2 (a int, b int, primary key (a)); +insert into t2 values (1,7),(2,7); +explain select a from t2 where a>1; +explain select a from (select a from t2 where a>1) tt; +drop table t2; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 7e1923b1825..4d03feae07c 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -247,7 +247,9 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; // uncachable cause #define UNCACHEABLE_DEPENDENT 1 #define UNCACHEABLE_RAND 2 -#define UNCACHEABLE_SIDEEFFECT 4 +#define UNCACHEABLE_SIDEEFFECT 4 +// forcing to save JOIN for explain +#define UNCACHEABLE_EXPLAIN 8 #ifdef EXTRA_DEBUG /* diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 8fa5694714c..a307b59b525 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -62,6 +62,15 @@ mysql_handle_derived(LEX *lex) return 1; } } + if (lex->describe) + { + /* + Force join->join_tmp creation, because we will use this JOIN + twice for EXPLAIN and we have to have unchanged join for EXPLAINing + */ + sl->uncacheable|= UNCACHEABLE_EXPLAIN; + sl->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN; + } } } return 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 4ada72167be..3b1b3873706 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -232,6 +232,7 @@ public: UNCACHEABLE_DEPENDENT UNCACHEABLE_RAND UNCACHEABLE_SIDEEFFECT + UNCACHEABLE_EXPLAIN */ uint8 uncacheable; enum sub_select_type linkage; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ede6e837984..e47ed8fcbbc 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1579,8 +1579,8 @@ mysql_select(THD *thd, Item ***rref_pointer_array, goto err; } } - free_join= 0; } + free_join= 0; join->select_options= select_options; } else @@ -3769,11 +3769,6 @@ JOIN::join_free(bool full) { if (tab->table) { - if (tab->table->key_read) - { - tab->table->key_read= 0; - tab->table->file->extra(HA_EXTRA_NO_KEYREAD); - } /* Don't free index if we are using read_record */ if (!tab->read_record.table) tab->table->file->index_end(); @@ -9128,6 +9123,9 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) sl; sl= sl->next_select()) { + // drop UNCACHEABLE_EXPLAIN, because it is for internal usage only + uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN); + res= mysql_explain_select(thd, sl, (((&thd->lex->select_lex)==sl)? ((thd->lex->all_selects_list != sl) ? @@ -9135,13 +9133,13 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) ((sl == first)? ((sl->linkage == DERIVED_TABLE_TYPE) ? "DERIVED": - ((sl->uncacheable & UNCACHEABLE_DEPENDENT) ? + ((uncacheable & UNCACHEABLE_DEPENDENT) ? "DEPENDENT SUBQUERY": - (sl->uncacheable?"UNCACHEABLE SUBQUERY": + (uncacheable?"UNCACHEABLE SUBQUERY": "SUBQUERY"))): - ((sl->uncacheable & UNCACHEABLE_DEPENDENT) ? + ((uncacheable & UNCACHEABLE_DEPENDENT) ? "DEPENDENT UNION": - sl->uncacheable?"UNCACHEABLE UNION": + uncacheable?"UNCACHEABLE UNION": "UNION"))), result); if (res) From 7b0ee22df4c8c8fe815165191ee20d952b9f987c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Feb 2004 02:30:28 +0000 Subject: [PATCH 05/36] Bug#2634 Emit "TYPE=" for 4.0 and 3.23 compatible modes mysql-test/r/mysqldump.result: Bug#2634 New test case mysql-test/t/mysqldump.test: Bug#2634 New test case --- mysql-test/r/mysqldump.result | 37 +++++++++++++++++++++++++++++++++++ mysql-test/t/mysqldump.test | 10 ++++++++++ sql/sql_show.cc | 5 ++++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index f51caee39d6..bdcdb0532f7 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -123,3 +123,40 @@ UNLOCK TABLES; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; DROP TABLE t1; +CREATE TABLE t1 (a int) ENGINE=MYISAM; +INSERT INTO t1 VALUES (1), (2); +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` int(11) default NULL +) TYPE=MyISAM; + + +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +LOCK TABLES `t1` WRITE; +INSERT INTO `t1` VALUES (1),(2); +UNLOCK TABLES; +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; + +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` int(11) default NULL +) TYPE=MyISAM; + + +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +LOCK TABLES `t1` WRITE; +INSERT INTO `t1` VALUES (1),(2); +UNLOCK TABLES; +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; + +DROP TABLE t1; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 93b0dd4a75d..9bfaaa51b09 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -53,3 +53,13 @@ CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'); --exec $MYSQL_DUMP --skip-comments test t1 DROP TABLE t1; + +# +# Bug #2634 +# + +CREATE TABLE t1 (a int) ENGINE=MYISAM; +INSERT INTO t1 VALUES (1), (2); +--exec $MYSQL_DUMP --skip-comments --compatible=mysql40 test t1 +--exec $MYSQL_DUMP --skip-comments --compatible=mysql323 test t1 +DROP TABLE t1; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 3b937f97089..5f6167f2cd1 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1338,7 +1338,10 @@ store_create_info(THD *thd, TABLE *table, String *packet) packet->append("\n)", 2); if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode) { - packet->append(" ENGINE=", 8); + if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) + packet->append(" TYPE=", 6); + else + packet->append(" ENGINE=", 8); packet->append(file->table_type()); if (table->table_charset && From 0db0b601abb3be2fdafa612583f4e03360876236 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Feb 2004 10:22:08 +0100 Subject: [PATCH 06/36] Added SQL_SELECT::cleanup() to make it easier to reuse SQL_SELECT item's for sub selects. Needed for proper fix for bug #2479. Added 'select_to_file' class to be able to merge identical code for select_export and select_dump client/mysql.cc: Print mysql_insert_id() in 'status' mysys/charset.c: after merge fixup sql/item_func.cc: Code cleanup + new comments sql/opt_range.cc: Added SQL_SELECT::cleanup() to make it easier to reuse SQL_SELECT item's for sub selects. sql/opt_range.h: Added SQL_SELECT::cleanup() to make it easier to reuse SQL_SELECT item's for sub selects. sql/sql_class.cc: Added 'select_to_file' class to be able to merge identical code for select_export and select_dump sql/sql_class.h: Added 'select_to_file' class to be able to merge identical code for select_export and select_dump sql/sql_select.cc: Fixed bug when calling 'delete select' in sub selects. (Bug 2479) (Test case is already commited to global source repository) --- client/mysql.cc | 8 +++- mysys/charset.c | 2 - sql/item_func.cc | 13 ++++-- sql/opt_range.cc | 21 ++++++--- sql/opt_range.h | 1 + sql/sql_class.cc | 110 +++++++++++++++++++++++++--------------------- sql/sql_class.h | 58 ++++++++++++------------ sql/sql_select.cc | 13 +++--- 8 files changed, 131 insertions(+), 95 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 2cdcd23165e..665a8dde82d 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -44,7 +44,7 @@ #include #endif -const char *VER= "14.4"; +const char *VER= "14.5"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 @@ -2703,6 +2703,9 @@ com_status(String *buffer __attribute__((unused)), char *line __attribute__((unused))) { const char *status; + char buff[22]; + ulonglong id; + tee_puts("--------------", stdout); usage(1); /* Print version */ if (connected) @@ -2748,6 +2751,9 @@ com_status(String *buffer __attribute__((unused)), tee_fprintf(stdout, "Server version:\t\t%s\n", mysql_get_server_info(&mysql)); tee_fprintf(stdout, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql)); tee_fprintf(stdout, "Connection:\t\t%s\n", mysql_get_host_info(&mysql)); + if ((id= mysql_insert_id(&mysql))) + tee_fprintf(stdout, "Insert id:\t\t%s\n", llstr(id, buff)); + tee_fprintf(stdout, "Client characterset:\t%s\n", charset_info->name); tee_fprintf(stdout, "Server characterset:\t%s\n", mysql.charset->name); diff --git a/mysys/charset.c b/mysys/charset.c index c0d8b183c17..5bf0ea972a5 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -537,7 +537,6 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) while we may changing the cs_info_table */ pthread_mutex_lock(&THR_LOCK_charset); - if ((cs= all_charsets[cs_number])) { if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED)) @@ -548,7 +547,6 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL; } pthread_mutex_unlock(&THR_LOCK_charset); - pthread_mutex_unlock(&THR_LOCK_charset); return cs; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 802b6dbb8d6..c995b50109f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2646,10 +2646,15 @@ longlong Item_func_inet_aton::val_int() } if (c != '.') // IP number can't end on '.' { - switch (dot_count) - { - case 1: result<<= 8; - case 2: result<<= 8; + /* + Handle short-forms addresses according to standard. Examples: + 127 -> 0.0.0.127 + 127.1 -> 127.0.0.1 + 127.2.1 -> 127.2.0.1 + */ + switch (dot_count) { + case 1: result<<= 8; /* Fall through */ + case 2: result<<= 8; /* Fall through */ } return (result << 8) + (ulonglong) byte_result; } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index acc23924f75..17fc948dd6e 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -369,14 +369,25 @@ SQL_SELECT::SQL_SELECT() :quick(0),cond(0),free_cond(0) } -SQL_SELECT::~SQL_SELECT() +void SQL_SELECT::cleanup() { delete quick; + quick= 0; if (free_cond) + { + free_cond=0; delete cond; + cond= 0; + } close_cached_file(&file); } + +SQL_SELECT::~SQL_SELECT() +{ + cleanup(); +} + #undef index // Fix for Unixware 7 QUICK_SELECT::QUICK_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc) @@ -2180,6 +2191,7 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree) param->table->quick_rows[key]=records; param->table->quick_key_parts[key]=param->max_key_part+1; } + DBUG_PRINT("exit", ("Records: %lu", (ulong) records)); DBUG_RETURN(records); } @@ -2532,12 +2544,7 @@ int QUICK_SELECT::get_next() int result; if (range) { // Already read through key -/* result=((range->flag & EQ_RANGE) ? - file->index_next_same(record, (byte*) range->min_key, - range->min_length) : - file->index_next(record)); -*/ - result=((range->flag & (EQ_RANGE | GEOM_FLAG) ) ? + result=((range->flag & (EQ_RANGE | GEOM_FLAG)) ? file->index_next_same(record, (byte*) range->min_key, range->min_length) : file->index_next(record)); diff --git a/sql/opt_range.h b/sql/opt_range.h index 1c209dc7027..bb0d27b722c 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -127,6 +127,7 @@ class SQL_SELECT :public Sql_alloc { SQL_SELECT(); ~SQL_SELECT(); + void cleanup(); bool check_quick(THD *thd, bool force_quick_range, ha_rows limit) { return test_quick_select(thd, key_map(~0), 0, limit, force_quick_range) < 0; } inline bool skipp_record() { return cond ? cond->val_int() == 0 : 0; } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ce30c6f3d09..2b743fc83c7 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -679,12 +679,24 @@ bool select_send::send_eof() } -/*************************************************************************** -** Export of select to textfile -***************************************************************************/ +/************************************************************************ + Handling writing to file +************************************************************************/ + +void select_to_file::send_error(uint errcode,const char *err) +{ + ::send_error(thd,errcode,err); + if (file > 0) + { + (void) end_io_cache(&cache); + (void) my_close(file,MYF(0)); + (void) my_delete(path,MYF(0)); // Delete file on error + file= -1; + } +} -select_export::~select_export() +select_to_file::~select_to_file() { if (file >= 0) { // This only happens in case of error @@ -692,17 +704,42 @@ select_export::~select_export() (void) my_close(file,MYF(0)); file= -1; } +} + +/*************************************************************************** +** Export of select to textfile +***************************************************************************/ + +select_export::~select_export() +{ thd->sent_row_count=row_count; } -static int create_file(THD *thd, char *path, sql_exchange *exchange, - File *file, IO_CACHE *cache) +/* + Create file with IO cache + + SYNOPSIS + create_file() + thd Thread handle + path File name + exchange Excange class + cache IO cache + + RETURN + >= 0 File handle + -1 Error +*/ + + +static File create_file(THD *thd, char *path, sql_exchange *exchange, + IO_CACHE *cache) { - uint option= 4; + File file; + uint option= MY_UNPACK_FILENAME; #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS - option|= 1; // Force use of db directory + option|= MY_REPLACE_DIR; // Force use of db directory #endif (void) fn_format(path, exchange->file_name, thd->db ? thd->db : "", "", option); @@ -712,35 +749,32 @@ static int create_file(THD *thd, char *path, sql_exchange *exchange, return 1; } /* Create the file world readable */ - if ((*file= my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0) - return 1; + if ((file= my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0) + return file; #ifdef HAVE_FCHMOD - (void) fchmod(*file, 0666); // Because of umask() + (void) fchmod(file, 0666); // Because of umask() #else (void) chmod(path, 0666); #endif - if (init_io_cache(cache, *file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME))) + if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME))) { - my_close(*file, MYF(0)); + my_close(file, MYF(0)); my_delete(path, MYF(0)); // Delete file on error, it was just created - *file= -1; - end_io_cache(cache); - return 1; + return -1; } - return 0; + return file; } int select_export::prepare(List &list, SELECT_LEX_UNIT *u) { - char path[FN_REFLEN]; bool blob_flag=0; unit= u; if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN) strmake(path,exchange->file_name,FN_REFLEN-1); - if (create_file(thd, path, exchange, &file, &cache)) + if ((file= create_file(thd, path, exchange, &cache)) < 0) return 1; /* Check if there is any blobs in data */ { @@ -912,14 +946,6 @@ err: } -void select_export::send_error(uint errcode, const char *err) -{ - ::send_error(thd,errcode,err); - (void) my_close(file,MYF(0)); - file= -1; -} - - bool select_export::send_eof() { int error=test(end_io_cache(&cache)); @@ -937,24 +963,12 @@ bool select_export::send_eof() ***************************************************************************/ -select_dump::~select_dump() -{ - if (file >= 0) - { // This only happens in case of error - (void) end_io_cache(&cache); - (void) my_close(file,MYF(0)); - file= -1; - } -} - int select_dump::prepare(List &list __attribute__((unused)), SELECT_LEX_UNIT *u) { unit= u; - if (create_file(thd, path, exchange, &file, &cache)) - return 1; - return 0; + return (int) ((file= create_file(thd, path, exchange, &cache)) < 0); } @@ -997,13 +1011,6 @@ err: } -void select_dump::send_error(uint errcode,const char *err) -{ - ::send_error(thd,errcode,err); - (void) my_close(file,MYF(0)); - file= -1; -} - bool select_dump::send_eof() { int error=test(end_io_cache(&cache)); @@ -1015,11 +1022,13 @@ bool select_dump::send_eof() return error; } + select_subselect::select_subselect(Item_subselect *item_arg) { item= item_arg; } + bool select_singlerow_subselect::send_data(List &items) { DBUG_ENTER("select_singlerow_subselect::send_data"); @@ -1042,6 +1051,7 @@ bool select_singlerow_subselect::send_data(List &items) DBUG_RETURN(0); } + bool select_max_min_finder_subselect::send_data(List &items) { DBUG_ENTER("select_max_min_finder_subselect::send_data"); @@ -1147,8 +1157,9 @@ bool select_exists_subselect::send_data(List &items) /*************************************************************************** -** Dump of select to variables + Dump of select to variables ***************************************************************************/ + int select_dumpvar::prepare(List &list, SELECT_LEX_UNIT *u) { List_iterator_fast li(list); @@ -1165,7 +1176,8 @@ int select_dumpvar::prepare(List &list, SELECT_LEX_UNIT *u) { ls= gl++; Item_func_set_user_var *xx = new Item_func_set_user_var(*ls,item); - xx->fix_fields(thd,(TABLE_LIST*) thd->lex->select_lex.table_list.first,&item); + xx->fix_fields(thd,(TABLE_LIST*) thd->lex->select_lex.table_list.first, + &item); xx->fix_length_and_dec(); vars.push_back(xx); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 7971137d848..51dc8270d09 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -962,41 +962,45 @@ public: }; -class select_export :public select_result { - sql_exchange *exchange; - File file; - IO_CACHE cache; - ha_rows row_count; - uint field_term_length; - int field_sep_char,escape_char,line_sep_char; - bool fixed_row_size; -public: - select_export(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) {} - ~select_export(); - int prepare(List &list, SELECT_LEX_UNIT *u); - bool send_fields(List &list, - uint flag) { return 0; } - bool send_data(List &items); - void send_error(uint errcode,const char *err); - bool send_eof(); -}; - - -class select_dump :public select_result { +class select_to_file :public select_result { +protected: sql_exchange *exchange; File file; IO_CACHE cache; ha_rows row_count; char path[FN_REFLEN]; + public: - select_dump(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) + select_to_file(sql_exchange *ex) :exchange(ex), file(-1),row_count(0L) { path[0]=0; } - ~select_dump(); - int prepare(List &list, SELECT_LEX_UNIT *u); - bool send_fields(List &list, - uint flag) { return 0; } - bool send_data(List &items); + ~select_to_file(); + bool send_fields(List &list, uint flag) { return 0; } void send_error(uint errcode,const char *err); +}; + + +class select_export :public select_to_file { + uint field_term_length; + int field_sep_char,escape_char,line_sep_char; + bool fixed_row_size; +public: + select_export(sql_exchange *ex) :select_to_file(ex) {} + ~select_export(); + int prepare(List &list, SELECT_LEX_UNIT *u); + bool send_data(List &items); + bool send_eof(); +}; + + +class select_dump :public select_to_file { + sql_exchange *exchange; + File file; + IO_CACHE cache; + ha_rows row_count; +public: + select_dump(sql_exchange *ex) :select_to_file(ex) {} + int prepare(List &list, SELECT_LEX_UNIT *u); + bool send_data(List &items); bool send_eof(); }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 75a94995830..34739c36b9d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1648,8 +1648,8 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select, { select->head=table; table->reginfo.impossible_range=0; - if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,limit)) - == 1) + if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0, + limit)) == 1) DBUG_RETURN(select->quick->records); if (error == -1) { @@ -7212,9 +7212,12 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, table->file->info(HA_STATUS_VARIABLE); // Get record count table->sort.found_records=filesort(thd, table,sortorder, length, select, filesort_limit, &examined_rows); - tab->records=table->sort.found_records; // For SQL_CALC_ROWS - delete select; // filesort did select - tab->select=0; + tab->records=table->sort.found_records; // For SQL_CALC_ROWS + if (select) + { + select->cleanup(); // filesort did select + tab->select= 0; + } tab->select_cond=0; tab->type=JT_ALL; // Read with normal read_record tab->read_first_record= join_init_read_record; From 04675623d691f539b25ac95b76425477f7a448d9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Feb 2004 18:58:10 +0400 Subject: [PATCH 07/36] code and comments cleanup --- sql/item_func.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sql/item_func.cc b/sql/item_func.cc index f90fcd5149e..e49980af733 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2648,10 +2648,9 @@ longlong Item_func_inet_aton::val_int() } if (c != '.') // IP number can't end on '.' { - switch (dot_count) - { - case 1: result<<= 8; - case 2: result<<= 8; + switch (dot_count) { + case 1: result<<= 8; /* fall through */ + case 2: result<<= 8; /* fall through */ } return (result << 8) + (ulonglong) byte_result; } From faa8a41b1db57e643617eda8c49803f6e1287f87 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 6 Feb 2004 16:59:25 +0400 Subject: [PATCH 08/36] Problem fix: http://bugs.mysql.com/bug.php?id=2366 Wrong utf8 behaviour when data is trancated --- include/m_ctype.h | 4 +++ mysql-test/r/ctype_mb.result | 2 +- mysql-test/r/ctype_utf8.result | 10 ++++++- mysql-test/t/ctype_utf8.test | 7 +++++ sql/field.cc | 48 +++++++++++++++++++--------------- sql/item_strfunc.h | 3 ++- sql/item_timefunc.cc | 5 ++-- strings/ctype-big5.c | 1 + strings/ctype-bin.c | 1 + strings/ctype-euc_kr.c | 1 + strings/ctype-gb2312.c | 1 + strings/ctype-gbk.c | 1 + strings/ctype-latin1.c | 1 + strings/ctype-mb.c | 16 ++++++++++++ strings/ctype-simple.c | 10 +++++++ strings/ctype-sjis.c | 1 + strings/ctype-tis620.c | 7 +++-- strings/ctype-ucs2.c | 12 +++++++++ strings/ctype-ujis.c | 1 + strings/ctype-utf8.c | 1 + 20 files changed, 105 insertions(+), 28 deletions(-) diff --git a/include/m_ctype.h b/include/m_ctype.h index 4a9415f43f9..88c3418fc0d 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -144,6 +144,8 @@ typedef struct my_charset_handler_st int (*mbcharlen)(struct charset_info_st *, uint); uint (*numchars)(struct charset_info_st *, const char *b, const char *e); uint (*charpos)(struct charset_info_st *, const char *b, const char *e, uint pos); + uint (*wellformedlen)(struct charset_info_st *, + const char *b,const char *e, uint nchars); uint (*lengthsp)(struct charset_info_st *, const char *ptr, uint length); /* Unicode convertion */ @@ -311,6 +313,7 @@ int my_wildcmp_8bit(CHARSET_INFO *, uint my_numchars_8bit(CHARSET_INFO *, const char *b, const char *e); uint my_charpos_8bit(CHARSET_INFO *, const char *b, const char *e, uint pos); +uint my_wellformedlen_8bit(CHARSET_INFO *, const char *b, const char *e, uint pos); int my_mbcharlen_8bit(CHARSET_INFO *, uint c); @@ -327,6 +330,7 @@ int my_wildcmp_mb(CHARSET_INFO *, int escape, int w_one, int w_many); uint my_numchars_mb(CHARSET_INFO *, const char *b, const char *e); uint my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, uint pos); +uint my_wellformedlen_mb(CHARSET_INFO *, const char *b, const char *e, uint pos); uint my_instr_mb(struct charset_info_st *, const char *b, uint b_length, const char *s, uint s_length, diff --git a/mysql-test/r/ctype_mb.result b/mysql-test/r/ctype_mb.result index 288033e7530..edccb047c85 100644 --- a/mysql-test/r/ctype_mb.result +++ b/mysql-test/r/ctype_mb.result @@ -22,7 +22,7 @@ Warning 1264 Data truncated for column 'c2' at row 1 Warning 1264 Data truncated for column 'c3' at row 1 SELECT * FROM t1; c1 c2 c3 -aaaabbbbcccc aaaabbbbcccc aaaabbbbcccc +aaaa aaaa aaaa DROP TABLE t1; CREATE TABLE t1 (a CHAR(4) CHARACTER SET utf8, KEY key_a(a(3))); SHOW CREATE TABLE t1; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 7c05b1ea446..31f26c421b6 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -73,9 +73,17 @@ create table t1 select date_format("2004-01-19 10:10:10", "%Y-%m-%d"); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `date_format("2004-01-19 10:10:10", "%Y-%m-%d")` char(4) character set utf8 default NULL + `date_format("2004-01-19 10:10:10", "%Y-%m-%d")` char(10) character set utf8 default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select * from t1; date_format("2004-01-19 10:10:10", "%Y-%m-%d") 2004-01-19 drop table t1; +set names koi8r; +create table t1 (s1 char(1) character set utf8); +insert into t1 values (_koi8r'ÁÂ'); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +select s1,hex(s1),char_length(s1),octet_length(s1) from t1; +s1 hex(s1) char_length(s1) octet_length(s1) +Á D0B0 1 2 diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 5e9324dd68f..c2ea1ed20a4 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -53,3 +53,10 @@ show create table t1; select * from t1; drop table t1; +# +# Bug #2366 Wrong utf8 behaviour when data is trancated +# +set names koi8r; +create table t1 (s1 char(1) character set utf8); +insert into t1 values (_koi8r'ÁÂ'); +select s1,hex(s1),char_length(s1),octet_length(s1) from t1; diff --git a/sql/field.cc b/sql/field.cc index 9f25b770ab0..57b77693275 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4060,6 +4060,8 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) int error= 0; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); + uint copy_length; + /* Convert character set if nesessary */ if (String::needs_conversion(from, length, cs, field_charset)) { @@ -4067,27 +4069,31 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) from= tmpstr.ptr(); length= tmpstr.length(); } - if (length <= field_length) - { - memcpy(ptr,from,length); - if (length < field_length) - field_charset->cset->fill(field_charset,ptr+length,field_length-length, - ' '); - } - else - { - memcpy(ptr,from,field_length); - if (current_thd->count_cuted_fields) - { // Check if we loosed some info - const char *end=from+length; - from+= field_length; - from+= field_charset->cset->scan(field_charset, from, end, - MY_SEQ_SPACES); - if (from != end) - { - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - error=1; - } + + /* + Make sure we don't break a multybite sequence + as well as don't copy a malformed data. + */ + copy_length= field_charset->cset->wellformedlen(field_charset, + from,from+length, + field_length/ + field_charset->mbmaxlen); + memcpy(ptr,from,copy_length); + if (copy_length < field_length) // Append spaces if shorter + field_charset->cset->fill(field_charset,ptr+copy_length, + field_length-copy_length,' '); + + + if (current_thd->count_cuted_fields && (copy_length < length)) + { // Check if we loosed some info + const char *end=from+length; + from+= copy_length; + from+= field_charset->cset->scan(field_charset, from, end, + MY_SEQ_SPACES); + if (from != end) + { + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); + error=1; } } return error; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index fd0afb19726..465300e721e 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -518,7 +518,8 @@ public: void fix_length_and_dec() { collation.set(default_charset()); - decimals=0; max_length=args[0]->max_length*2; + decimals=0; + max_length=args[0]->max_length*2*collation.collation->mbmaxlen; } }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index ed5b9ecc0db..062e7fc7b44 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1286,12 +1286,13 @@ void Item_func_date_format::fix_length_and_dec() if (args[1]->type() == STRING_ITEM) { // Optimize the normal case fixed_length=1; - max_length=format_length(((Item_string*) args[1])->const_string()); + max_length= format_length(((Item_string*) args[1])->const_string())* + collation.collation->mbmaxlen; } else { fixed_length=0; - max_length=args[1]->max_length*10; + max_length=args[1]->max_length*10*collation.collation->mbmaxlen; set_if_smaller(max_length,MAX_BLOB_WIDTH); } maybe_null=1; // If wrong date diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 8d4081fb2aa..574156a99ed 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6245,6 +6245,7 @@ static MY_CHARSET_HANDLER my_charset_big5_handler= mbcharlen_big5, my_numchars_mb, my_charpos_mb, + my_wellformedlen_mb, my_lengthsp_8bit, my_mb_wc_big5, /* mb_wc */ my_wc_mb_big5, /* wc_mb */ diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 43575bbc277..fc22938d46e 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -347,6 +347,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mbcharlen_8bit, /* mbcharlen */ my_numchars_8bit, my_charpos_8bit, + my_wellformedlen_8bit, my_lengthsp_8bit, my_mb_wc_bin, my_wc_mb_bin, diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index 366a5d500ed..278e8529e83 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -8653,6 +8653,7 @@ static MY_CHARSET_HANDLER my_charset_handler= mbcharlen_euc_kr, my_numchars_mb, my_charpos_mb, + my_wellformedlen_mb, my_lengthsp_8bit, my_mb_wc_euc_kr, /* mb_wc */ my_wc_mb_euc_kr, /* wc_mb */ diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index 44a58b2b906..722f00f0f7a 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -5704,6 +5704,7 @@ static MY_CHARSET_HANDLER my_charset_handler= mbcharlen_gb2312, my_numchars_mb, my_charpos_mb, + my_wellformedlen_mb, my_lengthsp_8bit, my_mb_wc_gb2312, /* mb_wc */ my_wc_mb_gb2312, /* wc_mb */ diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index 5475c3bd363..9e71a18e531 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -9900,6 +9900,7 @@ static MY_CHARSET_HANDLER my_charset_handler= mbcharlen_gbk, my_numchars_mb, my_charpos_mb, + my_wellformedlen_mb, my_lengthsp_8bit, my_mb_wc_gbk, my_wc_mb_gbk, diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index c00ded21575..933737b5f61 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -180,6 +180,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mbcharlen_8bit, my_numchars_8bit, my_charpos_8bit, + my_wellformedlen_8bit, my_lengthsp_8bit, my_mb_wc_latin1, my_wc_mb_latin1, diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index b5e8c4598a0..377bf311d38 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -274,6 +274,22 @@ uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)), return pos ? e+2-b0 : b-b0; } +uint my_wellformedlen_mb(CHARSET_INFO *cs __attribute__((unused)), + const char *b, const char *e, uint pos) +{ + uint mblen; + const char *b0=b; + + while (pos && b Date: Sat, 7 Feb 2004 00:57:22 +0400 Subject: [PATCH 09/36] 1. fixed bug @2593 "SHOW CREATE TABLE doesn't properly double quotes" 2. added automatic quotation of keywords in SHOW CREATE TABLE mysql-test/r/show_check.result: added tests for bug #2593 "SHOW CREATE TABLE doesn't properly double quotas" and for automatic quotation of keywords mysql-test/t/show_check.test: added tests for bug #2593 "SHOW CREATE TABLE doesn't properly double quotas" and for automatic quotation of keywords sql/mysql_priv.h: added declaration of function is_keyword sql/sql_lex.cc: added implementation of function is_keyword sql/sql_show.cc: changed function append_identifier and it's subfunctions 1. fixed bug @2593 "SHOW CREATE TABLE doesn't properly double quotes" 2. added automatic quotation of keywords --- mysql-test/r/show_check.result | 48 +++++++++++++++++++++++++ mysql-test/t/show_check.test | 40 +++++++++++++++++++++ sql/mysql_priv.h | 2 ++ sql/sql_lex.cc | 18 +++++++++- sql/sql_show.cc | 65 +++++++++++++++++++++++++++++++--- 5 files changed, 168 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 290f916ae72..235c6cd0ecf 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -265,3 +265,51 @@ c decimal(4,3) YES NULL d double(4,3) YES NULL f float(4,3) YES NULL drop table t1; +SET sql_mode=''; +SET sql_quote_show_create=OFF; +CREATE TABLE ```ab``cd``` (i INT); +SHOW CREATE TABLE ```ab``cd```; +Table Create Table +`ab`cd` CREATE TABLE ```ab``cd``` ( + i int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE ```ab``cd```; +CREATE TABLE ```ab````cd``` (i INT); +SHOW CREATE TABLE ```ab````cd```; +Table Create Table +`ab``cd` CREATE TABLE ```ab````cd``` ( + i int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE ```ab````cd```; +CREATE TABLE ```a` (i INT); +SHOW CREATE TABLE ```a`; +Table Create Table +`a CREATE TABLE ```a` ( + i int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE ```a`; +SET sql_mode='ANSI_QUOTES'; +CREATE TABLE """a" (i INT); +SHOW CREATE TABLE """a"; +Table Create Table +"a CREATE TABLE """a" ( + i int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE """a"; +SET sql_mode=''; +SET sql_quote_show_create=OFF; +CREATE TABLE t1 (i INT); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE t1 ( + i int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE `table` (i INT); +SHOW CREATE TABLE `table`; +Table Create Table +table CREATE TABLE `table` ( + i int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE `table`; +SET sql_quote_show_create=ON; diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index d262f02c978..1d64cfd2105 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -142,3 +142,43 @@ drop table t1; create table t1 (c decimal(3,3), d double(3,3), f float(3,3)); show columns from t1; drop table t1; + +# +# Test for Bug #2593 "SHOW CREATE TABLE doesn't properly double quotes" +# + +SET sql_mode=''; +SET sql_quote_show_create=OFF; + +CREATE TABLE ```ab``cd``` (i INT); +SHOW CREATE TABLE ```ab``cd```; +DROP TABLE ```ab``cd```; + +CREATE TABLE ```ab````cd``` (i INT); +SHOW CREATE TABLE ```ab````cd```; +DROP TABLE ```ab````cd```; + +CREATE TABLE ```a` (i INT); +SHOW CREATE TABLE ```a`; +DROP TABLE ```a`; + +SET sql_mode='ANSI_QUOTES'; + +CREATE TABLE """a" (i INT); +SHOW CREATE TABLE """a"; +DROP TABLE """a"; + +# to test quotes around keywords.. : + +SET sql_mode=''; +SET sql_quote_show_create=OFF; + +CREATE TABLE t1 (i INT); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE `table` (i INT); +SHOW CREATE TABLE `table`; +DROP TABLE `table`; + +SET sql_quote_show_create=ON; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 35740ff8bf1..ef825374301 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -759,6 +759,8 @@ uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match); uint check_word(TYPELIB *lib, const char *val, const char *end, const char **end_of_word); +bool is_keyword(const char *name, uint len); + /* sql_parse.cc */ void free_items(Item *item); void cleanup_items(Item *item); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 65c958093bd..b7a8ffa8433 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -181,6 +181,23 @@ static int find_keyword(LEX *lex, uint len, bool function) return 0; } +/* + Check if name is a keyword + + SYNOPSIS + is_keyword() + name checked name + len length of checked name + + RETURN VALUES + 0 name is a keyword + 1 name isn't a keyword +*/ + +bool is_keyword(const char *name, uint len) +{ + return get_hash_symbol(name,len,0)!=0; +} /* make a copy of token before ptr and set yytoklen */ @@ -420,7 +437,6 @@ inline static uint int_token(const char *str,uint length) return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger; } - /* yylex remember the following states from the following yylex() diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 3b937f97089..5870e58d9a4 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1086,7 +1086,6 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) DBUG_RETURN(0); } -/* possible TODO: call find_keyword() from sql_lex.cc here */ static bool require_quotes(const char *name, uint length) { uint i, d, c; @@ -1100,17 +1099,47 @@ static bool require_quotes(const char *name, uint length) return 0; } +/* + Looking for char in multibyte string + + SYNOPSIS + look_for_char() + name string for looking at + length length of name + q '\'' or '\"' for looking for + + RETURN VALUES + # pointer to found char in string + 0 string doesn't contain required char +*/ + +static const char *look_for_char(const char *name, uint length, char q) +{ + const char *cur= name; + const char *end= cur+length; + uint symbol_length; + for (; curvariables.sql_mode & MODE_ANSI_QUOTES) qtype= '\"'; else qtype= '`'; - if ((thd->options & OPTION_QUOTE_SHOW_CREATE) || - require_quotes(name, length)) + if (is_keyword(name,length)) { packet->append(&qtype, 1); packet->append(name, length, system_charset_info); @@ -1118,7 +1147,35 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) } else { - packet->append(name, length, system_charset_info); + if (!require_quotes(name, length)) + { + if (!(thd->options & OPTION_QUOTE_SHOW_CREATE)) + packet->append(name, length, system_charset_info); + else + { + packet->append(&qtype, 1); + packet->append(name, length, system_charset_info); + packet->append(&qtype, 1); + } + } + else + { + packet->append(&qtype, 1); + qplace= look_for_char(name,length,qtype); + while (qplace) + { + if ((part_len= qplace-name)) + { + packet->append(name, part_len, system_charset_info); + length-= part_len; + } + packet->append(qplace, 1, system_charset_info); + name= qplace; + qplace= look_for_char(name+1,length-1,qtype); + } + packet->append(name, length, system_charset_info); + packet->append(&qtype, 1); + } } } From a54adfc3ab4d6fcb20570202d33495e2b6ffd613 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 7 Feb 2004 02:22:12 +0400 Subject: [PATCH 10/36] fixed bug #2592 mysqldump doesn't quote "tricky" names correctly mysql-test/r/mysqldump.result: added test for bug #2592 mysqldump doesn't quote "tricky" names correctly please note, output's still looking wrong because of bug #2593 it will be fixed when fix for bug #2593 will be pushed mysql-test/t/mysqldump.test: added test for bug #2592 mysqldump doesn't quote "tricky" names correctly sql/sql_lex.cc: fixed processing of multibyte quoted variables --- client/mysqldump.c | 4 ++-- mysql-test/r/mysqldump.result | 18 ++++++++++++++++++ mysql-test/t/mysqldump.test | 8 ++++++++ sql/sql_lex.cc | 30 +++++++++++++++++++----------- 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 921ffbaab5b..74799ff4845 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -649,7 +649,7 @@ static char *quote_name(const char *name, char *buff, my_bool force) while (*name) { if (*name == QUOTE_CHAR) - *to= QUOTE_CHAR; + *to++= QUOTE_CHAR; *to++= *name++; } to[0]=QUOTE_CHAR; @@ -1647,7 +1647,7 @@ static int dump_all_tables_in_db(char *database) if (opt_xml) fputs("\n", md_result_file); if (lock_tables) - mysql_query(sock,"UNLOCK_TABLES"); + mysql_query(sock,"UNLOCK TABLES"); return 0; } /* dump_all_tables_in_db */ diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index f51caee39d6..651a33ac1db 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -123,3 +123,21 @@ UNLOCK TABLES; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; DROP TABLE t1; +create table ```a` (i int); +DROP TABLE IF EXISTS ```a`; +CREATE TABLE ``a` ( + `i` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE ```a` DISABLE KEYS */; +LOCK TABLES ```a` WRITE; +UNLOCK TABLES; +/*!40000 ALTER TABLE ```a` ENABLE KEYS */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; + +drop table ```a`; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 93b0dd4a75d..e6115b61bbf 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -53,3 +53,11 @@ CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'); --exec $MYSQL_DUMP --skip-comments test t1 DROP TABLE t1; + +# +# Bug #2592 +# + +create table ```a` (i int); +--exec $MYSQL_DUMP --skip-comments test +drop table ```a`; \ No newline at end of file diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 65c958093bd..017b5677ced 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -667,13 +667,24 @@ int yylex(void *arg, void *yythd) case MY_LEX_USER_VARIABLE_DELIMITER: { - char delim= c; // Used char + uint double_quotes= 0; + char quote_char= c; // Used char lex->tok_start=lex->ptr; // Skip first ` #ifdef USE_MB if (use_mb(cs)) { - while ((c=yyGet()) && c != delim && c != (uchar) NAMES_SEP_CHAR) + while ((c= yyGet())) { + if (c == quote_char) + { + if (yyPeek() != quote_char) + break; + c= yyGet(); + double_quotes++; + continue; + } + if (c == (uchar) NAMES_SEP_CHAR) + break; if (my_mbcharlen(cs, c) > 1) { int l; @@ -684,13 +695,10 @@ int yylex(void *arg, void *yythd) lex->ptr += l-1; } } - yylval->lex_str=get_token(lex,yyLength()); } else #endif { - uint double_quotes= 0; - char quote_char= c; while ((c=yyGet())) { if (c == quote_char) @@ -704,13 +712,13 @@ int yylex(void *arg, void *yythd) if (c == (uchar) NAMES_SEP_CHAR) break; } - if (double_quotes) - yylval->lex_str=get_quoted_token(lex,yyLength() - double_quotes, - quote_char); - else - yylval->lex_str=get_token(lex,yyLength()); } - if (c == delim) + if (double_quotes) + yylval->lex_str=get_quoted_token(lex,yyLength() - double_quotes, + quote_char); + else + yylval->lex_str=get_token(lex,yyLength()); + if (c == quote_char) yySkip(); // Skip end ` lex->next_state= MY_LEX_START; return(IDENT_QUOTED); From 35b1f5445056951dda823b6ec4ee6f06ca612714 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 Feb 2004 12:31:03 +0100 Subject: [PATCH 11/36] Added --compact to mysqlbinlog Fixed output from mysqlbinlog when using --skip-comments Fixed warnings from valgrind Fixed ref_length when used with HEAP tables More efficent need_conversion() Fixed error handling in UPDATE with not updateable tables Fixed bug in null handling in CAST to signed/unsigned client/client_priv.h: cleanup & added OPT_COMPACT client/mysqldump.c: Added option --compact to get a compact readable dump. Ensure that SET CHARACTER_SET_CLIENT is not done if we have not remembered the old character set Print optimization comments even if --skip-comments are given as these are not true comments. (Before these where only printed at end, which was a bug) mysql-test/r/cast.result: More cast tests mysql-test/r/derived.result: Removed warnings mysql-test/r/mysqldump.result: Update results after fixing mysqlbinlog mysql-test/r/query_cache.result: Make test usable with --extern more tests mysql-test/r/rpl_until.result: Make test repeatable under valgrind mysql-test/r/sql_mode.result: Fix test result mysql-test/r/subselect.result: Make test smaller. Update wrong results mysql-test/t/cast.test: More cast tests mysql-test/t/derived.test: Removed warnings mysql-test/t/query_cache.test: Make test usable with --extern more tests mysql-test/t/rpl_until.test: fix for valgrind. Becasue of unknown reason one got 'Slave_SQL_Running=yes' in this setup mysql-test/t/subselect.test: Make test case smaller sql/field.cc: Updated need_conversion() to use new arguments sql/ha_heap.cc: Moved initialization of ref_length to right place. This fixed problem that we had a ref_length of 8 for heap tables, which was not efficent. sql/item_func.cc: Cleanup sql/item_func.h: Fixed bug in null_handling for cast to signed/unsigned sql/item_strfunc.cc: Optimized/cleaned up Item_func_conv_charset3 sql/item_sum.cc: Cleanup. Ensure that some flag variables are cleared in cleanup() sql/item_sum.h: Fixed references to uninitialized memory sql/opt_range.cc: Fixed spelling error sql/sql_class.cc: Fixed wrong return code, which could case protocol problems sql/sql_class.h: After merge fix sql/sql_prepare.cc: Added comments sql/sql_show.cc: Cleanup sql/sql_string.cc: Optimzed usage of need_conversion(). - Removed not used argument - Save diff lenght in 'offset' to not have to recalculate length several times. Cleaned up comment Optimized copy_aligned() based on the knowledge that it's only called when you have wrong data sql/sql_string.h: Updated need_conversion() and copy_aligned() to use new arguments sql/sql_update.cc: Fixed error handling with non-updateable tables sql/sql_yacc.yy: Ensure that lex->lock_options are set correctly (to get rid of warnings from valgrind) Ensure that cast_type sets lex->charset and lex->length. Without these CONVERT() didn't work properly --- client/client_priv.h | 33 +++++---- client/mysqldump.c | 47 ++++++++----- mysql-test/r/cast.result | 27 ++++++++ mysql-test/r/derived.result | 8 +-- mysql-test/r/mysqldump.result | 23 ++++++- mysql-test/r/query_cache.result | 9 ++- mysql-test/r/rpl_until.result | 2 +- mysql-test/r/sql_mode.result | 2 +- mysql-test/r/subselect.result | 68 +++++++----------- mysql-test/t/cast.test | 9 +++ mysql-test/t/derived.test | 4 +- mysql-test/t/query_cache.test | 8 ++- mysql-test/t/rpl_until.test | 5 +- mysql-test/t/subselect.test | 64 +++++------------ sql/field.cc | 20 ++++-- sql/ha_heap.cc | 2 +- sql/item_func.cc | 5 +- sql/item_func.h | 20 ++++-- sql/item_strfunc.cc | 60 ++++------------ sql/item_sum.cc | 18 ++++- sql/item_sum.h | 7 +- sql/opt_range.cc | 2 +- sql/sql_class.cc | 2 +- sql/sql_class.h | 4 -- sql/sql_prepare.cc | 2 + sql/sql_show.cc | 3 +- sql/sql_string.cc | 118 ++++++++++++++++++-------------- sql/sql_string.h | 8 ++- sql/sql_update.cc | 3 + sql/sql_yacc.yy | 28 ++++---- 30 files changed, 327 insertions(+), 284 deletions(-) diff --git a/client/client_priv.h b/client/client_priv.h index f6d766b7ef9..910de1f03e9 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -26,18 +26,21 @@ /* We have to define 'enum options' identical in all files to keep OS2 happy */ -enum options_client { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET, - OPT_PAGER, OPT_NOPAGER, OPT_TEE, OPT_NOTEE, - OPT_LOW_PRIORITY, OPT_AUTO_REPAIR, OPT_COMPRESS, - OPT_DROP, OPT_LOCKS, OPT_KEYWORDS, OPT_DELAYED, OPT_OPTIMIZE, - OPT_FTB, OPT_LTB, OPT_ENC, OPT_O_ENC, OPT_ESC, OPT_TABLES, - OPT_MASTER_DATA, OPT_AUTOCOMMIT, OPT_AUTO_REHASH, - OPT_LINE_NUMBERS, OPT_COLUMN_NAMES, OPT_CONNECT_TIMEOUT, - OPT_MAX_ALLOWED_PACKET, OPT_NET_BUFFER_LENGTH, - OPT_SELECT_LIMIT, OPT_MAX_JOIN_SIZE, OPT_SSL_SSL, - OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH, - OPT_SSL_CIPHER, OPT_SHUTDOWN_TIMEOUT, OPT_LOCAL_INFILE, - OPT_DELETE_MASTER_LOGS, - OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL, - OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM, OPT_SKIP_OPTIMIZATION, - OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH }; +enum options_client +{ + OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET, + OPT_PAGER, OPT_NOPAGER, OPT_TEE, OPT_NOTEE, + OPT_LOW_PRIORITY, OPT_AUTO_REPAIR, OPT_COMPRESS, + OPT_DROP, OPT_LOCKS, OPT_KEYWORDS, OPT_DELAYED, OPT_OPTIMIZE, + OPT_FTB, OPT_LTB, OPT_ENC, OPT_O_ENC, OPT_ESC, OPT_TABLES, + OPT_MASTER_DATA, OPT_AUTOCOMMIT, OPT_AUTO_REHASH, + OPT_LINE_NUMBERS, OPT_COLUMN_NAMES, OPT_CONNECT_TIMEOUT, + OPT_MAX_ALLOWED_PACKET, OPT_NET_BUFFER_LENGTH, + OPT_SELECT_LIMIT, OPT_MAX_JOIN_SIZE, OPT_SSL_SSL, + OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH, + OPT_SSL_CIPHER, OPT_SHUTDOWN_TIMEOUT, OPT_LOCAL_INFILE, + OPT_DELETE_MASTER_LOGS, OPT_COMPACT, + OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL, + OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM, OPT_SKIP_OPTIMIZATION, + OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH, +}; diff --git a/client/mysqldump.c b/client/mysqldump.c index 921ffbaab5b..0025968ae5b 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -81,7 +81,7 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick= 1, extended_insert= 1, opt_alldbs=0,opt_create_db=0,opt_first_slave=0,opt_set_names=0, opt_autocommit=0,opt_master_data,opt_disable_keys=1,opt_xml=0, opt_delete_master_logs=0, tty_password=0, - opt_single_transaction=0, opt_comments= 0; + opt_single_transaction=0, opt_comments= 0, opt_compact= 0; static MYSQL mysql_connection,*sock=0; static char insert_pat[12 * 1024],*opt_password=0,*current_user=0, *current_host=0,*path=0,*fields_terminated=0, @@ -140,6 +140,10 @@ static struct my_option my_long_options[] = "Change the dump to be compatible with a given mode. By default tables are dumped without any restrictions. Legal modes are: ansi, mysql323, mysql40, postgresql, oracle, mssql, db2, maxdb, no_key_options, no_table_options, no_field_options. One can use several modes separated by commas. Note: Requires MySQL server version 4.1.0 or higher. This option does a no operation on earlier server versions.", (gptr*) &opt_compatible_mode_str, (gptr*) &opt_compatible_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"compact", OPT_COMPACT, + "Give less verbose output (useful for debugging). Disables structure comments and header/footer constructs. Enables options --skip-add-drop-table --no-set-names --skip-disable-keys --skip-lock-tables", + (gptr*) &opt_compact, (gptr*) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + 0, 0}, {"complete-insert", 'c', "Use complete insert statements.", (gptr*) &cFlag, (gptr*) &cFlag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use compression in server/client protocol.", @@ -347,15 +351,19 @@ static void write_header(FILE *sql_file, char *db_name) fputs("\n", sql_file); fputs("\n", sql_file); } - else if (opt_comments) + else if (!opt_compact) { - fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION); - fprintf(sql_file, "-- Host: %s Database: %s\n", - current_host ? current_host : "localhost", db_name ? db_name : ""); - fputs("-- ------------------------------------------------------\n", - sql_file); - fprintf(sql_file, "-- Server version\t%s\n", - mysql_get_server_info(&mysql_connection)); + if (opt_comments) + { + fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION); + fprintf(sql_file, "-- Host: %s Database: %s\n", + current_host ? current_host : "localhost", db_name ? db_name : + ""); + fputs("-- ------------------------------------------------------\n", + sql_file); + fprintf(sql_file, "-- Server version\t%s\n", + mysql_get_server_info(&mysql_connection)); + } if (!opt_set_names) fprintf(sql_file,"\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=%s */;\n",default_charset); fprintf(md_result_file,"\ @@ -371,17 +379,18 @@ static void write_header(FILE *sql_file, char *db_name) static void write_footer(FILE *sql_file) { if (opt_xml) - fputs("", sql_file); - else + fputs("\n", sql_file); + else if (!opt_compact) { fprintf(md_result_file,"\n\ /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n\ /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n\ -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n\ -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n\ -"); +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n"); + if (!opt_set_names) + fprintf(md_result_file, + "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"); + fputs("\n", sql_file); } - fputs("\n", sql_file); } /* write_footer */ @@ -448,6 +457,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), extended_insert= opt_drop= opt_lock= quick= create_options= opt_disable_keys= lock_tables= 0; break; + case (int) OPT_COMPACT: + if (opt_compact) + { + opt_comments= opt_drop= opt_disable_keys= opt_lock= 0; + opt_set_names= 1; + } case (int) OPT_TABLES: opt_databases=0; break; @@ -1270,7 +1285,7 @@ static void dumpTable(uint numFields, char *table) fprintf(md_result_file,"-- WHERE: %s\n",where); strxmov(strend(query), " WHERE ",where,NullS); } - if (!opt_xml) + if (!opt_xml && !opt_compact) fputs("\n", md_result_file); if (mysql_query(sock, query)) { diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index 893452290b2..c60d8e19fb4 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -24,6 +24,12 @@ Note 1003 select high_priority ~(5) AS `~5`,cast(~(5) as signed) AS `cast(~5 as select cast(5 as unsigned) -6.0; cast(5 as unsigned) -6.0 -1.0 +select cast(NULL as signed), cast(1/0 as signed); +cast(NULL as signed) cast(1/0 as signed) +NULL NULL +select cast(NULL as unsigned), cast(1/0 as unsigned); +cast(NULL as unsigned) cast(1/0 as unsigned) +NULL NULL select cast("A" as binary) = "a", cast(BINARY "a" as CHAR) = "A"; cast("A" as binary) = "a" cast(BINARY "a" as CHAR) = "A" 0 1 @@ -36,6 +42,21 @@ cast("1:2:3" as TIME) select CONVERT("2004-01-22 21:45:33",DATE); CONVERT("2004-01-22 21:45:33",DATE) 2004-01-22 +select CONVERT(DATE "2004-01-22 21:45:33" USING latin1); +CONVERT(DATE "2004-01-22 21:45:33" USING latin1) +2004-01-22 21:45:33 +select CONVERT(DATE "2004-01-22 21:45:33",CHAR); +CONVERT(DATE "2004-01-22 21:45:33",CHAR) +2004-01-22 21:45:33 +select CONVERT(DATE "2004-01-22 21:45:33",CHAR(4)); +CONVERT(DATE "2004-01-22 21:45:33",CHAR(4)) +2004 +select CONVERT(DATE "2004-01-22 21:45:33",CHAR(4) BINARY); +CONVERT(DATE "2004-01-22 21:45:33",CHAR(4) BINARY) +2004 +select CAST(DATE "2004-01-22 21:45:33" AS CHAR(4) BINARY); +CAST(DATE "2004-01-22 21:45:33" AS CHAR(4) BINARY) +2004 set names binary; select cast(_latin1'test' as char character set latin2); cast(_latin1'test' as char character set latin2) @@ -43,6 +64,12 @@ test select cast(_koi8r'ÔÅÓÔ' as char character set cp1251); cast(_koi8r'ÔÅÓÔ' as char character set cp1251) òåñò +select convert(_latin1'test', "latin1_german1_ci", "latin1_swedish_ci"); +convert(_latin1'test', "latin1_german1_ci", "latin1_swedish_ci") +test +select convert(_koi8r'ÔÅÓÔ', "koi8r_general_ci", "cp1251_general_ci"); +convert(_koi8r'ÔÅÓÔ', "koi8r_general_ci", "cp1251_general_ci") +òåñò create table t1 select cast(_koi8r'ÔÅÓÔ' as char character set cp1251) as t; show create table t1; Table Create Table diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 170c393524b..44d35148f87 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -252,9 +252,7 @@ drop table t1; CREATE TABLE `t1` ( `N` int(11) unsigned NOT NULL default '0', `M` tinyint(1) default '0', -) TYPE=MyISAM DEFAULT CHARSET=latin1; -Warnings: -Warning 1286 'TYPE=storage_engine' is deprecated. Use 'ENGINE=storage_engine' instead. +) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `t1` (N, M) VALUES (1, 0),(1, 0),(1, 0),(2, 0),(2, 0),(3, 0); UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2; select * from t1; @@ -279,9 +277,7 @@ OBJECTID int(11) NOT NULL default '0', SORTORDER int(11) NOT NULL auto_increment, KEY t1_SortIndex (SORTORDER), KEY t1_IdIndex (OBJECTID) -) TYPE=MyISAM DEFAULT CHARSET=latin1; -Warnings: -Warning 1286 'TYPE=storage_engine' is deprecated. Use 'ENGINE=storage_engine' instead. +) ENGINE=MyISAM DEFAULT CHARSET=latin1; CREATE TABLE t2 ( ID int(11) default NULL, PARID int(11) default NULL, diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index bdcdb0532f7..0414d6fa738 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -21,6 +21,11 @@ DROP TABLE t1; CREATE TABLE t1 (a decimal(240, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */; DROP TABLE IF EXISTS `t1`; CREATE TABLE `t1` ( `a` decimal(240,20) default NULL @@ -41,6 +46,11 @@ UNLOCK TABLES; DROP TABLE t1; CREATE TABLE t1 (a double); INSERT INTO t1 VALUES (-9e999999); + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */; DROP TABLE IF EXISTS `t1`; CREATE TABLE `t1` ( `a` double default NULL @@ -105,6 +115,11 @@ INSERT INTO t1 VALUES ("1\""), ("\"2"); DROP TABLE t1; CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'); + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */; DROP TABLE IF EXISTS `t1`; CREATE TABLE `t1` ( `a` varchar(255) default NULL @@ -125,6 +140,9 @@ UNLOCK TABLES; DROP TABLE t1; CREATE TABLE t1 (a int) ENGINE=MYISAM; INSERT INTO t1 VALUES (1), (2); +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */; DROP TABLE IF EXISTS `t1`; CREATE TABLE `t1` ( `a` int(11) default NULL @@ -140,8 +158,10 @@ UNLOCK TABLES; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */; DROP TABLE IF EXISTS `t1`; CREATE TABLE `t1` ( `a` int(11) default NULL @@ -157,6 +177,5 @@ UNLOCK TABLES; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; DROP TABLE t1; diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 49ae082dead..04bcb56d48d 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -696,17 +696,22 @@ word show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 1 -load data infile '../../std_data/words.dat' into table t1; +load data infile 'TEST_DIR/std_data/words.dat' into table t1; show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 +select count(*) from t1; +count(*) +70 drop table t1; create table t1 (a int); insert into t1 values (1),(2),(3); show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 -select * from t1 into outfile "query_caceh.out.file"; +select * from t1 into outfile "query_cache.out.file"; +select * from t1 into outfile "query_cache.out.file"; +ERROR HY000: File 'query_cache.out.file' already exists select * from t1 limit 1 into dumpfile "query_cache.dump.file"; show status like "Qcache_queries_in_cache"; Variable_name Value diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result index 82b1ed233ec..cb60ccfb1c9 100644 --- a/mysql-test/r/rpl_until.result +++ b/mysql-test/r/rpl_until.result @@ -55,7 +55,7 @@ stop slave; start slave until master_log_file='master-bin.000001', master_log_pos=561; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 # master-bin.000001 Yes No 0 0 561 # Master master-bin.000001 561 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 # master-bin.000001 Yes # 0 0 561 # Master master-bin.000001 561 No # start slave until master_log_file='master-bin', master_log_pos=561; ERROR HY000: Wrong parameter or combination of parameters for START SLAVE UNTIL start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12; diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index ddc848af1ed..77fe5d06bb0 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -70,7 +70,7 @@ t1 CREATE TABLE `t1` ( `email` varchar(60) NOT NULL default '', PRIMARY KEY (`a`), UNIQUE KEY `email` (`email`) -) ENGINE=HEAP ROW_FORMAT=DYNAMIC +) TYPE=HEAP ROW_FORMAT=DYNAMIC set sql_mode="postgresql,oracle,mssql,db2,maxdb"; select @@sql_mode; @@sql_mode diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index c06c9824b33..b5ebc8d80db 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1578,50 +1578,28 @@ select * from t1; a b 1 0.123 drop table t1; -CREATE TABLE t1 ( -id int(11) NOT NULL auto_increment, -ts timestamp NOT NULL, -id_cns tinyint(3) unsigned NOT NULL default '0', -id_desc_nota int(11) NOT NULL default '1', -id_publ_uff int(11) NOT NULL default '0', -tipo enum('','UNO','DUE') NOT NULL default '', -f_aggiunte set('TRE','TRETRE','QUATTRO','CINQUE','SEI','SETTE') NOT NULL -default '', -anno_dep smallint(4) unsigned zerofill NOT NULL default '0000', -data_dep smallint(4) unsigned zerofill NOT NULL default '0000', -particolare mediumint(8) unsigned NOT NULL default '0', -generale mediumint(8) unsigned NOT NULL default '0', -bis tinyint(3) unsigned NOT NULL default '0', -PRIMARY KEY(id), -UNIQUE KEY idx_cns_gen_anno (anno_dep,id_cns,generale,particolare), -UNIQUE KEY idx_cns_par_anno (id_cns,anno_dep,tipo,particolare,bis) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 PACK_KEYS=1; -INSERT INTO t1 (id, ts, id_cns, id_desc_nota, id_publ_uff, tipo, f_aggiunte, -anno_dep, data_dep, particolare, generale, bis) VALUES -(NULL, NULL, 16, 29, 622, 'UNO', '', 1987, 1218, 2048, 9681, 0), -(NULL, NULL, 50, 23, 1717, 'UNO', '', 1987, 1126, 1536, 13987, 0), -(NULL, NULL, 16, 123, 123, 'UNO', '', 1987, 1221, 2432, 14594, 0), -(NULL, NULL, 16, 124, 124, 'UNO', '', 1987, 1201, 1792, 13422, 0), -(NULL, NULL, 16, 125, 125, 'UNO', '', 1987, 0723, 1025, 10240, 0), -(NULL, NULL, 16, 126, 126, 'UNO', '', 1987, 1204, 1026, 7089, 0); -CREATE TABLE t2 ( -id tinyint(3) unsigned NOT NULL auto_increment, -descr varchar(40) NOT NULL default '', -f_servizi set('UNO','DUE') NOT NULL default '', -data_uno_min int(8) unsigned NOT NULL default '0', -data_due_min int(8) unsigned NOT NULL default '0', -max_anno_dep smallint(6) unsigned NOT NULL default '0', -data_agg int(8) unsigned NOT NULL default '0', -PRIMARY KEY (id) +CREATE TABLE `t1` ( +`id` int(11) NOT NULL auto_increment, +`id_cns` tinyint(3) unsigned NOT NULL default '0', +`tipo` enum('','UNO','DUE') NOT NULL default '', +`anno_dep` smallint(4) unsigned zerofill NOT NULL default '0000', +`particolare` mediumint(8) unsigned NOT NULL default '0', +`generale` mediumint(8) unsigned NOT NULL default '0', +`bis` tinyint(3) unsigned NOT NULL default '0', +PRIMARY KEY (`id`), +UNIQUE KEY `idx_cns_gen_anno` (`anno_dep`,`id_cns`,`generale`,`particolare`), +UNIQUE KEY `idx_cns_par_anno` (`id_cns`,`anno_dep`,`tipo`,`particolare`,`bis`) ); -INSERT INTO t2 (id, descr, f_servizi, data_uno_min, data_due_min, -max_anno_dep, data_agg) VALUES -(16, 'C_UNO', 'UNO,DUE', 19000000, 30000000, 1987, 0), -(50, 'C_TRE', 'UNO', 19000000, 30000000, 1990, 0); -SELECT cns.max_anno_dep = (SELECT s.anno_dep FROM t1 AS s WHERE -s.id_cns = cns.id ORDER BY s.anno_dep DESC LIMIT 1) AS PIPPO FROM -t2 AS cns; -PIPPO -1 -NULL +INSERT INTO `t1` VALUES (1,16,'UNO',1987,2048,9681,0),(2,50,'UNO',1987,1536,13987,0),(3,16,'UNO',1987,2432,14594,0),(4,16,'UNO',1987,1792,13422,0),(5,16,'UNO',1987,1025,10240,0),(6,16,'UNO',1987,1026,7089,0); +CREATE TABLE `t2` ( +`id` tinyint(3) unsigned NOT NULL auto_increment, +`max_anno_dep` smallint(6) unsigned NOT NULL default '0', +PRIMARY KEY (`id`) +); +INSERT INTO `t2` VALUES (16,1987),(50,1990),(51,1990); +SELECT cns.id, cns.max_anno_dep, cns.max_anno_dep = (SELECT s.anno_dep FROM t1 AS s WHERE s.id_cns = cns.id ORDER BY s.anno_dep DESC LIMIT 1) AS PIPPO FROM t2 AS cns; +id max_anno_dep PIPPO +16 1987 1 +50 1990 0 +51 1990 NULL DROP TABLE t1, t2; diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index e1cfe5760ee..ab0242990fc 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -10,10 +10,17 @@ select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1; select ~5, cast(~5 as signed); explain extended select ~5, cast(~5 as signed); select cast(5 as unsigned) -6.0; +select cast(NULL as signed), cast(1/0 as signed); +select cast(NULL as unsigned), cast(1/0 as unsigned); select cast("A" as binary) = "a", cast(BINARY "a" as CHAR) = "A"; select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME); select cast("1:2:3" as TIME); select CONVERT("2004-01-22 21:45:33",DATE); +select CONVERT(DATE "2004-01-22 21:45:33" USING latin1); +select CONVERT(DATE "2004-01-22 21:45:33",CHAR); +select CONVERT(DATE "2004-01-22 21:45:33",CHAR(4)); +select CONVERT(DATE "2004-01-22 21:45:33",CHAR(4) BINARY); +select CAST(DATE "2004-01-22 21:45:33" AS CHAR(4) BINARY); # # Character set convertion @@ -21,6 +28,8 @@ select CONVERT("2004-01-22 21:45:33",DATE); set names binary; select cast(_latin1'test' as char character set latin2); select cast(_koi8r'ÔÅÓÔ' as char character set cp1251); +select convert(_latin1'test', "latin1_german1_ci", "latin1_swedish_ci"); +select convert(_koi8r'ÔÅÓÔ', "koi8r_general_ci", "cp1251_general_ci"); create table t1 select cast(_koi8r'ÔÅÓÔ' as char character set cp1251) as t; show create table t1; drop table t1; diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index 154fc4b3834..8646a98551f 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -147,7 +147,7 @@ drop table t1; CREATE TABLE `t1` ( `N` int(11) unsigned NOT NULL default '0', `M` tinyint(1) default '0', -) TYPE=MyISAM DEFAULT CHARSET=latin1; +) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `t1` (N, M) VALUES (1, 0),(1, 0),(1, 0),(2, 0),(2, 0),(3, 0); UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2; select * from t1; @@ -167,7 +167,7 @@ CREATE TABLE t1 ( SORTORDER int(11) NOT NULL auto_increment, KEY t1_SortIndex (SORTORDER), KEY t1_IdIndex (OBJECTID) -) TYPE=MyISAM DEFAULT CHARSET=latin1; +) ENGINE=MyISAM DEFAULT CHARSET=latin1; CREATE TABLE t2 ( ID int(11) default NULL, PARID int(11) default NULL, diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index dba5619b777..5ae2039138d 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -466,8 +466,10 @@ select * from t1 where id=2; create table t1 (word char(20) not null); select * from t1; show status like "Qcache_queries_in_cache"; -load data infile '../../std_data/words.dat' into table t1; +--replace_result $MYSQL_TEST_DIR TEST_DIR +eval load data infile '$MYSQL_TEST_DIR/std_data/words.dat' into table t1; show status like "Qcache_queries_in_cache"; +select count(*) from t1; drop table t1; # @@ -476,7 +478,9 @@ drop table t1; create table t1 (a int); insert into t1 values (1),(2),(3); show status like "Qcache_queries_in_cache"; -select * from t1 into outfile "query_caceh.out.file"; +select * from t1 into outfile "query_cache.out.file"; +--error 1086 +select * from t1 into outfile "query_cache.out.file"; select * from t1 limit 1 into dumpfile "query_cache.dump.file"; show status like "Qcache_queries_in_cache"; drop table t1; diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index 4508fbea194..937a8c03f99 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -59,10 +59,11 @@ stop slave; # this should stop immideately start slave until master_log_file='master-bin.000001', master_log_pos=561; ---real-sleep 2; +# 2 is not enough when running with valgrind +--real-sleep 4; # here the sql slave thread should be stopped --replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004 ---replace_column 1 # 9 # 23 # 33 # +--replace_column 1 # 9 # 12 # 23 # 33 # show slave status; #testing various error conditions diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index c4392186055..6c53c70c9a0 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1026,52 +1026,26 @@ drop table t1; # Bug 2479 # -CREATE TABLE t1 ( -id int(11) NOT NULL auto_increment, -ts timestamp NOT NULL, -id_cns tinyint(3) unsigned NOT NULL default '0', -id_desc_nota int(11) NOT NULL default '1', -id_publ_uff int(11) NOT NULL default '0', -tipo enum('','UNO','DUE') NOT NULL default '', -f_aggiunte set('TRE','TRETRE','QUATTRO','CINQUE','SEI','SETTE') NOT NULL -default '', -anno_dep smallint(4) unsigned zerofill NOT NULL default '0000', -data_dep smallint(4) unsigned zerofill NOT NULL default '0000', -particolare mediumint(8) unsigned NOT NULL default '0', -generale mediumint(8) unsigned NOT NULL default '0', -bis tinyint(3) unsigned NOT NULL default '0', -PRIMARY KEY(id), -UNIQUE KEY idx_cns_gen_anno (anno_dep,id_cns,generale,particolare), -UNIQUE KEY idx_cns_par_anno (id_cns,anno_dep,tipo,particolare,bis) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 PACK_KEYS=1; - -INSERT INTO t1 (id, ts, id_cns, id_desc_nota, id_publ_uff, tipo, f_aggiunte, -anno_dep, data_dep, particolare, generale, bis) VALUES -(NULL, NULL, 16, 29, 622, 'UNO', '', 1987, 1218, 2048, 9681, 0), -(NULL, NULL, 50, 23, 1717, 'UNO', '', 1987, 1126, 1536, 13987, 0), -(NULL, NULL, 16, 123, 123, 'UNO', '', 1987, 1221, 2432, 14594, 0), -(NULL, NULL, 16, 124, 124, 'UNO', '', 1987, 1201, 1792, 13422, 0), -(NULL, NULL, 16, 125, 125, 'UNO', '', 1987, 0723, 1025, 10240, 0), -(NULL, NULL, 16, 126, 126, 'UNO', '', 1987, 1204, 1026, 7089, 0); - -CREATE TABLE t2 ( -id tinyint(3) unsigned NOT NULL auto_increment, -descr varchar(40) NOT NULL default '', -f_servizi set('UNO','DUE') NOT NULL default '', -data_uno_min int(8) unsigned NOT NULL default '0', -data_due_min int(8) unsigned NOT NULL default '0', -max_anno_dep smallint(6) unsigned NOT NULL default '0', -data_agg int(8) unsigned NOT NULL default '0', -PRIMARY KEY (id) +CREATE TABLE `t1` ( + `id` int(11) NOT NULL auto_increment, + `id_cns` tinyint(3) unsigned NOT NULL default '0', + `tipo` enum('','UNO','DUE') NOT NULL default '', + `anno_dep` smallint(4) unsigned zerofill NOT NULL default '0000', + `particolare` mediumint(8) unsigned NOT NULL default '0', + `generale` mediumint(8) unsigned NOT NULL default '0', + `bis` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + UNIQUE KEY `idx_cns_gen_anno` (`anno_dep`,`id_cns`,`generale`,`particolare`), + UNIQUE KEY `idx_cns_par_anno` (`id_cns`,`anno_dep`,`tipo`,`particolare`,`bis`) ); +INSERT INTO `t1` VALUES (1,16,'UNO',1987,2048,9681,0),(2,50,'UNO',1987,1536,13987,0),(3,16,'UNO',1987,2432,14594,0),(4,16,'UNO',1987,1792,13422,0),(5,16,'UNO',1987,1025,10240,0),(6,16,'UNO',1987,1026,7089,0); +CREATE TABLE `t2` ( + `id` tinyint(3) unsigned NOT NULL auto_increment, + `max_anno_dep` smallint(6) unsigned NOT NULL default '0', + PRIMARY KEY (`id`) +); +INSERT INTO `t2` VALUES (16,1987),(50,1990),(51,1990); -INSERT INTO t2 (id, descr, f_servizi, data_uno_min, data_due_min, -max_anno_dep, data_agg) VALUES -(16, 'C_UNO', 'UNO,DUE', 19000000, 30000000, 1987, 0), -(50, 'C_TRE', 'UNO', 19000000, 30000000, 1990, 0); - -SELECT cns.max_anno_dep = (SELECT s.anno_dep FROM t1 AS s WHERE -s.id_cns = cns.id ORDER BY s.anno_dep DESC LIMIT 1) AS PIPPO FROM -t2 AS cns; +SELECT cns.id, cns.max_anno_dep, cns.max_anno_dep = (SELECT s.anno_dep FROM t1 AS s WHERE s.id_cns = cns.id ORDER BY s.anno_dep DESC LIMIT 1) AS PIPPO FROM t2 AS cns; DROP TABLE t1, t2; diff --git a/sql/field.cc b/sql/field.cc index 9f25b770ab0..f337f4ca46c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4058,10 +4058,12 @@ void Field_datetime::sql_type(String &res) const int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) { int error= 0; + uint32 not_used; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); + /* Convert character set if nesessary */ - if (String::needs_conversion(from, length, cs, field_charset)) + if (String::needs_conversion(length, cs, field_charset, ¬_used)) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); @@ -4246,10 +4248,12 @@ uint Field_string::max_packed_col_length(uint max_length) int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) { int error= 0; + uint32 not_used; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); + /* Convert character set if nesessary */ - if (String::needs_conversion(from, length, cs, field_charset)) + if (String::needs_conversion(length, cs, field_charset, ¬_used)) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); @@ -4565,10 +4569,11 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) bool was_conversion; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); + uint32 not_used; /* Convert character set if nesessary */ - if ((was_conversion= String::needs_conversion(from, length, - cs, field_charset))) + if ((was_conversion= String::needs_conversion(length, cs, field_charset, + ¬_used))) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); @@ -5079,10 +5084,12 @@ void Field_enum::store_type(ulonglong value) int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) { int err= 0; + uint32 not_used; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); + /* Convert character set if nesessary */ - if (String::needs_conversion(from, length, cs, field_charset)) + if (String::needs_conversion(length, cs, field_charset, ¬_used)) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); @@ -5259,11 +5266,12 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) int err= 0; char *not_used; uint not_used2; + uint32 not_used_offset; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); /* Convert character set if nesessary */ - if (String::needs_conversion(from, length, cs, field_charset)) + if (String::needs_conversion(length, cs, field_charset, ¬_used_offset)) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index ae0267b98f3..c1228cbd319 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -40,6 +40,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked) if (!create(name, table, &create_info)) file= heap_open(name, mode); } + ref_length= sizeof(HEAP_PTR); return (file ? 0 : 1); } @@ -335,7 +336,6 @@ int ha_heap::create(const char *name, TABLE *table_arg, my_free((gptr) keydef, MYF(0)); if (file) info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE); - ref_length= sizeof(HEAP_PTR); return (error); } diff --git a/sql/item_func.cc b/sql/item_func.cc index efeb0d456ef..b1378784f92 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1068,9 +1068,8 @@ String *Item_func_min_max::val_str(String *str) } } } - if (!res) // If NULL - return 0; - res->set_charset(collation.collation); + if (res) // If !NULL + res->set_charset(collation.collation); return res; } case ROW_RESULT: diff --git a/sql/item_func.h b/sql/item_func.h index be20a9b4fc7..30f817d133b 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -211,20 +211,28 @@ class Item_func_signed :public Item_int_func { public: Item_func_signed(Item *a) :Item_int_func(a) {} - double val() { null_value=args[0]->null_value; return args[0]->val(); } - longlong val_int() { null_value=args[0]->null_value; return args[0]->val_int(); } + double val() + { + double tmp= args[0]->val(); + null_value= args[0]->null_value; + return tmp; + } + longlong val_int() + { + longlong tmp= args[0]->val_int(); + null_value= args[0]->null_value; + return tmp; + } void fix_length_and_dec() { max_length=args[0]->max_length; unsigned_flag=0; } void print(String *str); }; -class Item_func_unsigned :public Item_int_func +class Item_func_unsigned :public Item_func_signed { public: - Item_func_unsigned(Item *a) :Item_int_func(a) {} - double val() { null_value=args[0]->null_value; return args[0]->val(); } - longlong val_int() { null_value=args[0]->null_value; return args[0]->val_int(); } + Item_func_unsigned(Item *a) :Item_func_signed(a) {} void fix_length_and_dec() { max_length=args[0]->max_length; unsigned_flag=1; } void print(String *str); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index f5922d03868..fd1222d5f1a 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2126,14 +2126,12 @@ void Item_func_conv_charset::print(String *str) String *Item_func_conv_charset3::val_str(String *str) { - my_wc_t wc; - int cnvres; - const uchar *s, *se; - uchar *d, *d0, *de; - uint32 dmaxlen; + char cs1[30], cs2[30]; + String to_cs_buff(cs1, sizeof(cs1), default_charset_info); + String from_cs_buff(cs2, sizeof(cs2), default_charset_info); String *arg= args[0]->val_str(str); - String *to_cs= args[1]->val_str(str); - String *from_cs= args[2]->val_str(str); + String *to_cs= args[1]->val_str(&to_cs_buff); + String *from_cs= args[2]->val_str(&from_cs_buff); CHARSET_INFO *from_charset; CHARSET_INFO *to_charset; @@ -2143,51 +2141,17 @@ String *Item_func_conv_charset3::val_str(String *str) !(from_charset=get_charset_by_name(from_cs->ptr(), MYF(MY_WME))) || !(to_charset=get_charset_by_name(to_cs->ptr(), MYF(MY_WME)))) { - null_value=1; + null_value= 1; return 0; } - s=(const uchar*)arg->ptr(); - se=s+arg->length(); - - dmaxlen=arg->length()*to_charset->mbmaxlen+1; - str->alloc(dmaxlen); - d0=d=(unsigned char*)str->ptr(); - de=d+dmaxlen; - - while (1) + if (str_value.copy(arg->ptr(), arg->length(), from_charset, to_charset)) { - cnvres=from_charset->cset->mb_wc(from_charset,&wc,s,se); - if (cnvres>0) - { - s+=cnvres; - } - else if (cnvres==MY_CS_ILSEQ) - { - s++; - wc='?'; - } - else - break; - -outp: - cnvres=to_charset->cset->wc_mb(to_charset,wc,d,de); - if (cnvres>0) - { - d+=cnvres; - } - else if (cnvres==MY_CS_ILUNI && wc!='?') - { - wc='?'; - goto outp; - } - else - break; - }; - - str->length((uint32) (d-d0)); - str->set_charset(to_charset); - return str; + null_value= 1; + return 0; + } + null_value= 0; + return &str_value; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index e01f9db3463..10b50fa5b3b 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1092,15 +1092,21 @@ void Item_sum_count_distinct::cleanup() if (!original) { if (table) + { free_tmp_table(current_thd, table); + table= 0; + } delete tmp_table_param; + tmp_table_param= 0; if (use_tree) + { delete_tree(tree); - table= 0; - use_tree= 0; + use_tree= 0; + } } } + bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { @@ -1674,13 +1680,21 @@ void Item_func_group_concat::cleanup() { THD *thd= current_thd; if (table) + { free_tmp_table(thd, table); + table= 0; + } delete tmp_table_param; + tmp_table_param= 0; if (tree_mode) + { + tree_mode= 0; delete_tree(tree); + } } } + Item_func_group_concat::~Item_func_group_concat() { /* diff --git a/sql/item_sum.h b/sql/item_sum.h index dc84e4d4ab7..bb03f029997 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -397,12 +397,13 @@ class Item_sum_hybrid :public Item_sum public: Item_sum_hybrid(Item *item_par,int sign) - :Item_sum(item_par), hybrid_type(INT_RESULT), cmp_sign(sign), - used_table_cache(~(table_map) 0), + :Item_sum(item_par), sum(0.0), sum_int(0), + hybrid_type(INT_RESULT), hybrid_field_type(FIELD_TYPE_LONGLONG), + cmp_sign(sign), used_table_cache(~(table_map) 0), cmp_charset(&my_charset_bin) {} Item_sum_hybrid(THD *thd, Item_sum_hybrid *item): - Item_sum(thd, item), value(item->value), tmp_value(item->tmp_value), + Item_sum(thd, item), value(item->value), sum(item->sum), sum_int(item->sum_int), hybrid_type(item->hybrid_type), hybrid_field_type(item->hybrid_field_type),cmp_sign(item->cmp_sign), used_table_cache(item->used_table_cache), cmp_charset(item->cmp_charset) {} diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 2647a0ae818..4c9f3700ef1 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1005,7 +1005,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, } /* - We can't use an index when comparing stings of + We can't use an index when comparing strings of different collations */ if (field->result_type() == STRING_RESULT && diff --git a/sql/sql_class.cc b/sql/sql_class.cc index fc042ae7918..cbac11ac42e 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -744,7 +744,7 @@ static File create_file(THD *thd, char *path, sql_exchange *exchange, if (!access(path, F_OK)) { my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name); - return 1; + return -1; } /* Create the file world readable */ if ((file= my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0) diff --git a/sql/sql_class.h b/sql/sql_class.h index 51dc8270d09..b3135202ad6 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -993,10 +993,6 @@ public: class select_dump :public select_to_file { - sql_exchange *exchange; - File file; - IO_CACHE cache; - ha_rows row_count; public: select_dump(sql_exchange *ex) :select_to_file(ex) {} int prepare(List &list, SELECT_LEX_UNIT *u); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index de0d0c8aca8..9b8ef37757c 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1005,8 +1005,10 @@ void mysql_stmt_execute(THD *thd, char *packet) sl->where= sl->prep_where->copy_andor_structure(thd); DBUG_ASSERT(sl->join == 0); ORDER *order; + /* Fix GROUP list */ for (order=(ORDER *)sl->group_list.first ; order ; order=order->next) order->item= (Item **)(order+1); + /* Fix ORDER list */ for (order=(ORDER *)sl->order_list.first ; order ; order=order->next) order->item= (Item **)(order+1); } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5f6167f2cd1..4da2522bd3f 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -519,8 +519,7 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild) protocol->store_null(); // Send error to Comment field protocol->store(thd->net.last_error, system_charset_info); - thd->net.last_error[0]=0; - thd->net.last_errno= 0; + thd->clear_error(); } else { diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 7f26a0febda..cbee67c0a4a 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -230,68 +230,86 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs) /* - Checks that the source string can be just copied - to the destination string without conversion. - If either character set conversion or adding leading - zeros (e.g. for UCS-2) must be done then return - value is TRUE else FALSE. + Checks that the source string can be just copied to the destination string + without conversion. + + SYNPOSIS + + needs_conversion() + arg_length Length of string to copy. + from_cs Character set to copy from + to_cs Character set to copy to + uint32 *offset Returns number of unaligned characters. + + RETURN + 0 No conversion needed + 1 Either character set conversion or adding leading zeros + (e.g. for UCS-2) must be done */ -bool String::needs_conversion(const char *str, uint32 arg_length, - CHARSET_INFO *from_cs, - CHARSET_INFO *to_cs) + +bool String::needs_conversion(uint32 arg_length, + CHARSET_INFO *from_cs, + CHARSET_INFO *to_cs, + uint32 *offset) { + *offset= 0; if ((to_cs == &my_charset_bin) || (to_cs == from_cs) || my_charset_same(from_cs, to_cs) || - ((from_cs == &my_charset_bin) && (!(arg_length % to_cs->mbminlen)))) + ((from_cs == &my_charset_bin) && + (!(*offset=(arg_length % to_cs->mbminlen))))) return FALSE; - return TRUE; } + /* -** For real multi-byte, ascii incompatible charactser sets, -** like UCS-2, add leading zeros if we have an incomplete character. -** Thus, -** SELECT _ucs2 0xAA -** will automatically be converted into -** SELECT _ucs2 0x00AA + Copy a multi-byte character sets with adding leading zeros. + + SYNOPSIS + + copy_aligned() + str String to copy + arg_length Length of string. This should NOT be dividable with + cs->mbminlen. + offset arg_length % cs->mb_minlength + cs Character set for 'str' + + NOTES + For real multi-byte, ascii incompatible charactser sets, + like UCS-2, add leading zeros if we have an incomplete character. + Thus, + SELECT _ucs2 0xAA + will automatically be converted into + SELECT _ucs2 0x00AA + + RETURN + 0 ok + 1 error */ -bool String::copy_aligned(const char *str,uint32 arg_length, +bool String::copy_aligned(const char *str,uint32 arg_length, uint32 offset, CHARSET_INFO *cs) { /* How many bytes are in incomplete character */ - uint32 offs= (arg_length % cs->mbminlen); + offset= cs->mbmaxlen - offset; /* How many zeros we should prepend */ + DBUG_ASSERT(offset && offset != cs->mbmaxlen); - if (!offs) /* All characters are complete, just copy */ - { - copy(str, arg_length, cs); - return FALSE; - } - - offs= cs->mbmaxlen - offs; /* How many zeros we should prepend */ - uint32 aligned_length= arg_length + offs; + uint32 aligned_length= arg_length + offset; if (alloc(aligned_length)) return TRUE; /* - Probably this condition is not really necessary - because if aligned_length is 0 then offs is 0 too - and we'll return after calling set(). + Note, this is only safe for little-endian UCS-2. + If we add big-endian UCS-2 sometimes, this code + will be more complicated. But it's OK for now. */ - if ((str_length= aligned_length)) - { - /* - Note, this is only safe for little-endian UCS-2. - If we add big-endian UCS-2 sometimes, this code - will be more complicated. But it's OK for now. - */ - bzero((char*)Ptr, offs); - memcpy(Ptr + offs, str, arg_length); - } + bzero((char*) Ptr, offset); + memcpy(Ptr + offset, str, arg_length); Ptr[aligned_length]=0; - str_charset=cs; + /* str_length is always >= 0 as arg_length is != 0 */ + str_length= aligned_length; + str_charset= cs; return FALSE; } @@ -300,14 +318,14 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length, CHARSET_INFO *cs) { /* How many bytes are in incomplete character */ - uint32 offs= (arg_length % cs->mbminlen); + uint32 offset= (arg_length % cs->mbminlen); - if (!offs) /* All characters are complete, just copy */ + if (!offset) /* All characters are complete, just copy */ { set(str, arg_length, cs); return FALSE; } - return copy_aligned(str, arg_length, cs); + return copy_aligned(str, arg_length, offset, cs); } /* Copy with charset convertion */ @@ -315,14 +333,11 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length, bool String::copy(const char *str, uint32 arg_length, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) { - if (!needs_conversion(str, arg_length, from_cs, to_cs)) - { + uint32 offset; + if (!needs_conversion(arg_length, from_cs, to_cs, &offset)) return copy(str, arg_length, to_cs); - } - if ((from_cs == &my_charset_bin) && (arg_length % to_cs->mbminlen)) - { - return copy_aligned(str, arg_length, to_cs); - } + if ((from_cs == &my_charset_bin) && offset) + return copy_aligned(str, arg_length, offset, to_cs); uint32 new_length= to_cs->mbmaxlen*arg_length; if (alloc(new_length)) @@ -744,7 +759,8 @@ copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, while (1) { - if ((cnvres=from_cs->cset->mb_wc(from_cs, &wc, (uchar*) from, from_end)) > 0) + if ((cnvres= from_cs->cset->mb_wc(from_cs, &wc, (uchar*) from, + from_end)) > 0) from+= cnvres; else if (cnvres == MY_CS_ILSEQ) { diff --git a/sql/sql_string.h b/sql/sql_string.h index 9c0900137e3..163156fdfe2 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -183,9 +183,11 @@ public: bool copy(); // Alloc string if not alloced bool copy(const String &s); // Allocate new string bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs); // Allocate new string - static bool needs_conversion(const char *s, uint32 arg_length, - CHARSET_INFO *cs_from, CHARSET_INFO *cs_to); - bool copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs); + static bool needs_conversion(uint32 arg_length, + CHARSET_INFO *cs_from, CHARSET_INFO *cs_to, + uint32 *offset); + bool copy_aligned(const char *s, uint32 arg_length, uint32 offset, + CHARSET_INFO *cs); bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs); bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, CHARSET_INFO *csto); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index c6e470fd09f..86593f5ea20 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -482,8 +482,11 @@ int mysql_multi_update(THD *thd, for (tl= select_lex->get_table_list() ; tl ; tl= tl->next) { if (tl->derived && (item_tables & tl->table->map)) + { my_printf_error(ER_NON_UPDATABLE_TABLE, ER(ER_NON_UPDATABLE_TABLE), MYF(0), tl->alias, "UPDATE"); + DBUG_RETURN(-1); + } } } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f04cc9ec1dc..0dbe8981466 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -918,7 +918,7 @@ create: &tmp_table_alias : (LEX_STRING*) 0), TL_OPTION_UPDATING, - ((using_update_log)? + (using_update_log ? TL_READ_NO_INSERT: TL_READ))) YYABORT; @@ -2189,10 +2189,9 @@ select_init2: select_part2: { - LEX *lex=Lex; - SELECT_LEX * sel= lex->current_select; - if (lex->current_select == &lex->select_lex) - lex->lock_option= TL_READ; /* Only for global SELECT */ + LEX *lex= Lex; + SELECT_LEX *sel= lex->current_select; + lex->lock_option= TL_READ; if (sel->linkage != UNION_TYPE) mysql_init_select(lex); lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST; @@ -3060,7 +3059,7 @@ opt_gorder_clause: | order_clause { LEX *lex=Lex; - lex->gorder_list= + lex->gorder_list= (SQL_LIST*) sql_memdup((char*) &lex->current_select->order_list, sizeof(st_sql_list)); lex->current_select->order_list.empty(); @@ -3084,16 +3083,16 @@ in_sum_expr: }; cast_type: - BINARY { $$=ITEM_CAST_BINARY; } + BINARY { $$=ITEM_CAST_BINARY; Lex->charset= NULL; Lex->length= (char*)0; } | CHAR_SYM opt_len opt_binary { $$=ITEM_CAST_CHAR; } | NCHAR_SYM opt_len { $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; } - | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; } - | SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; } - | UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; } - | UNSIGNED INT_SYM { $$=ITEM_CAST_UNSIGNED_INT; } - | DATE_SYM { $$=ITEM_CAST_DATE; } - | TIME_SYM { $$=ITEM_CAST_TIME; } - | DATETIME { $$=ITEM_CAST_DATETIME; } + | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; } + | SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; } + | UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; } + | UNSIGNED INT_SYM { $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; } + | DATE_SYM { $$=ITEM_CAST_DATE; Lex->charset= NULL; Lex->length= (char*)0; } + | TIME_SYM { $$=ITEM_CAST_TIME; Lex->charset= NULL; Lex->length= (char*)0; } + | DATETIME { $$=ITEM_CAST_DATETIME; Lex->charset= NULL; Lex->length= (char*)0; } ; expr_list: @@ -3895,6 +3894,7 @@ update: LEX *lex= Lex; mysql_init_select(lex); lex->sql_command= SQLCOM_UPDATE; + lex->lock_option= TL_UNLOCK; /* Will be set later */ } opt_low_priority opt_ignore join_table_list SET update_list where_clause opt_order_clause delete_limit_clause From 61f0e69cb60b9db858bad3b6de6fa0b8b2f03899 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 Feb 2004 14:44:03 +0200 Subject: [PATCH 12/36] ufter revview fix (BUG#2120) mysql-test/r/derived.result: test of error handling in derived tables with UPDATE & DELETE mysql-test/t/derived.test: test of error handling in derived tables with UPDATE & DELETE sql/mysql_priv.h: opened tables counter added to avoid loop of tables calculating in lock_tables sql/sql_acl.cc: opened tables counter added to avoid loop of tables calculating in lock_tables, here it is just for compatibility sql/sql_base.cc: removed unneeded assignment opened tables counter added to avoid loop of tables calculating in lock_tables commentary fixed sql/sql_derived.cc: mysql_derived made static variable res moved in place where it used priveleges written in correct place sql/sql_handler.cc: opened tables counter added to avoid loop of tables calculating in lock_tables sql/sql_parse.cc: mistyping in commentary fixed --- mysql-test/r/derived.result | 4 +++ mysql-test/t/derived.test | 4 +++ sql/mysql_priv.h | 4 +-- sql/sql_acl.cc | 6 +++-- sql/sql_base.cc | 53 +++++++++++++++++++++++++------------ sql/sql_derived.cc | 16 +++++------ sql/sql_handler.cc | 3 ++- sql/sql_parse.cc | 4 +-- 8 files changed, 62 insertions(+), 32 deletions(-) diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index dea4dd9b4c2..6f35097e2b8 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -267,12 +267,16 @@ N M 3 0 UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2; ERROR HY000: The target table P2 of the UPDATE is not updatable. +UPDATE `t1` AS P1 INNER JOIN (SELECT aaaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2; +ERROR 42S22: Unknown column 'aaaa' in 'field list' delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; select * from t1; N M 3 0 delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; ERROR HY000: The target table P2 of the DELETE is not updatable. +delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; +ERROR 42S22: Unknown column 'aaa' in 'field list' drop table t1; CREATE TABLE t1 ( OBJECTID int(11) NOT NULL default '0', diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index 988ef30d1dc..0a7e3d41c73 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -153,10 +153,14 @@ UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) select * from t1; -- error 1287 UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2; +-- error 1054 +UPDATE `t1` AS P1 INNER JOIN (SELECT aaaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2; delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; select * from t1; -- error 1287 delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; +-- error 1054 +delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; drop table t1; # diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 4d03feae07c..73e30e72a3c 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -675,10 +675,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); int setup_ftfuncs(SELECT_LEX* select); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); void wait_for_refresh(THD *thd); -int open_tables(THD *thd,TABLE_LIST *tables); +int open_tables(THD *thd, TABLE_LIST *tables, uint *counter); int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables); int open_and_lock_tables(THD *thd,TABLE_LIST *tables); -int lock_tables(THD *thd,TABLE_LIST *tables); +int lock_tables(THD *thd, TABLE_LIST *tables, uint counter); TABLE *open_temporary_table(THD *thd, const char *path, const char *db, const char *table_name, bool link_in_list); bool rm_temporary_table(enum db_type base, char *path); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 8ef6a32a430..21c57d79da4 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -173,7 +173,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ; tables[0].db=tables[1].db=tables[2].db=thd->db; - if (open_tables(thd,tables)) + uint counter; + if (open_tables(thd, tables, &counter)) { sql_print_error("Fatal error: Can't open privilege tables: %s", thd->net.last_error); @@ -2524,7 +2525,8 @@ my_bool grant_init(THD *org_thd) tables[0].lock_type=tables[1].lock_type=TL_READ; tables[0].db=tables[1].db=thd->db; - if (open_tables(thd,tables)) + uint counter; + if (open_tables(thd, tables, &counter)) goto end; TABLE *ptr[2]; // Lock tables for quick update diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 2e8441bb23b..0ededa80ad6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1308,7 +1308,6 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, bzero((char*) &table_list, sizeof(table_list)); // just for safe table_list.db=(char*) db; table_list.real_name=(char*) name; - table_list.next=0; safe_mutex_assert_owner(&LOCK_open); if ((error=lock_table_name(thd,&table_list))) @@ -1357,24 +1356,40 @@ err: DBUG_RETURN(1); } -/***************************************************************************** -** open all tables in list -*****************************************************************************/ +/* + Open all tables in list -int open_tables(THD *thd,TABLE_LIST *start) + SYNOPSIS + open_tables() + thd - thread handler + start - list of tables + counter - number of opened tables will be return using this parameter + + RETURN + 0 - OK + -1 - error +*/ + +int open_tables(THD *thd, TABLE_LIST *start, uint *counter) { TABLE_LIST *tables; bool refresh; int result=0; DBUG_ENTER("open_tables"); + *counter= 0; thd->current_tablenr= 0; restart: thd->proc_info="Opening tables"; for (tables=start ; tables ; tables=tables->next) { + /* + Ignore placeholders for derived tables. After derived tables + processing, link to created temporary table will be put here. + */ if (tables->derived) continue; + (*counter)++; if (!tables->table && !(tables->table= open_table(thd, tables->db, @@ -1533,14 +1548,19 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) thd - thread handler tables - list of tables for open&locking + RETURN + 0 - ok + -1 - error + NOTE The lock will automaticly be freed by close_thread_tables() */ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables) { - DBUG_ENTER("open_n_lock_tables"); - if (open_tables(thd, tables) || lock_tables(thd, tables)) + DBUG_ENTER("simple_open_n_lock_tables"); + uint counter; + if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter)) DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(0); } @@ -1551,10 +1571,14 @@ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables) tables processing. SYNOPSIS - simple_open_n_lock_tables() + open_and_lock_tables() thd - thread handler tables - list of tables for open&locking + RETURN + 0 - ok + -1 - error + NOTE The lock will automaticly be freed by close_thread_tables() */ @@ -1562,7 +1586,8 @@ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables) int open_and_lock_tables(THD *thd, TABLE_LIST *tables) { DBUG_ENTER("open_and_lock_tables"); - if (open_tables(thd, tables) || lock_tables(thd, tables)) + uint counter; + if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter)) DBUG_RETURN(-1); /* purecov: inspected */ fix_tables_pointers(thd->lex->all_selects_list); DBUG_RETURN(mysql_handle_derived(thd->lex)); @@ -1576,6 +1601,7 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables) lock_tables() thd Thread handler tables Tables to lock + count umber of opened tables NOTES You can't call lock_tables twice, as this would break the dead-lock-free @@ -1587,7 +1613,7 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables) -1 Error */ -int lock_tables(THD *thd,TABLE_LIST *tables) +int lock_tables(THD *thd, TABLE_LIST *tables, uint count) { TABLE_LIST *table; if (!tables) @@ -1596,12 +1622,6 @@ int lock_tables(THD *thd,TABLE_LIST *tables) if (!thd->locked_tables) { DBUG_ASSERT(thd->lock == 0); // You must lock everything at once - uint count=0; - for (table = tables ; table ; table=table->next) - { - if (!table->derived) - count++; - } TABLE **start,**ptr; if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*)*count))) return -1; @@ -2207,7 +2227,6 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Ensure that we have access right to all columns */ if (!(table->grant.privilege & SELECT_ACL) && - !tables->derived && check_grant_all_columns(thd,SELECT_ACL,table)) DBUG_RETURN(-1); #endif diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index a307b59b525..6e70fdd46d5 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -25,7 +25,8 @@ #include "sql_select.h" #include "sql_acl.h" -int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); +static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, + TABLE_LIST *t); /* Resolve derived tables in all queries @@ -39,10 +40,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); -1 Error 1 Error and error message given */ + int mysql_handle_derived(LEX *lex) { - int res= 0; if (lex->derived_tables) { for (SELECT_LEX *sl= lex->all_selects_list; @@ -53,13 +54,12 @@ mysql_handle_derived(LEX *lex) cursor; cursor= cursor->next) { + int res; if (cursor->derived && (res=mysql_derived(lex->thd, lex, cursor->derived, cursor))) { - if (res < 0 || lex->thd->net.report_error) - send_error(lex->thd, lex->thd->killed ? ER_SERVER_SHUTDOWN : 0); - return 1; + return res; } } if (lex->describe) @@ -108,8 +108,8 @@ mysql_handle_derived(LEX *lex) */ -int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, - TABLE_LIST *org_table_list) +static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, + TABLE_LIST *org_table_list) { SELECT_LEX *first_select= unit->first_select(); TABLE *table; @@ -197,7 +197,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, table->derived_select_number= first_select->select_number; table->tmp_table= TMP_TABLE; #ifndef NO_EMBEDDED_ACCESS_CHECKS - org_table_list->grant.privilege= SELECT_ACL; + table->grant.privilege= SELECT_ACL; #endif org_table_list->db= (char *)""; // Force read of table stats in the optimizer diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 405cfdb5bdc..897aa37ba11 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -48,7 +48,8 @@ static TABLE **find_table_ptr_by_name(THD *thd,const char *db, int mysql_ha_open(THD *thd, TABLE_LIST *tables) { HANDLER_TABLES_HACK(thd); - int err=open_tables(thd,tables); + uint counter; + int err=open_tables(thd, tables, &counter); HANDLER_TABLES_HACK(thd); if (err) return -1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 14696ce7478..42ea6039b6c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2669,8 +2669,8 @@ mysql_execute_command(THD *thd) { auxi->table= auxi->table_list->table; /* - Multi-delete can't be constucted over-union => we always have - single SELECT on top and have to check underlayed SELECTs of it + Multi-delete can't be constructed over-union => we always have + single SELECT on top and have to check underlaying SELECTs of it */ for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit(); un; From 74b81a801785058706b46a1e75b67b026c468d04 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 Feb 2004 13:59:41 +0100 Subject: [PATCH 13/36] Ensure that result from date_format() is binary Removed warnings from test suite mysql-test/r/ctype_utf8.result: Update results after fix of return argument from date_format() mysql-test/r/date_formats.result: Remove unnecessary warnings mysql-test/r/type_decimal.result: Remove unnecessary warnings mysql-test/r/warnings.result: Remove unnecessary warnings mysql-test/t/ctype_utf8.test: Fixed test mysql-test/t/date_formats.test: Remove unnecessary warnings mysql-test/t/type_decimal.test: Remove unnecessary warnings mysql-test/t/warnings.test: Remove unnecessary warnings sql/field.cc: Optimize sql/item_timefunc.cc: Ensure that result from date_format() is binary strings/ctype-simple.c: Better names for arguments --- mysql-test/r/ctype_utf8.result | 3 +- mysql-test/r/date_formats.result | 2 - mysql-test/r/type_decimal.result | 123 ------------------------------- mysql-test/r/warnings.result | 3 - mysql-test/t/ctype_utf8.test | 1 + mysql-test/t/date_formats.test | 4 +- mysql-test/t/type_decimal.test | 4 +- mysql-test/t/warnings.test | 4 +- sql/field.cc | 5 +- sql/item_timefunc.cc | 11 ++- strings/ctype-simple.c | 6 +- 11 files changed, 22 insertions(+), 144 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 31f26c421b6..815ab492fa4 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -73,7 +73,7 @@ create table t1 select date_format("2004-01-19 10:10:10", "%Y-%m-%d"); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `date_format("2004-01-19 10:10:10", "%Y-%m-%d")` char(10) character set utf8 default NULL + `date_format("2004-01-19 10:10:10", "%Y-%m-%d")` char(10) binary default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select * from t1; date_format("2004-01-19 10:10:10", "%Y-%m-%d") @@ -87,3 +87,4 @@ Warning 1264 Data truncated for column 's1' at row 1 select s1,hex(s1),char_length(s1),octet_length(s1) from t1; s1 hex(s1) char_length(s1) octet_length(s1) Á D0B0 1 2 +drop table t1; diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result index ee4fa074477..165a8d7011c 100644 --- a/mysql-test/r/date_formats.result +++ b/mysql-test/r/date_formats.result @@ -1,6 +1,4 @@ drop table if exists t1; -Warnings: -Note 1051 Unknown table 't1' SHOW GLOBAL VARIABLES LIKE "%_format%"; Variable_name Value date_format %d.%m.%Y diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index 97d81d77722..fa4cd231129 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -446,39 +446,6 @@ CREATE TABLE t1 (a_dec DECIMAL(-1,1)); ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '-1,1))' at line 1 create table t1(a decimal(7,3)); insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000'); -Warnings: -Warning 1263 Data truncated, out of range for column 'a' at row 27 -Warning 1263 Data truncated, out of range for column 'a' at row 30 -Warning 1263 Data truncated, out of range for column 'a' at row 31 -Warning 1263 Data truncated, out of range for column 'a' at row 32 -Warning 1263 Data truncated, out of range for column 'a' at row 33 -Warning 1263 Data truncated, out of range for column 'a' at row 34 -Warning 1263 Data truncated, out of range for column 'a' at row 35 -Warning 1263 Data truncated, out of range for column 'a' at row 36 -Warning 1263 Data truncated, out of range for column 'a' at row 37 -Warning 1263 Data truncated, out of range for column 'a' at row 38 -Warning 1263 Data truncated, out of range for column 'a' at row 39 -Warning 1263 Data truncated, out of range for column 'a' at row 40 -Warning 1263 Data truncated, out of range for column 'a' at row 41 -Warning 1263 Data truncated, out of range for column 'a' at row 42 -Warning 1263 Data truncated, out of range for column 'a' at row 43 -Warning 1263 Data truncated, out of range for column 'a' at row 44 -Warning 1263 Data truncated, out of range for column 'a' at row 45 -Warning 1263 Data truncated, out of range for column 'a' at row 46 -Warning 1263 Data truncated, out of range for column 'a' at row 47 -Warning 1263 Data truncated, out of range for column 'a' at row 48 -Warning 1263 Data truncated, out of range for column 'a' at row 49 -Warning 1263 Data truncated, out of range for column 'a' at row 50 -Warning 1263 Data truncated, out of range for column 'a' at row 51 -Warning 1263 Data truncated, out of range for column 'a' at row 52 -Warning 1263 Data truncated, out of range for column 'a' at row 53 -Warning 1263 Data truncated, out of range for column 'a' at row 54 -Warning 1263 Data truncated, out of range for column 'a' at row 55 -Warning 1263 Data truncated, out of range for column 'a' at row 56 -Warning 1263 Data truncated, out of range for column 'a' at row 57 -Warning 1263 Data truncated, out of range for column 'a' at row 58 -Warning 1263 Data truncated, out of range for column 'a' at row 59 -Warning 1263 Data truncated, out of range for column 'a' at row 60 select * from t1; a 1.000 @@ -544,51 +511,6 @@ a drop table t1; create table t1(a decimal(7,3) unsigned); insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000'); -Warnings: -Warning 1263 Data truncated, out of range for column 'a' at row 3 -Warning 1263 Data truncated, out of range for column 'a' at row 6 -Warning 1263 Data truncated, out of range for column 'a' at row 9 -Warning 1263 Data truncated, out of range for column 'a' at row 12 -Warning 1263 Data truncated, out of range for column 'a' at row 15 -Warning 1263 Data truncated, out of range for column 'a' at row 18 -Warning 1263 Data truncated, out of range for column 'a' at row 21 -Warning 1263 Data truncated, out of range for column 'a' at row 24 -Warning 1263 Data truncated, out of range for column 'a' at row 25 -Warning 1263 Data truncated, out of range for column 'a' at row 26 -Warning 1263 Data truncated, out of range for column 'a' at row 27 -Warning 1263 Data truncated, out of range for column 'a' at row 28 -Warning 1263 Data truncated, out of range for column 'a' at row 29 -Warning 1263 Data truncated, out of range for column 'a' at row 30 -Warning 1263 Data truncated, out of range for column 'a' at row 31 -Warning 1263 Data truncated, out of range for column 'a' at row 32 -Warning 1263 Data truncated, out of range for column 'a' at row 33 -Warning 1263 Data truncated, out of range for column 'a' at row 34 -Warning 1263 Data truncated, out of range for column 'a' at row 35 -Warning 1263 Data truncated, out of range for column 'a' at row 36 -Warning 1263 Data truncated, out of range for column 'a' at row 37 -Warning 1263 Data truncated, out of range for column 'a' at row 38 -Warning 1263 Data truncated, out of range for column 'a' at row 39 -Warning 1263 Data truncated, out of range for column 'a' at row 40 -Warning 1263 Data truncated, out of range for column 'a' at row 41 -Warning 1263 Data truncated, out of range for column 'a' at row 42 -Warning 1263 Data truncated, out of range for column 'a' at row 43 -Warning 1263 Data truncated, out of range for column 'a' at row 44 -Warning 1263 Data truncated, out of range for column 'a' at row 45 -Warning 1263 Data truncated, out of range for column 'a' at row 46 -Warning 1263 Data truncated, out of range for column 'a' at row 47 -Warning 1263 Data truncated, out of range for column 'a' at row 48 -Warning 1263 Data truncated, out of range for column 'a' at row 49 -Warning 1263 Data truncated, out of range for column 'a' at row 50 -Warning 1263 Data truncated, out of range for column 'a' at row 51 -Warning 1263 Data truncated, out of range for column 'a' at row 52 -Warning 1263 Data truncated, out of range for column 'a' at row 53 -Warning 1263 Data truncated, out of range for column 'a' at row 54 -Warning 1263 Data truncated, out of range for column 'a' at row 55 -Warning 1263 Data truncated, out of range for column 'a' at row 56 -Warning 1263 Data truncated, out of range for column 'a' at row 57 -Warning 1263 Data truncated, out of range for column 'a' at row 58 -Warning 1263 Data truncated, out of range for column 'a' at row 59 -Warning 1263 Data truncated, out of range for column 'a' at row 60 select * from t1; a 1.000 @@ -654,51 +576,6 @@ a drop table t1; create table t1(a decimal(7,3) zerofill); insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000'); -Warnings: -Warning 1263 Data truncated, out of range for column 'a' at row 3 -Warning 1263 Data truncated, out of range for column 'a' at row 6 -Warning 1263 Data truncated, out of range for column 'a' at row 9 -Warning 1263 Data truncated, out of range for column 'a' at row 12 -Warning 1263 Data truncated, out of range for column 'a' at row 15 -Warning 1263 Data truncated, out of range for column 'a' at row 18 -Warning 1263 Data truncated, out of range for column 'a' at row 21 -Warning 1263 Data truncated, out of range for column 'a' at row 24 -Warning 1263 Data truncated, out of range for column 'a' at row 25 -Warning 1263 Data truncated, out of range for column 'a' at row 26 -Warning 1263 Data truncated, out of range for column 'a' at row 27 -Warning 1263 Data truncated, out of range for column 'a' at row 28 -Warning 1263 Data truncated, out of range for column 'a' at row 29 -Warning 1263 Data truncated, out of range for column 'a' at row 30 -Warning 1263 Data truncated, out of range for column 'a' at row 31 -Warning 1263 Data truncated, out of range for column 'a' at row 32 -Warning 1263 Data truncated, out of range for column 'a' at row 33 -Warning 1263 Data truncated, out of range for column 'a' at row 34 -Warning 1263 Data truncated, out of range for column 'a' at row 35 -Warning 1263 Data truncated, out of range for column 'a' at row 36 -Warning 1263 Data truncated, out of range for column 'a' at row 37 -Warning 1263 Data truncated, out of range for column 'a' at row 38 -Warning 1263 Data truncated, out of range for column 'a' at row 39 -Warning 1263 Data truncated, out of range for column 'a' at row 40 -Warning 1263 Data truncated, out of range for column 'a' at row 41 -Warning 1263 Data truncated, out of range for column 'a' at row 42 -Warning 1263 Data truncated, out of range for column 'a' at row 43 -Warning 1263 Data truncated, out of range for column 'a' at row 44 -Warning 1263 Data truncated, out of range for column 'a' at row 45 -Warning 1263 Data truncated, out of range for column 'a' at row 46 -Warning 1263 Data truncated, out of range for column 'a' at row 47 -Warning 1263 Data truncated, out of range for column 'a' at row 48 -Warning 1263 Data truncated, out of range for column 'a' at row 49 -Warning 1263 Data truncated, out of range for column 'a' at row 50 -Warning 1263 Data truncated, out of range for column 'a' at row 51 -Warning 1263 Data truncated, out of range for column 'a' at row 52 -Warning 1263 Data truncated, out of range for column 'a' at row 53 -Warning 1263 Data truncated, out of range for column 'a' at row 54 -Warning 1263 Data truncated, out of range for column 'a' at row 55 -Warning 1263 Data truncated, out of range for column 'a' at row 56 -Warning 1263 Data truncated, out of range for column 'a' at row 57 -Warning 1263 Data truncated, out of range for column 'a' at row 58 -Warning 1263 Data truncated, out of range for column 'a' at row 59 -Warning 1263 Data truncated, out of range for column 'a' at row 60 select * from t1; a 0001.000 diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index c3d9f165fed..b675d189d30 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -1,7 +1,4 @@ drop table if exists t1, t2; -Warnings: -Note 1051 Unknown table 't1' -Note 1051 Unknown table 't2' SET SQL_WARNINGS=1; create table t1 (a int); insert into t1 values (1); diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index c2ea1ed20a4..9da7b32eb6d 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -60,3 +60,4 @@ set names koi8r; create table t1 (s1 char(1) character set utf8); insert into t1 values (_koi8r'ÁÂ'); select s1,hex(s1),char_length(s1),octet_length(s1) from t1; +drop table t1; diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test index 7b88c0ecf72..18af3dfb3db 100644 --- a/mysql-test/t/date_formats.test +++ b/mysql-test/t/date_formats.test @@ -2,9 +2,9 @@ # Test of date format functions # ---disable-warnings +--disable_warnings drop table if exists t1; ---enable-warnings +--enable_warnings SHOW GLOBAL VARIABLES LIKE "%_format%"; SHOW SESSION VARIABLES LIKE "%_format%"; diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test index cddb0347b7e..3257002ae2c 100644 --- a/mysql-test/t/type_decimal.test +++ b/mysql-test/t/type_decimal.test @@ -248,7 +248,7 @@ CREATE TABLE t1 (a_dec DECIMAL(-1,1)); # # Zero prepend overflow bug # ---disable-warnings +--disable_warnings create table t1(a decimal(7,3)); insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000'); select * from t1; @@ -259,6 +259,6 @@ select * from t1; drop table t1; create table t1(a decimal(7,3) zerofill); insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000'); ---enable-warnings +--enable_warnings select * from t1; drop table t1; diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test index 0456ca8c1fe..b6042df51f1 100644 --- a/mysql-test/t/warnings.test +++ b/mysql-test/t/warnings.test @@ -1,9 +1,9 @@ # # Test some warnings # ---disable-warnings +--disable_warnings drop table if exists t1, t2; ---enable-warnings +--enable_warnings SET SQL_WARNINGS=1; create table t1 (a int); diff --git a/sql/field.cc b/sql/field.cc index 6f29737e4a0..cce7446dcff 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4072,7 +4072,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) } /* - Make sure we don't break a multybite sequence + Make sure we don't break a multibyte sequence as well as don't copy a malformed data. */ copy_length= field_charset->cset->wellformedlen(field_charset, @@ -4084,8 +4084,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) field_charset->cset->fill(field_charset,ptr+copy_length, field_length-copy_length,' '); - - if (current_thd->count_cuted_fields && (copy_length < length)) + if ((copy_length < length) && current_thd->count_cuted_fields) { // Check if we loosed some info const char *end=from+length; from+= copy_length; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 062e7fc7b44..32fbe192d8f 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1283,16 +1283,21 @@ longlong Item_func_sec_to_time::val_int() void Item_func_date_format::fix_length_and_dec() { decimals=0; + collation.set(&my_charset_bin); if (args[1]->type() == STRING_ITEM) { // Optimize the normal case fixed_length=1; - max_length= format_length(((Item_string*) args[1])->const_string())* - collation.collation->mbmaxlen; + /* + The result is a binary string (no reason to use collation->mbmaxlen + This is becasue make_date_time() only returns binary strings + */ + max_length= format_length(((Item_string*) args[1])->const_string()); } else { fixed_length=0; - max_length=args[1]->max_length*10*collation.collation->mbmaxlen; + /* The result is a binary string (no reason to use collation->mbmaxlen */ + max_length=args[1]->max_length*10; set_if_smaller(max_length,MAX_BLOB_WIDTH); } maybe_null=1; // If wrong date diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index fb2dee99ba5..233251e16a8 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -1021,11 +1021,11 @@ uint my_charpos_8bit(CHARSET_INFO *cs __attribute__((unused)), } uint my_wellformedlen_8bit(CHARSET_INFO *cs __attribute__((unused)), - const char *b, - const char *e, + const char *start, + const char *end, uint nchars) { - uint nbytes= e-b; + uint nbytes= (uint) (end-start); return nbytes < nchars ? nbytes : nchars; } From c4d0631b516e62dd66bf8cc3263db133f3dc7108 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 Feb 2004 16:26:38 +0300 Subject: [PATCH 14/36] switch off SERVER_MORE_RESULTS_EXISTS, but don't set other flags: it breaks future extensions --- sql/protocol.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/protocol.cc b/sql/protocol.cc index 2d2736b20d2..bef567ad346 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -123,7 +123,7 @@ void send_error(THD *thd, uint sql_errno, const char *err) /* Abort multi-result sets */ thd->lex->found_colon= 0; - thd->server_status= ~SERVER_MORE_RESULTS_EXISTS; + thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; DBUG_VOID_RETURN; } @@ -356,7 +356,7 @@ send_eof(THD *thd, bool no_flush) other queries (see the if test in dispatch_command / COM_QUERY) */ if (thd->is_fatal_error) - thd->server_status= ~SERVER_MORE_RESULTS_EXISTS; + thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; int2store(buff+3, thd->server_status); VOID(my_net_write(net,(char*) buff,5)); VOID(net_flush(net)); From d5b3cb44b9a96d2154af4b0b7520f1e2cd3d3e58 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 Feb 2004 23:47:28 +0100 Subject: [PATCH 15/36] Fix for the rpl_until.test. Don't use --command in tests; use command. mysql-test/r/rpl_until.result: result update mysql-test/t/rpl_until.test: real-sleep is incorrect syntax; mysqltest knows only real_sleep. Tip: don't use -- before commands; if mysqltest does not recognize the command after -- it just says "it must be a comment", so there is no syntax error detection. If you don't use the -- it will report the syntax error. The typo caused no sleep, so the slave did not have time to stop. Now it has time so we needn't replace the Slave_SQL_Running (and it's better to not replace it, because if we don't see that it is running, it will trigger errors just a bit later). --- mysql-test/r/rpl_until.result | 2 +- mysql-test/t/rpl_until.test | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result index cb60ccfb1c9..82b1ed233ec 100644 --- a/mysql-test/r/rpl_until.result +++ b/mysql-test/r/rpl_until.result @@ -55,7 +55,7 @@ stop slave; start slave until master_log_file='master-bin.000001', master_log_pos=561; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 # master-bin.000001 Yes # 0 0 561 # Master master-bin.000001 561 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 # master-bin.000001 Yes No 0 0 561 # Master master-bin.000001 561 No # start slave until master_log_file='master-bin', master_log_pos=561; ERROR HY000: Wrong parameter or combination of parameters for START SLAVE UNTIL start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12; diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index 937a8c03f99..40d36110296 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -60,10 +60,10 @@ stop slave; # this should stop immideately start slave until master_log_file='master-bin.000001', master_log_pos=561; # 2 is not enough when running with valgrind ---real-sleep 4; +real_sleep 4 # here the sql slave thread should be stopped --replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004 ---replace_column 1 # 9 # 12 # 23 # 33 # +--replace_column 1 # 9 # 23 # 33 # show slave status; #testing various error conditions From ecb11989ad22af2cdd2359dbb96705af240f1c84 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Feb 2004 02:18:22 +0200 Subject: [PATCH 16/36] after merge & valgrind test fixes (BUG#2120) sql/sql_derived.cc: memory leack fixed sql/sql_lex.cc: flag to avoid double cleaning sql/sql_lex.h: flag to avoid double cleaning sql/sql_select.cc: right way to cleanup JOIN_TAB sql/sql_select.h: right way to cleanup JOIN_TAB sql/sql_union.cc: flag to avoid double cleaning --- sql/sql_derived.cc | 2 ++ sql/sql_lex.cc | 1 + sql/sql_lex.h | 3 ++- sql/sql_select.cc | 66 ++++++++++++++++++++++++++-------------------- sql/sql_select.h | 2 ++ sql/sql_union.cc | 6 +++++ 6 files changed, 50 insertions(+), 30 deletions(-) diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 6e70fdd46d5..0e04316a2e7 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -204,6 +204,8 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, table->file->info(HA_STATUS_VARIABLE); } + if (!lex->describe) + unit->cleanup(); if (res) free_tmp_table(thd, table); else diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 62f255ea178..65357328927 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -988,6 +988,7 @@ void st_select_lex_unit::init_query() union_result= 0; table= 0; fake_select_lex= 0; + cleaned= 0; } void st_select_lex::init_query() diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 3b1b3873706..3f56be18c4a 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -305,7 +305,8 @@ protected: ulong found_rows_for_union; bool prepared, // prepare phase already performed for UNION (unit) optimized, // optimize phase already performed for UNION (unit) - executed; // already executed + executed, // already executed + cleaned; public: // list of fields which points to temporary table for union diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 082a06d97de..ea5050f2550 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1510,12 +1510,7 @@ JOIN::cleanup() JOIN_TAB *tab, *end; for (tab= join_tab, end= tab+tables ; tab != end ; tab++) { - delete tab->select; - delete tab->quick; - tab->select=0; - tab->quick=0; - x_free(tab->cache.buff); - tab->cache.buff= 0; + tab->cleanup(); } } tmp_join->tmp_join= 0; @@ -3759,6 +3754,41 @@ bool error_if_full_join(JOIN *join) } +/* + cleanup JOIN_TAB + + SYNOPSIS + JOIN_TAB::cleanup() +*/ + +void JOIN_TAB::cleanup() +{ + delete select; + select= 0; + delete quick; + quick= 0; + x_free(cache.buff); + cache.buff= 0; + if (table) + { + if (table->key_read) + { + table->key_read= 0; + table->file->extra(HA_EXTRA_NO_KEYREAD); + } + /* Don't free index if we are using read_record */ + if (!read_record.table) + table->file->index_end(); + /* + We need to reset this for next select + (Tested in part_of_refkey) + */ + table->reginfo.join_tab= 0; + } + end_read_record(&read_record); +} + + /* Free resources of given join @@ -3803,29 +3833,7 @@ JOIN::join_free(bool full) { for (tab= join_tab, end= tab+tables; tab != end; tab++) { - delete tab->select; - delete tab->quick; - tab->select=0; - tab->quick=0; - x_free(tab->cache.buff); - tab->cache.buff= 0; - if (tab->table) - { - if (tab->table->key_read) - { - tab->table->key_read= 0; - tab->table->file->extra(HA_EXTRA_NO_KEYREAD); - } - /* Don't free index if we are using read_record */ - if (!tab->read_record.table) - tab->table->file->index_end(); - /* - We need to reset this for next select - (Tested in part_of_refkey) - */ - tab->table->reginfo.join_tab= 0; - } - end_read_record(&tab->read_record); + tab->cleanup(); } table= 0; } diff --git a/sql/sql_select.h b/sql/sql_select.h index a463378006b..36526bee066 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -108,6 +108,8 @@ typedef struct st_join_table { TABLE_REF ref; JOIN_CACHE cache; JOIN *join; + + void cleanup(); } JOIN_TAB; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 226086d0d24..75fd9be88bd 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -442,6 +442,12 @@ int st_select_lex_unit::cleanup() int error= 0; DBUG_ENTER("st_select_lex_unit::cleanup"); + if (cleaned) + { + DBUG_RETURN(0); + } + cleaned= 0; + if (union_result) { delete union_result; From 102a9c6f50416b3faf79abd3ea360dd3b49b7513 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Feb 2004 15:42:46 +0400 Subject: [PATCH 17/36] http://bugs.mysql.com/bug.php?id=2368 Multibyte charsets do not check that incoming data is well-formed --- BUILD/compile-pentium-debug-max-no-embedded | 13 +++++ mysql-test/r/ctype_utf8.result | 55 +++++++++++++++++++++ mysql-test/t/ctype_utf8.test | 19 +++++++ sql/field.cc | 32 ++++++------ sql/field.h | 9 ++++ strings/ctype-mb.c | 17 ++++--- 6 files changed, 120 insertions(+), 25 deletions(-) create mode 100755 BUILD/compile-pentium-debug-max-no-embedded diff --git a/BUILD/compile-pentium-debug-max-no-embedded b/BUILD/compile-pentium-debug-max-no-embedded new file mode 100755 index 00000000000..4554e38fdc1 --- /dev/null +++ b/BUILD/compile-pentium-debug-max-no-embedded @@ -0,0 +1,13 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_flags="$pentium_cflags $debug_cflags" +c_warnings="$c_warnings $debug_extra_warnings" +cxx_warnings="$cxx_warnings $debug_extra_warnings" +extra_configs="$pentium_configs $debug_configs" + +extra_configs="$extra_configs --with-berkeley-db --with-innodb --without-isam --with-openssl --with-raid" + +. "$path/FINISH.sh" diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 815ab492fa4..a75b2b6065c 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -88,3 +88,58 @@ select s1,hex(s1),char_length(s1),octet_length(s1) from t1; s1 hex(s1) char_length(s1) octet_length(s1) Á D0B0 1 2 drop table t1; +create table t1 (s1 tinytext character set utf8); +insert into t1 select repeat('a',300); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +insert into t1 select repeat('Ñ',300); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +insert into t1 select repeat('aÑ',300); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +insert into t1 select repeat('Ña',300); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +insert into t1 select repeat('ÑÑ',300); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +select hex(s1) from t1; +hex(s1) +616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 +D18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18F +61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F +D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61 +D18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18F +select length(s1),char_length(s1) from t1; +length(s1) char_length(s1) +255 255 +254 127 +255 170 +255 170 +254 127 +drop table t1; +create table t1 (s1 text character set utf8); +insert into t1 select repeat('a',66000); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +insert into t1 select repeat('Ñ',66000); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +insert into t1 select repeat('aÑ',66000); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +insert into t1 select repeat('Ña',66000); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +insert into t1 select repeat('ÑÑ',66000); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +select length(s1),char_length(s1) from t1; +length(s1) char_length(s1) +65535 65535 +65534 32767 +65535 43690 +65535 43690 +65534 32767 +drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 9da7b32eb6d..0d42533c95f 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -61,3 +61,22 @@ create table t1 (s1 char(1) character set utf8); insert into t1 values (_koi8r'ÁÂ'); select s1,hex(s1),char_length(s1),octet_length(s1) from t1; drop table t1; + +create table t1 (s1 tinytext character set utf8); +insert into t1 select repeat('a',300); +insert into t1 select repeat('Ñ',300); +insert into t1 select repeat('aÑ',300); +insert into t1 select repeat('Ña',300); +insert into t1 select repeat('ÑÑ',300); +select hex(s1) from t1; +select length(s1),char_length(s1) from t1; +drop table t1; + +create table t1 (s1 text character set utf8); +insert into t1 select repeat('a',66000); +insert into t1 select repeat('Ñ',66000); +insert into t1 select repeat('aÑ',66000); +insert into t1 select repeat('Ña',66000); +insert into t1 select repeat('ÑÑ',66000); +select length(s1),char_length(s1) from t1; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index cce7446dcff..d26534b5ac7 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4485,19 +4485,9 @@ void Field_blob::store_length(uint32 number) { switch (packlength) { case 1: - if (number > 255) - { - number=255; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - } ptr[0]= (uchar) number; break; case 2: - if (number > (uint16) ~0) - { - number= (uint16) ~0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - } #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { @@ -4508,11 +4498,6 @@ void Field_blob::store_length(uint32 number) shortstore(ptr,(unsigned short) number); break; case 3: - if (number > (uint32) (1L << 24)) - { - number= (uint32) (1L << 24)-1L; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - } int3store(ptr,number); break; case 4: @@ -4573,6 +4558,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) bool was_conversion; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); + uint copy_length; uint32 not_used; /* Convert character set if nesessary */ @@ -4583,12 +4569,22 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) from= tmpstr.ptr(); length= tmpstr.length(); } - Field_blob::store_length(length); - if (was_conversion || table->copy_blobs || length <= MAX_FIELD_WIDTH) + + copy_length= max_data_length(); + if (copy_length > length) + copy_length= length; + copy_length= field_charset->cset->wellformedlen(field_charset, + from,from+copy_length, + field_length); + if (copy_length < length) + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); + + Field_blob::store_length(copy_length); + if (was_conversion || table->copy_blobs || copy_length <= MAX_FIELD_WIDTH) { // Must make a copy if (from != value.ptr()) // For valgrind { - value.copy(from,length,charset()); + value.copy(from,copy_length,charset()); from=value.ptr(); } } diff --git a/sql/field.h b/sql/field.h index 9a12fd48e54..b62b7a7859e 100644 --- a/sql/field.h +++ b/sql/field.h @@ -949,6 +949,15 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return (uint32) (packlength+table->blob_ptr_size); } + uint32 max_data_length() const + { + switch (packlength) { + case 1: return 255; + case 2: return (uint32) 0xFFFFL; + case 3: return (uint32) 0xFFFFFF; + default: return (uint32) 0xFFFFFFFF; + } + } void reset(void) { bzero(ptr, packlength+sizeof(char*)); } void reset_fields() { bzero((char*) &value,sizeof(value)); } void store_length(uint32 number); diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 377bf311d38..46f3e2f4fc3 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -274,18 +274,21 @@ uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)), return pos ? e+2-b0 : b-b0; } -uint my_wellformedlen_mb(CHARSET_INFO *cs __attribute__((unused)), - const char *b, const char *e, uint pos) +uint my_wellformedlen_mb(CHARSET_INFO *cs, + const char *b, const char *e, uint pos) { - uint mblen; - const char *b0=b; + my_wc_t wc; + int mblen; + const char *b0= b; - while (pos && bcset->mb_wc(cs, &wc, b, e)) <0) + break; + b+= mblen; pos--; } - return b-b0; + return b - b0; } From b4fc7c7fbf643b39f3686bfe344b21cdd7233fb5 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Feb 2004 17:09:59 +0400 Subject: [PATCH 18/36] Fix for #2208 (multi-query returns wrong result in embedded library) now we execute only one first select during mysql_real_query others - during 'mysql_next_result' include/mysql.h: 'virtual' next_result added libmysql/client_settings.h: cli_next_result declaration added libmysql/libmysql.c: mysql_next_result now works in embedded library as well libmysqld/lib_sql.cc: emb_next_result implemented sql/sql_class.h: fields to store the rest of the query added sql/sql_parse.cc: Saving the rest of the query added for embedded case --- include/mysql.h | 1 + libmysql/client_settings.h | 1 + libmysql/libmysql.c | 25 ++++++++++++++++--------- libmysqld/lib_sql.cc | 20 +++++++++++++++++++- sql/sql_class.h | 2 ++ sql/sql_parse.cc | 13 +++++++++++-- 6 files changed, 50 insertions(+), 12 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index d1b467f9649..3679b65ba4a 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -575,6 +575,7 @@ typedef struct st_mysql_methods int (*unbuffered_fetch)(MYSQL *mysql, char **row); void (*free_embedded_thd)(MYSQL *mysql); const char *(*read_statistic)(MYSQL *mysql); + int (*next_result)(MYSQL *mysql); #endif } MYSQL_METHODS; diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index b1a85f567f9..6a7da0bcc81 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -58,6 +58,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt); MYSQL_DATA * cli_read_binary_rows(MYSQL_STMT *stmt); int cli_unbuffered_fetch(MYSQL *mysql, char **row); const char * cli_read_statistic(MYSQL *mysql); +int cli_next_result(MYSQL *mysql); #ifdef EMBEDDED_LIBRARY int init_embedded_server(int argc, char **argv, char **groups); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 977657f8998..a3e88ccd03d 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -3511,6 +3511,21 @@ my_bool STDCALL mysql_more_results(MYSQL *mysql) Reads and returns the next query results */ +int cli_next_result(MYSQL *mysql) +{ + DBUG_ENTER("cli_next_result"); + + mysql->net.last_error[0]= 0; + mysql->net.last_errno= 0; + strmov(mysql->net.sqlstate, not_error_sqlstate); + mysql->affected_rows= ~(my_ulonglong) 0; + + if (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) + DBUG_RETURN((*mysql->methods->read_query_result)(mysql)); + + DBUG_RETURN(-1); /* No more results */ +} + int STDCALL mysql_next_result(MYSQL *mysql) { DBUG_ENTER("mysql_next_result"); @@ -3523,15 +3538,7 @@ int STDCALL mysql_next_result(MYSQL *mysql) DBUG_RETURN(1); } - mysql->net.last_error[0]= 0; - mysql->net.last_errno= 0; - strmov(mysql->net.sqlstate, not_error_sqlstate); - mysql->affected_rows= ~(my_ulonglong) 0; - - if (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) - DBUG_RETURN((*mysql->methods->read_query_result)(mysql)); - - DBUG_RETURN(-1); /* No more results */ + DBUG_RETURN((*mysql->methods->next_result)(mysql)); } diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index e36e878d4b1..81235ce0c22 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -245,6 +245,18 @@ static MYSQL_RES * emb_mysql_store_result(MYSQL *mysql) return mysql_store_result(mysql); } +int emb_next_result(MYSQL *mysql) +{ + THD *thd= (THD*)mysql->thd; + DBUG_ENTER("emb_next_result"); + + if (emb_advanced_command(mysql, COM_QUERY,0,0, + thd->query_rest,thd->query_rest_length,1) + || emb_mysql_read_query_result(mysql)) + DBUG_RETURN(1); + + DBUG_RETURN(0); /* No more results */ +} MYSQL_METHODS embedded_methods= { @@ -259,7 +271,8 @@ MYSQL_METHODS embedded_methods= emb_read_binary_rows, emb_unbuffered_fetch, emb_free_embedded_thd, - emb_read_statistic + emb_read_statistic, + emb_next_result }; C_MODE_END @@ -749,6 +762,11 @@ bool Protocol::net_store_data(const char *from, uint length) return false; } +char *memdup_mysql(struct st_mysql *mysql, const char*data, int length) +{ + return memdup_root(&mysql->field_alloc, data, length); +} + #if 0 /* The same as Protocol::net_store_data but does the converstion */ diff --git a/sql/sql_class.h b/sql/sql_class.h index 7971137d848..879d75fe26a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -565,6 +565,8 @@ public: struct st_mysql_bind *client_params; char *extra_data; ulong extra_length; + char *query_rest; + uint32 query_rest_length; #endif NET net; // client connection descriptor MEM_ROOT warn_root; // For warnings and errors diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9d742995976..564c22dd004 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -48,6 +48,7 @@ extern "C" int gethostname(char *name, int namelen); #endif +char *memdup_mysql(struct st_mysql *mysql, const char*data, int length); static int check_for_max_user_connections(THD *thd, USER_CONN *uc); static void decrease_user_connections(USER_CONN *uc); static bool check_db_used(THD *thd,TABLE_LIST *tables); @@ -1397,11 +1398,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, char *packet= thd->lex->found_colon; /* Multiple queries exits, execute them individually + in embedded server - just store them to be executed later */ +#ifndef EMBEDDED_LIBRARY if (thd->lock || thd->open_tables || thd->derived_tables) close_thread_tables(thd); - - ulong length= thd->query_length-(ulong)(thd->lex->found_colon-thd->query); +#endif + ulong length= thd->query_length-(ulong)(packet-thd->query); /* Remove garbage at start of query */ while (my_isspace(thd->charset(), *packet) && length > 0) @@ -1414,7 +1417,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id= query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); +#ifndef EMBEDDED_LIBRARY mysql_parse(thd, packet, length); +#else + thd->query_rest= (char*)memdup_mysql(thd->mysql, packet, length); + thd->query_rest_length= length; + break; +#endif /*EMBEDDED_LIBRARY*/ } if (!(specialflag & SPECIAL_NO_PRIOR)) From 4138b2ac5f51e71737b025ce04342866b384edc4 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Feb 2004 13:11:55 +0000 Subject: [PATCH 19/36] An include was missing. BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + sql/sql_string.cc | 1 + 2 files changed, 2 insertions(+) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index a7eb7c81105..2eb24c49273 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -54,6 +54,7 @@ jani@janikt.pp.saunalahti.fi jani@rhols221.adsl.netsonic.fi jani@rhols221.arenanet.fi jani@ua126d19.elisa.omakaista.fi +jani@ua141d10.elisa.omakaista.fi jani@ua167d18.elisa.omakaista.fi jcole@abel.spaceapes.com jcole@main.burghcom.com diff --git a/sql/sql_string.cc b/sql/sql_string.cc index cbee67c0a4a..093b85b46b7 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef HAVE_FCONVERT #include #endif From dc792940232f3265e21905cb939853f4db5ebd16 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Feb 2004 13:36:21 +0000 Subject: [PATCH 20/36] Wrong type of an argument was sent to my_printf_error(), which caused UDF functions to segmenation fault when they tried to print an error during wrong usage. --- sql/item_func.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/item_func.cc b/sql/item_func.cc index b1378784f92..34a61ba0353 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1552,7 +1552,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, if ((error=(uchar) init(&initid, &f_args, thd->net.last_error))) { my_printf_error(ER_CANT_INITIALIZE_UDF,ER(ER_CANT_INITIALIZE_UDF),MYF(0), - u_d->name,thd->net.last_error); + u_d->name.str, thd->net.last_error); free_udf(u_d); DBUG_RETURN(1); } @@ -1565,7 +1565,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, if (error) { my_printf_error(ER_CANT_INITIALIZE_UDF,ER(ER_CANT_INITIALIZE_UDF),MYF(0), - u_d->name, ER(ER_UNKNOWN_ERROR)); + u_d->name.str, ER(ER_UNKNOWN_ERROR)); DBUG_RETURN(1); } DBUG_RETURN(0); From 94f215cbe1d75b5eaf88f0e022a53918a36609a5 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Feb 2004 16:58:20 +0300 Subject: [PATCH 21/36] Fixed bug #2248 "mysql_fetch without prior mysql_execute hangs" Done clean-up in prep stmt API functions: 1) Removed some checks that were performed only in debug version were making debug version more tolerable to user errors than production (and thus caused problems for example masking some bugs). 2) Also removed some other checks to make prep stmt API consistent with the rest of C API (this also in line with general politics - make checks in only those places where errors are very common and hard to spot). include/mysql.h: Removed CHECK_EXTRA_ARGUMENTS define since it is no longer used anywhere. libmysql/libmysql.c: Added check that will cause mysql_fetch() to bark then it is used without calling mysql_execute() before. Removed checks that were performed only in debug version and caused problems since they were making debug version more tolerable to user errors than production. Also removed some other checks to make prep stmt API consistent in this regard with the rest of C API (this also in line with general politics - make checks in only those places where errors are very common and hard to spot). tests/client_test.c: Updated tests to reflect removal of some checks in prep stmt API. Removed lines that caused bug #2473 to pop up, should be added as separate test with the fix for this bug. Added test for bug#2248 "mysql_fetch without prior mysql_execute hangs" --- include/mysql.h | 3 -- libmysql/libmysql.c | 70 +++++--------------------------- tests/client_test.c | 98 +++++++++++++++++++++++++++++++-------------- 3 files changed, 79 insertions(+), 92 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index d1b467f9649..ebf3928ce9c 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -57,9 +57,6 @@ typedef int my_socket; #include "mysql_com.h" #include "mysql_version.h" #include "typelib.h" -#ifndef DBUG_OFF -#define CHECK_EXTRA_ARGUMENTS -#endif #include "my_list.h" /* for LISTs used in 'MYSQL' and 'MYSQL_STMT' */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 977657f8998..829ee09090e 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1653,14 +1653,6 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length) DBUG_ENTER("mysql_prepare"); DBUG_ASSERT(mysql != 0); -#ifdef CHECK_EXTRA_ARGUMENTS - if (!query) - { - set_mysql_error(mysql, CR_NULL_POINTER, unknown_sqlstate); - DBUG_RETURN(0); - } -#endif - if (!(stmt= (MYSQL_STMT *) my_malloc(sizeof(MYSQL_STMT), MYF(MY_WME | MY_ZEROFILL))) || !(stmt->query= my_strdup_with_length((byte *) query, length, MYF(0)))) @@ -2086,19 +2078,6 @@ int STDCALL mysql_execute(MYSQL_STMT *stmt) { DBUG_ENTER("mysql_execute"); - if (stmt->state == MY_ST_UNKNOWN) - { - set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate); - DBUG_RETURN(1); - } -#ifdef CHECK_EXTRA_ARGUMENTS - if (stmt->param_count && !stmt->param_buffers) - { - /* Parameters exists, but no bound buffers */ - set_stmt_error(stmt, CR_NOT_ALL_PARAMS_BOUND, unknown_sqlstate); - DBUG_RETURN(1); - } -#endif if ((*stmt->mysql->methods->stmt_execute)(stmt)) DBUG_RETURN(1); @@ -2144,19 +2123,6 @@ my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind) MYSQL_BIND *param, *end; DBUG_ENTER("mysql_bind_param"); -#ifdef CHECK_EXTRA_ARGUMENTS - if (stmt->state == MY_ST_UNKNOWN) - { - set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate); - DBUG_RETURN(1); - } - if (!stmt->param_count) - { - set_stmt_error(stmt, CR_NO_PARAMETERS_EXISTS, unknown_sqlstate); - DBUG_RETURN(1); - } -#endif - /* Allocated on prepare */ memcpy((char*) stmt->params, (char*) bind, sizeof(MYSQL_BIND) * stmt->param_count); @@ -2279,11 +2245,6 @@ mysql_send_long_data(MYSQL_STMT *stmt, uint param_number, DBUG_PRINT("enter",("param no : %d, data : %lx, length : %ld", param_number, data, length)); - if (param_number >= stmt->param_count) - { - set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate); - DBUG_RETURN(1); - } param= stmt->params+param_number; if (param->buffer_type < MYSQL_TYPE_TINY_BLOB || param->buffer_type > MYSQL_TYPE_STRING) @@ -2853,18 +2814,6 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) DBUG_ENTER("mysql_bind_result"); DBUG_ASSERT(stmt != 0); -#ifdef CHECK_EXTRA_ARGUMENTS - if (stmt->state == MY_ST_UNKNOWN) - { - set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate); - DBUG_RETURN(1); - } - if (!bind) - { - set_stmt_error(stmt, CR_NULL_POINTER, unknown_sqlstate); - DBUG_RETURN(1); - } -#endif if (!(bind_count= stmt->field_count) && !(bind_count= alloc_stmt_fields(stmt))) DBUG_RETURN(0); @@ -3035,6 +2984,15 @@ int STDCALL mysql_fetch(MYSQL_STMT *stmt) } else /* un-buffered */ { + if (mysql->status != MYSQL_STATUS_GET_RESULT) + { + if (!stmt->field_count) + goto no_data; + + set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); + DBUG_RETURN(1); + } + if((*mysql->methods->unbuffered_fetch)(mysql, ( char **)&row)) { set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, @@ -3065,7 +3023,7 @@ no_data: mysql_fetch_column() stmt Prepared statement handler bind Where data should be placed. Should be filled in as - when calling mysql_bind_param() + when calling mysql_bind_result() column Column to fetch (first column is 0) ulong offset Offset in result data (to fetch blob in pieces) This is normally 0 @@ -3083,14 +3041,6 @@ int STDCALL mysql_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind, if (!stmt->current_row) goto no_data; -#ifdef CHECK_EXTRA_ARGUMENTS - if (column >= stmt->field_count) - { - set_stmt_errmsg(stmt, "Invalid column descriptor",1, unknown_sqlstate); - DBUG_RETURN(1); - } -#endif - if (param->null_field) { if (bind->is_null) diff --git a/tests/client_test.c b/tests/client_test.c index 66637dcb04b..992c0ce5e78 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -953,8 +953,6 @@ static void test_prepare_simple() verify_param_count(stmt,1); - rc = mysql_execute(stmt); - mystmt_r(stmt, rc); mysql_stmt_close(stmt); /* select */ @@ -5589,27 +5587,24 @@ static void test_pure_coverage() stmt = mysql_prepare(mysql,"insert into test_pure(c67788) values(10)",100); mystmt_init_r(stmt); -#ifndef DBUG_OFF - stmt = mysql_prepare(mysql,(const char *)0,0); - mystmt_init_r(stmt); - + /* Query without params and result should allow to bind 0 arrays */ stmt = mysql_prepare(mysql,"insert into test_pure(c2) values(10)",100); mystmt_init(stmt); + + rc = mysql_bind_param(stmt, (MYSQL_BIND*)0); + mystmt(stmt, rc); + + rc = mysql_execute(stmt); + mystmt(stmt, rc); - rc = mysql_bind_param(stmt, bind); - mystmt_r(stmt, rc); - + rc = mysql_bind_result(stmt, (MYSQL_BIND*)0); + mystmt(stmt, rc); + mysql_stmt_close(stmt); -#endif stmt = mysql_prepare(mysql,"insert into test_pure(c2) values(?)",100); mystmt_init(stmt); -#ifndef DBUG_OFF - rc = mysql_execute(stmt); - mystmt_r(stmt, rc);/* No parameters supplied */ -#endif - bind[0].length= &length; bind[0].is_null= 0; bind[0].buffer_length= 0; @@ -5622,9 +5617,6 @@ static void test_pure_coverage() rc = mysql_bind_param(stmt, bind); mystmt(stmt, rc); - rc = mysql_send_long_data(stmt, 20, (char *)"venu", 4); - mystmt_r(stmt, rc); /* wrong param number */ - rc = mysql_stmt_store_result(stmt); mystmt(stmt, rc); @@ -5636,14 +5628,9 @@ static void test_pure_coverage() rc = mysql_execute(stmt); mystmt(stmt, rc); -#ifndef DBUG_OFF - rc = mysql_bind_result(stmt, (MYSQL_BIND *)0); - mystmt_r(stmt, rc); - bind[0].buffer_type= MYSQL_TYPE_GEOMETRY; rc = mysql_bind_result(stmt, bind); mystmt_r(stmt, rc); /* unsupported buffer type */ -#endif rc = mysql_stmt_store_result(stmt); mystmt(stmt, rc); @@ -7291,9 +7278,6 @@ static void test_fetch_offset() rc = mysql_fetch(stmt); mystmt(stmt,rc); - rc = mysql_fetch_column(stmt,bind,4,0); - mystmt_r(stmt,rc); - data[0]= '\0'; rc = mysql_fetch_column(stmt,bind,0,0); mystmt(stmt,rc); @@ -7411,9 +7395,6 @@ static void test_fetch_column() fprintf(stdout, "\n col 0: %d(%ld)", c1, l1); assert(c1 == 1 && l1 == 4); - rc = mysql_fetch_column(stmt,bind,10,0); - mystmt_r(stmt,rc); - rc = mysql_fetch(stmt); mystmt(stmt,rc); @@ -8096,6 +8077,64 @@ static void test_bug1946() } +/* + Test for bug#2248 "mysql_fetch without prior mysql_execute hangs" +*/ + +static void test_bug2248() +{ + MYSQL_STMT *stmt; + int rc; + const char *query1= "SELECT DATABASE()"; + const char *query2= "INSERT INTO test_bug2248 VALUES (10)"; + + myheader("test_bug2248"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bug2248"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE test_bug2248 (id int)"); + myquery(rc); + + stmt= mysql_prepare(mysql, query1, strlen(query1)); + mystmt_init(stmt); + + /* This should not hang */ + rc= mysql_fetch(stmt); + mystmt_r(stmt,rc); + + /* And this too */ + rc= mysql_stmt_store_result(stmt); + mystmt_r(stmt,rc); + + mysql_stmt_close(stmt); + + stmt= mysql_prepare(mysql, query2, strlen(query2)); + mystmt_init(stmt); + + rc= mysql_execute(stmt); + mystmt(stmt,rc); + + /* This too should not hang but should return proper error */ + rc= mysql_fetch(stmt); + assert(rc==MYSQL_NO_DATA); + + /* This too should not hang but should not bark */ + rc= mysql_stmt_store_result(stmt); + mystmt(stmt,rc); + + /* This should return proper error */ + rc= mysql_fetch(stmt); + mystmt_r(stmt,rc); + assert(rc==MYSQL_NO_DATA); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql,"DROP TABLE test_bug2248"); + myquery(rc); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -8340,6 +8379,7 @@ int main(int argc, char **argv) test_bug1644(); /* BUG#1644 */ test_bug1946(); /* test that placeholders are allowed only in prepared queries */ + test_bug2248(); /* BUG#2248 */ end_time= time((time_t *)0); total_time+= difftime(end_time, start_time); From 757c8c8a62b6b780f48d6f197981839ebb028fb8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Feb 2004 15:14:48 +0100 Subject: [PATCH 22/36] Follow-up of a discussion on dev-docs@ : Don't show PSEUDO_THREAD_ID in SHOW VARIABLES because: - we don't want people to discover this variable as it could never do good to set it (it was designed for use by mysqlbinlog only, so that a thread can have several temp tables of the same name at the same time) - if we show it in SHOW VARIABLES, Mysql Administrator will display it and this will force us to put a description, so all MySQL Administrator user will be aware of this variable, some may have the idea to set it with a SET command, and then it will cause bad things. The variable is still settable, and still visible with SELECT @@. sql/set_var.cc: Don't show PSEUDO_THREAD_ID in SHOW VARIABLES because: - we don't want people to discover this variable as it could never do good to set it (it was designed for use by mysqlbinlog only, so that a thread can have several temp tables of the same name at the same time) - if we show it in SHOW VARIABLES, Mysql Administrator will display it and this will force us to put a description, so all MySQL Administrator user will be aware of this variable, some may have the idea to set it with a SET command, and then it will cause bad things. The variable is still settable, and still visible with SELECT @@. --- sql/set_var.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/sql/set_var.cc b/sql/set_var.cc index ecb85440068..073330e06be 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -695,7 +695,6 @@ struct show_var_st init_vars[]= { {"port", (char*) &mysqld_port, SHOW_INT}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, - {sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS}, {sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size, SHOW_SYS}, #ifdef HAVE_QUERY_CACHE From aaa35925ac66b00eb1fcee5e4bcc9c05472f6950 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Feb 2004 18:44:27 +0400 Subject: [PATCH 23/36] added skiped newline to the end of file mysql-test/t/mysqldump.test mysql-test/t/mysqldump.test: added skiped newline to the end of file --- mysql-test/t/mysqldump.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index e6115b61bbf..eca83ce77d8 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -60,4 +60,4 @@ DROP TABLE t1; create table ```a` (i int); --exec $MYSQL_DUMP --skip-comments test -drop table ```a`; \ No newline at end of file +drop table ```a`; From e4f3eb79be9dc5da27097f73e9477d9318373105 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Feb 2004 19:29:28 +0400 Subject: [PATCH 24/36] correcting mysql-test/r/mysqldump.result after merge mysql-test/r/mysqldump.result: correcting result after merge --- mysql-test/r/mysqldump.result | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 37a604258d9..fd9e2a1f42b 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -180,6 +180,11 @@ UNLOCK TABLES; DROP TABLE t1; create table ```a` (i int); + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */; DROP TABLE IF EXISTS ```a`; CREATE TABLE ``a` ( `i` int(11) default NULL From ad2c55b6ce922f9541d15b6817ce54419c462e2b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Feb 2004 19:33:04 +0400 Subject: [PATCH 25/36] Bug #2368 Multibyte charsets do not check that incoming data is well-formed It was together with the previous but. This test tends to prove it. --- mysql-test/r/ctype_utf8.result | 24 ++++++++++++++++++++++++ mysql-test/t/ctype_utf8.test | 18 ++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index a75b2b6065c..658a7b8f5f6 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -143,3 +143,27 @@ length(s1) char_length(s1) 65535 43690 65534 32767 drop table t1; +create table t1 (s1 char(10) character set utf8); +insert into t1 values (0x41FF); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +select hex(s1) from t1; +hex(s1) +41 +drop table t1; +create table t1 (s1 varchar(10) character set utf8); +insert into t1 values (0x41FF); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +select hex(s1) from t1; +hex(s1) +41 +drop table t1; +create table t1 (s1 text character set utf8); +insert into t1 values (0x41FF); +Warnings: +Warning 1264 Data truncated for column 's1' at row 1 +select hex(s1) from t1; +hex(s1) +41 +drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 0d42533c95f..0615de99b7a 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -80,3 +80,21 @@ insert into t1 select repeat(' insert into t1 select repeat('ÑÑ',66000); select length(s1),char_length(s1) from t1; drop table t1; + +# +# Bug #2368 Multibyte charsets do not check that incoming data is well-formed +# +create table t1 (s1 char(10) character set utf8); +insert into t1 values (0x41FF); +select hex(s1) from t1; +drop table t1; + +create table t1 (s1 varchar(10) character set utf8); +insert into t1 values (0x41FF); +select hex(s1) from t1; +drop table t1; + +create table t1 (s1 text character set utf8); +insert into t1 values (0x41FF); +select hex(s1) from t1; +drop table t1; From f709bc18607a52d280e13aab3fb0a29ff09a214b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Feb 2004 19:33:05 +0400 Subject: [PATCH 26/36] configure.in: FreeBSD "ps" detection usually failed, in 90% cases, on FreeBSD-5.1. This change should work fine under 5.x and 4.x, and I believe in 3.x. too. configure.in: FreeBSD "ps" detection usually failed, in 90% cases. Thi --- configure.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure.in b/configure.in index e607f87747b..9cdb9d209c2 100644 --- a/configure.in +++ b/configure.in @@ -452,6 +452,9 @@ then FIND_PROC="$PS \$\$PID | grep mysqld > /dev/null" else case $SYSTEM_TYPE in + *freebsd*) + FIND_PROC="$PS p \$\$PID | grep mysqld > /dev/null" + ;; *darwin*) FIND_PROC="$PS -uaxww | grep mysqld | grep \" \$\$PID \" > /dev/null" ;; From 98216bc9d4a65bd133d9a374fd3fe77d8c333d33 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Feb 2004 18:33:06 +0300 Subject: [PATCH 27/36] Another implementation of send_eof() cleanup --- sql/protocol.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sql/protocol.cc b/sql/protocol.cc index bef567ad346..40adc9e8961 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -313,6 +313,7 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) DBUG_VOID_RETURN; } +static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */ /* Send eof (= end of result set) to the client @@ -339,12 +340,11 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) void send_eof(THD *thd, bool no_flush) { - static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */ NET *net= &thd->net; DBUG_ENTER("send_eof"); if (net->vio != 0) { - if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41)) + if (thd->client_capabilities & CLIENT_PROTOCOL_41) { uchar buff[5]; uint tmp= min(thd->total_warn_count, 65535); @@ -384,9 +384,8 @@ send_eof(THD *thd, bool no_flush) bool send_old_password_request(THD *thd) { - static char buff[1]= { (char) 254 }; NET *net= &thd->net; - return my_net_write(net, buff, 1) || net_flush(net); + return my_net_write(net, eof_buff, 1) || net_flush(net); } #endif /* EMBEDDED_LIBRARY */ @@ -585,7 +584,7 @@ bool Protocol::send_fields(List *list, uint flag) #endif } - send_eof(thd, 1); + my_net_write(&thd->net, eof_buff, 1); DBUG_RETURN(prepare_for_send(list)); err: From 69651163209efd701736fe09da4648e3b5ba1aa7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Feb 2004 00:47:18 +0400 Subject: [PATCH 28/36] code cleanup of processing MY_LEX_USER_VARIABLE_DELIMITER in sql/sql_lex.cc sql/sql_lex.cc: code cleanup of processing MY_LEX_USER_VARIABLE_DELIMITER --- sql/sql_lex.cc | 53 ++++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 2484ff0e30f..70c69bb7389 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -193,6 +193,13 @@ static LEX_STRING get_token(LEX *lex,uint length) return tmp; } +/* + todo: + There are no dangerous charsets in mysql for function + get_quoted_token yet. But it should be fixed in the + future to operate multichar strings (like ucs2) +*/ + static LEX_STRING get_quoted_token(LEX *lex,uint length, char quote) { LEX_STRING tmp; @@ -670,37 +677,14 @@ int yylex(void *arg, void *yythd) uint double_quotes= 0; char quote_char= c; // Used char lex->tok_start=lex->ptr; // Skip first ` + while ((c=yyGet())) + { #ifdef USE_MB - if (use_mb(cs)) - { - while ((c= yyGet())) - { - if (c == quote_char) - { - if (yyPeek() != quote_char) - break; - c= yyGet(); - double_quotes++; - continue; - } - if (c == (uchar) NAMES_SEP_CHAR) - break; - if (my_mbcharlen(cs, c) > 1) - { - int l; - if ((l = my_ismbchar(cs, - (const char *)lex->ptr-1, - (const char *)lex->end_of_query)) == 0) - break; - lex->ptr += l-1; - } - } - } - else + if (my_mbcharlen(cs, c) == 1) #endif - { - while ((c=yyGet())) { + if (c == (uchar) NAMES_SEP_CHAR) + break; /* Old .frm format can't handle this char */ if (c == quote_char) { if (yyPeek() != quote_char) @@ -709,9 +693,18 @@ int yylex(void *arg, void *yythd) double_quotes++; continue; } - if (c == (uchar) NAMES_SEP_CHAR) - break; } +#ifdef USE_MB + else + { + int l; + if ((l = my_ismbchar(cs, + (const char *)lex->ptr-1, + (const char *)lex->end_of_query)) == 0) + break; + lex->ptr += l-1; + } +#endif } if (double_quotes) yylval->lex_str=get_quoted_token(lex,yyLength() - double_quotes, From 38caa8c060053ef58017e0fa227eb3763f56e6ac Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Feb 2004 23:47:34 +0100 Subject: [PATCH 29/36] Fix for prepared statements: added setting of 'neg' in Item_param::set_time() (looks like the only forgotten member). It's the second place I find where 'neg' was forgotten. The symptom was unexpected negative times in the binary log when running tests/client_test.c (test_date() in fact): # at 43009 #040210 15:46:42 server id 1 log_pos 43009 Query thread_id=1 exec_time=0 error_code=0 SET TIMESTAMP=1076424402; INSERT INTO test_date VALUES('2000-01-10 11:16:20','-11:16:20' etc sql/item.cc: Don't forget to copy 'neg'. --- sql/item.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/item.cc b/sql/item.cc index 4d06d0d7765..850d5a3cad3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -568,6 +568,8 @@ void Item_param::set_time(TIME *tm, timestamp_type type) ltime.second_part= tm->second_part; + ltime.neg= tm->neg; + ltime.time_type= type; item_is_time= true; From 24e3862cb8752618a5c8d5a41eb739e698b727cb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Feb 2004 15:15:39 +0400 Subject: [PATCH 30/36] mysqlimport.c, mysqldump.c, mysqlcheck.c, mysql.cc: No needs to load charset index if the character set is build-in. client/mysql.cc: No needs to load charset index if the character set is build-in. client/mysqlcheck.c: No needs to load charset index if the character set is build-in. client/mysqldump.c: No needs to load charset index if the character set is build-in. client/mysqlimport.c: No needs to load charset index if the character set is build-in. --- client/mysql.cc | 4 +++- client/mysqlcheck.c | 3 ++- client/mysqldump.c | 3 ++- client/mysqlimport.c | 3 ++- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 665a8dde82d..eb466a86c91 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -839,7 +839,9 @@ static int get_options(int argc, char **argv) opt_reconnect= 0; connect_flag= 0; /* Not in interactive mode */ } - if (!(charset_info= get_charset_by_csname(default_charset, + + if (strcmp(default_charset, charset_info->csname) && + !(charset_info= get_charset_by_csname(default_charset, MY_CS_PRIMARY, MYF(MY_WME)))) exit(1); if (argc > 1) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 1768d948373..03ab45957d4 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -311,7 +311,8 @@ static int get_options(int *argc, char ***argv) } /* TODO: This variable is not yet used */ - if (!(charset_info= get_charset_by_csname(default_charset, + if (strcmp(default_charset, charset_info->csname) && + !(charset_info= get_charset_by_csname(default_charset, MY_CS_PRIMARY, MYF(MY_WME)))) exit(1); if (*argc > 0 && opt_alldbs) diff --git a/client/mysqldump.c b/client/mysqldump.c index 1383e0e0d02..345c7f0b945 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -536,7 +536,8 @@ static int get_options(int *argc, char ***argv) my_progname); return(1); } - if (!(charset_info= get_charset_by_csname(default_charset, + if (strcmp(default_charset, charset_info->csname) && + !(charset_info= get_charset_by_csname(default_charset, MY_CS_PRIMARY, MYF(MY_WME)))) exit(1); if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs)) diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 5ad6d1dc429..d47ae48b1ac 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -238,7 +238,8 @@ static int get_options(int *argc, char ***argv) fprintf(stderr, "You can't use --ignore (-i) and --replace (-r) at the same time.\n"); return(1); } - if (!(charset_info= get_charset_by_csname(default_charset, + if (strcmp(default_charset, charset_info->csname) && + !(charset_info= get_charset_by_csname(default_charset, MY_CS_PRIMARY, MYF(MY_WME)))) exit(1); if (*argc < 2) From 0aa48dc500a38c46ee5fa47e26382260364b06f5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Feb 2004 12:32:47 +0100 Subject: [PATCH 31/36] Fix for BUG#2703 "MySQL server does not detect if garbage chars at the end of query": Detect garbage chars at the end of the query or at the end of a query for a prepared statement (which happens if mysql_real_query() or mysql_prepare() were called with a too big 'length' parameter (bigger than the real intended length of the query: then we receive a query + garbage characters from the client). This resulted in garbage chars written into the binlog. Now instead the client receives something like: 'You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '!stmt' at line 1' i.e. the server is pointing at the weird tail of the query (this '!stmt' are the garbage chars sent by the client). All tests pass, except mysqldump.test and ctype_utf8.test but they failed before the patch. sql/sql_parse.cc: Detect garbage chars at the end of the query (which happens if mysql_real_query() was called with a too big 'length' parameter (bigger than the real intended length of the query: then we receive a query + garbage characters from the client). sql/sql_prepare.cc: Detect garbage chars at the end of the query (which happens if mysql_prepare() was called with a too big 'length' parameter (bigger than the real intended length of the query: then we receive a query + garbage characters from the client). tests/client_test.c: The change to sql_parse.cc and sql_prepare.cc rightfully gives many syntax errors to tests/client_test.c which is full of mysql_prepare(mysql, "SHOW TABLES", 100). Correcting all these commands. --- sql/sql_parse.cc | 18 ++- sql/sql_prepare.cc | 10 +- tests/client_test.c | 317 +++++++++++++++++++++++++------------------- 3 files changed, 203 insertions(+), 142 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 42ea6039b6c..80aa575265b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3845,7 +3845,23 @@ mysql_parse(THD *thd, char *inBuf, uint length) if (query_cache_send_result_to_client(thd, inBuf, length) <= 0) { LEX *lex=lex_start(thd, (uchar*) inBuf, length); - if (!yyparse((void *)thd) && ! thd->is_fatal_error) + if (!yyparse((void *)thd) && ! thd->is_fatal_error && + /* + If this is not a multiple query, ensure that it has been + successfully parsed until the last character. This is to prevent + against a wrong (too big) length passed to mysql_real_query(), + mysql_prepare()... which can generate garbage characters at the + end. If the query was initially multiple, found_colon will be false + only when we are in the last query; this last query had already + been end-spaces-stripped by alloc_query() in dispatch_command(); as + end spaces are the only thing we accept at the end of a query, and + they have been stripped already, here we can require that nothing + remains after parsing. + */ + (thd->lex->found_colon || + (char*)(thd->lex->ptr) == (thd->query+thd->query_length+1) || + /* yyerror() will show the garbage chars to the user */ + (yyerror("syntax error"), 0))) { #ifndef NO_EMBEDDED_ACCESS_CHECKS if (mqh_used && thd->user_connect && diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 2cf0000d973..cf723e18d85 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -909,7 +909,15 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) lex->safe_to_cache_query= 0; lex->param_count= 0; - if (yyparse((void *)thd) || thd->is_fatal_error || send_prepare_results(stmt)) + if (yyparse((void *)thd) || thd->is_fatal_error || + /* + Check for wrong (too big) length passed to mysql_prepare() resulting in + garbage at the end of the query. There is a similar check in mysql_parse(). + */ + (!thd->lex->found_colon && + (char*)(thd->lex->ptr) != (thd->query+thd->query_length+1) && + /* yyerror() will show the garbage chars to the user */ + (yyerror("syntax error"), 1)) || send_prepare_results(stmt)) goto yyparse_err; lex_end(lex); diff --git a/tests/client_test.c b/tests/client_test.c index 66637dcb04b..e0785f9d633 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -153,6 +153,17 @@ static void print_st_error(MYSQL_STMT *stmt, const char *msg) else if (msg) fprintf(stderr, " [MySQL] %s\n", msg); } +/* + This is to be what mysql_query() is for mysql_real_query(), for + mysql_prepare(): a variant without the 'length' parameter. +*/ +MYSQL_STMT *STDCALL +mysql_simple_prepare(MYSQL *mysql, const char *query) +{ + return mysql_prepare(mysql, query, strlen(query)); +} + + /******************************************************** * connect to the server * *********************************************************/ @@ -459,14 +470,14 @@ uint my_process_stmt_result(MYSQL_STMT *stmt) /******************************************************** * process the stmt result set * *********************************************************/ -uint my_stmt_result(const char *buff, unsigned long length) +uint my_stmt_result(const char *buff) { MYSQL_STMT *stmt; uint row_count; int rc; fprintf(stdout,"\n\n %s", buff); - stmt= mysql_prepare(mysql,buff,length); + stmt= mysql_simple_prepare(mysql,buff); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -605,7 +616,7 @@ static void execute_prepare_query(const char *query, ulonglong exp_count) ulonglong affected_rows; int rc; - stmt= mysql_prepare(mysql,query,strlen(query)); + stmt= mysql_simple_prepare(mysql,query); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -913,7 +924,7 @@ static void test_prepare_simple() /* alter table */ strmov(query,"ALTER TABLE test_prepare_simple ADD new char(20)"); - stmt = mysql_prepare(mysql, query, 70); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,0); @@ -921,7 +932,7 @@ static void test_prepare_simple() /* insert */ strmov(query,"INSERT INTO test_prepare_simple VALUES(?,?)"); - stmt = mysql_prepare(mysql, query, 70); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -929,7 +940,7 @@ static void test_prepare_simple() /* update */ strmov(query,"UPDATE test_prepare_simple SET id=? WHERE id=? AND name= ?"); - stmt = mysql_prepare(mysql, query, 100); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,3); @@ -937,7 +948,7 @@ static void test_prepare_simple() /* delete */ strmov(query,"DELETE FROM test_prepare_simple WHERE id=10"); - stmt = mysql_prepare(mysql, query, 60); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,0); @@ -948,7 +959,7 @@ static void test_prepare_simple() /* delete */ strmov(query,"DELETE FROM test_prepare_simple WHERE id=?"); - stmt = mysql_prepare(mysql, query, 50); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,1); @@ -959,7 +970,7 @@ static void test_prepare_simple() /* select */ strmov(query,"SELECT * FROM test_prepare_simple WHERE id=? AND name= ?"); - stmt = mysql_prepare(mysql, query, 100); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -997,7 +1008,7 @@ static void test_prepare_field_result() /* insert */ strmov(query,"SELECT int_c,var_c,date_c as date,ts_c,char_c FROM \ test_prepare_field_result as t1 WHERE int_c=?"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,1); @@ -1045,11 +1056,11 @@ static void test_prepare_syntax() myquery(rc); strmov(query,"INSERT INTO test_prepare_syntax VALUES(?"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init_r(stmt); strmov(query,"SELECT id,name FROM test_prepare_syntax WHERE id=? AND WHERE"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init_r(stmt); /* now fetch the results ..*/ @@ -1095,7 +1106,7 @@ static void test_prepare() /* insert by prepare */ strxmov(query,"INSERT INTO my_prepare VALUES(?,?,?,?,?,?,?)",NullS); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,7); @@ -1159,9 +1170,9 @@ static void test_prepare() myquery(rc); /* test the results now, only one row should exists */ - assert(tiny_data == (char) my_stmt_result("SELECT * FROM my_prepare",50)); + assert(tiny_data == (char) my_stmt_result("SELECT * FROM my_prepare")); - stmt = mysql_prepare(mysql,"SELECT * FROM my_prepare",50); + stmt = mysql_simple_prepare(mysql,"SELECT * FROM my_prepare"); mystmt_init(stmt); rc = mysql_bind_result(stmt, bind); @@ -1266,7 +1277,7 @@ static void test_double_compare() myquery(rc); strmov(query, "UPDATE test_double_compare SET col1=100 WHERE col1 = ? AND col2 = ? AND COL3 = ?"); - stmt = mysql_prepare(mysql,query, strlen(query)); + stmt = mysql_simple_prepare(mysql,query); mystmt_init(stmt); verify_param_count(stmt,3); @@ -1347,11 +1358,11 @@ static void test_null() /* insert by prepare, wrong column name */ strmov(query,"INSERT INTO test_null(col3,col2) VALUES(?,?)"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init_r(stmt); strmov(query,"INSERT INTO test_null(col1,col2) VALUES(?,?)"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -1393,7 +1404,7 @@ static void test_null() myquery(rc); nData*= 2; - assert(nData == my_stmt_result("SELECT * FROM test_null", 30)); + assert(nData == my_stmt_result("SELECT * FROM test_null")); /* Fetch results */ bind[0].buffer_type= MYSQL_TYPE_LONG; @@ -1403,7 +1414,7 @@ static void test_null() bind[0].is_null= &is_null[0]; bind[1].is_null= &is_null[1]; - stmt = mysql_prepare(mysql,"SELECT * FROM test_null",30); + stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_null"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -1475,9 +1486,9 @@ static void test_fetch_null() strmov((char *)query , "SELECT * FROM test_fetch_null"); - assert(3 == my_stmt_result(query,50)); + assert(3 == my_stmt_result(query)); - stmt = mysql_prepare(mysql, query, 50); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); rc = mysql_bind_result(stmt,bind); @@ -1516,7 +1527,7 @@ static void test_select_version() myheader("test_select_version"); - stmt = mysql_prepare(mysql, "SELECT @@version", 30); + stmt = mysql_simple_prepare(mysql, "SELECT @@version"); mystmt_init(stmt); verify_param_count(stmt,0); @@ -1538,7 +1549,7 @@ static void test_select_simple() myheader("test_select_simple"); - stmt = mysql_prepare(mysql, "SHOW TABLES FROM mysql", 50); + stmt = mysql_simple_prepare(mysql, "SHOW TABLES FROM mysql"); mystmt_init(stmt); verify_param_count(stmt,0); @@ -1630,7 +1641,7 @@ static void test_select_prepare() rc = mysql_commit(mysql); myquery(rc); - stmt = mysql_prepare(mysql,"SELECT * FROM test_select",50); + stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_select"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -1660,7 +1671,7 @@ static void test_select_prepare() rc = mysql_commit(mysql); myquery(rc); - stmt = mysql_prepare(mysql,"SELECT * FROM test_select",25); + stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_select"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -1715,7 +1726,7 @@ static void test_select() myquery(rc); strmov(query,"SELECT * FROM test_select WHERE id=? AND name=?"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -1774,7 +1785,7 @@ session_id char(9) NOT NULL, \ myquery(rc); strmov(query,"SELECT * FROM test_select WHERE session_id = ?"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,1); @@ -1852,7 +1863,7 @@ static void test_bug1180() myquery(rc); strmov(query,"SELECT * FROM test_select WHERE ?=\"1111\" and session_id = \"abc\""); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,1); @@ -1932,7 +1943,7 @@ static void test_bug1644() myquery(rc); strmov(query, "INSERT INTO foo_dfr VALUES (?,?,?,? )"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt, 4); @@ -2030,7 +2041,7 @@ static void test_select_show() rc = mysql_query(mysql, "CREATE TABLE test_show(id int(4) NOT NULL primary key, name char(2))"); myquery(rc); - stmt = mysql_prepare(mysql, "show columns from test_show", 30); + stmt = mysql_simple_prepare(mysql, "show columns from test_show"); mystmt_init(stmt); verify_param_count(stmt,0); @@ -2041,11 +2052,11 @@ static void test_select_show() my_process_stmt_result(stmt); mysql_stmt_close(stmt); - stmt = mysql_prepare(mysql, "show tables from mysql like ?", 50); + stmt = mysql_simple_prepare(mysql, "show tables from mysql like ?"); mystmt_init_r(stmt); strxmov(query,"show tables from ", current_db, " like \'test_show\'", NullS); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -2054,7 +2065,7 @@ static void test_select_show() my_process_stmt_result(stmt); mysql_stmt_close(stmt); - stmt = mysql_prepare(mysql, "describe test_show", 30); + stmt = mysql_simple_prepare(mysql, "describe test_show"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -2063,7 +2074,7 @@ static void test_select_show() my_process_stmt_result(stmt); mysql_stmt_close(stmt); - stmt = mysql_prepare(mysql, "show keys from test_show", 30); + stmt = mysql_simple_prepare(mysql, "show keys from test_show"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -2115,7 +2126,7 @@ static void test_simple_update() /* insert by prepare */ strmov(query,"UPDATE test_update SET col2=? WHERE col1=?"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -2190,11 +2201,11 @@ static void test_long_data() myquery(rc); strmov(query,"INSERT INTO test_long_data(col1,col2) VALUES(?)"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init_r(stmt); strmov(query,"INSERT INTO test_long_data(col1,col2,col3) VALUES(?,?,?)"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,3); @@ -2282,7 +2293,7 @@ static void test_long_data_str() myquery(rc); strmov(query,"INSERT INTO test_long_data_str VALUES(?,?)"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -2373,7 +2384,7 @@ static void test_long_data_str1() myquery(rc); strmov(query,"INSERT INTO test_long_data_str VALUES(?,?)"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -2462,7 +2473,7 @@ static void test_long_data_bin() myquery(rc); strmov(query,"INSERT INTO test_long_data_bin VALUES(?,?)"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -2557,7 +2568,7 @@ static void test_simple_delete() /* insert by prepare */ strmov(query,"DELETE FROM test_simple_delete WHERE col1=? AND col2=? AND col3=100"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -2637,7 +2648,7 @@ static void test_update() myquery(rc); strmov(query,"INSERT INTO test_update(col2,col3) VALUES(?,?)"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -2667,7 +2678,7 @@ static void test_update() mysql_stmt_close(stmt); strmov(query,"UPDATE test_update SET col2=? WHERE col3=?"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -2733,7 +2744,7 @@ static void test_prepare_noparam() /* insert by prepare */ strmov(query,"INSERT INTO my_prepare VALUES(10,'venu')"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,0); @@ -2812,7 +2823,7 @@ static void test_bind_result() bind[1].length= &length1; bind[1].is_null= &is_null[1]; - stmt = mysql_prepare(mysql, "SELECT * FROM test_bind_result", 50); + stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_bind_result"); mystmt_init(stmt); rc = mysql_bind_result(stmt,bind); @@ -2933,7 +2944,7 @@ static void test_bind_result_ext() bind[7].length= &bLength; bind[7].buffer_length= sizeof(bData); - stmt = mysql_prepare(mysql, "select * from test_bind_result", 50); + stmt = mysql_simple_prepare(mysql, "select * from test_bind_result"); mystmt_init(stmt); rc = mysql_bind_result(stmt,bind); @@ -3058,7 +3069,7 @@ static void test_bind_result_ext1() bind[i].length= &length[i]; } - stmt = mysql_prepare(mysql, "select * from test_bind_result", 50); + stmt = mysql_simple_prepare(mysql, "select * from test_bind_result"); mystmt_init(stmt); rc = mysql_bind_result(stmt,bind); @@ -3118,7 +3129,7 @@ static void bind_fetch(int row_count) MYSQL_BIND bind[7]; my_bool is_null[7]; - stmt = mysql_prepare(mysql,"INSERT INTO test_bind_fetch VALUES(?,?,?,?,?,?,?)",100); + stmt = mysql_simple_prepare(mysql,"INSERT INTO test_bind_fetch VALUES(?,?,?,?,?,?,?)"); mystmt_init(stmt); verify_param_count(stmt, 7); @@ -3151,9 +3162,9 @@ static void bind_fetch(int row_count) mysql_stmt_close(stmt); assert(row_count == (int) - my_stmt_result("SELECT * FROM test_bind_fetch",50)); + my_stmt_result("SELECT * FROM test_bind_fetch")); - stmt = mysql_prepare(mysql,"SELECT * FROM test_bind_fetch",50); + stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_bind_fetch"); myquery(rc); for (i= 0; i < (int) array_elements(bind); i++) @@ -3321,9 +3332,9 @@ static void test_fetch_date() bind[6].buffer_length= sizeof(ts_6); bind[6].length= &ts6_length; - assert(1 == my_stmt_result("SELECT * FROM test_bind_result",50)); + assert(1 == my_stmt_result("SELECT * FROM test_bind_result")); - stmt = mysql_prepare(mysql, "SELECT * FROM test_bind_result", 50); + stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_bind_result"); mystmt_init(stmt); rc = mysql_bind_result(stmt,bind); @@ -3651,7 +3662,7 @@ static void test_prepare_ext() /* insert by prepare - all integers */ strmov(query,(char *)"INSERT INTO test_prepare_ext(c1,c2,c3,c4,c5,c6) VALUES(?,?,?,?,?,?)"); - stmt = mysql_prepare(mysql,query, strlen(query)); + stmt = mysql_simple_prepare(mysql,query); mystmt_init(stmt); verify_param_count(stmt,6); @@ -3704,7 +3715,7 @@ static void test_prepare_ext() rc = mysql_commit(mysql); myquery(rc); - stmt = mysql_prepare(mysql,"SELECT c1,c2,c3,c4,c5,c6 FROM test_prepare_ext",100); + stmt = mysql_simple_prepare(mysql,"SELECT c1,c2,c3,c4,c5,c6 FROM test_prepare_ext"); mystmt_init(stmt); /* get the result */ @@ -3850,7 +3861,7 @@ static void test_insert() myquery(rc); /* insert by prepare */ - stmt = mysql_prepare(mysql, "INSERT INTO test_prep_insert VALUES(?,?)", 70); + stmt = mysql_simple_prepare(mysql, "INSERT INTO test_prep_insert VALUES(?,?)"); mystmt_init(stmt); verify_param_count(stmt,2); @@ -3922,7 +3933,7 @@ static void test_prepare_resultset() name varchar(50),extra double)"); myquery(rc); - stmt = mysql_prepare(mysql, "SELECT * FROM test_prepare_resultset", 60); + stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_prepare_resultset"); mystmt_init(stmt); verify_param_count(stmt,0); @@ -4034,25 +4045,25 @@ static void test_stmt_close() myquery(rc); strmov(query,"ALTER TABLE test_stmt_close ADD name varchar(20)"); - stmt1= mysql_prepare(lmysql, query, 70); + stmt1= mysql_simple_prepare(lmysql, query); mystmt_init(stmt1); verify_param_count(stmt1, 0); strmov(query,"INSERT INTO test_stmt_close(id) VALUES(?)"); - stmt_x= mysql_prepare(mysql, query, 70); + stmt_x= mysql_simple_prepare(mysql, query); mystmt_init(stmt_x); verify_param_count(stmt_x, 1); strmov(query,"UPDATE test_stmt_close SET id=? WHERE id=?"); - stmt3= mysql_prepare(lmysql, query, 70); + stmt3= mysql_simple_prepare(lmysql, query); mystmt_init(stmt3); verify_param_count(stmt3, 2); strmov(query,"SELECT * FROM test_stmt_close WHERE id=?"); - stmt2= mysql_prepare(lmysql, query, 70); + stmt2= mysql_simple_prepare(lmysql, query); mystmt_init(stmt2); verify_param_count(stmt2, 1); @@ -4119,7 +4130,7 @@ static void test_set_variable() mysql_autocommit(mysql, TRUE); - stmt1 = mysql_prepare(mysql, "show variables like 'max_error_count'", 50); + stmt1 = mysql_simple_prepare(mysql, "show variables like 'max_error_count'"); mystmt_init(stmt1); get_bind[0].buffer_type= MYSQL_TYPE_STRING; @@ -4150,7 +4161,7 @@ static void test_set_variable() rc = mysql_fetch(stmt1); assert(rc == MYSQL_NO_DATA); - stmt = mysql_prepare(mysql, "set max_error_count=?", 50); + stmt = mysql_simple_prepare(mysql, "set max_error_count=?"); mystmt_init(stmt); set_bind[0].buffer_type= MYSQL_TYPE_LONG; @@ -4225,7 +4236,7 @@ static void test_insert_meta() myquery(rc); strmov(query,"INSERT INTO test_prep_insert VALUES(10,'venu1','test')"); - stmt = mysql_prepare(mysql, query, 70); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,0); @@ -4236,7 +4247,7 @@ static void test_insert_meta() mysql_stmt_close(stmt); strmov(query,"INSERT INTO test_prep_insert VALUES(?,'venu',?)"); - stmt = mysql_prepare(mysql, query, 70); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -4288,7 +4299,7 @@ static void test_update_meta() myquery(rc); strmov(query,"UPDATE test_prep_update SET col1=10, col2='venu1' WHERE col3='test'"); - stmt = mysql_prepare(mysql, query, 100); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,0); @@ -4299,7 +4310,7 @@ static void test_update_meta() mysql_stmt_close(stmt); strmov(query,"UPDATE test_prep_update SET col1=?, col2='venu' WHERE col3=?"); - stmt = mysql_prepare(mysql, query, 100); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -4355,7 +4366,7 @@ static void test_select_meta() myquery(rc); strmov(query,"SELECT * FROM test_prep_select WHERE col1=10"); - stmt = mysql_prepare(mysql, query, 70); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,0); @@ -4364,7 +4375,7 @@ static void test_select_meta() mytest_r(result); strmov(query,"SELECT col1, col3 from test_prep_select WHERE col1=? AND col3='test' AND col2= ?"); - stmt = mysql_prepare(mysql, query, 120); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); verify_param_count(stmt,2); @@ -4499,10 +4510,10 @@ static void test_multi_stmt() rc = mysql_query(mysql,"INSERT INTO test_multi_table values(10,'mysql')"); myquery(rc); - stmt = mysql_prepare(mysql, "SELECT * FROM test_multi_table WHERE id = ?", 100); + stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_multi_table WHERE id = ?"); mystmt_init(stmt); - stmt2 = mysql_prepare(mysql, "UPDATE test_multi_table SET name='updated' WHERE id=10",100); + stmt2 = mysql_simple_prepare(mysql, "UPDATE test_multi_table SET name='updated' WHERE id=10"); mystmt_init(stmt2); verify_param_count(stmt,1); @@ -4544,7 +4555,7 @@ static void test_multi_stmt() assert(rc == MYSQL_NO_DATA); /* alter the table schema now */ - stmt1 = mysql_prepare(mysql,"DELETE FROM test_multi_table WHERE id = ? AND name=?",100); + stmt1 = mysql_simple_prepare(mysql,"DELETE FROM test_multi_table WHERE id = ? AND name=?"); mystmt_init(stmt1); verify_param_count(stmt1,2); @@ -4584,7 +4595,7 @@ static void test_multi_stmt() rc = mysql_fetch(stmt); assert(rc == MYSQL_NO_DATA); - assert(0 == my_stmt_result("SELECT * FROM test_multi_table",50)); + assert(0 == my_stmt_result("SELECT * FROM test_multi_table")); mysql_stmt_close(stmt); mysql_stmt_close(stmt2); @@ -4631,7 +4642,7 @@ static void test_manual_sample() /* Prepare a insert query with 3 parameters */ strmov(query, "INSERT INTO test_table(col1,col2,col3) values(?,?,?)"); - if (!(stmt = mysql_prepare(mysql,query,strlen(query)))) + if (!(stmt = mysql_simple_prepare(mysql,query))) { fprintf(stderr, "\n prepare, insert failed"); fprintf(stderr, "\n %s", mysql_error(mysql)); @@ -4735,7 +4746,7 @@ static void test_manual_sample() fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); exit(0); } - assert(2 == my_stmt_result("SELECT * FROM test_table",50)); + assert(2 == my_stmt_result("SELECT * FROM test_table")); /* DROP THE TABLE */ if (mysql_query(mysql,"DROP TABLE test_table")) @@ -4770,7 +4781,7 @@ static void test_prepare_alter() rc = mysql_query(mysql,"INSERT INTO test_prep_alter values(10,'venu'),(20,'mysql')"); myquery(rc); - stmt = mysql_prepare(mysql, "INSERT INTO test_prep_alter VALUES(?,'monty')", 100); + stmt = mysql_simple_prepare(mysql, "INSERT INTO test_prep_alter VALUES(?,'monty')"); mystmt_init(stmt); verify_param_count(stmt,1); @@ -4796,7 +4807,7 @@ static void test_prepare_alter() rc = mysql_execute(stmt); mystmt(stmt, rc); - assert(4 == my_stmt_result("SELECT * FROM test_prep_alter",50)); + assert(4 == my_stmt_result("SELECT * FROM test_prep_alter")); mysql_stmt_close(stmt); } @@ -4978,7 +4989,7 @@ static void test_store_result() bind[1].is_null= &is_null[1]; length1= 0; - stmt = mysql_prepare(mysql, "SELECT * FROM test_store_result", 50); + stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_store_result"); mystmt_init(stmt); rc = mysql_bind_result(stmt,bind); @@ -5089,7 +5100,7 @@ static void test_store_result1() rc = mysql_commit(mysql); myquery(rc); - stmt = mysql_prepare(mysql,"SELECT * FROM test_store_result",100); + stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_store_result"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -5160,7 +5171,7 @@ static void test_store_result2() bind[0].is_null= 0; strmov((char *)query , "SELECT col1 FROM test_store_result where col1= ?"); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); rc = mysql_bind_param(stmt,bind); @@ -5252,7 +5263,7 @@ static void test_subselect() bind[0].length= 0; bind[0].is_null= 0; - stmt = mysql_prepare(mysql, "INSERT INTO test_sub2(id) SELECT * FROM test_sub1 WHERE id=?", 100); + stmt = mysql_simple_prepare(mysql, "INSERT INTO test_sub2(id) SELECT * FROM test_sub1 WHERE id=?", 100); mystmt_init(stmt); rc = mysql_bind_param(stmt,bind); @@ -5275,13 +5286,13 @@ static void test_subselect() mysql_stmt_close(stmt); - assert(3 == my_stmt_result("SELECT * FROM test_sub2",50)); + assert(3 == my_stmt_result("SELECT * FROM test_sub2")); strmov((char *)query , "SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=?)"); - assert(1 == my_stmt_result("SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=8)",100)); - assert(1 == my_stmt_result("SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=7)",100)); + assert(1 == my_stmt_result("SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=8)")); + assert(1 == my_stmt_result("SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=7)")); - stmt = mysql_prepare(mysql, query, 150); + stmt = mysql_simple_prepare(mysql, query, 150); mystmt_init(stmt); rc = mysql_bind_param(stmt,bind); @@ -5335,7 +5346,7 @@ static void test_bind_date_conv(uint row_count) ulong second_part; uint year, month, day, hour, minute, sec; - stmt = mysql_prepare(mysql,"INSERT INTO test_date VALUES(?,?,?,?)", 100); + stmt = mysql_simple_prepare(mysql,"INSERT INTO test_date VALUES(?,?,?,?)"); mystmt_init(stmt); verify_param_count(stmt, 4); @@ -5389,9 +5400,9 @@ static void test_bind_date_conv(uint row_count) mysql_stmt_close(stmt); - assert(row_count == my_stmt_result("SELECT * FROM test_date",50)); + assert(row_count == my_stmt_result("SELECT * FROM test_date")); - stmt = mysql_prepare(mysql,"SELECT * FROM test_date",50); + stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_date"); myquery(rc); rc = mysql_bind_result(stmt, bind); @@ -5586,14 +5597,14 @@ static void test_pure_coverage() rc = mysql_query(mysql,"CREATE TABLE test_pure(c1 int, c2 varchar(20))"); myquery(rc); - stmt = mysql_prepare(mysql,"insert into test_pure(c67788) values(10)",100); + stmt = mysql_simple_prepare(mysql,"insert into test_pure(c67788) values(10)"); mystmt_init_r(stmt); #ifndef DBUG_OFF stmt = mysql_prepare(mysql,(const char *)0,0); mystmt_init_r(stmt); - stmt = mysql_prepare(mysql,"insert into test_pure(c2) values(10)",100); + stmt = mysql_simple_prepare(mysql,"insert into test_pure(c2) values(10)"); mystmt_init(stmt); rc = mysql_bind_param(stmt, bind); @@ -5602,7 +5613,7 @@ static void test_pure_coverage() mysql_stmt_close(stmt); #endif - stmt = mysql_prepare(mysql,"insert into test_pure(c2) values(?)",100); + stmt = mysql_simple_prepare(mysql,"insert into test_pure(c2) values(?)"); mystmt_init(stmt); #ifndef DBUG_OFF @@ -5630,7 +5641,7 @@ static void test_pure_coverage() mysql_stmt_close(stmt); - stmt = mysql_prepare(mysql,"select * from test_pure",100); + stmt = mysql_simple_prepare(mysql,"select * from test_pure"); mystmt(stmt, rc); rc = mysql_execute(stmt); @@ -5682,7 +5693,7 @@ static void test_buffers() ,('Database'),('Open-Source'),('Popular')"); myquery(rc); - stmt = mysql_prepare(mysql,"select str from test_buffer",100); + stmt = mysql_simple_prepare(mysql,"select str from test_buffer"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -5760,7 +5771,7 @@ static void test_open_direct() rc = mysql_query(mysql,"CREATE TABLE test_open_direct(id int, name char(6))"); myquery(rc); - stmt = mysql_prepare(mysql,"INSERT INTO test_open_direct values(10,'mysql')", 100); + stmt = mysql_simple_prepare(mysql,"INSERT INTO test_open_direct values(10,'mysql')"); mystmt_init(stmt); rc = mysql_query(mysql, "SELECT * FROM test_open_direct"); @@ -5799,7 +5810,7 @@ static void test_open_direct() mysql_stmt_close(stmt); /* run a direct query in the middle of a fetch */ - stmt= mysql_prepare(mysql,"SELECT * FROM test_open_direct",100); + stmt= mysql_simple_prepare(mysql,"SELECT * FROM test_open_direct"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -5818,7 +5829,7 @@ static void test_open_direct() myquery(rc); /* run a direct query with store result */ - stmt= mysql_prepare(mysql,"SELECT * FROM test_open_direct",100); + stmt= mysql_simple_prepare(mysql,"SELECT * FROM test_open_direct"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -5849,8 +5860,8 @@ static void test_fetch_nobuffs() myheader("test_fetch_nobuffs"); - stmt = mysql_prepare(mysql,"SELECT DATABASE(), CURRENT_USER(), \ - CURRENT_DATE(), CURRENT_TIME()",100); + stmt = mysql_simple_prepare(mysql,"SELECT DATABASE(), CURRENT_USER(), \ + CURRENT_DATE(), CURRENT_TIME()"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -5923,7 +5934,7 @@ static void test_ushort_bug() myquery(rc); - stmt = mysql_prepare(mysql,"SELECT * FROM test_ushort",50); + stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_ushort"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -6007,7 +6018,7 @@ static void test_sshort_bug() myquery(rc); - stmt = mysql_prepare(mysql,"SELECT * FROM test_sshort",50); + stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_sshort"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -6091,7 +6102,7 @@ static void test_stiny_bug() myquery(rc); - stmt = mysql_prepare(mysql,"SELECT * FROM test_stiny",50); + stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_stiny"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -6176,7 +6187,7 @@ static void test_field_misc() mysql_free_result(result); - stmt = mysql_prepare(mysql,"SELECT @@autocommit",20); + stmt = mysql_simple_prepare(mysql,"SELECT @@autocommit"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -6196,7 +6207,7 @@ static void test_field_misc() mysql_free_result(result); mysql_stmt_close(stmt); - stmt = mysql_prepare(mysql, "SELECT @@table_type", 30); + stmt = mysql_simple_prepare(mysql, "SELECT @@table_type"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -6220,7 +6231,7 @@ static void test_field_misc() mysql_stmt_close(stmt); - stmt = mysql_prepare(mysql, "SELECT @@table_type", 30); + stmt = mysql_simple_prepare(mysql, "SELECT @@table_type"); mystmt_init(stmt); result = mysql_get_metadata(stmt); @@ -6240,7 +6251,7 @@ static void test_field_misc() mysql_free_result(result); mysql_stmt_close(stmt); - stmt = mysql_prepare(mysql, "SELECT @@max_error_count", 30); + stmt = mysql_simple_prepare(mysql, "SELECT @@max_error_count"); mystmt_init(stmt); result = mysql_get_metadata(stmt); @@ -6260,7 +6271,7 @@ static void test_field_misc() mysql_free_result(result); mysql_stmt_close(stmt); - stmt = mysql_prepare(mysql, "SELECT @@max_allowed_packet", 30); + stmt = mysql_simple_prepare(mysql, "SELECT @@max_allowed_packet"); mystmt_init(stmt); result = mysql_get_metadata(stmt); @@ -6280,7 +6291,7 @@ static void test_field_misc() mysql_free_result(result); mysql_stmt_close(stmt); - stmt = mysql_prepare(mysql, "SELECT @@sql_warnings", 30); + stmt = mysql_simple_prepare(mysql, "SELECT @@sql_warnings"); mystmt_init(stmt); result = mysql_get_metadata(stmt); @@ -6341,7 +6352,7 @@ static void test_set_option() mysql_free_result(result); fprintf(stdout,"\n with SQL_SELECT_LIMIT=2 (prepare)"); - stmt = mysql_prepare(mysql, "SELECT * FROM test_limit", 50); + stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_limit"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -6356,7 +6367,7 @@ static void test_set_option() rc= mysql_query(mysql,"SET OPTION SQL_SELECT_LIMIT=DEFAULT"); myquery(rc); - stmt = mysql_prepare(mysql, "SELECT * FROM test_limit", 50); + stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_limit"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -6433,18 +6444,20 @@ static void test_prepare_grant() execute_prepare_query("INSERT INTO test_grant(a) VALUES(NULL)",1); execute_prepare_query("INSERT INTO test_grant VALUES(NULL)",1); execute_prepare_query("UPDATE test_grant SET a=9 WHERE a=1",1); - assert(4 == my_stmt_result("SELECT a FROM test_grant",50)); - + assert(4 == my_stmt_result("SELECT a FROM test_grant")); + + /* Both DELETE expected to fail as user does not have DELETE privs */ + rc = mysql_query(mysql,"DELETE FROM test_grant"); myquery_r(rc); - stmt= mysql_prepare(mysql,"DELETE FROM test_grant",50); + stmt= mysql_simple_prepare(mysql,"DELETE FROM test_grant"); mystmt_init(stmt); rc = mysql_execute(stmt); myquery_r(rc); - assert(4 == my_stmt_result("SELECT * FROM test_grant",50)); + assert(4 == my_stmt_result("SELECT * FROM test_grant")); mysql_close(lmysql); mysql= org_mysql; @@ -6487,7 +6500,7 @@ static void test_frm_bug() rc= mysql_query(mysql,"flush tables"); myquery(rc); - stmt = mysql_prepare(mysql, "show variables like 'datadir'", 50); + stmt = mysql_simple_prepare(mysql, "show variables like 'datadir'"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -6570,7 +6583,7 @@ static void test_decimal_bug() rc = mysql_query(mysql, "insert into test_decimal_bug value(8),(10.22),(5.61)"); myquery(rc); - stmt = mysql_prepare(mysql,"select c1 from test_decimal_bug where c1= ?",50); + stmt = mysql_simple_prepare(mysql,"select c1 from test_decimal_bug where c1= ?"); mystmt_init(stmt); bind[0].buffer_type= MYSQL_TYPE_DOUBLE; @@ -6666,7 +6679,7 @@ static void test_explain_bug() rc = mysql_query(mysql, "CREATE TABLE test_explain(id int, name char(2))"); myquery(rc); - stmt = mysql_prepare(mysql, "explain test_explain", 30); + stmt = mysql_simple_prepare(mysql, "explain test_explain"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -6702,7 +6715,7 @@ static void test_explain_bug() mysql_free_result(result); mysql_stmt_close(stmt); - stmt = mysql_prepare(mysql, "explain select id, name FROM test_explain", 50); + stmt = mysql_simple_prepare(mysql, "explain select id, name FROM test_explain"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -6950,10 +6963,10 @@ static void test_logs() myheader("test_logs"); - rc = mysql_real_query(mysql, "DROP TABLE IF EXISTS test_logs", 100); + rc = mysql_query(mysql, "DROP TABLE IF EXISTS test_logs"); myquery(rc); - rc = mysql_real_query(mysql, "CREATE TABLE test_logs(id smallint, name varchar(20))", 100); + rc = mysql_query(mysql, "CREATE TABLE test_logs(id smallint, name varchar(20))"); myquery(rc); length= (ulong)(strmov((char *)data,"INSERT INTO test_logs VALUES(?,?)") - data); @@ -7015,7 +7028,7 @@ static void test_logs() mysql_stmt_close(stmt); length= (ulong)(strmov((char *)data, "SELECT * FROM test_logs WHERE id=?") - data); - stmt = mysql_prepare(mysql, data, length+2); + stmt = mysql_prepare(mysql, data, length); mystmt_init(stmt); rc = mysql_bind_param(stmt, bind); @@ -7125,7 +7138,7 @@ static void test_nstmts() mysql_stmt_close(stmt); } - stmt = mysql_prepare(mysql," select count(*) from test_nstmts", 50); + stmt = mysql_simple_prepare(mysql," select count(*) from test_nstmts"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -7172,7 +7185,7 @@ static void test_fetch_seek() rc = mysql_query(mysql, "insert into test_seek(c2) values('venu'),('mysql'),('open'),('source')"); myquery(rc); - stmt = mysql_prepare(mysql,"select * from test_seek",50); + stmt = mysql_simple_prepare(mysql,"select * from test_seek"); mystmt_init(stmt); bind[0].buffer_type= MYSQL_TYPE_LONG; @@ -7267,7 +7280,7 @@ static void test_fetch_offset() rc = mysql_query(mysql, "insert into test_column values('abcdefghij'),(null)"); myquery(rc); - stmt = mysql_prepare(mysql,"select * from test_column",50); + stmt = mysql_simple_prepare(mysql,"select * from test_column"); mystmt_init(stmt); bind[0].buffer_type= MYSQL_TYPE_STRING; @@ -7350,7 +7363,7 @@ static void test_fetch_column() rc = mysql_query(mysql, "insert into test_column(c2) values('venu'),('mysql')"); myquery(rc); - stmt = mysql_prepare(mysql,"select * from test_column order by c2 desc", 50); + stmt = mysql_simple_prepare(mysql,"select * from test_column order by c2 desc"); mystmt_init(stmt); bind[0].buffer_type= MYSQL_TYPE_LONG; @@ -7537,7 +7550,7 @@ static void test_mem_overun() assert(1 == my_process_result(mysql)); - stmt = mysql_prepare(mysql, "select * from t_mem_overun",30); + stmt = mysql_simple_prepare(mysql, "select * from t_mem_overun"); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -7583,7 +7596,7 @@ static void test_free_result() rc = mysql_query(mysql, "insert into test_free_result values(),(),()"); myquery(rc); - stmt = mysql_prepare(mysql,"select * from test_free_result",50); + stmt = mysql_simple_prepare(mysql,"select * from test_free_result"); mystmt_init(stmt); bind[0].buffer_type= MYSQL_TYPE_LONG; @@ -7662,7 +7675,7 @@ static void test_free_store_result() rc = mysql_query(mysql, "insert into test_free_result values(),(),()"); myquery(rc); - stmt = mysql_prepare(mysql,"select * from test_free_result",50); + stmt = mysql_simple_prepare(mysql,"select * from test_free_result"); mystmt_init(stmt); bind[0].buffer_type= MYSQL_TYPE_LONG; @@ -7749,7 +7762,7 @@ static void test_sqlmode() strcpy(query, "INSERT INTO test_piping VALUES(?||?)"); fprintf(stdout,"\n query: %s", query); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); fprintf(stdout,"\n total parameters: %ld", mysql_param_count(stmt)); @@ -7781,7 +7794,7 @@ static void test_sqlmode() strcpy(query, "SELECT connection_id ()"); fprintf(stdout,"\n query: %s", query); - stmt = mysql_prepare(mysql, query, 70); + stmt = mysql_simple_prepare(mysql, query); mystmt_init_r(stmt); /* ANSI */ @@ -7792,7 +7805,7 @@ static void test_sqlmode() strcpy(query, "INSERT INTO test_piping VALUES(?||?)"); fprintf(stdout,"\n query: %s", query); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); fprintf(stdout,"\n total parameters: %ld", mysql_param_count(stmt)); @@ -7809,7 +7822,7 @@ static void test_sqlmode() /* ANSI mode spaces ... */ strcpy(query, "SELECT connection_id ()"); fprintf(stdout,"\n query: %s", query); - stmt = mysql_prepare(mysql, query, 70); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -7832,7 +7845,7 @@ static void test_sqlmode() strcpy(query, "SELECT connection_id ()"); fprintf(stdout,"\n query: %s", query); - stmt = mysql_prepare(mysql, query, 70); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); rc = mysql_execute(stmt); @@ -7873,7 +7886,7 @@ static void test_ts() rc = mysql_commit(mysql); myquery(rc); - stmt = mysql_prepare(mysql,"INSERT INTO test_ts VALUES(?,?,?),(?,?,?)",50); + stmt = mysql_simple_prepare(mysql,"INSERT INTO test_ts VALUES(?,?,?),(?,?,?)"); mystmt_init(stmt); ts.year= 2003; @@ -7912,7 +7925,7 @@ static void test_ts() verify_col_data("test_ts","b","21:07:46"); verify_col_data("test_ts","c","2003-07-12 21:07:46"); - stmt = mysql_prepare(mysql,"SELECT * FROM test_ts",50); + stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_ts"); mystmt_init(stmt); prep_res = mysql_get_metadata(stmt); @@ -7983,7 +7996,7 @@ static void test_bug1500() rc= mysql_commit(mysql); myquery(rc); - stmt= mysql_prepare(mysql,"SELECT i FROM test_bg1500 WHERE i IN (?,?,?)",44); + stmt= mysql_simple_prepare(mysql,"SELECT i FROM test_bg1500 WHERE i IN (?,?,?)"); mystmt_init(stmt); verify_param_count(stmt,3); @@ -8018,8 +8031,8 @@ static void test_bug1500() rc= mysql_commit(mysql); myquery(rc); - stmt= mysql_prepare(mysql, - "SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (?)",53); + stmt= mysql_simple_prepare(mysql, + "SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (?)"); mystmt_init(stmt); verify_param_count(stmt,1); @@ -8046,8 +8059,8 @@ static void test_bug1500() mysql_stmt_close(stmt); /* This should work too */ - stmt= mysql_prepare(mysql, - "SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (CONCAT(?,'digger'))", 70); + stmt= mysql_simple_prepare(mysql, + "SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (CONCAT(?,'digger'))"); mystmt_init(stmt); verify_param_count(stmt,1); @@ -8084,7 +8097,7 @@ static void test_bug1946() rc= mysql_query(mysql,"CREATE TABLE prepare_command(ID INT)"); myquery(rc); - stmt = mysql_prepare(mysql, query, strlen(query)); + stmt = mysql_simple_prepare(mysql, query); mystmt_init(stmt); rc= mysql_real_query(mysql, query, strlen(query)); assert(rc != 0); @@ -8095,6 +8108,28 @@ static void test_bug1946() rc= mysql_query(mysql,"DROP TABLE prepare_command"); } +static void test_parse_error_and_bad_length() +{ + MYSQL_STMT *stmt; + int rc; + + /* check that we get 4 syntax errors over the 4 calls */ + myheader("test_parse_error_and_bad_length"); + + rc= mysql_query(mysql,"SHOW DATABAAAA"); + assert(rc); + fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql)); + rc= mysql_real_query(mysql,"SHOW DATABASES",100); + assert(rc); + fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql)); + + stmt= mysql_simple_prepare(mysql,"SHOW DATABAAAA"); + assert(!stmt); + fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql)); + stmt= mysql_prepare(mysql,"SHOW DATABASES",100); + assert(!stmt); + fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql)); +} /* Read and parse arguments and MySQL options from my.cnf @@ -8340,6 +8375,8 @@ int main(int argc, char **argv) test_bug1644(); /* BUG#1644 */ test_bug1946(); /* test that placeholders are allowed only in prepared queries */ + test_parse_error_and_bad_length(); /* test if bad length param in + mysql_prepare() triggers error */ end_time= time((time_t *)0); total_time+= difftime(end_time, start_time); From e5c142a412f1c2ead19f8d8612e4278ffe92495e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Feb 2004 16:35:56 +0400 Subject: [PATCH 32/36] Addition to the fix for #2208 Made code shorter and more correct libmysql/client_settings.h: cli_next_result removed libmysql/libmysql.c: cli_next_result removed --- libmysql/client_settings.h | 1 - libmysql/libmysql.c | 26 +++++++++----------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index 6a7da0bcc81..b1a85f567f9 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -58,7 +58,6 @@ int cli_stmt_execute(MYSQL_STMT *stmt); MYSQL_DATA * cli_read_binary_rows(MYSQL_STMT *stmt); int cli_unbuffered_fetch(MYSQL *mysql, char **row); const char * cli_read_statistic(MYSQL *mysql); -int cli_next_result(MYSQL *mysql); #ifdef EMBEDDED_LIBRARY int init_embedded_server(int argc, char **argv, char **groups); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index a3e88ccd03d..27eb9bd3857 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -3510,22 +3510,6 @@ my_bool STDCALL mysql_more_results(MYSQL *mysql) /* Reads and returns the next query results */ - -int cli_next_result(MYSQL *mysql) -{ - DBUG_ENTER("cli_next_result"); - - mysql->net.last_error[0]= 0; - mysql->net.last_errno= 0; - strmov(mysql->net.sqlstate, not_error_sqlstate); - mysql->affected_rows= ~(my_ulonglong) 0; - - if (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) - DBUG_RETURN((*mysql->methods->read_query_result)(mysql)); - - DBUG_RETURN(-1); /* No more results */ -} - int STDCALL mysql_next_result(MYSQL *mysql) { DBUG_ENTER("mysql_next_result"); @@ -3538,7 +3522,15 @@ int STDCALL mysql_next_result(MYSQL *mysql) DBUG_RETURN(1); } - DBUG_RETURN((*mysql->methods->next_result)(mysql)); + mysql->net.last_error[0]= 0; + mysql->net.last_errno= 0; + strmov(mysql->net.sqlstate, not_error_sqlstate); + mysql->affected_rows= ~(my_ulonglong) 0; + + if (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) + DBUG_RETURN((*mysql->methods->next_result)(mysql)); + + DBUG_RETURN(-1); /* No more results */ } From b268952faf2a3a3eca9794018f1a368a5653aede Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Feb 2004 16:53:39 +0400 Subject: [PATCH 33/36] Bug 2701: Function CHARSET() inconsistency CONVERT3 was removed, it was for test purposes, and rather harmful. --- mysql-test/r/cast.result | 6 -- mysql-test/r/ctype_many.result | 123 -------------------------------- mysql-test/r/func_system.result | 14 ++++ mysql-test/t/cast.test | 2 - mysql-test/t/ctype_many.test | 5 -- mysql-test/t/func_system.test | 6 ++ sql/item_strfunc.cc | 40 +---------- sql/item_strfunc.h | 14 +--- sql/sql_yacc.yy | 2 - 9 files changed, 24 insertions(+), 188 deletions(-) diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index c60d8e19fb4..877a349d188 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -64,12 +64,6 @@ test select cast(_koi8r'ÔÅÓÔ' as char character set cp1251); cast(_koi8r'ÔÅÓÔ' as char character set cp1251) òåñò -select convert(_latin1'test', "latin1_german1_ci", "latin1_swedish_ci"); -convert(_latin1'test', "latin1_german1_ci", "latin1_swedish_ci") -test -select convert(_koi8r'ÔÅÓÔ', "koi8r_general_ci", "cp1251_general_ci"); -convert(_koi8r'ÔÅÓÔ', "koi8r_general_ci", "cp1251_general_ci") -òåñò create table t1 select cast(_koi8r'ÔÅÓÔ' as char character set cp1251) as t; show create table t1; Table Create Table diff --git a/mysql-test/r/ctype_many.result b/mysql-test/r/ctype_many.result index 173d41ecdd1..8bfc6e98226 100644 --- a/mysql-test/r/ctype_many.result +++ b/mysql-test/r/ctype_many.result @@ -340,129 +340,6 @@ CYR CAPIT SOFT SIGN CYR CAPIT E ü ü CYR CAPIT YU à à CYR CAPIT YA ñ ñ -select CONVERT(koi8_ru_f, 'cp1251_general_ci', 'utf8_general_ci'), comment from t1; -CONVERT(koi8_ru_f, 'cp1251_general_ci', 'utf8_general_ci') comment -a LAT SMALL A -b LAT SMALL B -c LAT SMALL C -d LAT SMALL D -e LAT SMALL E -f LAT SMALL F -g LAT SMALL G -h LAT SMALL H -i LAT SMALL I -j LAT SMALL J -k LAT SMALL K -l LAT SMALL L -m LAT SMALL M -n LAT SMALL N -o LAT SMALL O -p LAT SMALL P -q LAT SMALL Q -r LAT SMALL R -s LAT SMALL S -t LAT SMALL T -u LAT SMALL U -v LAT SMALL V -w LAT SMALL W -x LAT SMALL X -y LAT SMALL Y -z LAT SMALL Z -A LAT CAPIT A -B LAT CAPIT B -C LAT CAPIT C -D LAT CAPIT D -E LAT CAPIT E -F LAT CAPIT F -G LAT CAPIT G -H LAT CAPIT H -I LAT CAPIT I -J LAT CAPIT J -K LAT CAPIT K -L LAT CAPIT L -M LAT CAPIT M -N LAT CAPIT N -O LAT CAPIT O -P LAT CAPIT P -Q LAT CAPIT Q -R LAT CAPIT R -S LAT CAPIT S -T LAT CAPIT T -U LAT CAPIT U -V LAT CAPIT V -W LAT CAPIT W -X LAT CAPIT X -Y LAT CAPIT Y -Z LAT CAPIT Z -â CYR SMALL A -÷ CYR SMALL BE -þ CYR SMALL VE -ú CYR SMALL GE -ä CYR SMALL DE -å CYR SMALL IE -? CYR SMALL IO -ã CYR SMALL ZHE -ÿ CYR SMALL ZE -ê CYR SMALL I -ì CYR SMALL KA -í CYR SMALL EL -î CYR SMALL EM -ï CYR SMALL EN -ð CYR SMALL O -ò CYR SMALL PE -ô CYR SMALL ER -õ CYR SMALL ES -æ CYR SMALL TE -è CYR SMALL U -ö CYR SMALL EF -é CYR SMALL HA -ç CYR SMALL TSE -à CYR SMALL CHE -ù CYR SMALL SHA -ü CYR SMALL SCHA -ñ CYR SMALL HARD SIGN -ý CYR SMALL YERU -û CYR SMALL SOFT SIGN -ø CYR SMALL E -á CYR SMALL YU -ó CYR SMALL YA -Â CYR CAPIT A -× CYR CAPIT BE -Þ CYR CAPIT VE -Ú CYR CAPIT GE -Ä CYR CAPIT DE -Å CYR CAPIT IE -? CYR CAPIT IO -Ã CYR CAPIT ZHE -ß CYR CAPIT ZE -Ê CYR CAPIT I -Ì CYR CAPIT KA -Í CYR CAPIT EL -Î CYR CAPIT EM -Ï CYR CAPIT EN -Ð CYR CAPIT O -Ò CYR CAPIT PE -Ô CYR CAPIT ER -Õ CYR CAPIT ES -Æ CYR CAPIT TE -È CYR CAPIT U -Ö CYR CAPIT EF -É CYR CAPIT HA -Ç CYR CAPIT TSE -À CYR CAPIT CHE -Ù CYR CAPIT SHA -Ü CYR CAPIT SCHA -Ñ CYR CAPIT HARD SIGN -Ý CYR CAPIT YERU -Û CYR CAPIT SOFT SIGN -Ø CYR CAPIT E -Á CYR CAPIT YU -Ó CYR CAPIT YA -explain extended select CONVERT(koi8_ru_f, 'cp1251_general_ci', 'utf8_general_ci'), comment from t1; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 116 -Warnings: -Note 1003 select high_priority convert(test.t1.koi8_ru_f,_latin1'utf8_general_ci',_latin1'cp1251_general_ci') AS `CONVERT(koi8_ru_f, 'cp1251_general_ci', 'utf8_general_ci')`,test.t1.comment AS `comment` from test.t1 ALTER TABLE t1 ADD bin_f CHAR(32) BYTE NOT NULL; UPDATE t1 SET bin_f=koi8_ru_f; SELECT COUNT(DISTINCT bin_f),COUNT(DISTINCT koi8_ru_f),COUNT(DISTINCT utf8_f) FROM t1; diff --git a/mysql-test/r/func_system.result b/mysql-test/r/func_system.result index a0437ca1c56..338902e3f3a 100644 --- a/mysql-test/r/func_system.result +++ b/mysql-test/r/func_system.result @@ -51,6 +51,20 @@ t1 CREATE TABLE `t1` ( `version` char(40) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +select charset(charset(_utf8'a')), charset(collation(_utf8'a')); +charset(charset(_utf8'a')) charset(collation(_utf8'a')) +utf8 utf8 +select collation(charset(_utf8'a')), collation(collation(_utf8'a')); +collation(charset(_utf8'a')) collation(collation(_utf8'a')) +utf8_general_ci utf8_general_ci +create table t1 select charset(_utf8'a'), collation(_utf8'a'); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `charset(_utf8'a')` char(64) character set utf8 NOT NULL default '', + `collation(_utf8'a')` char(64) character set utf8 NOT NULL default '' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; select TRUE,FALSE,NULL; TRUE FALSE NULL 1 0 NULL diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index ab0242990fc..fab35bb334a 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -28,8 +28,6 @@ select CAST(DATE "2004-01-22 21:45:33" AS CHAR(4) BINARY); set names binary; select cast(_latin1'test' as char character set latin2); select cast(_koi8r'ÔÅÓÔ' as char character set cp1251); -select convert(_latin1'test', "latin1_german1_ci", "latin1_swedish_ci"); -select convert(_koi8r'ÔÅÓÔ', "koi8r_general_ci", "cp1251_general_ci"); create table t1 select cast(_koi8r'ÔÅÓÔ' as char character set cp1251) as t; show create table t1; drop table t1; diff --git a/mysql-test/t/ctype_many.test b/mysql-test/t/ctype_many.test index 7b44439aa50..26057e7c997 100644 --- a/mysql-test/t/ctype_many.test +++ b/mysql-test/t/ctype_many.test @@ -147,11 +147,6 @@ UPDATE t1 SET utf8_f=CONVERT(koi8_ru_f USING utf8); SET CHARACTER SET koi8r; SELECT * FROM t1; -# -# codecovarage for Item_func_conv_charset3 -# -select CONVERT(koi8_ru_f, 'cp1251_general_ci', 'utf8_general_ci'), comment from t1; -explain extended select CONVERT(koi8_ru_f, 'cp1251_general_ci', 'utf8_general_ci'), comment from t1; ALTER TABLE t1 ADD bin_f CHAR(32) BYTE NOT NULL; UPDATE t1 SET bin_f=koi8_ru_f; diff --git a/mysql-test/t/func_system.test b/mysql-test/t/func_system.test index f3b9b4ffc3f..a05b80ca56b 100644 --- a/mysql-test/t/func_system.test +++ b/mysql-test/t/func_system.test @@ -23,4 +23,10 @@ create table t1 (version char(40)) select database(), user(), version() as 'vers show create table t1; drop table t1; +select charset(charset(_utf8'a')), charset(collation(_utf8'a')); +select collation(charset(_utf8'a')), collation(collation(_utf8'a')); +create table t1 select charset(_utf8'a'), collation(_utf8'a'); +show create table t1; +drop table t1; + select TRUE,FALSE,NULL; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index fd1222d5f1a..ed6e44262c7 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2124,42 +2124,6 @@ void Item_func_conv_charset::print(String *str) str->append(')'); } -String *Item_func_conv_charset3::val_str(String *str) -{ - char cs1[30], cs2[30]; - String to_cs_buff(cs1, sizeof(cs1), default_charset_info); - String from_cs_buff(cs2, sizeof(cs2), default_charset_info); - String *arg= args[0]->val_str(str); - String *to_cs= args[1]->val_str(&to_cs_buff); - String *from_cs= args[2]->val_str(&from_cs_buff); - CHARSET_INFO *from_charset; - CHARSET_INFO *to_charset; - - if (!arg || args[0]->null_value || - !to_cs || args[1]->null_value || - !from_cs || args[2]->null_value || - !(from_charset=get_charset_by_name(from_cs->ptr(), MYF(MY_WME))) || - !(to_charset=get_charset_by_name(to_cs->ptr(), MYF(MY_WME)))) - { - null_value= 1; - return 0; - } - - if (str_value.copy(arg->ptr(), arg->length(), from_charset, to_charset)) - { - null_value= 1; - return 0; - } - null_value= 0; - return &str_value; -} - - -void Item_func_conv_charset3::fix_length_and_dec() -{ - max_length = args[0]->max_length; -} - String *Item_func_set_collation::val_str(String *str) { str=args[0]->val_str(str); @@ -2226,7 +2190,7 @@ String *Item_func_charset::val_str(String *str) if ((null_value=(args[0]->null_value || !res->charset()))) return 0; str->copy(res->charset()->csname,strlen(res->charset()->csname), - &my_charset_latin1, default_charset()); + &my_charset_latin1, collation.collation); return str; } @@ -2237,7 +2201,7 @@ String *Item_func_collation::val_str(String *str) if ((null_value=(args[0]->null_value || !res->charset()))) return 0; str->copy(res->charset()->name,strlen(res->charset()->name), - &my_charset_latin1, default_charset()); + &my_charset_latin1, collation.collation); return str; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 465300e721e..4832ddbd1b1 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -619,16 +619,6 @@ public: void print(String *str) { print_op(str); } }; -class Item_func_conv_charset3 :public Item_str_func -{ -public: - Item_func_conv_charset3(Item *arg1,Item *arg2,Item *arg3) - :Item_str_func(arg1,arg2,arg3) {} - String *val_str(String *); - void fix_length_and_dec(); - const char *func_name() const { return "convert"; } -}; - class Item_func_charset :public Item_str_func { public: @@ -637,8 +627,8 @@ public: const char *func_name() const { return "charset"; } void fix_length_and_dec() { - max_length=40; // should be enough collation.set(system_charset_info); + max_length= 64 * collation.collation->mbmaxlen; // should be enough }; }; @@ -650,8 +640,8 @@ public: const char *func_name() const { return "collation"; } void fix_length_and_dec() { - max_length=40; // should be enough collation.set(system_charset_info); + max_length= 64 * collation.collation->mbmaxlen; // should be enough }; }; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0dbe8981466..bdeaf5a0b86 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2574,8 +2574,6 @@ simple_expr: } | CONVERT_SYM '(' expr USING charset_name ')' { $$= new Item_func_conv_charset($3,$5); } - | CONVERT_SYM '(' expr ',' expr ',' expr ')' - { $$= new Item_func_conv_charset3($3,$7,$5); } | DEFAULT '(' simple_ident ')' { $$= new Item_default_value($3); } | VALUES '(' simple_ident ')' From 1e8dcbe01f463abac7845abe5bbeebb49251a5bd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Feb 2004 12:01:27 +0000 Subject: [PATCH 34/36] Bug#2703 "MySQL server does not detect if garbage chara at the end of query" Allow the parser to see the garbage characters. Garbage should cause the parser to report an error. sql/sql_lex.cc: Return END_OF_INPUT when at the end of the input buffer. Allows the parser to determine if there is junk after a \0 character. sql/sql_parse.cc: Undo 1.314.1.1 04/02/11 12:32:42 guilhem@mysql.com sql/sql_prepare.cc: Undo 1.73 04/02/11 12:32:42 guilhem@mysql.com --- sql/sql_lex.cc | 9 +++++++-- sql/sql_parse.cc | 18 +----------------- sql/sql_prepare.cc | 10 +--------- 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 70c69bb7389..90e5b0300f6 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -886,8 +886,13 @@ int yylex(void *arg, void *yythd) } /* fall true */ case MY_LEX_EOL: - lex->next_state=MY_LEX_END; // Mark for next loop - return(END_OF_INPUT); + if (lex->ptr >= lex->end_of_query) + { + lex->next_state=MY_LEX_END; // Mark for next loop + return(END_OF_INPUT); + } + state=MY_LEX_CHAR; + break; case MY_LEX_END: lex->next_state=MY_LEX_END; return(0); // We found end of input last time diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 81d6b80678d..51e1ebee4ad 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3854,23 +3854,7 @@ mysql_parse(THD *thd, char *inBuf, uint length) if (query_cache_send_result_to_client(thd, inBuf, length) <= 0) { LEX *lex=lex_start(thd, (uchar*) inBuf, length); - if (!yyparse((void *)thd) && ! thd->is_fatal_error && - /* - If this is not a multiple query, ensure that it has been - successfully parsed until the last character. This is to prevent - against a wrong (too big) length passed to mysql_real_query(), - mysql_prepare()... which can generate garbage characters at the - end. If the query was initially multiple, found_colon will be false - only when we are in the last query; this last query had already - been end-spaces-stripped by alloc_query() in dispatch_command(); as - end spaces are the only thing we accept at the end of a query, and - they have been stripped already, here we can require that nothing - remains after parsing. - */ - (thd->lex->found_colon || - (char*)(thd->lex->ptr) == (thd->query+thd->query_length+1) || - /* yyerror() will show the garbage chars to the user */ - (yyerror("syntax error"), 0))) + if (!yyparse((void *)thd) && ! thd->is_fatal_error) { #ifndef NO_EMBEDDED_ACCESS_CHECKS if (mqh_used && thd->user_connect && diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index cf723e18d85..2cf0000d973 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -909,15 +909,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) lex->safe_to_cache_query= 0; lex->param_count= 0; - if (yyparse((void *)thd) || thd->is_fatal_error || - /* - Check for wrong (too big) length passed to mysql_prepare() resulting in - garbage at the end of the query. There is a similar check in mysql_parse(). - */ - (!thd->lex->found_colon && - (char*)(thd->lex->ptr) != (thd->query+thd->query_length+1) && - /* yyerror() will show the garbage chars to the user */ - (yyerror("syntax error"), 1)) || send_prepare_results(stmt)) + if (yyparse((void *)thd) || thd->is_fatal_error || send_prepare_results(stmt)) goto yyparse_err; lex_end(lex); From eea7cbfba5f8c0c4721b31f0642f8824c995baac Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Feb 2004 16:47:57 +0400 Subject: [PATCH 35/36] Fix for #1438 (mysql_info always returns 0) libmysqld/lib_sql.cc: mysql.info set to the right value --- libmysqld/lib_sql.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 81235ce0c22..101e129d615 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -689,7 +689,10 @@ send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message) mysql->affected_rows= affected_rows; mysql->insert_id= id; if (message) + { strmake(thd->net.last_error, message, sizeof(thd->net.last_error)-1); + mysql->info= thd->net.last_error; + } DBUG_VOID_RETURN; } From b3bf99ed42f6ae344cb646ea421ccba7fbaee69f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Feb 2004 00:28:00 +0400 Subject: [PATCH 36/36] some optimization in append_identifier (sql/sql_show.cc) sql/sql_show.cc: some optimization in append_identifier --- sql/sql_show.cc | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5870e58d9a4..2d7b89a24a1 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1086,7 +1086,7 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) DBUG_RETURN(0); } -static bool require_quotes(const char *name, uint length) +static inline const char *require_quotes(const char *name, uint length) { uint i, d, c; for (i=0; iident_map[c]) - return 1; + return name+i; } return 0; } @@ -1113,7 +1113,8 @@ static bool require_quotes(const char *name, uint length) 0 string doesn't contain required char */ -static const char *look_for_char(const char *name, uint length, char q) +static inline const char *look_for_char(const char *name, + uint length, char q) { const char *cur= name; const char *end= cur+length; @@ -1141,27 +1142,29 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) if (is_keyword(name,length)) { - packet->append(&qtype, 1); + packet->append(&qtype, 1, system_charset_info); packet->append(name, length, system_charset_info); - packet->append(&qtype, 1); + packet->append(&qtype, 1, system_charset_info); } else { - if (!require_quotes(name, length)) + if (!(qplace= require_quotes(name, length))) { if (!(thd->options & OPTION_QUOTE_SHOW_CREATE)) packet->append(name, length, system_charset_info); else { - packet->append(&qtype, 1); + packet->append(&qtype, 1, system_charset_info); packet->append(name, length, system_charset_info); - packet->append(&qtype, 1); + packet->append(&qtype, 1, system_charset_info); } } else { - packet->append(&qtype, 1); - qplace= look_for_char(name,length,qtype); + packet->shrink(packet->length()+length+2); + packet->append(&qtype, 1, system_charset_info); + if (*qplace != qtype) + qplace= look_for_char(qplace+1,length-(qplace-name)-1,qtype); while (qplace) { if ((part_len= qplace-name)) @@ -1174,7 +1177,7 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) qplace= look_for_char(name+1,length-1,qtype); } packet->append(name, length, system_charset_info); - packet->append(&qtype, 1); + packet->append(&qtype, 1, system_charset_info); } } }