From d2810c56cf3e23553038e52d99d89624fff79e96 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Jul 2005 21:25:05 +0300 Subject: [PATCH 01/20] Fixed compiler warnings client/mysqldump.c: Fixed wrong argument to printf() client/mysqltest.c: Fixed compiler warning myisam/ft_boolean_search.c: Fixed compiler warning myisammrg/myrg_static.c: Fixed compiler warning mysql-test/r/rpl_drop_temp.result: Drop used database mysql-test/t/rpl_drop_temp.test: Drop used database ndb/src/common/logger/LogHandler.cpp: Fixed compiler warning sql/field.cc: Fixed compiler warning sql/ha_ndbcluster.cc: Fixed compiler warning sql/sql_base.cc: Fixed compiler warning tests/mysql_client_test.c: Fixed compiler warning --- client/mysqldump.c | 2 +- client/mysqltest.c | 1 + myisam/ft_boolean_search.c | 1 + myisammrg/myrg_static.c | 2 +- mysql-test/r/rpl_drop_temp.result | 1 + mysql-test/t/rpl_drop_temp.test | 2 ++ ndb/src/common/logger/LogHandler.cpp | 2 +- sql/field.cc | 2 +- sql/ha_ndbcluster.cc | 1 + sql/sql_base.cc | 1 + tests/mysql_client_test.c | 5 +++-- 11 files changed, 14 insertions(+), 6 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index d29667052ee..69f323fd8ec 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2370,7 +2370,7 @@ static int do_show_master_status(MYSQL *mysql_con) { /* SHOW MASTER STATUS reports nothing and --force is not enabled */ my_printf_error(0, "Error: Binlogging on server not active", - MYF(0), mysql_error(mysql_con)); + MYF(0)); mysql_free_result(master); return 1; } diff --git a/client/mysqltest.c b/client/mysqltest.c index b23b77e9bca..29ccbc3e1b8 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2654,6 +2654,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) if (!disable_result_log) { ulong affected_rows; /* Ok to be undef if 'disable_info' is set */ + LINT_INIT(affected_rows); if (res) { diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index 8045ddd4657..f1ff8f6d886 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -210,6 +210,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) MI_INFO *info=ftb->info; uint off, extra=HA_FT_WLEN+info->s->base.rec_reflength; byte *lastkey_buf=ftbw->word+ftbw->off; + LINT_INIT(off); if (ftbw->flags & FTB_FLAG_TRUNC) lastkey_buf+=ftbw->len; diff --git a/myisammrg/myrg_static.c b/myisammrg/myrg_static.c index b21b834ac24..9e76cbae07b 100644 --- a/myisammrg/myrg_static.c +++ b/myisammrg/myrg_static.c @@ -27,4 +27,4 @@ LIST *myrg_open_list=0; static const char *merge_insert_methods[] = { "FIRST", "LAST", NullS }; TYPELIB merge_insert_method= { array_elements(merge_insert_methods)-1,"", - merge_insert_methods}; + merge_insert_methods, 0}; diff --git a/mysql-test/r/rpl_drop_temp.result b/mysql-test/r/rpl_drop_temp.result index e00309cac8f..04fe094ea26 100644 --- a/mysql-test/r/rpl_drop_temp.result +++ b/mysql-test/r/rpl_drop_temp.result @@ -10,3 +10,4 @@ create temporary table mysqltest.t2 (n int); show status like 'Slave_open_temp_tables'; Variable_name Value Slave_open_temp_tables 0 +drop database mysqltest; diff --git a/mysql-test/t/rpl_drop_temp.test b/mysql-test/t/rpl_drop_temp.test index e1c06ef4473..18fc17ed064 100644 --- a/mysql-test/t/rpl_drop_temp.test +++ b/mysql-test/t/rpl_drop_temp.test @@ -11,5 +11,7 @@ disconnect master; connection slave; --real_sleep 3; # time for DROP to be written show status like 'Slave_open_temp_tables'; +connection default; +drop database mysqltest; # End of 4.1 tests diff --git a/ndb/src/common/logger/LogHandler.cpp b/ndb/src/common/logger/LogHandler.cpp index a9d4512112f..521bd346fd3 100644 --- a/ndb/src/common/logger/LogHandler.cpp +++ b/ndb/src/common/logger/LogHandler.cpp @@ -58,7 +58,7 @@ LogHandler::append(const char* pCategory, Logger::LoggerLevel level, } else // repeated message { - if (now < m_last_log_time+m_max_repeat_frequency) + if (now < (time_t) (m_last_log_time+m_max_repeat_frequency)) { m_count_repeated_messages++; m_now= now; diff --git a/sql/field.cc b/sql/field.cc index 39a99830b14..6d2f92e27ea 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5003,7 +5003,7 @@ int Field_str::store(double nr) double anr= fabs(nr); int neg= (nr < 0.0) ? 1 : 0; if (char_length > 4 && char_length < 32 && - (anr < 1.0 ? anr > 1/(log_10[max(0,char_length-neg-2)]) /* -2 for "0." */ + (anr < 1.0 ? anr > 1/(log_10[max(0,(int) char_length-neg-2)]) /* -2 for "0." */ : anr < log_10[char_length-neg]-1)) use_scientific_notation= FALSE; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index e14d4b13311..6a8fde36e30 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2413,6 +2413,7 @@ void ha_ndbcluster::print_results() break; } case NdbDictionary::Column::Undefined: + default: fprintf(DBUG_FILE, "Unknown type: %d", col->getType()); break; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ed09af5e070..1cedc89ef97 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2186,6 +2186,7 @@ find_item_in_list(Item *find, List &items, uint *counter, bool found_unaliased_non_uniq= 0; uint unaliased_counter; + LINT_INIT(unaliased_counter); *unaliased= FALSE; if (find->type() == Item::FIELD_ITEM || find->type() == Item::REF_ITEM) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 139595a5471..37d6d951f96 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -6805,6 +6805,7 @@ static void test_set_option() bug #89 (reported by mark@mysql.com) */ +#ifndef EMBEDDED_LIBRARY static void test_prepare_grant() { int rc; @@ -6896,7 +6897,7 @@ static void test_prepare_grant() } } - +#endif /* EMBEDDED_LIBRARY */ /* Test a crash when invalid/corrupted .frm is used in the @@ -11566,7 +11567,7 @@ static void test_bug8330() const char *stmt_text; MYSQL_STMT *stmt[2]; int i, rc; - char *query= "select a,b from t1 where a=?"; + const char *query= "select a,b from t1 where a=?"; MYSQL_BIND bind[2]; long lval[2]; From 16c45930897a3221fbf11acbad9403a267e9501b Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 31 Jul 2005 21:28:52 -0700 Subject: [PATCH 02/20] BUG 11104 (same as changeset 1.1891 on the 5.0 tree, but realised this needed to be fixed in earlier versions) Fixed the iteration of how substrings are handled with negative indexes in SUBSTRING_INDEX mysql-test/r/func_str.result: New results for the fix to substring_index mysql-test/t/func_str.test: Added tests for fix to substring_index, various lenth search patterns. Also included are the queuries the user who reported the bug listed in the bug report sql/item_strfunc.cc: Fix to BUG 11104 Took out the offset-=delimiter_length-1 out of the for loop. It was causing basically this: select substring_index('the king of the the hill', 'the', -2) to not work. The first iteration, offset would be initialised to 24, then strstr would point at 'the king of the the* hill' ('*'means right before the character following), returning a offset of 16. The for loop would then decrement offset by two (3 - 1), to 14, now pointing at "the king of th*e the hill", _skipping_ past the 'e' in the second to last 'the', and therefore strstr would never have a chance of matching the second to last 'the', then moving on to the 'the' at the begginning of the string! In a nutshell, offset was being decremented by too great a value, preventing the second to last 'the' from being ever found, hence the result of 'king of the the hill' from the query that is reported in the bug report --- mysql-test/r/func_str.result | 117 +++++++++++++++++++++++++++++++++++ mysql-test/t/func_str.test | 39 ++++++++++++ sql/item_strfunc.cc | 16 ++++- 3 files changed, 170 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 6fe71f97edd..6fefbb16353 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -38,6 +38,123 @@ www. .se select substring_index('.tcx.se','.',-2),substring_index('.tcx.se','.tcx',-1); substring_index('.tcx.se','.',-2) substring_index('.tcx.se','.tcx',-1) tcx.se .se +select substring_index('aaaaaaaaa1','a',1); +substring_index('aaaaaaaaa1','a',1) + +select substring_index('aaaaaaaaa1','aa',1); +substring_index('aaaaaaaaa1','aa',1) + +select substring_index('aaaaaaaaa1','aa',2); +substring_index('aaaaaaaaa1','aa',2) +aa +select substring_index('aaaaaaaaa1','aa',3); +substring_index('aaaaaaaaa1','aa',3) +aaaa +select substring_index('aaaaaaaaa1','aa',4); +substring_index('aaaaaaaaa1','aa',4) +aaaaaa +select substring_index('aaaaaaaaa1','aa',5); +substring_index('aaaaaaaaa1','aa',5) +aaaaaaaaa1 +select substring_index('aaaaaaaaa1','aaa',1); +substring_index('aaaaaaaaa1','aaa',1) + +select substring_index('aaaaaaaaa1','aaa',2); +substring_index('aaaaaaaaa1','aaa',2) +aaa +select substring_index('aaaaaaaaa1','aaa',3); +substring_index('aaaaaaaaa1','aaa',3) +aaaaaa +select substring_index('aaaaaaaaa1','aaa',4); +substring_index('aaaaaaaaa1','aaa',4) +aaaaaaaaa1 +select substring_index('aaaaaaaaa1','aaaa',1); +substring_index('aaaaaaaaa1','aaaa',1) + +select substring_index('aaaaaaaaa1','aaaa',2); +substring_index('aaaaaaaaa1','aaaa',2) +aaaa +select substring_index('aaaaaaaaa1','1',1); +substring_index('aaaaaaaaa1','1',1) +aaaaaaaaa +select substring_index('aaaaaaaaa1','a',-1); +substring_index('aaaaaaaaa1','a',-1) +1 +select substring_index('aaaaaaaaa1','aa',-1); +substring_index('aaaaaaaaa1','aa',-1) +1 +select substring_index('aaaaaaaaa1','aa',-2); +substring_index('aaaaaaaaa1','aa',-2) +aa1 +select substring_index('aaaaaaaaa1','aa',-3); +substring_index('aaaaaaaaa1','aa',-3) +aaaa1 +select substring_index('aaaaaaaaa1','aa',-4); +substring_index('aaaaaaaaa1','aa',-4) +aaaaaa1 +select substring_index('aaaaaaaaa1','aa',-5); +substring_index('aaaaaaaaa1','aa',-5) +aaaaaaaaa1 +select substring_index('aaaaaaaaa1','aaa',-1); +substring_index('aaaaaaaaa1','aaa',-1) +1 +select substring_index('aaaaaaaaa1','aaa',-2); +substring_index('aaaaaaaaa1','aaa',-2) +aaa1 +select substring_index('aaaaaaaaa1','aaa',-3); +substring_index('aaaaaaaaa1','aaa',-3) +aaaaaa1 +select substring_index('aaaaaaaaa1','aaa',-4); +substring_index('aaaaaaaaa1','aaa',-4) + +select substring_index('the king of thethe hill','the',-2); +substring_index('the king of thethe hill','the',-2) +the hill +select substring_index('the king of the the hill','the',-2); +substring_index('the king of the the hill','the',-2) + the hill +select substring_index('the king of the the hill','the',-2); +substring_index('the king of the the hill','the',-2) + the hill +select substring_index('the king of the the hill',' the ',-1); +substring_index('the king of the the hill',' the ',-1) +hill +select substring_index('the king of the the hill',' the ',-2); +substring_index('the king of the the hill',' the ',-2) + the hill +select substring_index('the king of the the hill',' ',-1); +substring_index('the king of the the hill',' ',-1) +hill +select substring_index('the king of the the hill',' ',-2); +substring_index('the king of the the hill',' ',-2) +the hill +select substring_index('the king of the the hill',' ',-3); +substring_index('the king of the the hill',' ',-3) + the hill +select substring_index('the king of the the hill',' ',-4); +substring_index('the king of the the hill',' ',-4) +the the hill +select substring_index('the king of the the hill',' ',-5); +substring_index('the king of the the hill',' ',-5) +of the the hill +select substring_index('the king of the.the hill','the',-2); +substring_index('the king of the.the hill','the',-2) +.the hill +select substring_index('the king of thethethe.the hill','the',-3); +substring_index('the king of thethethe.the hill','the',-3) +the.the hill +select substring_index('the king of thethethe.the hill','the',-1); +substring_index('the king of thethethe.the hill','the',-1) + hill +select substring_index('the king of the the hill','the',1); +substring_index('the king of the the hill','the',1) + +select substring_index('the king of the the hill','the',2); +substring_index('the king of the the hill','the',2) +the king of +select substring_index('the king of the the hill','the',3); +substring_index('the king of the the hill','the',3) +the king of the select concat(':',ltrim(' left '),':',rtrim(' right '),':'); concat(':',ltrim(' left '),':',rtrim(' right '),':') :left : right: diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 9dac1d823d9..81d5daaf0ba 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -19,6 +19,45 @@ select concat('',left(right(concat('what ',concat('is ','happening')),9),4),'',s select substring_index('www.tcx.se','.',-2),substring_index('www.tcx.se','.',1); select substring_index('www.tcx.se','tcx',1),substring_index('www.tcx.se','tcx',-1); select substring_index('.tcx.se','.',-2),substring_index('.tcx.se','.tcx',-1); +select substring_index('aaaaaaaaa1','a',1); +select substring_index('aaaaaaaaa1','aa',1); +select substring_index('aaaaaaaaa1','aa',2); +select substring_index('aaaaaaaaa1','aa',3); +select substring_index('aaaaaaaaa1','aa',4); +select substring_index('aaaaaaaaa1','aa',5); +select substring_index('aaaaaaaaa1','aaa',1); +select substring_index('aaaaaaaaa1','aaa',2); +select substring_index('aaaaaaaaa1','aaa',3); +select substring_index('aaaaaaaaa1','aaa',4); +select substring_index('aaaaaaaaa1','aaaa',1); +select substring_index('aaaaaaaaa1','aaaa',2); +select substring_index('aaaaaaaaa1','1',1); +select substring_index('aaaaaaaaa1','a',-1); +select substring_index('aaaaaaaaa1','aa',-1); +select substring_index('aaaaaaaaa1','aa',-2); +select substring_index('aaaaaaaaa1','aa',-3); +select substring_index('aaaaaaaaa1','aa',-4); +select substring_index('aaaaaaaaa1','aa',-5); +select substring_index('aaaaaaaaa1','aaa',-1); +select substring_index('aaaaaaaaa1','aaa',-2); +select substring_index('aaaaaaaaa1','aaa',-3); +select substring_index('aaaaaaaaa1','aaa',-4); +select substring_index('the king of thethe hill','the',-2); +select substring_index('the king of the the hill','the',-2); +select substring_index('the king of the the hill','the',-2); +select substring_index('the king of the the hill',' the ',-1); +select substring_index('the king of the the hill',' the ',-2); +select substring_index('the king of the the hill',' ',-1); +select substring_index('the king of the the hill',' ',-2); +select substring_index('the king of the the hill',' ',-3); +select substring_index('the king of the the hill',' ',-4); +select substring_index('the king of the the hill',' ',-5); +select substring_index('the king of the.the hill','the',-2); +select substring_index('the king of thethethe.the hill','the',-3); +select substring_index('the king of thethethe.the hill','the',-1); +select substring_index('the king of the the hill','the',1); +select substring_index('the king of the the hill','the',2); +select substring_index('the king of the the hill','the',3); select concat(':',ltrim(' left '),':',rtrim(' right '),':'); select concat(':',trim(LEADING FROM ' left'),':',trim(TRAILING FROM ' right '),':'); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 930014de771..f070382e5c1 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1084,11 +1084,23 @@ String *Item_func_substr_index::val_str(String *str) } } else - { // Start counting at end - for (offset=res->length() ; ; offset-=delimeter_length-1) + { + /* + Negative index, start counting at the end + */ + for (offset=res->length(); offset ;) { + /* + this call will result in finding the position pointing to one + address space less than where the found substring is located + in res + */ if ((int) (offset=res->strrstr(*delimeter,offset)) < 0) return res; // Didn't find, return org string + /* + At this point, we've searched for the substring + the number of times as supplied by the index value + */ if (!++count) { offset+=delimeter_length; From fdb4d307ab8c7639ced6e08c61528bfe81823fae Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 7 Aug 2005 03:16:15 +0100 Subject: [PATCH 03/20] Bug#10109 "INSERT .. SELECT ... ON DUPLICATE KEY UPDATE fails" Ensure that check_insert_fields() is only called once when doing an INSERT..SELECT mysql-test/r/insert_update.result: Test for bug 10109 mysql-test/t/insert_update.test: Test for bug 10109 sql/sql_class.h: select_insert needs more state sql/sql_insert.cc: ensure that check_insert_fields() is only called once when doing an INSERT...SELECT sql/sql_parse.cc: more args for select_insert constructor --- mysql-test/r/insert_update.result | 6 ++++++ mysql-test/t/insert_update.test | 14 ++++++++++++ sql/sql_class.h | 14 +++++++++--- sql/sql_insert.cc | 36 +++++++++++++++++++++---------- sql/sql_parse.cc | 3 ++- 5 files changed, 58 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index 150f4ef26c7..9e674cc4aae 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -191,3 +191,9 @@ 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; +CREATE TABLE t1 ( +a BIGINT(20) NOT NULL DEFAULT 0, +PRIMARY KEY (a) +) ENGINE=MyISAM; +INSERT INTO t1 ( a ) SELECT 0 ON DUPLICATE KEY UPDATE a = a + VALUES (a) ; +DROP TABLE t1; diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test index d0e75f0fa2a..8038bd7bfe7 100644 --- a/mysql-test/t/insert_update.test +++ b/mysql-test/t/insert_update.test @@ -101,4 +101,18 @@ insert into t1 select a from t1 on duplicate key update a=a+1 ; insert ignore into t1 select a from t1 on duplicate key update a=t1.a+1 ; drop table t1; +# +# Bug#10109 - INSERT .. SELECT ... ON DUPLICATE KEY UPDATE fails +# Bogus "Duplicate columns" error message +# + +CREATE TABLE t1 ( + a BIGINT(20) NOT NULL DEFAULT 0, + PRIMARY KEY (a) +) ENGINE=MyISAM; + +INSERT INTO t1 ( a ) SELECT 0 ON DUPLICATE KEY UPDATE a = a + VALUES (a) ; + +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/sql_class.h b/sql/sql_class.h index b6bf0dcdc45..bc651b32d94 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1236,19 +1236,27 @@ class select_insert :public select_result_interceptor { List *fields; ulonglong last_insert_id; COPY_INFO info; + TABLE_LIST *insert_table_list; + TABLE_LIST *dup_table_list; select_insert(TABLE *table_par, List *fields_par, enum_duplicates duplic, bool ignore) - :table(table_par), fields(fields_par), last_insert_id(0) + :table(table_par), fields(fields_par), last_insert_id(0), + insert_table_list(0), dup_table_list(0) { bzero((char*) &info,sizeof(info)); info.ignore= ignore; info.handle_duplicates=duplic; } - select_insert(TABLE *table_par, List *fields_par, + select_insert(TABLE *table_par, + TABLE_LIST *insert_table_list_par, + TABLE_LIST *dup_table_list_par, + List *fields_par, List *update_fields, List *update_values, enum_duplicates duplic, bool ignore) - :table(table_par), fields(fields_par), last_insert_id(0) + :table(table_par), fields(fields_par), last_insert_id(0), + insert_table_list(insert_table_list_par), + dup_table_list(dup_table_list_par) { bzero((char*) &info,sizeof(info)); info.ignore= ignore; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 7d613ad6fbf..8c6fed26f8e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -543,18 +543,22 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, if (!table->insert_values) DBUG_RETURN(-1); } - if ((values && check_insert_fields(thd, table, fields, *values)) || - setup_tables(insert_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, dup_table_list, update_values, 1, 0, 0)))) + if (setup_tables(insert_table_list)) DBUG_RETURN(-1); - if (values && find_real_table_in_list(table_list->next, table_list->db, - table_list->real_name)) + if (values) { - my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name); - DBUG_RETURN(-1); + if (check_insert_fields(thd, table, fields, *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, dup_table_list, update_values, 1, 0, 0)))) + DBUG_RETURN(-1); + if (find_real_table_in_list(table_list->next, table_list->db, + table_list->real_name)) + { + my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name); + DBUG_RETURN(-1); + } } if (duplic == DUP_UPDATE || duplic == DUP_REPLACE) table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY); @@ -1601,6 +1605,7 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) int res; LEX *lex= thd->lex; SELECT_LEX *lex_current_select_save= lex->current_select; + bool lex_select_no_error= lex->select_lex.no_error; DBUG_ENTER("select_insert::prepare"); unit= u; @@ -1608,10 +1613,19 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) Since table in which we are going to insert is added to the first select, LEX::current_select should point to the first select while we are fixing fields from insert list. + Since these checks may cause the query to fail, we don't want the + error messages to be converted into warnings, must force no_error=0 */ lex->current_select= &lex->select_lex; - res= check_insert_fields(thd, table, *fields, values); + lex->select_lex.no_error= 0; + res= + check_insert_fields(thd, table, *fields, values) || + setup_fields(thd, 0, insert_table_list, values, 0, 0, 0) || + (info.handle_duplicates == DUP_UPDATE && + (check_update_fields(thd, table, insert_table_list, *info.update_fields) || + setup_fields(thd, 0, dup_table_list, *info.update_values, 1, 0, 0))); lex->current_select= lex_current_select_save; + lex->select_lex.no_error= lex_select_no_error; if (res) DBUG_RETURN(1); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c32cbff0f5e..9fb431df318 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2877,7 +2877,8 @@ unsent_create_error: lex->field_list, 0, lex->update_list, lex->value_list, lex->duplicates)) && - (result= new select_insert(insert_table, &lex->field_list, + (result= new select_insert(insert_table, first_local_table, + &dup_tables, &lex->field_list, &lex->update_list, &lex->value_list, lex->duplicates, lex->ignore))) { From 38b4ccf5d338bfd146e78bfdb3c4500fb6eeae69 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Aug 2005 13:18:18 +0300 Subject: [PATCH 04/20] Fix for BUG #11642: [Patch]es x86 Assembler and text relocations Changed assembler functions to not access global variables or variables in text segement Added wrapper function in C to longlong2str() to pass _dig_vec_upper as an argument mysql-test/r/bigint.result: More tests for parsing of bigint's More tests for different values to conv() mysql-test/t/bigint.test: More tests for parsing of bigint's More tests for different values to conv() strings/Makefile.am: Added longlong2str_asm.c strings/longlong2str-x86.s: Changed functions to not access variables in text segment Fixed this by adding global variable '_dig_vec_upper' as an argument to longlong2str_with_dig_vector() strings/my_strtoll10-x86.s: Removd array lfactor by calculating the value in code (this is to to make the code position independent) strings/longlong2str_asm.c: New BitKeeper file ``strings/longlong2str_asm.c'' --- mysql-test/r/bigint.result | 9 ++++++ mysql-test/t/bigint.test | 3 ++ strings/Makefile.am | 4 +-- strings/longlong2str-x86.s | 35 ++++++++++----------- strings/longlong2str_asm.c | 33 ++++++++++++++++++++ strings/my_strtoll10-x86.s | 62 ++++++++++++++++++++++++-------------- 6 files changed, 104 insertions(+), 42 deletions(-) create mode 100644 strings/longlong2str_asm.c diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result index eb3d0da3f23..e9a457c9dfa 100644 --- a/mysql-test/r/bigint.result +++ b/mysql-test/r/bigint.result @@ -17,6 +17,15 @@ select 9223372036854775808+1; select -(0-3),round(-(0-3)), round(9999999999999999999); -(0-3) round(-(0-3)) round(9999999999999999999) 3 3 10000000000000000000 +select 1,11,101,1001,10001,100001,1000001,10000001,100000001,1000000001,10000000001,100000000001,1000000000001,10000000000001,100000000000001,1000000000000001,10000000000000001,100000000000000001,1000000000000000001,10000000000000000001; +1 11 101 1001 10001 100001 1000001 10000001 100000001 1000000001 10000000001 100000000001 1000000000001 10000000000001 100000000000001 1000000000000001 10000000000000001 100000000000000001 1000000000000000001 10000000000000000001 +1 11 101 1001 10001 100001 1000001 10000001 100000001 1000000001 10000000001 100000000001 1000000000001 10000000000001 100000000000001 1000000000000001 10000000000000001 100000000000000001 1000000000000000001 10000000000000000001 +select -1,-11,-101,-1001,-10001,-100001,-1000001,-10000001,-100000001,-1000000001,-10000000001,-100000000001,-1000000000001,-10000000000001,-100000000000001,-1000000000000001,-10000000000000001,-100000000000000001,-1000000000000000001,-10000000000000000001; +-1 -11 -101 -1001 -10001 -100001 -1000001 -10000001 -100000001 -1000000001 -10000000001 -100000000001 -1000000000001 -10000000000001 -100000000000001 -1000000000000001 -10000000000000001 -100000000000000001 -1000000000000000001 -10000000000000000001 +-1 -11 -101 -1001 -10001 -100001 -1000001 -10000001 -100000001 -1000000001 -10000000001 -100000000001 -1000000000001 -10000000000001 -100000000000001 -1000000000000001 -10000000000000001 -100000000000000001 -1000000000000000001 -10000000000000000000 +select conv(1,10,16),conv((1<<2)-1,10,16),conv((1<<10)-2,10,16),conv((1<<16)-3,10,16),conv((1<<25)-4,10,16),conv((1<<31)-5,10,16),conv((1<<36)-6,10,16),conv((1<<47)-7,10,16),conv((1<<48)-8,10,16),conv((1<<55)-9,10,16),conv((1<<56)-10,10,16),conv((1<<63)-11,10,16); +conv(1,10,16) conv((1<<2)-1,10,16) conv((1<<10)-2,10,16) conv((1<<16)-3,10,16) conv((1<<25)-4,10,16) conv((1<<31)-5,10,16) conv((1<<36)-6,10,16) conv((1<<47)-7,10,16) conv((1<<48)-8,10,16) conv((1<<55)-9,10,16) conv((1<<56)-10,10,16) conv((1<<63)-11,10,16) +1 3 3FE FFFD 1FFFFFC 7FFFFFFB FFFFFFFFA 7FFFFFFFFFF9 FFFFFFFFFFF8 7FFFFFFFFFFFF7 FFFFFFFFFFFFF6 7FFFFFFFFFFFFFF5 create table t1 (a bigint unsigned not null, primary key(a)); insert into t1 values (18446744073709551615), (0xFFFFFFFFFFFFFFFE), (18446744073709551613), (18446744073709551612); select * from t1; diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test index 741c7ec360b..8a238d33e08 100644 --- a/mysql-test/t/bigint.test +++ b/mysql-test/t/bigint.test @@ -14,6 +14,9 @@ select +9999999999999999999,-9999999999999999999; select cast(9223372036854775808 as unsigned)+1; select 9223372036854775808+1; select -(0-3),round(-(0-3)), round(9999999999999999999); +select 1,11,101,1001,10001,100001,1000001,10000001,100000001,1000000001,10000000001,100000000001,1000000000001,10000000000001,100000000000001,1000000000000001,10000000000000001,100000000000000001,1000000000000000001,10000000000000000001; +select -1,-11,-101,-1001,-10001,-100001,-1000001,-10000001,-100000001,-1000000001,-10000000001,-100000000001,-1000000000001,-10000000000001,-100000000000001,-1000000000000001,-10000000000000001,-100000000000000001,-1000000000000000001,-10000000000000000001; +select conv(1,10,16),conv((1<<2)-1,10,16),conv((1<<10)-2,10,16),conv((1<<16)-3,10,16),conv((1<<25)-4,10,16),conv((1<<31)-5,10,16),conv((1<<36)-6,10,16),conv((1<<47)-7,10,16),conv((1<<48)-8,10,16),conv((1<<55)-9,10,16),conv((1<<56)-10,10,16),conv((1<<63)-11,10,16); # # In 3.23 we have to disable the test of column to bigint as diff --git a/strings/Makefile.am b/strings/Makefile.am index 3f954f3c6a0..97b35075277 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -23,7 +23,7 @@ pkglib_LIBRARIES = libmystrings.a # Exact one of ASSEMBLER_X if ASSEMBLER_x86 ASRCS = strings-x86.s longlong2str-x86.s my_strtoll10-x86.s -CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c +CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c longlong2str_asm.c else if ASSEMBLER_sparc32 # These file MUST all be on the same line!! Otherwise automake @@ -46,7 +46,7 @@ EXTRA_DIST = ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-win1 ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-utf8.c \ ctype-ucs2.c ctype-uca.c ctype-tis620.c ctype-ujis.c \ xml.c strto.c strings-x86.s \ - longlong2str.c longlong2str-x86.s \ + longlong2str.c longlong2str-x86.s longlong2str_asm.c \ my_strtoll10.c my_strtoll10-x86.s \ strxmov.c bmove_upp.c strappend.c strcont.c strend.c \ strfill.c strcend.c is_prefix.c strstr.c strinstr.c \ diff --git a/strings/longlong2str-x86.s b/strings/longlong2str-x86.s index fcc57810224..1840bab3f47 100644 --- a/strings/longlong2str-x86.s +++ b/strings/longlong2str-x86.s @@ -16,26 +16,26 @@ # Optimized longlong2str function for Intel 80x86 (gcc/gas syntax) # Some set sequences are optimized for pentuimpro II - .file "longlong2str.s" - .version "1.01" + .file "longlong2str-x86.s" + .version "1.02" .text .align 4 -.globl longlong2str - .type longlong2str,@function +.globl longlong2str_with_dig_vector + .type longlong2str_with_dig_vector,@function -longlong2str: +longlong2str_with_dig_vector: subl $80,%esp pushl %ebp pushl %esi pushl %edi pushl %ebx movl 100(%esp),%esi # Lower part of val - movl 104(%esp),%ebp # Higher part of val - movl 108(%esp),%edi # get dst movl 112(%esp),%ebx # Radix + movl 104(%esp),%ebp # Higher part of val movl %ebx,%eax + movl 108(%esp),%edi # get dst testl %eax,%eax jge .L144 @@ -69,6 +69,8 @@ longlong2str: .L150: leal 92(%esp),%ecx # End of buffer + movl %edi, 108(%esp) # Store possible modified dest + movl 116(%esp), %edi # dig_vec_upper jmp .L155 .align 4 @@ -83,7 +85,7 @@ longlong2str: divl %ebx decl %ecx movl %eax,%esi # quotent in ebp:esi - movb _dig_vec_upper(%edx),%al # al is faster than dl + movb (%edx,%edi),%al # al is faster than dl movb %al,(%ecx) # store value in buff .align 4 .L155: @@ -91,20 +93,22 @@ longlong2str: ja .L153 testl %esi,%esi # rest value jl .L153 - je .L10_mov # Ready + je .L160 # Ready movl %esi,%eax - movl $_dig_vec_upper,%ebp .align 4 .L154: # Do rest with integer precision cltd divl %ebx decl %ecx - movb (%edx,%ebp),%dl # bh is always zero as ebx=radix < 36 + movb (%edx,%edi),%dl # bh is always zero as ebx=radix < 36 testl %eax,%eax movb %dl,(%ecx) jne .L154 +.L160: + movl 108(%esp),%edi # get dst + .L10_mov: movl %ecx,%esi leal 92(%esp),%ecx # End of buffer @@ -129,7 +133,7 @@ longlong2str: jmp .L165 .Lfe3: - .size longlong2str,.Lfe3-longlong2str + .size longlong2str_with_dig_vector,.Lfe3-longlong2str_with_dig_vector # # This is almost equal to the above, except that we can do the final @@ -137,9 +141,6 @@ longlong2str: # .align 4 -.Ltmp: - .long 0xcccccccd - .align 4 .globl longlong10_to_str .type longlong10_to_str,@function @@ -202,8 +203,8 @@ longlong10_to_str: # The following code uses some tricks to change division by 10 to # multiplication and shifts - movl .Ltmp,%esi # set %esi to 0xcccccccd - + movl $0xcccccccd,%esi + .L10_40: movl %ebx,%eax mull %esi diff --git a/strings/longlong2str_asm.c b/strings/longlong2str_asm.c new file mode 100644 index 00000000000..e38a8328b91 --- /dev/null +++ b/strings/longlong2str_asm.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2000 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Wrapper for longlong2str.s + + We need this because the assembler code can't access the local variable + _dig_vector in a portable manner. +*/ + +#include +#include "m_string.h" + +extern char *longlong2str_with_dig_vector(longlong val,char *dst,int radix, + const char *dig_vector); + +char *longlong2str(longlong val,char *dst,int radix) +{ + return longlong2str_with_dig_vector(val, dst, radix, _dig_vec_upper); +} diff --git a/strings/my_strtoll10-x86.s b/strings/my_strtoll10-x86.s index c04384667a7..1d8b8f2bbce 100644 --- a/strings/my_strtoll10-x86.s +++ b/strings/my_strtoll10-x86.s @@ -17,21 +17,8 @@ # For documentation, check my_strtoll.c .file "my_strtoll10-x86.s" - .version "01.01" -.data - .align 32 - .type lfactor,@object - .size lfactor,36 -lfactor: - .long 1 - .long 10 - .long 100 - .long 1000 - .long 10000 - .long 100000 - .long 1000000 - .long 10000000 - .long 100000000 + .version "01.02" + .text .align 4 @@ -209,14 +196,16 @@ my_strtoll10: jne .L500 cmpl -36(%ebp),%esi # Test if string is less than 18 digits jne .Lend_i_and_j - jmp .Lend3 # 18 digit string +.L499: + movl $1000000000,%eax + jmp .Lgot_factor # 18 digit string # Handle the possible next to last digit and store in ecx .L500: movb (%esi),%al addb $-48,%al cmpb $9,%al - ja .Lend3 + ja .L499 # 18 digit string incl %esi movzbl %al,%ecx @@ -315,14 +304,41 @@ my_strtoll10: .Lend_i_and_j: movl %esi,%ecx subl -12(%ebp),%ecx # ecx= number of digits in second part - movl lfactor(,%ecx,4),%eax - jmp .L523 - # Return -8(%ebp) * $1000000000 + edi + # Calculate %eax= 10 ** %cl, where %cl <= 8 + # With an array one could do this with: + # movl 10_factor_table(,%ecx,4),%eax + # We calculate the table here to avoid problems in + # position independent code (gcc -pic) + + cmpb $3,%cl + ja .L4_to_8 + movl $1000, %eax + je .Lgot_factor # %cl=3, eax= 1000 + movl $10, %eax + cmpb $1,%cl # %cl is here 0 - 2 + je .Lgot_factor # %cl=1, eax= 10 + movl $100, %eax + ja .Lgot_factor # %cl=2, eax=100 + movl $1, %eax + jmp .Lgot_factor # %cl=0, eax=1 + +.L4_to_8: # %cl is here 4-8 + cmpb $5,%cl + movl $100000, %eax + je .Lgot_factor # %cl=5, eax=100000 + movl $10000, %eax + jbe .Lgot_factor # %cl=4, eax=10000 + movl $10000000, %eax + cmpb $7,%cl + je .Lgot_factor # %cl=7, eax=10000000 + movl $100000000, %eax + ja .Lgot_factor # %cl=8, eax=100000000 + movl $1000000, %eax # %cl=6, eax=1000000 + + # Return -8(%ebp) * %eax + edi .p2align 4,,7 -.Lend3: - movl $1000000000,%eax -.L523: +.Lgot_factor: mull -8(%ebp) addl %edi,%eax adcl $0,%edx From 4112dc21765162ae3dfd356eedf480720eb32904 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Aug 2005 19:52:30 +0500 Subject: [PATCH 05/20] Bug#5439 : mysql_server_init() crashes if ShiftJIS path is passed (important for Adobe). mf_pack.c, mf_dirname.c, charset.c, my_sys.h: - adding fs_character_set() function on Windows - ignoring fake slashes which are just multibyte parts in several functions in /mysys Verified by Shu to work on WinXP and Win2k. Test is not possible, or very hard to do. include/my_sys.h: Bug#5439 : mysql_server_init() crashes if ShiftJIS path is passed (important for Adobe) - adding fs_character_set() function on Windows - ignoring fake slashes which are just multibyte parts in several functions in /mysys mysys/charset.c: d mysys/mf_dirname.c: d mysys/mf_pack.c: d --- include/my_sys.h | 5 +++++ mysys/charset.c | 26 ++++++++++++++++++++++++++ mysys/mf_dirname.c | 33 ++++++++++++++++++++++++++++++++- mysys/mf_pack.c | 12 ++++++++++++ 4 files changed, 75 insertions(+), 1 deletion(-) diff --git a/include/my_sys.h b/include/my_sys.h index e56f07a8140..8752aa30772 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -788,6 +788,11 @@ extern my_bool init_compiled_charsets(myf flags); extern void add_compiled_collation(CHARSET_INFO *cs); extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to, const char *from, ulong length); +#ifdef __WIN__ +#define BACKSLASH_MBTAIL +/* File system character set */ +extern CHARSET_INFO *fs_character_set(void); +#endif #ifdef __WIN__ extern my_bool have_tcpip; /* Is set if tcpip is used */ diff --git a/mysys/charset.c b/mysys/charset.c index cabdbad3413..3a39fce9437 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -637,3 +637,29 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to, *to= 0; return (ulong) (to - to_start); } + + +#ifdef BACKSLASH_MBTAIL +static CHARSET_INFO *fs_cset_cache= NULL; + +CHARSET_INFO *fs_character_set() +{ + if (!fs_cset_cache) + { + char buf[10]= "cp"; + GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE, + buf+2, sizeof(buf)-3); + /* + We cannot call get_charset_by_name here + because fs_character_set() is executed before + LOCK_THD_charset mutex initialization, which + is used inside get_charset_by_name. + As we're now interested in cp932 only, + let's just detect it using strcmp(). + */ + fs_cset_cache= !strcmp(buf, "cp932") ? + &my_charset_cp932_japanese_ci : &my_charset_bin; + } + return fs_cset_cache; +} +#endif diff --git a/mysys/mf_dirname.c b/mysys/mf_dirname.c index 3de82c05b87..45bf4d56c31 100644 --- a/mysys/mf_dirname.c +++ b/mysys/mf_dirname.c @@ -22,6 +22,9 @@ uint dirname_length(const char *name) { register my_string pos,gpos; +#ifdef BASKSLASH_MBTAIL + CHARSET_INFO *fs= fs_character_set(); +#endif #ifdef FN_DEVCHAR if ((pos=(char*)strrchr(name,FN_DEVCHAR)) == 0) #endif @@ -29,12 +32,22 @@ uint dirname_length(const char *name) gpos= pos++; for ( ; *pos ; pos++) /* Find last FN_LIBCHAR */ + { +#ifdef BASKSLASH_MBTAIL + uint l; + if (use_mb(fs) && (l= my_ismbchar(fs, pos, pos + 3))) + { + pos+= l - 1; + continue; + } +#endif if (*pos == FN_LIBCHAR || *pos == '/' #ifdef FN_C_AFTER_DIR || *pos == FN_C_AFTER_DIR || *pos == FN_C_AFTER_DIR_2 #endif ) gpos=pos; + } return ((uint) (uint) (gpos+1-(char*) name)); } @@ -85,6 +98,9 @@ uint dirname_part(my_string to, const char *name) char *convert_dirname(char *to, const char *from, const char *from_end) { char *to_org=to; +#ifdef BACKSLASH_MBTAIL + CHARSET_INFO *fs= fs_character_set(); +#endif /* We use -2 here, becasue we need place for the last FN_LIBCHAR */ if (!from_end || (from_end - from) > FN_REFLEN-2) @@ -103,7 +119,22 @@ char *convert_dirname(char *to, const char *from, const char *from_end) *to++= FN_C_AFTER_DIR; #endif else - *to++= *from; + { +#ifdef BACKSLASH_MBTAIL + uint l; + if (use_mb(fs) && (l= my_ismbchar(fs, from, from + 3))) + { + memmove(to, from, l); + to+= l; + from+= l - 1; + to_org= to; /* Don't look inside mbchar */ + } + else +#endif + { + *to++= *from; + } + } } *to=0; } diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index 86172f648f4..049aa59a578 100644 --- a/mysys/mf_pack.c +++ b/mysys/mf_pack.c @@ -124,6 +124,9 @@ uint cleanup_dirname(register my_string to, const char *from) reg4 my_string start; char parent[5], /* for "FN_PARENTDIR" */ buff[FN_REFLEN+1],*end_parentdir; +#ifdef BACKSLASH_MBTAIL + CHARSET_INFO *fs= fs_character_set(); +#endif DBUG_ENTER("cleanup_dirname"); DBUG_PRINT("enter",("from: '%s'",from)); @@ -141,6 +144,15 @@ uint cleanup_dirname(register my_string to, const char *from) length=(uint) (strmov(parent+1,FN_PARENTDIR)-parent); for (pos=start ; (*pos= *from_ptr++) != 0 ; pos++) { +#ifdef BACKSLASH_MBTAIL + uint l; + if (use_mb(fs) && (l= my_ismbchar(fs, from_ptr - 1, from_ptr + 2))) + { + for (l-- ; l ; *++pos= *from_ptr++, l--); + start= pos + 1; /* Don't look inside multi-byte char */ + continue; + } +#endif if (*pos == '/') *pos = FN_LIBCHAR; if (*pos == FN_LIBCHAR) From 10805ec23465bd3bc38744da89f855331db96251 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Aug 2005 13:46:13 -0700 Subject: [PATCH 06/20] item_strfunc.cc: BUG #11104 Took out the offset-=delimiter_length-1 out of the for loop. It was causing basically this: select substring_index('the king of the the hill', 'the', -2) to not work. The first iteration, offset would be initialised to 24, then strstr would point at 'the king of the the* hill' ('*'means right before the character following), returning a offset of 16. The for loop would then decrement offset by two (3 - 1), to 14, now pointing at "the king of th*e the hill", _skipping_ past the 'e' in the second to last 'the', and therefore strstr would never have a chance of matching the second to last 'the', then moving on to the 'the' at the begginning of the string! In a nutshell, offset was being decremented by too great a value, preventing the second to last 'the' from being ever found, hence the result of 'king of the the hill' from the query that is reported in the bug report func_str.test: BUG #11104 Added tests to make sure fix addresses issues in original bug report func_str.result: BUG #11104 New results for new tests mysql-test/r/func_str.result: BUG #11104 New results for new tests mysql-test/t/func_str.test: BUG #11104 Added tests to make sure fix addresses issues in original bug report sql/item_strfunc.cc: BUG #11104 Took out the offset-=delimiter_length-1 out of the for loop. It was causing basically this: select substring_index('the king of the the hill', 'the', -2) to not work. The first iteration, offset would be initialised to 24, then strstr would point at 'the king of the the* hill' ('*'means right before the character following), returning a offset of 16. The for loop would then decrement offset by two (3 - 1), to 14, now pointing at "the king of th*e the hill", _skipping_ past the 'e' in the second to last 'the', and therefore strstr would never have a chance of matching the second to last 'the', then moving on to the 'the' at the begginning of the string! In a nutshell, offset was being decremented by too great a value, preventing the second to last 'the' from being ever found, hence the result of 'king of the the hill' from the query that is reported in the bug report --- mysql-test/r/func_str.result | 117 +++++++++++++++++++++++++++++++++++ mysql-test/t/func_str.test | 39 ++++++++++++ sql/item_strfunc.cc | 16 ++++- 3 files changed, 170 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 4c3a03b8066..ae6578795f6 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -45,6 +45,123 @@ www. .se select substring_index('.tcx.se','.',-2),substring_index('.tcx.se','.tcx',-1); substring_index('.tcx.se','.',-2) substring_index('.tcx.se','.tcx',-1) tcx.se .se +select substring_index('aaaaaaaaa1','a',1); +substring_index('aaaaaaaaa1','a',1) + +select substring_index('aaaaaaaaa1','aa',1); +substring_index('aaaaaaaaa1','aa',1) + +select substring_index('aaaaaaaaa1','aa',2); +substring_index('aaaaaaaaa1','aa',2) +aa +select substring_index('aaaaaaaaa1','aa',3); +substring_index('aaaaaaaaa1','aa',3) +aaaa +select substring_index('aaaaaaaaa1','aa',4); +substring_index('aaaaaaaaa1','aa',4) +aaaaaa +select substring_index('aaaaaaaaa1','aa',5); +substring_index('aaaaaaaaa1','aa',5) +aaaaaaaaa1 +select substring_index('aaaaaaaaa1','aaa',1); +substring_index('aaaaaaaaa1','aaa',1) + +select substring_index('aaaaaaaaa1','aaa',2); +substring_index('aaaaaaaaa1','aaa',2) +aaa +select substring_index('aaaaaaaaa1','aaa',3); +substring_index('aaaaaaaaa1','aaa',3) +aaaaaa +select substring_index('aaaaaaaaa1','aaa',4); +substring_index('aaaaaaaaa1','aaa',4) +aaaaaaaaa1 +select substring_index('aaaaaaaaa1','aaaa',1); +substring_index('aaaaaaaaa1','aaaa',1) + +select substring_index('aaaaaaaaa1','aaaa',2); +substring_index('aaaaaaaaa1','aaaa',2) +aaaa +select substring_index('aaaaaaaaa1','1',1); +substring_index('aaaaaaaaa1','1',1) +aaaaaaaaa +select substring_index('aaaaaaaaa1','a',-1); +substring_index('aaaaaaaaa1','a',-1) +1 +select substring_index('aaaaaaaaa1','aa',-1); +substring_index('aaaaaaaaa1','aa',-1) +1 +select substring_index('aaaaaaaaa1','aa',-2); +substring_index('aaaaaaaaa1','aa',-2) +aa1 +select substring_index('aaaaaaaaa1','aa',-3); +substring_index('aaaaaaaaa1','aa',-3) +aaaa1 +select substring_index('aaaaaaaaa1','aa',-4); +substring_index('aaaaaaaaa1','aa',-4) +aaaaaa1 +select substring_index('aaaaaaaaa1','aa',-5); +substring_index('aaaaaaaaa1','aa',-5) +aaaaaaaaa1 +select substring_index('aaaaaaaaa1','aaa',-1); +substring_index('aaaaaaaaa1','aaa',-1) +1 +select substring_index('aaaaaaaaa1','aaa',-2); +substring_index('aaaaaaaaa1','aaa',-2) +aaa1 +select substring_index('aaaaaaaaa1','aaa',-3); +substring_index('aaaaaaaaa1','aaa',-3) +aaaaaa1 +select substring_index('aaaaaaaaa1','aaa',-4); +substring_index('aaaaaaaaa1','aaa',-4) + +select substring_index('the king of thethe hill','the',-2); +substring_index('the king of thethe hill','the',-2) +the hill +select substring_index('the king of the the hill','the',-2); +substring_index('the king of the the hill','the',-2) + the hill +select substring_index('the king of the the hill','the',-2); +substring_index('the king of the the hill','the',-2) + the hill +select substring_index('the king of the the hill',' the ',-1); +substring_index('the king of the the hill',' the ',-1) +hill +select substring_index('the king of the the hill',' the ',-2); +substring_index('the king of the the hill',' the ',-2) + the hill +select substring_index('the king of the the hill',' ',-1); +substring_index('the king of the the hill',' ',-1) +hill +select substring_index('the king of the the hill',' ',-2); +substring_index('the king of the the hill',' ',-2) +the hill +select substring_index('the king of the the hill',' ',-3); +substring_index('the king of the the hill',' ',-3) + the hill +select substring_index('the king of the the hill',' ',-4); +substring_index('the king of the the hill',' ',-4) +the the hill +select substring_index('the king of the the hill',' ',-5); +substring_index('the king of the the hill',' ',-5) +of the the hill +select substring_index('the king of the.the hill','the',-2); +substring_index('the king of the.the hill','the',-2) +.the hill +select substring_index('the king of thethethe.the hill','the',-3); +substring_index('the king of thethethe.the hill','the',-3) +the.the hill +select substring_index('the king of thethethe.the hill','the',-1); +substring_index('the king of thethethe.the hill','the',-1) + hill +select substring_index('the king of the the hill','the',1); +substring_index('the king of the the hill','the',1) + +select substring_index('the king of the the hill','the',2); +substring_index('the king of the the hill','the',2) +the king of +select substring_index('the king of the the hill','the',3); +substring_index('the king of the the hill','the',3) +the king of the select concat(':',ltrim(' left '),':',rtrim(' right '),':'); concat(':',ltrim(' left '),':',rtrim(' right '),':') :left : right: diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index ddfc83e620a..8afbe673ce3 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -23,6 +23,45 @@ select concat('',left(right(concat('what ',concat('is ','happening')),9),4),'',s select substring_index('www.tcx.se','.',-2),substring_index('www.tcx.se','.',1); select substring_index('www.tcx.se','tcx',1),substring_index('www.tcx.se','tcx',-1); select substring_index('.tcx.se','.',-2),substring_index('.tcx.se','.tcx',-1); +select substring_index('aaaaaaaaa1','a',1); +select substring_index('aaaaaaaaa1','aa',1); +select substring_index('aaaaaaaaa1','aa',2); +select substring_index('aaaaaaaaa1','aa',3); +select substring_index('aaaaaaaaa1','aa',4); +select substring_index('aaaaaaaaa1','aa',5); +select substring_index('aaaaaaaaa1','aaa',1); +select substring_index('aaaaaaaaa1','aaa',2); +select substring_index('aaaaaaaaa1','aaa',3); +select substring_index('aaaaaaaaa1','aaa',4); +select substring_index('aaaaaaaaa1','aaaa',1); +select substring_index('aaaaaaaaa1','aaaa',2); +select substring_index('aaaaaaaaa1','1',1); +select substring_index('aaaaaaaaa1','a',-1); +select substring_index('aaaaaaaaa1','aa',-1); +select substring_index('aaaaaaaaa1','aa',-2); +select substring_index('aaaaaaaaa1','aa',-3); +select substring_index('aaaaaaaaa1','aa',-4); +select substring_index('aaaaaaaaa1','aa',-5); +select substring_index('aaaaaaaaa1','aaa',-1); +select substring_index('aaaaaaaaa1','aaa',-2); +select substring_index('aaaaaaaaa1','aaa',-3); +select substring_index('aaaaaaaaa1','aaa',-4); +select substring_index('the king of thethe hill','the',-2); +select substring_index('the king of the the hill','the',-2); +select substring_index('the king of the the hill','the',-2); +select substring_index('the king of the the hill',' the ',-1); +select substring_index('the king of the the hill',' the ',-2); +select substring_index('the king of the the hill',' ',-1); +select substring_index('the king of the the hill',' ',-2); +select substring_index('the king of the the hill',' ',-3); +select substring_index('the king of the the hill',' ',-4); +select substring_index('the king of the the hill',' ',-5); +select substring_index('the king of the.the hill','the',-2); +select substring_index('the king of thethethe.the hill','the',-3); +select substring_index('the king of thethethe.the hill','the',-1); +select substring_index('the king of the the hill','the',1); +select substring_index('the king of the the hill','the',2); +select substring_index('the king of the the hill','the',3); select concat(':',ltrim(' left '),':',rtrim(' right '),':'); select concat(':',trim(LEADING FROM ' left'),':',trim(TRAILING FROM ' right '),':'); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index d316c7eaf72..52a2dedb67c 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -42,7 +42,7 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) { my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), - c1.collation->name,c1.derivation_name(), + c1.collation->name,c1.derivation_name(), c2.collation->name,c2.derivation_name(), fname); } @@ -1188,10 +1188,22 @@ String *Item_func_substr_index::val_str(String *str) } else { // Start counting at end - for (offset=res->length() ; ; offset-=delimeter_length-1) + /* + Negative index, start counting at the end + */ + for (offset=res->length(); offset ;) { + /* + this call will result in finding the position pointing to one + address space less than where the found substring is located + in res + */ if ((int) (offset=res->strrstr(*delimeter,offset)) < 0) return res; // Didn't find, return org string + /* + At this point, we've searched for the substring + the number of times as supplied by the index value + */ if (!++count) { offset+=delimeter_length; From b10670142c8f503b40f18aae736ac6bc53c75e4b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Aug 2005 13:50:10 -0700 Subject: [PATCH 07/20] BUG #12119 Removed unnecessary error message from mysql.cc (client program) client/mysql.cc: BUG #12119 The error message "Didn't find any fields in table ..." would be printed out when a table was created and dropped in rapid succession via a perl script. The client would get a list of tables, meanwhile, the one table would be deleted, and then this error message printed when the table was not found, which it should just quietly not print the fields. Removing the error message fixes this issue. --- client/mysql.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 5454c76e720..63173aab20d 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1563,11 +1563,8 @@ You can turn off this feature to get a quicker startup with -A\n\n"); mysql_free_result(fields); } else - { - tee_fprintf(stdout, - "Didn't find any fields in table '%s'\n",table_row[0]); field_names[i]= 0; - } + i++; } mysql_free_result(tables); From 97988099eb39c580b391c51cdaf7ff33c9f20a64 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 9 Aug 2005 00:13:49 +0300 Subject: [PATCH 08/20] Review of new pushed code - Fixed some error condtion when handling dates with 'T' - Added extra test for bug #11867 (Wrong result with "... WHERE ROW( a, b ) IN ( SELECT DISTINCT a, b WHERE ...)" to show it's not yet fixed - Safety fixes and cleanups mysql-test/r/subselect.result: Added extra test case to test case for bug #11867 (Result shows that current code is not yet right and needs to be fixed) mysql-test/r/type_datetime.result: More tests for dates of type CCYYMMDDTHHMMSS mysql-test/t/subselect.test: Added extra test case to test case for bug #11867 mysql-test/t/type_datetime.test: More tests for dates of type CCYYMMDDTHHMMSS sql-common/my_time.c: Fixed handling of dates of type CCYYMMDDTHHMMSS (Old code couldn't handle 2003-0304 or 2003-0003-02) sql/slave.cc: Indentation cleanup sql/sql_parse.cc: Added test of return value of get_system_var() sql/sql_select.cc: Removed unnecessary call to field->table->maybe_null sql/sql_union.cc: Indentation fixes --- mysql-test/r/subselect.result | 15 +++++++++++++++ mysql-test/r/type_datetime.result | 23 +++++++++++++---------- mysql-test/t/subselect.test | 4 ++++ mysql-test/t/type_datetime.test | 21 +++++++++++---------- sql-common/my_time.c | 6 ++++-- sql/slave.cc | 4 ++-- sql/sql_parse.cc | 12 ++++++++---- sql/sql_select.cc | 6 ++---- sql/sql_union.cc | 6 ++++-- 9 files changed, 63 insertions(+), 34 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 25d9a39705d..863a250c670 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2741,4 +2741,19 @@ WHERE ROW(one,two) IN (SELECT DISTINCT one,two FROM t1 WHERE flag = 'N'); one two flag 5 6 N 7 8 N +insert into t2 values (null,null,'N'); +SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N') as 'test' from t1; +one two test +1 2 0 +2 3 0 +3 4 0 +5 6 1 +7 8 1 +SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N' group by one,two) as 'test' from t1; +one two test +1 2 NULL +2 3 NULL +3 4 NULL +5 6 1 +7 8 1 DROP TABLE t1,t2; diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index 8d28504d790..f313a6b934b 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -26,6 +26,8 @@ Table Op Msg_type Msg_text test.t1 check status OK delete from t1; insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959"),("20030100000000"),("20030000000000"); +insert into t1 values ("2003-003-03"); +insert into t1 values ("20030102T131415"),("2001-01-01T01:01:01"), ("2001-1-1T1:01:01"); select * from t1; t 2000-01-01 00:00:00 @@ -43,6 +45,17 @@ t 9999-12-31 23:59:59 2003-01-00 00:00:00 2003-00-00 00:00:00 +2003-03-03 00:00:00 +2003-01-02 13:14:15 +2001-01-01 01:01:01 +2001-01-01 01:01:01 +truncate table t1; +insert into t1 values("2003-0303 12:13:14"); +Warnings: +Warning 1264 Data truncated; out of range for column 't' at row 1 +select * from t1; +t +0000-00-00 00:00:00 drop table t1; CREATE TABLE t1 (a timestamp, b date, c time, d datetime); insert into t1 (b,c,d) values(now(),curtime(),now()); @@ -153,13 +166,3 @@ dt 0000-00-00 00:00:00 0000-00-00 00:00:00 drop table t1; -create table t1 (dt datetime); -insert into t1 values ("20010101T010101"); -insert into t1 values ("2001-01-01T01:01:01"); -insert into t1 values ("2001-1-1T1:01:01"); -select * from t1; -dt -2001-01-01 01:01:01 -2001-01-01 01:01:01 -2001-01-01 01:01:01 -drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 0b4791b0023..ecd553ee8f8 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1768,6 +1768,10 @@ SELECT * FROM t1 SELECT * FROM t1 WHERE ROW(one,two) IN (SELECT DISTINCT one,two FROM t1 WHERE flag = 'N'); +insert into t2 values (null,null,'N'); +SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N') as 'test' from t1; +SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N' group by one,two) as 'test' from t1; + DROP TABLE t1,t2; # End of 4.1 tests diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index ca70e35d3cd..4b6741b4242 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -14,6 +14,17 @@ optimize table t1; check table t1; delete from t1; insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959"),("20030100000000"),("20030000000000"); + +# Strange dates +insert into t1 values ("2003-003-03"); + +# Bug #7308: ISO-8601 date format not handled correctly +insert into t1 values ("20030102T131415"),("2001-01-01T01:01:01"), ("2001-1-1T1:01:01"); +select * from t1; + +# Test some wrong dates +truncate table t1; +insert into t1 values("2003-0303 12:13:14"); select * from t1; drop table t1; @@ -102,14 +113,4 @@ insert into t1 values ("00-00-00"), ("00-00-00 00:00:00"); select * from t1; drop table t1; -# -# Bug #7308: ISO-8601 date format not handled correctly -# -create table t1 (dt datetime); -insert into t1 values ("20010101T010101"); -insert into t1 values ("2001-01-01T01:01:01"); -insert into t1 values ("2001-1-1T1:01:01"); -select * from t1; -drop table t1; - # End of 4.1 tests diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 1726a9a6e78..40d7799e274 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -137,7 +137,9 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, If length= 8 or >= 14 then year is of format YYYY. (YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS) */ - for (pos=str; pos != end && my_isdigit(&my_charset_latin1,*pos) ; pos++) + for (pos=str; + pos != end && (my_isdigit(&my_charset_latin1,*pos) || *pos == 'T'); + pos++) ; digits= (uint) (pos-str); @@ -203,7 +205,7 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, const char *start= str; ulong tmp_value= (uint) (uchar) (*str++ - '0'); while (str != end && my_isdigit(&my_charset_latin1,str[0]) && - --field_length) + (!is_internal_format || --field_length)) { tmp_value=tmp_value*10 + (ulong) (uchar) (*str - '0'); str++; diff --git a/sql/slave.cc b/sql/slave.cc index a0cc773d44f..9ff7a432b89 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2186,8 +2186,8 @@ int show_master_info(THD* thd, MASTER_INFO* mi) &my_charset_bin); protocol->store((ulonglong) mi->rli.group_relay_log_pos); protocol->store(mi->rli.group_master_log_name, &my_charset_bin); - protocol->store(mi->slave_running == MYSQL_SLAVE_RUN_CONNECT - ? "Yes":"No", &my_charset_bin); + protocol->store(mi->slave_running == MYSQL_SLAVE_RUN_CONNECT ? + "Yes" : "No", &my_charset_bin); protocol->store(mi->rli.slave_running ? "Yes":"No", &my_charset_bin); protocol->store(&replicate_do_db); protocol->store(&replicate_ignore_db); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 135cef43e90..869e8e5063f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4211,10 +4211,12 @@ void create_select_for_variable(const char *var_name) We set the name of Item to @@session.var_name because that then is used as the column name in the output. */ - var= get_system_var(thd, OPT_SESSION, tmp, null_lex_string); - end= strxmov(buff, "@@session.", var_name, NullS); - var->set_name(buff, end-buff, system_charset_info); - add_item_to_list(thd, var); + if ((var= get_system_var(thd, OPT_SESSION, tmp, null_lex_string))) + { + end= strxmov(buff, "@@session.", var_name, NullS); + var->set_name(buff, end-buff, system_charset_info); + add_item_to_list(thd, var); + } DBUG_VOID_RETURN; } @@ -5038,11 +5040,13 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, THR_LOCK_DATA **end_p= lock_p + thd->locked_tables->lock_count; for (; lock_p < end_p; lock_p++) + { if ((*lock_p)->type == TL_WRITE) { my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); return 1; } + } } /* Writing to the binlog could cause deadlocks, as we don't log diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 54afe5bb7a6..353ccf79ab8 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2260,11 +2260,9 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond, We use null_rejecting in add_not_null_conds() to add 'othertbl.field IS NOT NULL' to tab->select_cond. */ - (*key_fields)->null_rejecting= (cond->functype() == Item_func::EQ_FUNC) && + (*key_fields)->null_rejecting= ((cond->functype() == Item_func::EQ_FUNC) && ((*value)->type() == Item::FIELD_ITEM) && - - (((Item_field*)*value)->field->maybe_null() || - ((Item_field *)*value)->field->table->maybe_null); + ((Item_field*)*value)->field->maybe_null()); (*key_fields)++; } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index c33444fd73e..8bb53f7b573 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -285,6 +285,8 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, List_iterator_fast tp(types); Item_arena *arena= thd->current_arena; Item *type; + ulong create_options; + while ((type= tp++)) { if (type->result_type() == STRING_RESULT && @@ -295,8 +297,8 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } } - ulong create_options= first_select_in_union()->options | thd_arg->options | - TMP_TABLE_ALL_COLUMNS; + create_options= (first_select_in_union()->options | thd_arg->options | + TMP_TABLE_ALL_COLUMNS); /* Force the temporary table to be a MyISAM table if we're going to use fullext functions (MATCH ... AGAINST .. IN BOOLEAN MODE) when reading From 502e97f875d448bcf0c0be4b2cd2c83733150427 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Aug 2005 23:23:34 +0000 Subject: [PATCH 09/20] Fix for BUG#12228: SP cache code: * Cleanup SP Cache code, now SP Cache only deletes sp_head objects in sp_cache_flush_obsolete() invalidates all pointers to routines in the cache. * Use new SP Cache use contract in the code. There is no test case because it doesn't seem to be possible to cause thread races to end the same way they end in heavy-load test. This patch removes the crash in heavy test. mysql-test/r/type_bit.result: Drop the tables this test tries to create mysql-test/r/view.result: Drop function this test creates mysql-test/t/type_bit.test: Drop the tables this test tries to create mysql-test/t/view.test: Drop function this test creates sql/sp.cc: Fix for BUG#12228: When a routine is deleted/modified, invalidate all cached SPs in all threads. We need to do so because sp_lex_keeper::{prelocking_tables, query_tables_own_last} in one SP may depend on another SP sp_lex_keeper::m_lex is using. sql/sp_cache.cc: Fix for BUG#12228: * Move class sp_cache to here from sp_cache.h, document the functions. * sp_cache_insert, sp_cache_remove, sp_cache_invalidate and sp_cache_lookup must not delete sp_head* objects as they may be called during SP execution when sp_head objects are used. * Added sp_cache_flush_obsolete() function that may delete sp_head objects. * Removed sp_cache_remove as there is no need for it now - when we change one SP we should invalidate all other SPs, because sp_lex_keeper::{prelocking_tables, query_tables_own_last} from one SP depend on content of another SP (used in sp_lex_keeper::m_lex). sql/sp_cache.h: Fix for BUG#12228: * Move class sp_cache to sp_cache.cc it is not needed in .h file * Added comments sql/sql_parse.cc: Fix for BUG#12228: Call new sp_cache_flush_obsolete() function before running the query sql/sql_prepare.cc: Fix for BUG#12228: Call new sp_cache_flush_obsolete() function before preparing/executing a PS --- mysql-test/r/type_bit.result | 2 +- mysql-test/r/view.result | 2 + mysql-test/t/type_bit.test | 2 +- mysql-test/t/view.test | 4 + sql/sp.cc | 16 +-- sql/sp_cache.cc | 211 +++++++++++++++++++++++++---------- sql/sp_cache.h | 105 +++++------------ sql/sql_parse.cc | 3 +- sql/sql_prepare.cc | 5 + 9 files changed, 196 insertions(+), 154 deletions(-) diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result index 4aa8587d6e1..c22ceba70d8 100644 --- a/mysql-test/r/type_bit.result +++ b/mysql-test/r/type_bit.result @@ -34,7 +34,7 @@ select 0 + b'1111111111111111'; select 0 + b'1000000000000001'; 0 + b'1000000000000001' 32769 -drop table if exists t1; +drop table if exists t1,t2; create table t1 (a bit(65)); ERROR 42000: Column length too big for column 'a' (max = 64); use BLOB or TEXT instead create table t1 (a bit(0)); diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f6b5018cf3a..98020c7ec33 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1880,6 +1880,8 @@ test.v5 check error View 'test.v5' references invalid table(s) or column(s) or f test.v6 check status OK drop view v1, v2, v3, v4, v5, v6; drop table t2; +drop function if exists f1; +drop function if exists f2; CREATE TABLE t1 (col1 time); CREATE TABLE t2 (col1 time); CREATE TABLE t3 (col1 time); diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test index fd5eb49858c..a56b697ea6b 100644 --- a/mysql-test/t/type_bit.test +++ b/mysql-test/t/type_bit.test @@ -16,7 +16,7 @@ select 0 + b'1111111111111111'; select 0 + b'1000000000000001'; --disable_warnings -drop table if exists t1; +drop table if exists t1,t2; --enable_warnings --error 1074 diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 9885566442f..cba2d75fb7c 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1711,6 +1711,10 @@ CHECK TABLE v1, v2, v3, v4, v5, v6; drop view v1, v2, v3, v4, v5, v6; drop table t2; +--disable_warnings +drop function if exists f1; +drop function if exists f2; +--enable_warnings CREATE TABLE t1 (col1 time); CREATE TABLE t2 (col1 time); CREATE TABLE t3 (col1 time); diff --git a/sql/sp.cc b/sql/sp.cc index 297e17de689..e875c30ab1b 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -986,13 +986,11 @@ int sp_drop_procedure(THD *thd, sp_name *name) { int ret; - bool found; DBUG_ENTER("sp_drop_procedure"); DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str)); - found= sp_cache_remove(&thd->sp_proc_cache, name); ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name); - if (!found && !ret) + if (!ret) sp_cache_invalidate(); DBUG_RETURN(ret); } @@ -1002,13 +1000,11 @@ int sp_update_procedure(THD *thd, sp_name *name, st_sp_chistics *chistics) { int ret; - bool found; DBUG_ENTER("sp_update_procedure"); DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str)); - found= sp_cache_remove(&thd->sp_proc_cache, name); ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, chistics); - if (!found && !ret) + if (!ret) sp_cache_invalidate(); DBUG_RETURN(ret); } @@ -1099,13 +1095,11 @@ int sp_drop_function(THD *thd, sp_name *name) { int ret; - bool found; DBUG_ENTER("sp_drop_function"); DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str)); - found= sp_cache_remove(&thd->sp_func_cache, name); ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name); - if (!found && !ret) + if (!ret) sp_cache_invalidate(); DBUG_RETURN(ret); } @@ -1115,13 +1109,11 @@ int sp_update_function(THD *thd, sp_name *name, st_sp_chistics *chistics) { int ret; - bool found; DBUG_ENTER("sp_update_procedure"); DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str)); - found= sp_cache_remove(&thd->sp_func_cache, name); ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, chistics); - if (!found && !ret) + if (!ret) sp_cache_invalidate(); DBUG_RETURN(ret); } diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index c8f0ed6ba2d..135000d1443 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -24,17 +24,78 @@ static pthread_mutex_t Cversion_lock; static ulong Cversion = 0; -void -sp_cache_init() + +/* + Cache of stored routines. +*/ + +class sp_cache +{ +public: + ulong version; + + sp_cache(); + ~sp_cache(); + + inline void insert(sp_head *sp) + { + /* TODO: why don't we check return value? */ + my_hash_insert(&m_hashtable, (const byte *)sp); + } + + inline sp_head *lookup(char *name, uint namelen) + { + return (sp_head *)hash_search(&m_hashtable, (const byte *)name, namelen); + } + +#ifdef NOT_USED + inline bool remove(char *name, uint namelen) + { + sp_head *sp= lookup(name, namelen); + if (sp) + { + hash_delete(&m_hashtable, (byte *)sp); + return TRUE; + } + return FALSE; + } +#endif + + inline void remove_all() + { + cleanup(); + init(); + } + +private: + void init(); + void cleanup(); + + /* All routines in this cache */ + HASH m_hashtable; +}; // class sp_cache + + +/* Initialize the SP caching once at startup */ + +void sp_cache_init() { pthread_mutex_init(&Cversion_lock, MY_MUTEX_INIT_FAST); } -void -sp_cache_clear(sp_cache **cp) + +/* + Clear the cache *cp and set *cp to NULL. + SYNOPSIS + sp_cache_clear() + cp Pointer to cache to clear + NOTE + This function doesn't invalidate other caches. +*/ + +void sp_cache_clear(sp_cache **cp) { sp_cache *c= *cp; - if (c) { delete c; @@ -42,86 +103,119 @@ sp_cache_clear(sp_cache **cp) } } -void -sp_cache_insert(sp_cache **cp, sp_head *sp) + +/* + Insert a routine into the cache. + + SYNOPSIS + sp_cache_insert() + cp The cache to put routine into + sp Routine to insert. +*/ + +void sp_cache_insert(sp_cache **cp, sp_head *sp) { sp_cache *c= *cp; if (! c) - c= new sp_cache(); - if (c) { ulong v; - + c= new sp_cache(); pthread_mutex_lock(&Cversion_lock); // LOCK v= Cversion; pthread_mutex_unlock(&Cversion_lock); // UNLOCK - - if (c->version < v) - { - if (*cp) - c->remove_all(); - c->version= v; - } + c->version= v; + } + if (c) + { + DBUG_PRINT("info",("sp_cache: inserting: %*s", sp->m_qname.length, sp->m_qname.str)); c->insert(sp); if (*cp == NULL) *cp= c; } } -sp_head * -sp_cache_lookup(sp_cache **cp, sp_name *name) + +/* + Look up a routine in the cache. + SYNOPSIS + sp_cache_lookup() + cp Cache to look into + name Name of rutine to find + + NOTE + An obsolete (but not more obsolete then since last + sp_cache_flush_obsolete call) routine may be returned. + + RETURN + The routine or + NULL if the routine not found. +*/ + +sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name) { - ulong v; sp_cache *c= *cp; - - if (! c) + if (!c) return NULL; - - pthread_mutex_lock(&Cversion_lock); // LOCK - v= Cversion; - pthread_mutex_unlock(&Cversion_lock); // UNLOCK - - if (c->version < v) - { - c->remove_all(); - c->version= v; - return NULL; - } return c->lookup(name->m_qname.str, name->m_qname.length); } -bool -sp_cache_remove(sp_cache **cp, sp_name *name) -{ - sp_cache *c= *cp; - bool found= FALSE; - - if (c) - { - ulong v; - - pthread_mutex_lock(&Cversion_lock); // LOCK - v= Cversion++; - pthread_mutex_unlock(&Cversion_lock); // UNLOCK - - if (c->version < v) - c->remove_all(); - else - found= c->remove(name->m_qname.str, name->m_qname.length); - c->version= v+1; - } - return found; -} - -void -sp_cache_invalidate() + +/* + Invalidate all routines in all caches. + + SYNOPSIS + sp_cache_invalidate() + + NOTE + This is called when a VIEW definition is modifed. We can't destroy sp_head + objects here as one may modify VIEW definitions from prelocking-free SPs. +*/ + +void sp_cache_invalidate() { + DBUG_PRINT("info",("sp_cache: invalidating")); pthread_mutex_lock(&Cversion_lock); // LOCK Cversion++; pthread_mutex_unlock(&Cversion_lock); // UNLOCK } + +/* + Remove out-of-date SPs from the cache. + + SYNOPSIS + sp_cache_flush_obsolete() + cp Cache to flush + + NOTE + This invalidates pointers to sp_head objects this thread uses. + In practice that means 'dont call this function when inside SP'. +*/ + +void sp_cache_flush_obsolete(sp_cache **cp) +{ + sp_cache *c= *cp; + if (c) + { + ulong v; + pthread_mutex_lock(&Cversion_lock); // LOCK + v= Cversion; + pthread_mutex_unlock(&Cversion_lock); // UNLOCK + if (c->version < v) + { + DBUG_PRINT("info",("sp_cache: deleting all functions")); + /* We need to delete all elements. */ + c->remove_all(); + c->version= v; + } + } +} + +/************************************************************************* + Internal functions + *************************************************************************/ + static byte * hash_get_key_for_sp_head(const byte *ptr, uint *plen, my_bool first) @@ -136,7 +230,6 @@ static void hash_free_sp_head(void *p) { sp_head *sp= (sp_head *)p; - delete sp; } diff --git a/sql/sp_cache.h b/sql/sp_cache.h index 14b2db97f5f..402647db9ea 100644 --- a/sql/sp_cache.h +++ b/sql/sp_cache.h @@ -25,94 +25,39 @@ /* Stored procedures/functions cache. This is used as follows: * Each thread has its own cache. - * Each sp_head object is put into its thread cache before it is used, and + * Each sp_head object is put into its thread cache before it is used, and then remains in the cache until deleted. */ class sp_head; class sp_cache; -/* Initialize the SP caching once at startup */ -void sp_cache_init(); - -/* Clear the cache *cp and set *cp to NULL */ -void sp_cache_clear(sp_cache **cp); - -/* Insert an SP into cache. If 'cp' points to NULL, it's set to a new cache */ -void sp_cache_insert(sp_cache **cp, sp_head *sp); - -/* Lookup an SP in cache */ -sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name); - -/* - Remove an SP from cache, and also bump the Cversion number so all other - caches are invalidated. - Returns true if something was removed. -*/ -bool sp_cache_remove(sp_cache **cp, sp_name *name); - -/* Invalidate all existing SP caches by bumping Cversion number. */ -void sp_cache_invalidate(); - - /* - * - * The cache class. Don't use this directly, use the C API above - * - */ + Cache usage scenarios: + 1. Application-wide init: + sp_cache_init(); -class sp_cache -{ -public: + 2. SP execution in thread: + 2.1 While holding sp_head* pointers: + + // look up a routine in the cache (no checks if it is up to date or not) + sp_cache_lookup(); + + sp_cache_insert(); + sp_cache_invalidate(); + + 2.2 When not holding any sp_head* pointers (at query end): + sp_cache_flush_obsolete(); + + 3. Before thread exit: + sp_cache_clear(); +*/ - ulong version; - - sp_cache(); - - ~sp_cache(); - - void - init(); - - void - cleanup(); - - inline void - insert(sp_head *sp) - { - my_hash_insert(&m_hashtable, (const byte *)sp); - } - - inline sp_head * - lookup(char *name, uint namelen) - { - return (sp_head *)hash_search(&m_hashtable, (const byte *)name, namelen); - } - - inline bool - remove(char *name, uint namelen) - { - sp_head *sp= lookup(name, namelen); - - if (sp) - { - hash_delete(&m_hashtable, (byte *)sp); - return TRUE; - } - return FALSE; - } - - inline void - remove_all() - { - cleanup(); - init(); - } - -private: - - HASH m_hashtable; - -}; // class sp_cache +void sp_cache_init(); +void sp_cache_clear(sp_cache **cp); +void sp_cache_insert(sp_cache **cp, sp_head *sp); +sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name); +void sp_cache_invalidate(); +void sp_cache_flush_obsolete(sp_cache **cp); #endif /* _SP_CACHE_H_ */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 677b3a98174..00463dc0a3b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5347,7 +5347,8 @@ void mysql_init_multi_delete(LEX *lex) void mysql_parse(THD *thd, char *inBuf, uint length) { DBUG_ENTER("mysql_parse"); - + sp_cache_flush_obsolete(&thd->sp_proc_cache); + sp_cache_flush_obsolete(&thd->sp_func_cache); mysql_init_query(thd, (uchar*) inBuf, length); if (query_cache_send_result_to_client(thd, inBuf, length) <= 0) { diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 18707cc6c87..f8b19dac3d1 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -73,6 +73,7 @@ Long data handling: #include // for isspace() #include "sp_head.h" #include "sp.h" +#include "sp_cache.h" #ifdef EMBEDDED_LIBRARY /* include MYSQL_BIND headers */ #include @@ -1729,6 +1730,8 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, DBUG_ENTER("mysql_stmt_prepare"); DBUG_PRINT("prep_query", ("%s", packet)); + sp_cache_flush_obsolete(&thd->sp_proc_cache); + sp_cache_flush_obsolete(&thd->sp_func_cache); /* If this is an SQLCOM_PREPARE, we also increase Com_prepare_sql. @@ -1978,6 +1981,8 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) Prepared_statement *stmt; DBUG_ENTER("mysql_stmt_execute"); + sp_cache_flush_obsolete(&thd->sp_proc_cache); + sp_cache_flush_obsolete(&thd->sp_func_cache); packet+= 9; /* stmt_id + 5 bytes of flags */ statistic_increment(thd->status_var.com_stmt_execute, &LOCK_status); From 6f0a6260976712e6b9c828ebb120165540c14935 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Aug 2005 16:51:12 -0700 Subject: [PATCH 10/20] subselect.test, subselect.result: Added a test case for bug #12392. item_cmpfunc.cc: Fixed bug #12392. Missing handling of rows containing NULL components when evaluating IN predicates caused a crash. sql/item_cmpfunc.cc: Fixed bug #12392. Missing handling of rows containing NULL components when evaluating IN predicates caused a crash. mysql-test/r/subselect.result: Added a test case for bug #12392. mysql-test/t/subselect.test: Added a test case for bug #12392. --- mysql-test/r/subselect.result | 6 ++++++ mysql-test/t/subselect.test | 11 +++++++++++ sql/item_cmpfunc.cc | 2 ++ 3 files changed, 19 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 25d9a39705d..eaacf5ba2d0 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2742,3 +2742,9 @@ one two flag 5 6 N 7 8 N DROP TABLE t1,t2; +CREATE TABLE t1 (a char(5), b char(5)); +INSERT INTO t1 VALUES (NULL,'aaa'), ('aaa','aaa'); +SELECT * FROM t1 WHERE (a,b) IN (('aaa','aaa'), ('aaa','bbb')); +a b +aaa aaa +DROP TABLE t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 0b4791b0023..951dc31006e 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1770,4 +1770,15 @@ SELECT * FROM t1 DROP TABLE t1,t2; +# +# Bug #12392: where cond with IN predicate for rows and NULL values in table +# + +CREATE TABLE t1 (a char(5), b char(5)); +INSERT INTO t1 VALUES (NULL,'aaa'), ('aaa','aaa'); + +SELECT * FROM t1 WHERE (a,b) IN (('aaa','aaa'), ('aaa','bbb')); + +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f24638d1a93..9146b3c3b9e 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1551,6 +1551,8 @@ in_row::~in_row() byte *in_row::get_value(Item *item) { tmp.store_value(item); + if (item->is_null()) + return 0; return (byte *)&tmp; } From 08cadd816e7fd92f6f56c3ba621aa81d47954fca Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 9 Aug 2005 10:09:11 +0000 Subject: [PATCH 11/20] BUG#12228: Pre-review fixes: Fix coding style, handle the case when we're out of memory. --- sql/sp_cache.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index 135000d1443..1763432f2bc 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -111,6 +111,11 @@ void sp_cache_clear(sp_cache **cp) sp_cache_insert() cp The cache to put routine into sp Routine to insert. + + TODO: Perhaps it will be more straightforward if in case we returned an + error from this function when we couldn't allocate sp_cache. (right + now failure to put routine into cache will cause a 'SP not found' + error to be reported at some later time) */ void sp_cache_insert(sp_cache **cp, sp_head *sp) @@ -124,11 +129,13 @@ void sp_cache_insert(sp_cache **cp, sp_head *sp) pthread_mutex_lock(&Cversion_lock); // LOCK v= Cversion; pthread_mutex_unlock(&Cversion_lock); // UNLOCK - c->version= v; + if (c) + c->version= v; } if (c) { - DBUG_PRINT("info",("sp_cache: inserting: %*s", sp->m_qname.length, sp->m_qname.str)); + DBUG_PRINT("info",("sp_cache: inserting: %*s", sp->m_qname.length, + sp->m_qname.str)); c->insert(sp); if (*cp == NULL) *cp= c; From 61a68ed6fa0e408c64b857c1052b33eedc5e7de6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Aug 2005 00:23:56 +0400 Subject: [PATCH 12/20] Clumsy but working fix for bug #11973 "SELECT .. INTO var_name; in trigger cause crash on update". Let us update "thd" pointer in LEX, all its units and in LEX::result before executing statement in trigger body, since triggers are associated with TABLE object and because of this can be used in different threads. mysql-test/r/trigger.result: Added test case for bug #11973 "SELECT .. INTO var_name; in trigger cause crash on update". mysql-test/t/trigger.test: Added test case for bug #11973 "SELECT .. INTO var_name; in trigger cause crash on update". sql/item_subselect.cc: subselect_engine: Moved implementation of set_thd() method to item_subselect.cc, since now it also sets "thd" for subselect_engine::result. sql/item_subselect.h: subselect_engine: Moved implementation of set_thd() method to item_subselect.cc, since now it also sets "thd" for subselect_engine::result. sql/sql_class.h: select_result: Added set_thd() method for updating select_result::thd value (we need this in cases when statement to which this select_result belongs will be used in different threads, as it happens for statements in trigger body). multi_delete/multi_update: Got rid of redundant "thd" member (we already have it in select_result). sql/sql_delete.cc: multi_delete: Got rid of redundant "thd" member (we already have it in select_result). sql/sql_lex.h: st_select_lex_unit: Added set_thd() method for updating st_select_lex_unit::thd value (we need this in cases when statement to which this unit belongs will be used in different threads, as it happens for statements in trigger body). We don't update thd of select_result pointed by st_select_lex_unit::result in this method, since it is either have too short lifetime (i.e. created for each execution) or is accessible via Item_subquery or LEX::result and thus already taken care of. sql/sql_parse.cc: multi_delete: Got rid of redundant "thd" member (we already have it in select_result). sql/sql_prepare.cc: reinit_stmt_before_use(): We have to update "thd" pointer in LEX, all its units and in LEX::result, since statements which belong to trigger body are associated with TABLE object and because of this can be used in different threads. sql/sql_update.cc: multi_update: Got rid of redundant "thd" member (we already have it in select_result). --- mysql-test/r/trigger.result | 13 +++++++++++++ mysql-test/t/trigger.test | 23 +++++++++++++++++++++++ sql/item_subselect.cc | 8 ++++++++ sql/item_subselect.h | 7 +++++-- sql/sql_class.h | 7 +++---- sql/sql_delete.cc | 5 ++--- sql/sql_lex.h | 1 + sql/sql_parse.cc | 2 +- sql/sql_prepare.cc | 11 +++++++++++ sql/sql_update.cc | 6 +++--- 10 files changed, 70 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 52bf307a686..99abfc6db96 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -635,3 +635,16 @@ show triggers; Trigger Event Table Statement Timing Created sql_mode t1_bi INSERT t1 set new.a = '2004-01-00' BEFORE # drop table t1; +create table t1 (id int, data int, username varchar(16)); +insert into t1 (id, data) values (1, 0); +create trigger t1_whoupdated before update on t1 for each row +begin +declare user varchar(32); +declare i int; +select user() into user; +set NEW.username = user; +select count(*) from ((select 1) union (select 2)) as d1 into i; +end| +update t1 set data = 1; +update t1 set data = 2; +drop table t1; diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 7bf8b1a4e2b..3d5d3448a1b 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -642,3 +642,26 @@ show create table t1; --replace_column 6 # show triggers; drop table t1; + +# Test for bug #11973 "SELECT .. INTO var_name; in trigger cause +# crash on update" +create table t1 (id int, data int, username varchar(16)); +insert into t1 (id, data) values (1, 0); +delimiter |; +create trigger t1_whoupdated before update on t1 for each row +begin + declare user varchar(32); + declare i int; + select user() into user; + set NEW.username = user; + select count(*) from ((select 1) union (select 2)) as d1 into i; +end| +delimiter ;| +update t1 set data = 1; + +connect (addconroot, localhost, root,,); +connection addconroot; +update t1 set data = 2; + +connection default; +drop table t1; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index ad1c9977e5b..3cc75242ccb 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1271,6 +1271,14 @@ void Item_allany_subselect::print(String *str) } +void subselect_engine::set_thd(THD *thd_arg) +{ + thd= thd_arg; + if (result) + result->set_thd(thd_arg); +} + + subselect_single_select_engine:: subselect_single_select_engine(st_select_lex *select, select_subselect *result, diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 0b5736169fa..46623f76170 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -299,8 +299,11 @@ public: virtual ~subselect_engine() {}; // to satisfy compiler virtual void cleanup()= 0; - // set_thd should be called before prepare() - void set_thd(THD *thd_arg) { thd= thd_arg; } + /* + Also sets "thd" for subselect_engine::result. + Should be called before prepare(). + */ + void set_thd(THD *thd_arg); THD * get_thd() { return thd; } virtual int prepare()= 0; virtual void fix_length_and_dec(Item_cache** row)= 0; diff --git a/sql/sql_class.h b/sql/sql_class.h index ad4f38946a3..5e796c7297f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1560,6 +1560,7 @@ public: statement/stored procedure. */ virtual void cleanup(); + void set_thd(THD *thd_arg) { thd= thd_arg; } }; @@ -1915,14 +1916,13 @@ class multi_delete :public select_result_interceptor { TABLE_LIST *delete_tables, *table_being_deleted; Unique **tempfiles; - THD *thd; ha_rows deleted, found; uint num_of_tables; int error; bool do_delete, transactional_tables, normal_tables, delete_while_scanning; public: - multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables); + multi_delete(TABLE_LIST *dt, uint num_of_tables); ~multi_delete(); int prepare(List &list, SELECT_LEX_UNIT *u); bool send_data(List &items); @@ -1938,7 +1938,6 @@ class multi_update :public select_result_interceptor TABLE_LIST *all_tables; /* query/update command tables */ TABLE_LIST *leaves; /* list of leves of join table tree */ TABLE_LIST *update_tables, *table_being_updated; - THD *thd; TABLE **tmp_tables, *main_table, *table_to_update; TMP_TABLE_PARAM *tmp_table_param; ha_rows updated, found; @@ -1950,7 +1949,7 @@ class multi_update :public select_result_interceptor bool do_update, trans_safe, transactional_tables, ignore; public: - multi_update(THD *thd_arg, TABLE_LIST *ut, TABLE_LIST *leaves_list, + multi_update(TABLE_LIST *ut, TABLE_LIST *leaves_list, List *fields, List *values, enum_duplicates handle_duplicates, bool ignore); ~multi_update(); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d83937098e2..b6183bf5acb 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -407,9 +407,8 @@ bool mysql_multi_delete_prepare(THD *thd) } -multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, - uint num_of_tables_arg) - : delete_tables(dt), thd(thd_arg), deleted(0), found(0), +multi_delete::multi_delete(TABLE_LIST *dt, uint num_of_tables_arg) + : delete_tables(dt), deleted(0), found(0), num_of_tables(num_of_tables_arg), error(0), do_delete(0), transactional_tables(0), normal_tables(0) { diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 4bba0c432c7..e8c65ba5100 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -458,6 +458,7 @@ public: inline bool is_prepared() { return prepared; } bool change_result(select_subselect *result, select_subselect *old_result); void set_limit(st_select_lex *values); + void set_thd(THD *thd_arg) { thd= thd_arg; } friend void lex_start(THD *thd, uchar *buf, uint length); friend int subselect_union_engine::exec(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 677b3a98174..265c6e1d60d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3318,7 +3318,7 @@ end_with_restore_list: if ((res= mysql_multi_delete_prepare(thd))) goto error; - if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables, + if (!thd->is_fatal_error && (result= new multi_delete(aux_tables, lex->table_count))) { res= mysql_select(thd, &select_lex->ref_pointer_array, diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 18707cc6c87..3b0efd75426 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1850,6 +1850,13 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) SELECT_LEX *sl= lex->all_selects_list; DBUG_ENTER("reinit_stmt_before_use"); + /* + We have to update "thd" pointer in LEX, all its units and in LEX::result, + since statements which belong to trigger body are associated with TABLE + object and because of this can be used in different threads. + */ + lex->thd= thd; + if (lex->empty_field_list_on_rset) { lex->empty_field_list_on_rset= 0; @@ -1888,6 +1895,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) unit->types.empty(); /* for derived tables & PS (which can't be reset by Item_subquery) */ unit->reinit_exec_mechanism(); + unit->set_thd(thd); } } @@ -1926,7 +1934,10 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) lex->select_lex.leaf_tables= lex->leaf_tables_insert; if (lex->result) + { lex->result->cleanup(); + lex->result->set_thd(thd); + } DBUG_VOID_RETURN; } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 8a5b4ad8eae..cc7dff50551 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -820,7 +820,7 @@ bool mysql_multi_update(THD *thd, if (mysql_multi_update_prepare(thd)) DBUG_RETURN(TRUE); - if (!(result= new multi_update(thd, table_list, + if (!(result= new multi_update(table_list, thd->lex->select_lex.leaf_tables, fields, values, handle_duplicates, ignore))) @@ -846,13 +846,13 @@ bool mysql_multi_update(THD *thd, } -multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list, +multi_update::multi_update(TABLE_LIST *table_list, TABLE_LIST *leaves_list, List *field_list, List *value_list, enum enum_duplicates handle_duplicates_arg, bool ignore_arg) :all_tables(table_list), leaves(leaves_list), update_tables(0), - thd(thd_arg), tmp_tables(0), updated(0), found(0), fields(field_list), + tmp_tables(0), updated(0), found(0), fields(field_list), values(value_list), table_count(0), copy_field(0), handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(0), transactional_tables(1), ignore(ignore_arg) From 307ed9b4da9abfcb868f11ce7deb77d36ab4c662 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Aug 2005 18:58:55 +0300 Subject: [PATCH 13/20] block using QC in case of having tables locked by LOCK... (BUG#12385) sql/sql_cache.cc: block QC using if tables are locked with LOCK unlock QC mysql-test/r/query_cache_noembeded.result: New BitKeeper file ``mysql-test/r/query_cache_noembeded.result'' mysql-test/t/query_cache_noembeded.test: New BitKeeper file ``mysql-test/t/query_cache_noembeded.test'' --- mysql-test/r/query_cache_noembeded.result | 18 +++++++++++++ mysql-test/t/query_cache_noembeded.test | 33 +++++++++++++++++++++++ sql/sql_cache.cc | 7 +++-- 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 mysql-test/r/query_cache_noembeded.result create mode 100644 mysql-test/t/query_cache_noembeded.test diff --git a/mysql-test/r/query_cache_noembeded.result b/mysql-test/r/query_cache_noembeded.result new file mode 100644 index 00000000000..f2b06eea45d --- /dev/null +++ b/mysql-test/r/query_cache_noembeded.result @@ -0,0 +1,18 @@ +set GLOBAL query_cache_size=1355776; +reset query cache; +flush status; +CREATE TABLE t1 ( a INT NOT NULL PRIMARY KEY AUTO_INCREMENT ) ENGINE = +MyISAM; +LOCK TABLE t1 READ LOCAL; +INSERT INTO t1 VALUES (), (), (); +SELECT * FROM t1; +a +SELECT * FROM t1; +a +1 +2 +3 +SELECT * FROM t1; +a +drop table t1; +set GLOBAL query_cache_size=default; diff --git a/mysql-test/t/query_cache_noembeded.test b/mysql-test/t/query_cache_noembeded.test new file mode 100644 index 00000000000..c909bfcdf3b --- /dev/null +++ b/mysql-test/t/query_cache_noembeded.test @@ -0,0 +1,33 @@ +-- source include/have_query_cache.inc +-- source include/not_embedded.inc + +# +# Tests with query cache +# +set GLOBAL query_cache_size=1355776; + +# Reset query cache variables. + +reset query cache; +flush status; + +# +# do not use QC if tables locked (BUG#12385) +# +connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock); +connection root; +CREATE TABLE t1 ( a INT NOT NULL PRIMARY KEY AUTO_INCREMENT ) ENGINE = +MyISAM; +LOCK TABLE t1 READ LOCAL; +connect (root2,localhost,root,,test,$MASTER_MYPORT,master.sock); +connection root2; +INSERT INTO t1 VALUES (), (), (); +connection root; +SELECT * FROM t1; +connection root2; +SELECT * FROM t1; +connection root; +SELECT * FROM t1; +drop table t1; + +set GLOBAL query_cache_size=default; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index d729a6cc301..667b6e546d3 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -739,7 +739,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) TABLE_COUNTER_TYPE local_tables; ulong tot_length; DBUG_ENTER("Query_cache::store_query"); - if (query_cache_size == 0) + if (query_cache_size == 0 || thd->locked_tables) DBUG_VOID_RETURN; if ((local_tables= is_cacheable(thd, thd->query_length, @@ -750,7 +750,10 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) STRUCT_LOCK(&structure_guard_mutex); if (query_cache_size == 0) + { + STRUCT_UNLOCK(&structure_guard_mutex); DBUG_VOID_RETURN; + } DUMP(this); /* Key is query + database + flag */ @@ -874,7 +877,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) byte flags; DBUG_ENTER("Query_cache::send_result_to_client"); - if (query_cache_size == 0 || + if (query_cache_size == 0 || thd->locked_tables || /* it is not possible to check has_transactions() function of handler because tables not opened yet From 6b9ec78be00d37b91d4de8564bc0103d83ddfb26 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Aug 2005 21:17:02 +0000 Subject: [PATCH 14/20] BUG#12228: Post review fixes: Added test case, code cleanup. mysql-test/r/sp-threads.result: Testcase for BUG#12228 mysql-test/t/sp-threads.test: Testcase for BUG#12228 sql/sp_cache.cc: BUG#12228: Post-review fixes: small code cleanup sql/sp_cache.h: BUG#12228: Post-review fixes: fixed the comment sql/sql_parse.cc: BUG#12228: Post-review fixes: in mysql_parse, flush obsolete SPs from the caches only if the query hasn't been handled by the query cache. sql/sql_prepare.cc: BUG#12228: Post-review fixes: in mysql_stmt_prepare/execute, flush SP caches "closer to the execution" --- mysql-test/r/sp-threads.result | 25 ++++++++++++++++++++ mysql-test/t/sp-threads.test | 43 ++++++++++++++++++++++++++++++++++ sql/sp_cache.cc | 10 +++----- sql/sp_cache.h | 2 +- sql/sql_parse.cc | 4 ++-- sql/sql_prepare.cc | 9 +++---- 6 files changed, 79 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/sp-threads.result b/mysql-test/r/sp-threads.result index 2f7e8021aa7..c516d7a643f 100644 --- a/mysql-test/r/sp-threads.result +++ b/mysql-test/r/sp-threads.result @@ -37,6 +37,7 @@ Id User Host db Command Time State Info # root localhost test Sleep # NULL # root localhost test Query # Locked update t1, t2 set val= 1 where id1=id2 # root localhost test Query # NULL show processlist +# root localhost test Sleep # NULL unlock tables; drop procedure bug9486; drop table t1, t2; @@ -64,3 +65,27 @@ insert into t1 (select f from v1); drop function bug11554; drop table t1; drop view v1; +drop procedure if exists p1; +drop procedure if exists p2; +create table t1 (s1 int)| +create procedure p1() select * from t1| +create procedure p2() +begin +insert into t1 values (1); +call p1(); +select * from t1; +end| +use test; +lock table t1 write; + call p2(); +use test; +drop procedure p1; +create procedure p1() select * from t1; +unlock tables; +s1 +1 +s1 +1 +drop procedure p1; +drop procedure p2; +drop table t1; diff --git a/mysql-test/t/sp-threads.test b/mysql-test/t/sp-threads.test index 4c192f3e96f..5e51c1034e0 100644 --- a/mysql-test/t/sp-threads.test +++ b/mysql-test/t/sp-threads.test @@ -5,6 +5,7 @@ connect (con1root,localhost,root,,); connect (con2root,localhost,root,,); +connect (con3root,localhost,root,,); connection con1root; use test; @@ -130,6 +131,48 @@ drop function bug11554; drop table t1; drop view v1; + +# BUG#12228 +--disable_warnings +drop procedure if exists p1; +drop procedure if exists p2; +--enable_warnings + +connection con1root; +delimiter |; +create table t1 (s1 int)| +create procedure p1() select * from t1| +create procedure p2() +begin + insert into t1 values (1); + call p1(); + select * from t1; +end| +delimiter ;| + +connection con2root; +use test; +lock table t1 write; + +connection con1root; +send call p2(); + +connection con3root; +use test; +drop procedure p1; +create procedure p1() select * from t1; + +connection con2root; +unlock tables; + +connection con1root; +# Crash will be here if we hit BUG#12228 +reap; + +drop procedure p1; +drop procedure p2; +drop table t1; + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index 1763432f2bc..68e8dbb3252 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -122,19 +122,15 @@ void sp_cache_insert(sp_cache **cp, sp_head *sp) { sp_cache *c= *cp; - if (! c) + if (!c && (c= new sp_cache())) { - ulong v; - c= new sp_cache(); pthread_mutex_lock(&Cversion_lock); // LOCK - v= Cversion; + c->version= Cversion; pthread_mutex_unlock(&Cversion_lock); // UNLOCK - if (c) - c->version= v; } if (c) { - DBUG_PRINT("info",("sp_cache: inserting: %*s", sp->m_qname.length, + DBUG_PRINT("info",("sp_cache: inserting: %*s", sp->m_qname.length, sp->m_qname.str)); c->insert(sp); if (*cp == NULL) diff --git a/sql/sp_cache.h b/sql/sp_cache.h index 402647db9ea..1021d17b9e2 100644 --- a/sql/sp_cache.h +++ b/sql/sp_cache.h @@ -46,7 +46,7 @@ class sp_cache; sp_cache_insert(); sp_cache_invalidate(); - 2.2 When not holding any sp_head* pointers (at query end): + 2.2 When not holding any sp_head* pointers: sp_cache_flush_obsolete(); 3. Before thread exit: diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 00463dc0a3b..1a3f6f6f656 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5347,12 +5347,12 @@ void mysql_init_multi_delete(LEX *lex) void mysql_parse(THD *thd, char *inBuf, uint length) { DBUG_ENTER("mysql_parse"); - sp_cache_flush_obsolete(&thd->sp_proc_cache); - sp_cache_flush_obsolete(&thd->sp_func_cache); mysql_init_query(thd, (uchar*) inBuf, length); if (query_cache_send_result_to_client(thd, inBuf, length) <= 0) { LEX *lex= thd->lex; + sp_cache_flush_obsolete(&thd->sp_proc_cache); + sp_cache_flush_obsolete(&thd->sp_func_cache); if (!yyparse((void *)thd) && ! thd->is_fatal_error) { #ifndef NO_EMBEDDED_ACCESS_CHECKS diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index f8b19dac3d1..4eb8c00ae16 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1730,8 +1730,6 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, DBUG_ENTER("mysql_stmt_prepare"); DBUG_PRINT("prep_query", ("%s", packet)); - sp_cache_flush_obsolete(&thd->sp_proc_cache); - sp_cache_flush_obsolete(&thd->sp_func_cache); /* If this is an SQLCOM_PREPARE, we also increase Com_prepare_sql. @@ -1785,6 +1783,9 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, lex= thd->lex; lex->safe_to_cache_query= 0; + sp_cache_flush_obsolete(&thd->sp_proc_cache); + sp_cache_flush_obsolete(&thd->sp_func_cache); + error= yyparse((void *)thd) || thd->is_fatal_error || thd->net.report_error || init_param_array(stmt); /* @@ -1981,8 +1982,6 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) Prepared_statement *stmt; DBUG_ENTER("mysql_stmt_execute"); - sp_cache_flush_obsolete(&thd->sp_proc_cache); - sp_cache_flush_obsolete(&thd->sp_func_cache); packet+= 9; /* stmt_id + 5 bytes of flags */ statistic_increment(thd->status_var.com_stmt_execute, &LOCK_status); @@ -2063,6 +2062,8 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) thd->protocol= &thd->protocol_prep; // Switch to binary protocol if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(),QUERY_PRIOR); + sp_cache_flush_obsolete(&thd->sp_proc_cache); + sp_cache_flush_obsolete(&thd->sp_func_cache); mysql_execute_command(thd); if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); From a724dbc039771ed0bb3cab7b35330a1066612c6f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 Aug 2005 09:29:50 +0300 Subject: [PATCH 15/20] make the same filenames as in 4.1 mysql-test/t/query_cache_notembedded.test: Rename: mysql-test/t/query_cache_noembeded.test -> mysql-test/t/query_cache_notembedded.test mysql-test/r/query_cache_notembedded.result: Rename: mysql-test/r/query_cache_noembeded.result -> mysql-test/r/query_cache_notembedded.result --- ...uery_cache_noembeded.result => query_cache_notembedded.result} | 0 .../{query_cache_noembeded.test => query_cache_notembedded.test} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename mysql-test/r/{query_cache_noembeded.result => query_cache_notembedded.result} (100%) rename mysql-test/t/{query_cache_noembeded.test => query_cache_notembedded.test} (100%) diff --git a/mysql-test/r/query_cache_noembeded.result b/mysql-test/r/query_cache_notembedded.result similarity index 100% rename from mysql-test/r/query_cache_noembeded.result rename to mysql-test/r/query_cache_notembedded.result diff --git a/mysql-test/t/query_cache_noembeded.test b/mysql-test/t/query_cache_notembedded.test similarity index 100% rename from mysql-test/t/query_cache_noembeded.test rename to mysql-test/t/query_cache_notembedded.test From bf07693148f916b27e8a520965fdd556ad054806 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 Aug 2005 13:07:08 +0300 Subject: [PATCH 16/20] query_cache_notembedded.test, query_cache_notembedded.result: postmerge fix mysql-test/r/query_cache_notembedded.result: postmerge fix mysql-test/t/query_cache_notembedded.test: postmerge fix --- mysql-test/r/query_cache_notembedded.result | 14 ++++++++++++++ mysql-test/t/query_cache_notembedded.test | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/mysql-test/r/query_cache_notembedded.result b/mysql-test/r/query_cache_notembedded.result index 16a397f78b6..e773a63525b 100644 --- a/mysql-test/r/query_cache_notembedded.result +++ b/mysql-test/r/query_cache_notembedded.result @@ -80,4 +80,18 @@ show status like "Qcache_free_blocks"; Variable_name Value Qcache_free_blocks 1 drop table t1, t2, t3, t11, t21; +CREATE TABLE t1 ( a INT NOT NULL PRIMARY KEY AUTO_INCREMENT ) ENGINE = +MyISAM; +LOCK TABLE t1 READ LOCAL; +INSERT INTO t1 VALUES (), (), (); +SELECT * FROM t1; +a +SELECT * FROM t1; +a +1 +2 +3 +SELECT * FROM t1; +a +drop table t1; set GLOBAL query_cache_size=0; diff --git a/mysql-test/t/query_cache_notembedded.test b/mysql-test/t/query_cache_notembedded.test index d29dc10ccae..fd4785ffe95 100644 --- a/mysql-test/t/query_cache_notembedded.test +++ b/mysql-test/t/query_cache_notembedded.test @@ -78,4 +78,23 @@ show status like "Qcache_total_blocks"; show status like "Qcache_free_blocks"; drop table t1, t2, t3, t11, t21; +# +# do not use QC if tables locked (BUG#12385) +# +connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock); +connection root; +CREATE TABLE t1 ( a INT NOT NULL PRIMARY KEY AUTO_INCREMENT ) ENGINE = +MyISAM; +LOCK TABLE t1 READ LOCAL; +connect (root2,localhost,root,,test,$MASTER_MYPORT,master.sock); +connection root2; +INSERT INTO t1 VALUES (), (), (); +connection root; +SELECT * FROM t1; +connection root2; +SELECT * FROM t1; +connection root; +SELECT * FROM t1; +drop table t1; + set GLOBAL query_cache_size=0; From 8158bb033dc23eef22173a9af13756aeb44241ec Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 Aug 2005 18:03:01 +0200 Subject: [PATCH 17/20] set_var.cc, mysqld.cc, ha_innodb.h, ha_innodb.cc, srv0srv.c, srv0srv.h: Added innodb_commit_concurrency variable innobase/include/srv0srv.h: Added innodb_commit_concurrency variable innobase/srv/srv0srv.c: Added innodb_commit_concurrency variable sql/ha_innodb.cc: Added innodb_commit_concurrency variable sql/ha_innodb.h: Added innodb_commit_concurrency variable sql/mysqld.cc: Added innodb_commit_concurrency variable sql/set_var.cc: Added innodb_commit_concurrency variable --- innobase/include/srv0srv.h | 1 + innobase/srv/srv0srv.c | 1 + sql/ha_innodb.cc | 47 +++++++++++++++++++++++++++++++++++--- sql/ha_innodb.h | 1 + sql/mysqld.cc | 4 ++++ sql/set_var.cc | 4 ++++ 6 files changed, 55 insertions(+), 3 deletions(-) diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 116ae7b6438..11347f430d4 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -94,6 +94,7 @@ extern ulint srv_max_dirty_pages_pct; extern ulint srv_force_recovery; extern ulong srv_thread_concurrency; +extern ulong srv_commit_concurrency; extern ulint srv_max_n_threads; diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index dc85750f0be..64cbae3644a 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -261,6 +261,7 @@ Value 10 should be good if there are less than 4 processors + 4 disks in the computer. Bigger computers need bigger values. */ ulong srv_thread_concurrency = SRV_CONCURRENCY_THRESHOLD; +ulong srv_commit_concurrency = 0; os_fast_mutex_t srv_conc_mutex; /* this mutex protects srv_conc data structures */ diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 0a01c08c916..c0aa7cc78c7 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -48,6 +48,10 @@ have disables the InnoDB inlining in this file. */ pthread_mutex_t innobase_share_mutex, /* to protect innobase_open_files */ prepare_commit_mutex; /* to force correct commit order in binlog */ +ulong commit_threads= 0; +pthread_mutex_t commit_threads_m; +pthread_cond_t commit_cond; +pthread_mutex_t commit_cond_m; bool innodb_inited= 0; /*-----------------------------------------------------------------*/ @@ -1367,6 +1371,9 @@ innobase_init(void) (hash_get_key) innobase_get_key, 0, 0); pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST); pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST); + pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST); + pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST); + pthread_cond_init(&commit_cond, NULL); innodb_inited= 1; /* If this is a replication slave and we needed to do a crash recovery, @@ -1416,6 +1423,9 @@ innobase_end(void) MYF(MY_ALLOW_ZERO_PTR)); pthread_mutex_destroy(&innobase_share_mutex); pthread_mutex_destroy(&prepare_commit_mutex); + pthread_mutex_destroy(&commit_threads_m); + pthread_mutex_destroy(&commit_cond_m); + pthread_cond_destroy(&commit_cond); } DBUG_RETURN(err); @@ -1542,8 +1552,10 @@ innobase_commit( reserve the kernel mutex, we have to release the search system latch first to obey the latching order. */ - innobase_release_stat_resources(trx); - + if (trx->has_search_latch) { + trx_search_latch_release_if_reserved(trx); + } + /* The flag trx->active_trans is set to 1 in 1. ::external_lock(), @@ -1575,18 +1587,43 @@ innobase_commit( /* We need current binlog position for ibbackup to work. Note, the position is current because of prepare_commit_mutex */ +retry: + if (srv_commit_concurrency > 0) + { + pthread_mutex_lock(&commit_cond_m); + commit_threads++; + if (commit_threads > srv_commit_concurrency) + { + commit_threads--; + pthread_cond_wait(&commit_cond, &commit_cond_m); + pthread_mutex_unlock(&commit_cond_m); + goto retry; + } + else + pthread_mutex_unlock(&commit_cond_m); + } + trx->mysql_log_file_name = mysql_bin_log.get_log_fname(); trx->mysql_log_offset = (ib_longlong)mysql_bin_log.get_log_file()->pos_in_file; innobase_commit_low(trx); + if (srv_commit_concurrency > 0) + { + pthread_mutex_lock(&commit_cond_m); + commit_threads--; + pthread_cond_signal(&commit_cond); + pthread_mutex_unlock(&commit_cond_m); + } + if (trx->active_trans == 2) { pthread_mutex_unlock(&prepare_commit_mutex); } + trx->active_trans = 0; - + } else { /* We just mark the SQL statement ended and do not do a transaction commit */ @@ -1606,7 +1643,11 @@ innobase_commit( /* Tell the InnoDB server that there might be work for utility threads: */ + if (trx->declared_to_be_inside_innodb) { + /* Release our possible ticket in the FIFO */ + srv_conc_force_exit_innodb(trx); + } srv_active_wake_master_thread(); DBUG_RETURN(0); diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 3bc1fc5b2c8..4817ab9b682 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -232,6 +232,7 @@ extern ulong srv_n_spin_wait_rounds; extern ulong srv_n_free_tickets_to_enter; extern ulong srv_thread_sleep_delay; extern ulong srv_thread_concurrency; +extern ulong srv_commit_concurrency; } extern TYPELIB innobase_lock_typelib; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f8bfcb75be2..4dddac6b2d1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5314,6 +5314,10 @@ log and this option does nothing anymore.", "Helps in performance tuning in heavily concurrent environments.", (gptr*) &srv_thread_concurrency, (gptr*) &srv_thread_concurrency, 0, GET_LONG, REQUIRED_ARG, 20, 1, 1000, 0, 1, 0}, + {"innodb_commit_concurrency", OPT_INNODB_THREAD_CONCURRENCY, + "Helps in performance tuning in heavily concurrent environments.", + (gptr*) &srv_commit_concurrency, (gptr*) &srv_commit_concurrency, + 0, GET_LONG, REQUIRED_ARG, 0, 0, 1000, 0, 1, 0}, {"innodb_thread_sleep_delay", OPT_INNODB_THREAD_SLEEP_DELAY, "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0" " disable a sleep", diff --git a/sql/set_var.cc b/sql/set_var.cc index 637b33f18d2..53f3d45e522 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -411,6 +411,8 @@ sys_var_long_ptr sys_innodb_thread_sleep_delay("innodb_thread_sleep_delay", &srv_thread_sleep_delay); sys_var_long_ptr sys_innodb_thread_concurrency("innodb_thread_concurrency", &srv_thread_concurrency); +sys_var_long_ptr sys_innodb_commit_concurrency("innodb_commit_concurrency", + &srv_commit_concurrency); #endif /* Condition pushdown to storage engine */ @@ -708,6 +710,7 @@ sys_var *sys_variables[]= &sys_innodb_concurrency_tickets, &sys_innodb_thread_sleep_delay, &sys_innodb_thread_concurrency, + &sys_innodb_commit_concurrency, #endif &sys_trust_routine_creators, &sys_engine_condition_pushdown, @@ -828,6 +831,7 @@ struct show_var_st init_vars[]= { {sys_innodb_table_locks.name, (char*) &sys_innodb_table_locks, SHOW_SYS}, {sys_innodb_support_xa.name, (char*) &sys_innodb_support_xa, SHOW_SYS}, {sys_innodb_thread_concurrency.name, (char*) &sys_innodb_thread_concurrency, SHOW_SYS}, + {sys_innodb_commit_concurrency.name, (char*) &sys_innodb_commit_concurrency, SHOW_SYS}, {sys_innodb_thread_sleep_delay.name, (char*) &sys_innodb_thread_sleep_delay, SHOW_SYS}, #endif {sys_interactive_timeout.name,(char*) &sys_interactive_timeout, SHOW_SYS}, From 1d3d9ec13fc078cc30dbbe872c7cb5320c169feb Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 Aug 2005 19:19:20 +0300 Subject: [PATCH 18/20] Fixed some warning and error messages so that they use sql_print_warning() and sql_print_error() instead of fprintf to stderr. Above functions are tuned for different platforms so that the behavior is consistent around platforms. Using fprintf() different behavior can be expected at least on Windows and Unix. --- sql/ha_innodb.cc | 127 ++++++++++------------------------------------- 1 file changed, 25 insertions(+), 102 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 0a01c08c916..e7a6d7d5524 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -948,9 +948,7 @@ innobase_query_caching_of_table_permitted( trx = check_trx_exists(thd); if (trx->has_search_latch) { ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: the calling thread is holding the adaptive search\n" -"InnoDB: latch though calling innobase_query_caching_of_table_permitted\n"); + sql_print_error("The calling thread is holding the adaptive search, latch though calling innobase_query_caching_of_table_permitted."); } innobase_release_stat_resources(trx); @@ -1266,9 +1264,7 @@ innobase_init(void) &srv_log_group_home_dirs); if (ret == FALSE || innobase_mirrored_log_groups != 1) { - fprintf(stderr, - "InnoDB: syntax error in innodb_log_group_home_dir\n" - "InnoDB: or a wrong number of mirrored log groups\n"); + sql_print_error("syntax error in innodb_log_group_home_dir, or a wrong number of mirrored log groups"); my_free(internal_innobase_data_file_path, MYF(MY_ALLOW_ZERO_PTR)); @@ -1562,11 +1558,8 @@ innobase_commit( if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) { - fprintf(stderr, -"InnoDB: Error: trx->active_trans == 0\n" -"InnoDB: but trx->conc_state != TRX_NOT_STARTED\n"); + sql_print_error("trx->active_trans == 0, but trx->conc_state != TRX_NOT_STARTED"); } - if (all || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { @@ -1813,21 +1806,7 @@ try_again: if (ret != 0) { ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: MySQL synchronous replication\n" -"InnoDB: was not able to send the binlog to the slave within the\n" -"InnoDB: timeout %lu. We assume that the slave has become inaccessible,\n" -"InnoDB: and switch off synchronous replication until the communication.\n" -"InnoDB: to the slave works again.\n", - thd->variables.sync_replication_timeout); - fprintf(stderr, -"InnoDB: MySQL synchronous replication has sent binlog\n" -"InnoDB: to the slave up to file %s, position %lu\n", innobase_repl_file_name, - (ulong)innobase_repl_pos); - fprintf(stderr, -"InnoDB: This transaction needs it to be sent up to\n" -"InnoDB: file %s, position %lu\n", trx->repl_wait_binlog_name, - (ulong)trx->repl_wait_binlog_pos); + sql_print_error("MySQL synchronous replication was not able to send the binlog to the slave within the timeout %lu. We assume that the slave has become inaccessible, and switch off synchronous replication until the communication to the slave works again. MySQL synchronous replication has sent binlog to the slave up to file %s, position %lu. This transaction needs it to be sent up to file %s, position %lu.", thd->variables.sync_replication_timeout, innobase_repl_file_name, (ulong)innobase_repl_pos, trx->repl_wait_binlog_name, (ulong)trx->repl_wait_binlog_pos); innobase_repl_state = 0; @@ -1878,9 +1857,7 @@ innobase_repl_report_sent_binlog( if (innobase_repl_state == 0) { ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Switching MySQL synchronous replication on again at\n" -"InnoDB: binlog file %s, position %lu\n", log_file_name, (ulong)end_offset); + sql_print_warning("Switching MySQL synchronous replication on again at binlog file %s, position %lu", log_file_name, (ulong) end_offset); innobase_repl_state = 1; } @@ -1897,14 +1874,7 @@ innobase_repl_report_sent_binlog( || (cmp == 0 && end_offset < innobase_repl_pos)) { ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: MySQL synchronous replication has sent binlog\n" -"InnoDB: to the slave up to file %s, position %lu\n", innobase_repl_file_name, - (ulong)innobase_repl_pos); - fprintf(stderr, -"InnoDB: but now MySQL reports that it sent the binlog only up to\n" -"InnoDB: file %s, position %lu\n", log_file_name, (ulong)end_offset); - + sql_print_error("MySQL synchronous replication has sent binlog to the slave up to file %s, position %lu, but now MySQL reports that it sent the binlog only up to file %s, position %lu", innobase_repl_file_name, (ulong)innobase_repl_pos, log_file_name, (ulong) end_offset); } } @@ -2149,9 +2119,7 @@ innobase_close_connection( if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) { - fprintf(stderr, -"InnoDB: Error: trx->active_trans == 0\n" -"InnoDB: but trx->conc_state != TRX_NOT_STARTED\n"); + sql_print_error("trx->active_trans == 0, but trx->conc_state != TRX_NOT_STARTED"); } @@ -2363,9 +2331,7 @@ ha_innobase::open( if (!row_table_got_default_clust_index(ib_table)) { if (primary_key >= MAX_KEY) { - fprintf(stderr, - "InnoDB: Error: table %s has a primary key in InnoDB\n" - "InnoDB: data dictionary, but not in MySQL!\n", name); + sql_print_error("Table %s has a primary key in InnoDB data dictionary, but not in MySQL!", name); } ((row_prebuilt_t*)innobase_prebuilt) @@ -2379,16 +2345,7 @@ ha_innobase::open( ref_length = table->key_info[primary_key].key_length; } else { if (primary_key != MAX_KEY) { - fprintf(stderr, - "InnoDB: Error: table %s has no primary key in InnoDB\n" - "InnoDB: data dictionary, but has one in MySQL!\n" - "InnoDB: If you created the table with a MySQL\n" - "InnoDB: version < 3.23.54 and did not define a primary\n" - "InnoDB: key, but defined a unique key with all non-NULL\n" - "InnoDB: columns, then MySQL internally treats that key\n" - "InnoDB: as the primary key. You can fix this error by\n" - "InnoDB: dump + DROP + CREATE + reimport of the table.\n", - name); + sql_print_error("Table %s has no primary key in InnoDB data dictionary, but has one in MySQL! If you created the table with a MySQL version < 3.23.54 and did not define a primary key, but defined a unique key with all non-NULL columns, then MySQL internally treats that key as the primary key. You can fix this error by dump + DROP + CREATE + reimport of the table.", name); } ((row_prebuilt_t*)innobase_prebuilt) @@ -2405,10 +2362,7 @@ ha_innobase::open( and it will never be updated anyway. */ if (key_used_on_scan != MAX_KEY) { - fprintf(stderr, -"InnoDB: Warning: table %s key_used_on_scan is %lu even though there is no\n" -"InnoDB: primary key inside InnoDB.\n", - name, (ulong)key_used_on_scan); + sql_print_warning("Table %s key_used_on_scan is %lu even though there is no primary key inside InnoDB.", name, (ulong) key_used_on_scan); } } @@ -2563,9 +2517,7 @@ innobase_mysql_cmp( charset = get_charset(charset_number, MYF(MY_WME)); if (charset == NULL) { - fprintf(stderr, -"InnoDB: fatal error: InnoDB needs charset %lu for doing a comparison,\n" -"InnoDB: but MySQL cannot find that charset.\n", (ulong)charset_number); + sql_print_error("InnoDB needs charset %lu for doing a comparison, but MySQL cannot find that charset.", (ulong) charset_number); ut_a(0); } } @@ -3131,11 +3083,8 @@ ha_innobase::write_row( if (prebuilt->trx != (trx_t*) current_thd->ha_data[innobase_hton.slot]) { - fprintf(stderr, -"InnoDB: Error: the transaction object for the table handle is at\n" -"InnoDB: %p, but for the current thread it is at %p\n", - prebuilt->trx, - (trx_t*) current_thd->ha_data[innobase_hton.slot]); + sql_print_error("The transaction object for the table handle is at %p, but for the current thread it is at %p", prebuilt->trx, (trx_t*) current_thd->ha_data[innobase_hton.slot]); + fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr); ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200); fputs("\n" @@ -3622,9 +3571,7 @@ ha_innobase::unlock_row(void) if (last_query_id != user_thd->query_id) { ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: last_query_id is %lu != user_thd_query_id is %lu\n", - (ulong)last_query_id, (ulong)user_thd->query_id); + sql_print_error("last_query_id is %lu != user_thd_query_id is %lu", (ulong) last_query_id, (ulong) user_thd->query_id); mem_analyze_corruption((byte *) prebuilt->trx); ut_error; } @@ -4284,9 +4231,8 @@ ha_innobase::position( table. */ if (len != ref_length) { - fprintf(stderr, - "InnoDB: Error: stored ref len is %lu, but table ref len is %lu\n", - (ulong)len, (ulong)ref_length); + sql_print_error("Stored ref len is %lu, but table ref len is %lu", + (ulong) len, (ulong) ref_length); } } @@ -4491,11 +4437,8 @@ create_index( || col_type == DATA_FLOAT || col_type == DATA_DOUBLE || col_type == DATA_DECIMAL) { - fprintf(stderr, -"InnoDB: error: MySQL is trying to create a column prefix index field\n" -"InnoDB: on an inappropriate data type. Table name %s, column name %s.\n", - table_name, key_part->field->field_name); - + sql_print_error("MySQL is trying to create a column prefix index field, on an inappropriate data type. Table name %s, column name %s.", table_name, key_part->field->field_name); + prefix_len = 0; } } else { @@ -5378,12 +5321,7 @@ ha_innobase::info( for (i = 0; i < table->s->keys; i++) { if (index == NULL) { ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: table %s contains less indexes inside InnoDB\n" -"InnoDB: than are defined in the MySQL .frm file. Have you mixed up\n" -"InnoDB: .frm files from different installations? See section\n" -"InnoDB: 15.1 at http://www.innodb.com/ibman.html\n", - ib_table->name); + sql_print_error("Table %s contains less indexes inside InnoDB than are defined in the MySQL .frm file. Have you mixed up .frm files from different installations? See section 15.1 at http://www.innodb.com/ibman.html", ib_table->name); break; } @@ -5391,15 +5329,7 @@ ha_innobase::info( if (j + 1 > index->n_uniq) { ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: index %s of %s has %lu columns unique inside InnoDB\n" -"InnoDB: but MySQL is asking statistics for %lu columns. Have you mixed up\n" -"InnoDB: .frm files from different installations? See section\n" -"InnoDB: 15.1 at http://www.innodb.com/ibman.html\n", - index->name, - ib_table->name, - (unsigned long) index->n_uniq, - j + 1); + sql_print_error("Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking statistics for %lu columns. Have you mixed up .frm files from different installations? See section 15.1 at http://www.innodb.com/ibman.html", index->name, ib_table->name, (unsigned long) index->n_uniq, j + 1); break; } @@ -5947,9 +5877,7 @@ ha_innobase::start_stmt( if (prebuilt->stored_select_lock_type != LOCK_S && prebuilt->stored_select_lock_type != LOCK_X) { - fprintf(stderr, -"InnoDB: Error: stored_select_lock_type is %lu inside ::start_stmt()!\n", - prebuilt->stored_select_lock_type); + sql_print_error("stored_select_lock_type is %lu inside ::start_stmt()!", prebuilt->stored_select_lock_type); /* Set the value to LOCK_X: this is just fault tolerance, we do not know what the correct value @@ -6725,9 +6653,7 @@ ha_innobase::innobase_read_and_init_auto_inc( error = 0; } else { /* This should not happen in a consistent read */ - fprintf(stderr, -"InnoDB: Error: consistent read of auto-inc column returned %lu\n", - (ulong)error); + sql_print_error("Consistent read of auto-inc column returned %lu", (ulong) error); auto_inc = -1; goto func_exit; @@ -6784,9 +6710,8 @@ ha_innobase::get_auto_increment() initialized. */ ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: error %lu in ::get_auto_increment()\n", - (ulong)error); + sql_print_error("Error %lu in ::get_auto_increment()", + (ulong) error); return(~(ulonglong) 0); } @@ -7053,9 +6978,7 @@ innobase_xa_prepare( if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) { - fprintf(stderr, -"InnoDB: Error: trx->active_trans == 0\n" -"InnoDB: but trx->conc_state != TRX_NOT_STARTED\n"); + sql_print_error("trx->active_trans == 0, but trx->conc_state != TRX_NOT_STARTED"); } if (all From a6975c017ba47b2b4b4ec9261b5d935523b1c202 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 Aug 2005 18:42:22 +0100 Subject: [PATCH 19/20] fix after merge mysql-test/r/bigint.result: fix test after merge mysql-test/r/query_cache.result: fix test after merge mysql-test/r/type_datetime.result: fix test after merge --- mysql-test/r/bigint.result | 2 +- mysql-test/r/query_cache.result | 6 ------ mysql-test/r/type_datetime.result | 2 +- sql/sql_union.cc | 4 ++-- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result index 35374024649..1b5619eb18d 100644 --- a/mysql-test/r/bigint.result +++ b/mysql-test/r/bigint.result @@ -22,7 +22,7 @@ select 1,11,101,1001,10001,100001,1000001,10000001,100000001,1000000001,10000000 1 11 101 1001 10001 100001 1000001 10000001 100000001 1000000001 10000000001 100000000001 1000000000001 10000000000001 100000000000001 1000000000000001 10000000000000001 100000000000000001 1000000000000000001 10000000000000000001 select -1,-11,-101,-1001,-10001,-100001,-1000001,-10000001,-100000001,-1000000001,-10000000001,-100000000001,-1000000000001,-10000000000001,-100000000000001,-1000000000000001,-10000000000000001,-100000000000000001,-1000000000000000001,-10000000000000000001; -1 -11 -101 -1001 -10001 -100001 -1000001 -10000001 -100000001 -1000000001 -10000000001 -100000000001 -1000000000001 -10000000000001 -100000000000001 -1000000000000001 -10000000000000001 -100000000000000001 -1000000000000000001 -10000000000000000001 --1 -11 -101 -1001 -10001 -100001 -1000001 -10000001 -100000001 -1000000001 -10000000001 -100000000001 -1000000000001 -10000000000001 -100000000000001 -1000000000000001 -10000000000000001 -100000000000000001 -1000000000000000001 -10000000000000000000 +-1 -11 -101 -1001 -10001 -100001 -1000001 -10000001 -100000001 -1000000001 -10000000001 -100000000001 -1000000000001 -10000000000001 -100000000000001 -1000000000000001 -10000000000000001 -100000000000000001 -1000000000000000001 -10000000000000000001 select conv(1,10,16),conv((1<<2)-1,10,16),conv((1<<10)-2,10,16),conv((1<<16)-3,10,16),conv((1<<25)-4,10,16),conv((1<<31)-5,10,16),conv((1<<36)-6,10,16),conv((1<<47)-7,10,16),conv((1<<48)-8,10,16),conv((1<<55)-9,10,16),conv((1<<56)-10,10,16),conv((1<<63)-11,10,16); conv(1,10,16) conv((1<<2)-1,10,16) conv((1<<10)-2,10,16) conv((1<<16)-3,10,16) conv((1<<25)-4,10,16) conv((1<<31)-5,10,16) conv((1<<36)-6,10,16) conv((1<<47)-7,10,16) conv((1<<48)-8,10,16) conv((1<<55)-9,10,16) conv((1<<56)-10,10,16) conv((1<<63)-11,10,16) 1 3 3FE FFFD 1FFFFFC 7FFFFFFB FFFFFFFFA 7FFFFFFFFFF9 FFFFFFFFFFF8 7FFFFFFFFFFFF7 FFFFFFFFFFFFF6 7FFFFFFFFFFFFFF5 diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 6ff49951d27..0efd5ac1566 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -947,24 +947,18 @@ COUNT(*) Warnings: Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' -Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) 0 Warnings: Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect INTEGER value: '20050328 invalid' -Warning 1292 Truncated incorrect INTEGER value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) 0 Warnings: Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' -Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index 3aaa0e5f151..85f899be5d8 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -52,7 +52,7 @@ t truncate table t1; insert into t1 values("2003-0303 12:13:14"); Warnings: -Warning 1264 Data truncated; out of range for column 't' at row 1 +Warning 1264 Out of range value adjusted for column 't' at row 1 select * from t1; t 0000-00-00 00:00:00 diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 05472058489..c2888bee4c6 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -301,8 +301,8 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } } - ulong create_options= (first_select_in_union()->options | thd_arg->options | - TMP_TABLE_ALL_COLUMNS) & ~TMP_TABLE_FORCE_MYISAM; + create_options= (first_select_in_union()->options | thd_arg->options | + TMP_TABLE_ALL_COLUMNS) & ~TMP_TABLE_FORCE_MYISAM; /* Force the temporary table to be a MyISAM table if we're going to use fullext functions (MATCH ... AGAINST .. IN BOOLEAN MODE) when reading From 8ee51b0541d7cc65385c2b11da4f3e79a1df55e6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 Aug 2005 12:26:17 -0700 Subject: [PATCH 20/20] Build YASSL libraries with libtool so correct PIC settings are used automatically. (Bug #12324) extra/yassl/src/Makefile.am: Build library with libtool extra/yassl/taocrypt/src/Makefile.am: Build library with libtool --- extra/yassl/src/Makefile.am | 4 ++-- extra/yassl/taocrypt/src/Makefile.am | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am index 4ebb9a2d862..83397e24168 100644 --- a/extra/yassl/src/Makefile.am +++ b/extra/yassl/src/Makefile.am @@ -1,7 +1,7 @@ INCLUDES = -I../include -I../taocrypt/include -I../mySTL -noinst_LIBRARIES = libyassl.a -libyassl_a_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \ +noinst_LTLIBRARIES = libyassl.la +libyassl_la_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \ handshake.cpp lock.cpp log.cpp socket_wrapper.cpp ssl.cpp \ template_instnt.cpp timer.cpp yassl_imp.cpp yassl_error.cpp yassl_int.cpp EXTRA_DIST = ../include/*.hpp ../include/openssl/*.h diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am index 5bf45074a98..4549c218d87 100644 --- a/extra/yassl/taocrypt/src/Makefile.am +++ b/extra/yassl/taocrypt/src/Makefile.am @@ -1,7 +1,7 @@ INCLUDES = -I../include -I../../mySTL -noinst_LIBRARIES = libtaocrypt.a -libtaocrypt_a_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp asn.cpp \ +noinst_LTLIBRARIES = libtaocrypt.la +libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp asn.cpp \ coding.cpp dh.cpp des.cpp dsa.cpp file.cpp hash.cpp integer.cpp \ md2.cpp md5.cpp misc.cpp random.cpp ripemd.cpp rsa.cpp sha.cpp \ template_instnt.cpp