From 280b1c33e3e1ddd7b4e3b295c9e30c766da6c494 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 18:18:58 +0300 Subject: [PATCH 01/20] Cleanup during review of new code Fixed wrong allocation that could cause buffer overrun when using join cache myisam/mi_open.c: Fixed indentation mysql-test/r/lowercase_table2.result: Drop tables and databases used in the test mysql-test/t/lowercase_table2.test: Drop tables and databases used in the test mysys/my_fopen.c: Cleanup of comments and parameter names Simple optimization Removed compiler warnings sql/field.cc: Fixed wrong allocation that could cause buffer overrun sql/mysqld.cc: Removed not needed code sql/set_var.cc: Simply code sql/sql_select.cc: Use int2store/int2korr to store length of cached VARCHAR fields (Not dependent on type and faster code as we avoid one possible call) --- myisam/mi_open.c | 2 +- mysql-test/r/lowercase_table2.result | 3 +- mysql-test/t/lowercase_table2.test | 3 +- mysys/my_fopen.c | 86 ++++++++++++++++------------ sql/field.cc | 9 ++- sql/mysqld.cc | 3 - sql/set_var.cc | 2 +- sql/sql_select.cc | 18 +++--- 8 files changed, 72 insertions(+), 54 deletions(-) diff --git a/myisam/mi_open.c b/myisam/mi_open.c index e79fdb7e777..a5b303f86d4 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -78,7 +78,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) int lock_error,kfile,open_mode,save_errno,have_rtree=0; uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys, key_parts,unique_key_parts,fulltext_keys,uniques; - char name_buff[FN_REFLEN], org_name [FN_REFLEN], index_name[FN_REFLEN], + char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN], data_name[FN_REFLEN]; char *disk_cache, *disk_pos, *end_pos; MI_INFO info,*m_info,*old_info; diff --git a/mysql-test/r/lowercase_table2.result b/mysql-test/r/lowercase_table2.result index db833bcd970..f93a10dfbad 100644 --- a/mysql-test/r/lowercase_table2.result +++ b/mysql-test/r/lowercase_table2.result @@ -1,6 +1,7 @@ -DROP TABLE IF EXISTS t1,t2,t3; +DROP TABLE IF EXISTS t1,t2,t3,t2aA,t1Aa; DROP DATABASE IF EXISTS `TEST_$1`; DROP DATABASE IF EXISTS `test_$1`; +DROP DATABASE mysqltest_LC2; CREATE TABLE T1 (a int); INSERT INTO T1 VALUES (1); SHOW TABLES LIKE "T1"; diff --git a/mysql-test/t/lowercase_table2.test b/mysql-test/t/lowercase_table2.test index 51c6f6b5ac3..5e38c59386d 100644 --- a/mysql-test/t/lowercase_table2.test +++ b/mysql-test/t/lowercase_table2.test @@ -10,9 +10,10 @@ show variables like "lower_case_table_names"; enable_query_log; --disable_warnings -DROP TABLE IF EXISTS t1,t2,t3; +DROP TABLE IF EXISTS t1,t2,t3,t2aA,t1Aa; DROP DATABASE IF EXISTS `TEST_$1`; DROP DATABASE IF EXISTS `test_$1`; +DROP DATABASE mysqltest_LC2; --enable_warnings CREATE TABLE T1 (a int); diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index 002e5ca0f06..f07beec9f39 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -19,27 +19,36 @@ #include #include "mysys_err.h" -static void make_ftype(my_string to,int flag); +static void make_ftype(my_string to,int flag); - /* Open a file as stream */ +/* + Open a file as stream -FILE *my_fopen(const char *FileName, int Flags, myf MyFlags) - /* Path-name of file */ - /* Read | write .. */ - /* Special flags */ + SYNOPSIS + my_fopen() + FileName Path-name of file + Flags Read | write | append | trunc (like for open()) + MyFlags Flags for handling errors + + RETURN + 0 Error + # File handler +*/ + +FILE *my_fopen(const char *filename, int flags, myf MyFlags) { FILE *fd; char type[5]; DBUG_ENTER("my_fopen"); - DBUG_PRINT("my",("Name: '%s' Flags: %d MyFlags: %d", - FileName, Flags, MyFlags)); + DBUG_PRINT("my",("Name: '%s' flags: %d MyFlags: %d", + filename, flags, MyFlags)); /* if we are not creating, then we need to use my_access to make sure the file exists since Windows doesn't handle files like "com1.sym" very well */ #ifdef __WIN__ - if (check_if_legal_filename(FileName)) + if (check_if_legal_filename(filename)) { errno= EACCES; fd= 0; @@ -47,8 +56,8 @@ FILE *my_fopen(const char *FileName, int Flags, myf MyFlags) else #endif { - make_ftype(type,Flags); - fd = fopen(FileName, type); + make_ftype(type,flags); + fd = fopen(filename, type); } if (fd != 0) @@ -65,7 +74,7 @@ FILE *my_fopen(const char *FileName, int Flags, myf MyFlags) } pthread_mutex_lock(&THR_LOCK_open); if ((my_file_info[fileno(fd)].name = (char*) - my_strdup(FileName,MyFlags))) + my_strdup(filename,MyFlags))) { my_stream_opened++; my_file_info[fileno(fd)].type = STREAM_BY_FOPEN; @@ -81,9 +90,9 @@ FILE *my_fopen(const char *FileName, int Flags, myf MyFlags) my_errno=errno; DBUG_PRINT("error",("Got error %d on open",my_errno)); if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) - my_error((Flags & O_RDONLY) || (Flags == O_RDONLY ) ? EE_FILENOTFOUND : + my_error((flags & O_RDONLY) || (flags == O_RDONLY ) ? EE_FILENOTFOUND : EE_CANTCREATEFILE, - MYF(ME_BELL+ME_WAITTANG), FileName,my_errno); + MYF(ME_BELL+ME_WAITTANG), filename, my_errno); DBUG_RETURN((FILE*) 0); } /* my_fopen */ @@ -158,33 +167,39 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) DBUG_RETURN(fd); } /* my_fdopen */ -/* - make_ftype - Make a filehandler-open-typestring from ordinary inputflags - Note: This routine attempts to find the best possible match - between a numeric option and a string option that could be - fed to fopen. There is not a 1 to 1 mapping between the two. +/* + Make a fopen() typestring from a open() type bitmap + + SYNOPSIS + make_ftype() + to String for fopen() is stored here + flag Flag used by open() + + IMPLEMENTATION + This routine attempts to find the best possible match + between a numeric option and a string option that could be + fed to fopen. There is not a 1 to 1 mapping between the two. - r == O_RDONLY - w == O_WRONLY|O_TRUNC|O_CREAT - a == O_WRONLY|O_APPEND|O_CREAT - r+ == O_RDWR - w+ == O_RDWR|O_TRUNC|O_CREAT - a+ == O_RDWR|O_APPEND|O_CREAT + NOTE + On Unix, O_RDONLY is usually 0 + + MAPPING + r == O_RDONLY + w == O_WRONLY|O_TRUNC|O_CREAT + a == O_WRONLY|O_APPEND|O_CREAT + r+ == O_RDWR + w+ == O_RDWR|O_TRUNC|O_CREAT + a+ == O_RDWR|O_APPEND|O_CREAT */ + static void make_ftype(register my_string to, register int flag) { -#if FILE_BINARY - /* If we have binary-files */ - reg3 int org_flag=flag; -#endif - flag&= ~FILE_BINARY; /* remove binary bit */ - /* check some possible invalid combinations */ - DBUG_ASSERT(flag & (O_TRUNC|O_APPEND) != O_TRUNC|O_APPEND); + DBUG_ASSERT((flag & (O_TRUNC | O_APPEND)) != (O_TRUNC | O_APPEND)); + DBUG_ASSERT((flag & (O_WRONLY | O_RDWR)) != (O_WRONLY | O_RDWR)); - if (flag & (O_RDONLY|O_WRONLY) == O_WRONLY) + if ((flag & (O_RDONLY|O_WRONLY)) == O_WRONLY) *to++= (flag & O_APPEND) ? 'a' : 'w'; else if (flag & O_RDWR) { @@ -201,9 +216,8 @@ static void make_ftype(register my_string to, register int flag) *to++= 'r'; #if FILE_BINARY /* If we have binary-files */ - if (org_flag & FILE_BINARY) + if (flag & FILE_BINARY) *to++='b'; #endif *to='\0'; } /* make_ftype */ - diff --git a/sql/field.cc b/sql/field.cc index 692f123097a..88816151c10 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1053,6 +1053,7 @@ void Field_str::make_field(Send_field *field) uint Field::fill_cache_field(CACHE_FIELD *copy) { + uint store_length; copy->str=ptr; copy->length=pack_length(); copy->blob_field=0; @@ -1065,10 +1066,16 @@ uint Field::fill_cache_field(CACHE_FIELD *copy) } else if (!zero_pack() && (type() == FIELD_TYPE_STRING && copy->length > 4 || type() == FIELD_TYPE_VAR_STRING)) + { copy->strip=1; /* Remove end space */ + store_length= 2; + } else + { copy->strip=0; - return copy->length+(int) copy->strip; + store_length= 0; + } + return copy->length+ store_length; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ec05ea2b8ce..99c96a69ceb 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6098,9 +6098,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case (int) OPT_SLOW_QUERY_LOG: opt_slow_log=1; break; - case (int) OPT_LOG_SLOW_ADMIN_STATEMENTS: - opt_log_slow_admin_statements= 1; - break; case (int) OPT_SKIP_NEW: opt_specialflag|= SPECIAL_NO_NEW_FUNC; delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE; diff --git a/sql/set_var.cc b/sql/set_var.cc index 0f13a8a7f2d..b0fa61a12bc 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1516,7 +1516,7 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names) { if (!(res= var->value->val_str(&str))) { - strmake(buff, "NULL", 4); + strmov(buff, "NULL"); goto err; } var->save_result.ulong_value= ((ulong) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5bafe1a7df4..1031773eeed 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -28,8 +28,6 @@ #include #include -typedef uint32 cache_rec_length_type; - const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref", "MAYBE_REF","ALL","range","index","fulltext", "ref_or_null","unique_subquery","index_subquery" @@ -8074,7 +8072,7 @@ used_blob_length(CACHE_FIELD **ptr) static bool store_record_in_cache(JOIN_CACHE *cache) { - cache_rec_length_type length; + uint length; uchar *pos; CACHE_FIELD *copy,*end_field; bool last_record; @@ -8119,9 +8117,9 @@ store_record_in_cache(JOIN_CACHE *cache) end > str && end[-1] == ' ' ; end--) ; length=(uint) (end-str); - memcpy(pos+sizeof(length), str, length); - memcpy_fixed(pos, &length, sizeof(length)); - pos+= length+sizeof(length); + memcpy(pos+2, str, length); + int2store(pos, length); + pos+= length+2; } else { @@ -8155,7 +8153,7 @@ static void read_cached_record(JOIN_TAB *tab) { uchar *pos; - cache_rec_length_type length; + uint length; bool last_record; CACHE_FIELD *copy,*end_field; @@ -8184,10 +8182,10 @@ read_cached_record(JOIN_TAB *tab) { if (copy->strip) { - memcpy_fixed(&length, pos, sizeof(length)); - memcpy(copy->str, pos+sizeof(length), length); + length= uint2korr(pos); + memcpy(copy->str, pos+2, length); memset(copy->str+length, ' ', copy->length-length); - pos+= sizeof(length)+length; + pos+= 2 + length; } else { From d10877ce8ce4f939f88f79e6ad42af251fd51ebe Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 16:46:41 +0300 Subject: [PATCH 02/20] Better bug fix for: #9728 'Decreased functionality in "on duplicate key update #8147 'a column proclaimed ambigous in INSERT ... SELECT .. ON DUPLICATE' This ensures fields are uniquely qualified and also that one can't update other tables in the ON DUPLICATE KEY UPDATE part mysql-test/r/insert_select.result: More tests for bug #9728 and #8147 mysql-test/r/insert_update.result: Updated tests after changing how INSERT ... SELECT .. ON DUPLICATE KEY works mysql-test/t/insert_select.test: More tests for bug #9728 and #8147 mysql-test/t/insert_update.test: Updated tests after changing how INSERT ... SELECT .. ON DUPLICATE KEY works mysys/my_access.c: Cleanup (shorter loop variable names) sql/ha_ndbcluster.cc: Indentation fixes sql/item.cc: Remove item_flags sql/item.h: Remove item_flags sql/mysql_priv.h: New arguments to mysql_prepare_insert sql/sql_base.cc: Remove old fix for bug #8147 sql/sql_insert.cc: Extend mysql_prepare_insert() with new field list for tables that can be used in the values port of ON DUPLICATE KEY UPDATE sql/sql_parse.cc: Revert fix for #9728 Allow one to use other tables in ON DUPLICATE_KEY for INSERT ... SELECT if there is no GROUP BY clause sql/sql_prepare.cc: New arguments to mysql_prepare_insert sql/sql_yacc.yy: Revert bug fix for #9728 --- mysql-test/r/insert_select.result | 27 +++++++++++++++++--- mysql-test/r/insert_update.result | 10 +++++--- mysql-test/t/insert_select.test | 22 +++++++++++++--- mysql-test/t/insert_update.test | 10 +++++--- mysys/my_access.c | 9 +++---- sql/ha_ndbcluster.cc | 4 ++- sql/item.cc | 4 +-- sql/item.h | 11 -------- sql/mysql_priv.h | 3 ++- sql/sql_base.cc | 9 +++---- sql/sql_insert.cc | 34 ++++++++++++++++++------- sql/sql_parse.cc | 42 +++++++++++++++++++++---------- sql/sql_prepare.cc | 1 + sql/sql_yacc.yy | 15 ----------- 14 files changed, 123 insertions(+), 78 deletions(-) diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 69eb64f08ea..2ac73fe7662 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -1,4 +1,4 @@ -drop table if exists t1,t2; +drop table if exists t1,t2,t3; create table t1 (bandID MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY, payoutID SMALLINT UNSIGNED NOT NULL); insert into t1 (bandID,payoutID) VALUES (1,6),(2,6),(3,4),(4,9),(5,10),(6,1),(7,12),(8,12); create table t2 (payoutID SMALLINT UNSIGNED NOT NULL PRIMARY KEY); @@ -636,16 +636,35 @@ ff1 ff2 drop table t1, t2; create table t1 (a int unique); create table t2 (a int, b int); +create table t3 (c int, d int); insert into t1 values (1),(2); insert into t2 values (1,2); +insert into t3 values (1,6),(3,7); select * from t1; a 1 2 -insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b; +insert into t1 select a from t2 on duplicate key update a= t1.a + t2.b; select * from t1; a 2 3 -drop table t1; -drop table t2; +insert into t1 select a+1 from t2 on duplicate key update t1.a= t1.a + t2.b+1; +select * from t1; +a +3 +5 +insert into t1 select t3.c from t3 on duplicate key update a= a + t3.d; +select * from t1; +a +1 +5 +10 +insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= a + 10; +insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b; +ERROR 23000: Column 'a' in field list is ambiguous +insert into t1 select t2.a from t2 on duplicate key update t2.a= a + t2.b; +ERROR 42S02: Unknown table 't2' in field list +insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b; +ERROR 42S02: Unknown table 't2' in field list +drop table t1,t2,t3; diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index 2143538469b..150f4ef26c7 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -143,7 +143,7 @@ INSERT t1 VALUES (1,2,10), (3,4,20); CREATE TABLE t2 (a INT, b INT, c INT, d INT); INSERT t2 VALUES (5,6,30,1), (7,4,40,1), (8,9,60,1); INSERT t2 VALUES (2,1,11,2), (7,4,40,2); -INSERT t1 SELECT a,b,c FROM t2 WHERE d=1 ON DUPLICATE KEY UPDATE c=c+100; +INSERT t1 SELECT a,b,c FROM t2 WHERE d=1 ON DUPLICATE KEY UPDATE c=t1.c+100; SELECT * FROM t1; a b c 1 2 10 @@ -158,6 +158,8 @@ a b c 5 0 30 8 9 60 INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a); +ERROR 23000: Column 'c' in field list is ambiguous +INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=t1.c+VALUES(t1.a); SELECT *, VALUES(a) FROM t1; a b c VALUES(a) 1 2 10 NULL @@ -174,7 +176,7 @@ select * from t1; a 1 2 -insert ignore into t1 select a from t1 on duplicate key update a=a+1 ; +insert ignore into t1 select a from t1 as t2 on duplicate key update a=t1.a+1 ; select * from t1; a 1 @@ -185,5 +187,7 @@ a 2 3 insert into t1 select a from t1 on duplicate key update a=a+1 ; -ERROR 23000: Duplicate entry '3' for key 1 +ERROR 23000: Column 'a' in field list is ambiguous +insert ignore into t1 select a from t1 on duplicate key update a=t1.a+1 ; +ERROR 23000: Column 't1.a' in field list is ambiguous drop table t1; diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 7402940fa52..67799873b73 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -3,7 +3,7 @@ # --disable_warnings -drop table if exists t1,t2; +drop table if exists t1,t2,t3; --enable_warnings create table t1 (bandID MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY, payoutID SMALLINT UNSIGNED NOT NULL); @@ -182,10 +182,24 @@ drop table t1, t2; # create table t1 (a int unique); create table t2 (a int, b int); +create table t3 (c int, d int); insert into t1 values (1),(2); insert into t2 values (1,2); +insert into t3 values (1,6),(3,7); select * from t1; +insert into t1 select a from t2 on duplicate key update a= t1.a + t2.b; +select * from t1; +insert into t1 select a+1 from t2 on duplicate key update t1.a= t1.a + t2.b+1; +select * from t1; +insert into t1 select t3.c from t3 on duplicate key update a= a + t3.d; +select * from t1; +insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= a + 10; + +#Some error cases +--error 1052 insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b; -select * from t1; -drop table t1; -drop table t2; +--error 1109 +insert into t1 select t2.a from t2 on duplicate key update t2.a= a + t2.b; +--error 1109 +insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b; +drop table t1,t2,t3; diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test index f5857840588..3d6297d8d7a 100644 --- a/mysql-test/t/insert_update.test +++ b/mysql-test/t/insert_update.test @@ -72,11 +72,13 @@ CREATE TABLE t2 (a INT, b INT, c INT, d INT); # column names deliberately clash with columns in t1 (Bug#8147) INSERT t2 VALUES (5,6,30,1), (7,4,40,1), (8,9,60,1); INSERT t2 VALUES (2,1,11,2), (7,4,40,2); -INSERT t1 SELECT a,b,c FROM t2 WHERE d=1 ON DUPLICATE KEY UPDATE c=c+100; +INSERT t1 SELECT a,b,c FROM t2 WHERE d=1 ON DUPLICATE KEY UPDATE c=t1.c+100; SELECT * FROM t1; INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0; SELECT * FROM t1; +--error 1052 INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a); +INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=t1.c+VALUES(t1.a); SELECT *, VALUES(a) FROM t1; DROP TABLE t1; DROP TABLE t2; @@ -89,10 +91,12 @@ create table t1 (a int not null unique) engine=myisam; insert into t1 values (1),(2); insert ignore into t1 select 1 on duplicate key update a=2; select * from t1; -insert ignore into t1 select a from t1 on duplicate key update a=a+1 ; +insert ignore into t1 select a from t1 as t2 on duplicate key update a=t1.a+1 ; select * from t1; insert into t1 select 1 on duplicate key update a=2; select * from t1; ---error 1062 +--error 1052 insert into t1 select a from t1 on duplicate key update a=a+1 ; +--error 1052 +insert ignore into t1 select a from t1 on duplicate key update a=t1.a+1 ; drop table t1; diff --git a/mysys/my_access.c b/mysys/my_access.c index 1b9ad6ff380..8fc83a020cf 100644 --- a/mysys/my_access.c +++ b/mysys/my_access.c @@ -98,17 +98,16 @@ int check_if_legal_filename(const char *path) for (reserved_name= reserved_names; *reserved_name; reserved_name++) { + const char *reserved= *reserved_name; /* never empty */ const char *name= path; - const char *current_reserved_name= *reserved_name; - while (name != end && *current_reserved_name) + do { - if (*current_reserved_name != my_toupper(&my_charset_latin1, *name)) + if (*reserved != my_toupper(&my_charset_latin1, *name)) break; - current_reserved_name++; if (++name == end) DBUG_RETURN(1); /* Found wrong path */ - } + } while (*++reserved); } DBUG_RETURN(0); } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 88b7ff4dcb8..d5153269843 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -439,8 +439,10 @@ int ha_ndbcluster::ndb_err(NdbConnection *trans) if (m_rows_to_insert == 1) m_dupkey= table->primary_key; else - // We are batching inserts, offending key is not available + { + /* We are batching inserts, offending key is not available */ m_dupkey= (uint) -1; + } } DBUG_RETURN(res); } diff --git a/sql/item.cc b/sql/item.cc index 9c5bf499d11..c96794ff482 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -65,7 +65,6 @@ Item::Item(): place == IN_HAVING) thd->lex->current_select->select_n_having_items++; } - item_flags= 0; } /* @@ -84,8 +83,7 @@ Item::Item(THD *thd, Item *item): unsigned_flag(item->unsigned_flag), with_sum_func(item->with_sum_func), fixed(item->fixed), - collation(item->collation), - item_flags(item->item_flags) + collation(item->collation) { next= thd->free_list; // Put in free list thd->free_list= this; diff --git a/sql/item.h b/sql/item.h index 82ab5a66cfb..8de2adeb730 100644 --- a/sql/item.h +++ b/sql/item.h @@ -107,11 +107,6 @@ public: typedef bool (Item::*Item_processor)(byte *arg); -/* - See comments for sql_yacc.yy: insert_update_elem rule - */ -#define MY_ITEM_PREFER_1ST_TABLE 1 - class Item { Item(const Item &); /* Prevent use of these */ void operator=(Item &); @@ -147,7 +142,6 @@ public: my_bool with_sum_func; my_bool fixed; /* If item fixed with fix_fields */ DTCollation collation; - uint8 item_flags; /* Flags on how item should be processed */ // alloc & destruct is done as start of select using sql_alloc Item(); @@ -333,11 +327,6 @@ public: cleanup(); delete this; } - virtual bool set_flags_processor(byte *args) - { - this->item_flags|= *((uint8*)args); - return false; - } }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 2bcaa1ecc2d..cc58e34d582 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -576,7 +576,8 @@ int mysql_multi_update_lock(THD *thd, List *fields, SELECT_LEX *select_lex); int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, - TABLE_LIST *insert_table_list, TABLE *table, + TABLE_LIST *insert_table_list, + TABLE_LIST *dup_table_list, TABLE *table, List &fields, List_item *values, List &update_fields, List &update_values, enum_duplicates duplic); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 84c03bee917..9a5b2522be9 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1993,7 +1993,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, const char *name=item->field_name; uint length=(uint) strlen(name); char name_buff[NAME_LEN+1]; - + bool allow_rowid; if (item->cached_table) { @@ -2085,9 +2085,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, return (Field*) not_found_field; return (Field*) 0; } - bool allow_rowid= tables && !tables->next; // Only one table - uint table_idx= 0; - for (; tables ; tables=tables->next, table_idx++) + allow_rowid= tables && !tables->next; // Only one table + for (; tables ; tables=tables->next) { if (!tables->table) { @@ -2116,8 +2115,6 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, return (Field*) 0; } found= field; - if (table_idx == 0 && item->item_flags & MY_ITEM_PREFER_1ST_TABLE) - break; } } if (found) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index f09d3214c74..deccc1d4dca 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -271,7 +271,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, thd->used_tables=0; values= its++; - if (mysql_prepare_insert(thd, table_list, insert_table_list, table, + if (mysql_prepare_insert(thd, table_list, insert_table_list, + insert_table_list, table, fields, values, update_fields, update_values, duplic)) goto abort; @@ -499,22 +500,37 @@ abort: SYNOPSIS mysql_prepare_insert() - thd - thread handler - table_list - global table list - insert_table_list - local table list of INSERT SELECT_LEX - values - values to insert. NULL for INSERT ... SELECT + thd thread handler + table_list global table list (not including first table for + INSERT ... SELECT) + insert_table_list Table we are inserting into (for INSERT ... SELECT) + dup_table_list Tables to be used in ON DUPLICATE KEY + It's either all global tables or only the table we + insert into, depending on if we are using GROUP BY + in the SELECT clause). + values Values to insert. NULL for INSERT ... SELECT + + TODO (in far future) + In cases of: + INSERT INTO t1 SELECT a, sum(a) as sum1 from t2 GROUP BY a + ON DUPLICATE KEY ... + we should be able to refer to sum1 in the ON DUPLICATE KEY part RETURN VALUE - 0 - OK - -1 - error (message is not sent to user) + 0 OK + -1 error (message is not sent to user) */ + int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, - TABLE_LIST *insert_table_list, TABLE *table, + TABLE_LIST *insert_table_list, + TABLE_LIST *dup_table_list, + TABLE *table, List &fields, List_item *values, List &update_fields, List &update_values, enum_duplicates duplic) { DBUG_ENTER("mysql_prepare_insert"); + if (duplic == DUP_UPDATE && !table->insert_values) { /* it should be allocated before Item::fix_fields() */ @@ -528,7 +544,7 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, (values && setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0)) || (duplic == DUP_UPDATE && (check_update_fields(thd, table, insert_table_list, update_fields) || - setup_fields(thd, 0, insert_table_list, update_values, 1, 0, 0)))) + setup_fields(thd, 0, dup_table_list, update_values, 1, 0, 0)))) DBUG_RETURN(-1); if (values && find_real_table_in_list(table_list->next, table_list->db, table_list->real_name)) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 233104c9a90..c0283f81315 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1943,10 +1943,10 @@ mysql_execute_command(THD *thd) if (tables || &lex->select_lex != lex->all_selects_list) mysql_reset_errors(thd); - /* - When subselects or time_zone info is used in a query - we create a new TABLE_LIST containing all referenced tables - and set local variable 'tables' to point to this list. + /* + When subselects or time_zone info is used in a query + we create a new TABLE_LIST containing all referenced tables + and set local variable 'tables' to point to this list. */ if ((&lex->select_lex != lex->all_selects_list || lex->time_zone_tables_used) && @@ -2831,6 +2831,8 @@ unsent_create_error: case SQLCOM_INSERT_SELECT: { TABLE_LIST *first_local_table= (TABLE_LIST *) select_lex->table_list.first; + TABLE_LIST dup_tables; + TABLE *insert_table; if ((res= insert_precheck(thd, tables))) break; @@ -2856,14 +2858,27 @@ unsent_create_error: if ((res= open_and_lock_tables(thd, tables))) break; + insert_table= tables->table; /* Skip first table, which is the table we are inserting in */ select_lex->table_list.first= (byte*) first_local_table->next; - - if (!(res= mysql_prepare_insert(thd, tables, first_local_table, - tables->table, lex->field_list, 0, + tables= (TABLE_LIST *) select_lex->table_list.first; + dup_tables= *first_local_table; + first_local_table->next= 0; + if (select_lex->group_list.elements != 0) + { + /* + When we are using GROUP BY we can't refere to other tables in the + ON DUPLICATE KEY part + */ + dup_tables.next= 0; + } + + if (!(res= mysql_prepare_insert(thd, tables, first_local_table, + &dup_tables, insert_table, + lex->field_list, 0, lex->update_list, lex->value_list, lex->duplicates)) && - (result= new select_insert(tables->table, &lex->field_list, + (result= new select_insert(insert_table, &lex->field_list, &lex->update_list, &lex->value_list, lex->duplicates, lex->ignore))) { @@ -2876,7 +2891,7 @@ unsent_create_error: /* revert changes for SP */ lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; delete result; - tables->table->insert_values= 0; + insert_table->insert_values= 0; if (thd->net.report_error) res= -1; } @@ -4950,10 +4965,11 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, the slow query log, and the relay log (if it exists). */ - /* - Writing this command to the binlog may result in infinite loops when doing - mysqlbinlog|mysql, and anyway it does not really make sense to log it - automatically (would cause more trouble to users than it would help them) + /* + Writing this command to the binlog may result in infinite loops when + doing mysqlbinlog|mysql, and anyway it does not really make sense to + log it automatically (would cause more trouble to users than it would + help them) */ tmp_write_to_binlog= 0; mysql_log.new_file(1); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 1f5bb04c802..9e2612c5661 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -918,6 +918,7 @@ static int mysql_test_insert(Prepared_statement *stmt, table_list->table->insert_values=(byte *)1; // don't allocate insert_values if ((res= mysql_prepare_insert(thd, table_list, insert_table_list, + insert_table_list, table_list->table, fields, values, update_fields, update_values, duplic))) goto error; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 460234de156..bc21649fe54 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4239,24 +4239,9 @@ insert_update_elem: simple_ident equal expr_or_default { LEX *lex= Lex; - uint8 tmp= MY_ITEM_PREFER_1ST_TABLE; if (lex->update_list.push_back($1) || lex->value_list.push_back($3)) YYABORT; - /* - INSERT INTO a1(a) SELECT b1.a FROM b1 ON DUPLICATE KEY - UPDATE a= a + b1.b - - Set MY_ITEM_PREFER_1ST_TABLE flag to $1 and $3 items - to prevent find_field_in_tables() doing further item searching - if it finds item occurence in first table in insert_table_list. - This allows to avoid ambiguity in resolving 'a' field in - example above. - */ - $1->walk(&Item::set_flags_processor, - (byte *) &tmp); - $3->walk(&Item::set_flags_processor, - (byte *) &tmp); }; opt_low_priority: From 76d444fcb64d0272c0f8efd450edc7087a105723 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 20:31:00 +0300 Subject: [PATCH 03/20] Portability fixes Fixes while reviewing new pushed code NULL as argument to encrypt/decrypt should return NULL without a warning client/mysqldump.c: Cleanup Ensure we free allocated memory Portability fixes client/mysqltest.c: Cleanup of code during review Portability fixes (Don't use 'bool') mysql-test/r/func_encrypt.result: NULL as argument to encrypt/decrypt should return NULL without a warning mysql-test/r/func_encrypt_nossl.result: Added test of NULL argument mysql-test/t/func_encrypt_nossl.test: Added test of NULL argument sql/handler.cc: Cleanup during code review sql/item_strfunc.cc: NULL as argument to encrypt/decrypt should return NULL without a warning sql/sql_parse.cc: Fix wrong merge (fix was not needed as the previous code was reverted) sql/sql_table.cc: Removed extra new line --- client/mysqldump.c | 55 +++++++++++++++----------- client/mysqltest.c | 37 +++++++++-------- mysql-test/r/func_encrypt.result | 12 ------ mysql-test/r/func_encrypt_nossl.result | 4 ++ mysql-test/t/func_encrypt_nossl.test | 1 + sql/handler.cc | 16 +++----- sql/item_strfunc.cc | 6 +-- sql/sql_parse.cc | 1 + sql/sql_table.cc | 1 - 9 files changed, 65 insertions(+), 68 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 04f2f40068f..fb5270c3222 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -533,6 +533,12 @@ static void write_footer(FILE *sql_file) } } /* write_footer */ +static void free_table_ent(char *key) + +{ + my_free((gptr) key, MYF(0)); +} + byte* get_table_key(const char *entry, uint *length, my_bool not_used __attribute__((unused))) @@ -544,8 +550,9 @@ byte* get_table_key(const char *entry, uint *length, void init_table_rule_hash(HASH* h) { - if(hash_init(h, charset_info, 16, 0, 0, - (hash_get_key) get_table_key, 0, 0)) + if (hash_init(h, charset_info, 16, 0, 0, + (hash_get_key) get_table_key, + (hash_free_key) free_table_ent, 0)) exit(EX_EOM); } @@ -933,13 +940,14 @@ static char *quote_name(const char *name, char *buff, my_bool force) return buff; } /* quote_name */ + /* Quote a table name so it can be used in "SHOW TABLES LIKE " SYNOPSIS - quote_for_like - name - name of the table - buff - quoted name of the table + quote_for_like() + name name of the table + buff quoted name of the table DESCRIPTION Quote \, _, ' and % characters @@ -955,7 +963,6 @@ static char *quote_name(const char *name, char *buff, my_bool force) Example: "t\1" => "t\\\\1" */ - static char *quote_for_like(const char *name, char *buff) { char *to= buff; @@ -2228,17 +2235,17 @@ static int get_actual_table_name(const char *old_table_name, retval = 1; if (tableRes != NULL) { - my_ulonglong numRows = mysql_num_rows(tableRes); - if (numRows > 0) - { - row= mysql_fetch_row( tableRes ); - strmake(new_table_name, row[0], buf_size-1); - retval = 0; - DBUG_PRINT("info", ("new_table_name: %s", new_table_name)); - } - mysql_free_result(tableRes); + my_ulonglong numRows= mysql_num_rows(tableRes); + if (numRows > 0) + { + row= mysql_fetch_row( tableRes ); + strmake(new_table_name, row[0], buf_size-1); + retval= 0; + DBUG_PRINT("info", ("new_table_name: %s", new_table_name)); + } + mysql_free_result(tableRes); } - DBUG_PRINT("exit", ("retval: %d", retval)); + DBUG_PRINT("exit", ("retval: %d", retval)); DBUG_RETURN(retval); } @@ -2250,7 +2257,6 @@ static int dump_selected_tables(char *db, char **table_names, int tables) char new_table_name[NAME_LEN]; DYNAMIC_STRING lock_tables_query; HASH dump_tables; - DBUG_ENTER("dump_selected_tables"); if (init_dumping(db)) @@ -2258,7 +2264,8 @@ static int dump_selected_tables(char *db, char **table_names, int tables) /* Init hash table for storing the actual name of tables to dump */ if (hash_init(&dump_tables, charset_info, 16, 0, 0, - (hash_get_key) get_table_key, 0, 0)) + (hash_get_key) get_table_key, (hash_free_key) free_table_ent, + 0)) exit(EX_EOM); init_dynamic_string(&lock_tables_query, "LOCK TABLES ", 256, 1024); @@ -2266,8 +2273,8 @@ static int dump_selected_tables(char *db, char **table_names, int tables) { /* the table name passed on commandline may be wrong case */ - if (!get_actual_table_name( *table_names, - new_table_name, sizeof(new_table_name) )) + if (!get_actual_table_name(*table_names, + new_table_name, sizeof(new_table_name) )) { /* Add found table name to lock_tables_query */ if (lock_tables) @@ -2310,12 +2317,11 @@ static int dump_selected_tables(char *db, char **table_names, int tables) print_xml_tag1(md_result_file, "", "database name=", db, "\n"); /* Dump each selected table */ - const char *table_name; for (i= 0 ; i < dump_tables.records ; i++) { - table_name= hash_element(&dump_tables, i); + const char *table_name= hash_element(&dump_tables, i); DBUG_PRINT("info",("Dumping table %s", table_name)); - numrows = getTableStructure(table_name, db); + numrows= getTableStructure(table_name, db); if (!dFlag && numrows > 0) dumpTable(numrows, table_name); } @@ -2620,6 +2626,7 @@ int main(int argc, char **argv) { compatible_mode_normal_str[0]= 0; default_charset= (char *)mysql_universal_client_charset; + bzero((char*) &ignore_table, sizeof(ignore_table)); MY_INIT("mysqldump"); if (get_options(&argc, &argv)) @@ -2678,6 +2685,8 @@ err: if (md_result_file != stdout) my_fclose(md_result_file, MYF(0)); my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); + if (hash_inited(&ignore_table)) + hash_free(&ignore_table); if (extended_insert) dynstr_free(&extended_row); if (insert_pat_inited) diff --git a/client/mysqltest.c b/client/mysqltest.c index fd8f19332ec..87c34591b89 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -964,28 +964,27 @@ static void do_exec(struct st_query* q) error= pclose(res_file); if (error != 0) { - uint status= WEXITSTATUS(error); - if(q->abort_on_error) + uint status= WEXITSTATUS(error), i; + my_bool ok= 0; + + if (q->abort_on_error) die("At line %u: command \"%s\" failed", start_lineno, cmd); - else + + DBUG_PRINT("info", + ("error: %d, status: %d", error, status)); + for (i=0 ; (uint) i < q->expected_errors ; i++) { - DBUG_PRINT("info", - ("error: %d, status: %d", error, status)); - bool ok= 0; - uint i; - for (i=0 ; (uint) i < q->expected_errors ; i++) - { - DBUG_PRINT("info", ("expected error: %d", q->expected_errno[i].code.errnum)); - if ((q->expected_errno[i].type == ERR_ERRNO) && - (q->expected_errno[i].code.errnum == status)) - ok= 1; - verbose_msg("At line %u: command \"%s\" failed with expected error: %d", - start_lineno, cmd, status); - } - if (!ok) - die("At line: %u: command \"%s\" failed with wrong error: %d", - start_lineno, cmd, status); + DBUG_PRINT("info", ("expected error: %d", + q->expected_errno[i].code.errnum)); + if ((q->expected_errno[i].type == ERR_ERRNO) && + (q->expected_errno[i].code.errnum == status)) + ok= 1; + verbose_msg("At line %u: command \"%s\" failed with expected error: %d", + start_lineno, cmd, status); } + if (!ok) + die("At line: %u: command \"%s\" failed with wrong error: %d", + start_lineno, cmd, status); } else if (q->expected_errno[0].type == ERR_ERRNO && q->expected_errno[0].code.errnum != 0) diff --git a/mysql-test/r/func_encrypt.result b/mysql-test/r/func_encrypt.result index 992d01c66cd..3eb8ec4354c 100644 --- a/mysql-test/r/func_encrypt.result +++ b/mysql-test/r/func_encrypt.result @@ -128,18 +128,12 @@ Error 1108 Incorrect parameters to procedure 'des_encrypt' select des_encrypt(NULL); des_encrypt(NULL) NULL -Warnings: -Error 1108 Incorrect parameters to procedure 'des_encrypt' select des_encrypt(NULL, 10); des_encrypt(NULL, 10) NULL -Warnings: -Error 1108 Incorrect parameters to procedure 'des_encrypt' select des_encrypt(NULL, NULL); des_encrypt(NULL, NULL) NULL -Warnings: -Error 1108 Incorrect parameters to procedure 'des_encrypt' select des_encrypt(10, NULL); des_encrypt(10, NULL) NULL @@ -156,18 +150,12 @@ hello select des_decrypt(NULL); des_decrypt(NULL) NULL -Warnings: -Error 1108 Incorrect parameters to procedure 'des_decrypt' select des_decrypt(NULL, 10); des_decrypt(NULL, 10) NULL -Warnings: -Error 1108 Incorrect parameters to procedure 'des_decrypt' select des_decrypt(NULL, NULL); des_decrypt(NULL, NULL) NULL -Warnings: -Error 1108 Incorrect parameters to procedure 'des_decrypt' select des_decrypt(10, NULL); des_decrypt(10, NULL) 10 diff --git a/mysql-test/r/func_encrypt_nossl.result b/mysql-test/r/func_encrypt_nossl.result index fea752f4a4a..e3ae6a5192a 100644 --- a/mysql-test/r/func_encrypt_nossl.result +++ b/mysql-test/r/func_encrypt_nossl.result @@ -23,6 +23,10 @@ des_encrypt("test", NULL) NULL Warnings: Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +des_encrypt(NULL, NULL) +NULL +Warnings: +Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working select des_decrypt("test", 'anotherkeystr'); des_decrypt("test", 'anotherkeystr') NULL diff --git a/mysql-test/t/func_encrypt_nossl.test b/mysql-test/t/func_encrypt_nossl.test index 0e9d93f5968..95c104ce046 100644 --- a/mysql-test/t/func_encrypt_nossl.test +++ b/mysql-test/t/func_encrypt_nossl.test @@ -9,6 +9,7 @@ select des_encrypt("test", 1); select des_encrypt("test", 9); select des_encrypt("test", 100); select des_encrypt("test", NULL); +select des_encrypt(NULL, NULL); select des_decrypt("test", 'anotherkeystr'); select des_decrypt(1, 1); select des_decrypt(des_encrypt("test", 'thekey')); diff --git a/sql/handler.cc b/sql/handler.cc index dacfc7d9ac5..cb1d88a30d4 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1357,14 +1357,12 @@ int ha_create_table_from_engine(THD* thd, HA_CREATE_INFO create_info; TABLE table; DBUG_ENTER("ha_create_table_from_engine"); - DBUG_PRINT("enter", ("name '%s'.'%s'", - db, name)); + DBUG_PRINT("enter", ("name '%s'.'%s'", db, name)); bzero((char*) &create_info,sizeof(create_info)); - - if(error= ha_discover(thd, db, name, &frmblob, &frmlen)) + if ((error= ha_discover(thd, db, name, &frmblob, &frmlen))) { - // Table could not be discovered and thus not created + /* Table could not be discovered and thus not created */ DBUG_RETURN(error); } @@ -1375,11 +1373,10 @@ int ha_create_table_from_engine(THD* thd, (void)strxnmov(path,FN_REFLEN,mysql_data_home,"/",db,"/",name,NullS); // Save the frm file - if (writefrm(path, frmblob, frmlen)) - { - my_free((char*) frmblob, MYF(MY_ALLOW_ZERO_PTR)); + error= writefrm(path, frmblob, frmlen); + my_free((char*) frmblob, MYF(0)); + if (error) DBUG_RETURN(2); - } if (openfrm(path,"",0,(uint) READ_ALL, 0, &table)) DBUG_RETURN(3); @@ -1395,7 +1392,6 @@ int ha_create_table_from_engine(THD* thd, } error=table.file->create(path,&table,&create_info); VOID(closefrm(&table)); - my_free((char*) frmblob, MYF(MY_ALLOW_ZERO_PTR)); DBUG_RETURN(error != 0); } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index ceb925be4d2..881a8a7c915 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -381,8 +381,8 @@ String *Item_func_des_encrypt::val_str(String *str) uint key_number, res_length, tail; String *res= args[0]->val_str(str); - if ((null_value=args[0]->null_value)) - goto error; + if ((null_value= args[0]->null_value)) + return 0; // ENCRYPT(NULL) == NULL if ((res_length=res->length()) == 0) return &my_empty_string; @@ -474,7 +474,7 @@ String *Item_func_des_decrypt::val_str(String *str) uint length=res->length(),tail; if ((null_value=args[0]->null_value)) - goto error; + return 0; length=res->length(); if (length < 9 || (length % 8) != 1 || !((*res)[0] & 128)) return res; // Skip decryption if not encrypted diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c7442f06891..c0283f81315 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2897,6 +2897,7 @@ unsent_create_error: } else res= -1; + first_local_table->next= tables; lex->select_lex.table_list.first= (byte*) first_local_table; break; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index d7a07d17761..b68b20c32a3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -255,7 +255,6 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, table->real_name); else error= 1; - } else { From f3dd8151569f301d5201d073ba2d94a692353044 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 20:31:02 +0300 Subject: [PATCH 04/20] Fix test after last push --- mysql-test/r/func_encrypt_nossl.result | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/r/func_encrypt_nossl.result b/mysql-test/r/func_encrypt_nossl.result index e3ae6a5192a..d0df2335afa 100644 --- a/mysql-test/r/func_encrypt_nossl.result +++ b/mysql-test/r/func_encrypt_nossl.result @@ -23,6 +23,7 @@ des_encrypt("test", NULL) NULL Warnings: Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select des_encrypt(NULL, NULL); des_encrypt(NULL, NULL) NULL Warnings: From f7780a1cc2da33dd7527b9708c49deb6175a067c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 04:33:06 +0200 Subject: [PATCH 05/20] opt_range.cc: Added missing `;' to DBUG_RETURN() sql/opt_range.cc: Added missing `;' to DBUG_RETURN() --- sql/opt_range.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 75cf9e6b3f0..9f268804cc3 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -982,7 +982,7 @@ get_mm_parts(PARAM *param, COND *cond_func, Field *field, field, Item_func::GT_FUNC, value, cmp_type); if (!tree2) - DBUG_RETURN(0) + DBUG_RETURN(0); tree= tree_or(param,tree,tree2); } DBUG_RETURN(tree); From 9c41fbda76cb86f545046b1bf1dbc07710ab7927 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 04:37:01 +0200 Subject: [PATCH 06/20] mysqld.dsp: Corrected quoting of string "pro-nt" VC++Files/sql/mysqld.dsp: Corrected quoting of string "pro-nt" --- VC++Files/sql/mysqld.dsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index 3508e6b31d0..034c8350c67 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -272,7 +272,7 @@ LINK32=xilink6.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /D "NDEBUG" /FD /c # SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "__NT__" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D LICENSE=Commercial /D "NDEBUG" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-pro-nt" /FD +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "__NT__" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D LICENSE=Commercial /D "NDEBUG" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-pro-nt /FD # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe From c7e157e71ed71a3f024280c4b3997b79c903db97 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 04:44:27 +0200 Subject: [PATCH 07/20] configure.in: Enable build with CXX=gcc and gcc version 4 configure.in: Enable build with CXX=gcc and gcc version 4 --- configure.in | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index d454d23b38c..0889e9a3257 100644 --- a/configure.in +++ b/configure.in @@ -419,9 +419,14 @@ then if echo $CXX | grep gcc > /dev/null 2>&1 then - if $CXX -v 2>&1 | grep 'version 3' > /dev/null 2>&1 + AC_MSG_CHECKING([if CXX is gcc 3 or 4]) + if $CXX -v 2>&1 | grep 'version [[34]]' > /dev/null 2>&1 then + AC_MSG_RESULT([yes]) + AC_MSG_NOTICE([using MySQL tricks to avoid linking C++ code with C++ libraries]) CXXFLAGS="$CXXFLAGS -DUSE_MYSYS_NEW -DDEFINE_CXA_PURE_VIRTUAL" + else + AC_MSG_RESULT([no]) fi fi fi From 0037781f05b81f01cdd88ca893f200d2a5664c48 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 04:49:03 +0200 Subject: [PATCH 08/20] Makefile.am: Bug#9873, reenabled --without-man option to work Makefile.am: Bug#9873, reenabled --without-man option to work --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index ffa27220611..96f3561e31c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,7 @@ EXTRA_DIST = INSTALL-SOURCE README COPYING EXCEPTIONS-CLIENT SUBDIRS = . include @docs_dirs@ @zlib_dir@ \ @readline_topdir@ sql-common \ @thread_dirs@ pstack \ - @sql_union_dirs@ scripts man tests \ + @sql_union_dirs@ scripts @man_dirs@ tests \ netware @libmysqld_dirs@ \ @bench_dirs@ support-files @fs_dirs@ @tools_dirs@ From 5c429181187d28a76a555f85aa68425d50bc303f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 05:25:29 +0200 Subject: [PATCH 09/20] make_win_src_distribution.sh: Bug#11009, some more cleanup of unneded files from bootstrap scripts/make_win_src_distribution.sh: Bug#11009, some more cleanup of unneded files from bootstrap --- scripts/make_win_src_distribution.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh index b8dd907920c..71d61b7a02d 100644 --- a/scripts/make_win_src_distribution.sh +++ b/scripts/make_win_src_distribution.sh @@ -357,6 +357,9 @@ if [ -d $BASE/SSL/SCCS ] then find $BASE/ -type d -name SCCS -printf " \"%p\"" | xargs rm -r -f fi +find $BASE/ -type d -name .deps -printf " \"%p\"" | xargs rm -r -f +find $BASE/ -type d -name .libs -printf " \"%p\"" | xargs rm -r -f +rm -r -f "$BASE/mysql-test/var" # # Initialize the initial data directory From 2776aa35b7abc4c0f742eaa94c04b4072e2ba83d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 15:00:22 +0500 Subject: [PATCH 10/20] ctype_ucs.result, ctype_ucs.test, ctype_utf8.result, ctype_utf8.test: Fixing tests accordingly. ctype-ucs2.c: The same fix for UCS2. ctype-utf8.c: Bug #9557 MyISAM utf8 table crash The problem was that my_strnncollsp_xxx could return big value in the range 0..0xffff. for some constant pairs it could return 32738, which is defined as MI_FOUND_WRONG_KEY in myisamdef.h. As a result, table considered to be crashed. Fix to return -1,0 or 1. strings/ctype-utf8.c: Bug #9557 MyISAM utf8 table crash The problem was that my_strnncollsp_xxx could return big value in the range 0..0xffff. for some constant pairs it could return 32738, which is defined as MI_FOUND_WRONG_KEY in myisamdef.h. As a result, table considered to be crashed. Fix to return -1,0 or 1. strings/ctype-ucs2.c: The same fix for UCS2. mysql-test/t/ctype_utf8.test: Fixing tests accordingly. mysql-test/r/ctype_utf8.result: Fixing tests accordingly. mysql-test/t/ctype_ucs.test: Fixing tests accordingly. mysql-test/r/ctype_ucs.result: Fixing tests accordingly. --- mysql-test/r/ctype_ucs.result | 11 +++++++++++ mysql-test/r/ctype_utf8.result | 11 +++++++++++ mysql-test/t/ctype_ucs.test | 12 ++++++++++++ mysql-test/t/ctype_utf8.test | 12 ++++++++++++ strings/ctype-ucs2.c | 6 +++--- strings/ctype-utf8.c | 4 ++-- 6 files changed, 51 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 5902dd247ce..6d00f13737d 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -630,3 +630,14 @@ Warnings: Warning 1265 Data truncated for column 'Field1' at row 1 DROP TABLE t1; SET NAMES latin1; +CREATE TABLE t1 ( +a varchar(255) NOT NULL default '', +KEY a (a) +) ENGINE=MyISAM DEFAULT CHARSET=ucs2 COLLATE ucs2_general_ci; +insert into t1 values (0x803d); +insert into t1 values (0x005b); +select hex(a) from t1; +hex(a) +005B +803D +drop table t1; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 12ef8dfb8e8..3a8265b01f7 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -939,3 +939,14 @@ content msisdn ERR Имри.Афимим.Аеимимримдмримрмрирор имримримримр имридм ирбднримрфмририримрфмфмим.Ад.Д имдимримрад.Адимримримрмдиримримримр м.Дадимфшьмримд им.Адимимрн имадми 1234567890 11 g 1234567890 DROP TABLE t1,t2; +CREATE TABLE t1 ( +a varchar(255) NOT NULL default '', +KEY a (a) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE utf8_general_ci; +insert into t1 values (_utf8 0xe880bd); +insert into t1 values (_utf8 0x5b); +select hex(a) from t1; +hex(a) +5B +E880BD +drop table t1; diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 6c72c409463..8dd8d02d018 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -404,3 +404,15 @@ CREATE TABLE t1 (Field1 int(10) unsigned default '0'); INSERT INTO t1 VALUES ('-1'); DROP TABLE t1; SET NAMES latin1; + +# +# Bug#9557 MyISAM utf8 table crash +# +CREATE TABLE t1 ( + a varchar(255) NOT NULL default '', + KEY a (a) +) ENGINE=MyISAM DEFAULT CHARSET=ucs2 COLLATE ucs2_general_ci; +insert into t1 values (0x803d); +insert into t1 values (0x005b); +select hex(a) from t1; +drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 343b7c867e7..0a847057258 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -788,3 +788,15 @@ INSERT INTO t2 VALUES ('1234567890',2,'2005-05-24 13:53:25'); SELECT content, t2.msisdn FROM t1, t2 WHERE t1.msisdn = '1234567890'; DROP TABLE t1,t2; + +# +# Bug#9557 MyISAM utf8 table crash +# +CREATE TABLE t1 ( + a varchar(255) NOT NULL default '', + KEY a (a) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE utf8_general_ci; +insert into t1 values (_utf8 0xe880bd); +insert into t1 values (_utf8 0x5b); +select hex(a) from t1; +drop table t1; diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 12c1ae905cf..c3caaeadfb3 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -209,7 +209,7 @@ static int my_strnncoll_ucs2(CHARSET_INFO *cs, t_wc = uni_plane[plane] ? uni_plane[plane][t_wc & 0xFF].sort : t_wc; if ( s_wc != t_wc ) { - return ((int) s_wc) - ((int) t_wc); + return s_wc > t_wc ? 1 : -1; } s+=s_res; @@ -267,7 +267,7 @@ static int my_strnncollsp_ucs2(CHARSET_INFO *cs __attribute__((unused)), int t_wc = uni_plane[t[0]] ? (int) uni_plane[t[0]][t[1]].sort : (((int) t[0]) << 8) + (int) t[1]; if ( s_wc != t_wc ) - return s_wc - t_wc; + return s_wc > t_wc ? 1 : -1; s+= 2; t+= 2; @@ -1343,7 +1343,7 @@ int my_strnncoll_ucs2_bin(CHARSET_INFO *cs, } if ( s_wc != t_wc ) { - return ((int) s_wc) - ((int) t_wc); + return s_wc > t_wc ? 1 : -1; } s+=s_res; diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 230b44796e8..f5192b26ce2 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2000,7 +2000,7 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs, t_wc = uni_plane[plane] ? uni_plane[plane][t_wc & 0xFF].sort : t_wc; if ( s_wc != t_wc ) { - return ((int) s_wc) - ((int) t_wc); + return s_wc > t_wc ? 1 : -1; } s+=s_res; @@ -2065,7 +2065,7 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs, t_wc = uni_plane[plane] ? uni_plane[plane][t_wc & 0xFF].sort : t_wc; if ( s_wc != t_wc ) { - return ((int) s_wc) - ((int) t_wc); + return s_wc > t_wc ? 1 : -1; } s+=s_res; From 67abd491a1d5c631b0e72ea89941fafd9ac2fa34 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 03:18:37 -0700 Subject: [PATCH 11/20] group_by.result, group_by.test: Added a test case for bug #11414. sql_select.cc: Fixed bug #11414: crash on Windows with some simple GROUP BY queries. It happened to an allocation of an array containing 0 Copy_field elements in setup_copy_fields. The bug had been already fixed in 5.0. sql/sql_select.cc: Fixed bug #11414: crash on Windows with some simple GROUP BY queries. It happened to an allocation of an array containing 0 Copy_field elements in setup_copy_fields. The bug had been already fixed in 5.0. mysql-test/t/group_by.test: Added a test case for bug #11414. mysql-test/r/group_by.result: Added a test case for bug #11414. --- mysql-test/r/group_by.result | 6 ++++++ mysql-test/t/group_by.test | 12 ++++++++++++ sql/sql_select.cc | 5 +++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 7f78b8bda9b..295663fe1d3 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -751,3 +751,9 @@ COUNT(DISTINCT(t1.id)) err_comment 1 NULL 1 a problem DROP TABLE t1, t2; +CREATE TABLE t1 (n int); +INSERT INTO t1 VALUES (1); +SELECT n+1 AS n FROM t1 GROUP BY n; +n +2 +DROP TABLE t1; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 694aa8d7411..23d51b0f297 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -580,3 +580,15 @@ SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS err_comment FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY err_comment; DROP TABLE t1, t2; + +# +# Test for bug #11414: crash on Windows for a simple GROUP BY query +# + +CREATE TABLE t1 (n int); +INSERT INTO t1 VALUES (1); + +SELECT n+1 AS n FROM t1 GROUP BY n; + +DROP TABLE t1; + diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2f165565ce1..f2db5adfdda 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8727,7 +8727,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, { Item *pos; List_iterator_fast li(all_fields); - Copy_field *copy; + Copy_field *copy= NULL; res_selected_fields.empty(); res_all_fields.empty(); List_iterator_fast itr(res_all_fields); @@ -8735,7 +8735,8 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, uint i, border= all_fields.elements - elements; DBUG_ENTER("setup_copy_fields"); - if (!(copy=param->copy_field= new Copy_field[param->field_count])) + if (param->field_count && + !(copy=param->copy_field= new Copy_field[param->field_count])) goto err2; param->copy_funcs.empty(); From 05c7edf64801efa5b0d99ca779eb0b31a4d92462 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 15:06:16 +0300 Subject: [PATCH 12/20] Move reset of insert_values to ensure it's done also during error conditions This fixed a failure of insert_update.test on some platforms mysys/thr_alarm.c: Fixed problem noticed by valgrind sql/opt_range.cc: Simple optimization for common case sql/sql_base.cc: Safety assert sql/sql_insert.cc: Added comment --- mysys/thr_alarm.c | 1 + sql/opt_range.cc | 3 +-- sql/sql_base.cc | 1 + sql/sql_insert.cc | 4 ++++ sql/sql_parse.cc | 2 +- 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 19611a6027a..05d14073953 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -86,6 +86,7 @@ void init_thr_alarm(uint max_alarms) { struct sigaction sact; sact.sa_flags = 0; + bzero((char*) &sact, sizeof(sact)); sact.sa_handler = thread_alarm; sigaction(THR_CLIENT_ALARM, &sact, (struct sigaction*) 0); } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 9f268804cc3..2dd097cbaab 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -981,8 +981,7 @@ get_mm_parts(PARAM *param, COND *cond_func, Field *field, SEL_TREE *tree2= get_mm_parts(param, cond_func, field, Item_func::GT_FUNC, value, cmp_type); - if (!tree2) - DBUG_RETURN(0); + /* tree_or() will return 0 if tree2 is 0 */ tree= tree_or(param,tree,tree2); } DBUG_RETURN(tree); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c9861790b06..7a36d33a42c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -979,6 +979,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, if (table->timestamp_field) table->timestamp_field_type= table->timestamp_field->get_auto_set_type(); DBUG_ASSERT(table->key_read == 0); + DBUG_ASSERT(table->insert_values == 0); DBUG_RETURN(table); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index deccc1d4dca..7d613ad6fbf 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -516,6 +516,10 @@ abort: ON DUPLICATE KEY ... we should be able to refer to sum1 in the ON DUPLICATE KEY part + WARNING + You MUST set table->insert_values to 0 after calling this function + before releasing the table object. + RETURN VALUE 0 OK -1 error (message is not sent to user) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c0283f81315..d7fd3239df5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2891,12 +2891,12 @@ unsent_create_error: /* revert changes for SP */ lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; delete result; - insert_table->insert_values= 0; if (thd->net.report_error) res= -1; } else res= -1; + insert_table->insert_values= 0; // Set by mysql_prepare_insert() first_local_table->next= tables; lex->select_lex.table_list.first= (byte*) first_local_table; break; From 3aca0a0c62d8e2557dd366a9b2ecf0053bf1b832 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 22:20:25 +0300 Subject: [PATCH 13/20] fixed not_null_tables() for IN() (BUG#9393) (IN() remove NULL rows only for tables from first argument (value which we looking for in IN() list) but not for tables from IN() list) Also it will be better change Item::not_null_tables() to prohibit this optimisation by default for new created items in 5.0 or 5.1. mysql-test/r/select.result: IN with outer join condition mysql-test/t/select.test: IN with outer join condition sql/item_cmpfunc.h: correct not_null_tables() for IN --- mysql-test/r/select.result | 9 +++++++++ mysql-test/t/select.test | 15 +++++++++++++++ sql/item_cmpfunc.h | 6 ++++++ 3 files changed, 30 insertions(+) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index f828759672a..abf5c8c87ad 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2515,3 +2515,12 @@ SELECT b FROM t1 WHERE b=0x8000000000000000; b 9223372036854775808 DROP TABLE t1; +CREATE TABLE `t1` ( `gid` int(11) default NULL, `uid` int(11) default NULL); +CREATE TABLE `t2` ( `ident` int(11) default NULL, `level` char(16) default NULL); +INSERT INTO `t2` VALUES (0,'READ'); +CREATE TABLE `t3` ( `id` int(11) default NULL, `name` char(16) default NULL); +INSERT INTO `t3` VALUES (1,'fs'); +select * from t3 left join t1 on t3.id = t1.uid, t2 where t2.ident in (0, t1.gid, t3.id, 0); +id name gid uid ident level +1 fs NULL NULL 0 READ +drop table t1,t2,t3; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 3877e67de41..baaab6e4189 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2060,3 +2060,18 @@ CREATE TABLE t1 (b BIGINT(20) UNSIGNED NOT NULL, PRIMARY KEY (b)); INSERT INTO t1 VALUES (0x8000000000000000); SELECT b FROM t1 WHERE b=0x8000000000000000; DROP TABLE t1; + +# +# IN with outer join condition (BUG#9393) +# +CREATE TABLE `t1` ( `gid` int(11) default NULL, `uid` int(11) default NULL); + +CREATE TABLE `t2` ( `ident` int(11) default NULL, `level` char(16) default NULL); +INSERT INTO `t2` VALUES (0,'READ'); + +CREATE TABLE `t3` ( `id` int(11) default NULL, `name` char(16) default NULL); +INSERT INTO `t3` VALUES (1,'fs'); + +select * from t3 left join t1 on t3.id = t1.uid, t2 where t2.ident in (0, t1.gid, t3.id, 0); + +drop table t1,t2,t3; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index bea8250de9d..525f269e528 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -769,6 +769,12 @@ class Item_func_in :public Item_int_func bool nulls_in_row(); bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } + /* + IN() protect from NULL only first argument, if construction like + "expression IN ()" will be allowed, we will need to check number of + argument here, because "NOT(NULL IN ())" is TRUE. + */ + table_map not_null_tables() const { return args[0]->not_null_tables(); } }; /* Functions used by where clause */ From 3dcf7083a9518a4d4bb6c0c6cd3aad12e6864d02 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 02:40:25 -0700 Subject: [PATCH 14/20] func_str.test: Added test cases for bug #11469. item_strfunc.h: Fixed bug #11469: wrong implementation of the not_null_tables method for CONCAT_WS. sql/item_strfunc.h: Fixed bug #11469: wrong implementation of the not_null_tables method for CONCAT_WS. mysql-test/t/func_str.test: Added test cases for bug #11469. --- mysql-test/r/func_str.result | 50 ++++++++++++++++++++++++++++++++ mysql-test/t/func_str.test | 56 ++++++++++++++++++++++++++++++++++++ sql/item_strfunc.h | 1 + 3 files changed, 107 insertions(+) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 60c77d91ca5..cbedf4370ff 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -800,3 +800,53 @@ SELECT * FROM t1, t2 WHERE num=substring(str from 1 for 6); str num notnumber 0 DROP TABLE t1,t2; +CREATE TABLE t1( +id int(11) NOT NULL auto_increment, +pc int(11) NOT NULL default '0', +title varchar(20) default NULL, +PRIMARY KEY (id) +); +INSERT INTO t1 VALUES +(1, 0, 'Main'), +(2, 1, 'Toys'), +(3, 1, 'Games'); +SELECT t1.id, CONCAT_WS('->', t3.title, t2.title, t1.title) as col1 +FROM t1 LEFT JOIN t1 AS t2 ON t1.pc=t2.id +LEFT JOIN t1 AS t3 ON t2.pc=t3.id; +id col1 +1 Main +2 Main->Toys +3 Main->Games +SELECT t1.id, CONCAT_WS('->', t3.title, t2.title, t1.title) as col1 +FROM t1 LEFT JOIN t1 AS t2 ON t1.pc=t2.id +LEFT JOIN t1 AS t3 ON t2.pc=t3.id +WHERE CONCAT_WS('->', t3.title, t2.title, t1.title) LIKE '%Toys%'; +id col1 +2 Main->Toys +DROP TABLE t1; +CREATE TABLE t1( +trackid int(10) unsigned NOT NULL auto_increment, +trackname varchar(100) NOT NULL default '', +PRIMARY KEY (trackid) +); +CREATE TABLE t2( +artistid int(10) unsigned NOT NULL auto_increment, +artistname varchar(100) NOT NULL default '', +PRIMARY KEY (artistid) +); +CREATE TABLE t3( +trackid int(10) unsigned NOT NULL, +artistid int(10) unsigned NOT NULL, +PRIMARY KEY (trackid,artistid) +); +INSERT INTO t1 VALUES (1, 'April In Paris'), (2, 'Autumn In New York'); +INSERT INTO t2 VALUES (1, 'Vernon Duke'); +INSERT INTO t3 VALUES (1,1); +SELECT CONCAT_WS(' ', trackname, artistname) trackname, artistname +FROM t1 LEFT JOIN t3 ON t1.trackid=t3.trackid +LEFT JOIN t2 ON t2.artistid=t3.artistid +WHERE CONCAT_WS(' ', trackname, artistname) LIKE '%In%'; +trackname artistname +April In Paris Vernon Duke Vernon Duke +Autumn In New York NULL +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 36cfac16ff3..f5f9ddac3b5 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -541,3 +541,59 @@ SELECT * FROM t1, t2 WHERE num=str; SELECT * FROM t1, t2 WHERE num=substring(str from 1 for 6); DROP TABLE t1,t2; + +# +# Bug #11469: NOT NULL optimization wrongly used for arguments of CONCAT_WS +# + +CREATE TABLE t1( + id int(11) NOT NULL auto_increment, + pc int(11) NOT NULL default '0', + title varchar(20) default NULL, + PRIMARY KEY (id) +); + +INSERT INTO t1 VALUES + (1, 0, 'Main'), + (2, 1, 'Toys'), + (3, 1, 'Games'); + +SELECT t1.id, CONCAT_WS('->', t3.title, t2.title, t1.title) as col1 + FROM t1 LEFT JOIN t1 AS t2 ON t1.pc=t2.id + LEFT JOIN t1 AS t3 ON t2.pc=t3.id; +SELECT t1.id, CONCAT_WS('->', t3.title, t2.title, t1.title) as col1 + FROM t1 LEFT JOIN t1 AS t2 ON t1.pc=t2.id + LEFT JOIN t1 AS t3 ON t2.pc=t3.id + WHERE CONCAT_WS('->', t3.title, t2.title, t1.title) LIKE '%Toys%'; + +DROP TABLE t1; + + +CREATE TABLE t1( + trackid int(10) unsigned NOT NULL auto_increment, + trackname varchar(100) NOT NULL default '', + PRIMARY KEY (trackid) +); + +CREATE TABLE t2( + artistid int(10) unsigned NOT NULL auto_increment, + artistname varchar(100) NOT NULL default '', + PRIMARY KEY (artistid) +); + +CREATE TABLE t3( + trackid int(10) unsigned NOT NULL, + artistid int(10) unsigned NOT NULL, + PRIMARY KEY (trackid,artistid) +); + +INSERT INTO t1 VALUES (1, 'April In Paris'), (2, 'Autumn In New York'); +INSERT INTO t2 VALUES (1, 'Vernon Duke'); +INSERT INTO t3 VALUES (1,1); + +SELECT CONCAT_WS(' ', trackname, artistname) trackname, artistname + FROM t1 LEFT JOIN t3 ON t1.trackid=t3.trackid + LEFT JOIN t2 ON t2.artistid=t3.artistid + WHERE CONCAT_WS(' ', trackname, artistname) LIKE '%In%'; + +DROP TABLE t1,t2,t3; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 6f6af415086..b01d75b8e02 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -95,6 +95,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "concat_ws"; } + table_map not_null_tables() const { return 0; } }; class Item_func_reverse :public Item_str_func From 3378673653108ee89e8011e1d18cd394aea13039 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 15:31:43 +0200 Subject: [PATCH 15/20] Moved connections first in test, to reduce risk of connecting before servers are fully connected --- mysql-test/t/ndb_alter_table.test | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test index 9cc1426554f..d6a1ef5e25f 100644 --- a/mysql-test/t/ndb_alter_table.test +++ b/mysql-test/t/ndb_alter_table.test @@ -7,6 +7,13 @@ DROP TABLE IF EXISTS t1; drop database if exists mysqltest; --enable_warnings +connect (con1,localhost,root,,test); +connect (con2,localhost,root,,test); + +connection con2; +-- sleep 2 +connection con1; + # # Basic test to show that the ALTER TABLE # is working @@ -88,10 +95,6 @@ CREATE TABLE t1 ( INSERT INTO t1 VALUES (9410,9412); -connect (con1,localhost,,,test); -connect (con2,localhost,,,test); - -connection con1; ALTER TABLE t1 ADD COLUMN c int not null; select * from t1 order by a; From 5a13f2a8a61e97453e69d2eeef14e95cf46c327b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 16:13:22 +0300 Subject: [PATCH 16/20] Fixed Bug#11226 and reverted fix for Bug#6993. Using 8 bytes for data pointer does not work at least on all computers. The result may become 0 or negative number. (mysqld, myisamchk) myisam/mi_create.c: Fixed Bug#11226, "Dynamic table >4GB issue". mysql-test/r/variables.result: Restricted myisam_data_pointer_size back to 7. mysql-test/t/variables.test: Restricted myisam_data_pointer_size back to 7. sql/mysqld.cc: Restricted myisam_data_pointer_size back to 7. --- myisam/mi_create.c | 7 +++---- mysql-test/r/variables.result | 4 ++-- mysql-test/t/variables.test | 6 +++++- sql/mysqld.cc | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/myisam/mi_create.c b/myisam/mi_create.c index d363f3d5b67..db614935321 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -194,11 +194,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD)); min_pack_length+=packed; - if (!ci->data_file_length) + if (!ci->data_file_length && ci->max_rows) { - if (ci->max_rows == 0 || pack_reclength == INT_MAX32) - ci->data_file_length= INT_MAX32-1; /* Should be enough */ - else if ((~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength) + if (pack_reclength == INT_MAX32 || + (~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength) ci->data_file_length= ~(ulonglong) 0; else ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 602750d5033..e370202cc9f 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -482,10 +482,10 @@ t1 CREATE TABLE `t1` ( `c3` longtext ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; -SET GLOBAL MYISAM_DATA_POINTER_SIZE= 8; +SET GLOBAL MYISAM_DATA_POINTER_SIZE= 7; SHOW VARIABLES LIKE 'MYISAM_DATA_POINTER_SIZE'; Variable_name Value -myisam_data_pointer_size 8 +myisam_data_pointer_size 7 SET GLOBAL table_cache=-1; SHOW VARIABLES LIKE 'table_cache'; Variable_name Value diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index e45218a9ed7..b8a12323cf9 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -363,9 +363,13 @@ drop table t1; # # Bug #6993: myisam_data_pointer_size +# Wrong bug report, data pointer size must be restricted to 7, +# setting to 8 will not work on all computers, myisamchk and +# the server may see a wrong value, such as 0 or negative number +# if 8 bytes is set. # -SET GLOBAL MYISAM_DATA_POINTER_SIZE= 8; +SET GLOBAL MYISAM_DATA_POINTER_SIZE= 7; SHOW VARIABLES LIKE 'MYISAM_DATA_POINTER_SIZE'; # diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 99c96a69ceb..a757c47366d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5153,7 +5153,7 @@ The minimum value for this variable is 4096.", "Default pointer size to be used for MyISAM tables.", (gptr*) &myisam_data_pointer_size, (gptr*) &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG, - 4, 2, 8, 0, 1, 0}, + 4, 2, 7, 0, 1, 0}, {"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, "Used to help MySQL to decide when to use the slow but safe key cache index create method.", (gptr*) &global_system_variables.myisam_max_extra_sort_file_size, From 0ff72e6019d8f9deec9159db87cf7947142539b3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 17:55:47 +0300 Subject: [PATCH 17/20] Don't allow 8bytes for data file pointers for now. --- myisam/mi_create.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/myisam/mi_create.c b/myisam/mi_create.c index db614935321..890ee61fd7f 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -723,10 +723,13 @@ err: uint mi_get_pointer_length(ulonglong file_length, uint def) { + DBUG_ASSERT(def >= 2 && def <= 7); if (file_length) /* If not default */ { +#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS if (file_length >= (longlong) 1 << 56) def=8; +#endif if (file_length >= (longlong) 1 << 48) def=7; if (file_length >= (longlong) 1 << 40) From df7852f20d25f9f298a3a65133cb192d4f08983e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 09:40:05 +0300 Subject: [PATCH 18/20] Optimization during review Add extra check to delete [] to ensure we are not deleting not allocated data sql/sql_select.cc: Optimization Add extra check to delete [] to ensure we are not deleting not allocated data --- sql/sql_select.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 044dc60e4b6..fcc10ae466a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8222,12 +8222,10 @@ cp_buffer_from_ref(THD *thd, TABLE_REF *ref) thd->count_cuted_fields= CHECK_FIELD_IGNORE; for (store_key **copy=ref->key_copy ; *copy ; copy++) { - int res; - if ((res= (*copy)->copy())) + if ((*copy)->copy() & 1) { thd->count_cuted_fields= save_count_cuted_fields; - if ((res= res & 1)) - return res; // Something went wrong + return 1; // Something went wrong } } thd->count_cuted_fields= save_count_cuted_fields; @@ -8818,7 +8816,8 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, DBUG_RETURN(0); err: - delete [] param->copy_field; // This is never 0 + if (copy) + delete [] param->copy_field; param->copy_field=0; err2: DBUG_RETURN(TRUE); From 534ab53c17a0b3656a81cb6fbbc69b3d56fcf8c4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 20:13:07 +0300 Subject: [PATCH 19/20] fixed create_distinct_group() to make references via ref_pointer_array --- sql/sql_select.cc | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 044dc60e4b6..ba14c880b65 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -134,8 +134,8 @@ static void read_cached_record(JOIN_TAB *tab); static bool cmp_buffer_with_ref(JOIN_TAB *tab); static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List &fields, List &all_fields,ORDER *new_order); -static ORDER *create_distinct_group(THD *thd, ORDER *order, - List &fields, +static ORDER *create_distinct_group(THD *thd, Item **ref_pointer_array, + ORDER *order, List &fields, bool *all_order_by_fields_used); static bool test_if_subpart(ORDER *a,ORDER *b); static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables); @@ -642,7 +642,8 @@ JOIN::optimize() bool all_order_fields_used; if (order) skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1); - if ((group_list=create_distinct_group(thd, order, fields_list, + if ((group_list=create_distinct_group(thd, select_lex->ref_pointer_array, + order, fields_list, &all_order_fields_used))) { bool skip_group= (skip_sort_order && @@ -8440,12 +8441,14 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List &fields, */ static ORDER * -create_distinct_group(THD *thd, ORDER *order_list, List &fields, +create_distinct_group(THD *thd, Item **ref_pointer_array, + ORDER *order_list, List &fields, bool *all_order_by_fields_used) { List_iterator li(fields); Item *item; ORDER *order,*group,**prev; + uint index= 0; *all_order_by_fields_used= 1; while ((item=li++)) @@ -8477,11 +8480,17 @@ create_distinct_group(THD *thd, ORDER *order_list, List &fields, ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER)); if (!ord) return 0; - ord->item=li.ref(); + /* + We have here only field_list (not all_field_list), so we can use + simple indexing of ref_pointer_array (order in the array and in the + list are same) + */ + ord->item= ref_pointer_array + index; ord->asc=1; *prev=ord; prev= &ord->next; } + index++; } *prev=0; return group; From 2fec2ba4c910d3db4059b8ffc77169021a39e04a Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 2 Jul 2005 02:00:56 +0200 Subject: [PATCH 20/20] configure.in: Enable build with CXX=gcc and gcc version 4 configure.in: Enable build with CXX=gcc and gcc version 4 --- configure.in | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index b291200c114..5af41d29c21 100644 --- a/configure.in +++ b/configure.in @@ -370,9 +370,14 @@ then if echo $CXX | grep gcc > /dev/null 2>&1 then - if $CXX -v 2>&1 | grep 'version 3' > /dev/null 2>&1 + AC_MSG_CHECKING([if CXX is gcc 3 or 4]) + if $CXX -v 2>&1 | grep 'version [[34]]' > /dev/null 2>&1 then + AC_MSG_RESULT([yes]) + AC_MSG_NOTICE([using MySQL tricks to avoid linking C++ code with C++ libraries]) CXXFLAGS="$CXXFLAGS -DUSE_MYSYS_NEW -DDEFINE_CXA_PURE_VIRTUAL" + else + AC_MSG_RESULT([no]) fi fi fi