summaryrefslogtreecommitdiff
path: root/sql/sql_insert.cc
diff options
context:
space:
mode:
authorunknown <monty@mysql.com>2005-07-03 14:17:52 +0300
committerunknown <monty@mysql.com>2005-07-03 14:17:52 +0300
commiteeee5fb10b59f6580ebcb08ebd82d0b75c66aa8f (patch)
treebf06496ea5d097316e5972a5cf4c4d5f674fb90b /sql/sql_insert.cc
parent6d9bc9c8b71acd82aa79ae580271e7dc4012e5a4 (diff)
parentc7ab92c28a535d2419ffa906042fff7e476df972 (diff)
downloadmariadb-git-eeee5fb10b59f6580ebcb08ebd82d0b75c66aa8f.tar.gz
Merge with 4.1
Makefile.am: Auto merged myisam/mi_create.c: Auto merged myisam/mi_open.c: Auto merged mysql-test/r/ctype_utf8.result: Auto merged mysys/thr_alarm.c: Auto merged VC++Files/sql/mysqld.dsp: Keep old client/mysqldump.c: Manual merge client/mysqltest.c: Automatic merge configure.in: Manual merge mysql-test/r/ctype_ucs.result: Auto merge mysql-test/r/func_str.result: Auto merge mysql-test/r/group_by.result: Auto merge mysql-test/r/insert_select.result: Auto merge mysql-test/r/insert_update.result: Auto merge mysql-test/r/lowercase_table2.result: Auto merge mysql-test/r/select.result: Manual merge mysql-test/r/variables.result: Auto merge mysql-test/t/ctype_ucs.test: Auto merge mysql-test/t/func_str.test: Auto merge mysql-test/t/group_by.test: Auto merge mysql-test/t/insert_select.test: Auto merge mysql-test/t/insert_update.test: Auto merge mysql-test/t/ndb_alter_table.test: Auto merge mysql-test/t/select.test: Auto merge mysql-test/t/variables.test: Auto merge mysys/my_access.c: Auto merge scripts/make_win_src_distribution.sh: Auto merge sql/field.cc: Manual merge sql/ha_ndbcluster.cc: Auto merge sql/handler.cc: Auto merge sql/item.cc: Auto merge sql/item.h: Manual merge sql/item_cmpfunc.h: Auto merge sql/item_strfunc.cc: Auto merge sql/item_strfunc.h: Auto merge sql/mysql_priv.h: manual merge sql/mysqld.cc: manual merge sql/opt_range.cc: manual merge sql/set_var.cc: Auto merge sql/sql_base.cc: manual merge Restore processing of ON DUPLICATE KEY UPDATE sql/sql_insert.cc: manual merge Restore processing of ON DUPLICATE KEY UPDATE Simplify mysql_prepare_insert by using local variable for select_lex and save old values just before they are changed sql/sql_parse.cc: Restore processing of ON DUPLICATE KEY UPDATE sql/sql_prepare.cc: New ON DUPLICATE KEY UPDATE handling sql/sql_select.cc: manual merge sql/sql_table.cc: auto merge sql/sql_yacc.yy: auto merge strings/ctype-ucs2.c: auto merge strings/ctype-utf8.c: auto merge
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r--sql/sql_insert.cc85
1 files changed, 60 insertions, 25 deletions
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 53c47706734..adb1eb01292 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -327,7 +327,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->used_tables=0;
values= its++;
- if (mysql_prepare_insert(thd, table_list, table, fields, values,
+ if (mysql_prepare_insert(thd, table_list, table_list, table, fields, values,
update_fields, update_values, duplic, &unused_conds,
FALSE))
goto abort;
@@ -734,28 +734,43 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
mysql_prepare_insert()
thd Thread handler
table_list Global/local table list
- table Table to insert into (can be NULL if table should be taken from
- table_list->table)
+ dup_table_list Tables to be used in ON DUPLICATE KEY
+ It's either all global tables or only the table we
+ insert into, depending on if we are using GROUP BY
+ in the SELECT clause).
+ table Table to insert into (can be NULL if table should
+ be taken from table_list->table)
where Where clause (for insert ... select)
select_insert TRUE if INSERT ... SELECT statement
+ TODO (in far future)
+ In cases of:
+ INSERT INTO t1 SELECT a, sum(a) as sum1 from t2 GROUP BY a
+ ON DUPLICATE KEY ...
+ we should be able to refer to sum1 in the ON DUPLICATE KEY part
+
+ WARNING
+ You MUST set table->insert_values to 0 after calling this function
+ before releasing the table object.
+
RETURN VALUE
FALSE OK
TRUE error
*/
-bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
+bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
+ TABLE_LIST *dup_table_list, TABLE *table,
List<Item> &fields, List_item *values,
List<Item> &update_fields, List<Item> &update_values,
enum_duplicates duplic,
COND **where, bool select_insert)
{
- TABLE_LIST *save_table_list= thd->lex->select_lex.context.table_list;
+ SELECT_LEX= &thd->lex->select_lex;
+ TABLE_LIST *save_table_list;
+ TABLE_LIST *save_next_local;
bool insert_into_view= (table_list->view != 0);
- bool save_resolve_in_select_list=
- thd->lex->select_lex.context.resolve_in_select_list;
+ bool save_resolve_in_select_list;
bool res;
- TABLE_LIST *next_local;
DBUG_ENTER("mysql_prepare_insert");
DBUG_PRINT("enter", ("table_list 0x%lx, table 0x%lx, view %d",
(ulong)table_list, (ulong)table,
@@ -768,7 +783,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
*/
if (!select_insert)
{
- for (SELECT_LEX_UNIT *un= thd->lex->select_lex.first_inner_unit();
+ for (SELECT_LEX_UNIT *un= select_lex->first_inner_unit();
un;
un= un->next_unit())
{
@@ -792,23 +807,30 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
select_insert))
DBUG_RETURN(TRUE);
- next_local= table_list->next_local;
+ save_table_list= select_lex->context.table_list;
+ save_resolve_in_select_list= select_lex->context.resolve_in_select_list;
+ save_next_local= table_list->next_local;
+
table_list->next_local= 0;
- thd->lex->select_lex.context.resolve_in_table_list_only(table_list);
+ select_lex->context.resolve_in_table_list_only(table_list);
if ((values && check_insert_fields(thd, table_list, fields, *values,
!insert_into_view)) ||
(values && setup_fields(thd, 0, *values, 0, 0, 0)) ||
- (duplic == DUP_UPDATE &&
- ((thd->lex->select_lex.no_wrap_view_item= TRUE,
- (res= check_update_fields(thd, table_list, update_fields)),
- thd->lex->select_lex.no_wrap_view_item= FALSE,
- res) ||
- setup_fields(thd, 0, update_values, 1, 0, 0))))
- DBUG_RETURN(TRUE);
- table_list->next_local= next_local;
- thd->lex->select_lex.context.table_list= save_table_list;
- thd->lex->select_lex.context.resolve_in_select_list=
- save_resolve_in_select_list;
+ setup_fields(thd, 0, update_values, 1, 0, 0))
+ res= TRUE;
+ else if (duplic == DUP_UPDATE)
+ {
+ select_lex->context.resolve_in_table_list_only(dup_table_list);
+ select_lex->no_wrap_view_item= TRUE;
+ res= check_update_fields(thd, table_list, update_fields);
+ select_lex->no_wrap_view_item= FALSE;
+ }
+ table_list->next_local= save_next_local;
+ select_lex->context.table_list= save_table_list;
+ select_lex->context.resolve_in_select_list= save_resolve_in_select_list;
+ if (res)
+ DBUG_RETURN(res);
+
if (!table)
table= table_list->table;
@@ -820,8 +842,8 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
DBUG_RETURN(TRUE);
}
- thd->lex->select_lex.fix_prepare_information(thd, &fake_conds);
- thd->lex->select_lex.first_execution= 0;
+ select_lex->fix_prepare_information(thd, &fake_conds);
+ select_lex->first_execution= 0;
}
if (duplic == DUP_UPDATE || duplic == DUP_REPLACE)
table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
@@ -1992,12 +2014,25 @@ bool mysql_insert_select_prepare(THD *thd)
{
LEX *lex= thd->lex;
TABLE_LIST *first_select_leaf_table;
+ TABLE_LIST dup_tables;
DBUG_ENTER("mysql_insert_select_prepare");
+
/*
SELECT_LEX do not belong to INSERT statement, so we can't add WHERE
clause if table is VIEW
*/
- if (mysql_prepare_insert(thd, lex->query_tables,
+
+ dup_tables= *lex->query_tables;
+ if (lex->select_lex->group_list.elements != 0)
+ {
+ /*
+ When we are using GROUP BY we can't refere to other tables in the
+ ON DUPLICATE KEY part
+ */
+ dup_tables.local_next= 0;
+ }
+
+ if (mysql_prepare_insert(thd, lex->query_tables, &dup_tables
lex->query_tables->table, lex->field_list, 0,
lex->update_list, lex->value_list,
lex->duplicates,