From f2a610e1e072f3b50709be3f419ea3ac1d7a3aa5 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 14 Nov 2008 02:01:41 +0100 Subject: [PATCH 01/11] Bug #20430 mysqld.exe windows service stuck in "SERVICE_STOP_PENDING" status The problem appears to be a race condition, when service is being stopped right after startup. We set the service status to SERVICE_RUNNING way too early it cannot yet handle stop requests - initialization has not finished and hEventShutdown that signals server to stop is not yet created. If somebody issues "net stop MySQL" at this time, MySQL is not informed about the stop and continues to run as usual, while NTService::ServiceMain() stucks forever waiting for mysql's "main" thread to finish. Solution is to remain in SERVICE_START_PENDING status until after server initialization is fully complete and only then change the status to SERVICE_RUNNING. In SERVICE_START_PENDING we do not accept service control requests, i.e it is not possible to stop service in that time. sql/mysqld.cc: Set service status to running after all initialization is complete sql/nt_servc.cc: New method SetRunning() to be called by application to set service status to SERVICE_RUNNING when apllication has finished initialization. sql/nt_servc.h: New method SetRunning() to be called by application when initialization completes --- sql/mysqld.cc | 3 +++ sql/nt_servc.cc | 12 ++++++++---- sql/nt_servc.h | 14 +++++++++++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c3e5449b22b..ba6c8c6169f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3840,6 +3840,9 @@ we force server id to 2, but this MySQL server will not act as a slave."); : mysqld_unix_port), mysqld_port, MYSQL_COMPILATION_COMMENT); +#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY) + Service.SetRunning(); +#endif #if defined(__NT__) || defined(HAVE_SMEM) handle_connections_methods(); diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc index a04f284a3de..e570898f373 100644 --- a/sql/nt_servc.cc +++ b/sql/nt_servc.cc @@ -245,10 +245,6 @@ void NTService::ServiceMain(DWORD argc, LPTSTR *argv) if (!pService->StartService()) goto error; - // Check that the service is now running. - if (!pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0)) - goto error; - // wait for exit event WaitForSingleObject (pService->hExitEvent, INFINITE); @@ -264,6 +260,14 @@ error: return; } + +void NTService::SetRunning() +{ + if (pService) + pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0); +} + + /* ------------------------------------------------------------------------ StartService() - starts the appliaction thread -------------------------------------------------------------------------- */ diff --git a/sql/nt_servc.h b/sql/nt_servc.h index a3c12569114..9b689e434e1 100644 --- a/sql/nt_servc.h +++ b/sql/nt_servc.h @@ -56,7 +56,19 @@ class NTService BOOL IsService(LPCSTR ServiceName); BOOL got_service_option(char **argv, char *service_option); BOOL is_super_user(); - void Stop(void); //to be called from app. to stop service + + /* + SetRunning() is to be called by the application + when initialization completes and it can accept + stop request + */ + void SetRunning(void); + + /* + Stop() is to be called by the application to stop + the service + */ + void Stop(void); protected: LPSTR ServiceName; From d096079d330f77eebd3c3abef04236a9a4a08d7b Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Wed, 26 Nov 2008 09:28:17 +0100 Subject: [PATCH 02/11] Bug#37553: MySql Error Compare TimeDiff & Time We pretended that TIMEDIFF() would always return positive results; this gave strange results in comparisons of the TIMEDIFF(low,hi) =) sql/item_func.cc: signed now sql/item_timefunc.h: Functions such as TIMEDIFF() return signed results! The file-comments pretended we were doing that all along, anyway... sql/my_decimal.cc: heed sign when converting time to my_decimal; times may actually be negative! Needed for SELECT CAST(time('-73:42:12') AS DECIMAL); sql/mysql_priv.h: using signed for dates and times now --- mysql-test/r/func_sapdb.result | 12 ++++++++++++ mysql-test/t/func_sapdb.test | 17 +++++++++++++++++ sql/item_cmpfunc.cc | 14 +++++++------- sql/item_cmpfunc.h | 6 +++--- sql/item_func.cc | 2 +- sql/item_timefunc.h | 1 + sql/my_decimal.cc | 2 +- sql/mysql_priv.h | 4 ++-- 8 files changed, 44 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result index 4db0416bdce..a06d7004908 100644 --- a/mysql-test/r/func_sapdb.result +++ b/mysql-test/r/func_sapdb.result @@ -256,3 +256,15 @@ a select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f"); str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f") 2003-01-02 10:11:12.001200 +select timediff('2008-09-29 20:10:10','2008-09-30 20:10:10'),time('00:00:00'); +timediff('2008-09-29 20:10:10','2008-09-30 20:10:10') time('00:00:00') +-24:00:00 00:00:00 +select timediff('2008-09-29 20:10:10','2008-09-30 20:10:10')>time('00:00:00'); +timediff('2008-09-29 20:10:10','2008-09-30 20:10:10')>time('00:00:00') +0 +select timediff('2008-09-29 20:10:10','2008-09-30 20:10:10')time('00:00:00'); +select timediff('2008-09-29 20:10:10','2008-09-30 20:10:10')get_time(<ime); - value= !*is_null ? TIME_to_ulonglong_datetime(<ime) : 0; + value= !*is_null ? (longlong) TIME_to_ulonglong_datetime(<ime) : 0; } /* Do not cache GET_USER_VAR() function as its const_item() may return TRUE @@ -886,11 +886,11 @@ void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1) obtained value */ -ulonglong +longlong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, Item *warn_item, bool *is_null) { - ulonglong value= 0; + longlong value= 0; String buf, *str= 0; Item *item= **item_arg; @@ -925,7 +925,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, enum_field_types f_type= warn_item->field_type(); timestamp_type t_type= f_type == MYSQL_TYPE_DATE ? MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME; - value= get_date_from_str(thd, str, t_type, warn_item->name, &error); + value= (longlong) get_date_from_str(thd, str, t_type, warn_item->name, &error); /* If str did not contain a valid date according to the current SQL_MODE, get_date_from_str() has already thrown a warning, @@ -979,7 +979,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, int Arg_comparator::compare_datetime() { bool a_is_null, b_is_null; - ulonglong a_value, b_value; + longlong a_value, b_value; /* Get DATE/DATETIME/TIME value of the 'a' item. */ a_value= (*get_value_func)(thd, &a, &a_cache, *b, &a_is_null); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 1bd60ff37d9..db831c7030c 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -42,8 +42,8 @@ class Arg_comparator: public Sql_alloc bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE, CMP_DATE_WITH_STR, CMP_STR_WITH_DATE }; - ulonglong (*get_value_func)(THD *thd, Item ***item_arg, Item **cache_arg, - Item *warn_item, bool *is_null); + longlong (*get_value_func)(THD *thd, Item ***item_arg, Item **cache_arg, + Item *warn_item, bool *is_null); public: DTCollation cmp_collation; @@ -1028,7 +1028,7 @@ public: */ class cmp_item_datetime :public cmp_item { - ulonglong value; + longlong value; public: THD *thd; /* Item used for issuing warnings. */ diff --git a/sql/item_func.cc b/sql/item_func.cc index 45aa8e9bea0..8295bd41334 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2283,7 +2283,7 @@ uint Item_func_min_max::cmp_datetimes(ulonglong *value) { Item **arg= args + i; bool is_null; - ulonglong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null); + longlong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null); if ((null_value= args[i]->null_value)) return 0; if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0) diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 7960c03d2e5..81a6c3e98bd 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -408,6 +408,7 @@ public: { return save_time_in_field(field); } + bool result_as_longlong() { return TRUE; } }; diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index 31a5b09370a..a235edbd73c 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -216,7 +216,7 @@ my_decimal *date2my_decimal(MYSQL_TIME *ltime, my_decimal *dec) date = (ltime->year*100L + ltime->month)*100L + ltime->day; if (ltime->time_type > MYSQL_TIMESTAMP_DATE) date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second; - if (int2my_decimal(E_DEC_FATAL_ERROR, date, FALSE, dec)) + if (int2my_decimal(E_DEC_FATAL_ERROR, ltime->neg ? -date : date, FALSE, dec)) return dec; if (ltime->second_part) { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 1568f042b7e..d112c2b2f39 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1556,8 +1556,8 @@ void make_date(const DATE_TIME_FORMAT *format, const MYSQL_TIME *l_time, String *str); void make_time(const DATE_TIME_FORMAT *format, const MYSQL_TIME *l_time, String *str); -ulonglong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, - Item *warn_item, bool *is_null); +longlong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, + Item *warn_item, bool *is_null); int test_if_number(char *str,int *res,bool allow_wildcards); void change_byte(byte *,uint,char,char); From fbbdb613d77a673b225d23c46a84bb90520a5df0 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 27 Nov 2008 16:33:40 +0400 Subject: [PATCH 03/11] Bug#34825 perror on windows doesn't know about win32 error codes extended perror to enable printing of Win32 system errors extra/perror.c: extended perror to enable printing of Win32 system errors mysql-test/r/perror-win.result: test result mysql-test/t/perror-win.test: test case --- extra/perror.c | 40 ++++++++++++++++++++++++++++++++-- mysql-test/r/perror-win.result | 5 +++++ mysql-test/t/perror-win.test | 11 ++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 mysql-test/r/perror-win.result create mode 100644 mysql-test/t/perror-win.test diff --git a/extra/perror.c b/extra/perror.c index 4d19f4dd7eb..37d6b45c8dd 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -185,11 +185,36 @@ static const char *get_ha_error_msg(int code) } +#if defined(__WIN__) +static my_bool print_win_error_msg(DWORD error, my_bool verbose) +{ + LPTSTR s; + if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, 0, (LPTSTR)&s, 0, + NULL)) + { + if (verbose) + printf("Win32 error code %d: %s", error, s); + else + puts(s); + LocalFree(s); + return 0; + } + return 1; +} +#endif + + + int main(int argc,char *argv[]) { int error,code,found; const char *msg; char *unknown_error = 0; +#if defined(__WIN__) + my_bool skip_win_message= 0; +#endif MY_INIT(argv[0]); if (get_options(&argc,&argv)) @@ -286,8 +311,15 @@ int main(int argc,char *argv[]) /* Error message still not found, look in handler error codes */ if (!(msg=get_ha_error_msg(code))) { - fprintf(stderr,"Illegal error code: %d\n",code); - error=1; +#if defined(__WIN__) + if (!(skip_win_message= !print_win_error_msg((DWORD)code, verbose))) + { +#endif + fprintf(stderr,"Illegal error code: %d\n",code); + error=1; +#if defined(__WIN__) + } +#endif } else { @@ -298,6 +330,10 @@ int main(int argc,char *argv[]) puts(msg); } } +#if defined(__WIN__) + if (!skip_win_message) + print_win_error_msg((DWORD)code, verbose); +#endif } } diff --git a/mysql-test/r/perror-win.result b/mysql-test/r/perror-win.result new file mode 100644 index 00000000000..61e6fcaab4e --- /dev/null +++ b/mysql-test/r/perror-win.result @@ -0,0 +1,5 @@ +MySQL error code 150: Foreign key constraint is incorrectly formed +Win32 error code 150: System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed. +OS error code 23: Too many open files in system +Win32 error code 23: Data error (cyclic redundancy check). +Win32 error code 15000: The specified channel path is invalid. diff --git a/mysql-test/t/perror-win.test b/mysql-test/t/perror-win.test new file mode 100644 index 00000000000..56615e72a5a --- /dev/null +++ b/mysql-test/t/perror-win.test @@ -0,0 +1,11 @@ +# Windows-specific tests +--source include/windows.inc +--require r/have_perror.require +disable_query_log; +eval select LENGTH("$MY_PERROR") > 0 as "have_perror"; +enable_query_log; + + +--exec $MY_PERROR 150 +--exec $MY_PERROR 23 +--exec $MY_PERROR 15000 From 73960af037a68dd96ae636ff84b39007f825ab0e Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 27 Nov 2008 16:41:25 +0400 Subject: [PATCH 04/11] Bug#40365 Prepared statements may insert invalid dates. set DATE|DATETIME value to 0 if ALLOW_INVALID_DATES sql_mode is not enabled. sql/field.cc: set DATE|DATETIME value to 0 if ALLOW_INVALID_DATES sql_mode is not enabled. tests/mysql_client_test.c: test case --- sql/field.cc | 2 + tests/mysql_client_test.c | 81 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/sql/field.cc b/sql/field.cc index 3d3f698f912..8188b51d4d1 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5372,6 +5372,7 @@ int Field_newdate::store_time(MYSQL_TIME *ltime, timestamp_type time_type) { char buff[MAX_DATE_STRING_REP_LENGTH]; String str(buff, sizeof(buff), &my_charset_latin1); + tmp= 0; make_date((DATE_TIME_FORMAT *) 0, ltime, &str); set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, str.ptr(), str.length(), MYSQL_TIMESTAMP_DATE, 1); @@ -5608,6 +5609,7 @@ int Field_datetime::store_time(MYSQL_TIME *ltime,timestamp_type time_type) { char buff[MAX_DATE_STRING_REP_LENGTH]; String str(buff, sizeof(buff), &my_charset_latin1); + tmp= 0; make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str); set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, str.ptr(), str.length(), MYSQL_TIMESTAMP_DATETIME,1); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 9270a2a9d60..a9ec7eb358a 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16218,7 +16218,87 @@ static void test_bug38486(void) DBUG_VOID_RETURN; } +static void test_bug40365(void) +{ + uint rc, i, count= 1; + MYSQL_STMT *stmt= 0; + MYSQL_BIND my_bind[2]; + my_bool is_null[2]= {0}; + MYSQL_TIME tm[2]; + DBUG_ENTER("test_bug40365"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + rc= mysql_query(mysql, "CREATE TABLE t1(c1 DATETIME, \ + c2 DATE)"); + myquery(rc); + + stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 VALUES(?, ?)"); + check_stmt(stmt); + verify_param_count(stmt, 2); + + bzero((char*) my_bind, sizeof(my_bind)); + my_bind[0].buffer_type= MYSQL_TYPE_DATETIME; + my_bind[1].buffer_type= MYSQL_TYPE_DATE; + for (i= 0; i < (int) array_elements(my_bind); i++) + { + my_bind[i].buffer= (void *) &tm[i]; + my_bind[i].is_null= &is_null[i]; + } + + rc= mysql_stmt_bind_param(stmt, my_bind); + check_execute(stmt, rc); + + for (i= 0; i < (int) array_elements(my_bind); i++) + { + tm[i].neg= 0; + tm[i].second_part= 0; + tm[i].year= 2009; + tm[i].month= 2; + tm[i].day= 29; + tm[i].hour= 0; + tm[i].minute= 0; + tm[i].second= 0; + } + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_commit(mysql); + myquery(rc); + mysql_stmt_close(stmt); + + stmt= mysql_simple_prepare(mysql, "SELECT * FROM t1"); + check_stmt(stmt); + + rc= mysql_stmt_bind_result(stmt, my_bind); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_store_result(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + + if (!opt_silent) + fprintf(stdout, "\n"); + + for (i= 0; i < array_elements(my_bind); i++) + { + if (!opt_silent) + fprintf(stdout, "\ntime[%d]: %02d-%02d-%02d ", + i, tm[i].year, tm[i].month, tm[i].day); + DIE_UNLESS(tm[i].year == 0); + DIE_UNLESS(tm[i].month == 0); + DIE_UNLESS(tm[i].day == 0); + } + mysql_stmt_close(stmt); + + DBUG_VOID_RETURN; +} /* Read and parse arguments and MySQL options from my.cnf */ @@ -16514,6 +16594,7 @@ static struct my_tests_st my_tests[]= { { "test_bug31669", test_bug31669 }, { "test_bug32265", test_bug32265 }, { "test_bug38486", test_bug38486 }, + { "test_bug40365", test_bug40365 }, { 0, 0 } }; From 89d044062c1daa3f12358b003478cbaa5df91e3b Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 27 Nov 2008 17:57:34 +0400 Subject: [PATCH 05/11] Bug#37460 Assertion failed: !table->file || table->file->inited == handler::NONE enable uncacheable flag if we update a view with check option and check option has a subselect, otherwise, the check option can be evaluated after the subselect was freed as independent (See full_local in JOIN::join_free()) mysql-test/r/subselect.result: test result mysql-test/t/subselect.test: test case sql/mysql_priv.h: added UNCACHEABLE_CHECKOPTION flag sql/sql_update.cc: enable uncacheable flag if we update a view with check option and check option has a subselect, otherwise, the check option can be evaluated after the subselect was freed as independent (See full_local in JOIN::join_free()) --- mysql-test/r/subselect.result | 30 ++++++++++++++++++++++++++++++ mysql-test/t/subselect.test | 35 +++++++++++++++++++++++++++++++++++ sql/mysql_priv.h | 1 + sql/sql_update.cc | 26 ++++++++++++++++++++++++++ 4 files changed, 92 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 6eeb652e3c1..8830ea11f97 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4422,4 +4422,34 @@ id 2 3 DROP TABLE t1, t2; +CREATE TABLE t1 (id int); +CREATE TABLE t2 (id int, c int); +INSERT INTO t1 (id) VALUES (1); +INSERT INTO t2 (id) VALUES (1); +INSERT INTO t1 (id) VALUES (1); +INSERT INTO t2 (id) VALUES (1); +CREATE VIEW v1 AS +SELECT t2.c AS c FROM t1, t2 +WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; +UPDATE v1 SET c=1; +CREATE VIEW v2 (a,b) AS +SELECT t2.id, t2.c AS c FROM t1, t2 +WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; +INSERT INTO v2(a,b) VALUES (2,2); +ERROR HY000: CHECK OPTION failed 'test.v2' +INSERT INTO v2(a,b) VALUES (1,2); +SELECT * FROM v1; +c +1 +1 +1 +1 +2 +2 +CREATE VIEW v3 AS +SELECT t2.c AS c FROM t2 +WHERE 1 IN (SELECT id FROM t1) WITH CHECK OPTION; +DELETE FROM v3; +DROP VIEW v1,v2,v3; +DROP TABLE t1,t2; End of 5.0 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index d28e31fb545..ea911e4912d 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3325,4 +3325,39 @@ INSERT INTO t2 VALUES (2,1),(3,1); SELECT * FROM t1 i WHERE 1 IN (SELECT l.id2 FROM t2 l WHERE i.id=l.id1); DROP TABLE t1, t2; +# +# Bug#37460 Assertion failed: +# !table->file || table->file->inited == handler::NONE +# +CREATE TABLE t1 (id int); +CREATE TABLE t2 (id int, c int); + +INSERT INTO t1 (id) VALUES (1); +INSERT INTO t2 (id) VALUES (1); +INSERT INTO t1 (id) VALUES (1); +INSERT INTO t2 (id) VALUES (1); + +CREATE VIEW v1 AS + SELECT t2.c AS c FROM t1, t2 + WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; +UPDATE v1 SET c=1; + +CREATE VIEW v2 (a,b) AS + SELECT t2.id, t2.c AS c FROM t1, t2 + WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; + +--error 1369 +INSERT INTO v2(a,b) VALUES (2,2); +INSERT INTO v2(a,b) VALUES (1,2); +SELECT * FROM v1; + +CREATE VIEW v3 AS + SELECT t2.c AS c FROM t2 + WHERE 1 IN (SELECT id FROM t1) WITH CHECK OPTION; + +DELETE FROM v3; + +DROP VIEW v1,v2,v3; +DROP TABLE t1,t2; + --echo End of 5.0 tests. diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 1568f042b7e..75c95834ac9 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -435,6 +435,7 @@ MY_LOCALE *my_locale_by_number(uint number); #define UNCACHEABLE_PREPARE 16 /* For uncorrelated SELECT in an UNION with some correlated SELECTs */ #define UNCACHEABLE_UNITED 32 +#define UNCACHEABLE_CHECKOPTION 64 /* Used to check GROUP BY list in the MODE_ONLY_FULL_GROUP_BY mode */ #define UNDEF_POS (-1) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index eb4e9b7ed73..f15db220a3b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1249,6 +1249,32 @@ multi_update::initialize_tables(JOIN *join) } } + /* + enable uncacheable flag if we update a view with check option + and check option has a subselect, otherwise, the check option + can be evaluated after the subselect was freed as independent + (See full_local in JOIN::join_free()). + */ + if (table_ref->check_option && !join->select_lex->uncacheable) + { + SELECT_LEX_UNIT *tmp_unit; + SELECT_LEX *sl; + for (tmp_unit= join->select_lex->first_inner_unit(); + tmp_unit; + tmp_unit= tmp_unit->next_unit()) + { + for (sl= tmp_unit->first_select(); sl; sl= sl->next_select()) + { + if (sl->master_unit()->item) + { + join->select_lex->uncacheable|= UNCACHEABLE_CHECKOPTION; + goto loop_end; + } + } + } + } +loop_end: + if (table == first_table_for_update && table_ref->check_option) { table_map unupdated_tables= table_ref->check_option->used_tables() & From 3a3d3527a333f83eb454efa8fd1e7f34e06b578c Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 27 Nov 2008 18:26:22 +0400 Subject: [PATCH 06/11] removed unused variable --- tests/mysql_client_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index a9ec7eb358a..ee3a053f8bd 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16220,7 +16220,7 @@ static void test_bug38486(void) static void test_bug40365(void) { - uint rc, i, count= 1; + uint rc, i; MYSQL_STMT *stmt= 0; MYSQL_BIND my_bind[2]; my_bool is_null[2]= {0}; From 1182c0979a5d9acc345c2cba83cac0aa32d42bca Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 27 Nov 2008 18:54:23 +0400 Subject: [PATCH 07/11] Bug#37284 Crash in Field_string::type() The bug is repeatable with latest(1.0.1) InnoDB plugin on Linux, Win, If MySQL is compiled with valgrind there are errors about using of uninitialized variable(orig_table). The fix is to set field->orig_table correct value. mysql-test/r/innodb_mysql.result: test result mysql-test/t/innodb_mysql.test: test case sql/sql_base.cc: set field->orig_table to 'table' value because it may be bogus and it leads to crash on Field_string::type() function. --- mysql-test/r/innodb_mysql.result | 6 ++++++ mysql-test/t/innodb_mysql.test | 11 +++++++++++ sql/sql_base.cc | 3 +++ 3 files changed, 20 insertions(+) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 47fa331c9ab..682cc2e82e2 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1261,4 +1261,10 @@ a b c 5 1 1 4 1 1 DROP TABLE t1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a char(50)) ENGINE=InnoDB; +CREATE INDEX i1 on t1 (a(3)); +SELECT * FROM t1 WHERE a = 'abcde'; +a +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index e15d1aee08a..b4fc425cb7c 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -1014,4 +1014,15 @@ SELECT a, b, c FROM t1 WHERE b = 1 ORDER BY a DESC LIMIT 5; DROP TABLE t1; +# +# Bug#37284 Crash in Field_string::type() +# +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings +CREATE TABLE t1 (a char(50)) ENGINE=InnoDB; +CREATE INDEX i1 on t1 (a(3)); +SELECT * FROM t1 WHERE a = 'abcde'; +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 873a3eac24e..881c6a421e8 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2102,7 +2102,10 @@ bool reopen_table(TABLE *table,bool locked) for (key=0 ; key < table->s->keys ; key++) { for (part=0 ; part < table->key_info[key].usable_key_parts ; part++) + { table->key_info[key].key_part[part].field->table= table; + table->key_info[key].key_part[part].field->orig_table= table; + } } if (table->triggers) table->triggers->set_table(table); From 78119b2d04457abe94f2a0a9f3d887c0eb9210a5 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Fri, 28 Nov 2008 14:50:13 +0400 Subject: [PATCH 08/11] pushbuild failure fixes mysql-test/r/perror-win.result: pushbuild failure fix mysql-test/t/perror-win.test: pushbuild failure fix sql/item_func.cc: pushbuild failure fix --- mysql-test/r/perror-win.result | 7 ++++--- mysql-test/t/perror-win.test | 9 ++++++--- sql/item_func.cc | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/perror-win.result b/mysql-test/r/perror-win.result index 61e6fcaab4e..8d3026bc331 100644 --- a/mysql-test/r/perror-win.result +++ b/mysql-test/r/perror-win.result @@ -1,5 +1,6 @@ MySQL error code 150: Foreign key constraint is incorrectly formed -Win32 error code 150: System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed. +Win32 error code 150: System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed. OS error code 23: Too many open files in system -Win32 error code 23: Data error (cyclic redundancy check). -Win32 error code 15000: The specified channel path is invalid. +Win32 error code 23: Data error (cyclic redundancy check). +Win32 error code 500: User profile cannot be loaded. +Illegal error code: 30000 diff --git a/mysql-test/t/perror-win.test b/mysql-test/t/perror-win.test index 56615e72a5a..2b38c5fad54 100644 --- a/mysql-test/t/perror-win.test +++ b/mysql-test/t/perror-win.test @@ -6,6 +6,9 @@ eval select LENGTH("$MY_PERROR") > 0 as "have_perror"; enable_query_log; ---exec $MY_PERROR 150 ---exec $MY_PERROR 23 ---exec $MY_PERROR 15000 +--exec $MY_PERROR 150 2>&1 +--exec $MY_PERROR 23 2>&1 +--exec $MY_PERROR 500 2>&1 +--error 1 +--exec $MY_PERROR 30000 2>&1 + diff --git a/sql/item_func.cc b/sql/item_func.cc index 8295bd41334..c0d08d9b213 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2275,7 +2275,7 @@ void Item_func_min_max::fix_length_and_dec() uint Item_func_min_max::cmp_datetimes(ulonglong *value) { - ulonglong min_max; + longlong min_max; uint min_max_idx= 0; LINT_INIT(min_max); From fef07511e3c950438931e23eb286bf5638345700 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Fri, 28 Nov 2008 17:12:43 +0400 Subject: [PATCH 09/11] error code is changed to satisfy Win NT --- mysql-test/r/perror-win.result | 2 +- mysql-test/t/perror-win.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/perror-win.result b/mysql-test/r/perror-win.result index 8d3026bc331..1d42235cc14 100644 --- a/mysql-test/r/perror-win.result +++ b/mysql-test/r/perror-win.result @@ -2,5 +2,5 @@ MySQL error code 150: Foreign key constraint is incorrectly formed Win32 error code 150: System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed. OS error code 23: Too many open files in system Win32 error code 23: Data error (cyclic redundancy check). -Win32 error code 500: User profile cannot be loaded. +Win32 error code 1062: The service has not been started. Illegal error code: 30000 diff --git a/mysql-test/t/perror-win.test b/mysql-test/t/perror-win.test index 2b38c5fad54..cc09b8527be 100644 --- a/mysql-test/t/perror-win.test +++ b/mysql-test/t/perror-win.test @@ -8,7 +8,7 @@ enable_query_log; --exec $MY_PERROR 150 2>&1 --exec $MY_PERROR 23 2>&1 ---exec $MY_PERROR 500 2>&1 +--exec $MY_PERROR 1062 2>&1 --error 1 --exec $MY_PERROR 30000 2>&1 From 8e688a7a0246d16a8c636262872a6e7b06376b99 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 28 Nov 2008 16:25:16 +0200 Subject: [PATCH 10/11] Bug #37339: SHOW VARIABLES not working properly with multi-byte datadir The SHOW VARIABLES LIKE .../SELECT @@/SELECT ... FROM INFORMATION_SCHEMA.VARIABLES were assuming that all the system variables are in system charset (UTF-8). However the variables that are settable through command line will have a different character set (character_set_filesystem). Fixed the server to remember the correct character set of basedir, datadir, tmpdir, ssl, plugin_dir, slave_load_tmpdir, innodb variables; init_connect and init_slave variables and use it when processing data. mysql-test/r/ctype_filesystem.result: Bug #37339: test case (should be in utf-8) mysql-test/t/ctype_filesystem-master.opt: Bug #37339: test case (should be in ISO-8859-1) mysql-test/t/ctype_filesystem.test: Bug #37339: test case sql/mysqld.cc: Bug #37339: remember the correct character set for init_slave and init_connect sql/set_var.cc: Bug #37339: - remember the character set of the relevant variables - implement storing and using the correct character set sql/set_var.h: Bug #37339: implement storing and using the correct character set sql/sql_show.cc: Bug #37339: implement storing and using the correct character set --- mysql-test/r/ctype_filesystem.result | 11 ++++ mysql-test/t/ctype_filesystem-master.opt | 2 + mysql-test/t/ctype_filesystem.test | 5 ++ sql/mysqld.cc | 2 + sql/set_var.cc | 67 ++++++++++++++++-------- sql/set_var.h | 47 ++++++++++++++++- sql/sql_show.cc | 10 ++-- 7 files changed, 116 insertions(+), 28 deletions(-) create mode 100644 mysql-test/r/ctype_filesystem.result create mode 100644 mysql-test/t/ctype_filesystem-master.opt create mode 100644 mysql-test/t/ctype_filesystem.test diff --git a/mysql-test/r/ctype_filesystem.result b/mysql-test/r/ctype_filesystem.result new file mode 100644 index 00000000000..8a8f0f7f8cc --- /dev/null +++ b/mysql-test/r/ctype_filesystem.result @@ -0,0 +1,11 @@ +SET CHARACTER SET utf8; +SHOW VARIABLES like 'character_sets_dir'; +Variable_name Value +character_sets_dir /ß/ +SHOW VARIABLES like 'character_set_filesystem'; +Variable_name Value +character_set_filesystem latin1 +SHOW VARIABLES like 'character_set_client'; +Variable_name Value +character_set_client utf8 +SET CHARACTER SET default; diff --git a/mysql-test/t/ctype_filesystem-master.opt b/mysql-test/t/ctype_filesystem-master.opt new file mode 100644 index 00000000000..cb3427571b5 --- /dev/null +++ b/mysql-test/t/ctype_filesystem-master.opt @@ -0,0 +1,2 @@ +--character-sets-dir=/ß +--character-set-filesystem=latin1 diff --git a/mysql-test/t/ctype_filesystem.test b/mysql-test/t/ctype_filesystem.test new file mode 100644 index 00000000000..30b1607008b --- /dev/null +++ b/mysql-test/t/ctype_filesystem.test @@ -0,0 +1,5 @@ +SET CHARACTER SET utf8; +SHOW VARIABLES like 'character_sets_dir'; +SHOW VARIABLES like 'character_set_filesystem'; +SHOW VARIABLES like 'character_set_client'; +SET CHARACTER SET default; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c3e5449b22b..dd2bebfdd2d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3035,12 +3035,14 @@ static int init_common_variables(const char *conf_file_name, int argc, sys_init_connect.value_length= strlen(opt_init_connect); else sys_init_connect.value=my_strdup("",MYF(0)); + sys_init_connect.is_os_charset= TRUE; sys_init_slave.value_length= 0; if ((sys_init_slave.value= opt_init_slave)) sys_init_slave.value_length= strlen(opt_init_slave); else sys_init_slave.value=my_strdup("",MYF(0)); + sys_init_slave.is_os_charset= TRUE; if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1)) return 1; diff --git a/sql/set_var.cc b/sql/set_var.cc index 6bc19f2e6eb..59741e5683d 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -138,7 +138,7 @@ sys_var_thd_ulong sys_auto_increment_offset("auto_increment_offset", sys_var_bool_ptr sys_automatic_sp_privileges("automatic_sp_privileges", &sp_automatic_privileges); -sys_var_const_str sys_basedir("basedir", mysql_home); +sys_var_const_os_str sys_basedir("basedir", mysql_home); sys_var_long_ptr sys_binlog_cache_size("binlog_cache_size", &binlog_cache_size); sys_var_thd_ulong sys_bulk_insert_buff_size("bulk_insert_buffer_size", @@ -151,6 +151,8 @@ sys_var_character_set_client sys_character_set_client("character_set_client"); sys_var_character_set_connection sys_character_set_connection("character_set_connection"); sys_var_character_set_results sys_character_set_results("character_set_results"); sys_var_character_set_filesystem sys_character_set_filesystem("character_set_filesystem"); +sys_var_const_os_str sys_character_sets_dir("character_sets_dir", + mysql_charsets_dir); sys_var_thd_ulong sys_completion_type("completion_type", &SV::completion_type, check_completion_type, @@ -162,7 +164,7 @@ sys_var_long_ptr sys_concurrent_insert("concurrent_insert", &myisam_concurrent_insert); sys_var_long_ptr sys_connect_timeout("connect_timeout", &connect_timeout); -sys_var_const_str sys_datadir("datadir", mysql_real_data_home); +sys_var_const_os_str sys_datadir("datadir", mysql_real_data_home); sys_var_enum sys_delay_key_write("delay_key_write", &delay_key_write_options, &delay_key_write_typelib, @@ -311,6 +313,7 @@ sys_var_thd_ulong sys_optimizer_prune_level("optimizer_prune_level", &SV::optimizer_prune_level); sys_var_thd_ulong sys_optimizer_search_depth("optimizer_search_depth", &SV::optimizer_search_depth); +sys_var_const_os_str sys_plugin_dir("plugin_dir", opt_plugin_dir); sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size", &SV::preload_buff_size); sys_var_thd_ulong sys_read_buff_size("read_buffer_size", @@ -338,7 +341,7 @@ sys_var_thd_ulong sys_query_alloc_block_size("query_alloc_block_size", sys_var_thd_ulong sys_query_prealloc_size("query_prealloc_size", &SV::query_prealloc_size, 0, fix_thd_mem_root); -sys_var_readonly sys_tmpdir("tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir); +sys_var_readonly_os sys_tmpdir("tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir); sys_var_thd_ulong sys_trans_alloc_block_size("transaction_alloc_block_size", &SV::trans_alloc_block_size, 0, fix_trans_mem_root); @@ -363,9 +366,11 @@ sys_var_bool_ptr sys_secure_auth("secure_auth", &opt_secure_auth); sys_var_const_str_ptr sys_secure_file_priv("secure_file_priv", &opt_secure_file_priv); sys_var_long_ptr sys_server_id("server_id", &server_id, fix_server_id); +#ifdef HAVE_REPLICATION sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol", &opt_slave_compressed_protocol); -#ifdef HAVE_REPLICATION +sys_var_const_os_str_ptr sys_slave_load_tmpdir("slave_load_tmpdir", + &slave_load_tmpdir); sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout", &slave_net_timeout); sys_var_long_ptr sys_slave_trans_retries("slave_transaction_retries", @@ -380,17 +385,17 @@ sys_var_thd_sql_mode sys_sql_mode("sql_mode", #ifdef HAVE_OPENSSL extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher, *opt_ssl_key; -sys_var_const_str_ptr sys_ssl_ca("ssl_ca", &opt_ssl_ca); -sys_var_const_str_ptr sys_ssl_capath("ssl_capath", &opt_ssl_capath); -sys_var_const_str_ptr sys_ssl_cert("ssl_cert", &opt_ssl_cert); -sys_var_const_str_ptr sys_ssl_cipher("ssl_cipher", &opt_ssl_cipher); -sys_var_const_str_ptr sys_ssl_key("ssl_key", &opt_ssl_key); +sys_var_const_os_str_ptr sys_ssl_ca("ssl_ca", &opt_ssl_ca); +sys_var_const_os_str_ptr sys_ssl_capath("ssl_capath", &opt_ssl_capath); +sys_var_const_os_str_ptr sys_ssl_cert("ssl_cert", &opt_ssl_cert); +sys_var_const_os_str_ptr sys_ssl_cipher("ssl_cipher", &opt_ssl_cipher); +sys_var_const_os_str_ptr sys_ssl_key("ssl_key", &opt_ssl_key); #else -sys_var_const_str sys_ssl_ca("ssl_ca", NULL); -sys_var_const_str sys_ssl_capath("ssl_capath", NULL); -sys_var_const_str sys_ssl_cert("ssl_cert", NULL); -sys_var_const_str sys_ssl_cipher("ssl_cipher", NULL); -sys_var_const_str sys_ssl_key("ssl_key", NULL); +sys_var_const_os_str sys_ssl_ca("ssl_ca", NULL); +sys_var_const_os_str sys_ssl_capath("ssl_capath", NULL); +sys_var_const_os_str sys_ssl_cert("ssl_cert", NULL); +sys_var_const_os_str sys_ssl_cipher("ssl_cipher", NULL); +sys_var_const_os_str sys_ssl_key("ssl_key", NULL); #endif sys_var_thd_enum sys_updatable_views_with_limit("updatable_views_with_limit", @@ -460,6 +465,14 @@ sys_var_long_ptr sys_innodb_commit_concurrency("innodb_commit_concurrency", sys_var_long_ptr sys_innodb_flush_log_at_trx_commit( "innodb_flush_log_at_trx_commit", &srv_flush_log_at_trx_commit); +sys_var_const_os_str_ptr sys_innodb_data_file_path("innodb_data_file_path", + &innobase_data_file_path); +sys_var_const_os_str_ptr sys_innodb_data_home_dir("innodb_data_home_dir", + &innobase_data_home_dir); +sys_var_const_os_str_ptr sys_innodb_log_arch_dir("innodb_log_arch_dir", + &innobase_log_arch_dir); +sys_var_const_os_str_ptr sys_innodb_log_group_home_dir("innodb_log_group_home_dir", + &innobase_log_group_home_dir); #endif /* Condition pushdown to storage engine */ @@ -844,7 +857,7 @@ struct show_var_st init_vars[]= { {sys_character_set_results.name,(char*) &sys_character_set_results, SHOW_SYS}, {sys_character_set_server.name, (char*) &sys_character_set_server,SHOW_SYS}, {sys_charset_system.name, (char*) &sys_charset_system, SHOW_SYS}, - {"character_sets_dir", mysql_charsets_dir, SHOW_CHAR}, + {sys_character_sets_dir.name, (char *) &sys_character_sets_dir, SHOW_SYS}, {sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS}, {sys_collation_database.name,(char*) &sys_collation_database, SHOW_SYS}, {sys_collation_server.name,(char*) &sys_collation_server, SHOW_SYS}, @@ -905,8 +918,8 @@ struct show_var_st init_vars[]= { {"innodb_checksums", (char*) &innobase_use_checksums, SHOW_MY_BOOL}, {sys_innodb_commit_concurrency.name, (char*) &sys_innodb_commit_concurrency, SHOW_SYS}, {sys_innodb_concurrency_tickets.name, (char*) &sys_innodb_concurrency_tickets, SHOW_SYS}, - {"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR}, - {"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR}, + {sys_innodb_data_file_path.name, (char*) &sys_innodb_data_file_path, SHOW_SYS}, + {sys_innodb_data_home_dir.name, (char*) &sys_innodb_data_home_dir, SHOW_SYS}, {"innodb_adaptive_hash_index", (char*) &innobase_adaptive_hash_index, SHOW_MY_BOOL}, {"innodb_doublewrite", (char*) &innobase_use_doublewrite, SHOW_MY_BOOL}, {sys_innodb_fast_shutdown.name,(char*) &sys_innodb_fast_shutdown, SHOW_SYS}, @@ -917,12 +930,12 @@ struct show_var_st init_vars[]= { {"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG }, {"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG }, {"innodb_locks_unsafe_for_binlog", (char*) &innobase_locks_unsafe_for_binlog, SHOW_MY_BOOL}, - {"innodb_log_arch_dir", (char*) &innobase_log_arch_dir, SHOW_CHAR_PTR}, + {sys_innodb_log_arch_dir.name, (char*) &sys_innodb_log_arch_dir, SHOW_SYS}, {"innodb_log_archive", (char*) &innobase_log_archive, SHOW_MY_BOOL}, {"innodb_log_buffer_size", (char*) &innobase_log_buffer_size, SHOW_LONG }, {"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONGLONG}, {"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG}, - {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR}, + {sys_innodb_log_group_home_dir.name, (char*) &sys_innodb_log_group_home_dir, SHOW_SYS}, {sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS}, {sys_innodb_max_purge_lag.name, (char*) &sys_innodb_max_purge_lag, SHOW_SYS}, {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG}, @@ -1026,7 +1039,7 @@ struct show_var_st init_vars[]= { {sys_optimizer_search_depth.name,(char*) &sys_optimizer_search_depth, SHOW_SYS}, {"pid_file", (char*) pidfile_name, SHOW_CHAR}, - {"plugin_dir", (char*) opt_plugin_dir, SHOW_CHAR}, + {sys_plugin_dir.name, (char*) &sys_plugin_dir, SHOW_SYS}, {"port", (char*) &mysqld_port, SHOW_INT}, {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, @@ -1068,7 +1081,7 @@ struct show_var_st init_vars[]= { #ifdef HAVE_REPLICATION {sys_slave_compressed_protocol.name, (char*) &sys_slave_compressed_protocol, SHOW_SYS}, - {"slave_load_tmpdir", (char*) &slave_load_tmpdir, SHOW_CHAR_PTR}, + {sys_slave_load_tmpdir.name,(char*) &sys_slave_load_tmpdir, SHOW_SYS}, {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS}, {"slave_skip_errors", (char*) &slave_error_mask, SHOW_SLAVE_SKIP_ERRORS}, {sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries, SHOW_SYS}, @@ -1175,6 +1188,7 @@ bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex, old_value= var_str->value; var_str->value= res; var_str->value_length= new_length; + var_str->is_os_charset= FALSE; rw_unlock(var_mutex); my_free(old_value, MYF(MY_ALLOW_ZERO_PTR)); return 0; @@ -1914,11 +1928,11 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) char *str= (char*) value_ptr(thd, var_type, base); if (str) tmp= new Item_string(str, strlen(str), - system_charset_info, DERIVATION_SYSCONST); + charset(thd), DERIVATION_SYSCONST); else { tmp= new Item_null(); - tmp->collation.set(system_charset_info, DERIVATION_SYSCONST); + tmp->collation.set(charset(thd), DERIVATION_SYSCONST); } pthread_mutex_unlock(&LOCK_global_system_variables); return tmp; @@ -1930,6 +1944,13 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) } +CHARSET_INFO *sys_var::charset(THD *thd) +{ + return is_os_charset ? thd->variables.character_set_filesystem : + system_charset_info; +} + + bool sys_var_thd_enum::update(THD *thd, set_var *var) { if (var->type == OPT_GLOBAL) diff --git a/sql/set_var.h b/sql/set_var.h index c37cc400e43..f43d3b75cee 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -46,9 +46,17 @@ public: sys_after_update_func after_update; bool no_support_one_shot; + /* + true if the value is in character_set_filesystem, + false otherwise. + Note that we can't use a pointer to the charset as the system var is + instantiated in global scope and the charset pointers are initialized + later. + */ + bool is_os_charset; sys_var(const char *name_arg, sys_after_update_func func= NULL) :name(name_arg), after_update(func) - , no_support_one_shot(1) + , no_support_one_shot(1), is_os_charset(FALSE) {} virtual ~sys_var() {} virtual bool check(THD *thd, set_var *var); @@ -68,6 +76,7 @@ public: Item *item(THD *thd, enum_var_type type, LEX_STRING *base); virtual bool is_struct() { return 0; } virtual bool is_readonly() const { return 0; } + CHARSET_INFO *charset(THD *thd); }; @@ -247,6 +256,17 @@ public: }; +class sys_var_const_os_str: public sys_var_const_str +{ +public: + sys_var_const_os_str(const char *name_arg, const char *value_arg) + :sys_var_const_str(name_arg, value_arg) + { + is_os_charset= TRUE; + } +}; + + class sys_var_const_str_ptr :public sys_var { public: @@ -276,6 +296,17 @@ public: }; +class sys_var_const_os_str_ptr :public sys_var_const_str_ptr +{ +public: + sys_var_const_os_str_ptr(const char *name_arg, char **value_arg) + :sys_var_const_str_ptr(name_arg, value_arg) + { + is_os_charset= TRUE; + } +}; + + class sys_var_enum :public sys_var { uint *value; @@ -791,6 +822,20 @@ public: bool is_readonly() const { return 1; } }; + +class sys_var_readonly_os: public sys_var_readonly +{ +public: + sys_var_readonly_os(const char *name_arg, enum_var_type type, + SHOW_TYPE show_type_arg, + sys_value_ptr_func value_ptr_func_arg) + :sys_var_readonly(name_arg, type, show_type_arg, value_ptr_func_arg) + { + is_os_charset= TRUE; + } +}; + + class sys_var_thd_time_zone :public sys_var_thd { public: diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5a4772e9847..4e3d209f674 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1441,6 +1441,7 @@ static bool show_status_array(THD *thd, const char *wild, char name_buffer[80]; int len; LEX_STRING null_lex_str; + CHARSET_INFO *charset= system_charset_info; DBUG_ENTER("show_status_array"); null_lex_str.str= 0; // For sys_var->value_ptr() @@ -1469,9 +1470,10 @@ static bool show_status_array(THD *thd, const char *wild, long nr; if (show_type == SHOW_SYS) { - show_type= ((sys_var*) value)->show_type(); - value= (char*) ((sys_var*) value)->value_ptr(thd, value_type, - &null_lex_str); + sys_var *var= ((sys_var *) value); + show_type= var->show_type(); + value= (char*) var->value_ptr(thd, value_type, &null_lex_str); + charset= var->charset(thd); } pos= end= buff; @@ -1794,7 +1796,7 @@ static bool show_status_array(THD *thd, const char *wild, restore_record(table, s->default_values); table->field[0]->store(name_buffer, strlen(name_buffer), system_charset_info); - table->field[1]->store(pos, (uint32) (end - pos), system_charset_info); + table->field[1]->store(pos, (uint32) (end - pos), charset); if (schema_table_store_record(thd, table)) DBUG_RETURN(TRUE); } From 41ccbefcc4cbf75c18e37746bd52617f6c9794b9 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Fri, 28 Nov 2008 20:13:12 +0400 Subject: [PATCH 11/11] Bug #33461: SELECT ... FROM USE INDEX (...) throws an error Even after the fix for bug 28701 visible behaviors of SELECT FROM a view and SELECT FROM a regular table are little bit different: 1. "SELECT FROM regular table USE/FORCE/IGNORE(non existent index)" fails with a "ERROR 1176 (HY000): Key '...' doesn't exist in table '...'" 2. "SELECT FROM view USING/FORCE/IGNORE(any index)" fails with a "ERROR 1221 (HY000): Incorrect usage of USE/IGNORE INDEX and VIEW". OTOH "SHOW INDEX FROM view" always returns empty result set, so from the point of same behaviour view we trying to use/ignore non existent index. To harmonize the behaviour of USE/FORCE/IGNORE(index) clauses in SELECT from a view and from a regular table the "ERROR 1221 (HY000): Incorrect usage of USE/IGNORE INDEX and VIEW" message has been replaced with the "ERROR 1176 (HY000): Key '...' doesn't exist in table '...'" message like for tables and non existent keys. mysql-test/r/view.result: Added test case for bug #33461. Updated test case for bug 28701. mysql-test/t/view.test: Added test case for bug #33461. Updated test case for bug 28701. sql/sql_view.cc: Bug #33461: SELECT ... FROM USE INDEX (...) throws an error To harmonize the behaviour of USE/FORCE/IGNORE(index) clauses in SELECT from a view and from a regular table the "ERROR 1221 (HY000): Incorrect usage of USE/IGNORE INDEX and VIEW" message has been replaced with the "ERROR 1176 (HY000): Key '...' doesn't exist in table '...'" message like for tables and non existent keys. --- mysql-test/r/view.result | 33 +++++++++++++++++++++++++++++---- mysql-test/t/view.test | 34 ++++++++++++++++++++++++++++++---- sql/sql_view.cc | 13 +++++++------ 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 8cbe3fc36cf..311b77e7a99 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -625,7 +625,7 @@ drop table t1; create table t1 (a int, b int); create view v1 as select a, sum(b) from t1 group by a; select b from v1 use index (some_index) where b=1; -ERROR HY000: Incorrect usage of USE INDEX and VIEW +ERROR HY000: Key 'some_index' doesn't exist in table 'v1' drop view v1; drop table t1; create table t1 (col1 char(5),col2 char(5)); @@ -3567,11 +3567,11 @@ CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2); CREATE VIEW v1 AS SELECT * FROM t1; SELECT * FROM v1 USE KEY(non_existant); -ERROR HY000: Incorrect usage of USE INDEX and VIEW +ERROR HY000: Key 'non_existant' doesn't exist in table 'v1' SELECT * FROM v1 FORCE KEY(non_existant); -ERROR HY000: Incorrect usage of FORCE INDEX and VIEW +ERROR HY000: Key 'non_existant' doesn't exist in table 'v1' SELECT * FROM v1 IGNORE KEY(non_existant); -ERROR HY000: Incorrect usage of IGNORE INDEX and VIEW +ERROR HY000: Key 'non_existant' doesn't exist in table 'v1' DROP VIEW v1; DROP TABLE t1; CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, b INT NOT NULL DEFAULT 0, @@ -3679,6 +3679,31 @@ DROP VIEW v1; CREATE VIEW v1 AS SELECT 1; DROP VIEW v1; +CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT, INDEX (c2)); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +SELECT * FROM t1 USE INDEX (PRIMARY) WHERE c1=2; +c1 c2 +2 2 +SELECT * FROM t1 USE INDEX (c2) WHERE c2=2; +c1 c2 +2 2 +CREATE VIEW v1 AS SELECT c1, c2 FROM t1; +SHOW INDEX FROM v1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +SELECT * FROM v1 USE INDEX (PRIMARY) WHERE c1=2; +ERROR HY000: Key 'PRIMARY' doesn't exist in table 'v1' +SELECT * FROM v1 FORCE INDEX (PRIMARY) WHERE c1=2; +ERROR HY000: Key 'PRIMARY' doesn't exist in table 'v1' +SELECT * FROM v1 IGNORE INDEX (PRIMARY) WHERE c1=2; +ERROR HY000: Key 'PRIMARY' doesn't exist in table 'v1' +SELECT * FROM v1 USE INDEX (c2) WHERE c2=2; +ERROR HY000: Key 'c2' doesn't exist in table 'v1' +SELECT * FROM v1 FORCE INDEX (c2) WHERE c2=2; +ERROR HY000: Key 'c2' doesn't exist in table 'v1' +SELECT * FROM v1 IGNORE INDEX (c2) WHERE c2=2; +ERROR HY000: Key 'c2' doesn't exist in table 'v1' +DROP VIEW v1; +DROP TABLE t1; # ----------------------------------------------------------------- # -- End of 5.0 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index bcf31a4501d..2892ee7dd69 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -510,7 +510,7 @@ drop table t1; # create table t1 (a int, b int); create view v1 as select a, sum(b) from t1 group by a; ---error ER_WRONG_USAGE +--error ER_KEY_DOES_NOT_EXITS select b from v1 use index (some_index) where b=1; drop view v1; drop table t1; @@ -3424,11 +3424,11 @@ drop table t1; CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2); CREATE VIEW v1 AS SELECT * FROM t1; ---error ER_WRONG_USAGE +--error ER_KEY_DOES_NOT_EXITS SELECT * FROM v1 USE KEY(non_existant); ---error ER_WRONG_USAGE +--error ER_KEY_DOES_NOT_EXITS SELECT * FROM v1 FORCE KEY(non_existant); ---error ER_WRONG_USAGE +--error ER_KEY_DOES_NOT_EXITS SELECT * FROM v1 IGNORE KEY(non_existant); DROP VIEW v1; @@ -3568,6 +3568,32 @@ DROP VIEW v1; CREATE VIEW v1 AS SELECT 1; DROP VIEW v1; +# +# Bug #33461: SELECT ... FROM USE INDEX (...) throws an error +# + +CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT, INDEX (c2)); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +SELECT * FROM t1 USE INDEX (PRIMARY) WHERE c1=2; +SELECT * FROM t1 USE INDEX (c2) WHERE c2=2; + +CREATE VIEW v1 AS SELECT c1, c2 FROM t1; +SHOW INDEX FROM v1; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 USE INDEX (PRIMARY) WHERE c1=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 FORCE INDEX (PRIMARY) WHERE c1=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 IGNORE INDEX (PRIMARY) WHERE c1=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 USE INDEX (c2) WHERE c2=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 FORCE INDEX (c2) WHERE c2=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 IGNORE INDEX (c2) WHERE c2=2; + +DROP VIEW v1; +DROP TABLE t1; --echo # ----------------------------------------------------------------- --echo # -- End of 5.0 tests. diff --git a/sql/sql_view.cc b/sql/sql_view.cc index f65a62bed75..5bd3c09a289 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -980,13 +980,14 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, DBUG_RETURN(0); } - if (table->use_index || table->ignore_index) + List *index_list= table->use_index ? table->use_index + : table->ignore_index; + if (index_list) { - my_error(ER_WRONG_USAGE, MYF(0), - table->ignore_index ? "IGNORE INDEX" : - (table->force_index ? "FORCE INDEX" : "USE INDEX"), - "VIEW"); - DBUG_RETURN(TRUE); + DBUG_ASSERT(index_list->head()); // should never fail + my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), index_list->head()->c_ptr_safe(), + table->table_name); + DBUG_RETURN(TRUE); } /* check loop via view definition */