MDEV-30366 Permit bulk implementation to return ALL individual results
COM_STMT_BULK_STMT new flag to server to returns all unitary results
This commit is contained in:
parent
73ed0a23eb
commit
ea6975b1f1
@ -124,8 +124,7 @@ enum enum_indicator_type
|
|||||||
bulk PS flags
|
bulk PS flags
|
||||||
*/
|
*/
|
||||||
#define STMT_BULK_FLAG_CLIENT_SEND_TYPES 128
|
#define STMT_BULK_FLAG_CLIENT_SEND_TYPES 128
|
||||||
#define STMT_BULK_FLAG_INSERT_ID_REQUEST 64
|
#define STMT_BULK_FLAG_SEND_UNIT_RESULTS 64
|
||||||
|
|
||||||
|
|
||||||
/* sql type stored in .frm files for virtual fields */
|
/* sql type stored in .frm files for virtual fields */
|
||||||
#define MYSQL_TYPE_VIRTUAL 245
|
#define MYSQL_TYPE_VIRTUAL 245
|
||||||
@ -288,6 +287,9 @@ enum enum_indicator_type
|
|||||||
/* Do not resend metadata for prepared statements, since 10.6*/
|
/* Do not resend metadata for prepared statements, since 10.6*/
|
||||||
#define MARIADB_CLIENT_CACHE_METADATA (1ULL << 36)
|
#define MARIADB_CLIENT_CACHE_METADATA (1ULL << 36)
|
||||||
|
|
||||||
|
/* permit sending unit result-set for BULK commands */
|
||||||
|
#define MARIADB_CLIENT_BULK_UNIT_RESULTS (1ULL << 37)
|
||||||
|
|
||||||
#ifdef HAVE_COMPRESS
|
#ifdef HAVE_COMPRESS
|
||||||
#define CAN_CLIENT_COMPRESS CLIENT_COMPRESS
|
#define CAN_CLIENT_COMPRESS CLIENT_COMPRESS
|
||||||
#else
|
#else
|
||||||
@ -328,7 +330,8 @@ enum enum_indicator_type
|
|||||||
MARIADB_CLIENT_STMT_BULK_OPERATIONS |\
|
MARIADB_CLIENT_STMT_BULK_OPERATIONS |\
|
||||||
MARIADB_CLIENT_EXTENDED_METADATA|\
|
MARIADB_CLIENT_EXTENDED_METADATA|\
|
||||||
MARIADB_CLIENT_CACHE_METADATA |\
|
MARIADB_CLIENT_CACHE_METADATA |\
|
||||||
CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS)
|
CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS |\
|
||||||
|
MARIADB_CLIENT_BULK_UNIT_RESULTS)
|
||||||
/*
|
/*
|
||||||
Switch off the flags that are optional and depending on build flags
|
Switch off the flags that are optional and depending on build flags
|
||||||
If any of the optional flags is supported by the build it will be switched
|
If any of the optional flags is supported by the build it will be switched
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 1e2968ade732d320e074e89c3e9d39a4a57cd70c
|
Subproject commit b4d75e78c487254cab9c42e259c3522e9cd0c7c4
|
@ -593,6 +593,7 @@ void Protocol::end_statement()
|
|||||||
|
|
||||||
switch (thd->get_stmt_da()->status()) {
|
switch (thd->get_stmt_da()->status()) {
|
||||||
case Diagnostics_area::DA_ERROR:
|
case Diagnostics_area::DA_ERROR:
|
||||||
|
thd->stop_collecting_unit_results();
|
||||||
/* The query failed, send error to log and abort bootstrap. */
|
/* The query failed, send error to log and abort bootstrap. */
|
||||||
error= send_error(thd->get_stmt_da()->sql_errno(),
|
error= send_error(thd->get_stmt_da()->sql_errno(),
|
||||||
thd->get_stmt_da()->message(),
|
thd->get_stmt_da()->message(),
|
||||||
@ -600,12 +601,36 @@ void Protocol::end_statement()
|
|||||||
break;
|
break;
|
||||||
case Diagnostics_area::DA_EOF:
|
case Diagnostics_area::DA_EOF:
|
||||||
case Diagnostics_area::DA_EOF_BULK:
|
case Diagnostics_area::DA_EOF_BULK:
|
||||||
error= send_eof(thd->server_status,
|
if (thd->need_report_unit_results()) {
|
||||||
|
// bulk returning result-set, like INSERT ... RETURNING
|
||||||
|
// result is already send, needs an EOF with MORE_RESULT_EXISTS
|
||||||
|
// before sending unit result-set
|
||||||
|
error= send_eof(thd->server_status | SERVER_MORE_RESULTS_EXISTS,
|
||||||
|
thd->get_stmt_da()->statement_warn_count());
|
||||||
|
if (thd->report_collected_unit_results() && thd->is_error())
|
||||||
|
error= send_error(thd->get_stmt_da()->sql_errno(),
|
||||||
|
thd->get_stmt_da()->message(),
|
||||||
|
thd->get_stmt_da()->get_sqlstate());
|
||||||
|
else
|
||||||
|
error= send_eof(thd->server_status,
|
||||||
|
thd->get_stmt_da()->statement_warn_count());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error= send_eof(thd->server_status,
|
||||||
thd->get_stmt_da()->statement_warn_count());
|
thd->get_stmt_da()->statement_warn_count());
|
||||||
break;
|
break;
|
||||||
case Diagnostics_area::DA_OK:
|
case Diagnostics_area::DA_OK:
|
||||||
case Diagnostics_area::DA_OK_BULK:
|
case Diagnostics_area::DA_OK_BULK:
|
||||||
error= send_ok(thd->server_status,
|
if (thd->report_collected_unit_results())
|
||||||
|
if (thd->is_error())
|
||||||
|
error= send_error(thd->get_stmt_da()->sql_errno(),
|
||||||
|
thd->get_stmt_da()->message(),
|
||||||
|
thd->get_stmt_da()->get_sqlstate());
|
||||||
|
else
|
||||||
|
error= send_eof(thd->server_status,
|
||||||
|
thd->get_stmt_da()->statement_warn_count());
|
||||||
|
else
|
||||||
|
error= send_ok(thd->server_status,
|
||||||
thd->get_stmt_da()->statement_warn_count(),
|
thd->get_stmt_da()->statement_warn_count(),
|
||||||
thd->get_stmt_da()->affected_rows(),
|
thd->get_stmt_da()->affected_rows(),
|
||||||
thd->get_stmt_da()->last_insert_id(),
|
thd->get_stmt_da()->last_insert_id(),
|
||||||
@ -615,6 +640,7 @@ void Protocol::end_statement()
|
|||||||
break;
|
break;
|
||||||
case Diagnostics_area::DA_EMPTY:
|
case Diagnostics_area::DA_EMPTY:
|
||||||
default:
|
default:
|
||||||
|
thd->stop_collecting_unit_results();
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
error= send_ok(thd->server_status, 0, 0, 0, NULL);
|
error= send_ok(thd->server_status, 0, 0, 0, NULL);
|
||||||
break;
|
break;
|
||||||
|
@ -34,6 +34,12 @@ struct TABLE_LIST;
|
|||||||
typedef struct st_mysql_field MYSQL_FIELD;
|
typedef struct st_mysql_field MYSQL_FIELD;
|
||||||
typedef struct st_mysql_rows MYSQL_ROWS;
|
typedef struct st_mysql_rows MYSQL_ROWS;
|
||||||
|
|
||||||
|
struct unit_results_desc
|
||||||
|
{
|
||||||
|
ulonglong generated_id;
|
||||||
|
ulonglong affected_rows;
|
||||||
|
};
|
||||||
|
|
||||||
class Protocol
|
class Protocol
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
112
sql/sql_class.cc
112
sql/sql_class.cc
@ -1375,6 +1375,7 @@ void THD::init()
|
|||||||
|
|
||||||
apc_target.init(&LOCK_thd_kill);
|
apc_target.init(&LOCK_thd_kill);
|
||||||
gap_tracker_data.init();
|
gap_tracker_data.init();
|
||||||
|
unit_results= NULL;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8325,6 +8326,117 @@ bool Discrete_intervals_list::append(Discrete_interval *new_interval)
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
indicate that unit result has to be reported
|
||||||
|
*/
|
||||||
|
bool THD::need_report_unit_results()
|
||||||
|
{
|
||||||
|
return unit_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initialize unit result array
|
||||||
|
*/
|
||||||
|
bool THD::init_collecting_unit_results()
|
||||||
|
{
|
||||||
|
if (!unit_results)
|
||||||
|
{
|
||||||
|
void *buff;
|
||||||
|
|
||||||
|
if (!(my_multi_malloc(PSI_NOT_INSTRUMENTED, MYF(MY_WME), &unit_results, sizeof(DYNAMIC_ARRAY),
|
||||||
|
&buff, sizeof(unit_results_desc) * 10,
|
||||||
|
NullS)) ||
|
||||||
|
my_init_dynamic_array2(PSI_INSTRUMENT_ME, unit_results, sizeof(unit_results_desc),
|
||||||
|
buff, 10, 100, MYF(MY_WME)))
|
||||||
|
{
|
||||||
|
if (unit_results)
|
||||||
|
my_free(unit_results);
|
||||||
|
unit_results= NULL;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
remove unit result array
|
||||||
|
*/
|
||||||
|
void THD::stop_collecting_unit_results()
|
||||||
|
{
|
||||||
|
if (unit_results)
|
||||||
|
{
|
||||||
|
delete_dynamic(unit_results);
|
||||||
|
my_free(unit_results);
|
||||||
|
unit_results= NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add a unitary result to collection
|
||||||
|
*/
|
||||||
|
bool THD::collect_unit_results(ulonglong id, ulonglong affected_rows)
|
||||||
|
{
|
||||||
|
if (unit_results)
|
||||||
|
{
|
||||||
|
unit_results_desc el;
|
||||||
|
el.generated_id= id;
|
||||||
|
el.affected_rows= affected_rows;
|
||||||
|
if (insert_dynamic(unit_results, &el))
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Write unitary result result-set WITHOUT ending EOF/OK_Packet to socket.
|
||||||
|
*/
|
||||||
|
bool THD::report_collected_unit_results()
|
||||||
|
{
|
||||||
|
if (unit_results)
|
||||||
|
{
|
||||||
|
List<Item> field_list;
|
||||||
|
MEM_ROOT tmp_mem_root;
|
||||||
|
Query_arena arena(&tmp_mem_root, Query_arena::STMT_INITIALIZED), backup;
|
||||||
|
|
||||||
|
init_alloc_root(PSI_NOT_INSTRUMENTED, arena.mem_root, 2048, 4096, MYF(0));
|
||||||
|
set_n_backup_active_arena(&arena, &backup);
|
||||||
|
DBUG_ASSERT(mem_root == &tmp_mem_root);
|
||||||
|
|
||||||
|
field_list.push_back(new (mem_root)
|
||||||
|
Item_int(this, "Id", 0, MY_INT64_NUM_DECIMAL_DIGITS),
|
||||||
|
mem_root);
|
||||||
|
field_list.push_back(new (mem_root)
|
||||||
|
Item_int(this, "Affected_rows", 0, MY_INT64_NUM_DECIMAL_DIGITS),
|
||||||
|
mem_root);
|
||||||
|
|
||||||
|
if (protocol_binary.send_result_set_metadata(&field_list,
|
||||||
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for (ulonglong i= 0; i < unit_results->elements; i++)
|
||||||
|
{
|
||||||
|
unit_results_desc *last=
|
||||||
|
(unit_results_desc *)dynamic_array_ptr(unit_results, i);
|
||||||
|
protocol_binary.prepare_for_resend();
|
||||||
|
protocol_binary.store_longlong(last->generated_id, TRUE);
|
||||||
|
protocol_binary.store_longlong(last->affected_rows, TRUE);
|
||||||
|
if (protocol_binary.write())
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
restore_active_arena(&arena, &backup);
|
||||||
|
DBUG_ASSERT(arena.mem_root == &tmp_mem_root);
|
||||||
|
// no need free Items because they was only constants
|
||||||
|
free_root(arena.mem_root, MYF(0));
|
||||||
|
stop_collecting_unit_results();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void AUTHID::copy(MEM_ROOT *mem_root, const LEX_CSTRING *user_name,
|
void AUTHID::copy(MEM_ROOT *mem_root, const LEX_CSTRING *user_name,
|
||||||
const LEX_CSTRING *host_name)
|
const LEX_CSTRING *host_name)
|
||||||
|
@ -5953,6 +5953,14 @@ public:
|
|||||||
return (lex->sphead != 0 &&
|
return (lex->sphead != 0 &&
|
||||||
!(in_sub_stmt & (SUB_STMT_FUNCTION | SUB_STMT_TRIGGER)));
|
!(in_sub_stmt & (SUB_STMT_FUNCTION | SUB_STMT_TRIGGER)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Data and methods for bulk multiple unit result reporting */
|
||||||
|
DYNAMIC_ARRAY *unit_results;
|
||||||
|
void stop_collecting_unit_results();
|
||||||
|
bool collect_unit_results(ulonglong id, ulonglong affected_rows);
|
||||||
|
bool need_report_unit_results();
|
||||||
|
bool report_collected_unit_results();
|
||||||
|
bool init_collecting_unit_results();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -841,7 +841,7 @@ bool Sql_cmd_delete::delete_from_single_table(THD *thd)
|
|||||||
|
|
||||||
if (likely(!error))
|
if (likely(!error))
|
||||||
{
|
{
|
||||||
deleted++;
|
deleted++;
|
||||||
if (!delete_history && table->triggers &&
|
if (!delete_history && table->triggers &&
|
||||||
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
|
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
|
||||||
TRG_ACTION_AFTER, FALSE))
|
TRG_ACTION_AFTER, FALSE))
|
||||||
@ -849,15 +849,15 @@ bool Sql_cmd_delete::delete_from_single_table(THD *thd)
|
|||||||
error= 1;
|
error= 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!--limit && using_limit)
|
if (!--limit && using_limit)
|
||||||
{
|
{
|
||||||
error= -1;
|
error= -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
table->file->print_error(error,
|
table->file->print_error(error,
|
||||||
MYF(thd->lex->ignore ? ME_WARNING : 0));
|
MYF(thd->lex->ignore ? ME_WARNING : 0));
|
||||||
if (thd->is_error())
|
if (thd->is_error())
|
||||||
{
|
{
|
||||||
@ -947,7 +947,7 @@ cleanup:
|
|||||||
|
|
||||||
if (log_result > 0)
|
if (log_result > 0)
|
||||||
{
|
{
|
||||||
error=1;
|
error=1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -959,6 +959,8 @@ cleanup:
|
|||||||
if (thd->lex->analyze_stmt)
|
if (thd->lex->analyze_stmt)
|
||||||
goto send_nothing_and_leave;
|
goto send_nothing_and_leave;
|
||||||
|
|
||||||
|
thd->collect_unit_results(0, deleted);
|
||||||
|
|
||||||
if (returning)
|
if (returning)
|
||||||
result->send_eof();
|
result->send_eof();
|
||||||
else
|
else
|
||||||
|
@ -470,6 +470,7 @@ void upgrade_lock_type(THD *thd, thr_lock_type *lock_type,
|
|||||||
the statement indirectly via a stored function or trigger:
|
the statement indirectly via a stored function or trigger:
|
||||||
if it is used, that will lead to a deadlock between the
|
if it is used, that will lead to a deadlock between the
|
||||||
client connection and the delayed thread.
|
client connection and the delayed thread.
|
||||||
|
- client explicitly ask to retrieve unitary changes
|
||||||
*/
|
*/
|
||||||
if (specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE) ||
|
if (specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE) ||
|
||||||
thd->variables.max_insert_delayed_threads == 0 ||
|
thd->variables.max_insert_delayed_threads == 0 ||
|
||||||
@ -480,6 +481,14 @@ void upgrade_lock_type(THD *thd, thr_lock_type *lock_type,
|
|||||||
*lock_type= TL_WRITE;
|
*lock_type= TL_WRITE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* client explicitly asked to retrieved each affected rows and insert ids */
|
||||||
|
if (thd->need_report_unit_results())
|
||||||
|
{
|
||||||
|
*lock_type= TL_WRITE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (thd->slave_thread)
|
if (thd->slave_thread)
|
||||||
{
|
{
|
||||||
/* Try concurrent insert */
|
/* Try concurrent insert */
|
||||||
@ -717,6 +726,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
|
|||||||
uint value_count;
|
uint value_count;
|
||||||
/* counter of iteration in bulk PS operation*/
|
/* counter of iteration in bulk PS operation*/
|
||||||
ulonglong iteration= 0;
|
ulonglong iteration= 0;
|
||||||
|
ulonglong last_affected_rows= 0;
|
||||||
ulonglong id;
|
ulonglong id;
|
||||||
COPY_INFO info;
|
COPY_INFO info;
|
||||||
TABLE *table= 0;
|
TABLE *table= 0;
|
||||||
@ -931,7 +941,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
|
|||||||
functions or invokes triggers since they may access
|
functions or invokes triggers since they may access
|
||||||
to the same table and therefore should not see its
|
to the same table and therefore should not see its
|
||||||
inconsistent state created by this optimization.
|
inconsistent state created by this optimization.
|
||||||
So we call start_bulk_insert to perform nesessary checks on
|
So we call start_bulk_insert to perform necessary checks on
|
||||||
values_list.elements, and - if nothing else - to initialize
|
values_list.elements, and - if nothing else - to initialize
|
||||||
the code to make the call of end_bulk_insert() below safe.
|
the code to make the call of end_bulk_insert() below safe.
|
||||||
*/
|
*/
|
||||||
@ -1159,6 +1169,17 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
|
|||||||
}
|
}
|
||||||
its.rewind();
|
its.rewind();
|
||||||
iteration++;
|
iteration++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Save affected rows and insert id when collecting using results
|
||||||
|
*/
|
||||||
|
ulonglong new_affected_rows= info.copied + info.deleted +
|
||||||
|
((thd->client_capabilities & CLIENT_FOUND_ROWS) ?
|
||||||
|
info.touched : info.updated);
|
||||||
|
thd->collect_unit_results(
|
||||||
|
table->file->insert_id_for_cur_row,
|
||||||
|
new_affected_rows - last_affected_rows);
|
||||||
|
last_affected_rows = new_affected_rows;
|
||||||
} while (bulk_parameters_iterations(thd));
|
} while (bulk_parameters_iterations(thd));
|
||||||
|
|
||||||
values_loop_end:
|
values_loop_end:
|
||||||
@ -1342,7 +1363,7 @@ values_loop_end:
|
|||||||
Client expects an EOF/OK packet if result set metadata was sent. If
|
Client expects an EOF/OK packet if result set metadata was sent. If
|
||||||
LEX::has_returning and the statement returns result set
|
LEX::has_returning and the statement returns result set
|
||||||
we send EOF which is the indicator of the end of the row stream.
|
we send EOF which is the indicator of the end of the row stream.
|
||||||
Oherwise we send an OK packet i.e when the statement returns only the
|
Otherwise we send an OK packet i.e when the statement returns only the
|
||||||
status information
|
status information
|
||||||
*/
|
*/
|
||||||
if (returning)
|
if (returning)
|
||||||
|
@ -223,7 +223,7 @@ public:
|
|||||||
uchar *packet_arg, uchar *packet_end_arg);
|
uchar *packet_arg, uchar *packet_end_arg);
|
||||||
bool execute_bulk_loop(String *expanded_query,
|
bool execute_bulk_loop(String *expanded_query,
|
||||||
bool open_cursor,
|
bool open_cursor,
|
||||||
uchar *packet_arg, uchar *packet_end_arg);
|
uchar *packet_arg, uchar *packet_end_arg, bool multiple_ok_request);
|
||||||
bool execute_server_runnable(Server_runnable *server_runnable);
|
bool execute_server_runnable(Server_runnable *server_runnable);
|
||||||
my_bool set_bulk_parameters(bool reset);
|
my_bool set_bulk_parameters(bool reset);
|
||||||
bool bulk_iterations() { return iterations; };
|
bool bulk_iterations() { return iterations; };
|
||||||
@ -3099,7 +3099,8 @@ static void mysql_stmt_execute_common(THD *thd,
|
|||||||
uchar *packet_end,
|
uchar *packet_end,
|
||||||
ulong cursor_flags,
|
ulong cursor_flags,
|
||||||
bool iteration,
|
bool iteration,
|
||||||
bool types);
|
bool types,
|
||||||
|
bool send_all_ok);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
COM_STMT_EXECUTE handler: execute a previously prepared statement.
|
COM_STMT_EXECUTE handler: execute a previously prepared statement.
|
||||||
@ -3137,7 +3138,7 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
|
|||||||
packet+= 9; /* stmt_id + 5 bytes of flags */
|
packet+= 9; /* stmt_id + 5 bytes of flags */
|
||||||
|
|
||||||
mysql_stmt_execute_common(thd, stmt_id, packet, packet_end, flags, FALSE,
|
mysql_stmt_execute_common(thd, stmt_id, packet, packet_end, flags, FALSE,
|
||||||
FALSE);
|
FALSE, FALSE);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3164,9 +3165,9 @@ void mysqld_stmt_bulk_execute(THD *thd, char *packet_arg, uint packet_length)
|
|||||||
uchar *packet= (uchar*)packet_arg; // GCC 4.0.1 workaround
|
uchar *packet= (uchar*)packet_arg; // GCC 4.0.1 workaround
|
||||||
DBUG_ENTER("mysqld_stmt_execute_bulk");
|
DBUG_ENTER("mysqld_stmt_execute_bulk");
|
||||||
|
|
||||||
const uint packet_header_lenght= 4 + 2; //ID & 2 bytes of flags
|
const uint packet_header_length= 4 + 2; //ID & 2 bytes of flags
|
||||||
|
|
||||||
if (packet_length < packet_header_lenght)
|
if (packet_length < packet_header_length)
|
||||||
{
|
{
|
||||||
my_error(ER_MALFORMED_PACKET, MYF(0));
|
my_error(ER_MALFORMED_PACKET, MYF(0));
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -3185,7 +3186,7 @@ void mysqld_stmt_bulk_execute(THD *thd, char *packet_arg, uint packet_length)
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
/* Check for implemented parameters */
|
/* Check for implemented parameters */
|
||||||
if (flags & (~STMT_BULK_FLAG_CLIENT_SEND_TYPES))
|
if (flags & (~(STMT_BULK_FLAG_CLIENT_SEND_TYPES | STMT_BULK_FLAG_SEND_UNIT_RESULTS)))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error", ("unsupported bulk execute flags %x", flags));
|
DBUG_PRINT("error", ("unsupported bulk execute flags %x", flags));
|
||||||
my_error(ER_UNSUPPORTED_PS, MYF(0));
|
my_error(ER_UNSUPPORTED_PS, MYF(0));
|
||||||
@ -3193,9 +3194,10 @@ void mysqld_stmt_bulk_execute(THD *thd, char *packet_arg, uint packet_length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* stmt id and two bytes of flags */
|
/* stmt id and two bytes of flags */
|
||||||
packet+= packet_header_lenght;
|
packet+= packet_header_length;
|
||||||
mysql_stmt_execute_common(thd, stmt_id, packet, packet_end, 0, TRUE,
|
mysql_stmt_execute_common(thd, stmt_id, packet, packet_end, 0, TRUE,
|
||||||
(flags & STMT_BULK_FLAG_CLIENT_SEND_TYPES));
|
(flags & STMT_BULK_FLAG_CLIENT_SEND_TYPES),
|
||||||
|
(flags & STMT_BULK_FLAG_SEND_UNIT_RESULTS));
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3283,13 +3285,14 @@ stmt_execute_packet_sanity_check(Prepared_statement *stmt,
|
|||||||
/**
|
/**
|
||||||
Common part of prepared statement execution
|
Common part of prepared statement execution
|
||||||
|
|
||||||
@param thd THD handle
|
@param thd THD handle
|
||||||
@param stmt_id id of the prepared statement
|
@param stmt_id id of the prepared statement
|
||||||
@param paket packet with parameters to bind
|
@param paket packet with parameters to bind
|
||||||
@param packet_end pointer to the byte after parameters end
|
@param packet_end pointer to the byte after parameters end
|
||||||
@param cursor_flags cursor flags
|
@param cursor_flags cursor flags
|
||||||
@param bulk_op id it bulk operation
|
@param bulk_op is it bulk operation
|
||||||
@param read_types flag say that types muast been read
|
@param read_types flag say that types must been read
|
||||||
|
@param send_unit_results send a result-set with all insert IDs and affected rows
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void mysql_stmt_execute_common(THD *thd,
|
static void mysql_stmt_execute_common(THD *thd,
|
||||||
@ -3298,7 +3301,8 @@ static void mysql_stmt_execute_common(THD *thd,
|
|||||||
uchar *packet_end,
|
uchar *packet_end,
|
||||||
ulong cursor_flags,
|
ulong cursor_flags,
|
||||||
bool bulk_op,
|
bool bulk_op,
|
||||||
bool read_types)
|
bool read_types,
|
||||||
|
bool send_unit_results)
|
||||||
{
|
{
|
||||||
/* Query text for binary, general or slow log, if any of them is open */
|
/* Query text for binary, general or slow log, if any of them is open */
|
||||||
String expanded_query;
|
String expanded_query;
|
||||||
@ -3367,7 +3371,7 @@ static void mysql_stmt_execute_common(THD *thd,
|
|||||||
if (!bulk_op)
|
if (!bulk_op)
|
||||||
stmt->execute_loop(&expanded_query, open_cursor, packet, packet_end);
|
stmt->execute_loop(&expanded_query, open_cursor, packet, packet_end);
|
||||||
else
|
else
|
||||||
stmt->execute_bulk_loop(&expanded_query, open_cursor, packet, packet_end);
|
stmt->execute_bulk_loop(&expanded_query, open_cursor, packet, packet_end, send_unit_results);
|
||||||
|
|
||||||
thd->cur_stmt= save_cur_stmt;
|
thd->cur_stmt= save_cur_stmt;
|
||||||
thd->protocol= save_protocol;
|
thd->protocol= save_protocol;
|
||||||
@ -3482,7 +3486,7 @@ void mysql_sql_stmt_execute(THD *thd)
|
|||||||
thd->free_items(); // Free items created by execute_loop()
|
thd->free_items(); // Free items created by execute_loop()
|
||||||
/*
|
/*
|
||||||
Now restore the "external" (e.g. "SET STATEMENT") Item list.
|
Now restore the "external" (e.g. "SET STATEMENT") Item list.
|
||||||
It will be freed normaly in THD::cleanup_after_query().
|
It will be freed normally in THD::cleanup_after_query().
|
||||||
*/
|
*/
|
||||||
thd->free_list= free_list_backup;
|
thd->free_list= free_list_backup;
|
||||||
|
|
||||||
@ -4551,7 +4555,8 @@ bool
|
|||||||
Prepared_statement::execute_bulk_loop(String *expanded_query,
|
Prepared_statement::execute_bulk_loop(String *expanded_query,
|
||||||
bool open_cursor,
|
bool open_cursor,
|
||||||
uchar *packet_arg,
|
uchar *packet_arg,
|
||||||
uchar *packet_end_arg)
|
uchar *packet_end_arg,
|
||||||
|
bool send_unit_results)
|
||||||
{
|
{
|
||||||
Reprepare_observer reprepare_observer;
|
Reprepare_observer reprepare_observer;
|
||||||
unsigned char *readbuff= NULL;
|
unsigned char *readbuff= NULL;
|
||||||
@ -4584,9 +4589,16 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
|
|||||||
my_error(ER_UNSUPPORTED_PS, MYF(0));
|
my_error(ER_UNSUPPORTED_PS, MYF(0));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (send_unit_results && thd->init_collecting_unit_results())
|
||||||
|
{
|
||||||
|
DBUG_PRINT("error", ("Error initializing array."));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Here second buffer for not optimized commands,
|
Here second buffer for not optimized commands,
|
||||||
optimized commands do it inside thier internal loop.
|
optimized commands do it inside their internal loop.
|
||||||
*/
|
*/
|
||||||
if (!(sql_command_flags() & CF_PS_ARRAY_BINDING_OPTIMIZED) &&
|
if (!(sql_command_flags() & CF_PS_ARRAY_BINDING_OPTIMIZED) &&
|
||||||
this->lex->has_returning())
|
this->lex->has_returning())
|
||||||
@ -4619,7 +4631,7 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Here we set parameters for not optimized commands,
|
Here we set parameters for not optimized commands,
|
||||||
optimized commands do it inside thier internal loop.
|
optimized commands do it inside their internal loop.
|
||||||
*/
|
*/
|
||||||
if (!(sql_command_flags() & CF_PS_ARRAY_BINDING_OPTIMIZED))
|
if (!(sql_command_flags() & CF_PS_ARRAY_BINDING_OPTIMIZED))
|
||||||
{
|
{
|
||||||
@ -4662,7 +4674,7 @@ reexecute:
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Re-execution success is unlikely after an error from
|
Re-execution success is unlikely after an error from
|
||||||
wsrep_after_statement(), so retrun error immediately.
|
wsrep_after_statement(), so return error immediately.
|
||||||
*/
|
*/
|
||||||
thd->get_stmt_da()->reset_diagnostics_area();
|
thd->get_stmt_da()->reset_diagnostics_area();
|
||||||
wsrep_override_error(thd, thd->wsrep_cs().current_error(),
|
wsrep_override_error(thd, thd->wsrep_cs().current_error(),
|
||||||
|
@ -1250,6 +1250,9 @@ update_end:
|
|||||||
ER_THD(thd, ER_UPDATE_INFO_WITH_SYSTEM_VERSIONING),
|
ER_THD(thd, ER_UPDATE_INFO_WITH_SYSTEM_VERSIONING),
|
||||||
(ulong) found, (ulong) updated, (ulong) rows_inserted,
|
(ulong) found, (ulong) updated, (ulong) rows_inserted,
|
||||||
(ulong) thd->get_stmt_da()->current_statement_warn_count());
|
(ulong) thd->get_stmt_da()->current_statement_warn_count());
|
||||||
|
thd->collect_unit_results(
|
||||||
|
id,
|
||||||
|
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated);
|
||||||
my_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
|
my_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
|
||||||
id, buff);
|
id, buff);
|
||||||
DBUG_PRINT("info",("%ld records updated", (long) updated));
|
DBUG_PRINT("info",("%ld records updated", (long) updated));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user