From 4eec3b087de468382f6c4e9eb2397cacfc18821f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 15 Oct 2007 10:34:34 +0400 Subject: Fix for bug #30453: String not cast to int correctly. Problem: my_strntoull10rnd_8bit() handled incorrectly cases when the input string contains a decimal point and is long enough to overrun the 'unsigned long long' type. The position of the decimal point was not taken into account which resulted in miscalculated numbers and truncation to appropriate SQL data type limits. Solution: Fix my_strntoull10rnd_8bit() to take the position of a decimal point into account in such cases. mysql-test/r/insert.result: Added a test case for bug #30453. mysql-test/t/insert.test: Added a test case for bug #30453. strings/ctype-simple.c: In cases when the 'unsigned long long' type is overrun by the input string and a decimal point has occurred, adjust the 'shift' according to the position of the decimal point and skip all subsequent digits. --- mysql-test/r/insert.result | 14 ++++++++++++++ mysql-test/t/insert.test | 15 +++++++++++++++ strings/ctype-simple.c | 14 +++++++++----- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result index 8a0a3ba848c..e1cad814226 100644 --- a/mysql-test/r/insert.result +++ b/mysql-test/r/insert.result @@ -461,4 +461,18 @@ i 2 2 DROP TABLE t1, t2; +CREATE TABLE t1 (c1 INT NOT NULL); +INSERT INTO t1 VALUES(4188.32999999999992724042385816574096679687500), +('4188.32999999999992724042385816574096679687500'), (4188); +SELECT * FROM t1; +c1 +4188 +4188 +4188 +CREATE TABLE t2 (c1 BIGINT); +INSERT INTO t2 VALUES('15449237462.0000000000'); +SELECT * FROM t2; +c1 +15449237462 +DROP TABLE t1, t2; End of 5.0 tests. diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test index 76177403bd0..c36408a52fe 100644 --- a/mysql-test/t/insert.test +++ b/mysql-test/t/insert.test @@ -353,5 +353,20 @@ SELECT * FROM t2; DROP TABLE t1, t2; +# +# Bug #30453: String not cast to int correctly +# + +CREATE TABLE t1 (c1 INT NOT NULL); +INSERT INTO t1 VALUES(4188.32999999999992724042385816574096679687500), +('4188.32999999999992724042385816574096679687500'), (4188); +SELECT * FROM t1; + +CREATE TABLE t2 (c1 BIGINT); +INSERT INTO t2 VALUES('15449237462.0000000000'); +SELECT * FROM t2; + +DROP TABLE t1, t2; + --echo End of 5.0 tests. diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 8b1b0d6790d..e073262cd4c 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -1538,14 +1538,18 @@ my_strntoull10rnd_8bit(CHARSET_INFO *cs __attribute__((unused)), } else addon= (*str >= '5'); - for ( ; str < end && (ch= (unsigned char) (*str - '0')) < 10; str++) + if (!dot) { - if (!dot) - shift++; + for ( ; str < end && (ch= (unsigned char) (*str - '0')) < 10; shift++, str++); + if (str < end && *str == '.') + { + str++; + for ( ; str < end && (ch= (unsigned char) (*str - '0')) < 10; str++); + } } - if (str < end && *str == '.' && !dot) + else { - str++; + shift= dot - str; for ( ; str < end && (ch= (unsigned char) (*str - '0')) < 10; str++); } goto exp; -- cgit v1.2.1 From 620269fecf2590d6e359221a5349360ad5cb9dc3 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 16 Oct 2007 13:43:16 +0500 Subject: Fix for bug #31285: main.status test fails with different Table_locks_waited Problem: Table_locks_waited value may depend on general logging. Fix: switch general logging off. mysql-test/r/status.result: Fix for bug #31285: main.status test fails with different Table_locks_waited - switch general logging off. mysql-test/t/status.test: Fix for bug #31285: main.status test fails with different Table_locks_waited - switch general logging off. --- mysql-test/r/status.result | 3 +++ mysql-test/t/status.test | 3 +++ 2 files changed, 6 insertions(+) diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result index db75044ee5d..c95b09597fc 100644 --- a/mysql-test/r/status.result +++ b/mysql-test/r/status.result @@ -8,6 +8,8 @@ VARIABLE_NAME VARIABLE_VALUE TABLE_LOCKS_IMMEDIATE 2 TABLE_LOCKS_WAITED 0 SET SQL_LOG_BIN=0; +set @old_general_log = @@global.general_log; +set global general_log = 'OFF'; drop table if exists t1; create table t1(n int) engine=myisam; insert into t1 values(1); @@ -20,6 +22,7 @@ show status like 'Table_locks_waited'; Variable_name Value Table_locks_waited 1 drop table t1; +set global general_log = @old_general_log; select 1; 1 1 diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test index 1cd5aa1726a..6a11791924a 100644 --- a/mysql-test/t/status.test +++ b/mysql-test/t/status.test @@ -21,6 +21,8 @@ select * from information_schema.session_status where variable_name like 'Table_ connection con1; # ++Immediate = 3 SET SQL_LOG_BIN=0; +set @old_general_log = @@global.general_log; +set global general_log = 'OFF'; --disable_warnings # ++Immediate = 4 drop table if exists t1; @@ -60,6 +62,7 @@ reap; # ++Immediate = 16 + $wait_condition_reps show status like 'Table_locks_waited'; drop table t1; +set global general_log = @old_general_log; disconnect con2; disconnect con1; -- cgit v1.2.1 From faf0f9fb21397a7270ce9072a87643d30eee7157 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 16 Oct 2007 17:19:07 +0500 Subject: Fix bug #31604: server crash when setting slow_query_log_file/global general_log_file variable Problem: we don't evaluate given expression checking values of the slow_query_log_file/general_log_file, don't check it for NULL. Fix: evaluate the expression, check result returned. mysql-test/r/log_state.result: Fix bug #31604: server crash when setting slow_query_log_file/global general_log_file variable - test result. mysql-test/t/log_state.test: Fix bug #31604: server crash when setting slow_query_log_file/global general_log_file variable - test case. sql/set_var.cc: Fix bug #31604: server crash when setting slow_query_log_file/global general_log_file variable - evaluate var->value calling val_str() method; - check for null values returned; - return proper errors if any. --- mysql-test/r/log_state.result | 13 +++++++++++++ mysql-test/t/log_state.test | 20 ++++++++++++++++++++ sql/set_var.cc | 23 +++++++++++++++++------ 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/log_state.result b/mysql-test/r/log_state.result index 3a3ef584ce3..407d93cf321 100644 --- a/mysql-test/r/log_state.result +++ b/mysql-test/r/log_state.result @@ -175,3 +175,16 @@ SET GLOBAL slow_query_log = ON; SET GLOBAL READ_ONLY = OFF; SET GLOBAL general_log = @old_general_log_state; SET GLOBAL slow_query_log = @old_slow_log_state; +set @old_general_log_file= @@global.general_log_file; +set @old_slow_query_log_file= @@global.slow_query_log_file; +set global general_log_file= concat('/not exiting path/log.maste', 'r'); +ERROR 42000: Variable 'general_log_file' can't be set to the value of '/not exiting path/log.master' +set global general_log_file= NULL; +ERROR 42000: Variable 'general_log_file' can't be set to the value of 'NULL' +set global slow_query_log_file= concat('/not exiting path/log.maste', 'r'); +ERROR 42000: Variable 'slow_query_log_file' can't be set to the value of '/not exiting path/log.master' +set global slow_query_log_file= NULL; +ERROR 42000: Variable 'slow_query_log_file' can't be set to the value of 'NULL' +set global general_log_file= @old_general_log_file; +set global slow_query_log_file= @old_slow_query_log_file; +End of 5.1 tests diff --git a/mysql-test/t/log_state.test b/mysql-test/t/log_state.test index c67da261ef1..ec3644cbff1 100644 --- a/mysql-test/t/log_state.test +++ b/mysql-test/t/log_state.test @@ -189,3 +189,23 @@ disconnect con1; # Remove the log files that was created in the "default location" # i.e var/run --remove_file $MYSQLTEST_VARDIR/run/master.log + +# +# Bug #31604: server crash when setting slow_query_log_file/general_log_file +# +set @old_general_log_file= @@global.general_log_file; +set @old_slow_query_log_file= @@global.slow_query_log_file; + +--error 1231 +set global general_log_file= concat('/not exiting path/log.maste', 'r'); +--error 1231 +set global general_log_file= NULL; +--error 1231 +set global slow_query_log_file= concat('/not exiting path/log.maste', 'r'); +--error 1231 +set global slow_query_log_file= NULL; + +set global general_log_file= @old_general_log_file; +set global slow_query_log_file= @old_slow_query_log_file; + +--echo End of 5.1 tests diff --git a/sql/set_var.cc b/sql/set_var.cc index ec82b56d793..c26e9a8d6e2 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2102,18 +2102,24 @@ void sys_var_log_state::set_default(THD *thd, enum_var_type type) static int sys_check_log_path(THD *thd, set_var *var) { - char path[FN_REFLEN]; + char path[FN_REFLEN], buff[FN_REFLEN]; MY_STAT f_stat; - const char *var_path= var->value->str_value.ptr(); + String str(buff, sizeof(buff), system_charset_info), *res; + const char *log_file_str; + + if (!(res= var->value->val_str(&str))) + goto err; + + log_file_str= res->c_ptr(); bzero(&f_stat, sizeof(MY_STAT)); - (void) unpack_filename(path, var_path); + (void) unpack_filename(path, log_file_str); if (my_stat(path, &f_stat, MYF(0))) { /* Check if argument is a file and we have 'write' permission */ if (!MY_S_ISREG(f_stat.st_mode) || !(f_stat.st_mode & MY_S_IWRITE)) - return -1; + goto err; } else { @@ -2122,11 +2128,16 @@ static int sys_check_log_path(THD *thd, set_var *var) Check if directory exists and we have permission to create file & write to file */ - (void) dirname_part(path, var_path, &path_length); + (void) dirname_part(path, log_file_str, &path_length); if (my_access(path, (F_OK|W_OK))) - return -1; + goto err; } return 0; + +err: + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, + res ? log_file_str : "NULL"); + return 1; } -- cgit v1.2.1 From e8adc3f74be7c8c8e81e59b1f5927bedf4a561bb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 17 Oct 2007 14:28:00 +0500 Subject: Fix for bug#31615: crash after set names ucs2 collate xxx Problem: currently, UCS-2 cannot be used as a client character set. Fix: raise an error if one attempts to set it to USC-2. mysql-test/r/ctype_ucs.result: Fix for bug#31615: crash after set names ucs2 collate xxx - test result. mysql-test/t/ctype_ucs.test: Fix for bug#31615: crash after set names ucs2 collate xxx - test case. sql/set_var.cc: Fix for bug#31615: crash after set names ucs2 collate xxx - raise an error if one is going to set character_set_client to UCS-2. sql/set_var.h: Fix for bug#31615: crash after set names ucs2 collate xxx - raise an error if one is going to set character_set_client to UCS-2. --- mysql-test/r/ctype_ucs.result | 8 ++++++++ mysql-test/t/ctype_ucs.test | 12 ++++++++++++ sql/set_var.cc | 22 ++++++++++++++++++++++ sql/set_var.h | 1 + 4 files changed, 43 insertions(+) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index bf827209795..befbd04f63d 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -803,4 +803,12 @@ quote(name) ???????? ???????????????? drop table bug20536; +set names ucs2; +ERROR 42000: Variable 'character_set_client' can't be set to the value of 'ucs2' +set names ucs2 collate ucs2_bin; +ERROR 42000: Variable 'character_set_client' can't be set to the value of 'ucs2' +set character_set_client= ucs2; +ERROR 42000: Variable 'character_set_client' can't be set to the value of 'ucs2' +set character_set_client= concat('ucs', substr('2', 1)); +ERROR 42000: Variable 'character_set_client' can't be set to the value of 'ucs2' End of 4.1 tests diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 10559d33eb3..9e6bd0e95e6 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -535,4 +535,16 @@ select quote(name) from bug20536; drop table bug20536; +# +# Bug #31615: crash after set names ucs2 collate xxx +# +--error 1231 +set names ucs2; +--error 1231 +set names ucs2 collate ucs2_bin; +--error 1231 +set character_set_client= ucs2; +--error 1231 +set character_set_client= concat('ucs', substr('2', 1)); + --echo End of 4.1 tests diff --git a/sql/set_var.cc b/sql/set_var.cc index 520ee5c9f70..275252c4960 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1992,6 +1992,21 @@ void sys_var_character_set_client::set_default(THD *thd, enum_var_type type) } +bool sys_var_character_set_client::check(THD *thd, set_var *var) +{ + if (sys_var_character_set::check(thd, var)) + return 1; + /* Currently, UCS-2 cannot be used as a client character set */ + if (var->save_result.charset->mbminlen > 1) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, + var->save_result.charset->csname); + return 1; + } + return 0; +} + + CHARSET_INFO ** sys_var_character_set_results::ci_ptr(THD *thd, enum_var_type type) { @@ -2355,6 +2370,13 @@ end: int set_var_collation_client::check(THD *thd) { + /* Currently, UCS-2 cannot be used as a client character set */ + if (character_set_client->mbminlen > 1) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client", + character_set_client->csname); + return 1; + } return 0; } diff --git a/sql/set_var.h b/sql/set_var.h index 78b34963e9d..f6fd0a082b5 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -578,6 +578,7 @@ public: sys_var_character_set(name_arg) {} void set_default(THD *thd, enum_var_type type); CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); + bool check(THD *thd, set_var *var); }; class sys_var_character_set_results :public sys_var_character_set -- cgit v1.2.1 From ce8bf087b0abe3a1cae976a26cac5368a93ba1a7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 17 Oct 2007 20:08:58 +0400 Subject: Fix for bug #31207: Test "join_nested" shows different strategy on IA64 CPUs / Intel's ICC compile The bug is a combination of two problems: 1. IA64/ICC MySQL binaries use glibc's qsort(), not the one in mysys. 2. The order relation implemented by join_tab_cmp() is not transitive, i.e. it is possible to choose such a, b and c that (a < b) && (b < c) but (c < a). This implies that result of a sort using the relation implemented by join_tab_cmp() depends on the order in which elements are compared, i.e. the result is implementation-specific. Since choose_plan() uses qsort() to pre-sort the join tables using join_tab_cmp() as a compare function, the results of the sorting may vary depending on qsort() implementation. It is neither possible nor important to implement a better ordering algorithm in join_tab_cmp(). Therefore the only way to fix it is to force our own qsort() to be used by renaming it to my_qsort(), so we don't depend on linker to decide that. This patch also "fixes" bug #20530: qsort redefinition violates the standard. include/my_sys.h: Renamed qsort() and qsort2() to my_qsort() and my_qsort2(). Since previously we relied on stdlib.h to provide a declaration for qsort(), a separate declaration for my_qsort() is now required. libmysql/Makefile.shared: Added mf_qsort.c to libmysql, since my_lib.c now uses my_qsort() instead of qsort(). myisam/ft_boolean_search.c: Replaced qsort2() with my_qsort2(). myisam/ft_nlq_search.c: Replaced qsort2() with my_qsort2(). myisam/myisampack.c: Replaced qsort() with my_qsort(). myisam/sort.c: Replaced qsort2() with my_qsort2(). mysys/mf_keycache.c: Replaced qsort() with my_qsort(). mysys/mf_qsort.c: Renamed qsort() to my_qsort() and qsort2() to my_qsort2(). mysys/mf_sort.c: Replaced qsort2() with my_qsort2(). mysys/my_lib.c: Replaced qsort() with my_qsort(). mysys/queues.c: Replaced qsort2() with my_qsort2(). sql/item_cmpfunc.cc: Replaced qsort2() with my_qsort2(). sql/item_cmpfunc.h: Replaced qsort2() with my_qsort2(). sql/opt_range.cc: Replaced qsort() with my_qsort(). sql/records.cc: Replaced qsort() with my_qsort(). sql/sql_acl.cc: Replaced qsort() with my_qsort(). sql/sql_array.h: Replaced qsort() with my_qsort(). sql/sql_help.cc: Replaced qsort() with my_qsort(). sql/sql_select.cc: Replaced qsort() with my_qsort(). sql/examples/ha_tina.cc: Replaced qsort() with my_qsort(). sql/sql_table.cc: Replaced qsort() with my_qsort(). --- include/my_sys.h | 6 ++++-- libmysql/Makefile.shared | 2 +- myisam/ft_boolean_search.c | 4 ++-- myisam/ft_nlq_search.c | 3 ++- myisam/myisampack.c | 2 +- myisam/sort.c | 12 ++++++------ mysys/mf_keycache.c | 2 +- mysys/mf_qsort.c | 4 ++-- mysys/mf_sort.c | 2 +- mysys/my_lib.c | 6 +++--- mysys/queues.c | 4 ++-- sql/examples/ha_tina.cc | 2 +- sql/item_cmpfunc.cc | 2 +- sql/item_cmpfunc.h | 2 +- sql/opt_range.cc | 8 ++++---- sql/records.cc | 3 ++- sql/sql_acl.cc | 20 ++++++++++---------- sql/sql_array.h | 2 +- sql/sql_help.cc | 2 +- sql/sql_select.cc | 18 +++++++++++++++--- sql/sql_table.cc | 2 +- 21 files changed, 62 insertions(+), 46 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index 4f7e75a836e..d401cfca082 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -709,8 +709,10 @@ extern sig_handler my_set_alarm_variable(int signo); extern void my_string_ptr_sort(void *base,uint items,size_s size); extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements, size_s size_of_element,uchar *buffer[]); -extern qsort_t qsort2(void *base_ptr, size_t total_elems, size_t size, - qsort2_cmp cmp, void *cmp_argument); +extern qsort_t my_qsort(void *base_ptr, size_t total_elems, size_t size, + qsort_cmp cmp); +extern qsort_t my_qsort2(void *base_ptr, size_t total_elems, size_t size, + qsort2_cmp cmp, void *cmp_argument); extern qsort2_cmp get_ptr_compare(uint); void my_store_ptr(byte *buff, uint pack_length, my_off_t pos); my_off_t my_get_ptr(byte *ptr, uint pack_length); diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index dc6d658fcdf..5947ae26486 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -73,7 +73,7 @@ sqlobjects = net.lo sql_cmn_objects = pack.lo client.lo my_time.lo # Not needed in the minimum library -mysysobjects2 = my_lib.lo +mysysobjects2 = my_lib.lo mf_qsort.lo mysysobjects = $(mysysobjects1) $(mysysobjects2) target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) \ $(sql_cmn_objects) $(vio_objects) $(sqlobjects) diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index 9f442148069..57de75ee4be 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -430,8 +430,8 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query, ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root, sizeof(FTB_WORD *)*ftb->queue.elements); memcpy(ftb->list, ftb->queue.root+1, sizeof(FTB_WORD *)*ftb->queue.elements); - qsort2(ftb->list, ftb->queue.elements, sizeof(FTB_WORD *), - (qsort2_cmp)FTB_WORD_cmp_list, ftb->charset); + my_qsort2(ftb->list, ftb->queue.elements, sizeof(FTB_WORD *), + (qsort2_cmp)FTB_WORD_cmp_list, ftb->charset); if (ftb->queue.elements<2) ftb->with_scan &= ~FTB_FLAG_TRUNC; ftb->state=READY; return ftb; diff --git a/myisam/ft_nlq_search.c b/myisam/ft_nlq_search.c index f63735b7e68..41d145c070f 100644 --- a/myisam/ft_nlq_search.c +++ b/myisam/ft_nlq_search.c @@ -281,7 +281,8 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, byte *query, &dptr, left_root_right); if (flags & FT_SORTED) - qsort2(dlist->doc, dlist->ndocs, sizeof(FT_DOC), (qsort2_cmp)&FT_DOC_cmp, 0); + my_qsort2(dlist->doc, dlist->ndocs, sizeof(FT_DOC), (qsort2_cmp)&FT_DOC_cmp, + 0); err: delete_tree(&aio.dtree); diff --git a/myisam/myisampack.c b/myisam/myisampack.c index 4ead51639f3..fa58211ea88 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -3148,7 +3148,7 @@ static void fakebigcodes(HUFF_COUNTS *huff_counts, HUFF_COUNTS *end_count) cur_sort_p= sort_counts; while (cur_count_p < end_count_p) *(cur_sort_p++)= cur_count_p++; - (void) qsort(sort_counts, 256, sizeof(my_off_t*), (qsort_cmp) fakecmp); + (void) my_qsort(sort_counts, 256, sizeof(my_off_t*), (qsort_cmp) fakecmp); /* Assign faked counts. diff --git a/myisam/sort.c b/myisam/sort.c index f48161b7c8e..c44b05313b0 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -649,8 +649,8 @@ static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys, uint sort_length=info->key_length; DBUG_ENTER("write_keys"); - qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp, - info); + my_qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp, + info); if (!my_b_inited(tempfile) && open_cached_file(tempfile, my_tmpdir(info->tmpdir), "ST", DISK_BUFFER_SIZE, info->sort_info->param->myf_rw)) @@ -692,8 +692,8 @@ static int NEAR_F write_keys_varlen(MI_SORT_PARAM *info, int err; DBUG_ENTER("write_keys_varlen"); - qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp, - info); + my_qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp, + info); if (!my_b_inited(tempfile) && open_cached_file(tempfile, my_tmpdir(info->tmpdir), "ST", DISK_BUFFER_SIZE, info->sort_info->param->myf_rw)) @@ -735,8 +735,8 @@ static int NEAR_F write_index(MI_SORT_PARAM *info, register uchar **sort_keys, { DBUG_ENTER("write_index"); - qsort2((gptr) sort_keys,(size_t) count,sizeof(byte*), - (qsort2_cmp) info->key_cmp,info); + my_qsort2((gptr) sort_keys,(size_t) count,sizeof(byte*), + (qsort2_cmp) info->key_cmp,info); while (count--) { if ((*info->key_write)(info,*sort_keys++)) diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 83363e6960d..baf3bffccb8 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -2268,7 +2268,7 @@ static int flush_cached_blocks(KEY_CACHE *keycache, As all blocks referred in 'cache' are marked by BLOCK_IN_FLUSH we are guarunteed no thread will change them */ - qsort((byte*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link); + my_qsort((byte*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link); keycache_pthread_mutex_lock(&keycache->cache_lock); for ( ; cache != end ; cache++) diff --git a/mysys/mf_qsort.c b/mysys/mf_qsort.c index 3d52d56c952..4b3ecb603a6 100644 --- a/mysys/mf_qsort.c +++ b/mysys/mf_qsort.c @@ -91,10 +91,10 @@ typedef struct st_stack *****************************************************************************/ #ifdef QSORT_EXTRA_CMP_ARGUMENT -qsort_t qsort2(void *base_ptr, size_t count, size_t size, qsort2_cmp cmp, +qsort_t my_qsort2(void *base_ptr, size_t count, size_t size, qsort2_cmp cmp, void *cmp_argument) #else -qsort_t qsort(void *base_ptr, size_t count, size_t size, qsort_cmp cmp) +qsort_t my_qsort(void *base_ptr, size_t count, size_t size, qsort_cmp cmp) #endif { char *low, *high, *pivot; diff --git a/mysys/mf_sort.c b/mysys/mf_sort.c index e7fd6873eee..a0c74642cb0 100644 --- a/mysys/mf_sort.c +++ b/mysys/mf_sort.c @@ -35,7 +35,7 @@ void my_string_ptr_sort(void *base, uint items, size_s size) if (size && items) { uint size_arg=size; - qsort2(base,items,sizeof(byte*),get_ptr_compare(size),(void*) &size_arg); + my_qsort2(base,items,sizeof(byte*),get_ptr_compare(size),(void*) &size_arg); } } } diff --git a/mysys/my_lib.c b/mysys/my_lib.c index 61de4ff9065..a076a0c971d 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -187,7 +187,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) result->number_off_files= dir_entries_storage->elements; if (!(MyFlags & MY_DONT_SORT)) - qsort((void *) result->dir_entry, result->number_off_files, + my_qsort((void *) result->dir_entry, result->number_off_files, sizeof(FILEINFO), (qsort_cmp) comp_names); DBUG_RETURN(result); @@ -498,7 +498,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) result->number_off_files= dir_entries_storage->elements; if (!(MyFlags & MY_DONT_SORT)) - qsort((void *) result->dir_entry, result->number_off_files, + my_qsort((void *) result->dir_entry, result->number_off_files, sizeof(FILEINFO), (qsort_cmp) comp_names); DBUG_PRINT("exit", ("found %d files", result->number_off_files)); DBUG_RETURN(result); @@ -605,7 +605,7 @@ MY_DIR *my_dir(const char* path, myf MyFlags) result->number_off_files= dir_entries_storage->elements; if (!(MyFlags & MY_DONT_SORT)) - qsort((void *) result->dir_entry, result->number_off_files, + my_qsort((void *) result->dir_entry, result->number_off_files, sizeof(FILEINFO), (qsort_cmp) comp_names); DBUG_RETURN(result); diff --git a/mysys/queues.c b/mysys/queues.c index 7809c97131c..6b88420a1cd 100644 --- a/mysys/queues.c +++ b/mysys/queues.c @@ -250,6 +250,6 @@ static int queue_fix_cmp(QUEUE *queue, void **a, void **b) void queue_fix(QUEUE *queue) { - qsort2(queue->root+1,queue->elements, sizeof(void *), - (qsort2_cmp)queue_fix_cmp, queue); + my_qsort2(queue->root+1,queue->elements, sizeof(void *), + (qsort2_cmp)queue_fix_cmp, queue); } diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc index 2c5226222e2..0d1d821cf17 100644 --- a/sql/examples/ha_tina.cc +++ b/sql/examples/ha_tina.cc @@ -852,7 +852,7 @@ int ha_tina::rnd_end() It also sorts so that we move the final blocks to the beginning so that we move the smallest amount of data possible. */ - qsort(chain, (size_t)(chain_ptr - chain), sizeof(tina_set), (qsort_cmp)sort_set); + my_qsort(chain, (size_t)(chain_ptr - chain), sizeof(tina_set), (qsort_cmp)sort_set); for (ptr= chain; ptr < chain_ptr; ptr++) { memmove(share->mapped_file + ptr->begin, share->mapped_file + ptr->end, diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 86eb10d50b0..45ed61a2ab7 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2775,7 +2775,7 @@ static inline int cmp_ulongs (ulonglong a_val, ulonglong b_val) SYNOPSIS cmp_longlong() - cmp_arg an argument passed to the calling function (qsort2) + cmp_arg an argument passed to the calling function (my_qsort2) a left argument b right argument diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 8410c66b034..2ea155b3fac 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -781,7 +781,7 @@ public: virtual byte *get_value(Item *item)=0; void sort() { - qsort2(base,used_count,size,compare,collation); + my_qsort2(base,used_count,size,compare,collation); } int find(Item *item); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 04e2816d553..c3e9b6638bd 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3159,8 +3159,8 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, ROR_SCAN_INFO's. Step 2: Get best ROR-intersection using an approximate algorithm. */ - qsort(tree->ror_scans, tree->n_ror_scans, sizeof(ROR_SCAN_INFO*), - (qsort_cmp)cmp_ror_scan_info); + my_qsort(tree->ror_scans, tree->n_ror_scans, sizeof(ROR_SCAN_INFO*), + (qsort_cmp)cmp_ror_scan_info); DBUG_EXECUTE("info",print_ror_scans_arr(param->table, "ordered", tree->ror_scans, tree->ror_scans_end);); @@ -3349,8 +3349,8 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, bitmap_get_first(&(*scan)->covered_fields); } - qsort(ror_scan_mark, ror_scans_end-ror_scan_mark, sizeof(ROR_SCAN_INFO*), - (qsort_cmp)cmp_ror_scan_info_covering); + my_qsort(ror_scan_mark, ror_scans_end-ror_scan_mark, sizeof(ROR_SCAN_INFO*), + (qsort_cmp)cmp_ror_scan_info_covering); DBUG_EXECUTE("info", print_ror_scans_arr(param->table, "remaining scans", diff --git a/sql/records.cc b/sql/records.cc index 3a833c87b7b..f61efc13034 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -497,7 +497,8 @@ static int rr_from_cache(READ_RECORD *info) int3store(ref_position,(long) i); ref_position+=3; } - qsort(info->read_positions,length,info->struct_length,(qsort_cmp) rr_cmp); + my_qsort(info->read_positions, length, info->struct_length, + (qsort_cmp) rr_cmp); position=info->read_positions; for (i=0 ; i < length ; i++) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f9bd2c6ba0d..d5257b1076a 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -248,8 +248,8 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) #endif VOID(push_dynamic(&acl_hosts,(gptr) &host)); } - qsort((gptr) dynamic_element(&acl_hosts,0,ACL_HOST*),acl_hosts.elements, - sizeof(ACL_HOST),(qsort_cmp) acl_compare); + my_qsort((gptr) dynamic_element(&acl_hosts,0,ACL_HOST*),acl_hosts.elements, + sizeof(ACL_HOST),(qsort_cmp) acl_compare); end_read_record(&read_record_info); freeze_size(&acl_hosts); @@ -421,8 +421,8 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) allow_all_hosts=1; // Anyone can connect } } - qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, - sizeof(ACL_USER),(qsort_cmp) acl_compare); + my_qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, + sizeof(ACL_USER),(qsort_cmp) acl_compare); end_read_record(&read_record_info); freeze_size(&acl_users); @@ -479,8 +479,8 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) #endif VOID(push_dynamic(&acl_dbs,(gptr) &db)); } - qsort((gptr) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, - sizeof(ACL_DB),(qsort_cmp) acl_compare); + my_qsort((gptr) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, + sizeof(ACL_DB),(qsort_cmp) acl_compare); end_read_record(&read_record_info); freeze_size(&acl_dbs); init_check_host(); @@ -1110,8 +1110,8 @@ static void acl_insert_user(const char *user, const char *host, if (!acl_user.host.hostname || (acl_user.host.hostname[0] == wild_many && !acl_user.host.hostname[1])) allow_all_hosts=1; // Anyone can connect /* purecov: tested */ - qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, - sizeof(ACL_USER),(qsort_cmp) acl_compare); + my_qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, + sizeof(ACL_USER),(qsort_cmp) acl_compare); /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ rebuild_check_host(); @@ -1173,8 +1173,8 @@ static void acl_insert_db(const char *user, const char *host, const char *db, acl_db.access=privileges; acl_db.sort=get_sort(3,acl_db.host.hostname,acl_db.db,acl_db.user); VOID(push_dynamic(&acl_dbs,(gptr) &acl_db)); - qsort((gptr) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, - sizeof(ACL_DB),(qsort_cmp) acl_compare); + my_qsort((gptr) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, + sizeof(ACL_DB),(qsort_cmp) acl_compare); } diff --git a/sql/sql_array.h b/sql/sql_array.h index e2e12bee241..dcef457dce7 100644 --- a/sql/sql_array.h +++ b/sql/sql_array.h @@ -62,7 +62,7 @@ public: void sort(CMP_FUNC cmp_func) { - qsort(array.buffer, array.elements, sizeof(Elem), (qsort_cmp)cmp_func); + my_qsort(array.buffer, array.elements, sizeof(Elem), (qsort_cmp)cmp_func); } }; diff --git a/sql/sql_help.cc b/sql/sql_help.cc index ba7f1a534ea..69a257a9d37 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -524,7 +524,7 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol, List_iterator it(*names); for (pos= pointers; pos!=end; (*pos++= it++)); - qsort(pointers,names->elements,sizeof(String*),string_ptr_cmp); + my_qsort(pointers,names->elements,sizeof(String*),string_ptr_cmp); for (pos= pointers; pos!=end; pos++) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1d11f23d854..b519c06420f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3658,7 +3658,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, { KEYUSE key_end,*prev,*save_pos,*use; - qsort(keyuse->buffer,keyuse->elements,sizeof(KEYUSE), + my_qsort(keyuse->buffer,keyuse->elements,sizeof(KEYUSE), (qsort_cmp) sort_keyuse); bzero((char*) &key_end,sizeof(key_end)); /* Add for easy testing */ @@ -4371,8 +4371,9 @@ choose_plan(JOIN *join, table_map join_tables) Apply heuristic: pre-sort all access plans with respect to the number of records accessed. */ - qsort(join->best_ref + join->const_tables, join->tables - join->const_tables, - sizeof(JOIN_TAB*), straight_join?join_tab_cmp_straight:join_tab_cmp); + my_qsort(join->best_ref + join->const_tables, + join->tables - join->const_tables, sizeof(JOIN_TAB*), + straight_join ? join_tab_cmp_straight : join_tab_cmp); if (straight_join) { @@ -4421,6 +4422,17 @@ choose_plan(JOIN *join, table_map join_tables) ptr1 pointer to first JOIN_TAB object ptr2 pointer to second JOIN_TAB object + NOTES + The order relation implemented by join_tab_cmp() is not transitive, + i.e. it is possible to choose such a, b and c that (a < b) && (b < c) + but (c < a). This implies that result of a sort using the relation + implemented by join_tab_cmp() depends on the order in which + elements are compared, i.e. the result is implementation-specific. + Example: + a: dependent = 0x0 table->map = 0x1 found_records = 3 ptr = 0x907e6b0 + b: dependent = 0x0 table->map = 0x2 found_records = 3 ptr = 0x907e838 + c: dependent = 0x6 table->map = 0x10 found_records = 2 ptr = 0x907ecd0 + RETURN 1 if first is bigger -1 if second is bigger diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6cbe98fe862..b6e41788ef0 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1476,7 +1476,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, DBUG_RETURN(-1); } /* Sort keys in optimized order */ - qsort((gptr) *key_info_buffer, *key_count, sizeof(KEY), + my_qsort((gptr) *key_info_buffer, *key_count, sizeof(KEY), (qsort_cmp) sort_keys); create_info->null_bits= null_fields; -- cgit v1.2.1 From 89810417ae8321b4cf44e1321e776cb2e29ec538 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 18 Oct 2007 15:17:21 +0400 Subject: Post-merge changes for bug #31207: Test "join_nested" shows different strategy on IA64 CPUs / Intel's ICC compiler. --- include/my_sys.h | 2 +- sql/partition_info.cc | 4 ++-- sql/set_var.cc | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index e919ed75541..638b1f4a2d4 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -784,7 +784,7 @@ extern int get_index_dynamic(DYNAMIC_ARRAY *array, uchar * element); #define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index)) #define push_dynamic(A,B) insert_dynamic((A),(B)) #define reset_dynamic(array) ((array)->elements= 0) -#define sort_dynamic(A,cmp) qsort((A)->buffer, (A)->elements, (A)->size_of_element, (cmp)) +#define sort_dynamic(A,cmp) my_qsort((A)->buffer, (A)->elements, (A)->size_of_element, (cmp)) extern my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str, size_t init_alloc,size_t alloc_increment); diff --git a/sql/partition_info.cc b/sql/partition_info.cc index ab887d5dda0..86d50cdf524 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -666,8 +666,8 @@ bool partition_info::check_list_constants() if (fixed && no_list_values) { bool first= TRUE; - qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), - &list_part_cmp); + my_qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), + &list_part_cmp); i= 0; LINT_INIT(prev_value); diff --git a/sql/set_var.cc b/sql/set_var.cc index ec82b56d793..9a6ad9ce662 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2900,7 +2900,8 @@ SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted) /* sort into order */ if (sorted) - qsort(result, count + fixed_count, sizeof(SHOW_VAR), (qsort_cmp)show_cmp); + my_qsort(result, count + fixed_count, sizeof(SHOW_VAR), + (qsort_cmp) show_cmp); /* make last element empty */ bzero(show, sizeof(SHOW_VAR)); -- cgit v1.2.1 From 8933fb3abd0395b63f3b424a8fa4cfee8ecee9d2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 18 Oct 2007 21:48:16 +0200 Subject: Remove unportable use of "system rm" --- mysql-test/t/binlog_killed.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/binlog_killed.test b/mysql-test/t/binlog_killed.test index 034895f17cb..e0b2f0a3db6 100644 --- a/mysql-test/t/binlog_killed.test +++ b/mysql-test/t/binlog_killed.test @@ -242,7 +242,7 @@ drop function bug27563; drop function bug27565; } -system rm $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog ; +remove_file $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog ; drop table t1,t2,t3; -- cgit v1.2.1 From 426b551bf600e4c2d0a78227fe51dc009d0231c7 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Oct 2007 14:54:05 +0500 Subject: Fix for bug #31349: ERROR 1062 (23000): Duplicate entry '' for key 'group_key' Problem: lying to the optimizer that a function (Item_func_inet_ntoa) cannot return NULL values leads to unexpected results (in the case group keys creation/comparison is broken). Fix: Item_func_inet_ntoa::maybe_null should be set properly. mysql-test/r/func_misc.result: Fix for bug #31349: ERROR 1062 (23000): Duplicate entry '' for key 'group_key' - test result. mysql-test/t/func_misc.test: Fix for bug #31349: ERROR 1062 (23000): Duplicate entry '' for key 'group_key' - test case. sql/item_strfunc.h: Fix for bug #31349: ERROR 1062 (23000): Duplicate entry '' for key 'group_key' - set Item_func_inet_ntoa::maybe_null flag. --- mysql-test/r/func_misc.result | 6 ++++++ mysql-test/t/func_misc.test | 8 ++++++++ sql/item_strfunc.h | 7 ++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index 35101e26ff6..db2490bd261 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -185,4 +185,10 @@ ERROR 21000: Operand should contain 1 column(s) drop table table_26093; drop function func_26093_a; drop function func_26093_b; +create table t1 (a int not null); +insert into t1 values (-1), (-2); +select min(a) from t1 group by inet_ntoa(a); +min(a) +-2 +drop table t1; End of 5.0 tests diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index 8ff62f68e45..5a70daa50e8 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -189,4 +189,12 @@ drop table table_26093; drop function func_26093_a; drop function func_26093_b; +# +# Bug #31349: ERROR 1062 (23000): Duplicate entry '' for key 'group_key' +# +create table t1 (a int not null); +insert into t1 values (-1), (-2); +select min(a) from t1 group by inet_ntoa(a); +drop table t1; + --echo End of 5.0 tests diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 6ca0b89a22b..4ffd8125422 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -683,7 +683,12 @@ public: } String* val_str(String* str); const char *func_name() const { return "inet_ntoa"; } - void fix_length_and_dec() { decimals = 0; max_length=3*8+7; } + void fix_length_and_dec() + { + decimals= 0; + max_length= 3 * 8 + 7; + maybe_null= 1; + } }; class Item_func_quote :public Item_str_func -- cgit v1.2.1 From 89cca4b3696a7a958eaae030aeff38b47a9fd7d1 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Oct 2007 22:35:08 +0400 Subject: Fixed the Windows build failures introduced by the patch for bug #31207: Test "join_nested" shows different strategy on IA64 CPUs / Intel's ICC compiler. --- libmysql/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt index 59e70d68a6d..6f5d8a49363 100755 --- a/libmysql/CMakeLists.txt +++ b/libmysql/CMakeLists.txt @@ -96,7 +96,7 @@ SET(CLIENT_SOURCES ../mysys/array.c ../strings/bchange.c ../strings/bmove.c ../strings/strmov.c ../strings/strnlen.c ../strings/strnmov.c ../strings/strtod.c ../strings/strtoll.c ../strings/strtoull.c ../strings/strxmov.c ../strings/strxnmov.c ../mysys/thr_mutex.c ../mysys/typelib.c ../vio/vio.c ../vio/viosocket.c - ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c + ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c ../mysys/mf_qsort.c ${LIB_SOURCES}) # Need to set USE_TLS for building the DLL, since __declspec(thread) -- cgit v1.2.1 From f9d068bc09c3b415e8212897692b93a9fee5aae1 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Oct 2007 06:54:31 +0200 Subject: Bug #20901: CREATE privilege is enough to insert into a table CREATE TABLE IF NOT EXISTS ... SELECT let you insert into an existing table as long as you had the CREATE privilege. CREATE ... SELECT variants now always require INSERT privilege on target table. mysql-test/r/create.result: Show that CREATE...SELECT requires INSERT privilege on target table. mysql-test/r/grant.result: Sort output for a defined state. mysql-test/t/create.test: Show that CREATE...SELECT requires INSERT privilege on target table. mysql-test/t/grant.test: Sort output for a defined state. sql/sql_parse.cc: Require INSERT privilege on target table for CREATE ... SELECT. --- mysql-test/r/create.result | 38 +++++++++++++++++++++++ mysql-test/r/grant.result | 6 ++-- mysql-test/t/create.test | 76 ++++++++++++++++++++++++++++++++++++++++++++++ mysql-test/t/grant.test | 2 +- sql/sql_parse.cc | 9 +++++- 5 files changed, 126 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index aa25c55f394..17894c65109 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -701,3 +701,41 @@ t2 CREATE TABLE `t2` ( drop table t1, t2; create table t1(a set("a,b","c,d") not null); ERROR HY000: Illegal set 'a,b' value found during parsing +create database mysqltest; +use mysqltest; +grant create on mysqltest.* to mysqltest@localhost; +create table t1 (i INT); +insert into t1 values (1); +ERROR 42000: Access denied for user 'mysqltest'@'localhost' to database 'mysqltest' +create table t2 (i INT); +create table t4 (i INT); +grant select, insert on mysqltest.t2 to mysqltest@localhost; +grant insert on mysqltest.t4 to mysqltest@localhost; +grant create, insert on mysqltest.t5 to mysqltest@localhost; +grant create, insert on mysqltest.t6 to mysqltest@localhost; +flush privileges; +insert into t2 values (1); +create table if not exists t1 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' +create table if not exists t3 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't3' +create table if not exists t4 select * from t2; +Warnings: +Note 1050 Table 't4' already exists +create table if not exists t5 select * from t2; +create table t6 select * from t2; +create table t7 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't7' +create table t4 select * from t2; +ERROR 42S01: Table 't4' already exists +create table t1 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' +drop table t1,t2,t4,t5,t6; +revoke create on mysqltest.* from mysqltest@localhost; +revoke select, insert on mysqltest.t2 from mysqltest@localhost; +revoke insert on mysqltest.t4 from mysqltest@localhost; +revoke create, insert on mysqltest.t5 from mysqltest@localhost; +revoke create, insert on mysqltest.t6 from mysqltest@localhost; +flush privileges; +drop database mysqltest; +use test; diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 4e4e2ccff48..2f457a4acbc 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -349,12 +349,12 @@ show grants for grant_user@localhost; Grants for grant_user@localhost GRANT USAGE ON *.* TO 'grant_user'@'localhost' GRANT INSERT (a, d, c, b) ON `test`.`t1` TO 'grant_user'@'localhost' -select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv; +select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv order by Column_name; Host Db User Table_name Column_name Column_priv -localhost test grant_user t1 b Insert -localhost test grant_user t1 d Insert localhost test grant_user t1 a Insert +localhost test grant_user t1 b Insert localhost test grant_user t1 c Insert +localhost test grant_user t1 d Insert revoke ALL PRIVILEGES on t1 from grant_user@localhost; show grants for grant_user@localhost; Grants for grant_user@localhost diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 57b16a13c01..d54615ddb4d 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -609,4 +609,80 @@ drop table t1, t2; --error 1105 create table t1(a set("a,b","c,d") not null); +# +# Bug #20901 - CREATE privilege is enough to insert into a table +# + +create database mysqltest; +use mysqltest; + +grant create on mysqltest.* to mysqltest@localhost; +create table t1 (i INT); + +connect (user1,localhost,mysqltest,,mysqltest); +connection user1; +# show we don't have INSERT +--error 1044 +insert into t1 values (1); +# show we have CREATE +create table t2 (i INT); +create table t4 (i INT); + +connection default; +grant select, insert on mysqltest.t2 to mysqltest@localhost; +grant insert on mysqltest.t4 to mysqltest@localhost; +# to specify ACLs for non-existent objects, must explictly |CREATE +grant create, insert on mysqltest.t5 to mysqltest@localhost; +grant create, insert on mysqltest.t6 to mysqltest@localhost; +flush privileges; + +connection user1; +insert into t2 values (1); + + +# CREATE IF NOT EXISTS...SELECT, t1 exists, no INSERT, must fail +--error 1142 +create table if not exists t1 select * from t2; + +# CREATE IF NOT EXISTS...SELECT, no t3 yet, no INSERT, must fail +--error 1142 +create table if not exists t3 select * from t2; + +# CREATE IF NOT EXISTS...SELECT, t4 exists, have INSERT, must succeed +create table if not exists t4 select * from t2; + +# CREATE IF NOT EXISTS...SELECT, no t5 yet, have INSERT, must succeed +create table if not exists t5 select * from t2; + + +# CREATE...SELECT, no t6 yet, have INSERT, must succeed +create table t6 select * from t2; + +# CREATE...SELECT, no t7 yet, no INSERT, must fail +--error 1142 +create table t7 select * from t2; + +# CREATE...SELECT, t4 exists, have INSERT, must still fail (exists) +--error 1050 +create table t4 select * from t2; + +# CREATE...SELECT, t1 exists, no INSERT, must fail +--error 1142 +create table t1 select * from t2; + + +connection default; +drop table t1,t2,t4,t5,t6; + +revoke create on mysqltest.* from mysqltest@localhost; +revoke select, insert on mysqltest.t2 from mysqltest@localhost; +revoke insert on mysqltest.t4 from mysqltest@localhost; +revoke create, insert on mysqltest.t5 from mysqltest@localhost; +revoke create, insert on mysqltest.t6 from mysqltest@localhost; +flush privileges; + +disconnect user1; +drop database mysqltest; +use test; + # End of 4.1 tests diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index ea148c67262..dcdf3f6f4e0 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -296,7 +296,7 @@ DROP DATABASE testdb10; create table t1(a int, b int, c int, d int); grant insert(b), insert(c), insert(d), insert(a) on t1 to grant_user@localhost; show grants for grant_user@localhost; -select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv; +select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv order by Column_name; revoke ALL PRIVILEGES on t1 from grant_user@localhost; show grants for grant_user@localhost; select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 24f9ef30569..880a145903c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5832,8 +5832,15 @@ int create_table_precheck(THD *thd, TABLE_LIST *tables, int error= 1; // Error message is given DBUG_ENTER("create_table_precheck"); + /* + Require CREATE [TEMPORARY] privilege on new table; for + CREATE TABLE ... SELECT, also require INSERT. + */ + want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? - CREATE_TMP_ACL : CREATE_ACL); + CREATE_TMP_ACL : CREATE_ACL) | + (select_lex->item_list.elements ? INSERT_ACL : 0); + if (check_access(thd, want_priv, create_table->db, &create_table->grant.privilege, 0, 0) || check_merge_table_access(thd, create_table->db, -- cgit v1.2.1 From d4e4be8ad5ae3e717f31ebffae3f474586a753de Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Oct 2007 07:09:16 +0200 Subject: Bug #20901: CREATE privilege is enough to insert into a table CREATE TABLE IF NOT EXISTS ... SELECT let you insert into an existing table as long as you had the CREATE privilege. CREATE ... SELECT variants now always require INSERT privilege on target table. mysql-test/r/create.result: after-merge fixes, errno changed 4.1->5.0 mysql-test/t/create.test: after-merge fixes, errno changed 4.1->5.0 --- mysql-test/r/create.result | 2 +- mysql-test/t/create.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 006dc951297..daafaa1a45a 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -755,7 +755,7 @@ use mysqltest; grant create on mysqltest.* to mysqltest@localhost; create table t1 (i INT); insert into t1 values (1); -ERROR 42000: Access denied for user 'mysqltest'@'localhost' to database 'mysqltest' +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' create table t2 (i INT); create table t4 (i INT); grant select, insert on mysqltest.t2 to mysqltest@localhost; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 106ecbb2586..8d76787de5a 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -667,7 +667,7 @@ create table t1 (i INT); connect (user1,localhost,mysqltest,,mysqltest); connection user1; # show we don't have INSERT ---error 1044 +--error 1142 insert into t1 values (1); # show we have CREATE create table t2 (i INT); -- cgit v1.2.1 From 5aa9c1bd6f5f0106619012f75b086c08172cd33b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Oct 2007 11:52:55 +0200 Subject: Bug#30560 Valgrind option to mysql-test-run with spaces in cause strange error mysql-test/mysql-test-run.pl: Use an array to store the valgrind options Deprecate --valgrind-options=s and instead use --valgrind-option(but allow PushBuild's) --valgrind-options=s usage. Make the variables local --- mysql-test/mysql-test-run.pl | 48 ++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 1ec91d200a5..b81d2eb0019 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -255,13 +255,13 @@ our $opt_timer= 1; our $opt_user; -our $opt_valgrind= 0; -our $opt_valgrind_mysqld= 0; -our $opt_valgrind_mysqltest= 0; -our $default_valgrind_options= "--show-reachable=yes"; -our $opt_valgrind_options; -our $opt_valgrind_path; -our $opt_callgrind; +my $opt_valgrind= 0; +my $opt_valgrind_mysqld= 0; +my $opt_valgrind_mysqltest= 0; +my @default_valgrind_args= ("--show-reachable=yes"); +my @valgrind_args; +my $opt_valgrind_path; +my $opt_callgrind; our $opt_stress= ""; our $opt_stress_suite= "main"; @@ -575,7 +575,18 @@ sub command_line_setup () { 'valgrind|valgrind-all' => \$opt_valgrind, 'valgrind-mysqltest' => \$opt_valgrind_mysqltest, 'valgrind-mysqld' => \$opt_valgrind_mysqld, - 'valgrind-options=s' => \$opt_valgrind_options, + 'valgrind-options=s' => sub { + my ($opt, $value)= @_; + # Deprecated option unless it's what we know pushbuild uses + if ($value eq "--gen-suppressions=all --show-reachable=yes") { + push(@valgrind_args, $_) for (split(' ', $value)); + return; + } + die("--valgrind-options=s is deprecated. Use ", + "--valgrind-option=s, to be specified several", + " times if necessary"); + }, + 'valgrind-option=s' => \@valgrind_args, 'valgrind-path=s' => \$opt_valgrind_path, 'callgrind' => \$opt_callgrind, @@ -992,7 +1003,7 @@ sub command_line_setup () { # -------------------------------------------------------------------------- # Check valgrind arguments # -------------------------------------------------------------------------- - if ( $opt_valgrind or $opt_valgrind_path or defined $opt_valgrind_options) + if ( $opt_valgrind or $opt_valgrind_path or @valgrind_args) { mtr_report("Turning on valgrind for all executables"); $opt_valgrind= 1; @@ -1017,17 +1028,18 @@ sub command_line_setup () { $opt_valgrind_mysqld= 1; # Set special valgrind options unless options passed on command line - $opt_valgrind_options="--trace-children=yes" - unless defined $opt_valgrind_options; + push(@valgrind_args, "--trace-children=yes") + unless @valgrind_args; } if ( $opt_valgrind ) { # Set valgrind_options to default unless already defined - $opt_valgrind_options=$default_valgrind_options - unless defined $opt_valgrind_options; + push(@valgrind_args, @default_valgrind_args) + unless @valgrind_args; - mtr_report("Running valgrind with options \"$opt_valgrind_options\""); + mtr_report("Running valgrind with options \"", + join(" ", @valgrind_args), "\""); } if ( ! $opt_testcase_timeout ) @@ -5008,7 +5020,7 @@ sub valgrind_arguments { } # Add valgrind options, can be overriden by user - mtr_add_arg($args, '%s', $opt_valgrind_options); + mtr_add_arg($args, '%s', $_) for (@valgrind_args); mtr_add_arg($args, $$exe); @@ -5148,12 +5160,14 @@ Options for coverage, profiling etc gcov FIXME gprof FIXME valgrind Run the "mysqltest" and "mysqld" executables using - valgrind with options($default_valgrind_options) + valgrind with default options valgrind-all Synonym for --valgrind valgrind-mysqltest Run the "mysqltest" and "mysql_client_test" executable with valgrind valgrind-mysqld Run the "mysqld" executable with valgrind - valgrind-options=ARGS Options to give valgrind, replaces default options + valgrind-options=ARGS Deprecated, use --valgrind-option + valgrind-option=ARGS Option to give valgrind, replaces default option(s), + can be specified more then once valgrind-path=[EXE] Path to the valgrind executable callgrind Instruct valgrind to use callgrind -- cgit v1.2.1 From b5d33614ac8f41ad31557c778726ba753674a58e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Oct 2007 13:28:46 +0500 Subject: after-merge fix: new sys_var_character_set_client classs introduced to perform separate checking. --- sql/set_var.cc | 25 ++++++++++++++++++++++++- sql/set_var.h | 14 ++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/sql/set_var.cc b/sql/set_var.cc index b6b102aa4d0..8ab91caf1f3 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -164,7 +164,8 @@ static sys_var_character_set_sv sys_character_set_server(&vars, "character_set_s sys_var_const_str sys_charset_system(&vars, "character_set_system", (char *)my_charset_utf8_general_ci.name); static sys_var_character_set_database sys_character_set_database(&vars, "character_set_database"); -static sys_var_character_set_sv sys_character_set_client(&vars, "character_set_client", +static sys_var_character_set_client sys_character_set_client(&vars, + "character_set_client", &SV::character_set_client, &default_charset_info); static sys_var_character_set_sv sys_character_set_connection(&vars, "character_set_connection", @@ -1861,6 +1862,21 @@ CHARSET_INFO **sys_var_character_set_sv::ci_ptr(THD *thd, enum_var_type type) } +bool sys_var_character_set_client::check(THD *thd, set_var *var) +{ + if (sys_var_character_set_sv::check(thd, var)) + return 1; + /* Currently, UCS-2 cannot be used as a client character set */ + if (var->save_result.charset->mbminlen > 1) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, + var->save_result.charset->csname); + return 1; + } + return 0; +} + + CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type type) { @@ -2290,6 +2306,13 @@ uchar *sys_var_log_output::value_ptr(THD *thd, enum_var_type type, int set_var_collation_client::check(THD *thd) { + /* Currently, UCS-2 cannot be used as a client character set */ + if (character_set_client->mbminlen > 1) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client", + character_set_client->csname); + return 1; + } return 0; } diff --git a/sql/set_var.h b/sql/set_var.h index eb2c893c89e..0e282212a3f 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -667,6 +667,20 @@ public: }; +class sys_var_character_set_client: public sys_var_character_set_sv +{ +public: + sys_var_character_set_client(sys_var_chain *chain, const char *name_arg, + CHARSET_INFO *SV::*offset_arg, + CHARSET_INFO **global_default_arg, + bool is_nullable= 0) + : sys_var_character_set_sv(chain, name_arg, offset_arg, global_default_arg, + is_nullable) + { } + bool check(THD *thd, set_var *var); +}; + + class sys_var_character_set_database :public sys_var_character_set { public: -- cgit v1.2.1 From b260e144a591706141b48e49fd1b6a5c302a20f0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Oct 2007 21:16:20 +0400 Subject: Fix for bug #31566: my_write(fd, 0x0, 0, flags) fails with EFAULT on some platforms Since the behavior of write(fd, buf, 0) is undefined, it may fail with EFAULT on some architectures when buf == NULL. The error was propagated up to a caller, since my_write() code did not handle it properly. Fixed by checking the 'number of bytes' argument in my_write() and returning before calling the write() system call when there is nothing to write. mysys/my_write.c: Return from my_write() before calling the write() system call when the number of bytes to be written is 0, since the behavior of write() in this case is not portable. --- mysys/my_write.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mysys/my_write.c b/mysys/my_write.c index 4c3d187e4e8..08d70accd57 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -29,6 +29,10 @@ uint my_write(int Filedes, const byte *Buffer, uint Count, myf MyFlags) Filedes, (long) Buffer, Count, MyFlags)); errors=0; written=0L; + /* The behavior of write(fd, buf, 0) is not portable */ + if (unlikely(!Count)) + return 0; + for (;;) { if ((writenbytes = (uint) write(Filedes, Buffer, Count)) == Count) -- cgit v1.2.1 From d4befc1dca23d4ed535a4eb2f82700b54702375b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Oct 2007 22:36:57 +0500 Subject: Fix for bug #30679: 5.1 name encoding not performed for views during upgrade Problem: we skip views perfoming --fix-table-names. Fix: rename views as well. client/mysqlcheck.c: Fix for bug #30679: 5.1 name encoding not performed for views during upgrade - rename views performing --fix-table-names as well. mysql-test/r/mysqlcheck.result: Fix for bug #30679: 5.1 name encoding not performed for views during upgrade - test result. mysql-test/t/mysqlcheck.test: Fix for bug #30679: 5.1 name encoding not performed for views during upgrade - test case. --- client/mysqlcheck.c | 7 +++++-- mysql-test/r/mysqlcheck.result | 18 ++++++++++++++++++ mysql-test/t/mysqlcheck.test | 13 +++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index fb2071ce10f..34f09f6ca92 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -533,8 +533,11 @@ static int process_all_tables_in_db(char *database) else { while ((row = mysql_fetch_row(res))) - /* Skip tables with an engine of NULL (probably a view). */ - if (row[1]) + /* + Skip tables with an engine of NULL (probably a view) + if we don't perform renaming. + */ + if (row[1] || what_to_do == DO_UPGRADE) { handle_request_for_tables(row[0], strlen(row[0])); } diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index b8ada0adff9..ac21e0aeb6a 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -58,3 +58,21 @@ test.t1 OK drop view v1; drop table t1; End of 5.0 tests +create table t1(a int); +create view v1 as select * from t1; +show tables; +Tables_in_test +t1 +v1 +show tables; +Tables_in_test +t1 +#mysql50#v-1 +v1 +show tables; +Tables_in_test +t1 +v1 +v-1 +drop view v1, `v-1`; +drop table t1; diff --git a/mysql-test/t/mysqlcheck.test b/mysql-test/t/mysqlcheck.test index d233546f9e3..b789e275ffe 100644 --- a/mysql-test/t/mysqlcheck.test +++ b/mysql-test/t/mysqlcheck.test @@ -38,3 +38,16 @@ drop view v1; drop table t1; --echo End of 5.0 tests + +# +# Bug #30679: 5.1 name encoding not performed for views during upgrade +# +create table t1(a int); +create view v1 as select * from t1; +show tables; +--copy_file $MYSQLTEST_VARDIR/master-data/test/v1.frm $MYSQLTEST_VARDIR/master-data/test/v-1.frm +show tables; +--exec $MYSQL_CHECK --check-upgrade --fix-table-names --databases test +show tables; +drop view v1, `v-1`; +drop table t1; -- cgit v1.2.1 From c63f2e3fb6bf3a5eb6da2995c47965843e9b212d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Oct 2007 08:19:57 +0400 Subject: Replaced 'return' with DBUG_RETURN() in the fix for bug #31566. --- mysys/my_write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/my_write.c b/mysys/my_write.c index 08d70accd57..9ff7babab31 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -31,7 +31,7 @@ uint my_write(int Filedes, const byte *Buffer, uint Count, myf MyFlags) /* The behavior of write(fd, buf, 0) is not portable */ if (unlikely(!Count)) - return 0; + DBUG_RETURN(0); for (;;) { -- cgit v1.2.1 From d7d93cf548064aef95f18ac45a9d8c03220abfad Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Oct 2007 15:37:38 +0500 Subject: Fix for bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0, file .\ha_innodb. Problem: if a partial unique key followed by a non-partial one we declare the second one as a primary key. Fix: sort non-partial unique keys before partial ones. include/my_base.h: Fix for bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0, file .\ha_innodb. - sort unique keys that don't contain partial segments before other keys: set HA_KEY_HAS_PART_KEY_SEG flag for such keys in the mysql_prepare_table(), use it in the sort_keys(); mysql-test/r/innodb_mysql.result: Fix for bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0, file .\ha_innodb. - test result. mysql-test/r/key.result: Fix for bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0, file .\ha_innodb. - test result. mysql-test/t/innodb_mysql.test: Fix for bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0, file .\ha_innodb. - test case. mysql-test/t/key.test: Fix for bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0, file .\ha_innodb. - test case. sql/sql_table.cc: Fix for bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0, file .\ha_innodb. - sort unique keys that don't contain partial segments before other keys: set HA_KEY_HAS_PART_KEY_SEG flag for such keys in the mysql_prepare_table(), use it in the sort_keys(); sql/structs.h: Fix for bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0, file .\ha_innodb. - sort unique keys that don't contain partial segments before other keys: set HA_KEY_HAS_PART_KEY_SEG flag for such keys in the mysql_prepare_table(), use it in the sort_keys(); --- include/my_base.h | 2 +- mysql-test/r/innodb_mysql.result | 15 ++++++++++++++ mysql-test/r/key.result | 44 ++++++++++++++++++++++++++++++++++++++++ mysql-test/t/innodb_mysql.test | 9 ++++++++ mysql-test/t/key.test | 18 ++++++++++++++++ sql/sql_table.cc | 26 ++++++++++++++++-------- sql/structs.h | 2 +- 7 files changed, 106 insertions(+), 10 deletions(-) diff --git a/include/my_base.h b/include/my_base.h index ef5ac364fed..9240b01a9f1 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -224,7 +224,7 @@ enum ha_base_keytype { #define HA_SPATIAL 1024 /* For spatial search */ #define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */ #define HA_GENERATED_KEY 8192 /* Automaticly generated key */ - +#define HA_KEY_HAS_PART_KEY_SEG 65536 /* Key contains partial segments */ /* Automatic bits in key-flag */ #define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */ diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index d5f014b6840..5a85df76347 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1211,4 +1211,19 @@ a b 3 2 1 1 DROP TABLE t1; +create table t1(a char(10) not null, unique key aa(a(1)), +b char(4) not null, unique key bb(b(4))) engine=innodb; +desc t1; +Field Type Null Key Default Extra +a char(10) NO UNI NULL +b char(4) NO PRI NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) NOT NULL, + `b` char(4) NOT NULL, + UNIQUE KEY `bb` (`b`), + UNIQUE KEY `aa` (`a`(1)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index 2fc751c63bf..0f1ea46bd61 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -462,4 +462,48 @@ EXPLAIN SELECT MAX(a) FROM t1 FORCE INDEX(a); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 DROP TABLE t1; +create table t1(a int not null, key aa(a), +b char(10) not null, unique key bb(b(1)), +c char(4) not null, unique key cc(c)); +desc t1; +Field Type Null Key Default Extra +a int(11) NO MUL NULL +b char(10) NO UNI NULL +c char(4) NO PRI NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` char(10) NOT NULL, + `c` char(4) NOT NULL, + UNIQUE KEY `cc` (`c`), + UNIQUE KEY `bb` (`b`(1)), + KEY `aa` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1(a int not null, key aa(a), +b char(10) not null, unique key bb(b(1)), +c char(4) not null); +desc t1; +Field Type Null Key Default Extra +a int(11) NO MUL NULL +b char(10) NO UNI NULL +c char(4) NO NULL +alter table t1 add unique key cc(c); +desc t1; +Field Type Null Key Default Extra +a int(11) NO MUL NULL +b char(10) NO UNI NULL +c char(4) NO PRI NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` char(10) NOT NULL, + `c` char(4) NOT NULL, + UNIQUE KEY `cc` (`c`), + UNIQUE KEY `bb` (`b`(1)), + KEY `aa` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +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 f64efd600c5..13aa6afd701 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -960,4 +960,13 @@ SELECT * FROM t1 ORDER BY b DESC, a ASC; DROP TABLE t1; +# +# Bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0 +# +create table t1(a char(10) not null, unique key aa(a(1)), + b char(4) not null, unique key bb(b(4))) engine=innodb; +desc t1; +show create table t1; +drop table t1; + --echo End of 5.0 tests diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index 3d0e68dc0f3..f63336a9864 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -443,4 +443,22 @@ ALTER TABLE t1 DISABLE KEYS; EXPLAIN SELECT MAX(a) FROM t1 FORCE INDEX(a); DROP TABLE t1; +# +# Bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0 +# +create table t1(a int not null, key aa(a), + b char(10) not null, unique key bb(b(1)), + c char(4) not null, unique key cc(c)); +desc t1; +show create table t1; +drop table t1; +create table t1(a int not null, key aa(a), + b char(10) not null, unique key bb(b(1)), + c char(4) not null); +desc t1; +alter table t1 add unique key cc(c); +desc t1; +show create table t1; +drop table t1; + --echo End of 5.0 tests. diff --git a/sql/sql_table.cc b/sql/sql_table.cc index b6e41788ef0..9d6f66aff53 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -361,7 +361,8 @@ int quick_rm_table(enum db_type base,const char *db, /* Sort keys in the following order: - PRIMARY KEY - - UNIQUE keyws where all column are NOT NULL + - UNIQUE keys where all column are NOT NULL + - UNIQUE keys that don't contain partial segments - Other UNIQUE keys - Normal keys - Fulltext keys @@ -372,26 +373,31 @@ int quick_rm_table(enum db_type base,const char *db, static int sort_keys(KEY *a, KEY *b) { - if (a->flags & HA_NOSAME) + ulong a_flags= a->flags, b_flags= b->flags; + + if (a_flags & HA_NOSAME) { - if (!(b->flags & HA_NOSAME)) + if (!(b_flags & HA_NOSAME)) return -1; - if ((a->flags ^ b->flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) + if ((a_flags ^ b_flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) { /* Sort NOT NULL keys before other keys */ - return (a->flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1; + return (a_flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1; } if (a->name == primary_key_name) return -1; if (b->name == primary_key_name) return 1; + /* Sort keys don't containing partial segments before others */ + if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG) + return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1; } - else if (b->flags & HA_NOSAME) + else if (b_flags & HA_NOSAME) return 1; // Prefer b - if ((a->flags ^ b->flags) & HA_FULLTEXT) + if ((a_flags ^ b_flags) & HA_FULLTEXT) { - return (a->flags & HA_FULLTEXT) ? 1 : -1; + return (a_flags & HA_FULLTEXT) ? 1 : -1; } /* Prefer original key order. usable_key_parts contains here @@ -1421,6 +1427,10 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, else key_info->flags|= HA_PACK_KEY; } + /* Check if the key segment is partial, set the key flag accordingly */ + if (length != sql_field->key_length) + key_info->flags|= HA_KEY_HAS_PART_KEY_SEG; + key_length+=length; key_part_info++; diff --git a/sql/structs.h b/sql/structs.h index 28bdd8c1519..bc373fe4b52 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -87,7 +87,7 @@ typedef struct st_key_part_info { /* Info about a key part */ typedef struct st_key { uint key_length; /* Tot length of key */ - uint flags; /* dupp key and pack flags */ + ulong flags; /* dupp key and pack flags */ uint key_parts; /* How many key_parts */ uint extra_length; uint usable_key_parts; /* Should normally be = key_parts */ -- cgit v1.2.1 From 42894ed0b870f4adfc6023404877732a08b1ec22 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 29 Oct 2007 12:20:21 +0400 Subject: Fix for bug #30782: Truncated UNSIGNED BIGINT columns only in SELECT w/ CASE, JOIN, and ORDER BY Problem: improper maximum length calculation of the CASE function leads to decimal value truncation (storing/retrieving decimal field values). Fix: accurately calculate maximum length/unsigned flag/decimals parameters of the CASE function. mysql-test/r/case.result: Fix for bug #30782: Truncated UNSIGNED BIGINT columns only in SELECT w/ CASE, JOIN, and ORDER BY - test result. mysql-test/t/case.test: Fix for bug #30782: Truncated UNSIGNED BIGINT columns only in SELECT w/ CASE, JOIN, and ORDER BY - test case. sql/item_cmpfunc.cc: Fix for bug #30782: Truncated UNSIGNED BIGINT columns only in SELECT w/ CASE, JOIN, and ORDER BY - accurately calculate Item_func_case::max_length/unsigned_flag/decimals. sql/item_cmpfunc.h: Fix for bug #30782: Truncated UNSIGNED BIGINT columns only in SELECT w/ CASE, JOIN, and ORDER BY - accurately calculate Item_func_case::max_length/unsigned_flag/decimals. --- mysql-test/r/case.result | 20 +++++++++++++++++++- mysql-test/t/case.test | 21 +++++++++++++++++++-- sql/item_cmpfunc.cc | 36 ++++++++++++++++++++++++++++++------ sql/item_cmpfunc.h | 2 ++ 4 files changed, 70 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index cf358e6a404..bc05edcfac1 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -1,4 +1,4 @@ -drop table if exists t1; +drop table if exists t1, t2; select CASE "b" when "a" then 1 when "b" then 2 END; CASE "b" when "a" then 1 when "b" then 2 END 2 @@ -200,3 +200,21 @@ CEMPNUM EMPMUM1 EMPNUM2 0.00 0 0.00 2.00 2 NULL DROP TABLE t1,t2; +End of 4.1 tests +create table t1 (a int, b bigint unsigned); +create table t2 (c int); +insert into t1 (a, b) values (1,4572794622775114594), (2,18196094287899841997), +(3,11120436154190595086); +insert into t2 (c) values (1), (2), (3); +select t1.a, (case t1.a when 0 then 0 else t1.b end) d from t1 +join t2 on t1.a=t2.c order by d; +a d +1 4572794622775114594 +3 11120436154190595086 +2 18196094287899841997 +select t1.a, (case t1.a when 0 then 0 else t1.b end) d from t1 +join t2 on t1.a=t2.c where b=11120436154190595086 order by d; +a d +3 11120436154190595086 +drop table t1, t2; +End of 5.0 tests diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index 0e9e141f6d8..b6654df4ecb 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -3,7 +3,7 @@ # --disable_warnings -drop table if exists t1; +drop table if exists t1, t2; --enable_warnings select CASE "b" when "a" then 1 when "b" then 2 END; @@ -152,4 +152,21 @@ SELECT IFNULL(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM, FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM; DROP TABLE t1,t2; -# End of 4.1 tests + +--echo End of 4.1 tests + +# +# #30782: Truncated UNSIGNED BIGINT columns +# +create table t1 (a int, b bigint unsigned); +create table t2 (c int); +insert into t1 (a, b) values (1,4572794622775114594), (2,18196094287899841997), + (3,11120436154190595086); +insert into t2 (c) values (1), (2), (3); +select t1.a, (case t1.a when 0 then 0 else t1.b end) d from t1 + join t2 on t1.a=t2.c order by d; +select t1.a, (case t1.a when 0 then 0 else t1.b end) d from t1 + join t2 on t1.a=t2.c where b=11120436154190595086 order by d; +drop table t1, t2; + +--echo End of 5.0 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 86eb10d50b0..8cbbc115922 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2530,6 +2530,23 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref) } +void Item_func_case::agg_str_lengths(Item* arg) +{ + set_if_bigger(max_length, arg->max_length); + set_if_bigger(decimals, arg->decimals); + unsigned_flag= unsigned_flag && arg->unsigned_flag; +} + + +void Item_func_case::agg_num_lengths(Item *arg) +{ + uint len= my_decimal_length_to_precision(arg->max_length, arg->decimals, + arg->unsigned_flag) - arg->decimals; + set_if_bigger(max_length, len); + set_if_bigger(decimals, arg->decimals); + unsigned_flag= unsigned_flag && arg->unsigned_flag; +} + void Item_func_case::fix_length_and_dec() { @@ -2579,15 +2596,22 @@ void Item_func_case::fix_length_and_dec() max_length=0; decimals=0; - for (uint i=0 ; i < ncases ; i+=2) + unsigned_flag= TRUE; + if (cached_result_type == STRING_RESULT) { - set_if_bigger(max_length,args[i+1]->max_length); - set_if_bigger(decimals,args[i+1]->decimals); + for (uint i= 0; i < ncases; i+= 2) + agg_str_lengths(args[i + 1]); + if (else_expr_num != -1) + agg_str_lengths(args[else_expr_num]); } - if (else_expr_num != -1) + else { - set_if_bigger(max_length,args[else_expr_num]->max_length); - set_if_bigger(decimals,args[else_expr_num]->decimals); + for (uint i= 0; i < ncases; i+= 2) + agg_num_lengths(args[i + 1]); + if (else_expr_num != -1) + agg_num_lengths(args[else_expr_num]); + max_length= my_decimal_precision_to_length(max_length + decimals, decimals, + unsigned_flag); } } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 8410c66b034..3e32b5d2c9c 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -753,6 +753,8 @@ public: void print(String *str); Item *find_item(String *str); CHARSET_INFO *compare_collation() { return cmp_collation.collation; } + void agg_str_lengths(Item *arg); + void agg_num_lengths(Item *arg); }; -- cgit v1.2.1 From fe68d102fb0143351e278aefdb6d0c9e797d031f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 29 Oct 2007 20:31:03 +0400 Subject: after-merge fix-up. --- mysql-test/include/mix1.inc | 9 ++++++++ mysql-test/r/innodb_mysql.result | 15 ++++++++++++++ mysql-test/r/key.result | 45 ++++++++++++++++++++++++++++++++++++++++ mysql-test/t/key.test | 20 ++++++++++++++++++ 4 files changed, 89 insertions(+) diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index aee5613ff35..4d910e86e0f 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -1019,6 +1019,15 @@ SELECT * FROM t1 ORDER BY b DESC, a ASC; DROP TABLE t1; +# +# Bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0 +# +create table t1(a char(10) not null, unique key aa(a(1)), + b char(4) not null, unique key bb(b(4))) engine=innodb; +desc t1; +show create table t1; +drop table t1; + --echo End of 5.0 tests # Fix for BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 3a6758b38f4..8f46df311ad 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1287,6 +1287,21 @@ a b 3 2 1 1 DROP TABLE t1; +create table t1(a char(10) not null, unique key aa(a(1)), +b char(4) not null, unique key bb(b(4))) engine=innodb; +desc t1; +Field Type Null Key Default Extra +a char(10) NO UNI NULL +b char(4) NO PRI NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) NOT NULL, + `b` char(4) NOT NULL, + UNIQUE KEY `bb` (`b`), + UNIQUE KEY `aa` (`a`(1)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +drop table t1; End of 5.0 tests CREATE TABLE `t2` ( `k` int(11) NOT NULL auto_increment, diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index a2bed75a709..a3e63a0bdf4 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -530,3 +530,48 @@ ORDER BY c.b, c.d a b c d e f g h i j a b c d 2 2 1 2004-11-30 12:00:00 1 0 0 0 0 0 2 3388000 -553000 NULL DROP TABLE t1, t2; +create table t1(a int not null, key aa(a), +b char(10) not null, unique key bb(b(1)), +c char(4) not null, unique key cc(c)); +desc t1; +Field Type Null Key Default Extra +a int(11) NO MUL NULL +b char(10) NO UNI NULL +c char(4) NO PRI NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` char(10) NOT NULL, + `c` char(4) NOT NULL, + UNIQUE KEY `cc` (`c`), + UNIQUE KEY `bb` (`b`(1)), + KEY `aa` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1(a int not null, key aa(a), +b char(10) not null, unique key bb(b(1)), +c char(4) not null); +desc t1; +Field Type Null Key Default Extra +a int(11) NO MUL NULL +b char(10) NO UNI NULL +c char(4) NO NULL +alter table t1 add unique key cc(c); +desc t1; +Field Type Null Key Default Extra +a int(11) NO MUL NULL +b char(10) NO UNI NULL +c char(4) NO PRI NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` char(10) NOT NULL, + `c` char(4) NOT NULL, + UNIQUE KEY `cc` (`c`), + UNIQUE KEY `bb` (`b`(1)), + KEY `aa` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +End of 5.0 tests diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index f1eb8e68b49..f4d99024206 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -501,3 +501,23 @@ ORDER BY c.b, c.d ; DROP TABLE t1, t2; + +# +# Bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0 +# +create table t1(a int not null, key aa(a), + b char(10) not null, unique key bb(b(1)), + c char(4) not null, unique key cc(c)); +desc t1; +show create table t1; +drop table t1; +create table t1(a int not null, key aa(a), + b char(10) not null, unique key bb(b(1)), + c char(4) not null); +desc t1; +alter table t1 add unique key cc(c); +desc t1; +show create table t1; +drop table t1; + +--echo End of 5.0 tests -- cgit v1.2.1 From 2611e8ec0c3abac191100ab5c8527ff21ba99d81 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 30 Oct 2007 12:51:57 +0400 Subject: Fix for bug #30654: mysqlcheck fails during upgrade of tables whose names include backticks or blank Problem: mysqlcheck doesn't escape backtick characters in the table names. Fix: escape them. client/mysqlcheck.c: Fix for bug #30654: mysqlcheck fails during upgrade of tables whose names include backticks or blank - escape backtick characters in the table names. mysql-test/r/mysqlcheck.result: Fix for bug #30654: mysqlcheck fails during upgrade of tables whose names include backticks or blank - test result. mysql-test/t/mysqlcheck.test: Fix for bug #30654: mysqlcheck fails during upgrade of tables whose names include backticks or blank - test case. --- client/mysqlcheck.c | 52 ++++++++++++++++++++++++++++++------------ mysql-test/r/mysqlcheck.result | 7 +++++- mysql-test/t/mysqlcheck.test | 11 ++++++++- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 8205a83fdf4..3b504eb50b0 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -186,6 +186,7 @@ static void dbDisconnect(char *host); static void DBerror(MYSQL *mysql, const char *when); static void safe_exit(int error); static void print_result(); +static uint fixed_name_length(const char *name); static char *fix_table_name(char *dest, char *src); int what_to_do = 0; @@ -409,14 +410,14 @@ static int process_selected_tables(char *db, char **table_names, int tables) { /* We need table list in form `a`, `b`, `c` - that's why we need 4 more chars added to to each table name + that's why we need 2 more chars added to to each table name space is for more readable output in logs and in case of error */ char *table_names_comma_sep, *end; int i, tot_length = 0; for (i = 0; i < tables; i++) - tot_length += strlen(*(table_names + i)) + 4; + tot_length+= fixed_name_length(*(table_names + i)) + 2; if (!(table_names_comma_sep = (char *) my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME)))) @@ -434,23 +435,46 @@ static int process_selected_tables(char *db, char **table_names, int tables) } else for (; tables > 0; tables--, table_names++) - handle_request_for_tables(*table_names, strlen(*table_names)); + handle_request_for_tables(*table_names, fixed_name_length(*table_names)); return 0; } /* process_selected_tables */ -static char *fix_table_name(char *dest, char *src) +static uint fixed_name_length(const char *name) { - char *db_sep; + const char *p; + uint extra_length= 2; /* count the first/last backticks */ + + for (p= name; *p; p++) + { + if (*p == '`') + extra_length++; + else if (*p == '.') + extra_length+= 2; + } + return (p - name) + extra_length; +} + +static char *fix_table_name(char *dest, char *src) +{ *dest++= '`'; - if ((db_sep= strchr(src, '.'))) + for (; *src; src++) { - dest= strmake(dest, src, (uint) (db_sep - src)); - dest= strmov(dest, "`.`"); - src= db_sep + 1; + switch (*src) { + case '.': /* add backticks around '.' */ + *dest++= '`'; + *dest++= '.'; + *dest++= '`'; + break; + case '`': /* escape backtick character */ + *dest++= '`'; + /* fall through */ + default: + *dest++= *src; + } } - dest= strxmov(dest, src, "`", NullS); + *dest++= '`'; return dest; } @@ -471,7 +495,7 @@ static int process_all_tables_in_db(char *database) { /* We need table list in form `a`, `b`, `c` - that's why we need 4 more chars added to to each table name + that's why we need 2 more chars added to to each table name space is for more readable output in logs and in case of error */ @@ -479,7 +503,7 @@ static int process_all_tables_in_db(char *database) uint tot_length = 0; while ((row = mysql_fetch_row(res))) - tot_length += strlen(row[0]) + 4; + tot_length+= fixed_name_length(row[0]) + 2; mysql_data_seek(res, 0); if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME)))) @@ -507,7 +531,7 @@ static int process_all_tables_in_db(char *database) /* Skip tables with an engine of NULL (probably a view). */ if (row[1]) { - handle_request_for_tables(row[0], strlen(row[0])); + handle_request_for_tables(row[0], fixed_name_length(row[0])); } } mysql_free_result(res); @@ -741,7 +765,7 @@ int main(int argc, char **argv) for (i = 0; i < tables4repair.elements ; i++) { char *name= (char*) dynamic_array_ptr(&tables4repair, i); - handle_request_for_tables(name, strlen(name)); + handle_request_for_tables(name, fixed_name_length(name)); } } end: diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index b2820df8f4c..f8a28009c42 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -1,4 +1,4 @@ -DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t1, `t``1`, `t 1`; drop view if exists v1; drop database if exists client_test_db; mysql.columns_priv OK @@ -41,4 +41,9 @@ test.t1 OK test.t1 OK drop view v1; drop table t1; +create table `t``1`(a int); +create table `t 1`(a int); +test.t 1 OK +test.t`1 OK +drop table `t``1`, `t 1`; End of 5.0 tests diff --git a/mysql-test/t/mysqlcheck.test b/mysql-test/t/mysqlcheck.test index f4e18d4004f..04e7b6b4bdb 100644 --- a/mysql-test/t/mysqlcheck.test +++ b/mysql-test/t/mysqlcheck.test @@ -2,7 +2,7 @@ # --disable_warnings -DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t1, `t``1`, `t 1`; drop view if exists v1; drop database if exists client_test_db; --enable_warnings @@ -31,4 +31,13 @@ create view v1 as select * from t1; drop view v1; drop table t1; +# +# Bug #30654: mysqlcheck fails during upgrade of tables whose names include backticks +# +create table `t``1`(a int); +create table `t 1`(a int); +--replace_result 'Table is already up to date' OK +--exec $MYSQL_CHECK --databases test +drop table `t``1`, `t 1`; + --echo End of 5.0 tests -- cgit v1.2.1 From f8b5a34083ebcaccdca66100ccdb72138dbd9a2f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 Oct 2007 10:34:26 +0100 Subject: BUG#31799: Scrambled number output due to integer overflow An integer overflow in number->string conversion caused completely wrong output of the number LONGLONG_MIN with gcc 4.2.1. Fixed by eliminating the overflow, using only operations that are well-defined in ANSI C. strings/ctype-simple.c: An integer overflow in number->string conversion caused completely wrong output of the number LONGLONG_MIN with gcc 4.2.1. Fixed by eliminating the overflow, using only operations that are well-defined in ANSI C. strings/ctype-ucs2.c: An integer overflow in number->string conversion caused completely wrong output of the number LONGLONG_MIN with gcc 4.2.1. Fixed by eliminating the overflow, using only operations that are well-defined in ANSI C. strings/int2str.c: An integer overflow in number->string conversion caused completely wrong output of the number LONGLONG_MIN with gcc 4.2.1. Fixed by eliminating the overflow, using only operations that are well-defined in ANSI C. strings/longlong2str.c: An integer overflow in number->string conversion caused completely wrong output of the number LONGLONG_MIN with gcc 4.2.1. Fixed by eliminating the overflow, using only operations that are well-defined in ANSI C. --- strings/ctype-simple.c | 24 ++++++++++++++---------- strings/ctype-ucs2.c | 24 ++++++++++++++---------- strings/int2str.c | 16 ++++++++++------ strings/longlong2str.c | 32 ++++++++++++++++++-------------- 4 files changed, 56 insertions(+), 40 deletions(-) diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index e073262cd4c..99e02e02014 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -837,6 +837,7 @@ int my_long10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)), register char *p, *e; long int new_val; uint sign=0; + unsigned long int uval = (unsigned long int) val; e = p = &buffer[sizeof(buffer)-1]; *p= 0; @@ -845,15 +846,16 @@ int my_long10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)), { if (val < 0) { - val= -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval= (unsigned long int)0 - uval; *dst++= '-'; len--; sign= 1; } } - new_val = (long) ((unsigned long int) val / 10); - *--p = '0'+ (char) ((unsigned long int) val - (unsigned long) new_val * 10); + new_val = (long) (uval / 10); + *--p = '0'+ (char) (uval - (unsigned long) new_val * 10); val = new_val; while (val != 0) @@ -876,12 +878,14 @@ int my_longlong10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)), register char *p, *e; long long_val; uint sign= 0; + ulonglong uval = (ulonglong)val; if (radix < 0) { if (val < 0) { - val = -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (ulonglong)0 - uval; *dst++= '-'; len--; sign= 1; @@ -891,22 +895,22 @@ int my_longlong10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)), e = p = &buffer[sizeof(buffer)-1]; *p= 0; - if (val == 0) + if (uval == 0) { *--p= '0'; len= 1; goto cnv; } - while ((ulonglong) val > (ulonglong) LONG_MAX) + while (uval > (ulonglong) LONG_MAX) { - ulonglong quo=(ulonglong) val/(uint) 10; - uint rem= (uint) (val- quo* (uint) 10); + ulonglong quo= uval/(uint) 10; + uint rem= (uint) (uval- quo* (uint) 10); *--p = '0' + rem; - val= quo; + uval= quo; } - long_val= (long) val; + long_val= (long) uval; while (long_val != 0) { long quo= long_val/10; diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index b5353c55e4c..97e5defdec1 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1018,6 +1018,7 @@ int my_l10tostr_ucs2(CHARSET_INFO *cs, register char *p, *db, *de; long int new_val; int sl=0; + unsigned long int uval = (unsigned long int) val; p = &buffer[sizeof(buffer)-1]; *p='\0'; @@ -1027,12 +1028,13 @@ int my_l10tostr_ucs2(CHARSET_INFO *cs, if (val < 0) { sl = 1; - val = -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (unsigned long int)0 - uval; } } - new_val = (long) ((unsigned long int) val / 10); - *--p = '0'+ (char) ((unsigned long int) val - (unsigned long) new_val * 10); + new_val = (long) (uval / 10); + *--p = '0'+ (char) (uval - (unsigned long) new_val * 10); val = new_val; while (val != 0) @@ -1065,34 +1067,36 @@ int my_ll10tostr_ucs2(CHARSET_INFO *cs __attribute__((unused)), register char *p, *db, *de; long long_val; int sl=0; + ulonglong uval= (ulonglong) val; if (radix < 0) { if (val < 0) { sl=1; - val = -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (ulonglong)0 - uval; } } p = &buffer[sizeof(buffer)-1]; *p='\0'; - if (val == 0) + if (uval == 0) { *--p='0'; goto cnv; } - while ((ulonglong) val > (ulonglong) LONG_MAX) + while (uval > (ulonglong) LONG_MAX) { - ulonglong quo=(ulonglong) val/(uint) 10; - uint rem= (uint) (val- quo* (uint) 10); + ulonglong quo= uval/(uint) 10; + uint rem= (uint) (uval- quo* (uint) 10); *--p = '0' + rem; - val= quo; + uval= quo; } - long_val= (long) val; + long_val= (long) uval; while (long_val != 0) { long quo= long_val/10; diff --git a/strings/int2str.c b/strings/int2str.c index 9fc53032819..fba98aac3f1 100644 --- a/strings/int2str.c +++ b/strings/int2str.c @@ -57,6 +57,7 @@ int2str(register long int val, register char *dst, register int radix, register char *p; long int new_val; char *dig_vec= upcase ? _dig_vec_upper : _dig_vec_lower; + ulong uval= (ulong) val; if (radix < 0) { @@ -65,7 +66,8 @@ int2str(register long int val, register char *dst, register int radix, if (val < 0) { *dst++ = '-'; - val = -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (ulong)0 - uval; } radix = -radix; } @@ -86,8 +88,8 @@ int2str(register long int val, register char *dst, register int radix, */ p = &buffer[sizeof(buffer)-1]; *p = '\0'; - new_val=(ulong) val / (ulong) radix; - *--p = dig_vec[(uchar) ((ulong) val- (ulong) new_val*(ulong) radix)]; + new_val= uval / (ulong) radix; + *--p = dig_vec[(uchar) (uval- (ulong) new_val*(ulong) radix)]; val = new_val; #ifdef HAVE_LDIV while (val != 0) @@ -133,20 +135,22 @@ char *int10_to_str(long int val,char *dst,int radix) char buffer[65]; register char *p; long int new_val; + unsigned long int uval = (unsigned long int) val; if (radix < 0) /* -10 */ { if (val < 0) { *dst++ = '-'; - val = -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (unsigned long int)0 - uval; } } p = &buffer[sizeof(buffer)-1]; *p = '\0'; - new_val= (long) ((unsigned long int) val / 10); - *--p = '0'+ (char) ((unsigned long int) val - (unsigned long) new_val * 10); + new_val= (long) (uval / 10); + *--p = '0'+ (char) (uval - (unsigned long) new_val * 10); val = new_val; while (val != 0) diff --git a/strings/longlong2str.c b/strings/longlong2str.c index c464abcfccd..d7de5bb0f7c 100644 --- a/strings/longlong2str.c +++ b/strings/longlong2str.c @@ -51,13 +51,15 @@ char *longlong2str(longlong val,char *dst,int radix) char buffer[65]; register char *p; long long_val; + ulonglong uval= (ulonglong) val; if (radix < 0) { if (radix < -36 || radix > -2) return (char*) 0; if (val < 0) { *dst++ = '-'; - val = -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (ulonglong)0 - uval; } radix = -radix; } @@ -65,7 +67,7 @@ char *longlong2str(longlong val,char *dst,int radix) { if (radix > 36 || radix < 2) return (char*) 0; } - if (val == 0) + if (uval == 0) { *dst++='0'; *dst='\0'; @@ -74,14 +76,14 @@ char *longlong2str(longlong val,char *dst,int radix) p = &buffer[sizeof(buffer)-1]; *p = '\0'; - while ((ulonglong) val > (ulonglong) LONG_MAX) + while (uval > (ulonglong) LONG_MAX) { - ulonglong quo=(ulonglong) val/(uint) radix; - uint rem= (uint) (val- quo* (uint) radix); + ulonglong quo= uval/(uint) radix; + uint rem= (uint) (uval- quo* (uint) radix); *--p = _dig_vec_upper[rem]; - val= quo; + uval= quo; } - long_val= (long) val; + long_val= (long) uval; while (long_val != 0) { long quo= long_val/radix; @@ -100,17 +102,19 @@ char *longlong10_to_str(longlong val,char *dst,int radix) char buffer[65]; register char *p; long long_val; + ulonglong uval= (ulonglong) val; if (radix < 0) { if (val < 0) { *dst++ = '-'; - val = -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (ulonglong)0 - uval; } } - if (val == 0) + if (uval == 0) { *dst++='0'; *dst='\0'; @@ -119,14 +123,14 @@ char *longlong10_to_str(longlong val,char *dst,int radix) p = &buffer[sizeof(buffer)-1]; *p = '\0'; - while ((ulonglong) val > (ulonglong) LONG_MAX) + while (uval > (ulonglong) LONG_MAX) { - ulonglong quo=(ulonglong) val/(uint) 10; - uint rem= (uint) (val- quo* (uint) 10); + ulonglong quo= uval/(uint) 10; + uint rem= (uint) (uval- quo* (uint) 10); *--p = _dig_vec_upper[rem]; - val= quo; + uval= quo; } - long_val= (long) val; + long_val= (long) uval; while (long_val != 0) { long quo= long_val/10; -- cgit v1.2.1 From a0a4cf336fc0ad09f7e4d159df7e524bc0dd8be3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Nov 2007 11:01:05 +0100 Subject: Fix comment --- client/mysqltest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index eae3b05f61a..e5ae9e80a88 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2675,7 +2675,7 @@ void do_copy_file(struct st_command *command) command command handle DESCRIPTION - chmod_file + chmod Change file permission of */ -- cgit v1.2.1 From 8eb11f8405170135efd9466e71850d2b2c0ae7ec Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Nov 2007 11:02:28 +0100 Subject: Bug#27753 enable mysql-test-run.pl to ignore tests based on wildcard - Fix problem in first implementation mysql-test/lib/mtr_cases.pl: Prepend a ^ to the regex only if _all_ charactersin the pattern are normal --- mysql-test/lib/mtr_cases.pl | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 5aabb7f8863..b9943fb6cfa 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -32,16 +32,14 @@ my $skip_test; sub init_pattern { my ($from, $what)= @_; - if ( $from =~ /[a-z0-9]/ ) { + if ( $from =~ /^[a-z0-9]$/ ) { # Does not contain any regex, make the pattern match # beginning of string $from= "^$from"; } - else { - # Check that pattern is a valid regex - eval { "" =~/$from/; 1 } or - mtr_error("Invalid regex '$from' passed to $what\nPerl says: $@"); - } + # Check that pattern is a valid regex + eval { "" =~/$from/; 1 } or + mtr_error("Invalid regex '$from' passed to $what\nPerl says: $@"); return $from; } -- cgit v1.2.1 From 295a1573786c93862922d904b1aad9c8498cf79d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Nov 2007 11:33:35 +0100 Subject: Bug#32023 ndb_mgmd is slow to repsond when no nodes are up ndb/src/mgmsrv/Services.cpp: Only call 'updateStatus'(and forcing HB) once before printing node status ndb/src/ndbapi/ClusterMgr.cpp: Only wait for reply to forced API_REGREQ if any signals has been sent --- mysql-test/r/bdb_notembedded.result | 35 ---------------------------------- mysql-test/t/bdb_notembedded.test | 38 ------------------------------------- ndb/src/mgmsrv/Services.cpp | 2 +- ndb/src/ndbapi/ClusterMgr.cpp | 5 ++++- 4 files changed, 5 insertions(+), 75 deletions(-) delete mode 100644 mysql-test/r/bdb_notembedded.result delete mode 100644 mysql-test/t/bdb_notembedded.test diff --git a/mysql-test/r/bdb_notembedded.result b/mysql-test/r/bdb_notembedded.result deleted file mode 100644 index 14cb5fad915..00000000000 --- a/mysql-test/r/bdb_notembedded.result +++ /dev/null @@ -1,35 +0,0 @@ -set autocommit=1; -reset master; -create table bug16206 (a int); -insert into bug16206 values(1); -start transaction; -insert into bug16206 values(2); -commit; -show binlog events; -Log_name Pos Event_type Server_id End_log_pos Info -f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4 -f n Query 1 n use `test`; create table bug16206 (a int) -f n Query 1 n use `test`; insert into bug16206 values(1) -f n Query 1 n use `test`; insert into bug16206 values(2) -drop table bug16206; -reset master; -create table bug16206 (a int) engine= bdb; -insert into bug16206 values(0); -insert into bug16206 values(1); -start transaction; -insert into bug16206 values(2); -commit; -insert into bug16206 values(3); -show binlog events; -Log_name Pos Event_type Server_id End_log_pos Info -f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4 -f n Query 1 n use `test`; create table bug16206 (a int) engine= bdb -f n Query 1 n use `test`; insert into bug16206 values(0) -f n Query 1 n use `test`; insert into bug16206 values(1) -f n Query 1 n use `test`; BEGIN -f n Query 1 n use `test`; insert into bug16206 values(2) -f n Query 1 n use `test`; COMMIT -f n Query 1 n use `test`; insert into bug16206 values(3) -drop table bug16206; -set autocommit=0; -End of 5.0 tests diff --git a/mysql-test/t/bdb_notembedded.test b/mysql-test/t/bdb_notembedded.test deleted file mode 100644 index 24e64ebbfb2..00000000000 --- a/mysql-test/t/bdb_notembedded.test +++ /dev/null @@ -1,38 +0,0 @@ --- source include/not_embedded.inc --- source include/have_bdb.inc - -# -# Bug #16206: Superfluous COMMIT event in binlog when updating BDB in autocommit mode -# -set autocommit=1; - -let $VERSION=`select version()`; - -reset master; -create table bug16206 (a int); -insert into bug16206 values(1); -start transaction; -insert into bug16206 values(2); -commit; ---replace_result $VERSION VERSION ---replace_column 1 f 2 n 5 n -show binlog events; -drop table bug16206; - -reset master; -create table bug16206 (a int) engine= bdb; -insert into bug16206 values(0); -insert into bug16206 values(1); -start transaction; -insert into bug16206 values(2); -commit; -insert into bug16206 values(3); ---replace_result $VERSION VERSION ---replace_column 1 f 2 n 5 n -show binlog events; -drop table bug16206; - -set autocommit=0; - - ---echo End of 5.0 tests diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index b7ff4df7012..31218df019b 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -923,7 +923,6 @@ printNodeStatus(OutputStream *output, MgmtSrvr &mgmsrv, enum ndb_mgm_node_type type) { NodeId nodeId = 0; - mgmsrv.updateStatus(); while(mgmsrv.getNextNodeId(&nodeId, type)) { enum ndb_mgm_node_status status; Uint32 startPhase = 0, @@ -972,6 +971,7 @@ MgmApiSession::getStatus(Parser::Context &, m_output->println("node status"); m_output->println("nodes: %d", noOfNodes); + m_mgmsrv.updateStatus(); printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_NDB); printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_MGM); printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_API); diff --git a/ndb/src/ndbapi/ClusterMgr.cpp b/ndb/src/ndbapi/ClusterMgr.cpp index d3946dddfb7..a8fcb756cdf 100644 --- a/ndb/src/ndbapi/ClusterMgr.cpp +++ b/ndb/src/ndbapi/ClusterMgr.cpp @@ -222,7 +222,10 @@ ClusterMgr::forceHB() theFacade.sendSignalUnCond(&signal, nodeId); } - NdbCondition_WaitTimeout(waitForHBCond, theFacade.theMutexPtr, 1000); + /* Wait for nodes to reply - if any heartbeats was sent */ + if (!waitForHBFromNodes.isclear()) + NdbCondition_WaitTimeout(waitForHBCond, theFacade.theMutexPtr, 1000); + waitingForHB= false; #ifdef DEBUG_REG ndbout << "Still waiting for HB from " << waitForHBFromNodes.getText(buf) << endl; -- cgit v1.2.1 From 775f84186a4b026132ec08eb43ac15aec2b1aa63 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Nov 2007 19:40:27 +0100 Subject: Bug#30630 mysql-test-run all tests fail with MySQL 5.0.41 & 5.0.45 on Mac OS X Server 10.5 mysql-test/mysql-test-run.pl: Also check for euid == 0 --- mysql-test/mysql-test-run.pl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index b81d2eb0019..b123c377ce7 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3727,6 +3727,16 @@ sub mysqld_arguments ($$$$) { # see BUG#28359 mtr_add_arg($args, "%s--connect-timeout=60", $prefix); + + # When mysqld is run by a root user(euid is 0), it will fail + # to start unless we specify what user to run as. If not running + # as root it will be ignored, see BUG#30630 + my $euid= $>; + if (!$glob_win32 and $euid == 0 and + grep(/^--user/, @$extra_opt, @opt_extra_mysqld_opt) == 0) { + mtr_add_arg($args, "%s--user=root"); + } + if ( $opt_valgrind_mysqld ) { mtr_add_arg($args, "%s--skip-safemalloc", $prefix); -- cgit v1.2.1 From c7191f90a3634b1a0cc45dc76f16b254f3e0a18e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Nov 2007 12:47:19 +0400 Subject: Fix for bug #32137: prepared statement crash with str_to_date in update clause Problem: calling non-constant argument's val_xxx() methods in the ::fix_length_and_dec() is inadmissible. Fix: call the method only for constant arguments. mysql-test/r/ps.result: Fix for bug #32137: prepared statement crash with str_to_date in update clause - test result. mysql-test/t/ps.test: Fix for bug #32137: prepared statement crash with str_to_date in update clause - test case. sql/item_timefunc.cc: Fix for bug #32137: prepared statement crash with str_to_date in update clause - call argument's val_str() only for constant items in the Item_func_str_to_date::fix_length_and_dec(). --- mysql-test/r/ps.result | 5 +++++ mysql-test/t/ps.test | 9 +++++++++ sql/item_timefunc.cc | 49 ++++++++++++++++++++++++++----------------------- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 49e4bf2f318..49643dd3f78 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1109,4 +1109,9 @@ a 13 DEALLOCATE PREPARE st1; DROP TABLE t1; +create table t1 (a int, b tinyint); +prepare st1 from 'update t1 set b= (str_to_date(a, a))'; +execute st1; +deallocate prepare st1; +drop table t1; End of 4.1 tests. diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 5e5dcc36b19..18beb357d05 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1146,4 +1146,13 @@ EXECUTE st1; DEALLOCATE PREPARE st1; DROP TABLE t1; +# +# Bug #32137: prepared statement crash with str_to_date in update clause +# +create table t1 (a int, b tinyint); +prepare st1 from 'update t1 set b= (str_to_date(a, a))'; +execute st1; +deallocate prepare st1; +drop table t1; + --echo End of 4.1 tests. diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 4bd3d68b9c1..08e0a727544 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2958,39 +2958,42 @@ Field *Item_func_str_to_date::tmp_table_field(TABLE *t_arg) void Item_func_str_to_date::fix_length_and_dec() { - char format_buff[64]; - String format_str(format_buff, sizeof(format_buff), &my_charset_bin); - String *format; maybe_null= 1; decimals=0; cached_field_type= MYSQL_TYPE_STRING; max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; cached_timestamp_type= MYSQL_TIMESTAMP_NONE; - format= args[1]->val_str(&format_str); - if (!args[1]->null_value && (const_item= args[1]->const_item())) + if ((const_item= args[1]->const_item())) { - cached_format_type= get_date_time_result_type(format->ptr(), - format->length()); - switch (cached_format_type) { - case DATE_ONLY: - cached_timestamp_type= MYSQL_TIMESTAMP_DATE; - cached_field_type= MYSQL_TYPE_DATE; - max_length= MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; - break; - case TIME_ONLY: - case TIME_MICROSECOND: - cached_timestamp_type= MYSQL_TIMESTAMP_TIME; - cached_field_type= MYSQL_TYPE_TIME; - max_length= MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; - break; - default: - cached_timestamp_type= MYSQL_TIMESTAMP_DATETIME; - cached_field_type= MYSQL_TYPE_DATETIME; - break; + char format_buff[64]; + String format_str(format_buff, sizeof(format_buff), &my_charset_bin); + String *format= args[1]->val_str(&format_str); + if (!args[1]->null_value) + { + cached_format_type= get_date_time_result_type(format->ptr(), + format->length()); + switch (cached_format_type) { + case DATE_ONLY: + cached_timestamp_type= MYSQL_TIMESTAMP_DATE; + cached_field_type= MYSQL_TYPE_DATE; + max_length= MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN; + break; + case TIME_ONLY: + case TIME_MICROSECOND: + cached_timestamp_type= MYSQL_TIMESTAMP_TIME; + cached_field_type= MYSQL_TYPE_TIME; + max_length= MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN; + break; + default: + cached_timestamp_type= MYSQL_TIMESTAMP_DATETIME; + cached_field_type= MYSQL_TYPE_DATETIME; + break; + } } } } + bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date) { DATE_TIME_FORMAT date_time_format; -- cgit v1.2.1 From 9d2b259e236ce1df5d0cbf40c3bf7811bc4d92e6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Nov 2007 19:59:58 +0400 Subject: Fix for bug #26447: "ALTER TABLE .. ORDER" does not work with InnoDB and auto_increment keys Problems: 1. ALTER TABLE ... ORDER BY... doesn't make sence if there's a user-defined clustered index in the table. 2. using a secondary index is slower than using a clustered one for a table scan. Fixes: 1. raise a warning. 2. use the clustered index. mysql-test/include/mix1.inc: Fix for bug #26447: "ALTER TABLE .. ORDER" does not work with InnoDB and auto_increment keys - test case. mysql-test/r/innodb.result: Fix for bug #26447: "ALTER TABLE .. ORDER" does not work with InnoDB and auto_increment keys - results adjusted. mysql-test/r/innodb_mysql.result: Fix for bug #26447: "ALTER TABLE .. ORDER" does not work with InnoDB and auto_increment keys - results adjusted. mysql-test/r/join_outer_innodb.result: Fix for bug #26447: "ALTER TABLE .. ORDER" does not work with InnoDB and auto_increment keys - results adjusted. sql/sql_select.cc: Fix for bug #26447: "ALTER TABLE .. ORDER" does not work with InnoDB and auto_increment keys - use the clustered index for a table scan (if any) as it's faster than using a secondary index. sql/sql_table.cc: Fix for bug #26447: "ALTER TABLE .. ORDER" does not work with InnoDB and auto_increment keys - ALTER TABLE ... ORDER BY doesn't make sence if there's a user-defined clustered index in the table. Ignore it in such cases and raise a warning. --- mysql-test/include/mix1.inc | 8 +++++++ mysql-test/r/innodb.result | 30 ++++++++++++------------ mysql-test/r/innodb_mysql.result | 21 ++++++++++------- mysql-test/r/join_outer_innodb.result | 4 ++-- sql/sql_select.cc | 10 +++++++- sql/sql_table.cc | 44 ++++++++++++++++++++++------------- 6 files changed, 75 insertions(+), 42 deletions(-) diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index 4d910e86e0f..2887a1ac40a 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -1189,4 +1189,12 @@ if ($test_foreign_keys) DROP TABLE t1; } +# +# Bug #26447: "ALTER TABLE .. ORDER" does not work with InnoDB and +# auto_increment keys +# +create table t1 (a int auto_increment primary key) engine=innodb; +alter table t1 order by a; +drop table t1; + --echo End of 5.1 tests diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index d0b67e90afb..086bd714078 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -962,7 +962,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL b 4 NULL # Using index explain select a,b from t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL b 4 NULL # Using index +1 SIMPLE t1 index NULL PRIMARY 4 NULL # explain select a,b,c from t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL # @@ -1177,14 +1177,14 @@ UPDATE t1 set a=a+100 where b between 2 and 3 and a < 1000; SELECT * from t1; a b 1 1 -102 2 -103 3 4 4 5 5 6 6 7 7 8 8 9 9 +102 2 +103 3 drop table t1; CREATE TABLE t1 (a int not null primary key, b int not null, key (b)) engine=innodb; CREATE TABLE t2 (a int not null primary key, b int not null, key (b)) engine=innodb; @@ -1208,7 +1208,6 @@ a b update t1,t2 set t1.a=t1.a+100 where t1.a=101; select * from t1; a b -201 1 102 2 103 3 104 4 @@ -1220,10 +1219,11 @@ a b 110 10 111 11 112 12 +201 1 update t1,t2 set t1.b=t1.b+10 where t1.b=2; select * from t1; a b -201 1 +102 12 103 3 104 4 105 5 @@ -1233,34 +1233,34 @@ a b 109 9 110 10 111 11 -102 12 112 12 +201 1 update t1,t2 set t1.b=t1.b+2,t2.b=t1.b+10 where t1.b between 3 and 5 and t1.a=t2.a+100; select * from t1; a b -201 1 +102 12 103 5 104 6 -106 6 105 7 +106 6 107 7 108 8 109 9 110 10 111 11 -102 12 112 12 +201 1 select * from t2; a b 1 1 2 2 +3 13 +4 14 +5 15 6 6 7 7 8 8 9 9 -3 13 -4 14 -5 15 drop table t1,t2; CREATE TABLE t2 ( NEXT_T BIGINT NOT NULL PRIMARY KEY) ENGINE=MyISAM; CREATE TABLE t1 ( B_ID INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; @@ -1311,11 +1311,11 @@ insert into t1 (id) values (null),(null),(null),(null),(null); update t1 set fk=69 where fk is null order by id limit 1; SELECT * from t1; id fk +1 69 2 NULL 3 NULL 4 NULL 5 NULL -1 69 drop table t1; create table t1 (a int not null, b int not null, key (a)); insert into t1 values (1,1),(1,2),(1,3),(3,1),(3,2),(3,3),(3,1),(3,2),(3,3),(2,1),(2,2),(2,3); @@ -2444,8 +2444,8 @@ insert into t1 (b) values (1); replace into t1 (b) values (2), (1), (3); select * from t1; a b -3 1 2 2 +3 1 4 3 truncate table t1; insert into t1 (b) values (1); @@ -2454,8 +2454,8 @@ replace into t1 (b) values (1); replace into t1 (b) values (3); select * from t1; a b -3 1 2 2 +3 1 4 3 drop table t1; create table t1 (rowid int not null auto_increment, val int not null,primary diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 8f46df311ad..775151db9f0 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -352,13 +352,13 @@ EXPLAIN SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index PRIMARY,name name 23 NULL 3 Using where; Using index +1 SIMPLE t1 index PRIMARY,name PRIMARY 4 NULL 3 Using where 1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using where; Using index EXPLAIN SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%' OR FALSE; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 index NULL fkey 5 NULL 5 Using index +1 SIMPLE t2 index NULL PRIMARY 4 NULL 5 1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.fkey 1 Using where DROP TABLE t1,t2; CREATE TABLE t1 ( @@ -1260,11 +1260,11 @@ select_type SIMPLE table t1 type index possible_keys NULL -key b -key_len 5 +key PRIMARY +key_len 4 ref NULL rows 3 -Extra Using index; Using filesort +Extra Using filesort SELECT * FROM t1 ORDER BY b ASC, a DESC; a b 1 1 @@ -1276,11 +1276,11 @@ select_type SIMPLE table t1 type index possible_keys NULL -key b -key_len 5 +key PRIMARY +key_len 4 ref NULL rows 3 -Extra Using index; Using filesort +Extra Using filesort SELECT * FROM t1 ORDER BY b DESC, a ASC; a b 2 2 @@ -1470,4 +1470,9 @@ t2 CREATE TABLE `t2` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t2; DROP TABLE t1; +create table t1 (a int auto_increment primary key) engine=innodb; +alter table t1 order by a; +Warnings: +Warning 1105 ORDER BY ignored as there is a user-defined clustered index in the table 't1' +drop table t1; End of 5.1 tests diff --git a/mysql-test/r/join_outer_innodb.result b/mysql-test/r/join_outer_innodb.result index e8a2d6f668b..24a11b12b03 100644 --- a/mysql-test/r/join_outer_innodb.result +++ b/mysql-test/r/join_outer_innodb.result @@ -8,12 +8,12 @@ EXPLAIN SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index PRIMARY,name name 23 NULL 3 Using where; Using index +1 SIMPLE t1 index PRIMARY,name PRIMARY 4 NULL 3 Using where 1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using where; Using index EXPLAIN SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%' OR FALSE; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 index NULL fkey 5 NULL 5 Using index +1 SIMPLE t2 index NULL PRIMARY 4 NULL 5 1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.fkey 1 Using where DROP TABLE t1,t2; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1c8ff12eb92..2e28663e383 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6436,7 +6436,15 @@ make_join_readinfo(JOIN *join, ulonglong options) else if (!table->covering_keys.is_clear_all() && !(tab->select && tab->select->quick)) { // Only read index tree - tab->index=find_shortest_key(table, & table->covering_keys); + /* + See bug #26447: "Using the clustered index for a table scan + is always faster than using a secondary index". + */ + if (table->s->primary_key != MAX_KEY && + table->file->primary_key_is_clustered()) + tab->index= table->s->primary_key; + else + tab->index=find_shortest_key(table, & table->covering_keys); tab->read_first_record= join_read_first; tab->type=JT_NEXT; // Read with index_first / index_next } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e6d84d0ef45..d63a6d7d3fc 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6813,23 +6813,35 @@ copy_data_between_tables(TABLE *from,TABLE *to, if (order) { - from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), - MYF(MY_FAE | MY_ZEROFILL)); - bzero((char*) &tables,sizeof(tables)); - tables.table= from; - tables.alias= tables.table_name= from->s->table_name.str; - tables.db= from->s->db.str; - error=1; + if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered()) + { + char warn_buff[MYSQL_ERRMSG_SIZE]; + my_snprintf(warn_buff, sizeof(warn_buff), + "ORDER BY ignored as there is a user-defined clustered index" + " in the table '%-.192s'", from->s->table_name.str); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, + warn_buff); + } + else + { + from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), + MYF(MY_FAE | MY_ZEROFILL)); + bzero((char *) &tables, sizeof(tables)); + tables.table= from; + tables.alias= tables.table_name= from->s->table_name.str; + tables.db= from->s->db.str; + error= 1; - if (thd->lex->select_lex.setup_ref_array(thd, order_num) || - setup_order(thd, thd->lex->select_lex.ref_pointer_array, - &tables, fields, all_fields, order) || - !(sortorder=make_unireg_sortorder(order, &length, NULL)) || - (from->sort.found_records = filesort(thd, from, sortorder, length, - (SQL_SELECT *) 0, HA_POS_ERROR, 1, - &examined_rows)) == - HA_POS_ERROR) - goto err; + if (thd->lex->select_lex.setup_ref_array(thd, order_num) || + setup_order(thd, thd->lex->select_lex.ref_pointer_array, + &tables, fields, all_fields, order) || + !(sortorder= make_unireg_sortorder(order, &length, NULL)) || + (from->sort.found_records= filesort(thd, from, sortorder, length, + (SQL_SELECT *) 0, HA_POS_ERROR, + 1, &examined_rows)) == + HA_POS_ERROR) + goto err; + } }; /* Tell handler that we have values for all columns in the to table */ -- cgit v1.2.1 From f89441226b1eb2c09b0cb00be507705aaac269a0 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 9 Nov 2007 11:16:47 +0100 Subject: Bug#32217 rpl_ssl fails with different number of records on master and slave - Add debug queries mysql-test/suite/rpl/t/rpl_ssl.test: Add additional queries to run when we detect that the number of queries between slave and master differs --- mysql-test/suite/rpl/t/rpl_ssl.test | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mysql-test/suite/rpl/t/rpl_ssl.test b/mysql-test/suite/rpl/t/rpl_ssl.test index c1b7bc2097b..59f0bf6a6f8 100644 --- a/mysql-test/suite/rpl/t/rpl_ssl.test +++ b/mysql-test/suite/rpl/t/rpl_ssl.test @@ -76,6 +76,16 @@ if (`select $slave_count != $master_count`) echo master and slave differed in number of rows; echo master: $master_count; echo slave: $slave_count; + + connection master; + echo === master ===; + select count(*) t1; + select * from t1; + connection slave; + echo === slave ===; + select count(*) t1; + select * from t1; + query_vertical show slave status; } connection master; -- cgit v1.2.1 From f56e68929a9bd916a3395276e6165af366132c8c Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 10 Nov 2007 18:27:57 +0400 Subject: manual merge. --- mysql-test/r/ps.result | 5 +++++ mysql-test/t/ps.test | 10 ++++++++++ sql/item_timefunc.cc | 48 ++++++++++++++++++++++++++---------------------- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 4db588e5cac..0682cae5c80 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1136,6 +1136,11 @@ a 13 DEALLOCATE PREPARE st1; DROP TABLE t1; +create table t1 (a int, b tinyint); +prepare st1 from 'update t1 set b= (str_to_date(a, a))'; +execute st1; +deallocate prepare st1; +drop table t1; End of 4.1 tests. create table t1 (a varchar(20)); insert into t1 values ('foo'); diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index cd2fc44e3ce..c1505ffd645 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1210,6 +1210,16 @@ EXECUTE st1; DEALLOCATE PREPARE st1; DROP TABLE t1; + +# +# Bug #32137: prepared statement crash with str_to_date in update clause +# +create table t1 (a int, b tinyint); +prepare st1 from 'update t1 set b= (str_to_date(a, a))'; +execute st1; +deallocate prepare st1; +drop table t1; + --echo End of 4.1 tests. ############################# 5.0 tests start ################################ diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index ae18e4786d7..3a2df5125ba 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -3306,38 +3306,42 @@ Field *Item_func_str_to_date::tmp_table_field(TABLE *t_arg) void Item_func_str_to_date::fix_length_and_dec() { - char format_buff[64]; - String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format; maybe_null= 1; decimals=0; cached_field_type= MYSQL_TYPE_STRING; max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; cached_timestamp_type= MYSQL_TIMESTAMP_NONE; - format= args[1]->val_str(&format_str); - if (!args[1]->null_value && (const_item= args[1]->const_item())) + if ((const_item= args[1]->const_item())) { - cached_format_type= get_date_time_result_type(format->ptr(), - format->length()); - switch (cached_format_type) { - case DATE_ONLY: - cached_timestamp_type= MYSQL_TIMESTAMP_DATE; - cached_field_type= MYSQL_TYPE_DATE; - max_length= MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; - break; - case TIME_ONLY: - case TIME_MICROSECOND: - cached_timestamp_type= MYSQL_TIMESTAMP_TIME; - cached_field_type= MYSQL_TYPE_TIME; - max_length= MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; - break; - default: - cached_timestamp_type= MYSQL_TIMESTAMP_DATETIME; - cached_field_type= MYSQL_TYPE_DATETIME; - break; + char format_buff[64]; + String format_str(format_buff, sizeof(format_buff), &my_charset_bin); + String *format= args[1]->val_str(&format_str); + if (!args[1]->null_value) + { + cached_format_type= get_date_time_result_type(format->ptr(), + format->length()); + switch (cached_format_type) { + case DATE_ONLY: + cached_timestamp_type= MYSQL_TIMESTAMP_DATE; + cached_field_type= MYSQL_TYPE_DATE; + max_length= MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN; + break; + case TIME_ONLY: + case TIME_MICROSECOND: + cached_timestamp_type= MYSQL_TIMESTAMP_TIME; + cached_field_type= MYSQL_TYPE_TIME; + max_length= MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN; + break; + default: + cached_timestamp_type= MYSQL_TIMESTAMP_DATETIME; + cached_field_type= MYSQL_TYPE_DATETIME; + break; + } } } } + bool Item_func_str_to_date::get_date(MYSQL_TIME *ltime, uint fuzzy_date) { DATE_TIME_FORMAT date_time_format; -- cgit v1.2.1 From 9e6b13b5f24f22a74bd2a8ca2c008e83cf376c00 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 10 Nov 2007 18:57:09 +0400 Subject: manual merge. --- mysql-test/r/ps.result | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index edac68a88d6..14dec382244 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1143,6 +1143,11 @@ a 13 DEALLOCATE PREPARE st1; DROP TABLE t1; +create table t1 (a int, b tinyint); +prepare st1 from 'update t1 set b= (str_to_date(a, a))'; +execute st1; +deallocate prepare st1; +drop table t1; End of 4.1 tests. create table t1 (a varchar(20)); insert into t1 values ('foo'); -- cgit v1.2.1 From 170b1aa738ba4ecb9d58a82951bbab6efced1c32 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 10 Nov 2007 21:39:30 +0400 Subject: compiler warnings fixed. sql/ha_myisam.cc: compiler warning fixed. sql/unireg.cc: compiler warning fixed. --- sql/ha_myisam.cc | 2 +- sql/unireg.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 92fa9e405e1..66f66dccd99 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -173,7 +173,7 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, pos= table_arg->key_info; for (i= 0; i < share->keys; i++, pos++) { - keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL)); + keydef[i].flag= ((uint16) pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL)); keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ? (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) : pos->algorithm; diff --git a/sql/unireg.cc b/sql/unireg.cc index d8e63bb78e1..9e6c77d7b62 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -394,7 +394,7 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo, pos[6]=pos[7]=0; // For the future pos+=8; key_parts+=key->key_parts; - DBUG_PRINT("loop", ("flags: %d key_parts: %d at 0x%lx", + DBUG_PRINT("loop", ("flags: %lu key_parts: %d at 0x%lx", key->flags, key->key_parts, (long) key->key_part)); for (key_part=key->key_part,key_part_end=key_part+key->key_parts ; -- cgit v1.2.1 From 748446b99c435b9c268f8931878a2474ba6e753f Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 17 Nov 2007 19:05:31 +0100 Subject: Bug#24907: unpredictable (display) precission, if input precission increases Server failed in assert() when we tried to create a DECIMAL() temp field with a scale of more than the allowed 30. Now we limit the scale to the allowed maximum. A truncation warning is thrown as necessary. mysql-test/r/type_newdecimal.result: Show that out of range DECIMAL temp fields will no longer stop the server with an assert. mysql-test/t/type_newdecimal.test: Show that out of range DECIMAL temp fields will no longer stop the server with an assert. sql/sql_select.cc: When creating DECIMAL() temp field, ascertain we stay within allowed limits. If not, truncate and warn. --- mysql-test/r/type_newdecimal.result | 20 +++++++++++++++++++ mysql-test/t/type_newdecimal.test | 21 +++++++++++++++++++- sql/sql_select.cc | 38 +++++++++++++++++++++++++++++++++++-- 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 75d9582a23c..b53b49bd0dd 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1499,4 +1499,24 @@ SELECT 1 FROM t1 GROUP BY @b := @a, @b; 1 1 DROP TABLE t1; +CREATE TABLE t1 SELECT 0.123456789012345678901234567890123456 AS f1; +Warnings: +Note 1265 Data truncated for column 'f1' at row 1 +DESC t1; +Field Type Null Key Default Extra +f1 decimal(31,30) NO 0.000000000000000000000000000000 +SELECT f1 FROM t1; +f1 +0.123456789012345678901234567890 +DROP TABLE t1; +CREATE TABLE t1 SELECT 123451234512345123451234512345123451234512345.678906789067890678906789067890678906789067890 AS f1; +Warnings: +Warning 1264 Out of range value adjusted for column 'f1' at row 1 +DESC t1; +Field Type Null Key Default Extra +f1 decimal(59,30) NO 0.000000000000000000000000000000 +SELECT f1 FROM t1; +f1 +99999999999999999999999999999.999999999999999999999999999999 +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 5a631b6163e..cb7e0c4163a 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1195,6 +1195,25 @@ SELECT 1 FROM t1 GROUP BY @b := @a, @b; DROP TABLE t1; ---echo End of 5.0 tests +# +# Bug #24907: unpredictable (display) precission, if input precission +# increases +# +# As per 10.1.1. Overview of Numeric Types, type (new) DECIMAL has a +# maxmimum precision of 30 places after the decimal point. Show that +# temp field creation beyond that works and throws a truncation warning. +# DECIMAL(37,36) should be adjusted to DECIMAL(31,30). +CREATE TABLE t1 SELECT 0.123456789012345678901234567890123456 AS f1; +DESC t1; +SELECT f1 FROM t1; +DROP TABLE t1; +# too many decimal places, AND too many digits altogether (90 = 45+45). +# should preserve integers (65 = 45+20) +CREATE TABLE t1 SELECT 123451234512345123451234512345123451234512345.678906789067890678906789067890678906789067890 AS f1; +DESC t1; +SELECT f1 FROM t1; +DROP TABLE t1; + +--echo End of 5.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1d11f23d854..8227d09fe85 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8960,9 +8960,43 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, new_field->set_derivation(item->collation.derivation); break; case DECIMAL_RESULT: - new_field= new Field_new_decimal(item->max_length, maybe_null, item->name, - table, item->decimals, item->unsigned_flag); + { + uint8 dec= item->decimals; + uint8 intg= ((Item_decimal *) item)->decimal_precision() - dec; + uint8 len= item->max_length; + + /* + Trying to put too many digits overall in a DECIMAL(prec,dec) + will always throw a warning. We must limit dec to + DECIMAL_MAX_SCALE however to prevent an assert() later. + */ + + if (dec > 0) + { + signed int overflow; + + dec= min(dec, DECIMAL_MAX_SCALE); + + /* + If the value still overflows the field with the corrected dec, + we'll throw out decimals rather than integers. This is still + bad and of course throws a truncation warning. + +1: for decimal point + */ + + overflow= my_decimal_precision_to_length(intg + dec, dec, + item->unsigned_flag) - len; + + if (overflow > 0) + dec= max(0, dec - overflow); // too long, discard fract + else + len -= item->decimals - dec; // corrected value fits + } + + new_field= new Field_new_decimal(len, maybe_null, item->name, + table, dec, item->unsigned_flag); break; + } case ROW_RESULT: default: // This case should never be choosen -- cgit v1.2.1 From e473ffaa7e2c90989706d3c731c88fc6a0136e9c Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 17 Nov 2007 19:42:16 +0100 Subject: Bug#24907: unpredictable (display) precission, if input precission increases post-merge fixes: some things work differently in 5.1 mysql-test/r/type_newdecimal.result: post-merge fix: 5.1 throws different warning here sql/sql_select.cc: post-merge fix: signature has changed in 5.1 --- mysql-test/r/type_newdecimal.result | 2 +- sql/sql_select.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 32ee4b810b8..71be41b106f 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1521,7 +1521,7 @@ f1 DROP TABLE t1; CREATE TABLE t1 SELECT 123451234512345123451234512345123451234512345.678906789067890678906789067890678906789067890 AS f1; Warnings: -Warning 1264 Out of range value adjusted for column 'f1' at row 1 +Warning 1264 Out of range value for column 'f1' at row 1 DESC t1; Field Type Null Key Default Extra f1 decimal(59,30) NO 0.000000000000000000000000000000 diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 65d9e3deddb..97b8f3ff14a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9219,7 +9219,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, } new_field= new Field_new_decimal(len, maybe_null, item->name, - table, dec, item->unsigned_flag); + dec, item->unsigned_flag); break; } case ROW_RESULT: -- cgit v1.2.1 From f97e4d319d9d219f3cc849220b8589a1698bf502 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Nov 2007 10:25:07 +0100 Subject: BUG#27850 "mysqldump --single-transaction does not work if TRUNCATE/DROP/RENAME/ALTER": this has already been closed by a note in the manual, now we complete this by a note in "mysqldump --help" client/mysqldump.c: mention, in "mysqldump --help", of limitations reported as BUG#27850 "mysqldump --single-transaction does not work if TRUNCATE/DROP/RENAME/ALTER" The new text is inspired from what the "mysqldump" section of the manual now says about --single-transaction: http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html --- client/mysqldump.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 4916492201b..0b4951e1cf3 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -404,8 +404,12 @@ static struct my_option my_long_options[] = "Creates a consistent snapshot by dumping all tables in a single " "transaction. Works ONLY for tables stored in storage engines which " "support multiversioning (currently only InnoDB does); the dump is NOT " - "guaranteed to be consistent for other storage engines. Option " - "automatically turns off --lock-tables.", + "guaranteed to be consistent for other storage engines. " + "While a --single-transaction dump is in process, to ensure a valid " + "dump file (correct table contents and binary log position), no other " + "connection should use the following statements: ALTER TABLE, DROP " + "TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not " + "isolated from them. Option automatically turns off --lock-tables.", (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-opt", OPT_SKIP_OPTIMIZATION, -- cgit v1.2.1 From 1615f83804ae40db405d2537cd3bea02f4730d80 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 1 Dec 2007 10:05:59 +0300 Subject: Fix for bug #26788 "mysqld (debug) aborts when inserting specific numbers into char fields" and bug #12860 "Difference in zero padding of exponent between Unix and Windows" Rewrote the code that determines what 'precision' argument should be passed to sprintf() to fit the string representation of the input number into the field. We get finer control over conversion by pre-calculating the exponent, so we are able to determine which conversion format, 'e' or 'f', will be used by sprintf(). We also remove the leading zero from the exponent on Windows to make it compatible with the sprintf() output on other platforms. mysql-test/r/insert.result: Added test cases for bug #26788 and bug #31152. mysql-test/t/cast.test: Removed --replace_result, since the result is now correct on Windows. mysql-test/t/insert.test: Added test cases for bug #26788 and bug #31152. mysql-test/t/type_float.test: Removed --replace_result, since the result is now correct on Windows. mysql-test/t/variables.test: Removed --replace_result, since the result is now correct on Windows. sql/field.cc: Rewrote the code that determines what 'precision' argument should be passed to sprintf() to fit the string representation of the input number into the field. We get finer control over conversion by pre-calculating the exponent, so we are able to determine which conversion format, 'e' or 'f', will be used by sprintf(). --- mysql-test/r/insert.result | 120 +++++++++++++++++++++++++++++++++++++++++++ mysql-test/t/cast.test | 2 - mysql-test/t/insert.test | 81 +++++++++++++++++++++++++++++ mysql-test/t/type_float.test | 5 -- mysql-test/t/variables.test | 2 - sql/field.cc | 76 +++++++++++++++++++++------ 6 files changed, 262 insertions(+), 24 deletions(-) diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result index 8a0a3ba848c..0571d31fe57 100644 --- a/mysql-test/r/insert.result +++ b/mysql-test/r/insert.result @@ -461,4 +461,124 @@ i 2 2 DROP TABLE t1, t2; +CREATE TABLE t1 ( +a char(20) NOT NULL, +b char(7) DEFAULT NULL, +c char(4) DEFAULT NULL +); +INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0); +INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04); +INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01); +INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01); +INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01); +INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01); +INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05); +INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10); +INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15); +INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0); +INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78); +INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94); +INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203); +INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175); +INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0); +INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0); +INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0); +INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +SELECT * FROM t1; +a b c +9.999999000000000748 10 10 +1.225e-05 1.2e-05 1e-0 +0.0001225 0.00012 NULL +0.122499999999999998 0.1225 NULL +0.122587699999999994 0.12259 NULL +12.25 12.25 NULL +12.25 12.25 12.2 +122500 122500 NULL +12250000000 1.2e+10 NULL +1225000000000000 1.2e+15 NULL +5000000 5000000 NULL +1.25e+78 1.2e+78 NULL +1.25e-94 1.2e-94 NULL +1.25e+203 1e+203 NULL +1.25e-175 1e-175 NULL +1.225000000000000089 NULL 1.23 +1.370000000000000107 NULL 1.37 +-1.37 NULL -1.3 +0.00187 NULL 0.00 +-0.0187 NULL -0.0 +5000 NULL 5000 +-5000 NULL -500 +DROP TABLE t1; +CREATE TABLE t1 ( +a char(20) NOT NULL, +b char(7) DEFAULT NULL, +c char(5) +); +INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0); +INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05); +INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04); +INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01); +INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01); +INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01); +INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01); +INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05); +INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10); +INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15); +INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0); +INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78); +INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94); +INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203); +INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175); +INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0); +INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0); +INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0); +INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3); +INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0); +INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0); +SELECT * FROM t1; +a b c +9.999999000000000748 10 9.999 +1.225e-05 1.2e-05 1e-05 +0.0001225 0.00012 NULL +0.122499999999999998 0.1225 NULL +0.122587699999999994 0.12259 NULL +12.25 12.25 NULL +12.25 12.25 12.25 +122500 122500 NULL +12250000000 1.2e+10 NULL +1225000000000000 1.2e+15 NULL +5000000 5000000 NULL +1.25e+78 1.2e+78 NULL +1.25e-94 1.2e-94 NULL +1.25e+203 1e+203 NULL +1.25e-175 1e-175 NULL +1.225000000000000089 NULL 1.225 +1.370000000000000107 NULL 1.37 +-1.37 NULL -1.37 +0.00187 NULL 0.002 +-0.0187 NULL -0.01 +5000 NULL 5000 +-5000 NULL -5000 +DROP TABLE t1; +CREATE TABLE t (a CHAR(10),b INT); +INSERT INTO t VALUES (),(),(); +INSERT INTO t(a) SELECT rand() FROM t; +DROP TABLE t; End of 5.0 tests. diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index 316b79efe4d..fecb8677d51 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -177,8 +177,6 @@ select cast(1.0e+300 as signed int); CREATE TABLE t1 (f1 double); INSERT INTO t1 SET f1 = -1.0e+30 ; INSERT INTO t1 SET f1 = +1.0e+30 ; -# Expected result is +-1e+30, but Windows returns +-1e+030. ---replace_result 1e+030 1e+30 SELECT f1 AS double_val, CAST(f1 AS SIGNED INT) AS cast_val FROM t1; DROP TABLE t1; diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test index 76177403bd0..cf67935768a 100644 --- a/mysql-test/t/insert.test +++ b/mysql-test/t/insert.test @@ -353,5 +353,86 @@ SELECT * FROM t2; DROP TABLE t1, t2; +# +# Bug #26788: mysqld (debug) aborts when inserting specific numbers into char +# fields +# + +CREATE TABLE t1 ( + a char(20) NOT NULL, + b char(7) DEFAULT NULL, + c char(4) DEFAULT NULL +); + +INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0); +INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05); +INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04); +INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01); +INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01); +INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01); +INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01); +INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05); +INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10); +INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15); +INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0); +INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78); +INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94); +INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203); +INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175); +INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0); +INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0); +INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0); +INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3); +INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2); +INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0); +INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0); + +SELECT * FROM t1; + +DROP TABLE t1; + +CREATE TABLE t1 ( + a char(20) NOT NULL, + b char(7) DEFAULT NULL, + c char(5) +); + + +INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0); +INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05); +INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04); +INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01); +INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01); +INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01); +INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01); +INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05); +INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10); +INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15); +INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0); +INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78); +INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94); +INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203); +INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175); +INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0); +INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0); +INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0); +INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3); +INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2); +INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0); +INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0); + +SELECT * FROM t1; + +DROP TABLE t1; + +# +# Bug #31152: assertion in Field_str::store(double) +# + +CREATE TABLE t (a CHAR(10),b INT); +INSERT INTO t VALUES (),(),(); +INSERT INTO t(a) SELECT rand() FROM t; +DROP TABLE t; + --echo End of 5.0 tests. diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index a55200c8853..f67a1b1719b 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -116,15 +116,10 @@ drop table if exists t1; # Check conversion of floats to character field (Bug #7774) create table t1 (c char(20)); insert into t1 values (5e-28); -# Expected result is "5e-28", but windows returns "5e-028" ---replace_result 5e-028 5e-28 select * from t1; drop table t1; create table t1 (c char(6)); insert into t1 values (2e5),(2e6),(2e-4),(2e-5); -# Expected result is "2e+06", but windows returns "2e+006" -# Expected result is "2e-05", but windows returns "2e-005" ---replace_result 2e+006 2e+06 2e-005 2e-05 select * from t1; drop table t1; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 0ad85a32568..4b78ea6c026 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -51,8 +51,6 @@ select @test, @`test`, @TEST, @`TEST`, @"teSt"; set @select=2,@t5=1.23456; select @`select`,@not_used; set @test_int=10,@test_double=1e-10,@test_string="abcdeghi",@test_string2="abcdefghij",@select=NULL; -# Expected result "1e-10", windows returns "1e-010" ---replace_result 1e-010 1e-10 select @test_int,@test_double,@test_string,@test_string2,@select; set @test_int="hello",@test_double="hello",@test_string="hello",@test_string2="hello"; select @test_int,@test_double,@test_string,@test_string2; diff --git a/sql/field.cc b/sql/field.cc index 8191d885a27..c604f04339c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5907,24 +5907,70 @@ int Field_str::store(double nr) { char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; uint length; - bool use_scientific_notation= TRUE; uint local_char_length= field_length / charset()->mbmaxlen; - /* - Check fabs(nr) against longest value that can be stored in field, - which depends on whether the value is < 1 or not, and negative or not - */ double anr= fabs(nr); int neg= (nr < 0.0) ? 1 : 0; - if (local_char_length > 4 && local_char_length < 32 && - (anr < 1.0 ? anr > 1/(log_10[max(0,(int) local_char_length-neg-2)]) /* -2 for "0." */ - : anr < log_10[local_char_length-neg]-1)) - use_scientific_notation= FALSE; - - length= (uint) my_sprintf(buff, (buff, "%-.*g", - (use_scientific_notation ? - max(0, (int)local_char_length-neg-5) : - local_char_length), - nr)); + uint max_length; + int exp; + uint digits; + uint i; + + /* Calculate the exponent from the 'e'-format conversion */ + if (anr < 1.0 && anr > 0) + { + for (exp= 0; anr < 1e-100; exp-= 100, anr*= 1e100); + for (; anr < 1e-10; exp-= 10, anr*= 1e10); + for (i= 1; anr < 1 / log_10[i]; exp--, i++); + exp--; + } + else + { + for (exp= 0; anr > 1e100; exp+= 100, anr/= 1e100); + for (; anr > 1e10; exp+= 10, anr/= 1e10); + for (i= 1; anr > log_10[i]; exp++, i++); + } + + max_length= local_char_length - neg; + + /* + Since in sprintf("%g") precision means the number of significant digits, + calculate the maximum number of significant digits if the 'f'-format + would be used (+1 for decimal point if the number has a fractional part). + */ + digits= max(0, (int) max_length - (nr != trunc(nr))); + /* + If the exponent is negative, decrease digits by the number of leading zeros + after the decimal point that do not count as significant digits. + */ + if (exp < 0) + digits= max(0, (int) digits + exp); + /* + 'e'-format is used only if the exponent is less than -4 or greater than or + equal to the precision. In this case we need to adjust the number of + significant digits to take "e+NN" + decimal point into account (hence -5). + We also have to reserve one additional character if abs(exp) >= 100. + */ + if (exp >= (int) digits || exp < -4) + digits= max(0, (int) (max_length - 5 - (exp >= 100 || exp <= -100))); + + length= (uint) my_sprintf(buff, (buff, "%-.*g", digits, nr)); + +#ifdef __WIN__ + /* + Windows always zero-pads the exponent to 3 digits, we want to remove the + leading 0 to match the sprintf() output on other platforms. + */ + if ((exp >= (int) digits || exp < -4) && exp > -100 && exp < 100) + { + DBUG_ASSERT(length >= 6); /* 1e+NNN */ + uint tmp= length - 3; + buff[tmp]= buff[tmp + 1]; + tmp++; + buff[tmp]= buff[tmp + 1]; + length--; + } +#endif + /* +1 below is because "precision" in %g above means the max. number of significant digits, not the output width. -- cgit v1.2.1 From d8d07eff702b303b9458ac5622bdc42e5a0c1f93 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 1 Dec 2007 12:46:25 +0300 Subject: Fixed the build failure on Windows. It does not have trunc() defined in math.h, so we should not use it code. --- sql/field.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/field.cc b/sql/field.cc index c604f04339c..1878797297f 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5909,6 +5909,7 @@ int Field_str::store(double nr) uint length; uint local_char_length= field_length / charset()->mbmaxlen; double anr= fabs(nr); + bool fractional= (anr != floor(anr)); int neg= (nr < 0.0) ? 1 : 0; uint max_length; int exp; @@ -5937,7 +5938,7 @@ int Field_str::store(double nr) calculate the maximum number of significant digits if the 'f'-format would be used (+1 for decimal point if the number has a fractional part). */ - digits= max(0, (int) max_length - (nr != trunc(nr))); + digits= max(0, (int) max_length - fractional); /* If the exponent is negative, decrease digits by the number of leading zeros after the decimal point that do not count as significant digits. -- cgit v1.2.1 From 1f22720c3f6bf28a44ee0e3a9a9abd52e9debe64 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 1 Dec 2007 15:25:24 +0300 Subject: Fixed the floating point number tests on Windows. mysql-test/r/insert.result: Fixed the test cases. mysql-test/t/cast.test: We need to do replace_result because warnings are printed by another procedure. mysql-test/t/insert.test: Windows implements a different rounding rules in printf("%g"), thus we still need to do replace_result. sql/field.cc: Limit the precision to avoid garbage past the significant digits. --- mysql-test/r/insert.result | 24 ++++++++++++------------ mysql-test/t/cast.test | 2 ++ mysql-test/t/insert.test | 4 +++- sql/field.cc | 2 +- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result index 0571d31fe57..36cfeec1b3a 100644 --- a/mysql-test/r/insert.result +++ b/mysql-test/r/insert.result @@ -500,23 +500,23 @@ Warnings: Warning 1265 Data truncated for column 'c' at row 1 SELECT * FROM t1; a b c -9.999999000000000748 10 10 +9.999999 10 10 1.225e-05 1.2e-05 1e-0 0.0001225 0.00012 NULL -0.122499999999999998 0.1225 NULL -0.122587699999999994 0.12259 NULL +0.1225 0.1225 NULL +0.1225877 0.12259 NULL 12.25 12.25 NULL 12.25 12.25 12.2 122500 122500 NULL 12250000000 1.2e+10 NULL -1225000000000000 1.2e+15 NULL +1.225e+15 1.2e+15 NULL 5000000 5000000 NULL 1.25e+78 1.2e+78 NULL 1.25e-94 1.2e-94 NULL 1.25e+203 1e+203 NULL 1.25e-175 1e-175 NULL -1.225000000000000089 NULL 1.23 -1.370000000000000107 NULL 1.37 +1.225 NULL 1.23 +1.37 NULL 1.37 -1.37 NULL -1.3 0.00187 NULL 0.00 -0.0187 NULL -0.0 @@ -554,23 +554,23 @@ INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0); INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0); SELECT * FROM t1; a b c -9.999999000000000748 10 9.999 +9.999999 10 9.999 1.225e-05 1.2e-05 1e-05 0.0001225 0.00012 NULL -0.122499999999999998 0.1225 NULL -0.122587699999999994 0.12259 NULL +0.1225 0.1225 NULL +0.1225877 0.12259 NULL 12.25 12.25 NULL 12.25 12.25 12.25 122500 122500 NULL 12250000000 1.2e+10 NULL -1225000000000000 1.2e+15 NULL +1.225e+15 1.2e+15 NULL 5000000 5000000 NULL 1.25e+78 1.2e+78 NULL 1.25e-94 1.2e-94 NULL 1.25e+203 1e+203 NULL 1.25e-175 1e-175 NULL -1.225000000000000089 NULL 1.225 -1.370000000000000107 NULL 1.37 +1.225 NULL 1.225 +1.37 NULL 1.37 -1.37 NULL -1.37 0.00187 NULL 0.002 -0.0187 NULL -0.01 diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index fecb8677d51..316b79efe4d 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -177,6 +177,8 @@ select cast(1.0e+300 as signed int); CREATE TABLE t1 (f1 double); INSERT INTO t1 SET f1 = -1.0e+30 ; INSERT INTO t1 SET f1 = +1.0e+30 ; +# Expected result is +-1e+30, but Windows returns +-1e+030. +--replace_result 1e+030 1e+30 SELECT f1 AS double_val, CAST(f1 AS SIGNED INT) AS cast_val FROM t1; DROP TABLE t1; diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test index cf67935768a..3c150d0c3f6 100644 --- a/mysql-test/t/insert.test +++ b/mysql-test/t/insert.test @@ -386,7 +386,9 @@ INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3); INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2); INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0); INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0); - +# Expected results are "12.2" and "1.2e+78", but Windows returns "12.3" and +# "1.3e+78" due to different rounding rules +--replace_result 12.3 12.2 1.3e+78 1.2e+78 SELECT * FROM t1; DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index 1878797297f..a9aca5dc6e0 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5954,7 +5954,7 @@ int Field_str::store(double nr) if (exp >= (int) digits || exp < -4) digits= max(0, (int) (max_length - 5 - (exp >= 100 || exp <= -100))); - length= (uint) my_sprintf(buff, (buff, "%-.*g", digits, nr)); + length= (uint) my_sprintf(buff, (buff, "%-.*g", min(digits, DBL_DIG ), nr)); #ifdef __WIN__ /* -- cgit v1.2.1 From 5fd87abaa81c80cbcc4526bf6424e7ae24362fbd Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 2 Dec 2007 13:49:12 +0300 Subject: Windows-specific fixes in floating point tests. mysql-test/t/insert.test: Windows implements a different rounding rules in printf("%g"), thus we still need to do replace_result mysql-test/t/variables.test: We need to do replace_result because variables are printed by another procedure. sql/field.cc: Fixed the code to limit the precision to DBL_DIG. --- mysql-test/t/insert.test | 3 +++ mysql-test/t/variables.test | 2 ++ sql/field.cc | 5 ++++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test index 3c150d0c3f6..5cb85d32383 100644 --- a/mysql-test/t/insert.test +++ b/mysql-test/t/insert.test @@ -423,6 +423,9 @@ INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2); INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0); INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0); +# Expected results are "12.2" and "1.2e+78", but Windows returns "12.3" and +# "1.3e+78" due to different rounding rules +--replace_result 12.3 12.2 1.3e+78 1.2e+78 SELECT * FROM t1; DROP TABLE t1; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 4b78ea6c026..0ad85a32568 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -51,6 +51,8 @@ select @test, @`test`, @TEST, @`TEST`, @"teSt"; set @select=2,@t5=1.23456; select @`select`,@not_used; set @test_int=10,@test_double=1e-10,@test_string="abcdeghi",@test_string2="abcdefghij",@select=NULL; +# Expected result "1e-10", windows returns "1e-010" +--replace_result 1e-010 1e-10 select @test_int,@test_double,@test_string,@test_string2,@select; set @test_int="hello",@test_double="hello",@test_string="hello",@test_string2="hello"; select @test_int,@test_double,@test_string,@test_string2; diff --git a/sql/field.cc b/sql/field.cc index a9aca5dc6e0..31d2af1bb14 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5953,8 +5953,11 @@ int Field_str::store(double nr) */ if (exp >= (int) digits || exp < -4) digits= max(0, (int) (max_length - 5 - (exp >= 100 || exp <= -100))); + + /* Limit precision to DBL_DIG to avoid garbage past significant digits */ + set_if_smaller(digits, DBL_DIG); - length= (uint) my_sprintf(buff, (buff, "%-.*g", min(digits, DBL_DIG ), nr)); + length= (uint) my_sprintf(buff, (buff, "%-.*g", digits, nr)); #ifdef __WIN__ /* -- cgit v1.2.1 From 98ab044d8f64742a863b62f449faf19269e715ca Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 5 Dec 2007 13:54:11 -0700 Subject: Post-merge fix (reorder tests in ctype_ucs.test) mysql-test/t/ctype_ucs.test: Post-merge fix (fix order of tests to match results). --- mysql-test/t/ctype_ucs.test | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index e5c21bb72a0..3af5bfa54f9 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -547,14 +547,6 @@ select quote(name) from bug20536; drop table bug20536; -# -# BUG#31159 - fulltext search on ucs2 column crashes server -# -CREATE TABLE t1(a TEXT CHARSET ucs2 COLLATE ucs2_unicode_ci); -INSERT INTO t1 VALUES('abcd'); -SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abcd' IN BOOLEAN MODE); -DROP TABLE t1; - # # Bug #31615: crash after set names ucs2 collate xxx # @@ -567,6 +559,14 @@ set character_set_client= ucs2; --error 1231 set character_set_client= concat('ucs', substr('2', 1)); +# +# BUG#31159 - fulltext search on ucs2 column crashes server +# +CREATE TABLE t1(a TEXT CHARSET ucs2 COLLATE ucs2_unicode_ci); +INSERT INTO t1 VALUES('abcd'); +SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abcd' IN BOOLEAN MODE); +DROP TABLE t1; + --echo End of 4.1 tests # -- cgit v1.2.1 From 18d14b3a85dfcadacb5a8e33ead4bc8d5bf29d95 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 6 Dec 2007 15:05:24 -0700 Subject: ctype-simple.c: Backport quick fix to remove Windows compiler warnings strings/ctype-simple.c: Backport quick fix to remove Windows compiler warnings. --- strings/ctype-simple.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 0355803daa8..d497eec4550 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -802,7 +802,7 @@ int my_long10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)), { if (val < 0) { - val= -(unsigned long int)val; + val= ULL(0) - (unsigned long int)val; *dst++= '-'; len--; sign= 1; @@ -838,7 +838,7 @@ int my_longlong10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)), { if (val < 0) { - val = -(ulonglong)val; + val = ULL(0) - (ulonglong)val; *dst++= '-'; len--; sign= 1; -- cgit v1.2.1 From 2632dbf6ebdf70748483e1d3bc0a4c0e0285ec61 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 6 Dec 2007 16:11:26 -0700 Subject: Fix compiler warning about wrong integer size (probably harmless) sql/sql_select.cc: Fix compiler warning (probably harmless, wrong integer size) --- sql/sql_select.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2ca4b73a115..5699f1d1868 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8991,7 +8991,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, { uint8 dec= item->decimals; uint8 intg= ((Item_decimal *) item)->decimal_precision() - dec; - uint8 len= item->max_length; + uint32 len= item->max_length; /* Trying to put too many digits overall in a DECIMAL(prec,dec) -- cgit v1.2.1 From 20bbe71d73013fcb2d40be213592650539b38560 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 Dec 2007 00:54:32 -0700 Subject: Move the test case for bug #20901 from create.test to grant.test, so testing embedded server works correctly. mysql-test/r/create.result: Move one test from create.test to grant.test, because it actually tests privileges (and thus doesn't work with embedded server). mysql-test/r/grant.result: Move one test from create.test to grant.test, because it actually tests privileges (and thus doesn't work with embedded server). mysql-test/t/create.test: Move one test from create.test to grant.test, because it actually tests privileges (and thus doesn't work with embedded server). mysql-test/t/grant.test: Move one test from create.test to grant.test, because it actually tests privileges (and thus doesn't work with embedded server). --- mysql-test/r/create.result | 38 ---------------------- mysql-test/r/grant.result | 39 +++++++++++++++++++++++ mysql-test/t/create.test | 76 -------------------------------------------- mysql-test/t/grant.test | 78 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 114 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 23d2013cba5..73a9dba4e69 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -763,44 +763,6 @@ t2 CREATE TABLE `t2` ( drop table t1, t2; create table t1(a set("a,b","c,d") not null); ERROR 22007: Illegal set 'a,b' value found during parsing -create database mysqltest; -use mysqltest; -grant create on mysqltest.* to mysqltest@localhost; -create table t1 (i INT); -insert into t1 values (1); -ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' -create table t2 (i INT); -create table t4 (i INT); -grant select, insert on mysqltest.t2 to mysqltest@localhost; -grant insert on mysqltest.t4 to mysqltest@localhost; -grant create, insert on mysqltest.t5 to mysqltest@localhost; -grant create, insert on mysqltest.t6 to mysqltest@localhost; -flush privileges; -insert into t2 values (1); -create table if not exists t1 select * from t2; -ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' -create table if not exists t3 select * from t2; -ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't3' -create table if not exists t4 select * from t2; -Warnings: -Note 1050 Table 't4' already exists -create table if not exists t5 select * from t2; -create table t6 select * from t2; -create table t7 select * from t2; -ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't7' -create table t4 select * from t2; -ERROR 42S01: Table 't4' already exists -create table t1 select * from t2; -ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' -drop table t1,t2,t4,t5,t6; -revoke create on mysqltest.* from mysqltest@localhost; -revoke select, insert on mysqltest.t2 from mysqltest@localhost; -revoke insert on mysqltest.t4 from mysqltest@localhost; -revoke create, insert on mysqltest.t5 from mysqltest@localhost; -revoke create, insert on mysqltest.t6 from mysqltest@localhost; -flush privileges; -drop database mysqltest; -use test; create table t1 (i int) engine=myisam max_rows=100000000000; show create table t1; Table Create Table diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 4d402d7d0e9..5df0b4d9448 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -1226,3 +1226,42 @@ drop user юзер_юзер@localhost; grant select on test.* to очень_длинный_юзер@localhost; ERROR HY000: String 'очень_длинный_юзер' is too long for user name (should be no longer than 16) set names default; +create database mysqltest; +use mysqltest; +grant create on mysqltest.* to mysqltest@localhost; +create table t1 (i INT); +insert into t1 values (1); +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' +create table t2 (i INT); +create table t4 (i INT); +grant select, insert on mysqltest.t2 to mysqltest@localhost; +grant insert on mysqltest.t4 to mysqltest@localhost; +grant create, insert on mysqltest.t5 to mysqltest@localhost; +grant create, insert on mysqltest.t6 to mysqltest@localhost; +flush privileges; +insert into t2 values (1); +create table if not exists t1 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' +create table if not exists t3 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't3' +create table if not exists t4 select * from t2; +Warnings: +Note 1050 Table 't4' already exists +create table if not exists t5 select * from t2; +create table t6 select * from t2; +create table t7 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't7' +create table t4 select * from t2; +ERROR 42S01: Table 't4' already exists +create table t1 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' +drop table t1,t2,t4,t5,t6; +revoke create on mysqltest.* from mysqltest@localhost; +revoke select, insert on mysqltest.t2 from mysqltest@localhost; +revoke insert on mysqltest.t4 from mysqltest@localhost; +revoke create, insert on mysqltest.t5 from mysqltest@localhost; +revoke create, insert on mysqltest.t6 from mysqltest@localhost; +drop user mysqltest@localhost; +drop database mysqltest; +use test; +End of 5.1 tests diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 15c36dfff84..45ee4c1c88d 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -658,82 +658,6 @@ drop table t1, t2; --error 1367 create table t1(a set("a,b","c,d") not null); -# -# Bug #20901 - CREATE privilege is enough to insert into a table -# - -create database mysqltest; -use mysqltest; - -grant create on mysqltest.* to mysqltest@localhost; -create table t1 (i INT); - -connect (user1,localhost,mysqltest,,mysqltest); -connection user1; -# show we don't have INSERT ---error 1142 -insert into t1 values (1); -# show we have CREATE -create table t2 (i INT); -create table t4 (i INT); - -connection default; -grant select, insert on mysqltest.t2 to mysqltest@localhost; -grant insert on mysqltest.t4 to mysqltest@localhost; -# to specify ACLs for non-existent objects, must explictly |CREATE -grant create, insert on mysqltest.t5 to mysqltest@localhost; -grant create, insert on mysqltest.t6 to mysqltest@localhost; -flush privileges; - -connection user1; -insert into t2 values (1); - - -# CREATE IF NOT EXISTS...SELECT, t1 exists, no INSERT, must fail ---error 1142 -create table if not exists t1 select * from t2; - -# CREATE IF NOT EXISTS...SELECT, no t3 yet, no INSERT, must fail ---error 1142 -create table if not exists t3 select * from t2; - -# CREATE IF NOT EXISTS...SELECT, t4 exists, have INSERT, must succeed -create table if not exists t4 select * from t2; - -# CREATE IF NOT EXISTS...SELECT, no t5 yet, have INSERT, must succeed -create table if not exists t5 select * from t2; - - -# CREATE...SELECT, no t6 yet, have INSERT, must succeed -create table t6 select * from t2; - -# CREATE...SELECT, no t7 yet, no INSERT, must fail ---error 1142 -create table t7 select * from t2; - -# CREATE...SELECT, t4 exists, have INSERT, must still fail (exists) ---error 1050 -create table t4 select * from t2; - -# CREATE...SELECT, t1 exists, no INSERT, must fail ---error 1142 -create table t1 select * from t2; - - -connection default; -drop table t1,t2,t4,t5,t6; - -revoke create on mysqltest.* from mysqltest@localhost; -revoke select, insert on mysqltest.t2 from mysqltest@localhost; -revoke insert on mysqltest.t4 from mysqltest@localhost; -revoke create, insert on mysqltest.t5 from mysqltest@localhost; -revoke create, insert on mysqltest.t6 from mysqltest@localhost; -flush privileges; - -disconnect user1; -drop database mysqltest; -use test; - # End of 4.1 tests diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 8d909d63f51..73775c95d52 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -1277,3 +1277,81 @@ drop user юзер_юзер@localhost; --error ER_WRONG_STRING_LENGTH grant select on test.* to очень_длинный_юзер@localhost; set names default; + +# +# Bug #20901 - CREATE privilege is enough to insert into a table +# + +create database mysqltest; +use mysqltest; + +grant create on mysqltest.* to mysqltest@localhost; +create table t1 (i INT); + +connect (user1,localhost,mysqltest,,mysqltest); +connection user1; +# show we don't have INSERT +--error 1142 +insert into t1 values (1); +# show we have CREATE +create table t2 (i INT); +create table t4 (i INT); + +connection default; +grant select, insert on mysqltest.t2 to mysqltest@localhost; +grant insert on mysqltest.t4 to mysqltest@localhost; +# to specify ACLs for non-existent objects, must explictly |CREATE +grant create, insert on mysqltest.t5 to mysqltest@localhost; +grant create, insert on mysqltest.t6 to mysqltest@localhost; +flush privileges; + +connection user1; +insert into t2 values (1); + + +# CREATE IF NOT EXISTS...SELECT, t1 exists, no INSERT, must fail +--error 1142 +create table if not exists t1 select * from t2; + +# CREATE IF NOT EXISTS...SELECT, no t3 yet, no INSERT, must fail +--error 1142 +create table if not exists t3 select * from t2; + +# CREATE IF NOT EXISTS...SELECT, t4 exists, have INSERT, must succeed +create table if not exists t4 select * from t2; + +# CREATE IF NOT EXISTS...SELECT, no t5 yet, have INSERT, must succeed +create table if not exists t5 select * from t2; + + +# CREATE...SELECT, no t6 yet, have INSERT, must succeed +create table t6 select * from t2; + +# CREATE...SELECT, no t7 yet, no INSERT, must fail +--error 1142 +create table t7 select * from t2; + +# CREATE...SELECT, t4 exists, have INSERT, must still fail (exists) +--error 1050 +create table t4 select * from t2; + +# CREATE...SELECT, t1 exists, no INSERT, must fail +--error 1142 +create table t1 select * from t2; + + +connection default; +drop table t1,t2,t4,t5,t6; + +revoke create on mysqltest.* from mysqltest@localhost; +revoke select, insert on mysqltest.t2 from mysqltest@localhost; +revoke insert on mysqltest.t4 from mysqltest@localhost; +revoke create, insert on mysqltest.t5 from mysqltest@localhost; +revoke create, insert on mysqltest.t6 from mysqltest@localhost; +drop user mysqltest@localhost; + +disconnect user1; +drop database mysqltest; +use test; + +--echo End of 5.1 tests -- cgit v1.2.1 From 7d3a61e1f02ce2e890ab9825a791a1f075f31997 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 Dec 2007 03:39:37 -0700 Subject: Make tests more robust (clean up better after grant.test) mysql-test/r/grant.result: Update test results to .test changes mysql-test/t/grant.test: Drop users when done with them, to avoid skewing results of later tests. For example, running some test which examines the cardinality of the mysql.user table would fail if run right after this test, due to the extra users. --- mysql-test/r/grant.result | 2 ++ mysql-test/t/grant.test | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 855352a2195..e27ef64af43 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -1105,6 +1105,7 @@ ERROR 42000: SELECT command denied to user 'mysqltest_2'@'localhost' for table ' DROP DATABASE mysqltest1; DROP DATABASE mysqltest2; DROP USER mysqltest_1@localhost; +DROP USER mysqltest_2@localhost; use test; CREATE TABLE t1 (f1 int, f2 int); INSERT INTO t1 VALUES(1,1), (2,2); @@ -1124,6 +1125,7 @@ f1 f2 REVOKE UPDATE (f1) ON `test`.`t1` FROM 'mysqltest_1'@'localhost'; REVOKE SELECT ON `test`.* FROM 'mysqltest_1'@'localhost'; REVOKE ALL ON db27878.* FROM 'mysqltest_1'@'localhost'; +DROP USER mysqltest_1@localhost; DROP DATABASE db27878; use test; DROP TABLE t1; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 1d11a669811..ed95d90c8f8 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -1122,6 +1122,7 @@ DROP DATABASE mysqltest1; DROP DATABASE mysqltest2; DROP USER mysqltest_1@localhost; +DROP USER mysqltest_2@localhost; # # Bug#27878: Unchecked privileges on a view referring to a table from another @@ -1147,6 +1148,7 @@ connection default; REVOKE UPDATE (f1) ON `test`.`t1` FROM 'mysqltest_1'@'localhost'; REVOKE SELECT ON `test`.* FROM 'mysqltest_1'@'localhost'; REVOKE ALL ON db27878.* FROM 'mysqltest_1'@'localhost'; +DROP USER mysqltest_1@localhost; DROP DATABASE db27878; use test; DROP TABLE t1; -- cgit v1.2.1