diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 32 | ||||
-rw-r--r-- | sql/field.h | 9 | ||||
-rw-r--r-- | sql/item_func.cc | 4 | ||||
-rw-r--r-- | sql/mysql_priv.h | 12 | ||||
-rw-r--r-- | sql/protocol.cc | 9 | ||||
-rw-r--r-- | sql/repl_failsafe.cc | 2 | ||||
-rw-r--r-- | sql/sql_acl.cc | 16 | ||||
-rw-r--r-- | sql/sql_base.cc | 104 | ||||
-rw-r--r-- | sql/sql_delete.cc | 1 | ||||
-rw-r--r-- | sql/sql_derived.cc | 252 | ||||
-rw-r--r-- | sql/sql_handler.cc | 3 | ||||
-rw-r--r-- | sql/sql_insert.cc | 4 | ||||
-rw-r--r-- | sql/sql_lex.cc | 117 | ||||
-rw-r--r-- | sql/sql_lex.h | 13 | ||||
-rw-r--r-- | sql/sql_olap.cc | 12 | ||||
-rw-r--r-- | sql/sql_parse.cc | 74 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 3 | ||||
-rw-r--r-- | sql/sql_select.cc | 85 | ||||
-rw-r--r-- | sql/sql_select.h | 3 | ||||
-rw-r--r-- | sql/sql_string.cc | 1 | ||||
-rw-r--r-- | sql/sql_udf.cc | 2 | ||||
-rw-r--r-- | sql/sql_union.cc | 6 | ||||
-rw-r--r-- | sql/sql_update.cc | 2 |
23 files changed, 437 insertions, 329 deletions
diff --git a/sql/field.cc b/sql/field.cc index cce7446dcff..d26534b5ac7 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4485,19 +4485,9 @@ void Field_blob::store_length(uint32 number) { switch (packlength) { case 1: - if (number > 255) - { - number=255; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - } ptr[0]= (uchar) number; break; case 2: - if (number > (uint16) ~0) - { - number= (uint16) ~0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - } #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { @@ -4508,11 +4498,6 @@ void Field_blob::store_length(uint32 number) shortstore(ptr,(unsigned short) number); break; case 3: - if (number > (uint32) (1L << 24)) - { - number= (uint32) (1L << 24)-1L; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - } int3store(ptr,number); break; case 4: @@ -4573,6 +4558,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) bool was_conversion; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); + uint copy_length; uint32 not_used; /* Convert character set if nesessary */ @@ -4583,12 +4569,22 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) from= tmpstr.ptr(); length= tmpstr.length(); } - Field_blob::store_length(length); - if (was_conversion || table->copy_blobs || length <= MAX_FIELD_WIDTH) + + copy_length= max_data_length(); + if (copy_length > length) + copy_length= length; + copy_length= field_charset->cset->wellformedlen(field_charset, + from,from+copy_length, + field_length); + if (copy_length < length) + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); + + Field_blob::store_length(copy_length); + if (was_conversion || table->copy_blobs || copy_length <= MAX_FIELD_WIDTH) { // Must make a copy if (from != value.ptr()) // For valgrind { - value.copy(from,length,charset()); + value.copy(from,copy_length,charset()); from=value.ptr(); } } diff --git a/sql/field.h b/sql/field.h index 9a12fd48e54..b62b7a7859e 100644 --- a/sql/field.h +++ b/sql/field.h @@ -949,6 +949,15 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return (uint32) (packlength+table->blob_ptr_size); } + uint32 max_data_length() const + { + switch (packlength) { + case 1: return 255; + case 2: return (uint32) 0xFFFFL; + case 3: return (uint32) 0xFFFFFF; + default: return (uint32) 0xFFFFFFFF; + } + } void reset(void) { bzero(ptr, packlength+sizeof(char*)); } void reset_fields() { bzero((char*) &value,sizeof(value)); } void store_length(uint32 number); diff --git a/sql/item_func.cc b/sql/item_func.cc index b1378784f92..34a61ba0353 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1552,7 +1552,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, if ((error=(uchar) init(&initid, &f_args, thd->net.last_error))) { my_printf_error(ER_CANT_INITIALIZE_UDF,ER(ER_CANT_INITIALIZE_UDF),MYF(0), - u_d->name,thd->net.last_error); + u_d->name.str, thd->net.last_error); free_udf(u_d); DBUG_RETURN(1); } @@ -1565,7 +1565,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, if (error) { my_printf_error(ER_CANT_INITIALIZE_UDF,ER(ER_CANT_INITIALIZE_UDF),MYF(0), - u_d->name, ER(ER_UNKNOWN_ERROR)); + u_d->name.str, ER(ER_UNKNOWN_ERROR)); DBUG_RETURN(1); } DBUG_RETURN(0); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 35740ff8bf1..73e30e72a3c 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -247,7 +247,9 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; // uncachable cause #define UNCACHEABLE_DEPENDENT 1 #define UNCACHEABLE_RAND 2 -#define UNCACHEABLE_SIDEEFFECT 4 +#define UNCACHEABLE_SIDEEFFECT 4 +// forcing to save JOIN for explain +#define UNCACHEABLE_EXPLAIN 8 #ifdef EXTRA_DEBUG /* @@ -481,14 +483,13 @@ int mysql_select(THD *thd, Item ***rref_pointer_array, SELECT_LEX *select_lex); void free_underlaid_joins(THD *thd, SELECT_LEX *select); void fix_tables_pointers(SELECT_LEX *select_lex); -void fix_tables_pointers(SELECT_LEX_UNIT *select_lex); int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result); int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type, select_result *result); int mysql_union(THD *thd, LEX *lex, select_result *result, SELECT_LEX_UNIT *unit); -int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); +int mysql_handle_derived(LEX *lex); Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item ***copy_func, Field **from_field, bool group,bool modify_item); @@ -674,9 +675,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); int setup_ftfuncs(SELECT_LEX* select); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); void wait_for_refresh(THD *thd); -int open_tables(THD *thd,TABLE_LIST *tables); +int open_tables(THD *thd, TABLE_LIST *tables, uint *counter); +int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables); int open_and_lock_tables(THD *thd,TABLE_LIST *tables); -int lock_tables(THD *thd,TABLE_LIST *tables); +int lock_tables(THD *thd, TABLE_LIST *tables, uint counter); TABLE *open_temporary_table(THD *thd, const char *path, const char *db, const char *table_name, bool link_in_list); bool rm_temporary_table(enum db_type base, char *path); diff --git a/sql/protocol.cc b/sql/protocol.cc index bef567ad346..40adc9e8961 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -313,6 +313,7 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) DBUG_VOID_RETURN; } +static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */ /* Send eof (= end of result set) to the client @@ -339,12 +340,11 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) void send_eof(THD *thd, bool no_flush) { - static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */ NET *net= &thd->net; DBUG_ENTER("send_eof"); if (net->vio != 0) { - if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41)) + if (thd->client_capabilities & CLIENT_PROTOCOL_41) { uchar buff[5]; uint tmp= min(thd->total_warn_count, 65535); @@ -384,9 +384,8 @@ send_eof(THD *thd, bool no_flush) bool send_old_password_request(THD *thd) { - static char buff[1]= { (char) 254 }; NET *net= &thd->net; - return my_net_write(net, buff, 1) || net_flush(net); + return my_net_write(net, eof_buff, 1) || net_flush(net); } #endif /* EMBEDDED_LIBRARY */ @@ -585,7 +584,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag) #endif } - send_eof(thd, 1); + my_net_write(&thd->net, eof_buff, 1); DBUG_RETURN(prepare_for_send(list)); err: diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 81ea9d9e2ac..d125c95e839 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -732,7 +732,7 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db, int error; if (table_rules_on) { - table.next= 0; + bzero((char*) &table, sizeof(table)); //just for safe table.db= (char*) db; table.real_name= (char*) table_name; table.updating= 1; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 9d3ab8621d7..c500f0cf1f7 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -173,7 +173,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ; tables[0].db=tables[1].db=tables[2].db=thd->db; - if (open_tables(thd,tables)) + uint counter; + if (open_tables(thd, tables, &counter)) { sql_print_error("Fatal error: Can't open privilege tables: %s", thd->net.last_error); @@ -2247,7 +2248,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, } #endif - if (open_and_lock_tables(thd,tables)) + if (simple_open_n_lock_tables(thd,tables)) { // Should never happen close_thread_tables(thd); /* purecov: deadcode */ DBUG_RETURN(-1); /* purecov: deadcode */ @@ -2395,7 +2396,7 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, } /* open the mysql.user and mysql.db tables */ - + bzero((char*) &tables,sizeof(tables)); tables[0].alias=tables[0].real_name=(char*) "user"; tables[1].alias=tables[1].real_name=(char*) "db"; tables[0].next=tables+1; @@ -2421,7 +2422,7 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, } #endif - if (open_and_lock_tables(thd,tables)) + if (simple_open_n_lock_tables(thd,tables)) { // This should never happen close_thread_tables(thd); /* purecov: deadcode */ DBUG_RETURN(-1); /* purecov: deadcode */ @@ -2517,14 +2518,15 @@ my_bool grant_init(THD *org_thd) thd->store_globals(); thd->db= my_strdup("mysql",MYF(0)); thd->db_length=5; // Safety - bzero((char*) &tables,sizeof(tables)); + bzero((char*) &tables, sizeof(tables)); tables[0].alias=tables[0].real_name= (char*) "tables_priv"; tables[1].alias=tables[1].real_name= (char*) "columns_priv"; tables[0].next=tables+1; tables[0].lock_type=tables[1].lock_type=TL_READ; tables[0].db=tables[1].db=thd->db; - if (open_tables(thd,tables)) + uint counter; + if (open_tables(thd, tables, &counter)) goto end; TABLE *ptr[2]; // Lock tables for quick update @@ -3376,7 +3378,7 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables) } #endif - if (open_and_lock_tables(thd, tables)) + if (simple_open_n_lock_tables(thd, tables)) { // This should never happen close_thread_tables(thd); DBUG_RETURN(-1); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 2a4f73a986c..0ededa80ad6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1305,9 +1305,9 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, goto err; // Can't repair the table TABLE_LIST table_list; + bzero((char*) &table_list, sizeof(table_list)); // just for safe table_list.db=(char*) db; table_list.real_name=(char*) name; - table_list.next=0; safe_mutex_assert_owner(&LOCK_open); if ((error=lock_table_name(thd,&table_list))) @@ -1356,27 +1356,45 @@ err: DBUG_RETURN(1); } -/***************************************************************************** -** open all tables in list -*****************************************************************************/ +/* + Open all tables in list + + SYNOPSIS + open_tables() + thd - thread handler + start - list of tables + counter - number of opened tables will be return using this parameter -int open_tables(THD *thd,TABLE_LIST *start) + RETURN + 0 - OK + -1 - error +*/ + +int open_tables(THD *thd, TABLE_LIST *start, uint *counter) { TABLE_LIST *tables; bool refresh; int result=0; DBUG_ENTER("open_tables"); + *counter= 0; thd->current_tablenr= 0; restart: thd->proc_info="Opening tables"; for (tables=start ; tables ; tables=tables->next) { + /* + Ignore placeholders for derived tables. After derived tables + processing, link to created temporary table will be put here. + */ + if (tables->derived) + continue; + (*counter)++; if (!tables->table && - !(tables->table=open_table(thd, - tables->db, - tables->real_name, - tables->alias, &refresh))) + !(tables->table= open_table(thd, + tables->db, + tables->real_name, + tables->alias, &refresh))) { if (refresh) // Refresh in progress { @@ -1522,15 +1540,57 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) /* - Open all tables in list and locks them for read. - The lock will automaticly be freed by close_thread_tables() + Open all tables in list and locks them for read without derived + tables processing. + + SYNOPSIS + simple_open_n_lock_tables() + thd - thread handler + tables - list of tables for open&locking + + RETURN + 0 - ok + -1 - error + + NOTE + The lock will automaticly be freed by close_thread_tables() */ -int open_and_lock_tables(THD *thd,TABLE_LIST *tables) +int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables) { - if (open_tables(thd,tables) || lock_tables(thd,tables)) - return -1; /* purecov: inspected */ - return 0; + DBUG_ENTER("simple_open_n_lock_tables"); + uint counter; + if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter)) + DBUG_RETURN(-1); /* purecov: inspected */ + DBUG_RETURN(0); +} + + +/* + Open all tables in list, locks them and process derived tables + tables processing. + + SYNOPSIS + open_and_lock_tables() + thd - thread handler + tables - list of tables for open&locking + + RETURN + 0 - ok + -1 - error + + NOTE + The lock will automaticly be freed by close_thread_tables() +*/ + +int open_and_lock_tables(THD *thd, TABLE_LIST *tables) +{ + DBUG_ENTER("open_and_lock_tables"); + uint counter; + if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter)) + DBUG_RETURN(-1); /* purecov: inspected */ + fix_tables_pointers(thd->lex->all_selects_list); + DBUG_RETURN(mysql_handle_derived(thd->lex)); } @@ -1541,6 +1601,7 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables) lock_tables() thd Thread handler tables Tables to lock + count umber of opened tables NOTES You can't call lock_tables twice, as this would break the dead-lock-free @@ -1552,7 +1613,7 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables) -1 Error */ -int lock_tables(THD *thd,TABLE_LIST *tables) +int lock_tables(THD *thd, TABLE_LIST *tables, uint count) { TABLE_LIST *table; if (!tables) @@ -1561,14 +1622,14 @@ int lock_tables(THD *thd,TABLE_LIST *tables) if (!thd->locked_tables) { DBUG_ASSERT(thd->lock == 0); // You must lock everything at once - uint count=0; - for (table = tables ; table ; table=table->next) - count++; TABLE **start,**ptr; if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*)*count))) return -1; for (table = tables ; table ; table=table->next) - *(ptr++)= table->table; + { + if (!table->derived) + *(ptr++)= table->table; + } if (!(thd->lock=mysql_lock_tables(thd,start,count))) return -1; /* purecov: inspected */ } @@ -1576,7 +1637,8 @@ int lock_tables(THD *thd,TABLE_LIST *tables) { for (table = tables ; table ; table=table->next) { - if (check_lock_and_start_stmt(thd, table->table, table->lock_type)) + if (!table->derived && + check_lock_and_start_stmt(thd, table->table, table->lock_type)) { ha_rollback_stmt(thd); return -1; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index ed9136a6d5b..46dd4d7996e 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -43,7 +43,6 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order, if ((open_and_lock_tables(thd, table_list))) DBUG_RETURN(-1); - fix_tables_pointers(thd->lex->all_selects_list); table= table_list->table; table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); thd->proc_info="init"; diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 374e56ecdd4..0e04316a2e7 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -25,6 +25,58 @@ #include "sql_select.h" #include "sql_acl.h" +static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, + TABLE_LIST *t); + +/* + Resolve derived tables in all queries + + SYNOPSIS + mysql_handle_derived() + lex LEX for this thread + + RETURN + 0 ok + -1 Error + 1 Error and error message given +*/ + +int +mysql_handle_derived(LEX *lex) +{ + if (lex->derived_tables) + { + for (SELECT_LEX *sl= lex->all_selects_list; + sl; + sl= sl->next_select_in_list()) + { + for (TABLE_LIST *cursor= sl->get_table_list(); + cursor; + cursor= cursor->next) + { + int res; + if (cursor->derived && (res=mysql_derived(lex->thd, lex, + cursor->derived, + cursor))) + { + return res; + } + } + if (lex->describe) + { + /* + Force join->join_tmp creation, because we will use this JOIN + twice for EXPLAIN and we have to have unchanged join for EXPLAINing + */ + sl->uncacheable|= UNCACHEABLE_EXPLAIN; + sl->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN; + } + } + } + return 0; +} + + /* Resolve derived tables in all queries @@ -49,9 +101,6 @@ Derived tables is stored in thd->derived_tables and freed in close_thread_tables() - TODO - Move creation of derived tables in open_and_lock_tables() - RETURN 0 ok 1 Error @@ -59,8 +108,8 @@ */ -int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, - TABLE_LIST *org_table_list) +static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, + TABLE_LIST *org_table_list) { SELECT_LEX *first_select= unit->first_select(); TABLE *table; @@ -72,145 +121,91 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, bool is_subsel= first_select->first_inner_unit() ? 1: 0; SELECT_LEX *save_current_select= lex->current_select; DBUG_ENTER("mysql_derived"); - - /* - In create_total_list, derived tables have to be treated in case of - EXPLAIN, This is because unit/node is not deleted in that - case. Current code in this function has to be improved to - recognize better when this function is called from derived tables - and when from other functions. - */ - if ((is_union || is_subsel) && unit->create_total_list(thd, lex, &tables, 1)) - DBUG_RETURN(-1); + if (!(derived_result= new select_union(0))) + DBUG_RETURN(1); // out of memory + + // st_select_lex_unit::prepare correctly work for single select + if ((res= unit->prepare(thd, derived_result, 0))) + goto exit; + + + derived_result->tmp_table_param.init(); + derived_result->tmp_table_param.field_count= unit->types.elements; /* - We have to do access checks here as this code is executed before any - sql command is started to execute. + Temp table is created so that it hounours if UNION without ALL is to be + processed */ -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (tables) - res= check_table_access(thd,SELECT_ACL, tables,0); - else - res= check_access(thd, SELECT_ACL, any_db,0,0,0); - if (res) - DBUG_RETURN(1); -#endif - - if (!(res=open_and_lock_tables(thd,tables))) + if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param, + unit->types, (ORDER*) 0, + is_union && !unit->union_option, 1, + (first_select->options | thd->options | + TMP_TABLE_ALL_COLUMNS), + HA_POS_ERROR, + org_table_list->alias))) { - if (is_union || is_subsel) - { - /* - The following code is a re-do of fix_tables_pointers() found - in sql_select.cc for UNION's within derived tables. The only - difference is in navigation, as in derived tables we care for - this level only. - - */ - fix_tables_pointers(unit); - } + res= -1; + goto exit; + } + derived_result->set_table(table); - if (!(derived_result= new select_union(0))) - DBUG_RETURN(1); // out of memory - // st_select_lex_unit::prepare correctly work for single select - if ((res= unit->prepare(thd, derived_result, 0))) - goto exit; + if (is_union) + res= mysql_union(thd, lex, derived_result, unit); + else + { + unit->offset_limit_cnt= first_select->offset_limit; + unit->select_limit_cnt= first_select->select_limit+ + first_select->offset_limit; + if (unit->select_limit_cnt < first_select->select_limit) + unit->select_limit_cnt= HA_POS_ERROR; + if (unit->select_limit_cnt == HA_POS_ERROR) + first_select->options&= ~OPTION_FOUND_ROWS; + + lex->current_select= first_select; + res= mysql_select(thd, &first_select->ref_pointer_array, + (TABLE_LIST*) first_select->table_list.first, + first_select->with_wild, + first_select->item_list, first_select->where, + (first_select->order_list.elements+ + first_select->group_list.elements), + (ORDER *) first_select->order_list.first, + (ORDER *) first_select->group_list.first, + first_select->having, (ORDER*) NULL, + (first_select->options | thd->options | + SELECT_NO_UNLOCK), + derived_result, unit, first_select); + } - /* - This is done in order to redo all field optimisations when any of the - involved tables is used in the outer query - */ - if (tables) - { - for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next) - cursor->table->clear_query_id= 1; - } - - derived_result->tmp_table_param.init(); - derived_result->tmp_table_param.field_count= unit->types.elements; + if (!res) + { /* - Temp table is created so that it hounours if UNION without ALL is to be - processed + Here we entirely fix both TABLE_LIST and list of SELECT's as + there were no derived tables */ - if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param, - unit->types, (ORDER*) 0, - is_union && !unit->union_option, 1, - (first_select->options | thd->options | - TMP_TABLE_ALL_COLUMNS), - HA_POS_ERROR, - org_table_list->alias))) - { - res= -1; - goto exit; - } - derived_result->set_table(table); - - if (is_union) - res= mysql_union(thd, lex, derived_result, unit); + if (derived_result->flush()) + res= 1; else { - unit->offset_limit_cnt= first_select->offset_limit; - unit->select_limit_cnt= first_select->select_limit+ - first_select->offset_limit; - if (unit->select_limit_cnt < first_select->select_limit) - unit->select_limit_cnt= HA_POS_ERROR; - if (unit->select_limit_cnt == HA_POS_ERROR) - first_select->options&= ~OPTION_FOUND_ROWS; - - lex->current_select= first_select; - res= mysql_select(thd, &first_select->ref_pointer_array, - (TABLE_LIST*) first_select->table_list.first, - first_select->with_wild, - first_select->item_list, first_select->where, - (first_select->order_list.elements+ - first_select->group_list.elements), - (ORDER *) first_select->order_list.first, - (ORDER *) first_select->group_list.first, - first_select->having, (ORDER*) NULL, - (first_select->options | thd->options | - SELECT_NO_UNLOCK), - derived_result, unit, first_select); - } - - if (!res) - { - /* - Here we entirely fix both TABLE_LIST and list of SELECT's as - there were no derived tables - */ - if (derived_result->flush()) - res= 1; - else + org_table_list->real_name= table->real_name; + org_table_list->table= table; + if (org_table_list->table_list) { - org_table_list->real_name=table->real_name; - org_table_list->table=table; - table->derived_select_number= first_select->select_number; - table->tmp_table= TMP_TABLE; + org_table_list->table_list->real_name= table->real_name; + org_table_list->table_list->table= table; + } + table->derived_select_number= first_select->select_number; + table->tmp_table= TMP_TABLE; #ifndef NO_EMBEDDED_ACCESS_CHECKS - org_table_list->grant.privilege= SELECT_ACL; + table->grant.privilege= SELECT_ACL; #endif - if (lex->describe) - { - // to fix a problem in EXPLAIN - if (tables) - { - for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next) - if (cursor->table_list) - cursor->table_list->table=cursor->table; - } - } - else - { - unit->exclude_tree(); - unit->cleanup(); - } - org_table_list->db= (char *)""; - // Force read of table stats in the optimizer - table->file->info(HA_STATUS_VARIABLE); - } + org_table_list->db= (char *)""; + // Force read of table stats in the optimizer + table->file->info(HA_STATUS_VARIABLE); } + if (!lex->describe) + unit->cleanup(); if (res) free_tmp_table(thd, table); else @@ -223,7 +218,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, exit: delete derived_result; lex->current_select= save_current_select; - close_thread_tables(thd, 0, 1); } DBUG_RETURN(res); } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 405cfdb5bdc..897aa37ba11 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -48,7 +48,8 @@ static TABLE **find_table_ptr_by_name(THD *thd,const char *db, int mysql_ha_open(THD *thd, TABLE_LIST *tables) { HANDLER_TABLES_HACK(thd); - int err=open_tables(thd,tables); + uint counter; + int err=open_tables(thd, tables, &counter); HANDLER_TABLES_HACK(thd); if (err) return -1; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 74de1772555..58c3d143a4f 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -188,7 +188,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, res= open_and_lock_tables(thd, table_list); if (res) DBUG_RETURN(-1); - fix_tables_pointers(thd->lex->all_selects_list); table= table_list->table; thd->proc_info="init"; @@ -647,7 +646,8 @@ public: thd.command=COM_DELAYED_INSERT; thd.lex->current_select= 0; /* for my_message_sql */ - bzero((char*) &thd.net,sizeof(thd.net)); // Safety + bzero((char*) &thd.net, sizeof(thd.net)); // Safety + bzero((char*) &table_list, sizeof(table_list)); // Safety thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT; thd.host_or_ip= ""; bzero((char*) &info,sizeof(info)); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 65c958093bd..2484ff0e30f 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -667,13 +667,24 @@ int yylex(void *arg, void *yythd) case MY_LEX_USER_VARIABLE_DELIMITER: { - char delim= c; // Used char + uint double_quotes= 0; + char quote_char= c; // Used char lex->tok_start=lex->ptr; // Skip first ` #ifdef USE_MB if (use_mb(cs)) { - while ((c=yyGet()) && c != delim && c != (uchar) NAMES_SEP_CHAR) + while ((c= yyGet())) { + if (c == quote_char) + { + if (yyPeek() != quote_char) + break; + c= yyGet(); + double_quotes++; + continue; + } + if (c == (uchar) NAMES_SEP_CHAR) + break; if (my_mbcharlen(cs, c) > 1) { int l; @@ -684,13 +695,10 @@ int yylex(void *arg, void *yythd) lex->ptr += l-1; } } - yylval->lex_str=get_token(lex,yyLength()); } else #endif { - uint double_quotes= 0; - char quote_char= c; while ((c=yyGet())) { if (c == quote_char) @@ -704,13 +712,13 @@ int yylex(void *arg, void *yythd) if (c == (uchar) NAMES_SEP_CHAR) break; } - if (double_quotes) - yylval->lex_str=get_quoted_token(lex,yyLength() - double_quotes, - quote_char); - else - yylval->lex_str=get_token(lex,yyLength()); } - if (c == delim) + if (double_quotes) + yylval->lex_str=get_quoted_token(lex,yyLength() - double_quotes, + quote_char); + else + yylval->lex_str=get_token(lex,yyLength()); + if (c == quote_char) yySkip(); // Skip end ` lex->next_state= MY_LEX_START; return(IDENT_QUOTED); @@ -988,6 +996,7 @@ void st_select_lex_unit::init_query() union_result= 0; table= 0; fake_select_lex= 0; + cleaned= 0; } void st_select_lex::init_query() @@ -1286,12 +1295,10 @@ bool st_select_lex::test_limit() !0 - error */ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex, - TABLE_LIST **result_arg, - bool check_derived) + TABLE_LIST **result_arg) { *result_arg= 0; - res= create_total_list_n_last_return(thd_arg, lex, &result_arg, - check_derived); + res= create_total_list_n_last_return(thd_arg, lex, &result_arg); return res; } @@ -1303,8 +1310,7 @@ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex, thd THD pointer lex pointer on LEX stricture result pointer on pointer on result list of tables pointer - check_derived force derived table chacking (used for creating - table list for derived query) + DESCRIPTION This is used for UNION & subselect to create a new table list of all used tables. @@ -1318,8 +1324,7 @@ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex, bool st_select_lex_unit:: create_total_list_n_last_return(THD *thd_arg, st_lex *lex, - TABLE_LIST ***result_arg, - bool check_derived) + TABLE_LIST ***result_arg) { TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first; TABLE_LIST **new_table_list= *result_arg, *aux; @@ -1345,15 +1350,12 @@ create_total_list_n_last_return(THD *thd_arg, return 1; } - if (sl->linkage == DERIVED_TABLE_TYPE && !check_derived) - goto end; - for (SELECT_LEX_UNIT *inner= sl->first_inner_unit(); inner; inner= inner->next_unit()) { if (inner->create_total_list_n_last_return(thd, lex, - &slave_list_last, 0)) + &slave_list_last)) return 1; } @@ -1400,63 +1402,75 @@ end: return 0; } + st_select_lex_unit* st_select_lex_unit::master_unit() { return this; } + st_select_lex* st_select_lex_unit::outer_select() { return (st_select_lex*) master; } + bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc) { return add_to_list(thd, order_list, item, asc); } + bool st_select_lex::add_item_to_list(THD *thd, Item *item) { return item_list.push_back(item); } + bool st_select_lex::add_group_to_list(THD *thd, Item *item, bool asc) { return add_to_list(thd, group_list, item, asc); } + bool st_select_lex::add_ftfunc_to_list(Item_func_match *func) { return !func || ftfunc_list->push_back(func); // end of memory? } + st_select_lex_unit* st_select_lex::master_unit() { return (st_select_lex_unit*) master; } + st_select_lex* st_select_lex::outer_select() { return (st_select_lex*) master->get_master(); } + bool st_select_lex::set_braces(bool value) { braces= value; return 0; } + bool st_select_lex::inc_in_sum_expr() { in_sum_expr++; return 0; } + uint st_select_lex::get_in_sum_expr() { return in_sum_expr; } + TABLE_LIST* st_select_lex::get_table_list() { return (TABLE_LIST*) table_list.first; @@ -1467,21 +1481,25 @@ List<Item>* st_select_lex::get_item_list() return &item_list; } + List<String>* st_select_lex::get_use_index() { return use_index_ptr; } + List<String>* st_select_lex::get_ignore_index() { return ignore_index_ptr; } + ulong st_select_lex::get_table_join_options() { return table_join_options; } + bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) { if (ref_pointer_array) @@ -1493,6 +1511,58 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) order_group_num)* 5)) == 0; } + +/* + Find db.table which will be updated in this unit + + SYNOPSIS + st_select_lex_unit::check_updateable() + db - data base name + table - real table name + + RETURN + 1 - found + 0 - OK (table did not found) +*/ +bool st_select_lex_unit::check_updateable(char *db, char *table) +{ + for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) + if (sl->check_updateable(db, table)) + return 1; + return 0; +} + + +/* + Find db.table which will be updated in this select and + underlayed ones (except derived tables) + + SYNOPSIS + st_select_lex::check_updateable() + db - data base name + table - real table name + + RETURN + 1 - found + 0 - OK (table did not found) +*/ +bool st_select_lex::check_updateable(char *db, char *table) +{ + if (find_real_table_in_list(get_table_list(), db, table)) + return 1; + + for (SELECT_LEX_UNIT *un= first_inner_unit(); + un; + un= un->next_unit()) + { + if (un->first_select()->linkage != DERIVED_TABLE_TYPE && + un->check_updateable(db, table)) + return 1; + } + return 0; +} + + void st_select_lex_unit::print(String *str) { for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) @@ -1535,6 +1605,7 @@ void st_select_lex::print_order(String *str, ORDER *order) } } + void st_select_lex::print_limit(THD *thd, String *str) { if (!thd) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 68385bc7bba..3f56be18c4a 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -232,6 +232,7 @@ public: UNCACHEABLE_DEPENDENT UNCACHEABLE_RAND UNCACHEABLE_SIDEEFFECT + UNCACHEABLE_EXPLAIN */ uint8 uncacheable; enum sub_select_type linkage; @@ -304,7 +305,8 @@ protected: ulong found_rows_for_union; bool prepared, // prepare phase already performed for UNION (unit) optimized, // optimize phase already performed for UNION (unit) - executed; // already executed + executed, // already executed + cleaned; public: // list of fields which points to temporary table for union @@ -336,8 +338,7 @@ public: uint union_option; void init_query(); - bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result, - bool check_current_derived); + bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result); st_select_lex_unit* master_unit(); st_select_lex* outer_select(); st_select_lex* first_select() { return (st_select_lex*) slave; } @@ -355,14 +356,15 @@ public: int exec(); int cleanup(); + bool check_updateable(char *db, char *table); void print(String *str); + friend void mysql_init_query(THD *thd); friend int subselect_union_engine::exec(); private: bool create_total_list_n_last_return(THD *thd, st_lex *lex, - TABLE_LIST ***result, - bool check_current_derived); + TABLE_LIST ***result); }; typedef class st_select_lex_unit SELECT_LEX_UNIT; @@ -497,6 +499,7 @@ public: init_select(); } bool setup_ref_array(THD *thd, uint order_group_num); + bool check_updateable(char *db, char *table); void print(THD *thd, String *str); static void print_order(String *str, ORDER *order); void print_limit(THD *thd, String *str); diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc index 1d16771c1a4..efc4cf0921d 100644 --- a/sql/sql_olap.cc +++ b/sql/sql_olap.cc @@ -143,18 +143,6 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex) int count=select_lex->group_list.elements; int sl_return=0; -// a fix for UNION's - for (TABLE_LIST *cursor= (TABLE_LIST *)select_lex->table_list.first; - cursor; - cursor=cursor->next) - { - if (cursor->do_redirect) - { - //Sinisa TODO: there are function for this purpose: fix_tables_pointers - cursor->table= cursor->table_list->table; - cursor->do_redirect= 0; - } - } lex->last_selects=select_lex; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9d742995976..42ea6039b6c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1789,34 +1789,9 @@ mysql_execute_command(THD *thd) #endif } #endif /* !HAVE_REPLICATION */ - /* - TODO: make derived tables processing 'inside' SELECT processing. - TODO: solve problem with depended derived tables in subselects - */ - if (lex->derived_tables) - { - for (SELECT_LEX *sl= lex->all_selects_list; - sl; - sl= sl->next_select_in_list()) - { - for (TABLE_LIST *cursor= sl->get_table_list(); - cursor; - cursor= cursor->next) - { - if (cursor->derived && (res=mysql_derived(thd, lex, - cursor->derived, - cursor))) - { - if (res < 0 || thd->net.report_error) - send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); - DBUG_VOID_RETURN; - } - } - } - } if (&lex->select_lex != lex->all_selects_list && lex->sql_command != SQLCOM_CREATE_TABLE && - lex->unit.create_total_list(thd, lex, &tables, 0)) + lex->unit.create_total_list(thd, lex, &tables)) DBUG_VOID_RETURN; /* @@ -1875,7 +1850,6 @@ mysql_execute_command(THD *thd) } else thd->send_explain_fields(result); - fix_tables_pointers(lex->all_selects_list); res= mysql_explain_union(thd, &thd->lex->unit, result); MYSQL_LOCK *save_lock= thd->lock; thd->lock= (MYSQL_LOCK *)0; @@ -1914,7 +1888,6 @@ mysql_execute_command(THD *thd) (res= open_and_lock_tables(thd,tables)))) break; - fix_tables_pointers(lex->all_selects_list); res= mysql_do(thd, *lex->insert_list); if (thd->net.report_error) res= -1; @@ -2123,7 +2096,7 @@ mysql_execute_command(THD *thd) lex->select_lex.table_list.first= (byte*) (tables); create_table->next= 0; if (&lex->select_lex != lex->all_selects_list && - lex->unit.create_total_list(thd, lex, &tables, 0)) + lex->unit.create_total_list(thd, lex, &tables)) DBUG_VOID_RETURN; ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? @@ -2338,6 +2311,8 @@ mysql_execute_command(THD *thd) if (grant_option) { TABLE_LIST old_list,new_list; + bzero((char*) &old_list, sizeof(old_list)); + bzero((char*) &new_list, sizeof(new_list)); // Safety old_list=table[0]; new_list=table->next[0]; old_list.next=new_list.next=0; @@ -2669,23 +2644,15 @@ mysql_execute_command(THD *thd) } if (!walk) { - if (lex->derived_tables) - { - // are we trying to delete derived table? - for (walk= (TABLE_LIST*) tables; walk; walk= walk->next) - { - if (!strcmp(auxi->real_name,walk->alias) && - walk->derived) - { - net_printf(thd, ER_NON_UPDATABLE_TABLE, - auxi->real_name, "DELETE"); - goto error; - } - } - } net_printf(thd, ER_NONUNIQ_TABLE, auxi->real_name); goto error; } + if (walk->derived) + { + net_printf(thd, ER_NON_UPDATABLE_TABLE, + auxi->real_name, "DELETE"); + goto error; + } walk->lock_type= auxi->lock_type; auxi->table_list= walk; // Remember corresponding table } @@ -2699,21 +2666,27 @@ mysql_execute_command(THD *thd) break; /* Fix tables-to-be-deleted-from list to point at opened tables */ for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next) - auxi->table= auxi->table_list->table; - if (&lex->select_lex != lex->all_selects_list) { - for (TABLE_LIST *t= select_lex->get_table_list(); - t; t= t->next) + auxi->table= auxi->table_list->table; + /* + Multi-delete can't be constructed over-union => we always have + single SELECT on top and have to check underlaying SELECTs of it + */ + for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit(); + un; + un= un->next_unit()) { - if (find_real_table_in_list(t->table_list->next, t->db, t->real_name)) + if (un->first_select()->linkage != DERIVED_TABLE_TYPE && + un->check_updateable(auxi->table_list->db, + auxi->table_list->real_name)) { - my_error(ER_UPDATE_TABLE_USED, MYF(0), t->real_name); + my_error(ER_UPDATE_TABLE_USED, MYF(0), auxi->table_list->real_name); res= -1; break; } } } - fix_tables_pointers(lex->all_selects_list); + if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables, table_count))) { @@ -2958,7 +2931,6 @@ mysql_execute_command(THD *thd) if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) || (res= open_and_lock_tables(thd,tables)))) break; - fix_tables_pointers(lex->all_selects_list); if (!(res= sql_set_variables(thd, &lex->var_list))) send_ok(thd); if (thd->net.report_error) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 9b8ef37757c..2cf0000d973 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -733,7 +733,7 @@ static bool mysql_test_select_fields(Prepared_statement *stmt, DBUG_RETURN(1); #endif if ((&lex->select_lex != lex->all_selects_list && - lex->unit.create_total_list(thd, lex, &tables, 0))) + lex->unit.create_total_list(thd, lex, &tables))) DBUG_RETURN(1); if (open_and_lock_tables(thd, tables)) @@ -746,7 +746,6 @@ static bool mysql_test_select_fields(Prepared_statement *stmt, } else { - fix_tables_pointers(lex->all_selects_list); if (!result && !(result= new select_send())) { send_error(thd, ER_OUT_OF_RESOURCES); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 81051f70a4a..ea5050f2550 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -173,7 +173,6 @@ int handle_select(THD *thd, LEX *lex, select_result *result) register SELECT_LEX *select_lex = &lex->select_lex; DBUG_ENTER("handle_select"); - fix_tables_pointers(lex->all_selects_list); if (select_lex->next_select()) res=mysql_union(thd, lex, result, &lex->unit); else @@ -1511,12 +1510,7 @@ JOIN::cleanup() JOIN_TAB *tab, *end; for (tab= join_tab, end= tab+tables ; tab != end ; tab++) { - delete tab->select; - delete tab->quick; - tab->select=0; - tab->quick=0; - x_free(tab->cache.buff); - tab->cache.buff= 0; + tab->cleanup(); } } tmp_join->tmp_join= 0; @@ -1580,8 +1574,8 @@ mysql_select(THD *thd, Item ***rref_pointer_array, goto err; } } - free_join= 0; } + free_join= 0; join->select_options= select_options; } else @@ -3761,6 +3755,41 @@ bool error_if_full_join(JOIN *join) /* + cleanup JOIN_TAB + + SYNOPSIS + JOIN_TAB::cleanup() +*/ + +void JOIN_TAB::cleanup() +{ + delete select; + select= 0; + delete quick; + quick= 0; + x_free(cache.buff); + cache.buff= 0; + if (table) + { + if (table->key_read) + { + table->key_read= 0; + table->file->extra(HA_EXTRA_NO_KEYREAD); + } + /* Don't free index if we are using read_record */ + if (!read_record.table) + table->file->index_end(); + /* + We need to reset this for next select + (Tested in part_of_refkey) + */ + table->reginfo.join_tab= 0; + } + end_read_record(&read_record); +} + + +/* Free resources of given join SYNOPSIS @@ -3794,11 +3823,6 @@ JOIN::join_free(bool full) { if (tab->table) { - if (tab->table->key_read) - { - tab->table->key_read= 0; - tab->table->file->extra(HA_EXTRA_NO_KEYREAD); - } /* Don't free index if we are using read_record */ if (!tab->read_record.table) tab->table->file->index_end(); @@ -3809,29 +3833,7 @@ JOIN::join_free(bool full) { for (tab= join_tab, end= tab+tables; tab != end; tab++) { - delete tab->select; - delete tab->quick; - tab->select=0; - tab->quick=0; - x_free(tab->cache.buff); - tab->cache.buff= 0; - if (tab->table) - { - if (tab->table->key_read) - { - tab->table->key_read= 0; - tab->table->file->extra(HA_EXTRA_NO_KEYREAD); - } - /* Don't free index if we are using read_record */ - if (!tab->read_record.table) - tab->table->file->index_end(); - /* - We need to reset this for next select - (Tested in part_of_refkey) - */ - tab->table->reginfo.join_tab= 0; - } - end_read_record(&tab->read_record); + tab->cleanup(); } table= 0; } @@ -9149,6 +9151,9 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) sl; sl= sl->next_select()) { + // drop UNCACHEABLE_EXPLAIN, because it is for internal usage only + uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN); + res= mysql_explain_select(thd, sl, (((&thd->lex->select_lex)==sl)? ((thd->lex->all_selects_list != sl) ? @@ -9156,13 +9161,13 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) ((sl == first)? ((sl->linkage == DERIVED_TABLE_TYPE) ? "DERIVED": - ((sl->uncacheable & UNCACHEABLE_DEPENDENT) ? + ((uncacheable & UNCACHEABLE_DEPENDENT) ? "DEPENDENT SUBQUERY": - (sl->uncacheable?"UNCACHEABLE SUBQUERY": + (uncacheable?"UNCACHEABLE SUBQUERY": "SUBQUERY"))): - ((sl->uncacheable & UNCACHEABLE_DEPENDENT) ? + ((uncacheable & UNCACHEABLE_DEPENDENT) ? "DEPENDENT UNION": - sl->uncacheable?"UNCACHEABLE UNION": + uncacheable?"UNCACHEABLE UNION": "UNION"))), result); if (res) diff --git a/sql/sql_select.h b/sql/sql_select.h index ed650c450c0..36526bee066 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -108,6 +108,8 @@ typedef struct st_join_table { TABLE_REF ref; JOIN_CACHE cache; JOIN *join; + + void cleanup(); } JOIN_TAB; @@ -428,7 +430,6 @@ public: bool cp_buffer_from_ref(TABLE_REF *ref); bool error_if_full_join(JOIN *join); -void relink_tables(SELECT_LEX *select_lex); int report_error(TABLE *table, int error); int safe_index_read(JOIN_TAB *tab); COND *eliminate_not_funcs(COND *cond); diff --git a/sql/sql_string.cc b/sql/sql_string.cc index cbee67c0a4a..093b85b46b7 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -24,6 +24,7 @@ #include <my_sys.h> #include <m_string.h> #include <m_ctype.h> +#include <assert.h> #ifdef HAVE_FCONVERT #include <floatingpoint.h> #endif diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 337f2540a39..6e8aae54b23 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -149,7 +149,7 @@ void udf_init() tables.lock_type = TL_READ; tables.db=new_thd->db; - if (open_and_lock_tables(new_thd, &tables)) + if (simple_open_n_lock_tables(new_thd, &tables)) { DBUG_PRINT("error",("Can't open udf table")); sql_print_error("Can't open mysql/func table"); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 226086d0d24..75fd9be88bd 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -442,6 +442,12 @@ int st_select_lex_unit::cleanup() int error= 0; DBUG_ENTER("st_select_lex_unit::cleanup"); + if (cleaned) + { + DBUG_RETURN(0); + } + cleaned= 0; + if (union_result) { delete union_result; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 86593f5ea20..df7b2cf809f 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -79,7 +79,6 @@ int mysql_update(THD *thd, if ((open_and_lock_tables(thd, table_list))) DBUG_RETURN(-1); thd->proc_info="init"; - fix_tables_pointers(thd->lex->all_selects_list); table= table_list->table; table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); @@ -431,7 +430,6 @@ int mysql_multi_update(THD *thd, #endif if ((res=open_and_lock_tables(thd,table_list))) DBUG_RETURN(res); - fix_tables_pointers(thd->lex->all_selects_list); select_lex->select_limit= HA_POS_ERROR; |