Commit 02e0db5a authored by unknown's avatar unknown

Changes so that CREATE and INSERT work from UNION's


BitKeeper/etc/ignore:
  Added innobase/conftest.s1 innobase/conftest.subs sql/sql_select.cc.orig to the ignore list
parent ad5100da
...@@ -376,3 +376,6 @@ support-files/mysql.spec ...@@ -376,3 +376,6 @@ support-files/mysql.spec
tags tags
tmp/* tmp/*
vio/viotest-ssl vio/viotest-ssl
innobase/conftest.s1
innobase/conftest.subs
sql/sql_select.cc.orig
...@@ -309,7 +309,7 @@ int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds, ...@@ -309,7 +309,7 @@ int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
List<Item_func_match> &ftfuncs, List<Item_func_match> &ftfuncs,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param, ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
ulong select_type,select_result *result); ulong select_type,select_result *result);
int mysql_union(THD *thd,LEX *lex); int mysql_union(THD *thd,LEX *lex,select_result *create_insert=(select_result *)NULL);
Field *create_tmp_field(TABLE *table,Item *item, Item::Type type, Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
Item_result_field ***copy_func, Field **from_field, Item_result_field ***copy_func, Field **from_field,
bool group,bool modify_item); bool group,bool modify_item);
......
...@@ -56,7 +56,7 @@ enum enum_sql_command { ...@@ -56,7 +56,7 @@ enum enum_sql_command {
SQLCOM_SHOW_OPEN_TABLES, SQLCOM_LOAD_MASTER_DATA, SQLCOM_SHOW_OPEN_TABLES, SQLCOM_LOAD_MASTER_DATA,
SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ, SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_MULTI_DELETE, SQLCOM_UNION_SELECT, SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_MULTI_DELETE, SQLCOM_UNION_SELECT,
SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_NONE
}; };
enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT, enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT,
......
...@@ -48,7 +48,8 @@ static void remove_escape(char *name); ...@@ -48,7 +48,8 @@ static void remove_escape(char *name);
static void refresh_status(void); static void refresh_status(void);
static bool append_file_to_dir(char **filename_ptr, char *table_name); static bool append_file_to_dir(char **filename_ptr, char *table_name);
static int create_total_list_and_check_acl(THD *thd, LEX *lex, static int create_total_list_and_check_acl(THD *thd, LEX *lex,
TABLE_LIST **result); TABLE_LIST **result, bool skip_first = false);
static int handle_create_select(THD *thd, LEX *lex, select_result *c_i);
const char *any_db="*any*"; // Special symbol for check_access const char *any_db="*any*"; // Special symbol for check_access
...@@ -1068,7 +1069,7 @@ mysql_execute_command(void) ...@@ -1068,7 +1069,7 @@ mysql_execute_command(void)
int res=0; int res=0;
THD *thd=current_thd; THD *thd=current_thd;
LEX *lex= &thd->lex; LEX *lex= &thd->lex;
TABLE_LIST *tables=(TABLE_LIST*) lex->select->table_list.first; TABLE_LIST *tables=(TABLE_LIST*) lex->select_lex.table_list.first;
SELECT_LEX *select_lex = lex->select; SELECT_LEX *select_lex = lex->select;
DBUG_ENTER("mysql_execute_command"); DBUG_ENTER("mysql_execute_command");
...@@ -1322,32 +1323,15 @@ mysql_execute_command(void) ...@@ -1322,32 +1323,15 @@ mysql_execute_command(void)
thd->select_limit=select_lex->select_limit+select_lex->offset_limit; thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
if (thd->select_limit < select_lex->select_limit) if (thd->select_limit < select_lex->select_limit)
thd->select_limit= HA_POS_ERROR; // No limit thd->select_limit= HA_POS_ERROR; // No limit
if ((result=new select_create(tables->db ? tables->db : thd->db,
if (!(res=open_and_lock_tables(thd,tables->next)))
{
if ((result=new select_create(tables->db ? tables->db : thd->db,
tables->real_name, &lex->create_info, tables->real_name, &lex->create_info,
lex->create_list, lex->create_list,
lex->key_list, lex->key_list,
select_lex->item_list,lex->duplicates))) select_lex->item_list,lex->duplicates)))
{ res=handle_create_select(thd,lex,result);
res=mysql_select(thd,tables->next,select_lex->item_list, else
select_lex->where, res= -1;
select_lex->ftfunc_list, }
(ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first,
select_lex->having,
(ORDER*) lex->proc_list.first,
select_lex->options | thd->options,
result);
if (res)
result->abort();
delete result;
}
else
res= -1;
}
}
else // regular create else // regular create
{ {
res = mysql_create_table(thd,tables->db ? tables->db : thd->db, res = mysql_create_table(thd,tables->db ? tables->db : thd->db,
...@@ -1612,36 +1596,76 @@ mysql_execute_command(void) ...@@ -1612,36 +1596,76 @@ mysql_execute_command(void)
if (thd->select_limit < select_lex->select_limit) if (thd->select_limit < select_lex->select_limit)
thd->select_limit= HA_POS_ERROR; // No limit thd->select_limit= HA_POS_ERROR; // No limit
if (check_dup(thd,tables->db,tables->real_name,tables->next)) if (lex->select_lex.next)
{ {
net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name); TABLE_LIST *total;
DBUG_VOID_RETURN; if ((res = create_total_list_and_check_acl(thd,lex,&total)))
} goto error;
tables->lock_type=TL_WRITE; // update first table if (check_dup(thd,total->db,total->real_name,total->next))
{ {
TABLE_LIST *table; net_printf(&thd->net,ER_INSERT_TABLE_USED,total->real_name);
for (table = tables->next ; table ; table=table->next) DBUG_VOID_RETURN;
table->lock_type= lex->lock_option; }
} total->lock_type=TL_WRITE; // update first table
if (!(res=open_and_lock_tables(thd,tables))) {
{ TABLE_LIST *table;
if ((result=new select_insert(tables->table,&lex->field_list, for (table = total->next ; table ; table=table->next)
lex->sql_command == SQLCOM_REPLACE_SELECT ? table->lock_type= lex->lock_option;
DUP_REPLACE : DUP_IGNORE))) }
{ if (!(res=open_and_lock_tables(thd, total)))
res=mysql_select(thd,tables->next,select_lex->item_list, {
select_lex->where, if ((result=new select_insert(total->table,&lex->field_list,
select_lex->ftfunc_list, lex->sql_command == SQLCOM_REPLACE_SELECT ?
(ORDER*) select_lex->order_list.first, DUP_REPLACE : DUP_IGNORE)))
(ORDER*) select_lex->group_list.first, {
select_lex->having,
(ORDER*) lex->proc_list.first, for (SELECT_LEX *sl=&lex->select_lex; sl; sl=sl->next)
select_lex->options | thd->options, {
result); TABLE_LIST *help=(TABLE_LIST *)sl->table_list.first;
delete result; if (sl==&lex->select_lex) help=help->next;
} for (TABLE_LIST *cursor= help;
else cursor;
res= -1; cursor=cursor->next)
cursor->table= ((TABLE_LIST*) cursor->table)->table;
}
res=mysql_union(thd,lex,result);
}
close_thread_tables(thd);
}
}
else
{
if (check_dup(thd,tables->db,tables->real_name,tables->next))
{
net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN;
}
tables->lock_type=TL_WRITE; // update first table
{
TABLE_LIST *table;
for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option;
}
if (!(res=open_and_lock_tables(thd,tables)))
{
if ((result=new select_insert(tables->table,&lex->field_list,
lex->sql_command == SQLCOM_REPLACE_SELECT ?
DUP_REPLACE : DUP_IGNORE)))
{
res=mysql_select(thd,tables->next,select_lex->item_list,
select_lex->where,
select_lex->ftfunc_list,
(ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first,
select_lex->having,
(ORDER*) lex->proc_list.first,
select_lex->options | thd->options,
result);
delete result;
}
else
res= -1;
}
} }
#ifdef DELETE_ITEMS #ifdef DELETE_ITEMS
delete select_lex->having; delete select_lex->having;
...@@ -2434,6 +2458,7 @@ mysql_init_query(THD *thd) ...@@ -2434,6 +2458,7 @@ mysql_init_query(THD *thd)
thd->fatal_error=0; // Safety thd->fatal_error=0; // Safety
thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0; thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0;
thd->sent_row_count=thd->examined_row_count=0; thd->sent_row_count=thd->examined_row_count=0;
thd->lex.sql_command=SQLCOM_NONE;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -2910,14 +2935,14 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, ...@@ -2910,14 +2935,14 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
*/ */
static int create_total_list_and_check_acl(THD *thd, LEX *lex, static int create_total_list_and_check_acl(THD *thd, LEX *lex,
TABLE_LIST **result) TABLE_LIST **result, bool skip_first = false)
{ {
SELECT_LEX *sl; SELECT_LEX *sl;
TABLE_LIST **new_table_list= result, *aux; TABLE_LIST **new_table_list= result, *aux;
const char *current_db=thd->db ? thd->db : ""; // QQ; To be removed const char *current_db=thd->db ? thd->db : ""; // QQ; To be removed
*new_table_list=0; // end result list *new_table_list=0; // end result list
for (sl=&lex->select_lex; sl; sl=sl->next) for (sl= &lex->select_lex; sl; sl=sl->next)
{ {
if ((lex->sql_command == SQLCOM_UNION_SELECT) && if ((lex->sql_command == SQLCOM_UNION_SELECT) &&
sl->order_list.first && sl->next) sl->order_list.first && sl->next)
...@@ -2926,6 +2951,7 @@ static int create_total_list_and_check_acl(THD *thd, LEX *lex, ...@@ -2926,6 +2951,7 @@ static int create_total_list_and_check_acl(THD *thd, LEX *lex,
return -1; return -1;
} }
aux= (TABLE_LIST*) sl->table_list.first; aux= (TABLE_LIST*) sl->table_list.first;
if (skip_first && sl == &lex->select_lex) aux=aux->next;
if (aux) if (aux)
{ {
TABLE_LIST *next; TABLE_LIST *next;
...@@ -2961,6 +2987,51 @@ static int create_total_list_and_check_acl(THD *thd, LEX *lex, ...@@ -2961,6 +2987,51 @@ static int create_total_list_and_check_acl(THD *thd, LEX *lex,
return 0; return 0;
} }
static int handle_create_select(THD *thd, LEX *lex, select_result *c_i)
{
int res;
if (lex->select_lex.next)
{
TABLE_LIST *total;
if ((res = create_total_list_and_check_acl(thd,lex,&total,true)))
return res;
if (!(res=open_and_lock_tables(thd, total)))
{
for (SELECT_LEX *sl=&lex->select_lex; sl; sl=sl->next)
{
TABLE_LIST *help=(TABLE_LIST *)sl->table_list.first;
if (sl==&lex->select_lex) help=help->next;
for (TABLE_LIST *cursor= help;
cursor;
cursor=cursor->next)
cursor->table= ((TABLE_LIST*) cursor->table)->table;
}
res=mysql_union(thd,lex,c_i);
}
close_thread_tables(thd);
}
else
{
TABLE_LIST *tables=(TABLE_LIST*) lex->select_lex.table_list.first;
SELECT_LEX *select_lex=&lex->select_lex;
if (!(res=open_and_lock_tables(thd,tables->next)))
{
res=mysql_select(thd,tables->next,select_lex->item_list,
select_lex->where,
select_lex->ftfunc_list,
(ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first,
select_lex->having,
(ORDER*) lex->proc_list.first,
select_lex->options | thd->options,
c_i);
}
}
if (res)
c_i->abort();
delete c_i;
return res;
}
void add_join_on(TABLE_LIST *b,Item *expr) void add_join_on(TABLE_LIST *b,Item *expr)
{ {
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include "sql_select.h" #include "sql_select.h"
int mysql_union(THD *thd, LEX *lex) int mysql_union(THD *thd, LEX *lex,select_result *create_insert=(select_result *)NULL)
{ {
SELECT_LEX *sl, *last_sl; SELECT_LEX *sl, *last_sl;
ORDER *order; ORDER *order;
...@@ -60,6 +60,7 @@ int mysql_union(THD *thd, LEX *lex) ...@@ -60,6 +60,7 @@ int mysql_union(THD *thd, LEX *lex)
/* Create a list of items that will be in the result set */ /* Create a list of items that will be in the result set */
first_table= (TABLE_LIST*) lex->select_lex.table_list.first; first_table= (TABLE_LIST*) lex->select_lex.table_list.first;
if (create_insert) first_table=first_table->next;
while ((item= it++)) while ((item= it++))
if (item_list.push_back(item)) if (item_list.push_back(item))
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -95,7 +96,8 @@ int mysql_union(THD *thd, LEX *lex) ...@@ -95,7 +96,8 @@ int mysql_union(THD *thd, LEX *lex)
if (thd->select_limit == HA_POS_ERROR) if (thd->select_limit == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS; sl->options&= ~OPTION_FOUND_ROWS;
res=mysql_select(thd,(TABLE_LIST*) sl->table_list.first, res=mysql_select(thd,(sl == &lex->select_lex) ? first_table :
(TABLE_LIST*) sl->table_list.first,
sl->item_list, sl->item_list,
sl->where, sl->where,
sl->ftfunc_list, sl->ftfunc_list,
...@@ -114,17 +116,9 @@ int mysql_union(THD *thd, LEX *lex) ...@@ -114,17 +116,9 @@ int mysql_union(THD *thd, LEX *lex)
goto exit; goto exit;
} }
delete union_result; delete union_result;
if (create_insert)
/* result=create_insert;
Sinisa, we must also be able to handle else if (lex->exchange)
CREATE TABLE ... and INSERT ... SELECT with unions
To do this, it's probably best that we add a new handle_select() function
which takes 'select_result' as parameter and let this internally handle
SELECT with and without unions.
*/
if (lex->exchange)
{ {
if (lex->exchange->dumpfile) if (lex->exchange->dumpfile)
result=new select_dump(lex->exchange); result=new select_dump(lex->exchange);
......
...@@ -730,7 +730,7 @@ create3: ...@@ -730,7 +730,7 @@ create3:
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex); mysql_init_select(lex);
} }
select_options select_item_list opt_select_from {} select_options select_item_list opt_select_from union {}
opt_as: opt_as:
/* empty */ {} /* empty */ {}
...@@ -1319,7 +1319,7 @@ select: ...@@ -1319,7 +1319,7 @@ select:
SELECT_SYM SELECT_SYM
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command= SQLCOM_SELECT; if (lex->sql_command == SQLCOM_NONE) lex->sql_command= SQLCOM_SELECT;
lex->lock_option=TL_READ; lex->lock_option=TL_READ;
mysql_init_select(lex); mysql_init_select(lex);
} }
...@@ -2207,7 +2207,7 @@ insert_values: ...@@ -2207,7 +2207,7 @@ insert_values:
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex); mysql_init_select(lex);
} }
select_options select_item_list select_from select_lock_type {} select_options select_item_list select_from select_lock_type union {}
values_list: values_list:
values_list ',' no_braces values_list ',' no_braces
...@@ -3418,7 +3418,9 @@ union_list: ...@@ -3418,7 +3418,9 @@ union_list:
} }
select select
{ {
Lex->sql_command=SQLCOM_UNION_SELECT; LEX *lex=Lex;
if (lex->sql_command == SQLCOM_SELECT)
lex->sql_command=SQLCOM_UNION_SELECT;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment