MDEV-10075: Provide index of error causing error in array INSERT

use existing Warning_info::m_current_row_for_warning instead
of a newly introduced counter.

But use m_current_row_for_warning to count rows also in the parser
and during prepare.
This commit is contained in:
Sergei Golubchik 2021-09-15 15:54:49 +02:00
parent 0ff8976e12
commit d552e092c9
13 changed files with 43 additions and 82 deletions

View File

@ -1470,7 +1470,7 @@ ERROR 42000: Column 'id1' specified twice
GET DIAGNOSTICS CONDITION 1 @var118= ERROR_INDEX; GET DIAGNOSTICS CONDITION 1 @var118= ERROR_INDEX;
SELECT @var118; SELECT @var118;
@var118 @var118
0 1
CREATE FUNCTION f1() RETURNS INT CREATE FUNCTION f1() RETURNS INT
BEGIN BEGIN
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
@ -1481,38 +1481,38 @@ ERROR HY000: Can't update table 't1' in stored function/trigger because it is al
GET DIAGNOSTICS CONDITION 1 @var119= ERROR_INDEX; GET DIAGNOSTICS CONDITION 1 @var119= ERROR_INDEX;
SELECT @var119; SELECT @var119;
@var119 @var119
0 2
INSERT INTO t1 VALUES (1) RETURNING id2; INSERT INTO t1 VALUES (1) RETURNING id2;
ERROR 42S22: Unknown column 'id2' in 'field list' ERROR 42S22: Unknown column 'id2' in 'field list'
GET DIAGNOSTICS CONDITION 1 @var120= ERROR_INDEX; GET DIAGNOSTICS CONDITION 1 @var120= ERROR_INDEX;
SELECT @var120; SELECT @var120;
@var120 @var120
0 1
INSERT INTO t1(id2) VALUES(1); INSERT INTO t1(id2) VALUES(1);
ERROR 42S22: Unknown column 'id2' in 'field list' ERROR 42S22: Unknown column 'id2' in 'field list'
GET DIAGNOSTICS CONDITION 1 @var121= ERROR_INDEX; GET DIAGNOSTICS CONDITION 1 @var121= ERROR_INDEX;
SELECT @var121; SELECT @var121;
@var121 @var121
0 1
INSERT INTO v VALUES(1,2); INSERT INTO v VALUES(1,2);
ERROR HY000: Can not insert into join view 'test.v' without fields list ERROR HY000: Can not insert into join view 'test.v' without fields list
GET DIAGNOSTICS CONDITION 1 @var122= ERROR_INDEX; GET DIAGNOSTICS CONDITION 1 @var122= ERROR_INDEX;
SELECT @var122; SELECT @var122;
@var122 @var122
0 1
INSERT INTO v(a,b) VALUES (1,2); INSERT INTO v(a,b) VALUES (1,2);
ERROR HY000: Can not modify more than one base table through a join view 'test.v' ERROR HY000: Can not modify more than one base table through a join view 'test.v'
GET DIAGNOSTICS CONDITION 1 @var123= ERROR_INDEX; GET DIAGNOSTICS CONDITION 1 @var123= ERROR_INDEX;
SELECT @var123; SELECT @var123;
@var123 @var123
0 1
# REPLACE STATEMENT # REPLACE STATEMENT
REPLACE INTO t1(id1, id1) VALUES (1,1); REPLACE INTO t1(id1, id1) VALUES (1,1);
ERROR 42000: Column 'id1' specified twice ERROR 42000: Column 'id1' specified twice
GET DIAGNOSTICS CONDITION 1 @var124= ERROR_INDEX; GET DIAGNOSTICS CONDITION 1 @var124= ERROR_INDEX;
SELECT @var124; SELECT @var124;
@var124 @var124
0 1
CREATE FUNCTION f2() RETURNS INT CREATE FUNCTION f2() RETURNS INT
BEGIN BEGIN
REPLACE INTO t1 VALUES (1); REPLACE INTO t1 VALUES (1);
@ -1523,31 +1523,31 @@ ERROR HY000: Can't update table 't1' in stored function/trigger because it is al
GET DIAGNOSTICS CONDITION 1 @var125= ERROR_INDEX; GET DIAGNOSTICS CONDITION 1 @var125= ERROR_INDEX;
SELECT @var125; SELECT @var125;
@var125 @var125
0 2
REPLACE INTO t1 VALUES (1) RETURNING id2; REPLACE INTO t1 VALUES (1) RETURNING id2;
ERROR 42S22: Unknown column 'id2' in 'field list' ERROR 42S22: Unknown column 'id2' in 'field list'
GET DIAGNOSTICS CONDITION 1 @var126= ERROR_INDEX; GET DIAGNOSTICS CONDITION 1 @var126= ERROR_INDEX;
SELECT @var126; SELECT @var126;
@var126 @var126
0 1
REPLACE INTO t1(id2) VALUES(1); REPLACE INTO t1(id2) VALUES(1);
ERROR 42S22: Unknown column 'id2' in 'field list' ERROR 42S22: Unknown column 'id2' in 'field list'
GET DIAGNOSTICS CONDITION 1 @var127= ERROR_INDEX; GET DIAGNOSTICS CONDITION 1 @var127= ERROR_INDEX;
SELECT @var127; SELECT @var127;
@var127 @var127
0 1
REPLACE INTO v VALUES(1,2); REPLACE INTO v VALUES(1,2);
ERROR HY000: Can not insert into join view 'test.v' without fields list ERROR HY000: Can not insert into join view 'test.v' without fields list
GET DIAGNOSTICS CONDITION 1 @var128= ERROR_INDEX; GET DIAGNOSTICS CONDITION 1 @var128= ERROR_INDEX;
SELECT @var128; SELECT @var128;
@var128 @var128
0 1
REPLACE INTO v(a,b) VALUES (1,2); REPLACE INTO v(a,b) VALUES (1,2);
ERROR HY000: Can not modify more than one base table through a join view 'test.v' ERROR HY000: Can not modify more than one base table through a join view 'test.v'
GET DIAGNOSTICS CONDITION 1 @var129= ERROR_INDEX; GET DIAGNOSTICS CONDITION 1 @var129= ERROR_INDEX;
SELECT @var129; SELECT @var129;
@var129 @var129
0 1
DROP TABLE t1,t2; DROP TABLE t1,t2;
DROP FUNCTION f1; DROP FUNCTION f1;
DROP FUNCTION f2; DROP FUNCTION f2;

