diff options
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r-- | sql/sql_insert.cc | 82 |
1 files changed, 68 insertions, 14 deletions
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 22374458c3d..45296f22f35 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -229,6 +229,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, } if (values.elements != table->s->visible_fields) { + thd->get_stmt_da()->reset_current_row_for_warning(1); my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L); DBUG_RETURN(-1); } @@ -253,6 +254,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, if (fields.elements != values.elements) { + thd->get_stmt_da()->reset_current_row_for_warning(1); my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L); DBUG_RETURN(-1); } @@ -699,7 +701,6 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, const bool was_insert_delayed= (table_list->lock_type == TL_WRITE_DELAYED); bool using_bulk_insert= 0; uint value_count; - ulong counter = 1; /* counter of iteration in bulk PS operation*/ ulonglong iteration= 0; ulonglong id; @@ -767,7 +768,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, value_count= values->elements; if ((res= mysql_prepare_insert(thd, table_list, fields, values, - update_fields, update_values, duplic, + update_fields, update_values, duplic, ignore, &unused_conds, FALSE))) { retval= thd->is_error(); @@ -828,12 +829,27 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, context->resolve_in_table_list_only(table_list); switch_to_nullable_trigger_fields(*values, table); + /* + Check assignability for the leftmost () in VALUES: + INSERT INTO t1 (a,b) VALUES (1,2), (3,4); + This checks if the values (1,2) can be assigned to fields (a,b). + The further values, e.g. (3,4) are not checked - they will be + checked during the execution time (when processing actual rows). + This is to preserve the "insert until the very first error"-style + behaviour for non-transactional tables. + */ + if (values->elements && + table_list->table->check_assignability_opt_fields(fields, *values, + ignore)) + goto abort; + while ((values= its++)) { - counter++; + thd->get_stmt_da()->inc_current_row_for_warning(); if (values->elements != value_count) { - my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); + my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), + thd->get_stmt_da()->current_row_for_warning()); goto abort; } if (setup_fields(thd, Ref_ptr_array(), @@ -842,6 +858,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, switch_to_nullable_trigger_fields(*values, table); } its.rewind (); + thd->get_stmt_da()->reset_current_row_for_warning(0); /* Restore the current context. */ ctx_state.restore_state(context, table_list); @@ -1014,6 +1031,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, while ((values= its++)) { + thd->get_stmt_da()->inc_current_row_for_warning(); if (fields.elements || !value_count) { /* @@ -1130,7 +1148,6 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, if (unlikely(error)) break; info.accepted_rows++; - thd->get_stmt_da()->inc_current_row_for_warning(); } its.rewind(); iteration++; @@ -1163,8 +1180,13 @@ values_loop_end: table->file->ha_release_auto_increment(); if (using_bulk_insert) { - if (unlikely(table->file->ha_end_bulk_insert()) && - !error) + /* + if my_error() wasn't called yet on some specific row, end_bulk_insert() + can still do it, but the error shouldn't be for any specific row number + */ + if (!error) + thd->get_stmt_da()->reset_current_row_for_warning(0); + if (unlikely(table->file->ha_end_bulk_insert()) && !error) { table->file->print_error(my_errno,MYF(0)); error=1; @@ -1425,7 +1447,7 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view) DBUG_ASSERT(view->table != 0 && view->field_translation != 0); - (void) my_bitmap_init(&used_fields, used_fields_buff, table->s->fields, 0); + (void) my_bitmap_init(&used_fields, used_fields_buff, table->s->fields); bitmap_clear_all(&used_fields); view->contain_auto_increment= 0; @@ -1618,7 +1640,8 @@ static void prepare_for_positional_update(TABLE *table, TABLE_LIST *tables) int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, List<Item> &fields, List_item *values, List<Item> &update_fields, List<Item> &update_values, - enum_duplicates duplic, COND **where, + enum_duplicates duplic, bool ignore, + COND **where, bool select_insert) { SELECT_LEX *select_lex= thd->lex->first_select_lex(); @@ -1686,7 +1709,16 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, { select_lex->no_wrap_view_item= TRUE; res= check_update_fields(thd, context->table_list, update_fields, - update_values, false, &map); + update_values, false, &map) || + /* + Check that all col=expr pairs are compatible for assignment in + INSERT INTO t1 VALUES (...) + ON DUPLICATE KEY UPDATE col=expr [, col=expr]; + */ + TABLE::check_assignability_explicit_fields(update_fields, + update_values, + ignore); + select_lex->no_wrap_view_item= FALSE; } @@ -1694,6 +1726,8 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, ctx_state.restore_state(context, table_list); } + thd->get_stmt_da()->reset_current_row_for_warning(1); + if (res) DBUG_RETURN(res); @@ -2801,7 +2835,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) my_bitmap_init(©->has_value_set, (my_bitmap_map*) (bitmap + bitmaps_used*share->column_bitmap_size), - share->fields, FALSE); + share->fields); } copy->tmp_set.bitmap= 0; // To catch errors bzero((char*) bitmap, share->column_bitmap_size * bitmaps_used); @@ -3784,7 +3818,7 @@ int mysql_insert_select_prepare(THD *thd, select_result *sel_res) if ((res= mysql_prepare_insert(thd, lex->query_tables, lex->field_list, 0, lex->update_list, lex->value_list, - lex->duplicates, + lex->duplicates, lex->ignore, &select_lex->where, TRUE))) DBUG_RETURN(res); @@ -3878,6 +3912,17 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) check_insert_fields(thd, table_list, *fields, values, !insert_into_view, 1, &map)); + if (!res) + { + /* + Check that all colN=exprN pairs are compatible for assignment, e.g.: + INSERT INTO t1 (col1, col2) VALUES (expr1, expr2); + INSERT INTO t1 SET col1=expr1, col2=expr2; + */ + res= table_list->table->check_assignability_opt_fields(*fields, values, + lex->ignore); + } + if (!res && fields->elements) { Abort_on_warning_instant_set aws(thd, @@ -3931,7 +3976,15 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) } res= res || setup_fields(thd, Ref_ptr_array(), *info.update_values, - MARK_COLUMNS_READ, 0, NULL, 0); + MARK_COLUMNS_READ, 0, NULL, 0) || + /* + Check that all col=expr pairs are compatible for assignment in + INSERT INTO t1 SELECT ... FROM t2 + ON DUPLICATE KEY UPDATE col=expr [, col=expr] + */ + TABLE::check_assignability_explicit_fields(*info.update_fields, + *info.update_values, + lex->ignore); if (!res) { /* @@ -5100,7 +5153,8 @@ bool select_create::send_eof() { WSREP_DEBUG("select_create commit failed, thd: %llu err: %s %s", thd->thread_id, - wsrep_thd_transaction_state_str(thd), wsrep_thd_query(thd)); + wsrep_thd_transaction_state_str(thd), + wsrep_thd_query(thd)); mysql_mutex_unlock(&thd->LOCK_thd_data); abort_result_set(); DBUG_RETURN(true); |