diff options
author | matthias@three.local.lan <> | 2004-12-14 12:24:59 +0100 |
---|---|---|
committer | matthias@three.local.lan <> | 2004-12-14 12:24:59 +0100 |
commit | 621daba7b659bfdf0fe5e8b1754606e1ac116f6f (patch) | |
tree | bddd3849df4d89a28106f9b2ceaa154ae66cfba9 | |
parent | e69c8e76f9fa620aa62ffcac2643bfdadc021fac (diff) | |
parent | 94b3e06dd6dc258602b571c8b9803fce443c638d (diff) | |
download | mariadb-git-621daba7b659bfdf0fe5e8b1754606e1ac116f6f.tar.gz |
Merge mleich@bk-internal.mysql.com:/home/bk/mysql-4.1
into three.local.lan:/home/matthias/Arbeit/mysql-4.1/src
-rw-r--r-- | Makefile.am | 6 | ||||
-rw-r--r-- | innobase/dict/dict0load.c | 16 | ||||
-rw-r--r-- | mysql-test/mysql-test-run.sh | 2 | ||||
-rw-r--r-- | mysql-test/r/group_by.result | 12 | ||||
-rw-r--r-- | mysql-test/r/insert_select.result.es | 7 | ||||
-rw-r--r-- | mysql-test/t/group_by.test | 9 | ||||
-rw-r--r-- | sql/item.cc | 29 | ||||
-rw-r--r-- | sql/item.h | 31 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 7 | ||||
-rw-r--r-- | sql/item_func.cc | 5 | ||||
-rw-r--r-- | sql/item_row.cc | 1 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 1 | ||||
-rw-r--r-- | sql/item_strfunc.h | 3 | ||||
-rw-r--r-- | sql/item_subselect.cc | 3 | ||||
-rw-r--r-- | sql/item_sum.cc | 4 | ||||
-rw-r--r-- | sql/log_event.cc | 7 | ||||
-rw-r--r-- | sql/mysqld.cc | 3 | ||||
-rw-r--r-- | sql/set_var.cc | 6 | ||||
-rw-r--r-- | sql/sql_base.cc | 6 | ||||
-rw-r--r-- | sql/sql_handler.cc | 6 | ||||
-rw-r--r-- | sql/sql_help.cc | 3 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 23 | ||||
-rw-r--r-- | sql/sql_select.cc | 3 | ||||
-rw-r--r-- | tests/client_test.c | 51 |
24 files changed, 212 insertions, 32 deletions
diff --git a/Makefile.am b/Makefile.am index b00b3747294..c1ae9217e8b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -100,8 +100,4 @@ tags: # Test installation test: - cd mysql-test - ./mysql-test-run - ./mysql-test-run --ps-protocol - - + cd mysql-test; ./mysql-test-run && ./mysql-test-run --ps-protocol diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index 8fc6eb9141e..7890ebd2b47 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -765,6 +765,22 @@ dict_load_table( return(NULL); } +#if MYSQL_VERSION_ID < 50300 + /* Starting from MySQL 5.0.3, the high-order bit of MIX_LEN is the + "compact format" flag. */ + field = rec_get_nth_field(rec, 7, &len); + if (mach_read_from_1(field) & 0x80) { + btr_pcur_close(&pcur); + mtr_commit(&mtr); + mem_heap_free(heap); + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: table %s is in the new compact format\n" + "InnoDB: of MySQL 5.0.3 or later\n", name); + return(NULL); + } +#endif /* MYSQL_VERSION_ID < 50300 */ + ut_a(0 == ut_strcmp("SPACE", dict_field_get_col( dict_index_get_nth_field( diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 5a7ede0cba8..426b8b486be 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -947,7 +947,7 @@ start_ndbcluster() else NDBCLUSTER_EXTRA_OPTS="--small" fi - ./ndb/ndbcluster $NDBCLUSTER_OPTS $NDBCLUSTER_EXTRA_OPTS --diskless --initial || exit 1 + ./ndb/ndbcluster $NDBCLUSTER_OPTS $NDBCLUSTER_EXTRA_OPTS --initial || exit 1 NDB_CONNECTSTRING="host=localhost:$NDBCLUSTER_PORT" else NDB_CONNECTSTRING="$USE_RUNNING_NDBCLUSTER" diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 022b8eff7e8..f92b3ea4f4d 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -638,3 +638,15 @@ alias 1,2 1 drop table t1; +create table t1 (a int); +insert into t1 values(null); +select min(a) is null from t1; +min(a) is null +1 +select min(a) is null or null from t1; +min(a) is null or null +1 +select 1 and min(a) is null from t1; +1 and min(a) is null +1 +drop table t1; diff --git a/mysql-test/r/insert_select.result.es b/mysql-test/r/insert_select.result.es index 3955c0534f2..9e11402733d 100644 --- a/mysql-test/r/insert_select.result.es +++ b/mysql-test/r/insert_select.result.es @@ -78,6 +78,13 @@ a 1 2 drop table t1, t2; +create table t1(a int); +insert into t1 values(1),(1); +reset master; +create table t2(unique(a)) select a from t1; +ERROR 23000: Duplicate entry '1' for key 1 +show binlog events; +drop table t1; create table t1 (a int not null); create table t2 (a int not null); insert into t1 values (1); diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 59983594c32..c0447b06303 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -465,3 +465,12 @@ select group_concat( distinct col1 ) as alias from t1 drop table t1; + +#Test for BUG#6976: Aggregate functions have incorrect NULL-ness +create table t1 (a int); +insert into t1 values(null); +select min(a) is null from t1; +select min(a) is null or null from t1; +select 1 and min(a) is null from t1; +drop table t1; + diff --git a/sql/item.cc b/sql/item.cc index 9ed8b39dece..92a15694e89 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1488,7 +1488,14 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) "forward reference in item list"); return -1; } - + /* + Here, a subset of actions performed by Item_ref::set_properties + is not enough. So we pass ptr to NULL into Item_[direct]_ref + constructor, so no initialization is performed, and call + fix_fields() below. + */ + Item *save= last->ref_pointer_array[counter]; + last->ref_pointer_array[counter]= NULL; Item_ref *rf= (place == IN_HAVING ? new Item_ref(last->ref_pointer_array + counter, (char *)table_name, @@ -1499,6 +1506,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if (!rf) return 1; thd->change_item_tree(ref, rf); + last->ref_pointer_array[counter]= save; /* rf is Item_ref => never substitute other items (in this case) during fix_fields() => we can use rf after fix_fields() @@ -2221,19 +2229,24 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) "forward reference in item list")); return 1; } + + set_properties(); + + if (ref && (*ref)->check_cols(1)) + return 1; + return 0; +} + +void Item_ref::set_properties() +{ max_length= (*ref)->max_length; maybe_null= (*ref)->maybe_null; decimals= (*ref)->decimals; collation.set((*ref)->collation); with_sum_func= (*ref)->with_sum_func; fixed= 1; - - if (ref && (*ref)->check_cols(1)) - return 1; - return 0; } - void Item_ref::print(String *str) { if (ref && *ref) @@ -2279,7 +2292,7 @@ bool Item_default_value::fix_fields(THD *thd, fixed= 1; return 0; } - if (arg->fix_fields(thd, table_list, &arg)) + if (!arg->fixed && arg->fix_fields(thd, table_list, &arg)) return 1; if (arg->type() == REF_ITEM) @@ -2326,7 +2339,7 @@ bool Item_insert_value::fix_fields(THD *thd, Item **items) { DBUG_ASSERT(fixed == 0); - if (arg->fix_fields(thd, table_list, &arg)) + if (!arg->fixed && arg->fix_fields(thd, table_list, &arg)) return 1; if (arg->type() == REF_ITEM) diff --git a/sql/item.h b/sql/item.h index 7a288473533..71b92cd1efc 100644 --- a/sql/item.h +++ b/sql/item.h @@ -827,14 +827,36 @@ public: class Item_ref :public Item_ident { +protected: + void set_properties(); public: Field *result_field; /* Save result here */ Item **ref; Item_ref(const char *db_par, const char *table_name_par, const char *field_name_par) :Item_ident(db_par, table_name_par, field_name_par), ref(0) {} + /* + This constructor is used in two scenarios: + A) *item = NULL + No initialization is performed, fix_fields() call will be necessary. + + B) *item points to an Item this Item_ref will refer to. This is + used for GROUP BY. fix_fields() will not be called in this case, + so we call set_properties to make this item "fixed". set_properties + performs a subset of action Item_ref::fix_fields does, and this subset + is enough for Item_ref's used in GROUP BY. + + TODO we probably fix a superset of problems like in BUG#6658. Check this + with Bar, and if we have a more broader set of problems like this. + */ Item_ref(Item **item, const char *table_name_par, const char *field_name_par) - :Item_ident(NullS, table_name_par, field_name_par), ref(item) {} + :Item_ident(NullS, table_name_par, field_name_par), ref(item) + { + DBUG_ASSERT(item); + if (*item) + set_properties(); + } + /* Constructor need to process subselect with temporary tables (see Item) */ Item_ref(THD *thd, Item_ref *item) :Item_ident(thd, item), ref(item->ref) {} enum Type type() const { return REF_ITEM; } @@ -842,29 +864,34 @@ public: { return ref && (*ref)->eq(item, binary_cmp); } double val() { + DBUG_ASSERT(fixed); double tmp=(*ref)->val_result(); null_value=(*ref)->null_value; return tmp; } longlong val_int() { + DBUG_ASSERT(fixed); longlong tmp=(*ref)->val_int_result(); null_value=(*ref)->null_value; return tmp; } String *val_str(String* tmp) { + DBUG_ASSERT(fixed); tmp=(*ref)->str_result(tmp); null_value=(*ref)->null_value; return tmp; } bool is_null() { + DBUG_ASSERT(fixed); (void) (*ref)->val_int_result(); return (*ref)->null_value; } bool get_date(TIME *ltime,uint fuzzydate) { + DBUG_ASSERT(fixed); return (null_value=(*ref)->get_date_result(ltime,fuzzydate)); } bool send(Protocol *prot, String *tmp){ return (*ref)->send(prot, tmp); } @@ -902,6 +929,7 @@ public: :Item_ref(item, table_name_par, field_name_par) {} /* Constructor need to process subselect with temporary tables (see Item) */ Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {} + double val() { double tmp=(*ref)->val(); @@ -933,6 +961,7 @@ public: class Item_in_subselect; + class Item_ref_null_helper: public Item_ref { protected: diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 88083878053..a135f08ae45 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2022,6 +2022,7 @@ void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array, { 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; @@ -2373,8 +2374,10 @@ bool Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { DBUG_ASSERT(fixed == 0); - if (args[0]->fix_fields(thd, tables, args) || args[0]->check_cols(1) || - args[1]->fix_fields(thd,tables, args + 1) || args[1]->check_cols(1)) + if ((!args[0]->fixed && + args[0]->fix_fields(thd, tables, args)) || args[0]->check_cols(1) || + (!args[1]->fixed && + args[1]->fix_fields(thd,tables, args + 1)) || args[1]->check_cols(1)) return 1; /* purecov: inspected */ with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func; max_length= 1; diff --git a/sql/item_func.cc b/sql/item_func.cc index 98b204d1809..2d939f47716 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -349,8 +349,8 @@ void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array, else if (item->used_tables() || item->type() == SUM_FUNC_ITEM) { uint el= fields.elements; + ref_pointer_array[el]= item; Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name); - new_item->collation.set(item->collation); fields.push_front(item); ref_pointer_array[el]= item; thd->change_item_tree(arg, new_item); @@ -1663,7 +1663,8 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, arg != arg_end ; arg++,i++) { - if ((*arg)->fix_fields(thd, tables, arg)) + if (!(*arg)->fixed && + (*arg)->fix_fields(thd, tables, arg)) DBUG_RETURN(1); // we can't assign 'item' before, because fix_fields() can change arg Item *item= *arg; diff --git a/sql/item_row.cc b/sql/item_row.cc index 289efe45300..4e4957b980e 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -95,6 +95,7 @@ void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array, else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_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; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index aaeeb9d8bb8..e1b063cd5e0 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1748,6 +1748,7 @@ void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array, else if (item->used_tables() || item->type() == SUM_FUNC_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; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 8efe60bbd89..698536a61c7 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -397,7 +397,8 @@ public: bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { DBUG_ASSERT(fixed == 0); - return (item->fix_fields(thd, tlist, &item) || + return (!item->fixed && + item->fix_fields(thd, tlist, &item) || item->check_cols(1) || Item_func::fix_fields(thd, tlist, ref)); } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index ffa3b072801..1d0f46fd196 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -766,7 +766,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, // left expression belong to outer select SELECT_LEX *current= thd->lex->current_select, *up; thd->lex->current_select= up= current->return_after_parsing(); - if (left_expr->fix_fields(thd, up->get_table_list(), &left_expr)) + if (!left_expr->fixed && + left_expr->fix_fields(thd, up->get_table_list(), &left_expr)) { thd->lex->current_select= current; goto err; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 66d4fba205c..029a1fd6c48 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1918,7 +1918,9 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) for (i=0 ; i < arg_count ; i++) { - if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1)) + if ((!args[i]->fixed && + args[i]->fix_fields(thd, tables, args + i)) || + args[i]->check_cols(1)) return 1; if (i < arg_count_field) maybe_null|= args[i]->maybe_null; diff --git a/sql/log_event.cc b/sql/log_event.cc index 7a4d14d101a..087e58a7bad 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1416,7 +1416,9 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, List<Item> &fields_arg, enum enum_duplicates handle_dup, bool using_trans) - :Log_event(thd_arg, 0, using_trans), thread_id(thd_arg->thread_id), + :Log_event(thd_arg, !thd_arg->tmp_table_used ? + 0 : LOG_EVENT_THREAD_SPECIFIC_F, using_trans), + thread_id(thd_arg->thread_id), slave_proxy_id(thd_arg->variables.pseudo_thread_id), num_fields(0),fields(0), field_lens(0),field_block_len(0), @@ -1606,6 +1608,9 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db, commented ? "# " : "", db); + if (flags & LOG_EVENT_THREAD_SPECIFIC_F) + fprintf(file,"%sSET @@session.pseudo_thread_id=%lu;\n", + commented ? "# " : "", (ulong)thread_id); fprintf(file, "%sLOAD DATA ", commented ? "# " : ""); if (check_fname_outside_temp_buf()) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9343c79c9f0..e39c902444e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4757,7 +4757,8 @@ replicating a LOAD DATA INFILE command.", (gptr*) &delayed_queue_size, (gptr*) &delayed_queue_size, 0, GET_ULONG, REQUIRED_ARG, DELAYED_QUEUE_SIZE, 1, ~0L, 0, 1, 0}, {"expire_logs_days", OPT_EXPIRE_LOGS_DAYS, - "Binary logs will be rotated after expire-log-days days ", + "If non-zero, binary logs will be purged after expire_logs_days " + "days; possible purges happen at startup and at binary log rotation.", (gptr*) &expire_logs_days, (gptr*) &expire_logs_days, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 99, 0, 1, 0}, diff --git a/sql/set_var.cc b/sql/set_var.cc index b7f410c207d..d10ea3e11c1 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2799,7 +2799,8 @@ int set_var::check(THD *thd) return 0; } - if (value->fix_fields(thd, 0, &value) || value->check_cols(1)) + if ((!value->fixed && + value->fix_fields(thd, 0, &value)) || value->check_cols(1)) return -1; if (var->check_update_type(value->result_type())) { @@ -2834,7 +2835,8 @@ int set_var::light_check(THD *thd) if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)) return 1; - if (value && (value->fix_fields(thd, 0, &value) || value->check_cols(1))) + if (value && ((!value->fixed && value->fix_fields(thd, 0, &value)) || + value->check_cols(1))) return -1; return 0; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 05b11646cd7..5c71049e565 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2684,7 +2684,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) thd->restore_backup_item_arena(arena, &backup); if (*conds && !(*conds)->fixed) { - if ((*conds)->fix_fields(thd, tables, conds)) + if (!(*conds)->fixed && + (*conds)->fix_fields(thd, tables, conds)) DBUG_RETURN(1); } } @@ -2696,7 +2697,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) thd->restore_backup_item_arena(arena, &backup); if (table->on_expr && !table->on_expr->fixed) { - if (table->on_expr->fix_fields(thd, tables, &table->on_expr)) + if (!table->on_expr->fixed && + table->on_expr->fix_fields(thd, tables, &table->on_expr)) DBUG_RETURN(1); } } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index f98bb0a9131..f250a00eca1 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -429,7 +429,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, } tables->table=table; - if (cond && (cond->fix_fields(thd, tables, &cond) || cond->check_cols(1))) + if (cond && ((!cond->fixed && + cond->fix_fields(thd, tables, &cond)) || cond->check_cols(1))) goto err0; table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it @@ -516,7 +517,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, for (key_len=0 ; (item=it_ke++) ; key_part++) { // 'item' can be changed by fix_fields() call - if (item->fix_fields(thd, tables, it_ke.ref()) || + if ((!item->fixed && + item->fix_fields(thd, tables, it_ke.ref())) || (item= *it_ke.ref())->check_cols(1)) goto err; if (item->used_tables() & ~RAND_TABLE_BIT) diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 04ecbbd43b9..0e0d32a922d 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -557,7 +557,8 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol, SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables, TABLE *table, int *error) { - cond->fix_fields(thd, tables, &cond); // can never fail + if (!cond->fixed) + cond->fix_fields(thd, tables, &cond); // can never fail SQL_SELECT *res= make_select(table,0,0,cond,error); if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR))) { diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index f4a96d751cd..6d2ddf03b50 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1514,6 +1514,27 @@ static bool init_param_array(Prepared_statement *stmt) } +/* Init statement before execution */ + +static void cleanup_stmt_for_execute(Prepared_statement *stmt) +{ + THD *thd= stmt->thd; + LEX *lex= stmt->lex; + SELECT_LEX *sl= lex->all_selects_list; + + for (; sl; sl= sl->next_select_in_list()) + { + for (TABLE_LIST *tables= (TABLE_LIST*) sl->table_list.first; + tables; + tables= tables->next) + { + if (tables->table) + tables->table->insert_values= 0; + } + } +} + + /* Given a query string with parameter markers, create a Prepared Statement from it and send PS info back to the client. @@ -1614,6 +1635,7 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, if (!error) error= send_prepare_results(stmt, test(name)); + cleanup_stmt_for_execute(stmt); /* restore to WAIT_PRIOR: QUERY_PRIOR is set inside alloc_query */ if (!(specialflag & SPECIAL_NO_PRIOR)) @@ -1904,6 +1926,7 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt, reset_stmt_params(stmt); close_thread_tables(thd); // to close derived tables thd->set_statement(&thd->stmt_backup); + cleanup_stmt_for_execute(stmt); DBUG_VOID_RETURN; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f2499966815..2d701e668cf 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8904,7 +8904,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) if (thd->is_fatal_error) DBUG_RETURN(TRUE); - cond->fix_fields(thd,(TABLE_LIST *) 0, (Item**)&cond); + if (!cond->fixed) + cond->fix_fields(thd,(TABLE_LIST *) 0, (Item**)&cond); if (join_tab->select) { error=(int) cond->add(join_tab->select->cond); diff --git a/tests/client_test.c b/tests/client_test.c index 75ce242900a..b0bf40799da 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -1026,6 +1026,56 @@ static void test_tran_innodb() } +/* Test for BUG#7242 */ + +static void test_prepare_insert_update() +{ + MYSQL_STMT *stmt; + int rc; + int i; + const char *testcase[]= { + "CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B))", + "INSERT t1 VALUES (1,2,10), (3,4,20)", + "INSERT t1 VALUES (5,6,30), (7,4,40), (8,9,60) ON DUPLICATE KEY UPDATE c=c+100", + "SELECT * FROM t1", + "INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0", + "SELECT * FROM t1", + "INSERT t1 VALUES (2,1,11), (7,4,40) ON DUPLICATE KEY UPDATE c=c+VALUES(a)", + NULL}; + const char **cur_query; + + myheader("test_prepare_insert_update"); + + for (cur_query= testcase; *cur_query; cur_query++) + { + printf("\nRunning query: %s", *cur_query); + strmov(query, *cur_query); + stmt= mysql_simple_prepare(mysql, query); + check_stmt(stmt); + + verify_param_count(stmt, 0); + rc= mysql_stmt_execute(stmt); + + check_execute(stmt, rc); + /* try the last query several times */ + if (!cur_query[1]) + { + for (i=0; i < 3;i++) + { + printf("\nExecuting last statement again"); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + } + } + mysql_stmt_close(stmt); + } + + rc= mysql_commit(mysql); + myquery(rc); +} + /* Test simple prepares of all DML statements */ static void test_prepare_simple() @@ -11513,6 +11563,7 @@ and you are welcome to modify and redistribute it under the GPL license\n"); static struct my_tests_st my_tests[]= { { "client_query", client_query }, + { "test_prepare_insert_update", test_prepare_insert_update}, #if NOT_YET_WORKING { "test_drop_temp", test_drop_temp }, #endif |