View File

@ -518,7 +518,8 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
found_condition= found_condition=
new (callers_arena->mem_root) Sql_condition(callers_arena->mem_root, new (callers_arena->mem_root) Sql_condition(callers_arena->mem_root,
da->get_error_condition_identity(), da->get_error_condition_identity(),
da->message(), 0); da->message(),
da->current_row_for_warning());
} }
} }
else if (da->current_statement_warn_count()) else if (da->current_statement_warn_count())

View File

@ -908,7 +908,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
org_charset= 0; org_charset= 0;
/* Restore THR_THD */ /* Restore THR_THD */
set_current_thd(old_THR_THD); set_current_thd(old_THR_THD);
current_insert_index= 0;
} }
@ -1056,8 +1055,6 @@ Sql_condition* THD::raise_condition(uint sql_errno,
{ {
Diagnostics_area *da= get_stmt_da(); Diagnostics_area *da= get_stmt_da();
Sql_condition *cond= NULL; Sql_condition *cond= NULL;
ulonglong saved_error_index;
DBUG_ENTER("THD::raise_condition"); DBUG_ENTER("THD::raise_condition");
DBUG_ASSERT(level < Sql_condition::WARN_LEVEL_END); DBUG_ASSERT(level < Sql_condition::WARN_LEVEL_END);
@ -1152,10 +1149,7 @@ Sql_condition* THD::raise_condition(uint sql_errno,
if (likely(!(is_fatal_error && (sql_errno == EE_OUTOFMEMORY || if (likely(!(is_fatal_error && (sql_errno == EE_OUTOFMEMORY ||
sql_errno == ER_OUTOFMEMORY)))) sql_errno == ER_OUTOFMEMORY))))
{ {
saved_error_index= this->current_insert_index;
this->current_insert_index= this->correct_error_index(sql_errno);
cond= da->push_warning(this, sql_errno, sqlstate, level, ucid, msg); cond= da->push_warning(this, sql_errno, sqlstate, level, ucid, msg);
this->current_insert_index= saved_error_index;
} }
DBUG_RETURN(cond); DBUG_RETURN(cond);
} }

View File

@ -5502,29 +5502,6 @@ public:
{ {
lex= backup_lex; lex= backup_lex;
} }
/*
Stores the the processed record during INSERT/REPLACE. Used for assigning
value of error_index in case of warning or error.
*/
ulonglong current_insert_index;
/*
Error may take place in prepare phase and it might not be because of
rows/values we are inserting into the table, it could be because of say
something like wrong field name. In such case we want to return 0
for error index.
*/
ulonglong correct_error_index(uint error_no)
{
if (error_no == ER_FIELD_SPECIFIED_TWICE ||
error_no == ER_BAD_FIELD_ERROR ||
error_no == ER_VIEW_NO_INSERT_FIELD_LIST ||
error_no == ER_VIEW_MULTIUPDATE)
return 0;
return current_insert_index;
}
}; };

