Skip to content

Commit ea06c67

Browse files
mariadb-RuchaDeodharvuvova
authored andcommitted
MDEV-10075: Provide index of error causing error in array INSERT
Extended the parser for GET DIAGNOSTICS to use ERROR_INDEX to get warning/error index. Error information is stored in Sql_condition. So it can be used to store the index of warning/error too. THD::current_insert_index keeps a track of count for each row that is processed or going to be inserted in the table (or first row in case of prepare phase). When an error occurs, first we need to fetch corrected error index (using correct_error_index()) for an error number. This is needed because in prepare phase, the error may not be because of rows/values. In such case, correct value of error_index should be 0. Once correct value if fetched, assign it to Sql_condition::error_index when the object is created during error/warning. This error_index variable is returned when ERROR_INDEX is used in GET DIAGNOSTICS.
1 parent 50e08f3 commit ea06c67

16 files changed

+1501
-8
lines changed

mysql-test/main/get_diagnostics.result

Lines changed: 763 additions & 0 deletions
Large diffs are not rendered by default.

mysql-test/main/get_diagnostics.test

Lines changed: 579 additions & 0 deletions
Large diffs are not rendered by default.

sql/lex.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ SYMBOL symbols[] = {
222222
{ "ENUM", SYM(ENUM)},
223223
{ "ERROR", SYM(ERROR_SYM)},
224224
{ "ERRORS", SYM(ERRORS)},
225+
{ "ERROR_INDEX", SYM(ERROR_INDEX_SYM)},
225226
{ "ESCAPE", SYM(ESCAPE_SYM)},
226227
{ "ESCAPED", SYM(ESCAPED)},
227228
{ "EVENT", SYM(EVENT_SYM)},

sql/sp_rcontext.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
518518
found_condition=
519519
new (callers_arena->mem_root) Sql_condition(callers_arena->mem_root,
520520
da->get_error_condition_identity(),
521-
da->message());
521+
da->message(), 0);
522522
}
523523
}
524524
else if (da->current_statement_warn_count())

sql/sql_class.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
908908
org_charset= 0;
909909
/* Restore THR_THD */
910910
set_current_thd(old_THR_THD);
911+
current_insert_index= 0;
911912
}
912913

913914

