merge 10.5 to 10.6
This commit is contained in:
commit
e7f4daf88c
@ -1,4 +1,5 @@
|
|||||||
-- require include/have_pool_of_threads.require
|
--source include/not_aix.inc
|
||||||
|
--require include/have_pool_of_threads.require
|
||||||
disable_query_log;
|
disable_query_log;
|
||||||
show variables like 'thread_handling';
|
show variables like 'thread_handling';
|
||||||
enable_query_log;
|
enable_query_log;
|
||||||
|
@ -1 +1,2 @@
|
|||||||
# run with and without threadpool
|
# run with and without threadpool
|
||||||
|
--source include/not_aix.inc
|
||||||
|
@ -496,3 +496,22 @@ natural right outer join t3;
|
|||||||
drop table t1,t2,t3;
|
drop table t1,t2,t3;
|
||||||
set optimizer_prune_level=@mdev4270_opl;
|
set optimizer_prune_level=@mdev4270_opl;
|
||||||
set optimizer_search_depth=@mdev4270_osd;
|
set optimizer_search_depth=@mdev4270_osd;
|
||||||
|
#
|
||||||
|
# Bug #20939184:INNODB: UNLOCK ROW COULD NOT FIND A 2 MODE LOCK ON THE
|
||||||
|
# RECORD
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (c1 INT, c2 INT, c3 INT, PRIMARY KEY (c1,c2) ) engine=innodb;
|
||||||
|
CREATE TABLE t2 (c1 INT, c2 INT, c3 INT, PRIMARY KEY (c1), KEY (c2)) engine=innodb;
|
||||||
|
INSERT INTO t1 VALUES (1,2,3),(2,3,4),(3,4,5);
|
||||||
|
INSERT INTO t2 SELECT * FROM t1;
|
||||||
|
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||||
|
START TRANSACTION;
|
||||||
|
SELECT * FROM t1 LEFT JOIN t2 ON t1.c2=t2.c2 AND t2.c1=1 FOR UPDATE;
|
||||||
|
c1 c2 c3 c1 c2 c3
|
||||||
|
1 2 3 1 2 3
|
||||||
|
2 3 4 NULL NULL NULL
|
||||||
|
3 4 5 NULL NULL NULL
|
||||||
|
UPDATE t1 LEFT JOIN t2 ON t1.c1 = t2.c2 AND t2.c1 = 3 SET t1.c3 = RAND()*10;
|
||||||
|
COMMIT;
|
||||||
|
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
@ -374,3 +374,20 @@ drop table t1,t2,t3;
|
|||||||
set optimizer_prune_level=@mdev4270_opl;
|
set optimizer_prune_level=@mdev4270_opl;
|
||||||
set optimizer_search_depth=@mdev4270_osd;
|
set optimizer_search_depth=@mdev4270_osd;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug #20939184:INNODB: UNLOCK ROW COULD NOT FIND A 2 MODE LOCK ON THE
|
||||||
|
--echo # RECORD
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 (c1 INT, c2 INT, c3 INT, PRIMARY KEY (c1,c2) ) engine=innodb;
|
||||||
|
CREATE TABLE t2 (c1 INT, c2 INT, c3 INT, PRIMARY KEY (c1), KEY (c2)) engine=innodb;
|
||||||
|
INSERT INTO t1 VALUES (1,2,3),(2,3,4),(3,4,5);
|
||||||
|
INSERT INTO t2 SELECT * FROM t1;
|
||||||
|
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||||
|
START TRANSACTION;
|
||||||
|
#unlocks rows in table t2 where c1 = 1
|
||||||
|
SELECT * FROM t1 LEFT JOIN t2 ON t1.c2=t2.c2 AND t2.c1=1 FOR UPDATE;
|
||||||
|
UPDATE t1 LEFT JOIN t2 ON t1.c1 = t2.c2 AND t2.c1 = 3 SET t1.c3 = RAND()*10;
|
||||||
|
COMMIT;
|
||||||
|
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
source include/not_embedded.inc;
|
source include/not_embedded.inc;
|
||||||
source include/not_windows.inc;
|
source include/not_windows.inc;
|
||||||
|
source include/not_aix.inc;
|
||||||
|
|
||||||
# All these tests refer to configuration files that do not exist
|
# All these tests refer to configuration files that do not exist
|
||||||
|
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result
|
||||||
|
index 7b0ce27ead3..38176dcaa86 100644
|
||||||
|
--- a/mysql-test/main/mysqld--help.result
|
||||||
|
+++ b/mysql-test/main/mysqld--help.result
|
||||||
|
@@ -1301,8 +1301,6 @@ The following specify which files/extra groups are read (specified before remain
|
||||||
|
WHERE clause, or a LIMIT clause, or else they will
|
||||||
|
aborted. Prevents the common mistake of accidentally
|
||||||
|
deleting or updating every row in a table.
|
||||||
|
- --stack-trace Print a symbolic stack trace on failure
|
||||||
|
- (Defaults to on; use --skip-stack-trace to disable.)
|
||||||
|
--standard-compliant-cte
|
||||||
|
Allow only CTEs compliant to SQL standard
|
||||||
|
(Defaults to on; use --skip-standard-compliant-cte to disable.)
|
||||||
|
@@ -1367,39 +1365,6 @@ The following specify which files/extra groups are read (specified before remain
|
||||||
|
--thread-cache-size=#
|
||||||
|
How many threads we should keep in a cache for reuse.
|
||||||
|
These are freed after 5 minutes of idle time
|
||||||
|
- --thread-pool-dedicated-listener
|
||||||
|
- If set to 1,listener thread will not pick up queries
|
||||||
|
- --thread-pool-exact-stats
|
||||||
|
- If set to 1, provides better statistics in
|
||||||
|
- information_schema threadpool tables
|
||||||
|
- --thread-pool-idle-timeout=#
|
||||||
|
- Timeout in seconds for an idle thread in the thread
|
||||||
|
- pool.Worker thread will be shut down after timeout
|
||||||
|
- --thread-pool-max-threads=#
|
||||||
|
- Maximum allowed number of worker threads in the thread
|
||||||
|
- pool
|
||||||
|
- --thread-pool-oversubscribe=#
|
||||||
|
- How many additional active worker threads in a group are
|
||||||
|
- allowed.
|
||||||
|
- --thread-pool-prio-kickup-timer=#
|
||||||
|
- The number of milliseconds before a dequeued low-priority
|
||||||
|
- statement is moved to the high-priority queue
|
||||||
|
- --thread-pool-priority=name
|
||||||
|
- Threadpool priority. High priority connections usually
|
||||||
|
- start executing earlier than low priority.If priority set
|
||||||
|
- to 'auto', the the actual priority(low or high) is
|
||||||
|
- determined based on whether or not connection is inside
|
||||||
|
- transaction.
|
||||||
|
- --thread-pool-size=#
|
||||||
|
- Number of thread groups in the pool. This parameter is
|
||||||
|
- roughly equivalent to maximum number of concurrently
|
||||||
|
- executing threads (threads in a waiting state do not
|
||||||
|
- count as executing).
|
||||||
|
- --thread-pool-stall-limit=#
|
||||||
|
- Maximum query execution time in milliseconds,before an
|
||||||
|
- executing non-yielding thread is considered stalled.If a
|
||||||
|
- worker thread is stalled, additional worker thread may be
|
||||||
|
- created to handle remaining clients.
|
||||||
|
--thread-stack=# The stack size for each thread
|
||||||
|
--time-format=name The TIME format (ignored)
|
||||||
|
--tls-version=name TLS protocol version for secure connections.. Any
|
||||||
|
@@ -1788,7 +1753,6 @@ slow-query-log FALSE
|
||||||
|
sort-buffer-size 2097152
|
||||||
|
sql-mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
|
||||||
|
sql-safe-updates FALSE
|
||||||
|
-stack-trace TRUE
|
||||||
|
standard-compliant-cte TRUE
|
||||||
|
stored-program-cache 256
|
||||||
|
strict-password-validation TRUE
|
||||||
|
@@ -1807,14 +1771,6 @@ tcp-keepalive-probes 0
|
||||||
|
tcp-keepalive-time 0
|
||||||
|
tcp-nodelay TRUE
|
||||||
|
thread-cache-size 151
|
||||||
|
-thread-pool-dedicated-listener FALSE
|
||||||
|
-thread-pool-exact-stats FALSE
|
||||||
|
-thread-pool-idle-timeout 60
|
||||||
|
-thread-pool-max-threads 65536
|
||||||
|
-thread-pool-oversubscribe 3
|
||||||
|
-thread-pool-prio-kickup-timer 1000
|
||||||
|
-thread-pool-priority auto
|
||||||
|
-thread-pool-stall-limit 500
|
||||||
|
thread-stack 299008
|
||||||
|
time-format %H:%i:%s
|
||||||
|
tmp-disk-table-size 18446744073709551615
|
@ -1 +1 @@
|
|||||||
--skip-stack-trace --skip-core-file
|
--loose-skip-stack-trace --skip-core-file
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# uint global
|
# uint global
|
||||||
--source include/not_windows.inc
|
--source include/not_windows.inc
|
||||||
--source include/not_embedded.inc
|
--source include/not_embedded.inc
|
||||||
|
--source include/not_aix.inc
|
||||||
SET @start_global_value = @@global.thread_pool_idle_timeout;
|
SET @start_global_value = @@global.thread_pool_idle_timeout;
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
--source include/not_windows.inc
|
--source include/not_windows.inc
|
||||||
--source include/not_embedded.inc
|
--source include/not_embedded.inc
|
||||||
|
--source include/not_aix.inc
|
||||||
|
|
||||||
SET @global=@@global.thread_pool_idle_timeout;
|
SET @global=@@global.thread_pool_idle_timeout;
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# uint global
|
# uint global
|
||||||
--source include/not_embedded.inc
|
--source include/not_embedded.inc
|
||||||
|
--source include/not_aix.inc
|
||||||
SET @start_global_value = @@global.thread_pool_max_threads;
|
SET @start_global_value = @@global.thread_pool_max_threads;
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# uint global
|
# uint global
|
||||||
--source include/not_embedded.inc
|
--source include/not_embedded.inc
|
||||||
|
--source include/not_aix.inc
|
||||||
|
|
||||||
SET @global=@@global.thread_pool_max_threads;
|
SET @global=@@global.thread_pool_max_threads;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# uint global
|
# uint global
|
||||||
--source include/not_embedded.inc
|
--source include/not_embedded.inc
|
||||||
--source include/windows.inc
|
--source include/windows.inc
|
||||||
|
--source include/not_aix.inc
|
||||||
SET @start_global_value = @@global.thread_pool_min_threads;
|
SET @start_global_value = @@global.thread_pool_min_threads;
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# uint global
|
# uint global
|
||||||
--source include/not_windows.inc
|
--source include/not_windows.inc
|
||||||
--source include/not_embedded.inc
|
--source include/not_embedded.inc
|
||||||
|
--source include/not_aix.inc
|
||||||
SET @start_global_value = @@global.thread_pool_oversubscribe;
|
SET @start_global_value = @@global.thread_pool_oversubscribe;
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
--source include/not_windows.inc
|
--source include/not_windows.inc
|
||||||
--source include/not_embedded.inc
|
--source include/not_embedded.inc
|
||||||
|
--source include/not_aix.inc
|
||||||
|
|
||||||
SET @global=@@global.thread_pool_oversubscribe;
|
SET @global=@@global.thread_pool_oversubscribe;
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# uint global
|
# uint global
|
||||||
--source include/not_embedded.inc
|
--source include/not_embedded.inc
|
||||||
|
--source include/not_aix.inc
|
||||||
SET @start_global_value = @@global.thread_pool_stall_limit;
|
SET @start_global_value = @@global.thread_pool_stall_limit;
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# uint global
|
# uint global
|
||||||
--source include/not_embedded.inc
|
--source include/not_embedded.inc
|
||||||
|
--source include/not_aix.inc
|
||||||
|
|
||||||
SET @global=@@global.thread_pool_stall_limit;
|
SET @global=@@global.thread_pool_stall_limit;
|
||||||
|
|
||||||
|
@ -179,14 +179,26 @@ my_bool my_net_init(NET *net, Vio *vio, void *thd, uint my_flags)
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocate and assign new net buffer
|
||||||
|
|
||||||
|
@note In case of error the old buffer left
|
||||||
|
|
||||||
|
@retval TRUE error
|
||||||
|
@retval FALSE success
|
||||||
|
*/
|
||||||
|
|
||||||
my_bool net_allocate_new_packet(NET *net, void *thd, uint my_flags)
|
my_bool net_allocate_new_packet(NET *net, void *thd, uint my_flags)
|
||||||
{
|
{
|
||||||
|
uchar *tmp;
|
||||||
DBUG_ENTER("net_allocate_new_packet");
|
DBUG_ENTER("net_allocate_new_packet");
|
||||||
if (!(net->buff=(uchar*) my_malloc(key_memory_NET_buff,
|
if (!(tmp= (uchar*) my_malloc(key_memory_NET_buff,
|
||||||
(size_t) net->max_packet +
|
(size_t) net->max_packet +
|
||||||
NET_HEADER_SIZE + COMP_HEADER_SIZE + 1,
|
NET_HEADER_SIZE + COMP_HEADER_SIZE + 1,
|
||||||
MYF(MY_WME | my_flags))))
|
MYF(MY_WME | my_flags))))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
net->buff= tmp;
|
||||||
net->buff_end=net->buff+net->max_packet;
|
net->buff_end=net->buff+net->max_packet;
|
||||||
net->write_pos=net->read_pos = net->buff;
|
net->write_pos=net->read_pos = net->buff;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
@ -597,6 +597,7 @@ void Protocol::end_statement()
|
|||||||
thd->get_stmt_da()->get_sqlstate());
|
thd->get_stmt_da()->get_sqlstate());
|
||||||
break;
|
break;
|
||||||
case Diagnostics_area::DA_EOF:
|
case Diagnostics_area::DA_EOF:
|
||||||
|
case Diagnostics_area::DA_EOF_BULK:
|
||||||
error= send_eof(thd->server_status,
|
error= send_eof(thd->server_status,
|
||||||
thd->get_stmt_da()->statement_warn_count());
|
thd->get_stmt_da()->statement_warn_count());
|
||||||
break;
|
break;
|
||||||
|
@ -709,7 +709,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
!table->prepare_triggers_for_delete_stmt_or_event())
|
!table->prepare_triggers_for_delete_stmt_or_event())
|
||||||
will_batch= !table->file->start_bulk_delete();
|
will_batch= !table->file->start_bulk_delete();
|
||||||
|
|
||||||
if (returning)
|
/*
|
||||||
|
thd->get_stmt_da()->is_set() means first iteration of prepared statement
|
||||||
|
with array binding operation execution (non optimized so it is not
|
||||||
|
INSERT)
|
||||||
|
*/
|
||||||
|
if (returning && !thd->get_stmt_da()->is_set())
|
||||||
{
|
{
|
||||||
if (result->send_result_set_metadata(returning->item_list,
|
if (result->send_result_set_metadata(returning->item_list,
|
||||||
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
||||||
|
@ -371,7 +371,7 @@ Diagnostics_area::set_eof_status(THD *thd)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("set_eof_status");
|
DBUG_ENTER("set_eof_status");
|
||||||
/* Only allowed to report eof if has not yet reported an error */
|
/* Only allowed to report eof if has not yet reported an error */
|
||||||
DBUG_ASSERT(! is_set());
|
DBUG_ASSERT(!is_set() || (m_status == DA_EOF_BULK && is_bulk_op()));
|
||||||
/*
|
/*
|
||||||
In production, refuse to overwrite an error or a custom response
|
In production, refuse to overwrite an error or a custom response
|
||||||
with an EOF packet.
|
with an EOF packet.
|
||||||
@ -384,11 +384,23 @@ Diagnostics_area::set_eof_status(THD *thd)
|
|||||||
number of warnings, since they are not available to the client
|
number of warnings, since they are not available to the client
|
||||||
anyway.
|
anyway.
|
||||||
*/
|
*/
|
||||||
m_statement_warn_count= (thd->spcont ?
|
if (m_status == DA_EOF_BULK)
|
||||||
0 :
|
{
|
||||||
current_statement_warn_count());
|
if (!thd->spcont)
|
||||||
|
m_statement_warn_count+= current_statement_warn_count();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (thd->spcont)
|
||||||
|
{
|
||||||
|
m_statement_warn_count= 0;
|
||||||
|
m_affected_rows= 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_statement_warn_count= current_statement_warn_count();
|
||||||
|
m_status= (is_bulk_op() ? DA_EOF_BULK : DA_EOF);
|
||||||
|
}
|
||||||
|
|
||||||
m_status= DA_EOF;
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -970,6 +970,8 @@ public:
|
|||||||
DA_EOF,
|
DA_EOF,
|
||||||
/** Set whenever one calls my_ok() in PS bulk mode. */
|
/** Set whenever one calls my_ok() in PS bulk mode. */
|
||||||
DA_OK_BULK,
|
DA_OK_BULK,
|
||||||
|
/** Set whenever one calls my_eof() in PS bulk mode. */
|
||||||
|
DA_EOF_BULK,
|
||||||
/** Set whenever one calls my_error() or my_message(). */
|
/** Set whenever one calls my_error() or my_message(). */
|
||||||
DA_ERROR,
|
DA_ERROR,
|
||||||
/** Set in case of a custom response, such as one from COM_STMT_PREPARE. */
|
/** Set in case of a custom response, such as one from COM_STMT_PREPARE. */
|
||||||
@ -1029,8 +1031,11 @@ public:
|
|||||||
enum_diagnostics_status status() const { return m_status; }
|
enum_diagnostics_status status() const { return m_status; }
|
||||||
|
|
||||||
const char *message() const
|
const char *message() const
|
||||||
{ DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK ||
|
{
|
||||||
m_status == DA_OK_BULK); return m_message; }
|
DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK ||
|
||||||
|
m_status == DA_OK_BULK || m_status == DA_EOF_BULK);
|
||||||
|
return m_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint sql_errno() const
|
uint sql_errno() const
|
||||||
@ -1057,7 +1062,7 @@ public:
|
|||||||
uint statement_warn_count() const
|
uint statement_warn_count() const
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK ||
|
DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK ||
|
||||||
m_status == DA_EOF);
|
m_status == DA_EOF ||m_status == DA_EOF_BULK );
|
||||||
return m_statement_warn_count;
|
return m_statement_warn_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,6 +710,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
|
|||||||
Name_resolution_context *context;
|
Name_resolution_context *context;
|
||||||
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;
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
char *query= thd->query();
|
char *query= thd->query();
|
||||||
@ -786,7 +787,25 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
|
|||||||
|
|
||||||
/* Prepares LEX::returing_list if it is not empty */
|
/* Prepares LEX::returing_list if it is not empty */
|
||||||
if (returning)
|
if (returning)
|
||||||
|
{
|
||||||
result->prepare(returning->item_list, NULL);
|
result->prepare(returning->item_list, NULL);
|
||||||
|
if (thd->is_bulk_op())
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
It is RETURNING which needs network buffer to write result set and
|
||||||
|
it is array binfing which need network buffer to read parameters.
|
||||||
|
So we allocate yet another network buffer.
|
||||||
|
The old buffer will be freed at the end of operation.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(thd->protocol == &thd->protocol_binary);
|
||||||
|
readbuff= thd->net.buff; // old buffer
|
||||||
|
if (net_allocate_new_packet(&thd->net, thd, MYF(MY_THREAD_SPECIFIC)))
|
||||||
|
{
|
||||||
|
readbuff= NULL; // failure, net_allocate_new_packet keeps old buffer
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
context= &thd->lex->first_select_lex()->context;
|
context= &thd->lex->first_select_lex()->context;
|
||||||
/*
|
/*
|
||||||
@ -1322,7 +1341,8 @@ values_loop_end:
|
|||||||
thd->lex->current_select->save_leaf_tables(thd);
|
thd->lex->current_select->save_leaf_tables(thd);
|
||||||
thd->lex->current_select->first_cond_optimization= 0;
|
thd->lex->current_select->first_cond_optimization= 0;
|
||||||
}
|
}
|
||||||
|
if (readbuff)
|
||||||
|
my_free(readbuff);
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
abort:
|
abort:
|
||||||
@ -1336,6 +1356,8 @@ abort:
|
|||||||
if (!joins_freed)
|
if (!joins_freed)
|
||||||
free_underlaid_joins(thd, thd->lex->first_select_lex());
|
free_underlaid_joins(thd, thd->lex->first_select_lex());
|
||||||
thd->abort_on_warning= 0;
|
thd->abort_on_warning= 0;
|
||||||
|
if (readbuff)
|
||||||
|
my_free(readbuff);
|
||||||
DBUG_RETURN(retval);
|
DBUG_RETURN(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -903,6 +903,9 @@ static bool insert_bulk_params(Prepared_statement *stmt,
|
|||||||
case STMT_INDICATOR_IGNORE:
|
case STMT_INDICATOR_IGNORE:
|
||||||
param->set_ignore();
|
param->set_ignore();
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -4680,6 +4683,7 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
|
|||||||
uchar *packet_end_arg)
|
uchar *packet_end_arg)
|
||||||
{
|
{
|
||||||
Reprepare_observer reprepare_observer;
|
Reprepare_observer reprepare_observer;
|
||||||
|
unsigned char *readbuff= NULL;
|
||||||
bool error= 0;
|
bool error= 0;
|
||||||
packet= packet_arg;
|
packet= packet_arg;
|
||||||
packet_end= packet_end_arg;
|
packet_end= packet_end_arg;
|
||||||
@ -4693,24 +4697,37 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
|
|||||||
if (state == Query_arena::STMT_ERROR)
|
if (state == Query_arena::STMT_ERROR)
|
||||||
{
|
{
|
||||||
my_message(last_errno, last_error, MYF(0));
|
my_message(last_errno, last_error, MYF(0));
|
||||||
thd->set_bulk_execution(0);
|
goto err;
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
/* Check for non zero parameter count*/
|
/* Check for non zero parameter count*/
|
||||||
if (param_count == 0)
|
if (param_count == 0)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error", ("Statement with no parameters for bulk execution."));
|
DBUG_PRINT("error", ("Statement with no parameters for bulk execution."));
|
||||||
my_error(ER_UNSUPPORTED_PS, MYF(0));
|
my_error(ER_UNSUPPORTED_PS, MYF(0));
|
||||||
thd->set_bulk_execution(0);
|
goto err;
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(sql_command_flags[lex->sql_command] & CF_PS_ARRAY_BINDING_SAFE))
|
if (!(sql_command_flags[lex->sql_command] & CF_PS_ARRAY_BINDING_SAFE))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error", ("Command is not supported in bulk execution."));
|
DBUG_PRINT("error", ("Command is not supported in bulk execution."));
|
||||||
my_error(ER_UNSUPPORTED_PS, MYF(0));
|
my_error(ER_UNSUPPORTED_PS, MYF(0));
|
||||||
thd->set_bulk_execution(0);
|
goto err;
|
||||||
return TRUE;
|
}
|
||||||
|
/*
|
||||||
|
Here second buffer for not optimized commands,
|
||||||
|
optimized commands do it inside thier internal loop.
|
||||||
|
*/
|
||||||
|
if (!(sql_command_flags[lex->sql_command] & CF_PS_ARRAY_BINDING_OPTIMIZED) &&
|
||||||
|
this->lex->has_returning())
|
||||||
|
{
|
||||||
|
// Above check can be true for SELECT in future
|
||||||
|
DBUG_ASSERT(lex->sql_command != SQLCOM_SELECT);
|
||||||
|
readbuff= thd->net.buff; // old buffer
|
||||||
|
if (net_allocate_new_packet(&thd->net, thd, MYF(MY_THREAD_SPECIFIC)))
|
||||||
|
{
|
||||||
|
readbuff= NULL; // failure, net_allocate_new_packet keeps old buffer
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
@ -4722,9 +4739,7 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
|
|||||||
{
|
{
|
||||||
my_error(ER_WRONG_ARGUMENTS, MYF(0),
|
my_error(ER_WRONG_ARGUMENTS, MYF(0),
|
||||||
"mysqld_stmt_bulk_execute");
|
"mysqld_stmt_bulk_execute");
|
||||||
reset_stmt_params(this);
|
goto err;
|
||||||
thd->set_bulk_execution(0);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
read_types= FALSE;
|
read_types= FALSE;
|
||||||
|
|
||||||
@ -4741,8 +4756,7 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
|
|||||||
{
|
{
|
||||||
if (set_bulk_parameters(TRUE))
|
if (set_bulk_parameters(TRUE))
|
||||||
{
|
{
|
||||||
thd->set_bulk_execution(0);
|
goto err;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4806,8 +4820,16 @@ reexecute:
|
|||||||
}
|
}
|
||||||
reset_stmt_params(this);
|
reset_stmt_params(this);
|
||||||
thd->set_bulk_execution(0);
|
thd->set_bulk_execution(0);
|
||||||
|
if (readbuff)
|
||||||
|
my_free(readbuff);
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
err:
|
||||||
|
reset_stmt_params(this);
|
||||||
|
thd->set_bulk_execution(0);
|
||||||
|
if (readbuff)
|
||||||
|
my_free(readbuff);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,6 +190,7 @@ static int join_read_system(JOIN_TAB *tab);
|
|||||||
static int join_read_const(JOIN_TAB *tab);
|
static int join_read_const(JOIN_TAB *tab);
|
||||||
static int join_read_key(JOIN_TAB *tab);
|
static int join_read_key(JOIN_TAB *tab);
|
||||||
static void join_read_key_unlock_row(st_join_table *tab);
|
static void join_read_key_unlock_row(st_join_table *tab);
|
||||||
|
static void join_const_unlock_row(JOIN_TAB *tab);
|
||||||
static int join_read_always_key(JOIN_TAB *tab);
|
static int join_read_always_key(JOIN_TAB *tab);
|
||||||
static int join_read_last_key(JOIN_TAB *tab);
|
static int join_read_last_key(JOIN_TAB *tab);
|
||||||
static int join_no_more_records(READ_RECORD *info);
|
static int join_no_more_records(READ_RECORD *info);
|
||||||
@ -11189,8 +11190,12 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
|
|||||||
else
|
else
|
||||||
j->type=JT_EQ_REF;
|
j->type=JT_EQ_REF;
|
||||||
|
|
||||||
j->read_record.unlock_row= (j->type == JT_EQ_REF)?
|
if (j->type == JT_EQ_REF)
|
||||||
join_read_key_unlock_row : rr_unlock_row;
|
j->read_record.unlock_row= join_read_key_unlock_row;
|
||||||
|
else if (j->type == JT_CONST)
|
||||||
|
j->read_record.unlock_row= join_const_unlock_row;
|
||||||
|
else
|
||||||
|
j->read_record.unlock_row= rr_unlock_row;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13455,6 +13460,7 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
|
|||||||
/* Only happens with outer joins */
|
/* Only happens with outer joins */
|
||||||
tab->read_first_record= tab->type == JT_SYSTEM ? join_read_system
|
tab->read_first_record= tab->type == JT_SYSTEM ? join_read_system
|
||||||
: join_read_const;
|
: join_read_const;
|
||||||
|
tab->read_record.unlock_row= join_const_unlock_row;
|
||||||
if (!(table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) &&
|
if (!(table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) &&
|
||||||
(!jcl || jcl > 4) && !tab->ref.is_access_triggered())
|
(!jcl || jcl > 4) && !tab->ref.is_access_triggered())
|
||||||
push_index_cond(tab, tab->ref.key);
|
push_index_cond(tab, tab->ref.key);
|
||||||
@ -21726,6 +21732,19 @@ join_read_key_unlock_row(st_join_table *tab)
|
|||||||
tab->ref.use_count--;
|
tab->ref.use_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Rows from const tables are read once but potentially used
|
||||||
|
multiple times during execution of a query.
|
||||||
|
Ensure such rows are never unlocked during query execution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
join_const_unlock_row(JOIN_TAB *tab)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(tab->type == JT_CONST);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ref access method implementation: "read_first" function
|
ref access method implementation: "read_first" function
|
||||||
|
|
||||||
@ -24178,8 +24197,12 @@ check_reverse_order:
|
|||||||
else if (select && select->quick)
|
else if (select && select->quick)
|
||||||
select->quick->need_sorted_output();
|
select->quick->need_sorted_output();
|
||||||
|
|
||||||
tab->read_record.unlock_row= (tab->type == JT_EQ_REF) ?
|
if (tab->type == JT_EQ_REF)
|
||||||
join_read_key_unlock_row : rr_unlock_row;
|
tab->read_record.unlock_row= join_read_key_unlock_row;
|
||||||
|
else if (tab->type == JT_CONST)
|
||||||
|
tab->read_record.unlock_row= join_const_unlock_row;
|
||||||
|
else
|
||||||
|
tab->read_record.unlock_row= rr_unlock_row;
|
||||||
|
|
||||||
} // QEP has been modified
|
} // QEP has been modified
|
||||||
|
|
||||||
|
@ -674,8 +674,7 @@ void buf_dblwr_t::flush_buffered_writes_completed(const IORequest &request)
|
|||||||
static_cast<const byte*>(frame)));
|
static_cast<const byte*>(frame)));
|
||||||
ut_ad(lsn);
|
ut_ad(lsn);
|
||||||
ut_ad(lsn >= bpage->oldest_modification());
|
ut_ad(lsn >= bpage->oldest_modification());
|
||||||
if (lsn > log_sys.get_flushed_lsn())
|
log_write_up_to(lsn, true);
|
||||||
log_write_up_to(lsn, true);
|
|
||||||
e.request.node->space->io(e.request, bpage->physical_offset(), e_size,
|
e.request.node->space->io(e.request, bpage->physical_offset(), e_size,
|
||||||
frame, bpage);
|
frame, bpage);
|
||||||
}
|
}
|
||||||
|
@ -15432,7 +15432,7 @@ ha_innobase::extra(
|
|||||||
case HA_EXTRA_END_ALTER_COPY:
|
case HA_EXTRA_END_ALTER_COPY:
|
||||||
m_prebuilt->table->skip_alter_undo = 0;
|
m_prebuilt->table->skip_alter_undo = 0;
|
||||||
if (!m_prebuilt->table->is_temporary()) {
|
if (!m_prebuilt->table->is_temporary()) {
|
||||||
log_write_up_to(LSN_MAX, true);
|
log_buffer_flush_to_disk();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:/* Do nothing */
|
default:/* Do nothing */
|
||||||
|
@ -705,15 +705,6 @@ public:
|
|||||||
|
|
||||||
/** Shut down the redo log subsystem. */
|
/** Shut down the redo log subsystem. */
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
/** Initiate a write of the log buffer to the file if needed.
|
|
||||||
@param flush whether to initiate a durable write */
|
|
||||||
inline void initiate_write(bool flush)
|
|
||||||
{
|
|
||||||
const lsn_t lsn= get_lsn();
|
|
||||||
if (!flush || get_flushed_lsn() < lsn)
|
|
||||||
log_write_up_to(lsn, flush);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Redo log system */
|
/** Redo log system */
|
||||||
|
@ -791,6 +791,7 @@ void log_write_up_to(lsn_t lsn, bool flush_to_disk, bool rotate_key,
|
|||||||
{
|
{
|
||||||
ut_ad(!srv_read_only_mode);
|
ut_ad(!srv_read_only_mode);
|
||||||
ut_ad(!rotate_key || flush_to_disk);
|
ut_ad(!rotate_key || flush_to_disk);
|
||||||
|
ut_ad(lsn != LSN_MAX);
|
||||||
|
|
||||||
if (recv_no_ibuf_operations)
|
if (recv_no_ibuf_operations)
|
||||||
{
|
{
|
||||||
|
@ -702,7 +702,7 @@ static lsn_t log_reserve_and_open(size_t len)
|
|||||||
DEBUG_SYNC_C("log_buf_size_exceeded");
|
DEBUG_SYNC_C("log_buf_size_exceeded");
|
||||||
|
|
||||||
/* Not enough free space, do a write of the log buffer */
|
/* Not enough free space, do a write of the log buffer */
|
||||||
log_sys.initiate_write(false);
|
log_write_up_to(log_sys.get_lsn(), false);
|
||||||
|
|
||||||
srv_stats.log_waits.inc();
|
srv_stats.log_waits.inc();
|
||||||
|
|
||||||
|
@ -2672,7 +2672,7 @@ rollback:
|
|||||||
ALTER TABLE...DISCARD TABLESPACE operation altogether. */
|
ALTER TABLE...DISCARD TABLESPACE operation altogether. */
|
||||||
err= row_discard_tablespace(trx, table);
|
err= row_discard_tablespace(trx, table);
|
||||||
DBUG_EXECUTE_IF("ib_discard_before_commit_crash",
|
DBUG_EXECUTE_IF("ib_discard_before_commit_crash",
|
||||||
log_write_up_to(LSN_MAX, true); DBUG_SUICIDE(););
|
log_buffer_flush_to_disk(); DBUG_SUICIDE(););
|
||||||
/* FTS_ tables may be deleted */
|
/* FTS_ tables may be deleted */
|
||||||
std::vector<pfs_os_file_t> deleted;
|
std::vector<pfs_os_file_t> deleted;
|
||||||
trx->commit(deleted);
|
trx->commit(deleted);
|
||||||
|
@ -1477,7 +1477,7 @@ static void srv_sync_log_buffer_in_background()
|
|||||||
srv_main_thread_op_info = "flushing log";
|
srv_main_thread_op_info = "flushing log";
|
||||||
if (difftime(current_time, srv_last_log_flush_time)
|
if (difftime(current_time, srv_last_log_flush_time)
|
||||||
>= srv_flush_log_at_timeout) {
|
>= srv_flush_log_at_timeout) {
|
||||||
log_sys.initiate_write(true);
|
log_buffer_flush_to_disk();
|
||||||
srv_last_log_flush_time = current_time;
|
srv_last_log_flush_time = current_time;
|
||||||
srv_log_writes_and_flush++;
|
srv_log_writes_and_flush++;
|
||||||
}
|
}
|
||||||
|
@ -328,7 +328,7 @@ static dberr_t create_log_file(bool create_new_db, lsn_t lsn,
|
|||||||
mysql_mutex_unlock(&log_sys.mutex);
|
mysql_mutex_unlock(&log_sys.mutex);
|
||||||
|
|
||||||
log_make_checkpoint();
|
log_make_checkpoint();
|
||||||
log_write_up_to(LSN_MAX, true);
|
log_buffer_flush_to_disk();
|
||||||
|
|
||||||
return DB_SUCCESS;
|
return DB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -777,7 +777,7 @@ not_free:
|
|||||||
|
|
||||||
DBUG_EXECUTE_IF("ib_undo_trunc",
|
DBUG_EXECUTE_IF("ib_undo_trunc",
|
||||||
ib::info() << "ib_undo_trunc";
|
ib::info() << "ib_undo_trunc";
|
||||||
log_write_up_to(LSN_MAX, true);
|
log_buffer_flush_to_disk();
|
||||||
DBUG_SUICIDE(););
|
DBUG_SUICIDE(););
|
||||||
|
|
||||||
for (auto& rseg : trx_sys.rseg_array) {
|
for (auto& rseg : trx_sys.rseg_array) {
|
||||||
|
@ -5466,6 +5466,7 @@ void pfs_end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
|
|||||||
switch(da->status())
|
switch(da->status())
|
||||||
{
|
{
|
||||||
case Diagnostics_area::DA_OK_BULK:
|
case Diagnostics_area::DA_OK_BULK:
|
||||||
|
case Diagnostics_area::DA_EOF_BULK:
|
||||||
case Diagnostics_area::DA_EMPTY:
|
case Diagnostics_area::DA_EMPTY:
|
||||||
break;
|
break;
|
||||||
case Diagnostics_area::DA_OK:
|
case Diagnostics_area::DA_OK:
|
||||||
@ -5706,6 +5707,7 @@ void pfs_end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
|
|||||||
switch (da->status())
|
switch (da->status())
|
||||||
{
|
{
|
||||||
case Diagnostics_area::DA_OK_BULK:
|
case Diagnostics_area::DA_OK_BULK:
|
||||||
|
case Diagnostics_area::DA_EOF_BULK:
|
||||||
case Diagnostics_area::DA_EMPTY:
|
case Diagnostics_area::DA_EMPTY:
|
||||||
break;
|
break;
|
||||||
case Diagnostics_area::DA_OK:
|
case Diagnostics_area::DA_OK:
|
||||||
|
@ -20547,6 +20547,178 @@ static void test_bulk_replace()
|
|||||||
rc= mysql_query(mysql, "DROP TABLE t1");
|
rc= mysql_query(mysql, "DROP TABLE t1");
|
||||||
myquery(rc);
|
myquery(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_bulk_insert_returning()
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
MYSQL_STMT *stmt;
|
||||||
|
MYSQL_BIND bind[2], res_bind[2];
|
||||||
|
MYSQL_ROW row;
|
||||||
|
MYSQL_RES *result;
|
||||||
|
int i,
|
||||||
|
id[]= {1, 2, 3, 4},
|
||||||
|
val[]= {1, 1, 1, 1},
|
||||||
|
count= sizeof(id)/sizeof(id[0]);
|
||||||
|
unsigned long length[2];
|
||||||
|
my_bool is_null[2];
|
||||||
|
my_bool error[2];
|
||||||
|
int32 res[2];
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql,
|
||||||
|
"CREATE TABLE t1 (id int not null primary key, active int)");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
stmt= mysql_stmt_init(mysql);
|
||||||
|
rc= mysql_stmt_prepare(stmt,
|
||||||
|
"insert into t1 values (?, ?) returning id, active",
|
||||||
|
-1);
|
||||||
|
check_execute(stmt, rc);
|
||||||
|
|
||||||
|
memset(bind, 0, sizeof(bind));
|
||||||
|
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
bind[0].buffer = (void *)id;
|
||||||
|
bind[0].buffer_length = 0;
|
||||||
|
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
bind[1].buffer = (void *)val;
|
||||||
|
bind[1].buffer_length = 0;
|
||||||
|
|
||||||
|
mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, (void*)&count);
|
||||||
|
rc= mysql_stmt_bind_param(stmt, bind);
|
||||||
|
check_execute(stmt, rc);
|
||||||
|
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
memset(res_bind, 0, sizeof(res_bind));
|
||||||
|
for (i= 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
res_bind[i].buffer_type= MYSQL_TYPE_LONG;
|
||||||
|
res_bind[i].buffer= (char *)&res[i];
|
||||||
|
res_bind[i].is_null= &is_null[i];
|
||||||
|
res_bind[i].length= &length[i];
|
||||||
|
res_bind[i].error= &error[i];
|
||||||
|
}
|
||||||
|
rc= mysql_stmt_bind_result(stmt, res_bind);
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_stmt_store_result(stmt);
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
i= 0;
|
||||||
|
while (!mysql_stmt_fetch(stmt))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
DIE_IF(is_null[0] || is_null[1]);
|
||||||
|
DIE_IF(res[0] != i);
|
||||||
|
DIE_IF(res[1] != 1);
|
||||||
|
}
|
||||||
|
DIE_IF(i != 4);
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "SELECT id,active FROM t1");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
result= mysql_store_result(mysql);
|
||||||
|
mytest(result);
|
||||||
|
|
||||||
|
i= 0;
|
||||||
|
while ((row= mysql_fetch_row(result)))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
DIE_IF(atoi(row[0]) != i);
|
||||||
|
DIE_IF(atoi(row[1]) != 1);
|
||||||
|
}
|
||||||
|
DIE_IF(i != 4);
|
||||||
|
mysql_free_result(result);
|
||||||
|
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE t1");
|
||||||
|
myquery(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_bulk_delete_returning()
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
MYSQL_STMT *stmt;
|
||||||
|
MYSQL_BIND bind[2], res_bind[2];
|
||||||
|
MYSQL_ROW row;
|
||||||
|
MYSQL_RES *result;
|
||||||
|
int i,
|
||||||
|
id[]= {1, 2, 3, 4},
|
||||||
|
count= sizeof(id)/sizeof(id[0]);
|
||||||
|
unsigned long length[1];
|
||||||
|
my_bool is_null[1];
|
||||||
|
my_bool error[1];
|
||||||
|
int32 res[1];
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "CREATE TABLE t1 (id int not null primary key)");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "insert into t1 values (1), (2), (3), (4)");
|
||||||
|
myquery(rc);
|
||||||
|
verify_affected_rows(4);
|
||||||
|
|
||||||
|
stmt= mysql_stmt_init(mysql);
|
||||||
|
rc= mysql_stmt_prepare(stmt, "DELETE FROM t1 WHERE id=? RETURNING id", -1);
|
||||||
|
check_execute(stmt, rc);
|
||||||
|
|
||||||
|
memset(bind, 0, sizeof(bind));
|
||||||
|
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
bind[0].buffer = (void *)id;
|
||||||
|
bind[0].buffer_length = 0;
|
||||||
|
|
||||||
|
mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, (void*)&count);
|
||||||
|
rc= mysql_stmt_bind_param(stmt, bind);
|
||||||
|
check_execute(stmt, rc);
|
||||||
|
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
memset(res_bind, 0, sizeof(res_bind));
|
||||||
|
res_bind[0].buffer_type= MYSQL_TYPE_LONG;
|
||||||
|
res_bind[0].buffer= (char *)&res[0];
|
||||||
|
res_bind[0].is_null= &is_null[0];
|
||||||
|
res_bind[0].length= &length[0];
|
||||||
|
res_bind[0].error= &error[0];
|
||||||
|
rc= mysql_stmt_bind_result(stmt, res_bind);
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_stmt_store_result(stmt);
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
i= 0;
|
||||||
|
while (!mysql_stmt_fetch(stmt))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
DIE_IF(is_null[0]);
|
||||||
|
DIE_IF(res[0] != i);
|
||||||
|
}
|
||||||
|
DIE_IF(i != 4);
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "SELECT id FROM t1");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
result= mysql_store_result(mysql);
|
||||||
|
mytest(result);
|
||||||
|
|
||||||
|
i= 0;
|
||||||
|
while ((row= mysql_fetch_row(result)))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
printf("\nResult (SHOULD NOT BE HERE!!!) %d %s \n", i, row[0]);
|
||||||
|
}
|
||||||
|
DIE_IF(i != 0 );
|
||||||
|
mysql_free_result(result);
|
||||||
|
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE t1");
|
||||||
|
myquery(rc);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -21556,6 +21728,8 @@ static struct my_tests_st my_tests[]= {
|
|||||||
{ "test_bulk_autoinc", test_bulk_autoinc},
|
{ "test_bulk_autoinc", test_bulk_autoinc},
|
||||||
{ "test_bulk_delete", test_bulk_delete },
|
{ "test_bulk_delete", test_bulk_delete },
|
||||||
{ "test_bulk_replace", test_bulk_replace },
|
{ "test_bulk_replace", test_bulk_replace },
|
||||||
|
{ "test_bulk_insert_returning", test_bulk_insert_returning },
|
||||||
|
{ "test_bulk_delete_returning", test_bulk_delete_returning },
|
||||||
#endif
|
#endif
|
||||||
{ "test_ps_params_in_ctes", test_ps_params_in_ctes },
|
{ "test_ps_params_in_ctes", test_ps_params_in_ctes },
|
||||||
{ "test_explain_meta", test_explain_meta },
|
{ "test_explain_meta", test_explain_meta },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user