View File

@ -673,7 +673,7 @@ Sql_condition *Warning_info::push_warning(THD *thd,
m_warn_list.elements() < thd->variables.max_error_count) m_warn_list.elements() < thd->variables.max_error_count)
{ {
cond= new (& m_warn_root) Sql_condition(& m_warn_root, *value, msg, cond= new (& m_warn_root) Sql_condition(& m_warn_root, *value, msg,
thd->current_insert_index); m_current_row_for_warning);
if (cond) if (cond)
m_warn_list.push_back(cond); m_warn_list.push_back(cond);
} }

View File

@ -306,6 +306,8 @@ protected:
/** SQL CURSOR_NAME condition item. */ /** SQL CURSOR_NAME condition item. */
String m_cursor_name; String m_cursor_name;
ulong m_error_index;
Sql_condition_items() Sql_condition_items()
:m_class_origin((const char*) NULL, 0, & my_charset_utf8mb3_bin), :m_class_origin((const char*) NULL, 0, & my_charset_utf8mb3_bin),
m_subclass_origin((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_subclass_origin((const char*) NULL, 0, & my_charset_utf8mb3_bin),
@ -316,7 +318,8 @@ protected:
m_schema_name((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_schema_name((const char*) NULL, 0, & my_charset_utf8mb3_bin),
m_table_name((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_table_name((const char*) NULL, 0, & my_charset_utf8mb3_bin),
m_column_name((const char*) NULL, 0, & my_charset_utf8mb3_bin), m_column_name((const char*) NULL, 0, & my_charset_utf8mb3_bin),
m_cursor_name((const char*) NULL, 0, & my_charset_utf8mb3_bin) m_cursor_name((const char*) NULL, 0, & my_charset_utf8mb3_bin),
m_error_index(0)
{ } { }
void clear() void clear()
@ -331,6 +334,7 @@ protected:
m_table_name.length(0); m_table_name.length(0);
m_column_name.length(0); m_column_name.length(0);
m_cursor_name.length(0); m_cursor_name.length(0);
m_error_index= 0;
} }
}; };
@ -396,7 +400,7 @@ private:
*/ */
Sql_condition() Sql_condition()
:m_mem_root(NULL) :m_mem_root(NULL)
{ error_index= 0; } { }
/** /**
Complete the Sql_condition initialisation. Complete the Sql_condition initialisation.
@ -419,7 +423,6 @@ private:
:m_mem_root(mem_root) :m_mem_root(mem_root)
{ {
DBUG_ASSERT(mem_root != NULL); DBUG_ASSERT(mem_root != NULL);
error_index= 0;
} }
Sql_condition(MEM_ROOT *mem_root, const Sql_user_condition_identity &ucid) Sql_condition(MEM_ROOT *mem_root, const Sql_user_condition_identity &ucid)
@ -427,7 +430,6 @@ private:
m_mem_root(mem_root) m_mem_root(mem_root)
{ {
DBUG_ASSERT(mem_root != NULL); DBUG_ASSERT(mem_root != NULL);
error_index= 0;
} }
/** /**
Constructor for a fixed message text. Constructor for a fixed message text.
@ -436,18 +438,15 @@ private:
@param level - the error level for this condition @param level - the error level for this condition
@param msg - the message text for this condition @param msg - the message text for this condition
*/ */
Sql_condition(MEM_ROOT *mem_root, Sql_condition(MEM_ROOT *mem_root, const Sql_condition_identity &value,
const Sql_condition_identity &value, const char *msg, ulong current_row_for_warning)
const char *msg, : Sql_condition_identity(value), m_mem_root(mem_root)
ulonglong current_error_index)
:Sql_condition_identity(value),
m_mem_root(mem_root)
{ {
DBUG_ASSERT(mem_root != NULL); DBUG_ASSERT(mem_root != NULL);
DBUG_ASSERT(value.get_sql_errno() != 0); DBUG_ASSERT(value.get_sql_errno() != 0);
DBUG_ASSERT(msg != NULL); DBUG_ASSERT(msg != NULL);
set_builtin_message_text(msg); set_builtin_message_text(msg);
error_index= current_error_index; m_error_index= current_row_for_warning;
} }
/** Destructor. */ /** Destructor. */
@ -501,9 +500,6 @@ private:
/** Memory root to use to hold condition item values. */ /** Memory root to use to hold condition item values. */
MEM_ROOT *m_mem_root; MEM_ROOT *m_mem_root;
/* Index of error for INSERT/REPLACE statement. */
ulonglong error_index;
}; };
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////

