From 6515400d92058681f21fe90dc7ebf7452287ca6d Mon Sep 17 00:00:00 2001 From: "jimw@mysql.com" <> Date: Mon, 7 Feb 2005 15:17:30 -0800 Subject: [PATCH 01/14] Add the zlib .libs directory to LD_LIBRARY_PATH in mysql-test-run.sh, which fixes running the tests when using the bundled zlib. --- mysql-test/mysql-test-run.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 39d3f0492c2..af432f37868 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -194,8 +194,8 @@ MY_LOG_DIR="$MYSQL_TEST_DIR/var/log" # # Set LD_LIBRARY_PATH if we are using shared libraries # -LD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$LD_LIBRARY_PATH" -DYLD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$DYLD_LIBRARY_PATH" +LD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$BASEDIR/zlib/.libs:$LD_LIBRARY_PATH" +DYLD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$BASEDIR/zlib/.libs:$DYLD_LIBRARY_PATH" export LD_LIBRARY_PATH DYLD_LIBRARY_PATH MASTER_RUNNING=0 From fcfc1d8f2996b5212c89e1cb5b9d8ca1cbaf4833 Mon Sep 17 00:00:00 2001 From: "jan@hundin.mysql.fi" <> Date: Tue, 8 Feb 2005 09:36:36 +0200 Subject: [PATCH 02/14] Relaxed locking in INSERT...SELECT, single table UPDATE...SELECT and single table DELETE...SELECT clauses when innobase_locks_unsafe_for_binlog is used and isolation level of the transaction is not serializable. InnoDB uses consistent read in these cases for a selected table. Backported from 5.0.x. --- sql/ha_innodb.cc | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 1d75ce99aee..702139624ff 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -5282,8 +5282,27 @@ ha_innobase::store_lock( are not simple SELECTs; note that select_lock_type in this case may get strengthened in ::external_lock() to LOCK_X. */ - prebuilt->select_lock_type = LOCK_S; - prebuilt->stored_select_lock_type = LOCK_S; + if (srv_locks_unsafe_for_binlog && + prebuilt->trx->isolation_level != TRX_ISO_SERIALIZABLE && + (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) && + thd->lex->sql_command != SQLCOM_SELECT && + thd->lex->sql_command != SQLCOM_UPDATE_MULTI && + thd->lex->sql_command != SQLCOM_DELETE_MULTI ) { + + /* In case we have innobase_locks_unsafe_for_binlog + option set and isolation level of the transaction + is not set to serializable and MySQL is doing + INSERT INTO...SELECT without FOR UPDATE or IN + SHARE MODE we use consistent read for select. + Similarly, in case of DELETE...SELECT and + UPDATE...SELECT when these are not multi table.*/ + + prebuilt->select_lock_type = LOCK_NONE; + prebuilt->stored_select_lock_type = LOCK_NONE; + } else { + prebuilt->select_lock_type = LOCK_S; + prebuilt->stored_select_lock_type = LOCK_S; + } } else if (lock_type != TL_IGNORE) { From 79ec81071a7a3468365e587be1ec7f68b11fe960 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Tue, 8 Feb 2005 14:41:09 +0200 Subject: [PATCH 03/14] Better bugfix for "HAVING when refering to RAND()" (Bug #8216) Ensure that references in HAVING, ORDER BY or GROUP BY are calculated after fields in SELECT. This will ensure that any reference to these has a valid value. Generalized the code for split_sum_func() --- .bzrignore | 1 + mysql-test/r/group_by.result | 4 +-- mysql-test/r/user_var.result | 4 +-- mysql-test/t/group_by.test | 3 ++- sql/item.cc | 52 ++++++++++++++++++++++++++++++++++++ sql/item.h | 3 +++ sql/item_cmpfunc.cc | 52 +++++------------------------------- sql/item_func.cc | 20 +++----------- sql/item_row.cc | 19 ++----------- sql/item_strfunc.cc | 15 +---------- sql/sql_list.h | 9 +++++++ sql/sql_select.cc | 14 +++++++++- 12 files changed, 96 insertions(+), 100 deletions(-) diff --git a/.bzrignore b/.bzrignore index 199da0dd558..f43a67af883 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1007,3 +1007,4 @@ tests/mysql_client_test libmysqld/examples/mysql_client_test.c libmysqld/examples/mysql_client_test_embedded libmysqld/examples/mysqltest_embedded +support-files/ndb-config-2-node.ini diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 17b1bb03d1d..7f365eac58a 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -655,9 +655,9 @@ insert into t1 (a,b) values (1,2),(1,3),(2,5); select a, 0.1*0+1 r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2=1; a r2 r1 1 1.0 2 -select a, rand()*0+1 r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2=1; +select a, round(rand(100)*10) r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2<=2; a r2 r1 -1 1 2 +1 2 2 select a,sum(b) from t1 where a=1 group by c; a sum(b) 1 5 diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 041d1b836b7..81846391795 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -109,8 +109,8 @@ select @a:=0; select @a, @a:=@a+count(*), count(*), @a from t1 group by i; @a @a:=@a+count(*) count(*) @a 0 1 1 0 -0 3 2 0 -0 6 3 0 +0 2 2 0 +0 3 3 0 select @a:=0; @a:=0 0 diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 379f668df1a..afd479c520e 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -480,7 +480,8 @@ drop table t1; create table t1 (a integer, b integer, c integer); insert into t1 (a,b) values (1,2),(1,3),(2,5); select a, 0.1*0+1 r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2=1; -select a, rand()*0+1 r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2=1; +# rand(100)*10 will be < 2 only for the first row (of 6) +select a, round(rand(100)*10) r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2<=2; select a,sum(b) from t1 where a=1 group by c; select a*sum(b) from t1 where a=1 group by c; select sum(a)*sum(b) from t1 where a=1 group by c; diff --git a/sql/item.cc b/sql/item.cc index d61d628e8fa..17d41fda677 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -295,6 +295,58 @@ CHARSET_INFO *Item::default_charset() } +/* + Move SUM items out from item tree and replace with reference + + SYNOPSIS + split_sum_func2() + thd Thread handler + ref_pointer_array Pointer to array of reference fields + fields All fields in select + ref Pointer to item + + NOTES + This is from split_sum_func2() for items that should be split + + All found SUM items are added FIRST in the fields list and + we replace the item with a reference. + + thd->fatal_error() may be called if we are out of memory +*/ + + +void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, + List &fields, Item **ref) +{ + if (type() != SUM_FUNC_ITEM && with_sum_func) + { + /* Will split complicated items and ignore simple ones */ + split_sum_func(thd, ref_pointer_array, fields); + } + else if ((type() == SUM_FUNC_ITEM || + (used_tables() & ~PARAM_TABLE_BIT)) && + type() != REF_ITEM) + { + /* + Replace item with a reference so that we can easily calculate + it (in case of sum functions) or copy it (in case of fields) + + The test above is to ensure we don't do a reference for things + that are constants (PARAM_TABLE_BIT is in effect a constant) + or already referenced (for example an item in HAVING) + */ + uint el= fields.elements; + Item *new_item; + ref_pointer_array[el]= this; + if (!(new_item= new Item_ref(ref_pointer_array + el, 0, name))) + return; // fatal_error is set + fields.push_front(this); + ref_pointer_array[el]= this; + thd->change_item_tree(ref, new_item); + } +} + + /* Aggregate two collations together taking into account their coercibility (aka derivation): diff --git a/sql/item.h b/sql/item.h index e0de7452eec..a8b892292d3 100644 --- a/sql/item.h +++ b/sql/item.h @@ -262,6 +262,9 @@ public: virtual void update_used_tables() {} virtual void split_sum_func(THD *thd, Item **ref_pointer_array, List &fields) {} + /* Called for items that really have to be split */ + void split_sum_func2(THD *thd, Item **ref_pointer_array, List &fields, + Item **ref); virtual bool get_date(TIME *ltime,uint fuzzydate); virtual bool get_time(TIME *ltime); virtual bool get_date_result(TIME *ltime,uint fuzzydate) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 2b9a612da18..a827f316ec1 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1969,10 +1969,10 @@ bool Item_cond::walk(Item_processor processor, byte *arg) Move SUM items out from item tree and replace with reference SYNOPSIS - split_sum_func() - thd Thread handler - ref_pointer_array Pointer to array of reference fields - fields All fields in select + split_sum_func() + thd Thread handler + ref_pointer_array Pointer to array of reference fields + fields All fields in select NOTES This function is run on all expression (SELECT list, WHERE, HAVING etc) @@ -1982,16 +1982,6 @@ bool Item_cond::walk(Item_processor processor, byte *arg) so that we can easily find and calculate them. (Calculation done by update_sum_func() and copy_sum_funcs() in sql_select.cc) - - All found SUM items are added FIRST in the fields list and - we replace the item with a reference. - - We also replace all functions without side effects (like RAND() or UDF's) - that uses columns as arguments. - For functions with side effects, we just remember any fields referred - by the function to ensure that we get a copy of the field value for the - first accepted row. This ensures that we can do things like - SELECT a*SUM(b) FROM t1 WHERE a=1 */ void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array, @@ -1999,38 +1989,8 @@ void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array, { List_iterator li(list); Item *item; - used_tables_cache=0; - const_item_cache=0; - while ((item=li++)) - { - /* with_sum_func is set for items that contains a SUM expression */ - if (item->type() != SUM_FUNC_ITEM && - (item->with_sum_func || - (item->used_tables() & PSEUDO_TABLE_BITS))) - item->split_sum_func(thd, ref_pointer_array, fields); - else if (item->type() == SUM_FUNC_ITEM || - (item->used_tables() && item->type() != REF_ITEM)) - { - /* - Replace item with a reference so that we can easily calculate - it (in case of sum functions) or copy it (in case of fields) - - The test above is to ensure we don't do a reference for things - that are constants or are not yet calculated as in: - SELECT RAND() as r1, SUM(a) as r2 FROM t1 HAVING r1 > 1 AND r2 > 0 - */ - Item **ref= li.ref(); - uint el= fields.elements; - ref_pointer_array[el]= item; - Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name); - fields.push_front(item); - ref_pointer_array[el]= item; - thd->change_item_tree(ref, new_item); - } - item->update_used_tables(); - used_tables_cache|=item->used_tables(); - const_item_cache&=item->const_item(); - } + while ((item= li++)) + item->split_sum_func2(thd, ref_pointer_array, fields, li.ref()); } diff --git a/sql/item_func.cc b/sql/item_func.cc index d5d0ac8cd49..34c8732a9f2 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -352,28 +352,14 @@ bool Item_func::walk (Item_processor processor, byte *argument) } +/* See comments in Item_cmp_func::split_sum_func() */ + void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array, List &fields) { Item **arg, **arg_end; for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++) - { - Item *item=* arg; - if (item->type() != SUM_FUNC_ITEM && - (item->with_sum_func || - (item->used_tables() & PSEUDO_TABLE_BITS))) - item->split_sum_func(thd, ref_pointer_array, fields); - else if (item->type() == SUM_FUNC_ITEM || - (item->used_tables() && item->type() != REF_ITEM)) - { - uint el= fields.elements; - ref_pointer_array[el]= item; - Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name); - fields.push_front(item); - ref_pointer_array[el]= item; - thd->change_item_tree(arg, new_item); - } - } + (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg); } diff --git a/sql/item_row.cc b/sql/item_row.cc index 0ace0fc0451..12d202a1699 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -90,25 +90,10 @@ void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array, { Item **arg, **arg_end; for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++) - { - Item *item= *arg; - if (item->type() != SUM_FUNC_ITEM && - (item->with_sum_func || - (item->used_tables() & PSEUDO_TABLE_BITS))) - item->split_sum_func(thd, ref_pointer_array, fields); - else if (item->type() == SUM_FUNC_ITEM || - (item->used_tables() && item->type() != REF_ITEM)) - { - uint el= fields.elements; - ref_pointer_array[el]=*arg; - Item *new_item= new Item_ref(ref_pointer_array + el, 0, (*arg)->name); - fields.push_front(*arg); - ref_pointer_array[el]= *arg; - thd->change_item_tree(arg, new_item); - } - } + (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg); } + void Item_row::update_used_tables() { used_tables_cache= 0; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index b22b65eddd0..a92c4e94c87 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1758,20 +1758,7 @@ String *Item_func_elt::val_str(String *str) void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array, List &fields) { - if (item->type() != SUM_FUNC_ITEM && - (item->with_sum_func || - (item->used_tables() & PSEUDO_TABLE_BITS))) - item->split_sum_func(thd, ref_pointer_array, fields); - else if (item->type() == SUM_FUNC_ITEM || - (item->used_tables() && item->type() != REF_ITEM)) - { - uint el= fields.elements; - ref_pointer_array[el]=item; - Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name); - fields.push_front(item); - ref_pointer_array[el]= item; - thd->change_item_tree(&item, new_item); - } + item->split_sum_func2(thd, ref_pointer_array, fields, &item); Item_str_func::split_sum_func(thd, ref_pointer_array, fields); } diff --git a/sql/sql_list.h b/sql/sql_list.h index 38c5af2a4f7..a607b31d60c 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -134,6 +134,15 @@ public: if (!--elements) last= &first; } + inline void concat(base_list *list) + { + if (!list->is_empty()) + { + *last= list->first; + last= list->last; + elements+= list->elements; + } + } inline void *pop(void) { if (first == &end_of_list) return 0; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8353ca9333d..7bb60fe8e79 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8502,6 +8502,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, res_selected_fields.empty(); res_all_fields.empty(); List_iterator_fast itr(res_all_fields); + List extra_funcs; uint i, border= all_fields.elements - elements; DBUG_ENTER("setup_copy_fields"); @@ -8563,7 +8564,12 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, */ if (!(pos=new Item_copy_string(pos))) goto err; - if (param->copy_funcs.push_back(pos)) + if (i < border) // HAVING, ORDER and GROUP BY + { + if (extra_funcs.push_back(pos)) + goto err; + } + else if (param->copy_funcs.push_back(pos)) goto err; } res_all_fields.push_back(pos); @@ -8575,6 +8581,12 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, for (i= 0; i < border; i++) itr++; itr.sublist(res_selected_fields, elements); + /* + Put elements from HAVING, ORDER BY and GROUP BY last to ensure that any + reference used in these will resolve to a item that is already calculated + */ + param->copy_funcs.concat(&extra_funcs); + DBUG_RETURN(0); err: From 1c2f4ffecb5ee57c91f8961544f20a73de360bc3 Mon Sep 17 00:00:00 2001 From: "jani@ua141d10.elisa.omakaista.fi" <> Date: Tue, 8 Feb 2005 19:49:40 +0200 Subject: [PATCH 04/14] Applied a patch for Netware. --- client/mysqltest.c | 5 +++++ extra/my_print_defaults.c | 5 +++++ extra/perror.c | 5 +++++ extra/resolve_stack_dump.c | 5 +++++ include/help_end.h | 1 + include/help_start.h | 2 ++ isam/pack_isam.c | 4 ++++ myisam/myisamlog.c | 2 ++ mysys/my_rename.c | 2 +- netware/BUILD/nwbootstrap | 8 +------- netware/mysql_test_run.c | 5 +++-- scripts/make_binary_distribution.sh | 8 ++++++-- sql/mysqld.cc | 8 +++++++- 13 files changed, 47 insertions(+), 13 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index d81e199ab1f..042f84dfb9e 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2169,6 +2169,9 @@ static struct my_option my_long_options[] = { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; + +#include + static void print_version(void) { printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION, @@ -2187,6 +2190,8 @@ void usage() my_print_variables(my_long_options); } +#include + static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c index f4da839f8e2..2ec6f8b406f 100644 --- a/extra/my_print_defaults.c +++ b/extra/my_print_defaults.c @@ -55,6 +55,9 @@ static struct my_option my_long_options[] = {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; + +#include + static void usage(my_bool version) { printf("%s Ver 1.6 for %s at %s\n",my_progname,SYSTEM_TYPE, @@ -69,6 +72,8 @@ static void usage(my_bool version) printf("\nExample usage:\n%s --config-file=my client mysql\n", my_progname); } +#include + static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), diff --git a/extra/perror.c b/extra/perror.c index 27027520cbe..b377b360b5c 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -113,12 +113,15 @@ static HA_ERRORS ha_errlist[]= }; +#include + static void print_version(void) { printf("%s Ver %s, for %s (%s)\n",my_progname,PERROR_VERSION, SYSTEM_TYPE,MACHINE_TYPE); } + static void usage(void) { print_version(); @@ -130,6 +133,8 @@ static void usage(void) my_print_variables(my_long_options); } +#include + static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), diff --git a/extra/resolve_stack_dump.c b/extra/resolve_stack_dump.c index 06a670b935d..666125990d2 100644 --- a/extra/resolve_stack_dump.c +++ b/extra/resolve_stack_dump.c @@ -65,12 +65,16 @@ static struct my_option my_long_options[] = static void verify_sort(); + +#include + static void print_version(void) { printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); } + static void usage() { print_version(); @@ -87,6 +91,7 @@ The numeric-dump-file should contain a numeric stack trace from mysqld.\n\ If the numeric-dump-file is not given, the stack trace is read from stdin.\n"); } +#include static void die(const char* fmt, ...) diff --git a/include/help_end.h b/include/help_end.h index a63d9e7ca9f..3bd16c09e3b 100644 --- a/include/help_end.h +++ b/include/help_end.h @@ -2,5 +2,6 @@ #undef printf #undef puts #undef fputs +#undef fputc #undef putchar #endif diff --git a/include/help_start.h b/include/help_start.h index 38bb91f7655..7ffde1ab803 100644 --- a/include/help_start.h +++ b/include/help_start.h @@ -4,4 +4,6 @@ #define printf consoleprintf #define puts(s) consoleprintf("%s\n",s) #define fputs(s,f) puts(s) +#define fputc(s,f) consoleprintf("%c", s) +#define putchar(s) consoleprintf("%c", s) #endif diff --git a/isam/pack_isam.c b/isam/pack_isam.c index aa83b2b2a96..0134e0411b2 100644 --- a/isam/pack_isam.c +++ b/isam/pack_isam.c @@ -260,6 +260,8 @@ static struct my_option my_long_options[] = }; +#include + static void print_version(void) { printf("%s Ver 5.10 for %s on %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE); @@ -283,6 +285,8 @@ static void usage(void) my_print_variables(my_long_options); } +#include + static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), diff --git a/myisam/myisamlog.c b/myisam/myisamlog.c index 6679510227e..dc98d813266 100644 --- a/myisam/myisamlog.c +++ b/myisam/myisamlog.c @@ -247,6 +247,7 @@ static void get_options(register int *argc, register char ***argv) /* Fall through */ case 'I': case '?': +#include printf("%s Ver 1.4 for %s at %s\n",my_progname,SYSTEM_TYPE, MACHINE_TYPE); puts("By Monty, for your professional use\n"); @@ -268,6 +269,7 @@ static void get_options(register int *argc, register char ***argv) puts("If a recover is done all writes and all possibly updates and deletes is done\nand errors are only counted."); puts("If one gives table names as arguments only these tables will be updated\n"); help=1; +#include break; default: printf("illegal option: \"-%c\"\n",*pos); diff --git a/mysys/my_rename.c b/mysys/my_rename.c index d4f99e83247..b5d813ad787 100644 --- a/mysys/my_rename.c +++ b/mysys/my_rename.c @@ -45,7 +45,7 @@ int my_rename(const char *from, const char *to, myf MyFlags) } #endif #if defined(HAVE_RENAME) -#ifdef __WIN__ +#if defined(__WIN__) || defined(__NETWARE__) /* On windows we can't rename over an existing file: Remove any conflicting files: diff --git a/netware/BUILD/nwbootstrap b/netware/BUILD/nwbootstrap index 25e843c87e3..2bd7150ec0d 100755 --- a/netware/BUILD/nwbootstrap +++ b/netware/BUILD/nwbootstrap @@ -171,15 +171,9 @@ do rm $file.org done -# create the libmysql.imp file in netware folder from libmysql/libmysql.def -# file -echo "generating llibmysql.imp file..." -awk 'BEGIN{x=0;} x==1 {print $1;next} /EXPORTS/{x=1}' libmysql/libmysql.def > netware/libmysql.imp - # create the libmysql.imp file in netware folder from libmysql/libmysql.def file echo "generating llibmysql.imp file..." -awk 'BEGIN{x=0;} x==1 {print $1;next} /EXPORTS/{x=1}' libmysql/libmysql.def > netware/libmysql.imp - +awk 'BEGIN{x=0;} END{printf("\n");} x==1 {printf(" %s",$1); x++; next} x>1 {printf(",\n %s", $1);next} /EXPORTS/{x=1}' libmysql/libmysql.def > netware/libmysql.imp # build linux tools echo "compiling linux tools..." diff --git a/netware/mysql_test_run.c b/netware/mysql_test_run.c index fd5725a6414..d8cfb79c1cb 100644 --- a/netware/mysql_test_run.c +++ b/netware/mysql_test_run.c @@ -192,7 +192,7 @@ void install_db(char *datadir) char error[PATH_MAX]; // input file - snprintf(input, PATH_MAX, "%s/bin/init_db.sql", base_dir); + snprintf(input, PATH_MAX, "%s/bin/test_db.sql", base_dir); snprintf(output, PATH_MAX, "%s/install.out", datadir); snprintf(error, PATH_MAX, "%s/install.err", datadir); @@ -1160,7 +1160,8 @@ void setup(char *file) setenv("MASTER_MYPORT", "9306", 1); setenv("SLAVE_MYPORT", "9307", 1); setenv("MYSQL_TCP_PORT", "3306", 1); - + snprintf(file_path, PATH_MAX*2, "%s/mysql_client_test --no-defaults --testcase--user=root --port=%u ", bin_dir, master_port); + setenv("MYSQL_CLIENT_TEST",file_path,1); } /****************************************************************************** diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 910aa38c33f..7a6e052f5c7 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -242,8 +242,12 @@ rm -f $BASE/bin/Makefile* $BASE/bin/*.in $BASE/bin/*.sh $BASE/bin/mysql_install_ # Copy system dependent files # if [ $BASE_SYSTEM = "netware" ] ; then - cp ./netware/static_init_db.sql ./netware/init_db.sql - ./scripts/fill_help_tables < ./Docs/manual.texi >> ./netware/init_db.sql +echo "CREATE DATABASE mysql;" > $BASE/bin/init_db.sql + echo "CREATE DATABASE test;" >> $BASE/bin/init_db.sql + sh ./scripts/mysql_create_system_tables.sh real "" "%" 0 >> $BASE/bin/init_db.sql + sh ./scripts/mysql_create_system_tables.sh test "" "%" 0 > $BASE/bin/test_db.sql +# cp ./netware/static_init_db.sql ./netware/init_db.sql +# ./scripts/fill_help_tables < ./Docs/manual.texi >> ./netware/init_db.sql fi # diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 503fb5bfb99..53dca59bc92 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -147,6 +147,10 @@ int deny_severity = LOG_WARNING; #include #endif +#define zVOLSTATE_ACTIVE 6 +#define zVOLSTATE_DEACTIVE 2 +#define zVOLSTATE_MAINTENANCE 3 + #ifdef __NETWARE__ #include #include @@ -1667,7 +1671,9 @@ ulong neb_event_callback(struct EventBlock *eblock) voldata= (EventChangeVolStateEnter_s *)eblock->EBEventData; /* Deactivation of a volume */ - if ((voldata->oldState == 6 && voldata->newState == 2)) + if ((voldata->oldState == zVOLSTATE_ACTIVE && + voldata->newState == zVOLSTATE_DEACTIVE || + voldata->newState == zVOLSTATE_MAINTENANCE)) { /* Ensure that we bring down MySQL server only for MySQL data From dcc65b77a676bfa545135295fdda20ec2af4de0d Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Tue, 8 Feb 2005 23:44:51 +0300 Subject: [PATCH 05/14] Fix for BUG#8371: wrong rec_per_key value for hash index on temporary table --- mysql-test/r/heap_hash.result | 10 ++++++++++ mysql-test/t/heap_hash.test | 6 ++++++ sql/ha_heap.cc | 13 +++++++------ sql/sql_select.cc | 1 + 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result index 4f5de197858..d3673cd2a63 100644 --- a/mysql-test/r/heap_hash.result +++ b/mysql-test/r/heap_hash.result @@ -355,3 +355,13 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref heap_idx heap_idx 20 const 7 Using where 1 SIMPLE t3 ref a a 40 func,const 6 Using where drop table t1, t2, t3; +create temporary table t1 ( a int, index (a) ) engine=memory; +insert into t1 values (1),(2),(3),(4),(5); +select a from t1 where a in (1,3); +a +1 +3 +explain select a from t1 where a in (1,3); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 5 NULL 2 Using where +drop table t1; diff --git a/mysql-test/t/heap_hash.test b/mysql-test/t/heap_hash.test index 6d8fdec4b9e..6d27f19dfad 100644 --- a/mysql-test/t/heap_hash.test +++ b/mysql-test/t/heap_hash.test @@ -251,3 +251,9 @@ explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a drop table t1, t2, t3; +# Fix for BUG#8371: wrong rec_per_key value for hash index on temporary table +create temporary table t1 ( a int, index (a) ) engine=memory; +insert into t1 values (1),(2),(3),(4),(5); +select a from t1 where a in (1,3); +explain select a from t1 where a in (1,3); +drop table t1; diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 96c19ce0705..3c2249ce281 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -60,8 +60,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked) { /* Initialize variables for the opened table */ set_keys_for_scanning(); - if (table->tmp_table == NO_TMP_TABLE) - update_key_stats(); + update_key_stats(); } return (file ? 0 : 1); } @@ -103,6 +102,8 @@ void ha_heap::update_key_stats() for (uint i= 0; i < table->keys; i++) { KEY *key=table->key_info+i; + if (!key->rec_per_key) + continue; if (key->algorithm != HA_KEY_ALG_BTREE) { ha_rows hash_buckets= file->s->keydef[i].hash_buckets; @@ -122,8 +123,8 @@ int ha_heap::write_row(byte * buf) if (table->next_number_field && buf == table->record[0]) update_auto_increment(); res= heap_write(file,buf); - if (!res && table->tmp_table == NO_TMP_TABLE && - ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) + if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > + file->s->records) update_key_stats(); return res; } @@ -135,8 +136,8 @@ int ha_heap::update_row(const byte * old_data, byte * new_data) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); res= heap_update(file,old_data,new_data); - if (!res && table->tmp_table == NO_TMP_TABLE && - ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) + if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > + file->s->records) update_key_stats(); return res; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8353ca9333d..96265a96386 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5289,6 +5289,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, keyinfo->key_length=(uint16) reclength; keyinfo->name=(char*) "tmp"; keyinfo->algorithm= HA_KEY_ALG_UNDEF; + keyinfo->rec_per_key=0; if (null_pack_length) { key_part_info->null_bit=0; From 9b77596587ea014c5f87c31de7cb55aff504ae6b Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Wed, 9 Feb 2005 14:24:25 +0100 Subject: [PATCH 06/14] ndb - Fix bug in bug fix in FastScheduler remove possibility of endless loop resulting in APZJobBuffer overflow due to statistics reporting --- ndb/src/kernel/vm/FastScheduler.cpp | 42 +++++++++++++++-------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/ndb/src/kernel/vm/FastScheduler.cpp b/ndb/src/kernel/vm/FastScheduler.cpp index d05c02360a7..d0b7af27463 100644 --- a/ndb/src/kernel/vm/FastScheduler.cpp +++ b/ndb/src/kernel/vm/FastScheduler.cpp @@ -85,7 +85,7 @@ FastScheduler::activateSendPacked() void FastScheduler::doJob() { - Uint32 init_loopCount = 0; + Uint32 loopCount = 0; Uint32 TminLoops = getBOccupancy() + EXTRA_SIGNALS_PER_DO_JOB; Uint32 TloopMax = (Uint32)globalData.loopMax; if (TminLoops < TloopMax) { @@ -94,10 +94,9 @@ FastScheduler::doJob() if (TloopMax < MIN_NUMBER_OF_SIG_PER_DO_JOB) { TloopMax = MIN_NUMBER_OF_SIG_PER_DO_JOB; }//if + register Signal* signal = getVMSignals(); + register Uint32 tHighPrio= globalData.highestAvailablePrio; do{ - Uint32 loopCount = init_loopCount; - register Uint32 tHighPrio = globalData.highestAvailablePrio; - register Signal* signal = getVMSignals(); while ((tHighPrio < LEVEL_IDLE) && (loopCount < TloopMax)) { // signal->garbage_register(); // To ensure we find bugs quickly @@ -155,24 +154,27 @@ FastScheduler::doJob() }//if loopCount++; }//while - if (globalData.sendPackedActivated == 1) { - Uint32 t1 = theDoJobTotalCounter; - Uint32 t2 = theDoJobCallCounter; - t1 += (loopCount - init_loopCount); - t2++; - theDoJobTotalCounter = t1; - theDoJobCallCounter = t2; - if (t2 == 8192) { - reportDoJobStatistics(t1 >> 13); - theDoJobCallCounter = 0; - theDoJobTotalCounter = 0; - }//if - }//if - init_loopCount = loopCount; sendPacked(); + tHighPrio = globalData.highestAvailablePrio; + if(getBOccupancy() > MAX_OCCUPANCY) + { + if(loopCount != TloopMax) + abort(); + assert( loopCount == TloopMax ); + TloopMax += 512; + } } while ((getBOccupancy() > MAX_OCCUPANCY) || - ((init_loopCount < TloopMax) && - (globalData.highestAvailablePrio < LEVEL_IDLE))); + ((loopCount < TloopMax) && + (tHighPrio < LEVEL_IDLE))); + + theDoJobCallCounter ++; + theDoJobTotalCounter += loopCount; + if (theDoJobCallCounter == 8192) { + reportDoJobStatistics(theDoJobTotalCounter >> 13); + theDoJobCallCounter = 0; + theDoJobTotalCounter = 0; + }//if + }//FastScheduler::doJob() void FastScheduler::sendPacked() From 90c00242179d2df8b97c442b2d0d8da724efe5ca Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Wed, 9 Feb 2005 21:08:08 +0200 Subject: [PATCH 07/14] reverted patch for BUG#7351 (because of performance ussie) --- mysql-test/r/subselect.result | 38 +++++------------------------------ mysql-test/t/subselect.test | 30 +-------------------------- sql/item_cmpfunc.cc | 5 ++--- sql/item_subselect.cc | 13 ++++-------- 4 files changed, 12 insertions(+), 74 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 03dcc23c919..3018726e6a1 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1425,7 +1425,7 @@ Note 1003 (select test.t1.s1 AS `s1` from test.t1) s1 tttt drop table t1; -create table t1 (s1 char(5) not null, index s1(s1)); +create table t1 (s1 char(5), index s1(s1)); create table t2 (s1 char(5), index s1(s1)); insert into t1 values ('a1'),('a2'),('a3'); insert into t2 values ('a1'),('a2'); @@ -1451,25 +1451,25 @@ a2 1 a3 1 explain extended select s1, s1 NOT IN (SELECT s1 FROM t2) from t1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index NULL s1 5 NULL 3 Using index +1 PRIMARY t1 index NULL s1 6 NULL 3 Using index 2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index Warnings: Note 1003 select test.t1.s1 AS `s1`,not((test.t1.s1,(((test.t1.s1) in t2 on s1 chicking NULL)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from test.t1 explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index NULL s1 5 NULL 3 Using index +1 PRIMARY t1 index NULL s1 6 NULL 3 Using index 2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index Warnings: Note 1003 select test.t1.s1 AS `s1`,(test.t1.s1,(((test.t1.s1) in t2 on s1 chicking NULL))) AS `s1 = ANY (SELECT s1 FROM t2)` from test.t1 explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index NULL s1 5 NULL 3 Using index +1 PRIMARY t1 index NULL s1 6 NULL 3 Using index 2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index Warnings: Note 1003 select test.t1.s1 AS `s1`,not((test.t1.s1,(((test.t1.s1) in t2 on s1 chicking NULL)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from test.t1 explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index NULL s1 5 NULL 3 Using index +1 PRIMARY t1 index NULL s1 6 NULL 3 Using index 2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 1 Using index; Using where Warnings: Note 1003 select test.t1.s1 AS `s1`,not((test.t1.s1,(((test.t1.s1) in t2 on s1 chicking NULL where (test.t2.s1 < _latin1'a2'))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from test.t1 @@ -2125,34 +2125,6 @@ SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 c Oceania drop table t1; -CREATE TABLE t1 ( f1 BIGINT ); -INSERT INTO t1 SET f1= NULL; -INSERT INTO t1 SET f1= 1; -CREATE TABLE t2 ( f1 BIGINT ); -SELECT f1 FROM t1 -WHERE f1 <> ALL ( SELECT f1 FROM t2 ); -f1 -NULL -1 -INSERT INTO t2 VALUES (1), (2); -SELECT f1 FROM t1 -WHERE f1 <> ALL ( SELECT f1 FROM t2 WHERE f1 > 2 ); -f1 -NULL -1 -SELECT f1 FROM t1 -WHERE f1 <> ALL ( SELECT f1 FROM t2 WHERE f1 > 2 -UNION -SELECT f1 FROM t2 WHERE f1 > 3); -f1 -NULL -1 -SELECT f1 FROM t1 -WHERE f1 <> ALL ( SELECT SUM(f1) AS sf1 FROM t2 HAVING sf1 > 10000); -f1 -NULL -1 -drop table t1,t2; create table t1 (a1 int); create table t2 (b1 int); select * from t1 where a2 > any(select b1 from t2); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 55400dae0be..cb4f2eab923 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -889,7 +889,7 @@ drop table t1; # # IN optimisation test results # -create table t1 (s1 char(5) not null, index s1(s1)); +create table t1 (s1 char(5), index s1(s1)); create table t2 (s1 char(5), index s1(s1)); insert into t1 values ('a1'),('a2'),('a3'); insert into t2 values ('a1'),('a2'); @@ -1387,34 +1387,6 @@ INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','M SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 WHERE Continent = c AND Population < 200); drop table t1; -# -# Test cases for bug #7351: -# quantified predicate with subquery returning empty result set -# - -CREATE TABLE t1 ( f1 BIGINT ); -INSERT INTO t1 SET f1= NULL; -INSERT INTO t1 SET f1= 1; -CREATE TABLE t2 ( f1 BIGINT ); - -SELECT f1 FROM t1 - WHERE f1 <> ALL ( SELECT f1 FROM t2 ); - -INSERT INTO t2 VALUES (1), (2); - -SELECT f1 FROM t1 - WHERE f1 <> ALL ( SELECT f1 FROM t2 WHERE f1 > 2 ); - -SELECT f1 FROM t1 - WHERE f1 <> ALL ( SELECT f1 FROM t2 WHERE f1 > 2 - UNION - SELECT f1 FROM t2 WHERE f1 > 3); - -SELECT f1 FROM t1 - WHERE f1 <> ALL ( SELECT SUM(f1) AS sf1 FROM t2 HAVING sf1 > 10000); - -drop table t1,t2; - # # Test for BUG#7885: Server crash when 'any' subselect compared to # non-existant field. diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 2b9a612da18..79295eb90b0 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -636,13 +636,12 @@ longlong Item_in_optimizer::val_int() { DBUG_ASSERT(fixed == 1); cache->store(args[0]); - longlong tmp= args[1]->val_int_result(); if (cache->null_value) { - if (tmp) - null_value= 1; + null_value= 1; return 0; } + longlong tmp= args[1]->val_int_result(); null_value= args[1]->null_value; return tmp; } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 16186b1a6d3..3a1e1918e55 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -825,8 +825,6 @@ Item_in_subselect::single_value_transformer(JOIN *join, select_lex->ref_pointer_array, (char *)"", this->full_name())); - if (!abort_on_null && left_expr->maybe_null) - item= new Item_cond_or(new Item_func_isnull(left_expr), item); /* AND and comparison functions can't be changed during fix_fields() we can assign select_lex->having here, and pass 0 as last @@ -872,8 +870,6 @@ Item_in_subselect::single_value_transformer(JOIN *join, select_lex->having_fix_field= 0; item= new Item_cond_or(item, new Item_func_isnull(orig_item)); - if (left_expr->maybe_null) - item= new Item_cond_or(new Item_func_isnull(left_expr), item); } item->name= (char *)in_additional_cond; /* @@ -894,13 +890,12 @@ Item_in_subselect::single_value_transformer(JOIN *join, we can assign select_lex->having here, and pass 0 as last argument (reference) to fix_fields() */ - item= func->create(expr, - new Item_null_helper(this, item, + select_lex->having= + join->having= + func->create(expr, + new Item_null_helper(this, item, (char *)"", (char *)"")); - if (!abort_on_null && left_expr->maybe_null) - item= new Item_cond_or(new Item_func_isnull(left_expr), item); - select_lex->having= join->having= item; select_lex->having_fix_field= 1; if (join->having->fix_fields(thd, join->tables_list, 0)) From b2f4af0013ba42e2996997fc7b2a125f31d5aea1 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Wed, 9 Feb 2005 22:02:48 +0200 Subject: [PATCH 08/14] cleaned up mysql installation code for windows. This removes a (small) memory leak. --- sql/mysqld.cc | 29 ++++++++++++++--------------- sql/nt_servc.h | 5 +++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9400bedb585..120cfd4828b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3299,12 +3299,14 @@ default_service_handling(char **argv, if (Service.got_service_option(argv, "install")) { - Service.Install(1, servicename, displayname, path_and_service, account_name); + Service.Install(1, servicename, displayname, path_and_service, + account_name); return 0; } if (Service.got_service_option(argv, "install-manual")) { - Service.Install(0, servicename, displayname, path_and_service, account_name); + Service.Install(0, servicename, displayname, path_and_service, + account_name); return 0; } if (Service.got_service_option(argv, "remove")) @@ -3324,7 +3326,7 @@ int main(int argc, char **argv) application PID e.g.: MySQLShutdown1890; MySQLShutdown2342 */ int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name, - "MySQLShutdown"), 10); + "MySQLShutdown"), 10); /* Must be initialized early for comparison of service name */ system_charset_info= &my_charset_utf8_general_ci; @@ -3358,7 +3360,8 @@ int main(int argc, char **argv) } else if (argc == 3) /* install or remove any optional service */ { - if (!default_service_handling(argv, argv[2], argv[2], file_path, "", NULL)) + if (!default_service_handling(argv, argv[2], argv[2], file_path, "", + NULL)) return 0; if (Service.IsService(argv[2])) { @@ -3385,24 +3388,20 @@ int main(int argc, char **argv) --defaults-file=file, but that was not enforced in 4.1, so we don't enforce it here.) */ - char *extra_opt= NULL; - char *account_name = NULL; + const char *extra_opt= NullS; + const char *account_name = NullS; int index; for (index = 3; index < argc; index++) { - if (strncmp(argv[index], "--local-service", 15) == 0) - { - account_name=(char*)malloc(27); - strmov(account_name, "NT AUTHORITY\\LocalService\0"); - } + if (!strcmp(argv[index], "--local-service")) + account_name= "NT AUTHORITY\\LocalService"; else - { extra_opt= argv[index]; - } } - if (argc != 5 || account_name) - if (!default_service_handling(argv, argv[2], argv[2], file_path, extra_opt, account_name)) + if (argc == 4 || account_name) + if (!default_service_handling(argv, argv[2], argv[2], file_path, + extra_opt, account_name)) return 0; } else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME)) diff --git a/sql/nt_servc.h b/sql/nt_servc.h index 6d74eaccea2..a3c12569114 100644 --- a/sql/nt_servc.h +++ b/sql/nt_servc.h @@ -48,8 +48,9 @@ class NTService //service install / un-install - BOOL Install(int startType,LPCSTR szInternName,LPCSTR szDisplayName,LPCSTR szFullPath, - LPCSTR szAccountName=NULL,LPCSTR szPassword=NULL); + BOOL Install(int startType,LPCSTR szInternName,LPCSTR szDisplayName, + LPCSTR szFullPath, LPCSTR szAccountName=NULL, + LPCSTR szPassword=NULL); BOOL SeekStatus(LPCSTR szInternName, int OperationType); BOOL Remove(LPCSTR szInternName); BOOL IsService(LPCSTR ServiceName); From 016544df2276f3bb0471e3638416c1ecc378c710 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 10 Feb 2005 14:56:20 +0300 Subject: [PATCH 09/14] A fix and test case for Bug#8330 "mysql_stmt_execute crashes" (libmysql). --- libmysql/libmysql.c | 5 ++++ tests/mysql_client_test.c | 54 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 3d84059e981..24a7fa5f929 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2467,6 +2467,11 @@ int cli_stmt_execute(MYSQL_STMT *stmt) set_stmt_error(stmt, CR_PARAMS_NOT_BOUND, unknown_sqlstate); DBUG_RETURN(1); } + if (stmt->mysql->status != MYSQL_STATUS_READY) + { + set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); + DBUG_RETURN(1); + } net_clear(net); /* Sets net->write_pos */ /* Reserve place for null-marker bytes */ diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 83f8f6ab143..e4bdd1d350a 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -11532,6 +11533,58 @@ static void test_bug6761(void) myquery(rc); } + +/* Bug#8330 - Bug #8330 mysql_stmt_execute crashes (libmysql) */ + +static void test_bug8330() +{ + const char *stmt_text; + MYSQL_STMT *stmt[2]; + int i, rc; + char *query= "select a,b from t1 where a=?"; + MYSQL_BIND bind[2]; + long lval[2]; + + myheader("test_bug8330"); + + stmt_text= "drop table if exists t1"; + /* in case some previos test failed */ + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); + stmt_text= "create table t1 (a int, b int)"; + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); + + bzero(bind, sizeof(bind)); + for (i=0; i < 2; i++) + { + stmt[i]= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt[i], query, strlen(query)); + check_execute(stmt[i], rc); + + bind[i].buffer_type= MYSQL_TYPE_LONG; + bind[i].buffer= (void*) &lval[i]; + bind[i].is_null= 0; + mysql_stmt_bind_param(stmt[i], &bind[i]); + } + + rc= mysql_stmt_execute(stmt[0]); + check_execute(stmt[0], rc); + + rc= mysql_stmt_execute(stmt[1]); + DIE_UNLESS(rc && mysql_stmt_errno(stmt[1]) == CR_COMMANDS_OUT_OF_SYNC); + rc= mysql_stmt_execute(stmt[0]); + check_execute(stmt[0], rc); + + mysql_stmt_close(stmt[0]); + mysql_stmt_close(stmt[1]); + + stmt_text= "drop table t1"; + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -11739,6 +11792,7 @@ static struct my_tests_st my_tests[]= { { "test_conversion", test_conversion }, { "test_rewind", test_rewind }, { "test_bug6761", test_bug6761 }, + { "test_bug8330", test_bug8330 }, { 0, 0 } }; From 8fb1f824ea3e918527a983ece4988a5c0e0a7431 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.homeip.net" <> Date: Thu, 10 Feb 2005 14:13:23 +0100 Subject: [PATCH 10/14] Change script to avoiud multiple --debug flags when starting master servers --- mysql-test/mysql-test-run.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index c3b27dd9af2..75e2a8c7cc8 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -1151,8 +1151,7 @@ start_master() fi if [ -n "$EXTRA_MASTER_MYSQLD_TRACE" ] then - EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT \ - $EXTRA_MASTER_MYSQLD_TRACE$1" + CURR_MASTER_MYSQLD_TRACE="$EXTRA_MASTER_MYSQLD_TRACE$1" fi if [ -z "$DO_BENCH" ] then @@ -1177,7 +1176,7 @@ start_master() $MASTER_40_ARGS \ $SMALL_SERVER \ $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \ - $NOT_FIRST_MASTER_EXTRA_OPTS" + $NOT_FIRST_MASTER_EXTRA_OPTS $CURR_MASTER_MYSQLD_TRACE" else master_args="--no-defaults --log-bin=$MYSQL_TEST_DIR/var/log/master-bin$1 \ --server-id=$id --rpl-recovery-rank=1 \ From ccb2f3381bb8732ecb684978fe62af8dc1cd1c38 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Thu, 10 Feb 2005 15:41:51 +0200 Subject: [PATCH 11/14] Things missing in last changset After merge fixes Don't give duplicate warnings for some ::store() functions --- mysql-test/mysql-test-run.sh | 1 + mysql-test/r/ps_2myisam.result | 2 - mysql-test/r/ps_3innodb.result | 2 - mysql-test/r/ps_4heap.result | 2 - mysql-test/r/ps_5merge.result | 4 -- sql/field.cc | 86 +++++++++++++++++++++++----------- sql/field.h | 6 ++- sql/sql_class.h | 1 + sql/sql_error.cc | 1 + sql/sql_list.h | 9 ---- 10 files changed, 66 insertions(+), 48 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index c3b27dd9af2..67dce0d225b 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -692,6 +692,7 @@ then fi MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST --no-defaults --testcase --user=root --socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT --silent" +MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT" MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR --character-sets-dir=$CHARSETSDIR $EXTRA_MYSQLBINLOG_OPT" MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose" MYSQL="$MYSQL --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD" diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 78436b69ec7..14b7e8a7069 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -2666,7 +2666,6 @@ Warning 1264 Out of range value adjusted for column 'c4' at row 1 Warning 1264 Out of range value adjusted for column 'c5' at row 1 Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 -Note 1265 Data truncated for column 'c12' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; c1 127 @@ -2717,7 +2716,6 @@ Warning 1264 Out of range value adjusted for column 'c4' at row 1 Warning 1264 Out of range value adjusted for column 'c5' at row 1 Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 -Note 1265 Data truncated for column 'c12' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; c1 -128 diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index e5db53e1c18..940f5e8cbac 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -2649,7 +2649,6 @@ Warning 1264 Out of range value adjusted for column 'c4' at row 1 Warning 1264 Out of range value adjusted for column 'c5' at row 1 Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 -Note 1265 Data truncated for column 'c12' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; c1 127 @@ -2700,7 +2699,6 @@ Warning 1264 Out of range value adjusted for column 'c4' at row 1 Warning 1264 Out of range value adjusted for column 'c5' at row 1 Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 -Note 1265 Data truncated for column 'c12' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; c1 -128 diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index ad02de1110c..37dd8cb263e 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -2650,7 +2650,6 @@ Warning 1264 Out of range value adjusted for column 'c4' at row 1 Warning 1264 Out of range value adjusted for column 'c5' at row 1 Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 -Note 1265 Data truncated for column 'c12' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; c1 127 @@ -2701,7 +2700,6 @@ Warning 1264 Out of range value adjusted for column 'c4' at row 1 Warning 1264 Out of range value adjusted for column 'c5' at row 1 Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 -Note 1265 Data truncated for column 'c12' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; c1 -128 diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 374f6142c44..867d410ebf1 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -2586,7 +2586,6 @@ Warning 1264 Out of range value adjusted for column 'c4' at row 1 Warning 1264 Out of range value adjusted for column 'c5' at row 1 Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 -Note 1265 Data truncated for column 'c12' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; c1 127 @@ -2637,7 +2636,6 @@ Warning 1264 Out of range value adjusted for column 'c4' at row 1 Warning 1264 Out of range value adjusted for column 'c5' at row 1 Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 -Note 1265 Data truncated for column 'c12' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; c1 -128 @@ -5597,7 +5595,6 @@ Warning 1264 Out of range value adjusted for column 'c4' at row 1 Warning 1264 Out of range value adjusted for column 'c5' at row 1 Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 -Note 1265 Data truncated for column 'c12' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; c1 127 @@ -5648,7 +5645,6 @@ Warning 1264 Out of range value adjusted for column 'c4' at row 1 Warning 1264 Out of range value adjusted for column 'c5' at row 1 Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 -Note 1265 Data truncated for column 'c12' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; c1 -128 diff --git a/sql/field.cc b/sql/field.cc index ad66fec2fc2..bc95e1dab54 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -149,7 +149,7 @@ bool Field::check_int(const char *str, int length, const char *int_end, truncation. SYNOPSIS - Field::check_overflow() + Field::warn_if_overflow() op_result decimal library return code (E_DEC_* see include/decimal.h) RETURN @@ -157,19 +157,22 @@ bool Field::check_int(const char *str, int length, const char *int_end, 0 no error or some other errors except overflow */ -int Field::check_overflow(int op_result) +int Field::warn_if_overflow(int op_result) { if (op_result == E_DEC_OVERFLOW) { set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); return 1; } - else if (op_result == E_DEC_TRUNCATED) + if (op_result == E_DEC_TRUNCATED) + { set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1); - /* we return 1 only in case of EFL */ + /* We return 0 here as this is not a critical issue */ + } return 0; } + #ifdef NOT_USED static bool test_if_real(const char *str,int length, CHARSET_INFO *cs) { @@ -507,7 +510,7 @@ longlong Field::convert_decimal2longlong(const my_decimal *val, i= 0; *err= 1; } - else if (check_overflow(my_decimal2int(E_DEC_ERROR & + else if (warn_if_overflow(my_decimal2int(E_DEC_ERROR & ~E_DEC_OVERFLOW & ~E_DEC_TRUNCATED, val, TRUE, &i))) { @@ -515,7 +518,7 @@ longlong Field::convert_decimal2longlong(const my_decimal *val, *err= 1; } } - else if (check_overflow(my_decimal2int(E_DEC_ERROR & + else if (warn_if_overflow(my_decimal2int(E_DEC_ERROR & ~E_DEC_OVERFLOW & ~E_DEC_TRUNCATED, val, FALSE, &i))) { @@ -616,7 +619,7 @@ int Field_str::store_decimal(const my_decimal *d) { double val; /* TODO: use decimal2string? */ - int err= check_overflow(my_decimal2double(E_DEC_FATAL_ERROR & + int err= warn_if_overflow(my_decimal2double(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, d, &val)); return err | store(val); } @@ -1552,12 +1555,17 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value, checks if decimal_value fits into field size. if it does, stores the decimal in the buffer using binary format. Otherwise sets maximal number that can be stored in the field. + + RETURN + 0 ok + 1 error */ bool Field_new_decimal::store_value(const my_decimal *decimal_value) { - DBUG_ENTER("Field_new_decimal::store_value"); my_decimal *dec= (my_decimal*)decimal_value; + int error= 0; + DBUG_ENTER("Field_new_decimal::store_value"); DBUG_EXECUTE("enter", print_decimal(dec);); /* check that we do not try to write negative value in unsigned field */ @@ -1565,16 +1573,18 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value) { DBUG_PRINT("info", ("unsigned overflow")); set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + error= 1; dec= &decimal_zero; } DBUG_PRINT("info", ("saving with precision %d, scale: %d", (int)field_length, (int)decimals())); DBUG_EXECUTE("info", print_decimal(dec);); - if (check_overflow(my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, - dec, ptr, - field_length, - decimals()))) + if (warn_if_overflow(my_decimal2binary(E_DEC_FATAL_ERROR & + ~E_DEC_OVERFLOW, + dec, ptr, + field_length, + decimals()))) { my_decimal buff; DBUG_PRINT("info", ("overflow")); @@ -1584,20 +1594,20 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value) DBUG_RETURN(1); } DBUG_EXECUTE("info", print_decimal_buff(dec, ptr, bin_size);); - DBUG_RETURN(0); + DBUG_RETURN(error); } int Field_new_decimal::store(const char *from, uint length, CHARSET_INFO *charset) { - DBUG_ENTER("Field_new_decimal::store(char*)"); int err; my_decimal decimal_value; + DBUG_ENTER("Field_new_decimal::store(char*)"); + switch ((err= str2my_decimal(E_DEC_FATAL_ERROR & ~(E_DEC_OVERFLOW | E_DEC_BAD_NUM), - from, length, charset, &decimal_value))) - { + from, length, charset, &decimal_value))) { case E_DEC_TRUNCATED: set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1); break; @@ -1624,9 +1634,11 @@ int Field_new_decimal::store(const char *from, uint length, int Field_new_decimal::store(double nr) { my_decimal decimal_value; - int err= double2my_decimal(E_DEC_FATAL_ERROR & - ~E_DEC_OVERFLOW, nr, - &decimal_value); + int err; + DBUG_ENTER("Field_new_decimal::store(double)"); + + err= double2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, nr, + &decimal_value); /* TODO: fix following when double2my_decimal when double2decimal will return E_DEC_TRUNCATED always correctly @@ -1638,10 +1650,18 @@ int Field_new_decimal::store(double nr) if (nr2 != nr) err= E_DEC_TRUNCATED; } - if (check_overflow(err)) - set_value_on_overflow(&decimal_value, decimal_value.sign()); - store_value(&decimal_value); - return err; + if (err) + { + if (check_overflow(err)) + set_value_on_overflow(&decimal_value, decimal_value.sign()); + /* Only issue a warning if store_value doesn't issue an warning */ + table->in_use->got_warning= 0; + } + if (store_value(&decimal_value)) + err= 1; + else if (err && !table->in_use->got_warning) + err= warn_if_overflow(err); + DBUG_RETURN(err); } @@ -1649,10 +1669,19 @@ int Field_new_decimal::store(longlong nr) { my_decimal decimal_value; int err; - if ((err= check_overflow(int2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, - nr, unsigned_flag, &decimal_value)))) - set_value_on_overflow(&decimal_value, decimal_value.sign()); - store_value(&decimal_value); + + if ((err= int2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, + nr, unsigned_flag, &decimal_value))) + { + if (check_overflow(err)) + set_value_on_overflow(&decimal_value, decimal_value.sign()); + /* Only issue a warning if store_value doesn't issue an warning */ + table->in_use->got_warning= 0; + } + if (store_value(&decimal_value)) + err= 1; + else if (err && !table->in_use->got_warning) + err= warn_if_overflow(err); return err; } @@ -1694,7 +1723,7 @@ my_decimal* Field_new_decimal::val_decimal(my_decimal *decimal_value) String *Field_new_decimal::val_str(String *val_buffer, - String *val_ptr __attribute__((unused))) + String *val_ptr __attribute__((unused))) { my_decimal decimal_value; int fixed_precision= (zerofill ? @@ -1728,6 +1757,7 @@ void Field_new_decimal::sql_type(String &str) const add_zerofill_and_unsigned(str); } + /**************************************************************************** ** tiny int ****************************************************************************/ diff --git a/sql/field.h b/sql/field.h index d0b43e77e5a..327fb4c885b 100644 --- a/sql/field.h +++ b/sql/field.h @@ -290,7 +290,11 @@ public: int cuted_increment); void set_datetime_warning(const uint level, const uint code, double nr, timestamp_type ts_type); - int check_overflow(int op_result); + inline bool check_overflow(int op_result) + { + return (op_result == E_DEC_OVERFLOW); + } + int warn_if_overflow(int op_result); virtual field_cast_enum field_cast_type()= 0; bool field_cast_compatible(field_cast_enum type); /* maximum possible display length */ diff --git a/sql/sql_class.h b/sql/sql_class.h index b04ad449ba3..32a2390a402 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1027,6 +1027,7 @@ public: bool charset_is_system_charset, charset_is_collation_connection; bool slow_command; bool no_trans_update, abort_on_warning; + bool got_warning; /* Set on call to push_warning() */ longlong row_count_func; /* For the ROW_COUNT() function */ sp_rcontext *spcont; // SP runtime context sp_cache *sp_proc_cache; diff --git a/sql/sql_error.cc b/sql/sql_error.cc index adae481d608..d0f06c47edb 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -108,6 +108,7 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, if (thd->query_id != thd->warn_id) mysql_reset_errors(thd); + thd->got_warning= 1; if (thd->spcont && thd->spcont->find_handler(code, ((int) level >= diff --git a/sql/sql_list.h b/sql/sql_list.h index 6317d215399..85da553f64a 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -158,15 +158,6 @@ public: last= &first; return tmp->info; } - inline void concat(base_list *list) - { - if (!list->is_empty()) - { - *last= list->first; - last= list->last; - elements+= list->elements; - } - } inline void disjoin(base_list *list) { list_node **prev= &first; From 4b2b327dccfb2acc2903d83a5611045987e47183 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 10 Feb 2005 17:41:54 +0300 Subject: [PATCH 12/14] A fix and test case for Bug#7990 "mysql_stmt_close doesn't reset mysql->net.last_error": the solution is to clear MYSQL->net error before performing COM_CLOSE: if the call succeeds, the connection is usable for other statements. More comprehensive fix is to clear MYSQL->net for all recoverable errors at the time they happen, it will be implemented in 5.0 as it introduces incompatibility in behavior. --- libmysql/libmysql.c | 17 +++++++++++++++++ tests/mysql_client_test.c | 22 +++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 24a7fa5f929..76cf5c3913c 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1788,6 +1788,18 @@ static my_bool my_realloc_str(NET *net, ulong length) } +/* Clear possible error statee of struct NET */ + +static void net_clear_error(NET *net) +{ + if (net->last_errno) + { + net->last_errno= 0; + net->last_error[0]= '\0'; + strmov(net->sqlstate, not_error_sqlstate); + } +} + /* Set statement error code, sqlstate, and error message from given errcode and sqlstate. @@ -4512,6 +4524,11 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt) if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled) mysql->unbuffered_fetch_owner= 0; + /* + Clear NET error state: if the following commands come through + successfully, connection will still be usable for other commands. + */ + net_clear_error(&mysql->net); if (mysql->status != MYSQL_STATUS_READY) { /* diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index e4bdd1d350a..2c7a8fdb635 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11534,7 +11534,7 @@ static void test_bug6761(void) } -/* Bug#8330 - Bug #8330 mysql_stmt_execute crashes (libmysql) */ +/* Bug#8330 - mysql_stmt_execute crashes (libmysql) */ static void test_bug8330() { @@ -11585,6 +11585,26 @@ static void test_bug8330() } +/* Bug#7990 - mysql_stmt_close doesn't reset mysql->net.last_error */ + +static void test_bug7990() +{ + MYSQL_STMT *stmt; + int rc; + myheader("test_bug7990"); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, "foo", 3); + /* + XXX: the fact that we store errno both in STMT and in + MYSQL is not documented and is subject to change in 5.0 + */ + DIE_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql)); + mysql_stmt_close(stmt); + DIE_UNLESS(!mysql_errno(mysql)); +} + + /* Read and parse arguments and MySQL options from my.cnf */ From e9225b2588fd4c3c94ff3d74e3b38fd5f090d3e2 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 10 Feb 2005 17:46:27 +0300 Subject: [PATCH 13/14] Fix -ansi -pedantic compilation failure. --- sql/sql_parse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 19dc6b389e3..0a0258465fb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1310,7 +1310,7 @@ enum enum_mysql_completiontype { SAVEPOINT_NAME_ROLLBACK=2, SAVEPOINT_NAME_RELEASE=4, COMMIT_AND_CHAIN=6, - ROLLBACK_AND_CHAIN=7, + ROLLBACK_AND_CHAIN=7 }; int mysql_endtrans(THD *thd, enum enum_mysql_completiontype completion, From 36c992b264eca68467659f4aeb475ad6c0a53704 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 10 Feb 2005 18:24:26 +0300 Subject: [PATCH 14/14] Follow-up for bug#7990 --- libmysql/libmysql.c | 10 +++++----- tests/mysql_client_test.c | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 76cf5c3913c..9c49c7eb15b 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -4518,17 +4518,17 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt) if (mysql) { mysql->stmts= list_delete(mysql->stmts, &stmt->list); + /* + Clear NET error state: if the following commands come through + successfully, connection will still be usable for other commands. + */ + net_clear_error(&mysql->net); if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE) { char buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */ if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled) mysql->unbuffered_fetch_owner= 0; - /* - Clear NET error state: if the following commands come through - successfully, connection will still be usable for other commands. - */ - net_clear_error(&mysql->net); if (mysql->status != MYSQL_STATUS_READY) { /* diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 2c7a8fdb635..14b3ddbf8b2 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11813,6 +11813,7 @@ static struct my_tests_st my_tests[]= { { "test_rewind", test_rewind }, { "test_bug6761", test_bug6761 }, { "test_bug8330", test_bug8330 }, + { "test_bug7990", test_bug7990 }, { 0, 0 } };