diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_ndbcluster.cc | 1 | ||||
-rw-r--r-- | sql/handler.cc | 2 | ||||
-rw-r--r-- | sql/item.cc | 26 | ||||
-rw-r--r-- | sql/item.h | 3 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 11 | ||||
-rw-r--r-- | sql/item_func.cc | 3 | ||||
-rw-r--r-- | sql/log_event.cc | 2 | ||||
-rw-r--r-- | sql/mysql_priv.h | 2 | ||||
-rw-r--r-- | sql/opt_range.cc | 3 | ||||
-rw-r--r-- | sql/protocol.cc | 2 | ||||
-rw-r--r-- | sql/protocol.h | 4 | ||||
-rw-r--r-- | sql/protocol_cursor.cc | 23 | ||||
-rw-r--r-- | sql/sp.cc | 8 | ||||
-rw-r--r-- | sql/sp_head.cc | 2 | ||||
-rw-r--r-- | sql/sql_base.cc | 20 | ||||
-rw-r--r-- | sql/sql_class.cc | 15 | ||||
-rw-r--r-- | sql/sql_class.h | 9 | ||||
-rw-r--r-- | sql/sql_handler.cc | 7 | ||||
-rw-r--r-- | sql/sql_parse.cc | 27 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 27 | ||||
-rw-r--r-- | sql/sql_select.cc | 71 | ||||
-rw-r--r-- | sql/sql_table.cc | 37 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 7 | ||||
-rw-r--r-- | sql/sql_update.cc | 7 | ||||
-rw-r--r-- | sql/sql_view.cc | 9 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 3 |
26 files changed, 201 insertions, 130 deletions
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index d59ab919862..7878684718c 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -4015,6 +4015,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path, (void)mysql_rm_table_part2(thd, &table_list, /* if_exists */ TRUE, /* drop_temporary */ FALSE, + /* drop_view */ FALSE, /* dont_log_query*/ TRUE); } } diff --git a/sql/handler.cc b/sql/handler.cc index edb47865e8d..5b600719acd 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1427,7 +1427,7 @@ int ha_create_table_from_engine(THD* thd, if ((error = writefrm(path, frmblob, frmlen))) goto err_end; - if (openfrm(path,"",0,(uint) READ_ALL, 0, &table)) + if (openfrm(thd, path,"",0,(uint) READ_ALL, 0, &table)) DBUG_RETURN(1); update_create_info_from_table(&create_info, &table); diff --git a/sql/item.cc b/sql/item.cc index 7476f5af312..6730b0dd4a2 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -45,11 +45,11 @@ void item_init(void) } Item::Item(): - name_length(0), fixed(0) + name_length(0), fixed(0), + collation(default_charset(), DERIVATION_COERCIBLE) { marker= 0; maybe_null=null_value=with_sum_func=unsigned_flag=0; - collation.set(default_charset(), DERIVATION_COERCIBLE); name= 0; decimals= 0; max_length= 0; @@ -1576,6 +1576,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) (char*) cached_table->alias, (char*) field_name); if (!rf) return 1; + thd->change_item_tree(ref, rf); /* rf is Item_ref => never substitute other items (in this case) during fix_fields() => we can use rf after fix_fields() @@ -1654,6 +1655,7 @@ void Item_field::cleanup() I.e. we can drop 'field'. */ field= result_field= 0; + DBUG_VOID_RETURN; } /* @@ -1698,7 +1700,8 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal) /* - Set a pointer to the multiple equality the field reference belongs to (if any) + Set a pointer to the multiple equality the field reference belongs to + (if any) SYNOPSIS equal_fields_propagator() @@ -1737,7 +1740,21 @@ Item *Item_field::equal_fields_propagator(byte *arg) /* - Set a pointer to the multiple equality the field reference belongs to (if any) + Mark the item to not be part of substitution if it's not a binary item + See comments in Arg_comparator::set_compare_func() for details +*/ + +Item *Item_field::set_no_const_sub(byte *arg) +{ + if (field->charset() != &my_charset_bin) + no_const_subst=1; + return this; +} + + +/* + Set a pointer to the multiple equality the field reference belongs to + (if any) SYNOPSIS replace_equal_field_processor() @@ -1773,6 +1790,7 @@ bool Item_field::replace_equal_field_processor(byte *arg) return 0; } + void Item::init_make_field(Send_field *tmp_field, enum enum_field_types field_type) { diff --git a/sql/item.h b/sql/item.h index b39a95d796c..d3e53af1523 100644 --- a/sql/item.h +++ b/sql/item.h @@ -285,6 +285,7 @@ public: virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; } virtual bool collect_item_field_processor(byte * arg) { return 0; } virtual Item *equal_fields_propagator(byte * arg) { return this; } + virtual Item *set_no_const_sub(byte *arg) { return this; } virtual bool replace_equal_field_processor(byte * arg) { return 0; } virtual Item *this_item() { return this; } /* For SPs mostly. */ @@ -536,6 +537,7 @@ public: void cleanup(); Item_equal *find_item_equal(COND_EQUAL *cond_equal); Item *equal_fields_propagator(byte *arg); + Item *set_no_const_sub(byte *arg); bool replace_equal_field_processor(byte *arg); inline uint32 max_disp_length() { return field->max_length(); } Item_field *filed_for_view_update() { return this; } @@ -1024,6 +1026,7 @@ public: bool walk(Item_processor processor, byte *arg) { return (*ref)->walk(processor, arg); } void print(String *str); + void cleanup(); }; class Item_in_subselect; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index ab8acdd465f..467cd8313a4 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -320,6 +320,17 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) func= &Arg_comparator::compare_binary_string; else if (func == &Arg_comparator::compare_e_string) func= &Arg_comparator::compare_e_binary_string; + + /* + As this is binary comparsion, mark all fields that they can't be + transformed. Otherwise we would get into trouble with comparisons + like: + WHERE col= 'j' AND col LIKE BINARY 'j' + which would be transformed to: + WHERE col= 'j' + */ + (*a)->transform(&Item::set_no_const_sub, (byte*) 0); + (*b)->transform(&Item::set_no_const_sub, (byte*) 0); } } else if (type == INT_RESULT) diff --git a/sql/item_func.cc b/sql/item_func.cc index 58ef44cc225..3cc0fd077a4 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -292,7 +292,8 @@ Item *Item_func::transform(Item_transformer transformer, byte *argument) Item *new_item= (*arg)->transform(transformer, argument); if (!new_item) return 0; - *arg= new_item; + if (*arg != new_item) + current_thd->change_item_tree(arg, new_item); } } return (this->*transformer)(argument); diff --git a/sql/log_event.cc b/sql/log_event.cc index a80b0e13df8..ee5af6ed1c0 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1543,7 +1543,7 @@ end: updating query. */ return (thd->query_error ? thd->query_error : - (thd->one_shot_set ? (rli->inc_event_relay_log_pos(get_event_len()),0) : + (thd->one_shot_set ? (rli->inc_event_relay_log_pos(),0) : Log_event::exec_event(rli))); } #endif diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a339b61563a..5c0b47aca4a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -492,7 +492,7 @@ bool is_update_query(enum enum_sql_command command); bool alloc_query(THD *thd, char *packet, ulong packet_length); void mysql_init_select(LEX *lex); void mysql_reset_thd_for_next_command(THD *thd); -void mysql_init_query(THD *thd, uchar *buf, uint length, bool lexonly=0); +void mysql_init_query(THD *thd, uchar *buf, uint length); bool mysql_new_select(LEX *lex, bool move_down); void create_select_for_variable(const char *var_name); void mysql_init_multi_delete(LEX *lex); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 10b9fc9fbfd..c2cdc39714b 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -712,8 +712,9 @@ QUICK_SELECT_I::QUICK_SELECT_I() QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc, MEM_ROOT *parent_alloc) - :dont_free(0),sorted(0),error(0),free_file(0),cur_range(NULL),range(0) + :dont_free(0),error(0),free_file(0),cur_range(NULL),range(0) { + sorted= 0; index= key_nr; head= table; key_part_info= head->key_info[index].key_part; diff --git a/sql/protocol.cc b/sql/protocol.cc index 36296cea59b..051eaaf7bda 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -507,7 +507,7 @@ void Protocol::init(THD *thd_arg) */ #ifndef EMBEDDED_LIBRARY -bool Protocol::send_fields(List<Item> *list, int flags) +bool Protocol::send_fields(List<Item> *list, uint flags) { List_iterator_fast<Item> it(*list); Item *item; diff --git a/sql/protocol.h b/sql/protocol.h index 1a5896a3ae5..7d390242417 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -52,7 +52,7 @@ public: void init(THD* thd_arg); enum { SEND_NUM_ROWS= 1, SEND_DEFAULTS= 2, SEND_EOF= 4 }; - virtual bool send_fields(List<Item> *list, int flags); + virtual bool send_fields(List<Item> *list, uint flags); bool send_records_num(List<Item> *list, ulonglong records); bool store(I_List<i_string> *str_list); @@ -166,7 +166,7 @@ public: prev_record= &data; return Protocol_simple::prepare_for_send(item_list); } - bool send_fields(List<Item> *list, int flags); + bool send_fields(List<Item> *list, uint flags); bool write(); uint get_field_count() { return field_count; } }; diff --git a/sql/protocol_cursor.cc b/sql/protocol_cursor.cc index 8904aba7b88..104457b3bcc 100644 --- a/sql/protocol_cursor.cc +++ b/sql/protocol_cursor.cc @@ -26,22 +26,21 @@ #include "mysql_priv.h" #include <mysql.h> -bool Protocol_cursor::send_fields(List<Item> *list, int flags) +bool Protocol_cursor::send_fields(List<Item> *list, uint flags) { List_iterator_fast<Item> it(*list); Item *item; MYSQL_FIELD *client_field; - - DBUG_ENTER("send_fields"); + DBUG_ENTER("Protocol_cursor::send_fields"); + if (prepare_for_send(list)) - return FALSE; + return FALSE; fields= (MYSQL_FIELD *)alloc_root(alloc, sizeof(MYSQL_FIELD) * field_count); if (!fields) goto err; - client_field= fields; - while ((item= it++)) + for (client_field= fields; (item= it++) ; client_field++) { Send_field server_field; item->make_field(&server_field); @@ -67,7 +66,7 @@ bool Protocol_cursor::send_fields(List<Item> *list, int flags) if (INTERNAL_NUM_FIELD(client_field)) client_field->flags|= NUM_FLAG; - if (flags & (int) Protocol::SEND_DEFAULTS) + if (flags & (uint) Protocol::SEND_DEFAULTS) { char buff[80]; String tmp(buff, sizeof(buff), default_charset_info), *res; @@ -80,16 +79,18 @@ bool Protocol_cursor::send_fields(List<Item> *list, int flags) else client_field->def=0; client_field->max_length= 0; - ++client_field; } DBUG_RETURN(FALSE); - err: + +err: send_error(thd, ER_OUT_OF_RESOURCES); /* purecov: inspected */ DBUG_RETURN(TRUE); /* purecov: inspected */ } + /* Get the length of next field. Change parameter to point at fieldstart */ + bool Protocol_cursor::write() { byte *cp= (byte *)packet->ptr(); @@ -121,7 +122,7 @@ bool Protocol_cursor::write() { if ((long)len > (end_pos - cp)) { -// TODO error signal send_error(thd, CR_MALFORMED_PACKET); + // TODO error signal send_error(thd, CR_MALFORMED_PACKET); return TRUE; } *data_tmp= to; @@ -141,6 +142,6 @@ bool Protocol_cursor::write() row_count++; return FALSE; err: -// TODO error signal send_error(thd, ER_OUT_OF_RESOURCES); + // TODO error signal send_error(thd, ER_OUT_OF_RESOURCES); return TRUE; } diff --git a/sql/sp.cc b/sql/sp.cc index e444a412760..a1e52ee1ca7 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -293,7 +293,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) */ List<Item> vals= thd->lex->value_list; - mysql_init_query(thd, (uchar*)defstr.c_ptr(), defstr.length(), TRUE); + lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length()); thd->lex->value_list= vals; } @@ -455,7 +455,7 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) if (ret == SP_OK) { store_record(table,record[1]); - table->timestamp_on_update_now = 0; // Don't update create time now. + table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time(); if (chistics->suid != SP_IS_DEFAULT_SUID) table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]-> @@ -1055,6 +1055,10 @@ create_string(THD *thd, String *buf, case SP_MODIFIES_SQL_DATA: buf->append(" MODIFIES SQL DATA\n"); break; + case SP_DEFAULT_ACCESS: + case SP_CONTAINS_SQL: + /* Do nothing */ + break; } if (chistics->detistic) buf->append(" DETERMINISTIC\n", 18); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 82f8e88d889..8de1b6e906a 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -765,7 +765,7 @@ sp_head::reset_lex(THD *thd) thd->lex= sublex= new st_lex; /* Reset most stuff. The length arguments doesn't matter here. */ - mysql_init_query(thd,oldlex->buf, oldlex->end_of_query - oldlex->ptr, TRUE); + lex_start(thd, oldlex->buf, (ulong) (oldlex->end_of_query - oldlex->ptr)); /* We must reset ptr and end_of_query again */ sublex->ptr= oldlex->ptr; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index af6c4740e93..b3be1fc7338 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -958,7 +958,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, } /* close handler tables which are marked for flush */ - mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE); + if (thd->handler_tables) + mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE); for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; table && table->in_use ; @@ -2095,11 +2096,14 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, *ref= trans[i]; else { - *ref= new Item_ref(trans + i, ref, table_list->view_name.str, - item_name); - /* as far as Item_ref have defined refernce it do not need tables */ - if (*ref) + Item_ref *item_ref= new Item_ref(trans + i, table_list->view_name.str, + item_name); + /* as far as Item_ref have defined reference it do not need tables */ + if (item_ref) + { + thd->change_item_tree(ref, item_ref); (*ref)->fix_fields(thd, 0, ref); + } } return (Field*) view_ref_found; } @@ -2823,7 +2827,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table, RETURN 0 ok 'it' is updated to point at last inserted - 1 error. The error message is sent to client + 1 error. Error message is generated but not sent to client */ bool @@ -2999,9 +3003,8 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, during cleunup() this item will be put in list to replace expression from VIEW */ - item->changed_during_fix_field= it->ref(); + thd->nocheck_register_item_tree_change(it->ref(), item, &thd->mem_root); } - } /* All fields are used */ table->used_fields=table->fields; @@ -3016,7 +3019,6 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, my_error(ER_BAD_TABLE_ERROR, MYF(0), table_name); err: - send_error(thd); DBUG_RETURN(1); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9bf7cff85c0..f5283020b30 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -165,6 +165,9 @@ THD::THD() in_lock_tables(0), bootstrap(0), spcont(NULL) { current_arena= this; +#ifndef DBUG_OFF + backup_arena= 0; +#endif host= user= priv_user= db= ip= 0; catalog= (char*)"std"; // the only catalog we have for now host_or_ip= "connecting host"; @@ -795,10 +798,13 @@ void THD::rollback_item_tree_changes() { I_List_iterator<Item_change_record> it(change_list); Item_change_record *change; + DBUG_ENTER("rollback_item_tree_changes"); + while ((change= it++)) *change->place= change->old_value; /* We can forget about changes memory: it's allocated in runtime memroot */ change_list.empty(); + DBUG_VOID_RETURN; } @@ -1585,16 +1591,24 @@ void THD::end_statement() void Item_arena::set_n_backup_item_arena(Item_arena *set, Item_arena *backup) { DBUG_ENTER("Item_arena::set_n_backup_item_arena"); + DBUG_ASSERT(backup_arena == 0); backup->set_item_arena(this); set_item_arena(set); +#ifndef DBUG_OFF + backup_arena= 1; +#endif DBUG_VOID_RETURN; } void Item_arena::restore_backup_item_arena(Item_arena *set, Item_arena *backup) { + DBUG_ENTER("Item_arena::restore_backup_item_arena"); set->set_item_arena(this); set_item_arena(backup); +#ifndef DBUG_OFF + backup_arena= 0; +#endif #ifdef NOT_NEEDED_NOW /* Reset backup mem_root to avoid its freeing. @@ -1605,6 +1619,7 @@ void Item_arena::restore_backup_item_arena(Item_arena *set, Item_arena *backup) */ clear_alloc_root(&backup->mem_root); #endif + DBUG_VOID_RETURN; } void Item_arena::set_item_arena(Item_arena *set) diff --git a/sql/sql_class.h b/sql/sql_class.h index 6e0aacc4fce..fcaebe64b43 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -516,6 +516,9 @@ public: */ Item *free_list; MEM_ROOT mem_root; +#ifndef DBUG_OFF + bool backup_arena; +#endif enum enum_state { INITIALIZED= 0, PREPARED= 1, EXECUTED= 3, CONVENTIONAL_EXECUTION= 2, @@ -552,7 +555,7 @@ public: inline bool is_first_stmt_execute() const { return state == PREPARED; } inline bool is_stmt_execute() const { return state == PREPARED || state == EXECUTED; } - inline bool is_conventional_execution() const + inline bool is_conventional() const { return state == CONVENTIONAL_EXECUTION; } inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); } inline gptr calloc(unsigned int size) @@ -1167,7 +1170,7 @@ public: void change_item_tree(Item **place, Item *new_value) { /* TODO: check for OOM condition here */ - if (!current_arena->is_conventional_execution()) + if (!current_arena->is_conventional()) nocheck_register_item_tree_change(place, *place, &mem_root); *place= new_value; } @@ -1254,6 +1257,7 @@ public: virtual bool initialize_tables (JOIN *join=0) { return 0; } virtual void send_error(uint errcode,const char *err); virtual bool send_eof()=0; + virtual bool simple_select() { return 0; } virtual void abort() {} /* Cleanup instance of this class for next execution of a prepared @@ -1283,6 +1287,7 @@ public: bool send_fields(List<Item> &list, uint flags); bool send_data(List<Item> &items); bool send_eof(); + bool simple_select() { return 1; } }; diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 61e57362bd4..edb895fd24a 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -288,7 +288,6 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables) { (*table_ptr)->file->ha_index_or_rnd_end(); VOID(pthread_mutex_lock(&LOCK_open)); - table->file->ha_index_or_rnd_end(); if (close_thread_table(thd, table_ptr)) { /* Tell threads waiting for refresh that something has happened */ @@ -532,11 +531,11 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, { if (error == HA_ERR_RECORD_DELETED) continue; - if (err != HA_ERR_KEY_NOT_FOUND && err != HA_ERR_END_OF_FILE) + if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) { sql_print_error("mysql_ha_read: Got error %d when reading table '%s'", - err, tables->real_name); - table->file->print_error(err,MYF(0)); + error, tables->real_name); + table->file->print_error(error,MYF(0)); goto err; } goto ok; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 55e0d33cdde..77919329e16 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2809,7 +2809,8 @@ unsent_create_error: break; res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values, select_lex->item_list, lex->value_list, - lex->duplicates); + (lex->value_list.elements ? + DUP_UPDATE : lex->duplicates)); if (thd->net.report_error) res= -1; if (first_table->view && !first_table->contain_auto_increment) @@ -6241,9 +6242,9 @@ int insert_precheck(THD *thd, TABLE_LIST *tables) LEX *lex= thd->lex; DBUG_ENTER("insert_precheck"); - ulong privilege= INSERT_ACL | - (lex->duplicates == DUP_REPLACE ? DELETE_ACL : 0) | - (lex->duplicates == DUP_UPDATE ? UPDATE_ACL : 0); + ulong privilege= (INSERT_ACL | + (lex->duplicates == DUP_REPLACE ? DELETE_ACL : 0) | + (lex->value_list.elements ? UPDATE_ACL : 0)); if (check_one_table_access(thd, privilege, tables)) DBUG_RETURN(1); @@ -6308,27 +6309,13 @@ int create_table_precheck(THD *thd, TABLE_LIST *tables, For temporary tables we don't have to check if the created table exists */ if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) && - find_real_table_in_list(tables, create_table->db, - create_table->real_name)) + find_table_in_global_list(tables, create_table->db, + create_table->real_name)) { net_printf(thd,ER_UPDATE_TABLE_USED, create_table->real_name); goto err; } - if (lex->create_info.used_fields & HA_CREATE_USED_UNION) - { - TABLE_LIST *tab; - for (tab= tables; tab; tab= tab->next) - { - if (find_real_table_in_list((TABLE_LIST*) lex->create_info. - merge_list.first, - tables->db, tab->real_name)) - { - net_printf(thd, ER_UPDATE_TABLE_USED, tab->real_name); - goto err; - } - } - } } if (tables && check_table_access(thd, SELECT_ACL, tables,0)) goto err; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index a9a81ed7b06..bb2362dd562 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -156,6 +156,8 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns) { NET *net= &stmt->thd->net; char buff[9]; + DBUG_ENTER("send_prep_stmt"); + buff[0]= 0; /* OK packet indicator */ int4store(buff+1, stmt->id); int2store(buff+5, columns); @@ -164,13 +166,12 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns) Send types and names of placeholders to the client XXX: fix this nasty upcast from List<Item_param> to List<Item> */ - return my_net_write(net, buff, sizeof(buff)) || - (stmt->param_count && - stmt->thd->protocol_simple.send_fields((List<Item> *) - &stmt->lex->param_list, - Protocol::SEND_EOF)) || - net_flush(net); - return 0; + DBUG_RETURN(my_net_write(net, buff, sizeof(buff)) || + (stmt->param_count && + stmt->thd->protocol_simple.send_fields((List<Item> *) + &stmt->lex->param_list, + Protocol::SEND_EOF)) || + net_flush(net)); } #else static bool send_prep_stmt(Prepared_statement *stmt, @@ -1114,8 +1115,7 @@ static int mysql_test_select(Prepared_statement *stmt, prepared in unit->prepare call above. */ if (send_prep_stmt(stmt, lex->result->field_count(fields)) || - thd->protocol_simple.send_fields(fields, - Protocol::SEND_EOF) + lex->result->send_fields(fields, Protocol::SEND_EOF) #ifndef EMBEDDED_LIBRARY || net_flush(&thd->net) #endif @@ -1682,11 +1682,13 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, DBUG_RETURN(!stmt); } + /* Reinit statement before execution */ void reset_stmt_for_execute(THD *thd, LEX *lex) { SELECT_LEX *sl= lex->all_selects_list; + DBUG_ENTER("reset_stmt_for_execute"); if (lex->empty_field_list_on_rset) { @@ -1749,6 +1751,8 @@ void reset_stmt_for_execute(THD *thd, LEX *lex) lex->current_select= &lex->select_lex; if (lex->result) lex->result->cleanup(); + + DBUG_VOID_RETURN; } @@ -1814,8 +1818,9 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) mysql_reset_thd_for_next_command(thd); if (flags & (ulong) CURSOR_TYPE_READ_ONLY) { - if (stmt->lex->result) + if (!stmt->lex->result || !stmt->lex->result->simple_select()) { + DBUG_PRINT("info",("Cursor asked for not SELECT stmt")); /* If lex->result is set in the parser, this is not a SELECT statement: we can't open a cursor for it. @@ -1824,6 +1829,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) } else { + DBUG_PRINT("info",("Using READ_ONLY cursor")); if (!stmt->cursor && !(stmt->cursor= new (&stmt->mem_root) Cursor())) { @@ -1885,6 +1891,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) cleanup_items(stmt->free_list); reset_stmt_params(stmt); close_thread_tables(thd); /* to close derived tables */ + thd->rollback_item_tree_changes(); thd->cleanup_after_query(); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f4fbd03768d..2e1429feb3e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -91,7 +91,7 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables, uint select_options, const char *info, Item *having, Procedure *proc, SELECT_LEX_UNIT *unit); -static COND *build_equal_items(COND *cond, +static COND *build_equal_items(THD *thd, COND *cond, COND_EQUAL *inherited, List<TABLE_LIST> *join_list, COND_EQUAL **cond_equal_ref); @@ -101,6 +101,7 @@ static COND* substitute_for_best_equal_field(COND *cond, static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top); static COND *optimize_cond(JOIN *join, COND *conds, + List<TABLE_LIST> *join_list, Item::cond_result *cond_value); static bool resolve_nested_join (TABLE_LIST *table); static COND *remove_eq_conds(THD *thd, COND *cond, @@ -228,14 +229,11 @@ int handle_select(THD *thd, LEX *lex, select_result *result) select_lex->options | thd->options, result, unit, select_lex); } - - /* Don't set res if it's -1 as we may want this later */ DBUG_PRINT("info",("res: %d report_error: %d", res, thd->net.report_error)); - if (thd->net.report_error || res<0) + if (thd->net.report_error || res < 0) { - if (res > 0) - result->send_error(0, NullS); + result->send_error(0, NullS); result->abort(); res= 1; // Error sent to client } @@ -556,17 +554,7 @@ JOIN::optimize() thd->restore_backup_item_arena(arena, &backup); } - /* - Build all multiple equality predicates and eliminate equality - predicates that can be inferred from these multiple equalities. - For each reference of a field included into a multiple equality - that occurs in a function set a pointer to the multiple equality - predicate. Substitute a constant instead of this field if the - multiple equality contains a constant. - */ - conds= build_equal_items(conds, NULL, join_list, &cond_equal); - - conds= optimize_cond(this, conds,&cond_value); + conds= optimize_cond(this, conds, join_list, &cond_value); if (thd->net.report_error) { error= 1; @@ -684,6 +672,7 @@ JOIN::optimize() { conds= substitute_for_best_equal_field(conds, cond_equal, map2table); conds->update_used_tables(); + DBUG_EXECUTE("where", print_where(conds, "after substitute_best_equal");); } /* Permorm the the optimization on fields evaluation mentioned above @@ -1723,11 +1712,10 @@ int Cursor::open(JOIN *join_arg) { join= join_arg; - THD *thd= join->thd; - /* First non-constant table */ JOIN_TAB *join_tab= join->join_tab + join->const_tables; + DBUG_ENTER("Cursor::open"); /* Send fields description to the client; server_status is sent @@ -1749,7 +1737,9 @@ Cursor::open(JOIN *join_arg) join->fetch_limit= join->unit->offset_limit_cnt; /* Disable JOIN CACHE as it is not working with cursors yet */ - for (JOIN_TAB *tab= join_tab; tab != join->join_tab + join->tables - 1; ++tab) + for (JOIN_TAB *tab= join_tab; + tab != join->join_tab + join->tables - 1; + tab++) { if (tab->next_select == sub_select_cache) tab->next_select= sub_select; @@ -1763,7 +1753,7 @@ Cursor::open(JOIN *join_arg) */ DBUG_ASSERT(join_tab->table->null_row == 0); - return join_tab->read_first_record(join_tab); + DBUG_RETURN(join_tab->read_first_record(join_tab)); } @@ -6028,7 +6018,7 @@ template class List_iterator<Item_func_match>; find_item_equal() cond_equal multiple equalities to search in field field to look for - inherited_fl :out set up to TRUE iff multiple equality is found + inherited_fl :out set up to TRUE if multiple equality is found on upper levels (not on current level of cond_equal) DESCRIPTION @@ -6446,12 +6436,14 @@ static COND *build_equal_items_for_cond(COND *cond, return cond; } + /* Build multiple equalities for a condition and all on expressions that inherit these multiple equalities SYNOPSIS build_equal_items() + thd Thread handler cond condition to build the multiple equalities for inherited path to all inherited multiple equality items join_list list of join tables to which the condition refers to @@ -6503,7 +6495,7 @@ static COND *build_equal_items_for_cond(COND *cond, pointer to the transformed condition containing multiple equalities */ -static COND *build_equal_items(COND *cond, +static COND *build_equal_items(THD *thd, COND *cond, COND_EQUAL *inherited, List<TABLE_LIST> *join_list, COND_EQUAL **cond_equal_ref) @@ -6540,12 +6532,13 @@ static COND *build_equal_items(COND *cond, { if (table->on_expr) { + Item *expr; List<TABLE_LIST> *join_list= table->nested_join ? &table->nested_join->join_list : NULL; - table->on_expr= build_equal_items(table->on_expr, - inherited, - join_list, - &table->cond_equal); + expr= build_equal_items(thd, table->on_expr, inherited, join_list, + &table->cond_equal); + if (expr != table->on_expr) + thd->change_item_tree(&table->on_expr, expr); } } } @@ -6553,6 +6546,7 @@ static COND *build_equal_items(COND *cond, return cond; } + /* Compare field items by table order in the execution plan @@ -6797,6 +6791,7 @@ static COND* substitute_for_best_equal_field(COND *cond, return cond; } + /* change field = field to field = const for each found field = const in the and_level @@ -7089,6 +7084,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top) */ if (table->on_expr) { + Item *expr; /* If an on expression E is attached to the table, check all null rejected predicates in this expression. @@ -7097,8 +7093,9 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top) the outer join is converted to an inner join and the corresponding on expression is added to E. */ - table->on_expr= simplify_joins(join, &nested_join->join_list, - table->on_expr, FALSE); + expr= simplify_joins(join, &nested_join->join_list, + table->on_expr, FALSE); + table->on_expr= expr; } nested_join->used_tables= (table_map) 0; nested_join->not_null_tables=(table_map) 0; @@ -7207,8 +7204,10 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top) DBUG_RETURN(conds); } + static COND * -optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value) +optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list, + Item::cond_result *cond_value) { THD *thd= join->thd; SELECT_LEX *select= thd->lex->current_select; @@ -7221,7 +7220,19 @@ optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value) } else { + /* + Build all multiple equality predicates and eliminate equality + predicates that can be inferred from these multiple equalities. + For each reference of a field included into a multiple equality + that occurs in a function set a pointer to the multiple equality + predicate. Substitute a constant instead of this field if the + multiple equality contains a constant. + */ DBUG_EXECUTE("where", print_where(conds, "original");); + conds= build_equal_items(join->thd, conds, NULL, join_list, + &join->cond_equal); + DBUG_EXECUTE("where",print_where(conds,"after equal_items");); + /* change field = field to field = const for each found field = const */ propagate_cond_constants(thd, (I_List<COND_CMP> *) 0, conds, conds); /* diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c359c0f5f54..d9626c760be 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1395,18 +1395,20 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, open_table(). TODO: create and open should be done atomic ! */ - tmp_disable_binlog(thd); - if (!mysql_create_table(thd, create_table->db, create_table->real_name, - create_info, *extra_fields, *keys, 0, - select_field_count)) { - if (!(table= open_table(thd, create_table, &thd->mem_root, (bool*) 0))) - quick_rm_table(create_info->db_type, create_table->db, - table_case_name(create_info, create_table->real_name)); + tmp_disable_binlog(thd); + if (!mysql_create_table(thd, create_table->db, create_table->real_name, + create_info, *extra_fields, *keys, 0, + select_field_count)) + { + if (!(table= open_table(thd, create_table, &thd->mem_root, (bool*) 0))) + quick_rm_table(create_info->db_type, create_table->db, + table_case_name(create_info, create_table->real_name)); + } + reenable_binlog(thd); + if (!table) // open failed + DBUG_RETURN(0); } - reenable_binlog(thd); - if (!table) // open failed - DBUG_RETURN(0); table->reginfo.lock_type=TL_WRITE; if (!((*lock)= mysql_lock_tables(thd, &table,1))) @@ -3033,13 +3035,14 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, create_info->data_file_name=create_info->index_file_name=0; /* We don't log the statement, it will be logged later. */ - tmp_disable_binlog(thd); - error= mysql_create_table(thd, new_db, tmp_name, - create_info,create_list,key_list,1,0); - reenable_binlog(thd); - if (error) - DBUG_RETURN(error); - + { + tmp_disable_binlog(thd); + error= mysql_create_table(thd, new_db, tmp_name, + create_info,create_list,key_list,1,0); + reenable_binlog(thd); + if (error) + DBUG_RETURN(error); + } if (table->tmp_table) { TABLE_LIST tbl; diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index add4078ce8e..17f3bc48678 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -16,9 +16,9 @@ static const char * const triggers_file_ext= ".TRG"; */ static File_option triggers_file_parameters[]= { - {{(char*)"triggers", 8}, offsetof(Table_triggers_list, definitions_list), + {{(char*)"triggers", 8}, offsetof(class Table_triggers_list, definitions_list), FILE_OPTIONS_STRLIST}, - {{NULL, 0}, 0, FILE_OPTIONS_STRING} + {{0, 0}, 0, FILE_OPTIONS_STRING} }; @@ -373,8 +373,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, while ((trg_create_str= it++)) { - mysql_init_query(thd, (uchar*)trg_create_str->str, - trg_create_str->length, true); + lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length); lex.trg_table= table; if (yyparse((void *)thd) || thd->is_fatal_error) { diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 4d64455ab53..5e91e730079 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -80,8 +80,7 @@ static bool check_fields(THD *thd, List<Item> &items) we make temporary copy of Item_field, to avoid influence of changing result_field on Item_ref which refer on this field */ - it.replace(new Item_field(thd, field)); - field->register_item_tree_changing(it.ref()); + thd->change_item_tree(it.ref(), new Item_field(thd, field)); } return FALSE; } @@ -650,7 +649,7 @@ int mysql_multi_update_prepare(THD *thd) // Only set timestamp column if this is not modified if (table->timestamp_field && table->timestamp_field->query_id == thd->query_id) - table->timestamp_on_update_now= 0; + table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; if (!tl->updatable || check_key_in_view(thd, tl)) readonly_tables|= table->map; @@ -689,6 +688,8 @@ int mysql_multi_update(THD *thd, multi_update *result; DBUG_ENTER("mysql_multi_update"); + /* QQ: This should be fixed soon to get lower granularity locks */ + select_lex->set_lock_for_tables(thd->lex->multi_lock_option); if ((res= open_and_lock_tables(thd, table_list))) DBUG_RETURN(res); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 4cdbfe9728b..f8994148ffc 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -28,7 +28,8 @@ const char *updatable_views_with_limit_names[]= { "NO", "YES", NullS }; TYPELIB updatable_views_with_limit_typelib= { array_elements(updatable_views_with_limit_names)-1, "", - updatable_views_with_limit_names + updatable_views_with_limit_names, + 0 }; @@ -347,7 +348,7 @@ static File_option view_parameters[]= FILE_OPTIONS_ULONGLONG}, {{(char*) "algorithm", 9}, offsetof(TABLE_LIST, algorithm), FILE_OPTIONS_ULONGLONG}, - {{"with_check_option", 17}, offsetof(TABLE_LIST, with_check), + {{(char*) "with_check_option", 17}, offsetof(TABLE_LIST, with_check), FILE_OPTIONS_ULONGLONG}, {{(char*) "revision", 8}, offsetof(TABLE_LIST, revision), FILE_OPTIONS_REV}, @@ -357,7 +358,7 @@ static File_option view_parameters[]= FILE_OPTIONS_ULONGLONG}, {{(char*) "source", 6}, offsetof(TABLE_LIST, source), FILE_OPTIONS_ESTRING}, - {{NULL, 0}, 0, + {{NullS, 0}, 0, FILE_OPTIONS_STRING} }; @@ -586,7 +587,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) now Lex placed in statement memory */ table->view= lex= thd->lex= (LEX*) new(&thd->mem_root) st_lex_local; - mysql_init_query(thd, (uchar*)table->query.str, table->query.length, TRUE); + lex_start(thd, (uchar*)table->query.str, table->query.length); lex->select_lex.select_number= ++thd->select_number; old_lex->derived_tables|= DERIVED_VIEW; { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index bdda1f6fa07..c4ec8c84091 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -425,6 +425,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token RETURN_SYM %token RETURNS_SYM %token UDF_SONAME_SYM +%token UDF_RETURNS_SYM %token FUNCTION_SYM %token UNCOMMITTED_SYM %token UNDEFINED_SYM @@ -5730,7 +5731,6 @@ opt_insert_update: yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; } - lex->duplicates= DUP_UPDATE; } KEY_SYM UPDATE_SYM update_list ; @@ -6859,6 +6859,7 @@ keyword: | EXPANSION_SYM {} | EXTENDED_SYM {} | FAST_SYM {} + | FOUND_SYM {} | DISABLE_SYM {} | ENABLE_SYM {} | FULL {} |