View File

@ -339,7 +339,7 @@ Condition_information_item::get_value(THD *thd, const Sql_condition *cond)
value= make_utf8_string_item(thd, &str); value= make_utf8_string_item(thd, &str);
break; break;
case ERROR_INDEX: case ERROR_INDEX:
value= new (thd->mem_root) Item_uint(thd, cond->error_index); value= new (thd->mem_root) Item_uint(thd, cond->m_error_index);
} }
DBUG_RETURN(value); DBUG_RETURN(value);

View File

@ -699,7 +699,6 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
const bool was_insert_delayed= (table_list->lock_type == TL_WRITE_DELAYED); const bool was_insert_delayed= (table_list->lock_type == TL_WRITE_DELAYED);
bool using_bulk_insert= 0; bool using_bulk_insert= 0;
uint value_count; uint value_count;
ulong counter = 1;
/* counter of iteration in bulk PS operation*/ /* counter of iteration in bulk PS operation*/
ulonglong iteration= 0; ulonglong iteration= 0;
ulonglong id; ulonglong id;
@ -711,7 +710,6 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
Name_resolution_context_state ctx_state; Name_resolution_context_state ctx_state;
SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0; SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0;
unsigned char *readbuff= NULL; unsigned char *readbuff= NULL;
thd->current_insert_index= 0;
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
char *query= thd->query(); char *query= thd->query();
@ -831,10 +829,11 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
while ((values= its++)) while ((values= its++))
{ {
thd->current_insert_index= ++counter; thd->get_stmt_da()->inc_current_row_for_warning();
if (values->elements != value_count) 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; goto abort;
} }
if (setup_fields(thd, Ref_ptr_array(), if (setup_fields(thd, Ref_ptr_array(),
@ -843,7 +842,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
switch_to_nullable_trigger_fields(*values, table); switch_to_nullable_trigger_fields(*values, table);
} }
its.rewind (); its.rewind ();
thd->current_insert_index= 0; thd->get_stmt_da()->reset_current_row_for_warning();
/* Restore the current context. */ /* Restore the current context. */
ctx_state.restore_state(context, table_list); ctx_state.restore_state(context, table_list);
@ -1010,7 +1009,6 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
while ((values= its++)) while ((values= its++))
{ {
thd->current_insert_index++;
if (fields.elements || !value_count) if (fields.elements || !value_count)
{ {
/* /*
@ -1134,7 +1132,6 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
} while (bulk_parameters_iterations(thd)); } while (bulk_parameters_iterations(thd));
values_loop_end: values_loop_end:
thd->current_insert_index= 0;
free_underlaid_joins(thd, thd->lex->first_select_lex()); free_underlaid_joins(thd, thd->lex->first_select_lex());
joins_freed= TRUE; joins_freed= TRUE;
@ -1610,8 +1607,6 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
bool res= 0; bool res= 0;
table_map map= 0; table_map map= 0;
TABLE *table; TABLE *table;
thd->current_insert_index= 1;
DBUG_ENTER("mysql_prepare_insert"); DBUG_ENTER("mysql_prepare_insert");
DBUG_PRINT("enter", ("table_list: %p view: %d", DBUG_PRINT("enter", ("table_list: %p view: %d",
table_list, (int) insert_into_view)); table_list, (int) insert_into_view));
@ -1665,7 +1660,6 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
if (!res) if (!res)
res= setup_fields(thd, Ref_ptr_array(), res= setup_fields(thd, Ref_ptr_array(),
update_values, MARK_COLUMNS_READ, 0, NULL, 0); update_values, MARK_COLUMNS_READ, 0, NULL, 0);
thd->current_insert_index= 0;
if (!res && duplic == DUP_UPDATE) if (!res && duplic == DUP_UPDATE)
{ {

View File

@ -7978,7 +7978,6 @@ void mysql_parse(THD *thd, char *rawbuf, uint length,
LEX *lex= thd->lex; LEX *lex= thd->lex;
bool err= parse_sql(thd, parser_state, NULL, true); bool err= parse_sql(thd, parser_state, NULL, true);
thd->current_insert_index= 0;
if (likely(!err)) if (likely(!err))
{ {

View File

@ -1314,7 +1314,6 @@ static bool mysql_test_insert_common(Prepared_statement *stmt,
if ((values= its++)) if ((values= its++))
{ {
uint value_count; uint value_count;
ulong counter= 0;
Item *unused_conds= 0; Item *unused_conds= 0;
if (table_list->table) if (table_list->table)
@ -1338,20 +1337,20 @@ static bool mysql_test_insert_common(Prepared_statement *stmt,
table_list->table_name.str)); table_list->table_name.str));
goto error; goto error;
} }
thd->current_insert_index= 0;
while ((values= its++)) while ((values= its++))
{ {
thd->current_insert_index= ++counter;
if (values->elements != value_count) 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 error; goto error;
} }
if (setup_fields(thd, Ref_ptr_array(), if (setup_fields(thd, Ref_ptr_array(),
*values, COLUMNS_READ, 0, NULL, 0)) *values, COLUMNS_READ, 0, NULL, 0))
goto error; goto error;
thd->get_stmt_da()->inc_current_row_for_warning();
} }
thd->current_insert_index= 0; thd->get_stmt_da()->reset_current_row_for_warning();
} }
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);

View File

@ -419,7 +419,8 @@ bool Sql_cmd_resignal::execute(THD *thd)
DBUG_RETURN(result); DBUG_RETURN(result);
} }
Sql_condition signaled_err(thd->mem_root, *signaled, signaled->message, 0); Sql_condition signaled_err(thd->mem_root, *signaled, signaled->message,
da->current_row_for_warning());
if (m_cond) if (m_cond)
{ {

View File

@ -12833,6 +12833,7 @@ insert:
{ {
Lex->sql_command= SQLCOM_INSERT; Lex->sql_command= SQLCOM_INSERT;
Lex->duplicates= DUP_ERROR; Lex->duplicates= DUP_ERROR;
thd->get_stmt_da()->opt_clear_warning_info(thd->query_id);
} }
insert_start insert_lock_option opt_ignore opt_into insert_table insert_start insert_lock_option opt_ignore opt_into insert_table
{ {
@ -12842,6 +12843,7 @@ insert:
stmt_end stmt_end
{ {
Lex->mark_first_table_as_inserting(); Lex->mark_first_table_as_inserting();
thd->get_stmt_da()->reset_current_row_for_warning();
} }
; ;
@ -12850,6 +12852,7 @@ replace:
{ {
Lex->sql_command = SQLCOM_REPLACE; Lex->sql_command = SQLCOM_REPLACE;
Lex->duplicates= DUP_REPLACE; Lex->duplicates= DUP_REPLACE;
thd->get_stmt_da()->opt_clear_warning_info(thd->query_id);
} }
insert_start replace_lock_option opt_into insert_table insert_start replace_lock_option opt_into insert_table
{ {
@ -12859,6 +12862,7 @@ replace:
stmt_end stmt_end
{ {
Lex->mark_first_table_as_inserting(); Lex->mark_first_table_as_inserting();
thd->get_stmt_da()->reset_current_row_for_warning();
} }
; ;
@ -12918,7 +12922,6 @@ insert_table:
//lex->field_list.empty(); //lex->field_list.empty();
lex->many_values.empty(); lex->many_values.empty();
lex->insert_list=0; lex->insert_list=0;
thd->current_insert_index= lex->many_values.elements+1;
} }
; ;
@ -12928,14 +12931,11 @@ insert_field_spec:
| SET | SET
{ {
LEX *lex=Lex; LEX *lex=Lex;
ulonglong saved_current_insert_index= thd->current_insert_index;
if (unlikely(!(lex->insert_list= new (thd->mem_root) List_item)) || if (unlikely(!(lex->insert_list= new (thd->mem_root) List_item)) ||
unlikely(lex->many_values.push_back(lex->insert_list, unlikely(lex->many_values.push_back(lex->insert_list,
thd->mem_root))) thd->mem_root)))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->current_select->parsing_place= NO_MATTER; lex->current_select->parsing_place= NO_MATTER;
if (saved_current_insert_index < lex->many_values.elements)
thd->current_insert_index++;
} }
ident_eq_list ident_eq_list
; ;
@ -13013,10 +13013,10 @@ no_braces:
opt_values ')' opt_values ')'
{ {
LEX *lex=Lex; LEX *lex=Lex;
thd->get_stmt_da()->inc_current_row_for_warning();
if (unlikely(lex->many_values.push_back(lex->insert_list, if (unlikely(lex->many_values.push_back(lex->insert_list,
thd->mem_root))) thd->mem_root)))
MYSQL_YYABORT; MYSQL_YYABORT;
thd->current_insert_index++;
} }
; ;
@ -13029,10 +13029,10 @@ no_braces_with_names:
opt_values_with_names ')' opt_values_with_names ')'
{ {
LEX *lex=Lex; LEX *lex=Lex;
thd->get_stmt_da()->inc_current_row_for_warning();
if (unlikely(lex->many_values.push_back(lex->insert_list, if (unlikely(lex->many_values.push_back(lex->insert_list,
thd->mem_root))) thd->mem_root)))
MYSQL_YYABORT; MYSQL_YYABORT;
thd->current_insert_index++;
} }
; ;