@@ -1055,6 +1056,8 @@ Sql_condition* THD::raise_condition(uint sql_errno,
10551056
{
10561057
Diagnostics_area *da= get_stmt_da();
10571058
Sql_condition *cond= NULL;
1059+
ulonglong saved_error_index;
1060+
10581061
DBUG_ENTER("THD::raise_condition");
10591062
DBUG_ASSERT(level < Sql_condition::WARN_LEVEL_END);
10601063

@@ -1149,7 +1152,10 @@ Sql_condition* THD::raise_condition(uint sql_errno,
11491152
if (likely(!(is_fatal_error && (sql_errno == EE_OUTOFMEMORY ||
11501153
sql_errno == ER_OUTOFMEMORY))))
11511154
{
1155+
saved_error_index= this->current_insert_index;
1156+
this->current_insert_index= this->correct_error_index(sql_errno);
11521157
cond= da->push_warning(this, sql_errno, sqlstate, level, ucid, msg);
1158+
this->current_insert_index= saved_error_index;
11531159
}
11541160
DBUG_RETURN(cond);
11551161
}

sql/sql_class.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5502,6 +5502,29 @@ class THD: public THD_count, /* this must be first */
55025502
{
55035503
lex= backup_lex;
55045504
}
5505+
5506+
/*
5507+
Stores the the processed record during INSERT/REPLACE. Used for assigning
5508+
value of error_index in case of warning or error.
5509+
*/
5510+
ulonglong current_insert_index;
5511+
5512+
/*
5513+
Error may take place in prepare phase and it might not be because of
5514+
rows/values we are inserting into the table, it could be because of say
5515+
something like wrong field name. In such case we want to return 0
5516+
for error index.
5517+
*/
5518+
ulonglong correct_error_index(uint error_no)
5519+
{
5520+
if (error_no == ER_FIELD_SPECIFIED_TWICE ||
5521+
error_no == ER_BAD_FIELD_ERROR ||
5522+
error_no == ER_VIEW_NO_INSERT_FIELD_LIST ||
5523+
error_no == ER_VIEW_MULTIUPDATE)
5524+
return 0;
5525+
5526+
return current_insert_index;
5527+
}
55055528
};
55065529

55075530

sql/sql_error.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,8 @@ Sql_condition *Warning_info::push_warning(THD *thd,
672672
if (m_allow_unlimited_warnings ||
673673
m_warn_list.elements() < thd->variables.max_error_count)
674674
{
675-
cond= new (& m_warn_root) Sql_condition(& m_warn_root, *value, msg);
675+
cond= new (& m_warn_root) Sql_condition(& m_warn_root, *value, msg,
676+
thd->current_insert_index);
676677
if (cond)
677678
m_warn_list.push_back(cond);
678679
}

sql/sql_error.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ class Sql_condition : public Sql_alloc,
396396
*/
397397
Sql_condition()
398398
:m_mem_root(NULL)
399-
{ }
399+
{ error_index= 0; }
400400

401401
/**
402402
Complete the Sql_condition initialisation.
@@ -419,13 +419,15 @@ class Sql_condition : public Sql_alloc,
419419
:m_mem_root(mem_root)
420420
{
421421
DBUG_ASSERT(mem_root != NULL);
422+
error_index= 0;
422423
}
423424

424425
Sql_condition(MEM_ROOT *mem_root, const Sql_user_condition_identity &ucid)
425426
:Sql_condition_identity(Sql_state_errno_level(), ucid),
426427
m_mem_root(mem_root)
427428
{
428429
DBUG_ASSERT(mem_root != NULL);
430+
error_index= 0;
429431
}
430432
/**
431433
Constructor for a fixed message text.
@@ -436,14 +438,16 @@ class Sql_condition : public Sql_alloc,
436438
*/
437439
Sql_condition(MEM_ROOT *mem_root,
438440
const Sql_condition_identity &value,
439-
const char *msg)
441+
const char *msg,
442+
ulonglong current_error_index)
440443
:Sql_condition_identity(value),
441444
m_mem_root(mem_root)
442445
{
443446
DBUG_ASSERT(mem_root != NULL);
444447
DBUG_ASSERT(value.get_sql_errno() != 0);
445448
DBUG_ASSERT(msg != NULL);
446449
set_builtin_message_text(msg);
450+
error_index= current_error_index;
447451
}
448452

449453
/** Destructor. */
@@ -497,6 +501,9 @@ class Sql_condition : public Sql_alloc,
497501

498502
/** Memory root to use to hold condition item values. */
499503
MEM_ROOT *m_mem_root;
504+
505+
/* Index of error for INSERT/REPLACE statement. */
506+
ulonglong error_index;
500507
};
501508

502509
///////////////////////////////////////////////////////////////////////////

sql/sql_get_diagnostics.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,8 @@ Condition_information_item::get_value(THD *thd, const Sql_condition *cond)
338338
str.set_ascii(cond->get_sqlstate(), strlen(cond->get_sqlstate()));
339339
value= make_utf8_string_item(thd, &str);
340340
break;
341+
case ERROR_INDEX:
342+
value= new (thd->mem_root) Item_uint(thd, cond->error_index);
341343
}
342344

343345
DBUG_RETURN(value);

sql/sql_get_diagnostics.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,8 @@ class Condition_information_item : public Diagnostics_information_item
254254
CURSOR_NAME,
255255
MESSAGE_TEXT,
256256
MYSQL_ERRNO,
257-
RETURNED_SQLSTATE
257+
RETURNED_SQLSTATE,
258+
ERROR_INDEX
258259
};
259260

260261
/**

0 commit comments

Comments
 (0)