diff options
-rw-r--r-- | sql/sql_class.h | 9 | ||||
-rw-r--r-- | sql/sql_insert.cc | 7 | ||||
-rw-r--r-- | sql/sql_parse.cc | 21 | ||||
-rw-r--r-- | sql/sql_unions.cc | 145 |
4 files changed, 106 insertions, 76 deletions
diff --git a/sql/sql_class.h b/sql/sql_class.h index 5cec5341dc3..bb5071a2e1c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -481,12 +481,13 @@ class select_insert :public select_result { uint save_time_stamp; ulonglong last_insert_id; COPY_INFO info; + bool unions; - select_insert(TABLE *table_par,List<Item> *fields_par,enum_duplicates duplic) + select_insert(TABLE *table_par,List<Item> *fields_par,enum_duplicates duplic, bool u=false) :table(table_par),fields(fields_par), save_time_stamp(0),last_insert_id(0) { bzero((char*) &info,sizeof(info)); - info.handle_duplicates=duplic; + info.handle_duplicates=duplic; unions = u; } ~select_insert(); int prepare(List<Item> &list); @@ -511,8 +512,8 @@ public: HA_CREATE_INFO *create_info_par, List<create_field> &fields_par, List<Key> &keys_par, - List<Item> &select_fields,enum_duplicates duplic) - :select_insert (NULL, &select_fields, duplic), db(db_name), + List<Item> &select_fields,enum_duplicates duplic, bool u=false) + :select_insert (NULL, &select_fields, duplic, u), db(db_name), name(table_name), extra_fields(&fields_par),keys(&keys_par), create_info(create_info_par), lock(0) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index ea60716dcf2..195bd559145 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1319,7 +1319,8 @@ bool select_insert::send_eof() thd->cuted_fields); if (last_insert_id) thd->insert_id(last_insert_id); // For update log - ::send_ok(&thd->net,info.copied,last_insert_id,buff); + if (!unions) + ::send_ok(&thd->net,info.copied,last_insert_id,buff); mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { @@ -1401,7 +1402,9 @@ bool select_create::send_eof() mysql_unlock_tables(thd, lock); if (!table->tmp_table) hash_delete(&open_cache,(byte*) table); - lock=0; table=0; + lock=0; + if (!unions) + table=0; VOID(pthread_mutex_unlock(&LOCK_open)); } return tmp; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 981e64e5de5..ea8e5980852 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1754,7 +1754,15 @@ mysql_execute_command(void) break; } if (!(res=open_and_lock_tables(thd,(TABLE_LIST *)total->first))) + { + /* Fix tables--to-be-unioned-from list to point at opened tables */ + for (SELECT_LEX *sl=&lex->select_lex;sl;sl=sl->next) + { + for (TABLE_LIST *cursor=(TABLE_LIST *)sl->table_list.first;cursor;cursor=cursor->next) + cursor->table= ((TABLE_LIST*) cursor->table)->table; + } res=mysql_union(thd,lex, select_lex->select_number+1); + } close_thread_tables(thd); break; } @@ -2894,11 +2902,12 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, static int link_in_large_list_and_check_acl(THD *thd,LEX *lex,SQL_LIST *tables) { SELECT_LEX *sl; const char *current_db=thd->db ? thd->db : ""; + TABLE_LIST *ptr; for (sl=&lex->select_lex;sl;sl=sl->next) { if ((lex->sql_command == SQLCOM_UNION_SELECT) && (sl->order_list.first != (byte *)NULL) && (sl->next != (st_select_lex *)NULL)) { - net_printf(&thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); // correct error message will come here; only last SELECt can have ORDER BY + net_printf(&thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); // correct error message will come here; only last SELECT can have ORDER BY return -1; } if (sl->table_list.first == (byte *)NULL) continue; @@ -2919,7 +2928,15 @@ static int link_in_large_list_and_check_acl(THD *thd,LEX *lex,SQL_LIST *tables) aux->lock_type= lex->lock_option; if (!tables->next) tables->next= (byte**) &tables->first; - link_in_list(tables,(byte*)aux,(byte**) &aux->next); + if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))) + return 1; + ptr->db= aux->db; ptr->real_name=aux->real_name; + ptr->name=aux->name; ptr->lock_type=aux->lock_type; + ptr->updating=aux->updating; + ptr->use_index=aux->use_index; + ptr->ignore_index=aux->use_index; + aux->table=(TABLE *)ptr; + link_in_list(tables,(byte*)ptr,(byte**) &ptr->next); } } } diff --git a/sql/sql_unions.cc b/sql/sql_unions.cc index 1a00f08c434..cd0b41ac3ca 100644 --- a/sql/sql_unions.cc +++ b/sql/sql_unions.cc @@ -29,7 +29,8 @@ int mysql_union(THD *thd,LEX *lex,uint no_of_selects) { SELECT_LEX *sl, *for_order=&lex->select_lex; uint no=0; int res=0; - List<Item> fields; TABLE *table=(TABLE *)NULL; TABLE_LIST *resulting=(TABLE_LIST *)NULL; + select_create *create_result; + List<Item> fields; TABLE *table=(TABLE *)NULL; TABLE_LIST *resulting=(TABLE_LIST *)NULL; for (;for_order->next;for_order=for_order->next); ORDER *some_order = (ORDER *)for_order->order_list.first; for (sl=&lex->select_lex;sl;sl=sl->next, no++) @@ -37,102 +38,110 @@ int mysql_union(THD *thd,LEX *lex,uint no_of_selects) TABLE_LIST *tables=(TABLE_LIST*) sl->table_list.first; if (!no) // First we do CREATE from SELECT { - select_create *result; lex->create_info.options=HA_LEX_CREATE_TMP_TABLE; - if ((result=new select_create(tables->db ? tables->db : thd->db, - NULL, &lex->create_info, + lex->create_info.db_type=DB_TYPE_MYISAM; + lex->create_info.row_type = ROW_TYPE_DEFAULT; + lex->create_info.avg_row_length = 0; + lex->create_info.max_rows=INT_MAX; lex->create_info.min_rows=0; + lex->create_info.comment=lex->create_info.password=NullS; + lex->create_info.data_file_name=lex->create_info.index_file_name=NullS; + lex->create_info.raid_type=lex->create_info.raid_chunks=0; + lex->create_info.raid_chunksize=0; + lex->create_info.if_not_exists=false; + lex->create_info.used_fields=0; + + if ((create_result=new select_create(tables->db ? tables->db : thd->db, + "ZVEK", &lex->create_info, lex->create_list, lex->key_list, - sl->item_list,DUP_IGNORE))) + sl->item_list,DUP_IGNORE,true))) { - res=mysql_select(thd,tables,sl->item_list, - sl->where, - sl->ftfunc_list, - (ORDER*) NULL, - (ORDER*) sl->group_list.first, - sl->having, - (ORDER*) some_order, - sl->options | thd->options, - result); - if (res) - { - result->abort(); - delete result; - return res; - } - table=result->table; - List_iterator<Item> it(*(result->fields)); - Item *item; - while ((item= it++)) - fields.push_back(item); - delete result; - if (!reopen_table(table)) return 1; - if (!(resulting = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))) - return 1; - resulting->db=tables->db ? tables->db : thd->db; - resulting->real_name=table->real_name; - resulting->name=table->table_name; - resulting->table=table; + res=mysql_select(thd,tables,sl->item_list, + sl->where, + sl->ftfunc_list, + (ORDER*) NULL, + (ORDER*) sl->group_list.first, + sl->having, + (ORDER*) some_order, + sl->options | thd->options, + create_result); + if (res) + { + create_result->abort(); + delete create_result; + return res; + } + table=create_result->table; + List_iterator<Item> it(*(create_result->fields)); + Item *item; + while ((item= it++)) + fields.push_back(item); + if (!(resulting = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))) + return 1; + resulting->db=tables->db ? tables->db : thd->db; + resulting->real_name=table->real_name; + resulting->name=table->table_name; + resulting->table=table; } else - return -1; + return -1; } else // Then we do INSERT from SELECT { select_result *result; - if ((result=new select_insert(table, &fields, DUP_IGNORE))) + if ((result=new select_insert(table, &fields, DUP_IGNORE, true))) { - res=mysql_select(thd,tables,sl->item_list, - sl->where, + res=mysql_select(thd,tables,sl->item_list, + sl->where, sl->ftfunc_list, - (ORDER*) some_order, - (ORDER*) sl->group_list.first, - sl->having, - (ORDER*) NULL, - sl->options | thd->options, - result); - delete result; - if (res) return 1; + (ORDER*) some_order, + (ORDER*) sl->group_list.first, + sl->having, + (ORDER*) NULL, + sl->options | thd->options, + result); + delete result; + if (res) + { + delete create_result; + return 1; + } } else - return -1; + { + delete create_result; + return -1; + } } } select_result *result; List<Item> item_list; List<Item_func_match> ftfunc_list; ftfunc_list.empty(); - if (item_list.push_back(new Item_field(NULL,NULL,"*"))) - return -1; + void(item_list.push_back(new Item_field(NULL,NULL,"*"))); if (lex->exchange) { if (lex->exchange->dumpfile) - { - if (!(result=new select_dump(lex->exchange))) - return -1; - } + result=new select_dump(lex->exchange); else - { - if (!(result=new select_export(lex->exchange))) - return -1; - } + result=new select_export(lex->exchange); } - else if (!(result=new select_send())) - return -1; - else + else result=new select_send(); + if (result) { res=mysql_select(thd,resulting,item_list, - NULL, - ftfunc_list, - (ORDER*) NULL, - (ORDER*) NULL, - NULL, - (ORDER*) NULL, - thd->options, - result); + NULL, + ftfunc_list, + (ORDER*) NULL, + (ORDER*) NULL, + NULL, + (ORDER*) NULL, + thd->options, + result); if (res) result->abort(); + delete result; } - delete result; + delete create_result; return res; } |