Skip to content

Commit 61d9367

Browse files
author
gkodinov/kgeorge@macbook.gmz
committed
Bug #26261:
INSERT uses query_id to verify what fields are mentioned in the fields list of the INSERT command. However the check for that is made after the ON DUPLICATE KEY is processed. This causes all the fields mentioned in ON DUPLICATE KEY to be considered as mentioned in the fields list of INSERT. Moved the check up, right after processing the fields list.
1 parent bcf1596 commit 61d9367

File tree

5 files changed

+80
-25
lines changed

5 files changed

+80
-25
lines changed

mysql-test/r/insert_update.result

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,3 +236,14 @@ INSERT INTO t2 VALUES (1), (3);
236236
INSERT INTO t1 SELECT 1, COUNT(*) FROM t2 ON DUPLICATE KEY UPDATE j= a;
237237
ERROR 42S22: Unknown column 'a' in 'field list'
238238
DROP TABLE t1,t2;
239+
SET SQL_MODE = 'TRADITIONAL';
240+
CREATE TABLE t1 (a INT PRIMARY KEY, b INT NOT NULL);
241+
INSERT INTO t1 (a) VALUES (1);
242+
ERROR HY000: Field 'b' doesn't have a default value
243+
INSERT INTO t1 (a) VALUES (1) ON DUPLICATE KEY UPDATE a = b;
244+
ERROR HY000: Field 'b' doesn't have a default value
245+
INSERT INTO t1 (a) VALUES (1) ON DUPLICATE KEY UPDATE b = b;
246+
ERROR HY000: Field 'b' doesn't have a default value
247+
SELECT * FROM t1;
248+
a b
249+
DROP TABLE t1;

mysql-test/t/insert_update.test

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,24 @@ INSERT INTO t2 VALUES (1), (3);
162162
--error ER_BAD_FIELD_ERROR
163163
INSERT INTO t1 SELECT 1, COUNT(*) FROM t2 ON DUPLICATE KEY UPDATE j= a;
164164
DROP TABLE t1,t2;
165+
166+
#
167+
# Bug #26261: Missing default value isn't noticed in
168+
# insert ... on duplicate key update
169+
#
170+
SET SQL_MODE = 'TRADITIONAL';
171+
172+
CREATE TABLE t1 (a INT PRIMARY KEY, b INT NOT NULL);
173+
174+
--error 1364
175+
INSERT INTO t1 (a) VALUES (1);
176+
177+
--error 1364
178+
INSERT INTO t1 (a) VALUES (1) ON DUPLICATE KEY UPDATE a = b;
179+
180+
--error 1364
181+
INSERT INTO t1 (a) VALUES (1) ON DUPLICATE KEY UPDATE b = b;
182+
183+
SELECT * FROM t1;
184+
185+
DROP TABLE t1;

sql/mysql_priv.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,8 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
823823
List<Item> &fields, List_item *values,
824824
List<Item> &update_fields,
825825
List<Item> &update_values, enum_duplicates duplic,
826-
COND **where, bool select_insert);
826+
COND **where, bool select_insert,
827+
bool check_fields, bool abort_on_warning);
827828
bool mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
828829
List<List_item> &values, List<Item> &update_fields,
829830
List<Item> &update_values, enum_duplicates flag,

sql/sql_insert.cc

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -451,10 +451,15 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
451451
thd->proc_info="init";
452452
thd->used_tables=0;
453453
values= its++;
454+
value_count= values->elements;
454455

455456
if (mysql_prepare_insert(thd, table_list, table, fields, values,
456457
update_fields, update_values, duplic, &unused_conds,
457-
FALSE))
458+
FALSE,
459+
(fields.elements || !value_count),
460+
!ignore && (thd->variables.sql_mode &
461+
(MODE_STRICT_TRANS_TABLES |
462+
MODE_STRICT_ALL_TABLES))))
458463
goto abort;
459464

460465
/* mysql_prepare_insert set table_list->table if it was not set */
@@ -480,7 +485,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
480485
table_list->next_local= 0;
481486
context->resolve_in_table_list_only(table_list);
482487

