summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/sql_class.h9
-rw-r--r--sql/sql_insert.cc7
-rw-r--r--sql/sql_parse.cc21
-rw-r--r--sql/sql_unions.cc145
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;
}