483-
value_count= values->elements;
484488
while ((values= its++))
485489
{
486490
counter++;
@@ -551,17 +555,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
551555
table->file->start_bulk_insert(values_list.elements);
552556

553557
thd->no_trans_update= 0;
554-
thd->abort_on_warning= (!ignore &&
555-
(thd->variables.sql_mode &
556-
(MODE_STRICT_TRANS_TABLES |
557-
MODE_STRICT_ALL_TABLES)));
558-
559-
if ((fields.elements || !value_count) &&
560-
check_that_all_fields_are_given_values(thd, table, table_list))
561-
{
562-
/* thd->net.report_error is now set, which will abort the next loop */
563-
error= 1;
564-
}
558+
thd->abort_on_warning= (!ignore && (thd->variables.sql_mode &
559+
(MODE_STRICT_TRANS_TABLES |
560+
MODE_STRICT_ALL_TABLES)));
565561

566562
mark_fields_used_by_triggers_for_insert_stmt(thd, table, duplic);
567563

@@ -934,6 +930,10 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
934930
be taken from table_list->table)
935931
where Where clause (for insert ... select)
936932
select_insert TRUE if INSERT ... SELECT statement
933+
check_fields TRUE if need to check that all INSERT fields are
934+
given values.
935+
abort_on_warning whether to report if some INSERT field is not
936+
assigned as an error (TRUE) or as a warning (FALSE).
937937
938938
TODO (in far future)
939939
In cases of:
@@ -954,7 +954,8 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
954954
TABLE *table, List<Item> &fields, List_item *values,
955955
List<Item> &update_fields, List<Item> &update_values,
956956
enum_duplicates duplic,
957-
COND **where, bool select_insert)
957+
COND **where, bool select_insert,
958+
bool check_fields, bool abort_on_warning)
958959
{
959960
SELECT_LEX *select_lex= &thd->lex->select_lex;
960961
Name_resolution_context *context= &select_lex->context;
@@ -1017,10 +1018,22 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
10171018
table_list->next_local= 0;
10181019
context->resolve_in_table_list_only(table_list);
10191020

1020-
if (!(res= check_insert_fields(thd, context->table_list, fields, *values,
1021-
!insert_into_view, &map) ||
1022-
setup_fields(thd, 0, *values, 0, 0, 0))
1023-
&& duplic == DUP_UPDATE)
1021+
res= check_insert_fields(thd, context->table_list, fields, *values,
1022+
!insert_into_view, &map) ||
1023+
setup_fields(thd, 0, *values, 0, 0, 0);
1024+
1025+
if (!res && check_fields)
1026+
{
1027+
bool saved_abort_on_warning= thd->abort_on_warning;
1028+
thd->abort_on_warning= abort_on_warning;
1029+
res= check_that_all_fields_are_given_values(thd,
1030+
table ? table :
1031+
context->table_list->table,
1032+
context->table_list);
1033+
thd->abort_on_warning= saved_abort_on_warning;
1034+
}
1035+
1036+
if (!res && duplic == DUP_UPDATE)
10241037
{
10251038
select_lex->no_wrap_view_item= TRUE;
10261039
res= check_update_fields(thd, context->table_list, update_fields, &map);
@@ -2295,7 +2308,7 @@ bool mysql_insert_select_prepare(THD *thd)
22952308
lex->query_tables->table, lex->field_list, 0,
22962309
lex->update_list, lex->value_list,
22972310
lex->duplicates,
2298-
&select_lex->where, TRUE))
2311+
&select_lex->where, TRUE, FALSE, FALSE))
22992312
DBUG_RETURN(TRUE);
23002313

23012314
/*
@@ -2357,7 +2370,18 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
23572370
!insert_into_view, &map) ||
23582371
setup_fields(thd, 0, values, 0, 0, 0);
23592372

2360-
if (info.handle_duplicates == DUP_UPDATE)
2373+
if (!res && fields->elements)
2374+
{
2375+
bool saved_abort_on_warning= thd->abort_on_warning;
2376+
thd->abort_on_warning= !info.ignore && (thd->variables.sql_mode &
2377+
(MODE_STRICT_TRANS_TABLES |
2378+
MODE_STRICT_ALL_TABLES));
2379+
res= check_that_all_fields_are_given_values(thd, table_list->table,
2380+
table_list);
2381+
thd->abort_on_warning= saved_abort_on_warning;
2382+
}
2383+
2384+
if (info.handle_duplicates == DUP_UPDATE && !res)
23612385
{
23622386
Name_resolution_context *context= &lex->select_lex.context;
23632387
Name_resolution_context_state ctx_state;
@@ -2459,9 +2483,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
24592483
(thd->variables.sql_mode &
24602484
(MODE_STRICT_TRANS_TABLES |
24612485
MODE_STRICT_ALL_TABLES)));
2462-
res= ((fields->elements &&
2463-
check_that_all_fields_are_given_values(thd, table, table_list)) ||
2464-
table_list->prepare_where(thd, 0, TRUE) ||
2486+
res= (table_list->prepare_where(thd, 0, TRUE) ||
24652487
table_list->prepare_check_option(thd));
24662488

24672489
if (!res)

sql/sql_prepare.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1058,7 +1058,7 @@ static bool mysql_test_insert(Prepared_statement *stmt,
10581058

10591059
if (mysql_prepare_insert(thd, table_list, table_list->table,
10601060
fields, values, update_fields, update_values,
1061-
duplic, &unused_conds, FALSE))
1061+
duplic, &unused_conds, FALSE, FALSE, FALSE))
10621062
goto error;
10631063

10641064
value_count= values->elements;

0 commit comments

Comments
 (0)