mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
Merge branch 10.11 into 11.4
# Conflicts: # sql/handler.h # sql/log_event.h # sql/log_event_server.cc
This commit is contained in:
@@ -1404,9 +1404,7 @@ int main(int argc,char *argv[])
|
||||
if (opt_outfile)
|
||||
end_tee();
|
||||
mysql_end(0);
|
||||
#ifndef _lint
|
||||
DBUG_RETURN(0); // Keep compiler happy
|
||||
#endif
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
sig_handler mysql_end(int sig)
|
||||
@@ -3507,8 +3505,6 @@ static int com_go(String *buffer, char *)
|
||||
old_buffer.copy();
|
||||
}
|
||||
|
||||
/* Remove garbage for nicer messages */
|
||||
LINT_INIT_STRUCT(buff[0]);
|
||||
remove_cntrl(*buffer);
|
||||
|
||||
if (buffer->is_empty())
|
||||
|
||||
@@ -67,6 +67,14 @@ IF(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS
|
||||
SET(MY_ERROR_FLAGS ${MY_ERROR_FLAGS} -Wno-error=non-virtual-dtor) # gcc bug 7302
|
||||
ENDIF()
|
||||
|
||||
FOREACH(LANG C CXX)
|
||||
IF(CMAKE_${LANG}_COMPILER_ID MATCHES "Clang")
|
||||
MY_CHECK_AND_SET_COMPILER_FLAG(-Werror=uninitialized-explicit-init)
|
||||
MY_CHECK_AND_SET_COMPILER_FLAG(-Werror=uninitialized-const-reference)
|
||||
SET(CMAKE_${LANG}_FLAGS "${CMAKE_${LANG}_FLAGS} -Werror=uninitialized")
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
|
||||
IF(MYSQL_MAINTAINER_MODE MATCHES "OFF|WARN")
|
||||
RETURN()
|
||||
ELSEIF(MYSQL_MAINTAINER_MODE MATCHES "AUTO")
|
||||
|
||||
@@ -80,12 +80,6 @@ extern const char _dig_vec_lower[];
|
||||
|
||||
extern char *strmov_overlapp(char *dest, const char *src);
|
||||
|
||||
#if defined(_lint) || defined(FORCE_INIT_OF_VARS)
|
||||
#define LINT_INIT_STRUCT(var) bzero(&var, sizeof(var)) /* No uninitialize-warning */
|
||||
#else
|
||||
#define LINT_INIT_STRUCT(var)
|
||||
#endif
|
||||
|
||||
/* Prototypes for string functions */
|
||||
|
||||
extern void bmove_upp(uchar *dst,const uchar *src,size_t len);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#if !defined(DBUG_OFF) && !defined(_lint)
|
||||
#if !defined(DBUG_OFF)
|
||||
|
||||
struct _db_stack_frame_ {
|
||||
const char *func; /* function name of the previous stack frame */
|
||||
@@ -210,7 +210,7 @@ extern void (*my_dbug_assert_failed)(const char *assert_expr, const char* file,
|
||||
#define DBUG_ASSERT(A) do { } while(0)
|
||||
#define IF_DBUG_ASSERT(A,B) B
|
||||
#endif /* DBUG_ASSERT_AS_PRINTF */
|
||||
#endif /* !defined(DBUG_OFF) && !defined(_lint) */
|
||||
#endif /* !defined(DBUG_OFF) */
|
||||
|
||||
#ifdef EXTRA_DEBUG
|
||||
/**
|
||||
|
||||
@@ -281,10 +281,6 @@ C_MODE_END
|
||||
#error "Please add -fno-exceptions to CXXFLAGS and reconfigure/recompile"
|
||||
#endif
|
||||
|
||||
#if defined(_lint) && !defined(lint)
|
||||
#define lint
|
||||
#endif
|
||||
|
||||
#ifndef stdin
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
@@ -448,22 +444,19 @@ extern "C" int madvise(void *addr, size_t len, int behav);
|
||||
/*
|
||||
Suppress uninitialized variable warning without generating code.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
/* GCC specific self-initialization which inhibits the warning. */
|
||||
#if defined(__GNUC__) && !defined(WITH_UBSAN)
|
||||
/*
|
||||
GCC specific self-initialization which inhibits the warning.
|
||||
clang and static analysis will complain loudly about this
|
||||
so compile those under WITH_UBSAN.
|
||||
*/
|
||||
#define UNINIT_VAR(x) x= x
|
||||
#elif defined(_lint) || defined(FORCE_INIT_OF_VARS)
|
||||
#elif defined(FORCE_INIT_OF_VARS)
|
||||
#define UNINIT_VAR(x) x= 0
|
||||
#else
|
||||
#define UNINIT_VAR(x) x
|
||||
#endif
|
||||
|
||||
/* This is only to be used when resetting variables in a class constructor */
|
||||
#if defined(_lint) || defined(FORCE_INIT_OF_VARS)
|
||||
#define LINT_INIT(x) x= 0
|
||||
#else
|
||||
#define LINT_INIT(x)
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_UINT)
|
||||
#undef HAVE_UINT
|
||||
#define HAVE_UINT
|
||||
@@ -505,7 +498,7 @@ C_MODE_END
|
||||
#endif
|
||||
|
||||
/* We might be forced to turn debug off, if not turned off already */
|
||||
#if (defined(FORCE_DBUG_OFF) || defined(_lint)) && !defined(DBUG_OFF)
|
||||
#if defined(FORCE_DBUG_OFF) && !defined(DBUG_OFF)
|
||||
# define DBUG_OFF
|
||||
# ifdef DBUG_ON
|
||||
# undef DBUG_ON
|
||||
@@ -527,7 +520,7 @@ typedef int my_socket; /* File descriptor for sockets */
|
||||
#endif
|
||||
/* Type for functions that handles signals */
|
||||
#define sig_handler RETSIGTYPE
|
||||
#if defined(__GNUC__) && !defined(_lint)
|
||||
#if defined(__GNUC__)
|
||||
typedef char pchar; /* Mixed prototypes can take char */
|
||||
typedef char puchar; /* Mixed prototypes can take char */
|
||||
typedef char pbool; /* Mixed prototypes can take char */
|
||||
|
||||
@@ -9,20 +9,64 @@ insert into t1 values (2,2);
|
||||
update t1 set a1 = 'd' limit 1;
|
||||
update t1 set a1 = 'd2' where i1= 2;
|
||||
connection slave;
|
||||
connection slave;
|
||||
select * from t1;
|
||||
i1 a1
|
||||
1 d
|
||||
2 d2
|
||||
connection master;
|
||||
drop table t1;
|
||||
connection slave;
|
||||
connection master;
|
||||
#
|
||||
# MDEV-32093 long uniques break old->new replication
|
||||
#
|
||||
connection slave;
|
||||
create table t1 (id int not null, b1 varchar(255) not null, b2 varchar(2550) not null, unique (id), unique key (b1,b2) using hash) default charset utf8mb3;
|
||||
set global slave_exec_mode=idempotent;
|
||||
binlog 'aRf2ZA8BAAAA/AAAAAABAAAAAAQAMTAuNS4xNS1NYXJpYURCLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABpF/ZkEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEwQADQgICAoKCgFRmTlk';
|
||||
binlog 'bBf2ZBMBAAAANAAAAJgHAAAAAHEAAAAAAAEABHRlc3QAAnQxAAQDDw8IBP0C4h0AeqMD4A==bBf2ZBcBAAAANAAAAMwHAAAAAHEAAAAAAAEABP/wj6QAAAEAYgEAZa6/VU0JAAAANteqUw==';
|
||||
binlog 'bBf2ZBMBAAAANAAAAJgHAAAAAHEAAAAAAAEABHRlc3QAAnQxAAQDDw8IBP0C4h0AeqMD4A==bBf2ZBcBAAAANAAAAMwHAAAAAHEAAAAAAAEABP/wj6QAAAEAYgEAZa6/VU0JAAAANteqUw==';
|
||||
binlog 'bBf2ZBMBAAAANAAAAHUkAAAAAHEAAAAAAAEABHRlc3QAAnQxAAQDDw8IBP0C4h0AaTGFIg==bBf2ZBgBAAAASAAAAL0kAAAAAHEAAAAAAAEABP//8I+kAAABAGIBAGWuv1VNCQAAAPBuWwAAAQBiAQBlrr9VTQkAAADxS9Lu';
|
||||
drop table t1;
|
||||
connection slave;
|
||||
select * from t1;
|
||||
id b1 b2
|
||||
23406 b e
|
||||
connection master;
|
||||
set global slave_exec_mode=default;
|
||||
drop table t1;
|
||||
#
|
||||
# End of 10.4 tests
|
||||
#
|
||||
# Idempotent scenario, which triggers REPLACE code to be used in the
|
||||
# event, i.e. duplicated record will be deleted and then re-inserted.
|
||||
create table t1 (i1 int, a1 text, unique key i1 (a1)) engine=myisam;
|
||||
connection slave;
|
||||
connection slave;
|
||||
set @save_slave_exec_mode= @@slave_exec_mode;
|
||||
set global slave_exec_mode = idempotent;
|
||||
insert into t1 values (1,1);
|
||||
connection master;
|
||||
insert into t1 values (2,1);
|
||||
connection slave;
|
||||
connection slave;
|
||||
select * from t1;
|
||||
i1 a1
|
||||
2 1
|
||||
connection master;
|
||||
insert into t1 values (3,3);
|
||||
update t1 set a1 = 'd' limit 1;
|
||||
update t1 set a1 = 'd2' where i1= 3;
|
||||
connection slave;
|
||||
connection slave;
|
||||
select * from t1;
|
||||
i1 a1
|
||||
2 d
|
||||
3 d2
|
||||
set global slave_exec_mode = @save_slave_exec_mode;
|
||||
connection master;
|
||||
drop table t1;
|
||||
connection slave;
|
||||
connection master;
|
||||
#
|
||||
# End of 10.4 tests
|
||||
#
|
||||
|
||||
@@ -16,17 +16,21 @@ update t1 set a1 = 'd' limit 1;
|
||||
update t1 set a1 = 'd2' where i1= 2;
|
||||
|
||||
sync_slave_with_master;
|
||||
|
||||
connection slave;
|
||||
select * from t1;
|
||||
connection master;
|
||||
drop table t1;
|
||||
|
||||
sync_slave_with_master;
|
||||
connection master;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32093 long uniques break old->new replication
|
||||
--echo #
|
||||
|
||||
# this is techically a bug in replication, but it needs an old master
|
||||
# so we'll run it as a non-replicated test with BINLOG command
|
||||
sync_slave_with_master;
|
||||
create table t1 (id int not null, b1 varchar(255) not null, b2 varchar(2550) not null, unique (id), unique key (b1,b2) using hash) default charset utf8mb3;
|
||||
set global slave_exec_mode=idempotent;
|
||||
|
||||
@@ -40,10 +44,46 @@ binlog 'bBf2ZBMBAAAANAAAAJgHAAAAAHEAAAAAAAEABHRlc3QAAnQxAAQDDw8IBP0C4h0AeqMD4A==
|
||||
### UPDATE t1 WHERE (42127, 'b', 'e', 39952170926) SET (23406, 'b', 'e', 39952170926)
|
||||
binlog 'bBf2ZBMBAAAANAAAAHUkAAAAAHEAAAAAAAEABHRlc3QAAnQxAAQDDw8IBP0C4h0AaTGFIg==bBf2ZBgBAAAASAAAAL0kAAAAAHEAAAAAAAEABP//8I+kAAABAGIBAGWuv1VNCQAAAPBuWwAAAQBiAQBlrr9VTQkAAADxS9Lu';
|
||||
|
||||
drop table t1;
|
||||
sync_slave_with_master;
|
||||
select * from t1;
|
||||
connection master;
|
||||
set global slave_exec_mode=default;
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.4 tests
|
||||
--echo #
|
||||
|
||||
--echo # Idempotent scenario, which triggers REPLACE code to be used in the
|
||||
--echo # event, i.e. duplicated record will be deleted and then re-inserted.
|
||||
create table t1 (i1 int, a1 text, unique key i1 (a1)) engine=myisam;
|
||||
|
||||
sync_slave_with_master;
|
||||
connection slave;
|
||||
set @save_slave_exec_mode= @@slave_exec_mode;
|
||||
set global slave_exec_mode = idempotent;
|
||||
insert into t1 values (1,1);
|
||||
connection master;
|
||||
insert into t1 values (2,1);
|
||||
sync_slave_with_master;
|
||||
connection slave;
|
||||
select * from t1;
|
||||
connection master;
|
||||
insert into t1 values (3,3);
|
||||
update t1 set a1 = 'd' limit 1;
|
||||
update t1 set a1 = 'd2' where i1= 3;
|
||||
sync_slave_with_master;
|
||||
|
||||
connection slave;
|
||||
select * from t1;
|
||||
set global slave_exec_mode = @save_slave_exec_mode;
|
||||
connection master;
|
||||
drop table t1;
|
||||
sync_slave_with_master;
|
||||
connection master;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.4 tests
|
||||
--echo #
|
||||
|
||||
--source include/rpl_end.inc
|
||||
|
||||
@@ -59,4 +59,39 @@ call p2('2');
|
||||
drop table t1;
|
||||
drop procedure p1;
|
||||
drop procedure p2;
|
||||
#
|
||||
# MDEV-26115: Crash when calling stored function in FOR loop argument
|
||||
#
|
||||
CREATE OR REPLACE FUNCTION cnt()
|
||||
RETURNS INTEGER NO SQL
|
||||
BEGIN
|
||||
RETURN 3;
|
||||
END;
|
||||
$
|
||||
CREATE OR REPLACE PROCEDURE p1()
|
||||
NO SQL
|
||||
BEGIN
|
||||
DECLARE i INTEGER;
|
||||
FOR i IN 1..cnt() DO
|
||||
SELECT 1;
|
||||
END FOR;
|
||||
END;
|
||||
$
|
||||
CALL p1();
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
CALL p1();
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
# Clean up
|
||||
DROP FUNCTION cnt;
|
||||
DROP PROCEDURE p1;
|
||||
# End of 10.11 tests
|
||||
|
||||
@@ -67,4 +67,34 @@ drop table t1;
|
||||
drop procedure p1;
|
||||
drop procedure p2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-26115: Crash when calling stored function in FOR loop argument
|
||||
--echo #
|
||||
--delimiter $
|
||||
CREATE OR REPLACE FUNCTION cnt()
|
||||
RETURNS INTEGER NO SQL
|
||||
BEGIN
|
||||
RETURN 3;
|
||||
END;
|
||||
$
|
||||
|
||||
CREATE OR REPLACE PROCEDURE p1()
|
||||
NO SQL
|
||||
BEGIN
|
||||
DECLARE i INTEGER;
|
||||
FOR i IN 1..cnt() DO
|
||||
SELECT 1;
|
||||
END FOR;
|
||||
END;
|
||||
$
|
||||
|
||||
--delimiter ;
|
||||
|
||||
CALL p1();
|
||||
CALL p1();
|
||||
|
||||
--echo # Clean up
|
||||
DROP FUNCTION cnt;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
--echo # End of 10.11 tests
|
||||
|
||||
@@ -34,4 +34,14 @@ CREATE TABLE t6 (a INT AUTO_INCREMENT PRIMARY KEY, b TEXT) ENGINE=InnoDB;
|
||||
# Run innochecksum on t6
|
||||
# Restore the original tables
|
||||
# restart
|
||||
# Trigger AHI and test pages_hashed, pages_old as non zero from sys view
|
||||
SELECT STRAIGHT_JOIN COUNT(t6a.a)
|
||||
FROM t6 AS t6a, t6 AS t6b
|
||||
WHERE t6a.a = t6b.a;
|
||||
COUNT(t6a.a)
|
||||
1000
|
||||
SELECT SUM(pages_hashed)>0 `1`, SUM(pages_old)>0 `1`
|
||||
FROM sys.innodb_buffer_stats_by_table;
|
||||
1 1
|
||||
1 1
|
||||
DROP TABLE t1, t2, t3, t4, t5, t6;
|
||||
|
||||
2
mysql-test/suite/encryption/t/innochecksum.opt
Normal file
2
mysql-test/suite/encryption/t/innochecksum.opt
Normal file
@@ -0,0 +1,2 @@
|
||||
--innodb-adaptive-hash-index=ON
|
||||
--innodb-buffer-pool-size=64M
|
||||
@@ -299,4 +299,14 @@ if (0 && $have_debug) { # these messages sometimes fail to appear
|
||||
--move_file $MYSQLD_DATADIR/test/t6.ibd.backup $MYSQLD_DATADIR/test/t6.ibd
|
||||
|
||||
--source include/start_mysqld.inc
|
||||
|
||||
--echo # Trigger AHI and test pages_hashed, pages_old as non zero from sys view
|
||||
|
||||
SELECT STRAIGHT_JOIN COUNT(t6a.a)
|
||||
FROM t6 AS t6a, t6 AS t6b
|
||||
WHERE t6a.a = t6b.a;
|
||||
|
||||
SELECT SUM(pages_hashed)>0 `1`, SUM(pages_old)>0 `1`
|
||||
FROM sys.innodb_buffer_stats_by_table;
|
||||
|
||||
DROP TABLE t1, t2, t3, t4, t5, t6;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
SET @save_slave_parallel_threads= @@GLOBAL.slave_parallel_threads;
|
||||
SELECT IF(COUNT(*) < 20, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
|
||||
IF(COUNT(*) < 20, "OK", CONCAT("Found too many system user processes: ", COUNT(*)))
|
||||
SELECT IF(COUNT(*) < 20, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) AS ProcessCheck FROM information_schema.processlist WHERE user = "system user";
|
||||
ProcessCheck
|
||||
OK
|
||||
SELECT @@GLOBAL.slave_parallel_threads as 'must be 20 because of .cnf';
|
||||
must be 20 because of .cnf
|
||||
@@ -16,7 +16,7 @@ SET GLOBAL slave_parallel_threads= 10;
|
||||
SELECT @@GLOBAL.slave_parallel_threads;
|
||||
@@GLOBAL.slave_parallel_threads
|
||||
10
|
||||
SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
|
||||
IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*)))
|
||||
SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) AS ProcessCheck FROM information_schema.processlist WHERE user = "system user";
|
||||
ProcessCheck
|
||||
OK
|
||||
SET GLOBAL slave_parallel_threads = @save_slave_parallel_threads;
|
||||
|
||||
@@ -4,7 +4,7 @@ SET @save_slave_parallel_threads= @@GLOBAL.slave_parallel_threads;
|
||||
|
||||
# Check that we don't spawn worker threads at server startup, when no
|
||||
# slave is configured (MDEV-5289).
|
||||
SELECT IF(COUNT(*) < 20, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
|
||||
SELECT IF(COUNT(*) < 20, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) AS ProcessCheck FROM information_schema.processlist WHERE user = "system user";
|
||||
|
||||
SELECT @@GLOBAL.slave_parallel_threads as 'must be 20 because of .cnf';
|
||||
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||
@@ -16,6 +16,6 @@ SELECT @@GLOBAL.slave_parallel_threads as 'must be 0 because of default';
|
||||
SET GLOBAL slave_parallel_threads= 10;
|
||||
SELECT @@GLOBAL.slave_parallel_threads;
|
||||
# Check that we don't spawn worker threads when no slave is started.
|
||||
SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
|
||||
SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) AS ProcessCheck FROM information_schema.processlist WHERE user = "system user";
|
||||
|
||||
SET GLOBAL slave_parallel_threads = @save_slave_parallel_threads;
|
||||
|
||||
@@ -7,7 +7,11 @@ pages bigint(21) NO 0
|
||||
pages_hashed bigint(21) NO 0
|
||||
pages_old bigint(21) NO 0
|
||||
rows_cached decimal(44,0) YES NULL
|
||||
SELECT * FROM sys.innodb_buffer_stats_by_schema;
|
||||
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
SELECT * FROM sys.innodb_buffer_stats_by_schema
|
||||
where object_schema = 'test';
|
||||
object_schema allocated data pages pages_hashed pages_old rows_cached
|
||||
test 16.00 KiB 0 bytes 1 0 0 0
|
||||
DESC sys.x$innodb_buffer_stats_by_schema;
|
||||
Field Type Null Key Default Extra
|
||||
object_schema text YES NULL
|
||||
@@ -17,4 +21,8 @@ pages bigint(21) NO 0
|
||||
pages_hashed bigint(21) NO 0
|
||||
pages_old bigint(21) NO 0
|
||||
rows_cached decimal(44,0) NO 0
|
||||
SELECT * FROM sys.x$innodb_buffer_stats_by_schema;
|
||||
SELECT * FROM sys.x$innodb_buffer_stats_by_schema
|
||||
where object_schema = 'test';
|
||||
object_schema allocated data pages pages_hashed pages_old rows_cached
|
||||
test 16384 0 1 0 0 0
|
||||
DROP TABLE t1;
|
||||
|
||||
@@ -8,7 +8,11 @@ pages bigint(21) NO 0
|
||||
pages_hashed bigint(21) NO 0
|
||||
pages_old bigint(21) NO 0
|
||||
rows_cached decimal(44,0) YES NULL
|
||||
SELECT * FROM sys.innodb_buffer_stats_by_table;
|
||||
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
SELECT * FROM sys.innodb_buffer_stats_by_table
|
||||
where object_schema = 'test' and object_name = 't1';
|
||||
object_schema object_name allocated data pages pages_hashed pages_old rows_cached
|
||||
test t1 16.00 KiB 0 bytes 1 0 0 0
|
||||
DESC sys.x$innodb_buffer_stats_by_table;
|
||||
Field Type Null Key Default Extra
|
||||
object_schema text YES NULL
|
||||
@@ -19,4 +23,8 @@ pages bigint(21) NO 0
|
||||
pages_hashed bigint(21) NO 0
|
||||
pages_old bigint(21) NO 0
|
||||
rows_cached decimal(44,0) NO 0
|
||||
SELECT * FROM sys.x$innodb_buffer_stats_by_table;
|
||||
SELECT * FROM sys.x$innodb_buffer_stats_by_table
|
||||
where object_schema = 'test' and object_name = 't1';
|
||||
object_schema object_name allocated data pages pages_hashed pages_old rows_cached
|
||||
test t1 16384 0 1 0 0 0
|
||||
DROP TABLE t1;
|
||||
|
||||
@@ -8,16 +8,21 @@
|
||||
# Ensure structure changes don't slip in
|
||||
DESC sys.innodb_buffer_stats_by_schema;
|
||||
|
||||
# Make sure view select does not error, but ignore results
|
||||
--disable_result_log
|
||||
SELECT * FROM sys.innodb_buffer_stats_by_schema;
|
||||
--enable_result_log
|
||||
# Create an Empty table
|
||||
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
|
||||
# Make sure view select does not error, and
|
||||
# is_hashed & is_old is 0 for empty table
|
||||
SELECT * FROM sys.innodb_buffer_stats_by_schema
|
||||
where object_schema = 'test';
|
||||
|
||||
# Ensure structure changes don't slip in
|
||||
DESC sys.x$innodb_buffer_stats_by_schema;
|
||||
|
||||
# Make sure view select does not error, but ignore results
|
||||
--disable_result_log
|
||||
SELECT * FROM sys.x$innodb_buffer_stats_by_schema;
|
||||
--enable_result_log
|
||||
# Make sure view select does not error, and
|
||||
# is_hashed & is_old is 0 for empty table
|
||||
SELECT * FROM sys.x$innodb_buffer_stats_by_schema
|
||||
where object_schema = 'test';
|
||||
|
||||
# Drop the table
|
||||
DROP TABLE t1;
|
||||
|
||||
@@ -8,16 +8,21 @@
|
||||
# Ensure structure changes don't slip in
|
||||
DESC sys.innodb_buffer_stats_by_table;
|
||||
|
||||
# Make sure view select does not error, but ignore results
|
||||
--disable_result_log
|
||||
SELECT * FROM sys.innodb_buffer_stats_by_table;
|
||||
--enable_result_log
|
||||
# Create an Empty table
|
||||
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
|
||||
# Make sure view select does not error and
|
||||
# is_hashed & is_old is 0 for empty table
|
||||
SELECT * FROM sys.innodb_buffer_stats_by_table
|
||||
where object_schema = 'test' and object_name = 't1';
|
||||
|
||||
# Ensure structure changes don't slip in
|
||||
DESC sys.x$innodb_buffer_stats_by_table;
|
||||
|
||||
# Make sure view select does not error, but ignore results
|
||||
--disable_result_log
|
||||
SELECT * FROM sys.x$innodb_buffer_stats_by_table;
|
||||
--enable_result_log
|
||||
# Make sure view select does not error and
|
||||
# is_hashed & is_old is 0 for empty table
|
||||
SELECT * FROM sys.x$innodb_buffer_stats_by_table
|
||||
where object_schema = 'test' and object_name = 't1';
|
||||
|
||||
# Drop the table
|
||||
DROP TABLE t1;
|
||||
|
||||
@@ -66,6 +66,11 @@ if ($MTR_COMBINATION_TRX_ID)
|
||||
let $sys_datatype_expl= bigint(20) unsigned;
|
||||
let $sys_datatype_expl_uc= BIGINT(20) UNSIGNED;
|
||||
let $sys_datatype_max= 18446744073709551615;
|
||||
let $current_row= current_row;
|
||||
}
|
||||
if ($MTR_COMBINATION_TIMESTAMP)
|
||||
{
|
||||
let $current_row= current_row_ts;
|
||||
}
|
||||
|
||||
eval create or replace function current_row(sys_trx_end $sys_datatype_expl)
|
||||
@@ -76,7 +81,7 @@ deterministic
|
||||
eval create or replace function current_row_ts(sys_trx_end timestamp(6))
|
||||
returns int
|
||||
deterministic
|
||||
return convert_tz(sys_trx_end, '+00:00', @@time_zone) = TIMESTAMP'2038-01-19 03:14:07.999999';
|
||||
return convert_tz(sys_trx_end, @@time_zone, '+00:00') = TIMESTAMP'2038-01-19 03:14:07.999999';
|
||||
|
||||
delimiter ~~;
|
||||
eval create or replace function check_row(row_start $sys_datatype_expl, row_end $sys_datatype_expl)
|
||||
@@ -87,7 +92,7 @@ begin
|
||||
return "ERROR: row_end < row_start";
|
||||
elseif row_end = row_start then
|
||||
return "ERROR: row_end == row_start";
|
||||
elseif current_row(row_end) then
|
||||
elseif $current_row(row_end) then
|
||||
return "CURRENT ROW";
|
||||
end if;
|
||||
return "HISTORICAL ROW";
|
||||
@@ -99,7 +104,7 @@ eval create or replace function check_row_slave(row_start $sys_datatype_expl, ro
|
||||
returns varchar(255)
|
||||
deterministic
|
||||
begin
|
||||
if current_row(row_end) then
|
||||
if $current_row(row_end) then
|
||||
return "CURRENT ROW";
|
||||
end if;
|
||||
return "HISTORICAL ROW";
|
||||
|
||||
@@ -391,10 +391,7 @@ SET FOREIGN_KEY_CHECKS = ON;
|
||||
SET SESSION SQL_MODE= 'NO_BACKSLASH_ESCAPES';
|
||||
SET timestamp = 8;
|
||||
LOAD DATA INFILE 't1.data' REPLACE INTO TABLE t1;
|
||||
Warnings:
|
||||
Warning 1265 Data truncated for column 'f12' at row 2
|
||||
Warning 1265 Data truncated for column 'f12' at row 4
|
||||
Warning 1265 Data truncated for column 'f12' at row 7
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`f13`) REFERENCES `t2` (`f`) ON DELETE SET NULL)
|
||||
SET timestamp = 9;
|
||||
REPLACE INTO t2 SELECT * FROM t2;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
@@ -78,9 +78,3 @@ create or replace table t1 (pk int primary key) with system versioning;
|
||||
create trigger tr before insert on t1 for each row select 1 into @a;
|
||||
insert into t1 values (1),(2);
|
||||
drop table t1;
|
||||
create table t1 (pk int primary key, i int) with system versioning;
|
||||
replace into t1 values (1,10),(1,100),(1,1000);
|
||||
select pk,i,row_end > '2038-01-01' from t1 for system_time all;
|
||||
pk i row_end > '2038-01-01'
|
||||
1 1000 1
|
||||
drop table t1;
|
||||
|
||||
@@ -57,6 +57,30 @@ insert into t2 (a) values (now()),(now());
|
||||
select * from t2 where a in (select row_start from t1);
|
||||
a
|
||||
drop table t1, t2;
|
||||
# MDEV-30046 wrong row targeted with "insert ... on duplicate" and "replace"
|
||||
# Don't allow changes from the past
|
||||
create or replace table t1 (pk int primary key, i int) with system versioning;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`pk` int(11) NOT NULL,
|
||||
`i` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`pk`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci WITH SYSTEM VERSIONING
|
||||
set timestamp=12345;
|
||||
insert t1(pk, i) values(1,3);
|
||||
set timestamp=12344;
|
||||
delete from t1;
|
||||
select pk,i from t1 for system_time all;
|
||||
pk i
|
||||
set timestamp=12345;
|
||||
insert t1(pk, i) values(1,3);
|
||||
set timestamp=12344;
|
||||
replace t1(pk, i) values(1,4);
|
||||
select pk,i from t1 for system_time all;
|
||||
pk i
|
||||
1 4
|
||||
drop table t1;
|
||||
#
|
||||
# End of 10.11 tests
|
||||
#
|
||||
|
||||
@@ -1267,7 +1267,7 @@ where table_name = 't1';
|
||||
partition_name table_rows
|
||||
p0 150
|
||||
p1 60
|
||||
pn 90
|
||||
pn 91
|
||||
rollback;
|
||||
select partition_name, table_rows
|
||||
from information_schema.partitions
|
||||
@@ -1275,7 +1275,7 @@ where table_name = 't1';
|
||||
partition_name table_rows
|
||||
p0 0
|
||||
p1 0
|
||||
pn 90
|
||||
pn 91
|
||||
replace into t1 select seq from seq_1_to_10;
|
||||
select partition_name, table_rows
|
||||
from information_schema.partitions
|
||||
|
||||
26
mysql-test/suite/versioning/r/replace,trx_id.rdiff
Normal file
26
mysql-test/suite/versioning/r/replace,trx_id.rdiff
Normal file
@@ -0,0 +1,26 @@
|
||||
--- replace.result
|
||||
+++ replace.reject
|
||||
@@ -75,7 +75,6 @@
|
||||
replace into t1 (pk,i) values (1,10),(1,100),(1,1000);
|
||||
select pk, i, check_row(row_start, row_end) from t1 for system_time all;
|
||||
pk i check_row(row_start, row_end)
|
||||
-1 10 ERROR: row_end == row_start
|
||||
1 1000 CURRENT ROW
|
||||
drop table t1;
|
||||
create or replace table t1 (
|
||||
@@ -94,7 +93,6 @@
|
||||
commit;
|
||||
select pk, i, check_row(row_start, row_end) from t1 for system_time all;
|
||||
pk i check_row(row_start, row_end)
|
||||
-1 3 ERROR: row_end == row_start
|
||||
1 300 CURRENT ROW
|
||||
drop table t1;
|
||||
# In this case there'll be no unique constraint on a historical row.
|
||||
@@ -114,8 +112,6 @@
|
||||
commit;
|
||||
select pk, i, check_row(row_start, row_end) from t1 for system_time all;
|
||||
pk i check_row(row_start, row_end)
|
||||
-1 3 ERROR: row_end == row_start
|
||||
-1 30 ERROR: row_end == row_start
|
||||
1 300 CURRENT ROW
|
||||
drop table t1;
|
||||
@@ -63,9 +63,11 @@ connection default;
|
||||
replace into t1 values (1),(2);
|
||||
connection con1;
|
||||
replace into t1 values (1),(2);
|
||||
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
|
||||
drop table t1;
|
||||
#
|
||||
# MDEV-14794 Limitations which the row end as a part of PK imposes due to
|
||||
# CURRENT_TIMESTAMP behavior and otherwise
|
||||
#
|
||||
# MDEV-15330 Server crash or assertion `table->insert_values' failure in write_record upon LOAD DATA
|
||||
#
|
||||
create table t1 (a int, b int, c int, vc int as (c), unique(a), unique(b)) with system versioning;
|
||||
@@ -88,3 +90,62 @@ Note 1831 Duplicate index `data_2`. This is deprecated and will be disallowed in
|
||||
alter table t1 add system versioning;
|
||||
replace into t1 values ('o'), ('o');
|
||||
drop table t1;
|
||||
#
|
||||
# MDEV-15990 REPLACE on a precise-versioned table returns duplicate key
|
||||
# error (ER_DUP_ENTRY)
|
||||
#
|
||||
create or replace table t1 (
|
||||
pk int KEY_TYPE, i int,
|
||||
row_start SYS_DATATYPE as row start invisible,
|
||||
row_end SYS_DATATYPE as row end invisible,
|
||||
period for system_time(row_start, row_end)
|
||||
) with system versioning;
|
||||
replace into t1 (pk,i) values (1,10),(1,100),(1,1000);
|
||||
select pk, i, check_row(row_start, row_end) from t1 for system_time all;
|
||||
pk i check_row(row_start, row_end)
|
||||
1 10 ERROR: row_end == row_start
|
||||
1 1000 CURRENT ROW
|
||||
drop table t1;
|
||||
create or replace table t1 (
|
||||
pk int KEY_TYPE, i int,
|
||||
row_start SYS_DATATYPE as row start invisible,
|
||||
row_end SYS_DATATYPE as row end invisible,
|
||||
period for system_time(row_start, row_end)
|
||||
) with system versioning;
|
||||
set timestamp= (select unix_timestamp());
|
||||
begin;
|
||||
insert t1(pk, i) values(1,3);
|
||||
delete from t1;
|
||||
insert t1(pk, i) values(1,30);
|
||||
delete from t1;
|
||||
insert t1(pk, i) values(1,300);
|
||||
commit;
|
||||
select pk, i, check_row(row_start, row_end) from t1 for system_time all;
|
||||
pk i check_row(row_start, row_end)
|
||||
1 3 ERROR: row_end == row_start
|
||||
1 300 CURRENT ROW
|
||||
drop table t1;
|
||||
# In this case there'll be no unique constraint on a historical row.
|
||||
create or replace table t1 (
|
||||
pk int, i int,
|
||||
row_start SYS_DATATYPE as row start invisible,
|
||||
row_end SYS_DATATYPE as row end invisible,
|
||||
period for system_time(row_start, row_end)
|
||||
) with system versioning;
|
||||
set timestamp= (select unix_timestamp());
|
||||
begin;
|
||||
insert t1(pk, i) values(1,3);
|
||||
delete from t1;
|
||||
insert t1(pk, i) values(1,30);
|
||||
delete from t1;
|
||||
insert t1(pk, i) values(1,300);
|
||||
commit;
|
||||
select pk, i, check_row(row_start, row_end) from t1 for system_time all;
|
||||
pk i check_row(row_start, row_end)
|
||||
1 3 ERROR: row_end == row_start
|
||||
1 30 ERROR: row_end == row_start
|
||||
1 300 CURRENT ROW
|
||||
drop table t1;
|
||||
#
|
||||
# End of 10.5 tests
|
||||
#
|
||||
|
||||
@@ -419,6 +419,7 @@ SET FOREIGN_KEY_CHECKS = ON;
|
||||
|
||||
SET SESSION SQL_MODE= 'NO_BACKSLASH_ESCAPES';
|
||||
SET timestamp = 8;
|
||||
--error ER_NO_REFERENCED_ROW_2
|
||||
LOAD DATA INFILE 't1.data' REPLACE INTO TABLE t1;
|
||||
SET timestamp = 9;
|
||||
REPLACE INTO t2 SELECT * FROM t2;
|
||||
|
||||
@@ -78,11 +78,3 @@ create or replace table t1 (pk int primary key) with system versioning;
|
||||
create trigger tr before insert on t1 for each row select 1 into @a;
|
||||
insert into t1 values (1),(2);
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# MDEV-14794 Limitations which the row end as a part of PK imposes due to CURRENT_TIMESTAMP behavior and otherwise
|
||||
#
|
||||
create table t1 (pk int primary key, i int) with system versioning;
|
||||
replace into t1 values (1,10),(1,100),(1,1000);
|
||||
select pk,i,row_end > '2038-01-01' from t1 for system_time all;
|
||||
drop table t1;
|
||||
|
||||
@@ -46,6 +46,25 @@ insert into t2 (a) values (now()),(now());
|
||||
select * from t2 where a in (select row_start from t1);
|
||||
drop table t1, t2;
|
||||
|
||||
--echo # MDEV-30046 wrong row targeted with "insert ... on duplicate" and "replace"
|
||||
--echo # Don't allow changes from the past
|
||||
create or replace table t1 (pk int primary key, i int) with system versioning;
|
||||
show create table t1;
|
||||
set timestamp=12345;
|
||||
insert t1(pk, i) values(1,3);
|
||||
set timestamp=12344;
|
||||
delete from t1;
|
||||
|
||||
select pk,i from t1 for system_time all;
|
||||
|
||||
set timestamp=12345;
|
||||
insert t1(pk, i) values(1,3);
|
||||
set timestamp=12344;
|
||||
replace t1(pk, i) values(1,4);
|
||||
|
||||
select pk,i from t1 for system_time all;
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.11 tests
|
||||
--echo #
|
||||
|
||||
@@ -76,11 +76,12 @@ replace into t1 values (1),(2);
|
||||
replace into t1 values (1),(2);
|
||||
|
||||
--connection con1
|
||||
--error ER_DUP_ENTRY
|
||||
replace into t1 values (1),(2);
|
||||
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-14794 Limitations which the row end as a part of PK imposes due to
|
||||
--echo # CURRENT_TIMESTAMP behavior and otherwise
|
||||
--echo #
|
||||
--echo # MDEV-15330 Server crash or assertion `table->insert_values' failure in write_record upon LOAD DATA
|
||||
--echo #
|
||||
@@ -116,4 +117,61 @@ alter table t1 add system versioning;
|
||||
replace into t1 values ('o'), ('o');
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-15990 REPLACE on a precise-versioned table returns duplicate key
|
||||
--echo # error (ER_DUP_ENTRY)
|
||||
--echo #
|
||||
|
||||
--replace_result $sys_datatype_expl SYS_DATATYPE "$KEY_TYPE" KEY_TYPE
|
||||
eval create or replace table t1 (
|
||||
pk int $KEY_TYPE, i int,
|
||||
row_start $sys_datatype_expl as row start invisible,
|
||||
row_end $sys_datatype_expl as row end invisible,
|
||||
period for system_time(row_start, row_end)
|
||||
) with system versioning;
|
||||
replace into t1 (pk,i) values (1,10),(1,100),(1,1000);
|
||||
select pk, i, check_row(row_start, row_end) from t1 for system_time all;
|
||||
drop table t1;
|
||||
|
||||
--replace_result $sys_datatype_expl SYS_DATATYPE "$KEY_TYPE" KEY_TYPE
|
||||
eval create or replace table t1 (
|
||||
pk int $KEY_TYPE, i int,
|
||||
row_start $sys_datatype_expl as row start invisible,
|
||||
row_end $sys_datatype_expl as row end invisible,
|
||||
period for system_time(row_start, row_end)
|
||||
) with system versioning;
|
||||
set timestamp= (select unix_timestamp());
|
||||
begin;
|
||||
insert t1(pk, i) values(1,3);
|
||||
delete from t1;
|
||||
insert t1(pk, i) values(1,30);
|
||||
delete from t1;
|
||||
insert t1(pk, i) values(1,300);
|
||||
commit;
|
||||
select pk, i, check_row(row_start, row_end) from t1 for system_time all;
|
||||
drop table t1;
|
||||
|
||||
--echo # In this case there'll be no unique constraint on a historical row.
|
||||
--replace_result $sys_datatype_expl SYS_DATATYPE
|
||||
eval create or replace table t1 (
|
||||
pk int, i int,
|
||||
row_start $sys_datatype_expl as row start invisible,
|
||||
row_end $sys_datatype_expl as row end invisible,
|
||||
period for system_time(row_start, row_end)
|
||||
) with system versioning;
|
||||
set timestamp= (select unix_timestamp());
|
||||
begin;
|
||||
insert t1(pk, i) values(1,3);
|
||||
delete from t1;
|
||||
insert t1(pk, i) values(1,30);
|
||||
delete from t1;
|
||||
insert t1(pk, i) values(1,300);
|
||||
commit;
|
||||
select pk, i, check_row(row_start, row_end) from t1 for system_time all;
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.5 tests
|
||||
--echo #
|
||||
|
||||
--source suite/versioning/common_finish.inc
|
||||
|
||||
@@ -53,8 +53,8 @@ SELECT IF(LOCATE('.', ibp.table_name) = 0, 'InnoDB System', REPLACE(SUBSTRING_IN
|
||||
sys.format_bytes(SUM(IF(ibp.compressed_size = 0, 16384, compressed_size))) AS allocated,
|
||||
sys.format_bytes(SUM(ibp.data_size)) AS data,
|
||||
COUNT(ibp.page_number) AS pages,
|
||||
COUNT(IF(ibp.is_hashed = 'YES', 1, NULL)) AS pages_hashed,
|
||||
COUNT(IF(ibp.is_old = 'YES', 1, NULL)) AS pages_old,
|
||||
COUNT(IF(ibp.is_hashed, 1, NULL)) AS pages_hashed,
|
||||
COUNT(IF(ibp.is_old, 1, NULL)) AS pages_old,
|
||||
ROUND(SUM(ibp.number_records)/COUNT(DISTINCT ibp.index_name)) AS rows_cached
|
||||
FROM information_schema.innodb_buffer_page ibp
|
||||
WHERE table_name IS NOT NULL
|
||||
@@ -62,4 +62,3 @@ SELECT IF(LOCATE('.', ibp.table_name) = 0, 'InnoDB System', REPLACE(SUBSTRING_IN
|
||||
ORDER BY SUM(IF(ibp.compressed_size = 0, 16384, compressed_size)) DESC;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
|
||||
@@ -56,12 +56,12 @@ SELECT IF(LOCATE('.', ibp.table_name) = 0, 'InnoDB System', REPLACE(SUBSTRING_IN
|
||||
sys.format_bytes(SUM(IF(ibp.compressed_size = 0, 16384, compressed_size))) AS allocated,
|
||||
sys.format_bytes(SUM(ibp.data_size)) AS data,
|
||||
COUNT(ibp.page_number) AS pages,
|
||||
COUNT(IF(ibp.is_hashed = 'YES', 1, NULL)) AS pages_hashed,
|
||||
COUNT(IF(ibp.is_old = 'YES', 1, NULL)) AS pages_old,
|
||||
COUNT(IF(ibp.is_hashed, 1, NULL)) AS pages_hashed,
|
||||
COUNT(IF(ibp.is_old, 1, NULL)) AS pages_old,
|
||||
ROUND(SUM(ibp.number_records)/COUNT(DISTINCT ibp.index_name)) AS rows_cached
|
||||
FROM information_schema.innodb_buffer_page ibp
|
||||
WHERE table_name IS NOT NULL
|
||||
GROUP BY object_schema, object_name
|
||||
ORDER BY SUM(IF(ibp.compressed_size = 0, 16384, compressed_size)) DESC;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
DELIMITER ;
|
||||
|
||||
@@ -63,4 +63,4 @@ SELECT IF(LOCATE('.', ibp.table_name) = 0, 'InnoDB System', REPLACE(SUBSTRING_IN
|
||||
GROUP BY object_schema, object_name
|
||||
ORDER BY SUM(IF(ibp.compressed_size = 0, 16384, compressed_size)) DESC;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
DELIMITER ;
|
||||
|
||||
12
sql/field.cc
12
sql/field.cc
@@ -4723,17 +4723,17 @@ void Field_longlong::set_max()
|
||||
int8store(ptr, unsigned_flag ? ULONGLONG_MAX : LONGLONG_MAX);
|
||||
}
|
||||
|
||||
bool Field_longlong::is_max()
|
||||
bool Field_longlong::is_max(const uchar *ptr_arg) const
|
||||
{
|
||||
DBUG_ASSERT(marked_for_read());
|
||||
if (unsigned_flag)
|
||||
{
|
||||
ulonglong j;
|
||||
j= uint8korr(ptr);
|
||||
j= uint8korr(ptr_arg);
|
||||
return j == ULONGLONG_MAX;
|
||||
}
|
||||
longlong j;
|
||||
j= sint8korr(ptr);
|
||||
j= sint8korr(ptr_arg);
|
||||
return j == LONGLONG_MAX;
|
||||
}
|
||||
|
||||
@@ -5792,13 +5792,13 @@ void Field_timestampf::set_max()
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
bool Field_timestampf::is_max()
|
||||
bool Field_timestampf::is_max(const uchar *ptr_arg) const
|
||||
{
|
||||
DBUG_ENTER("Field_timestampf::is_max");
|
||||
DBUG_ASSERT(marked_for_read());
|
||||
|
||||
DBUG_RETURN(mi_sint4korr(ptr) == TIMESTAMP_MAX_VALUE &&
|
||||
mi_sint3korr(ptr + 4) == TIME_MAX_SECOND_PART);
|
||||
DBUG_RETURN(mi_sint4korr(ptr_arg) == TIMESTAMP_MAX_VALUE &&
|
||||
mi_sint3korr(ptr_arg + 4) == TIME_MAX_SECOND_PART);
|
||||
}
|
||||
|
||||
my_time_t Field_timestampf::get_timestamp(const uchar *pos,
|
||||
|
||||
19
sql/field.h
19
sql/field.h
@@ -799,8 +799,9 @@ public:
|
||||
*/
|
||||
virtual void set_max()
|
||||
{ DBUG_ASSERT(0); }
|
||||
virtual bool is_max()
|
||||
virtual bool is_max(const uchar *ptr_arg) const
|
||||
{ DBUG_ASSERT(0); return false; }
|
||||
bool is_max() const { return is_max(ptr); }
|
||||
|
||||
uchar *ptr; // Position to field in record
|
||||
|
||||
@@ -2862,7 +2863,7 @@ public:
|
||||
return unpack_int64(to, from, from_end);
|
||||
}
|
||||
void set_max() override;
|
||||
bool is_max() override;
|
||||
bool is_max(const uchar *ptr_arg) const override;
|
||||
ulonglong get_max_int_value() const override
|
||||
{
|
||||
return unsigned_flag ? 0xFFFFFFFFFFFFFFFFULL : 0x7FFFFFFFFFFFFFFFULL;
|
||||
@@ -3442,7 +3443,7 @@ public:
|
||||
return memcmp(a_ptr, b_ptr, pack_length());
|
||||
}
|
||||
void set_max() override;
|
||||
bool is_max() override;
|
||||
bool is_max(const uchar *ptr_arg) const override;
|
||||
my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const override;
|
||||
bool val_native(Native *to) override;
|
||||
uint size_of() const override { return sizeof *this; }
|
||||
@@ -5981,17 +5982,21 @@ bool check_expression(Virtual_column_info *vcol, const LEX_CSTRING *name,
|
||||
#define f_visibility(x) (static_cast<field_visibility_t> ((x) & INVISIBLE_MAX_BITS))
|
||||
|
||||
inline
|
||||
ulonglong TABLE::vers_end_id() const
|
||||
ulonglong TABLE::vers_end_id(const uchar *record_arg) const
|
||||
{
|
||||
DBUG_ASSERT(versioned(VERS_TRX_ID));
|
||||
return static_cast<ulonglong>(vers_end_field()->val_int());
|
||||
DBUG_ASSERT(dynamic_cast<Field_longlong*>(vers_end_field()));
|
||||
const uchar *ptr= vers_end_field()->ptr_in_record(record_arg);
|
||||
return static_cast<ulonglong>(sint8korr(ptr));
|
||||
}
|
||||
|
||||
inline
|
||||
ulonglong TABLE::vers_start_id() const
|
||||
ulonglong TABLE::vers_start_id(const uchar *record_arg) const
|
||||
{
|
||||
DBUG_ASSERT(versioned(VERS_TRX_ID));
|
||||
return static_cast<ulonglong>(vers_start_field()->val_int());
|
||||
DBUG_ASSERT(dynamic_cast<Field_longlong*>(vers_start_field()));
|
||||
const uchar *ptr= vers_start_field()->ptr_in_record(record_arg);
|
||||
return static_cast<ulonglong>(sint8korr(ptr));
|
||||
}
|
||||
|
||||
double pos_in_interval_for_string(CHARSET_INFO *cset,
|
||||
|
||||
@@ -5200,12 +5200,6 @@ uint handler::get_dup_key(int error)
|
||||
DBUG_RETURN(errkey);
|
||||
}
|
||||
|
||||
bool handler::has_dup_ref() const
|
||||
{
|
||||
DBUG_ASSERT(lookup_errkey != (uint)-1 || errkey != (uint)-1);
|
||||
return ha_table_flags() & HA_DUPLICATE_POS || lookup_errkey != (uint)-1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Delete all files with extension from bas_ext().
|
||||
@@ -7795,8 +7789,12 @@ int handler::ha_check_overlaps(const uchar *old_data, const uchar* new_data)
|
||||
DBUG_ASSERT(this == table->file);
|
||||
if (!table_share->period.unique_keys)
|
||||
return 0;
|
||||
if (table->versioned() && !table->vers_end_field()->is_max())
|
||||
return 0;
|
||||
if (table->versioned())
|
||||
{
|
||||
Field *end= table->vers_end_field();
|
||||
if (!end->is_max(end->ptr_in_record(new_data)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
const bool after_write= ha_table_flags() & HA_CHECK_UNIQUE_AFTER_WRITE;
|
||||
const bool is_update= !after_write && old_data;
|
||||
|
||||
@@ -3227,7 +3227,6 @@ protected:
|
||||
Table_flags cached_table_flags; /* Set on init() and open() */
|
||||
|
||||
ha_rows estimation_rows_to_insert;
|
||||
handler *lookup_handler;
|
||||
/* Statistics for the query. Updated if handler_stats.active is set */
|
||||
ha_handler_stats active_handler_stats;
|
||||
void set_handler_stats();
|
||||
@@ -3237,6 +3236,7 @@ public:
|
||||
uchar *ref; /* Pointer to current row */
|
||||
uchar *dup_ref; /* Pointer to duplicate row */
|
||||
uchar *lookup_buffer;
|
||||
handler *lookup_handler;
|
||||
|
||||
/* General statistics for the table like number of row, file sizes etc */
|
||||
ha_statistics stats;
|
||||
@@ -3442,9 +3442,8 @@ public:
|
||||
handler(handlerton *ht_arg, TABLE_SHARE *share_arg)
|
||||
:table_share(share_arg), table(0),
|
||||
estimation_rows_to_insert(0),
|
||||
lookup_handler(this),
|
||||
ht(ht_arg), costs(0), ref(0), lookup_buffer(NULL), handler_stats(NULL),
|
||||
end_range(NULL), implicit_emptied(0),
|
||||
ht(ht_arg), costs(0), ref(0), lookup_buffer(NULL), lookup_handler(this),
|
||||
handler_stats(NULL), end_range(NULL), implicit_emptied(0),
|
||||
mark_trx_read_write_done(0),
|
||||
check_table_binlog_row_based_done(0),
|
||||
check_table_binlog_row_based_result(0),
|
||||
@@ -3656,7 +3655,6 @@ public:
|
||||
virtual void print_error(int error, myf errflag);
|
||||
virtual bool get_error_message(int error, String *buf);
|
||||
uint get_dup_key(int error);
|
||||
bool has_dup_ref() const;
|
||||
/**
|
||||
Retrieves the names of the table and the key for which there was a
|
||||
duplicate entry in the case of HA_ERR_FOREIGN_DUPLICATE_KEY.
|
||||
|
||||
36
sql/item.cc
36
sql/item.cc
@@ -2896,8 +2896,6 @@ Item_sp::func_name_cstring(THD *thd, bool is_package_function) const
|
||||
void
|
||||
Item_sp::cleanup()
|
||||
{
|
||||
delete sp_result_field;
|
||||
sp_result_field= NULL;
|
||||
m_sp= NULL;
|
||||
delete func_ctx;
|
||||
func_ctx= NULL;
|
||||
@@ -3069,7 +3067,6 @@ Item_sp::init_result_field(THD *thd, uint max_length, uint maybe_null,
|
||||
DBUG_ENTER("Item_sp::init_result_field");
|
||||
|
||||
DBUG_ASSERT(m_sp != NULL);
|
||||
DBUG_ASSERT(sp_result_field == NULL);
|
||||
|
||||
/*
|
||||
A Field needs to be attached to a Table.
|
||||
@@ -3083,23 +3080,26 @@ Item_sp::init_result_field(THD *thd, uint max_length, uint maybe_null,
|
||||
dummy_table->s->table_name= empty_clex_str;
|
||||
dummy_table->maybe_null= maybe_null;
|
||||
|
||||
if (!(sp_result_field= m_sp->create_result_field(max_length, name,
|
||||
dummy_table)))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
if (sp_result_field->pack_length() > sizeof(result_buf))
|
||||
if (!sp_result_field)
|
||||
{
|
||||
void *tmp;
|
||||
if (!(tmp= thd->alloc(sp_result_field->pack_length())))
|
||||
DBUG_RETURN(TRUE);
|
||||
sp_result_field->move_field((uchar*) tmp);
|
||||
sp_result_field= m_sp->create_result_field(max_length, name,
|
||||
dummy_table);
|
||||
if (!sp_result_field)
|
||||
DBUG_RETURN(true);
|
||||
|
||||
if (sp_result_field->pack_length() > sizeof(result_buf))
|
||||
{
|
||||
void *tmp;
|
||||
if (!(tmp= thd->alloc(sp_result_field->pack_length())))
|
||||
DBUG_RETURN(TRUE);
|
||||
sp_result_field->move_field((uchar*) tmp);
|
||||
}
|
||||
else
|
||||
sp_result_field->move_field(result_buf);
|
||||
|
||||
sp_result_field->null_ptr= (uchar *) null_value;
|
||||
sp_result_field->null_bit= 1;
|
||||
}
|
||||
else
|
||||
sp_result_field->move_field(result_buf);
|
||||
|
||||
sp_result_field->null_ptr= (uchar *) null_value;
|
||||
sp_result_field->null_bit= 1;
|
||||
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
||||
@@ -5849,6 +5849,11 @@ public:
|
||||
Field *sp_result_field;
|
||||
Item_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name_arg);
|
||||
Item_sp(THD *thd, Item_sp *item);
|
||||
virtual ~Item_sp()
|
||||
{
|
||||
delete sp_result_field;
|
||||
sp_result_field= NULL;
|
||||
}
|
||||
LEX_CSTRING func_name_cstring(THD *thd, bool is_package_function) const;
|
||||
void cleanup();
|
||||
bool sp_check_access(THD *thd);
|
||||
|
||||
@@ -6848,12 +6848,29 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
Query_arena *arena, backup;
|
||||
/*
|
||||
Allocation an instance of Item_func_sp used for initialization of
|
||||
sp_result_field taken place inside the method init_result_field() is done
|
||||
on sp_head's mem_root since Item_sp also allocated on this memory root.
|
||||
|
||||
Switching to SP/PS memory root is done explicitly before calling the method
|
||||
init_result_field() instead doing that inside init_result_field()
|
||||
since for the case when rollup aggregate function is handled
|
||||
(@see Item_sum_sp::copy_or_same, @see JOIN::rollup_make_fields)
|
||||
the runtime arena used for operations, so switching to SP/PS arena for this
|
||||
case would result in assertion failure on second execution of the same
|
||||
prepared statement because the memory root be already marked as read only.
|
||||
*/
|
||||
arena= thd->activate_stmt_arena_if_needed(&backup);
|
||||
/*
|
||||
We must call init_result_field before Item_func::fix_fields()
|
||||
to make m_sp and result_field members available to fix_length_and_dec(),
|
||||
which is called from Item_func::fix_fields().
|
||||
*/
|
||||
res= init_result_field(thd, max_length, maybe_null(), &null_value, &name);
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
|
||||
if (res)
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
@@ -1742,9 +1742,16 @@ bool Item_func_json_contains_path::val_bool()
|
||||
longlong result;
|
||||
json_path_t p;
|
||||
int n_found;
|
||||
LINT_INIT(n_found);
|
||||
int array_sizes[JSON_DEPTH_LIMIT];
|
||||
uint has_negative_path= 0;
|
||||
#if defined(FORCE_INIT_OF_VARS)
|
||||
/*
|
||||
Initialization force not required after gcc 13.3
|
||||
where it correctly sees that an uninitialized read
|
||||
of n_found doesn't occur with mode_one being true.
|
||||
*/
|
||||
n_found= 0;
|
||||
#endif
|
||||
|
||||
if ((null_value= args[0]->null_value))
|
||||
return 0;
|
||||
@@ -1784,8 +1791,6 @@ bool Item_func_json_contains_path::val_bool()
|
||||
bzero(p_found, (arg_count-2) * sizeof(bool));
|
||||
n_found= arg_count - 2;
|
||||
}
|
||||
else
|
||||
n_found= 0; /* Just to prevent 'uninitialized value' warnings */
|
||||
|
||||
result= 0;
|
||||
while (json_get_path_next(&je, &p) == 0)
|
||||
@@ -2658,7 +2663,6 @@ String *Item_func_json_merge::val_str(String *str)
|
||||
String *js1= args[0]->val_json(&tmp_js1), *js2=NULL;
|
||||
uint n_arg;
|
||||
THD *thd= current_thd;
|
||||
LINT_INIT(js2);
|
||||
|
||||
JSON_DO_PAUSE_EXECUTION(thd, 0.0002);
|
||||
|
||||
|
||||
@@ -1365,8 +1365,16 @@ Item_sum_sp::fix_fields(THD *thd, Item **ref)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (init_result_field(thd, max_length, maybe_null(), &null_value, &name))
|
||||
return TRUE;
|
||||
Query_arena *arena, backup;
|
||||
arena= thd->activate_stmt_arena_if_needed(&backup);
|
||||
|
||||
bool ret= init_result_field(thd, max_length, maybe_null(),
|
||||
&null_value, &name);
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
|
||||
if(ret)
|
||||
return true;
|
||||
|
||||
for (uint i= 0 ; i < arg_count ; i++)
|
||||
{
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "rpl_record.h"
|
||||
#include "rpl_reporting.h"
|
||||
#include "sql_class.h" /* THD */
|
||||
#include "sql_insert.h"
|
||||
#else
|
||||
typedef ulong enum_slave_exec_mode;
|
||||
#endif
|
||||
@@ -4476,7 +4477,7 @@ public:
|
||||
enum_logged_status logged_status() override { return LOGGED_TABLE_MAP; }
|
||||
bool is_valid() const override { return m_memory != NULL; /* we check malloc */ }
|
||||
|
||||
int get_data_size() override { return (uint) m_data_size; }
|
||||
int get_data_size() override { return (uint) m_data_size; }
|
||||
#ifdef MYSQL_SERVER
|
||||
#ifdef HAVE_REPLICATION
|
||||
bool is_part_of_group() override { return 1; }
|
||||
@@ -4901,7 +4902,6 @@ protected:
|
||||
uint find_key_parts(const KEY *key) const;
|
||||
bool use_pk_position() const;
|
||||
int find_row(rpl_group_info *);
|
||||
int write_row(rpl_group_info *, const bool);
|
||||
int update_sequence();
|
||||
|
||||
// Unpack the current row into m_table->record[0], but with
|
||||
@@ -4965,7 +4965,8 @@ private:
|
||||
error code otherwise.
|
||||
*/
|
||||
virtual
|
||||
int do_before_row_operations(const rpl_group_info *) = 0;
|
||||
int do_before_row_operations(rpl_group_info *log, COPY_INFO *,
|
||||
Write_record *) = 0;
|
||||
|
||||
/**
|
||||
@brief Primitive to clean up after a sequence of row executions.
|
||||
@@ -5045,6 +5046,8 @@ public:
|
||||
{
|
||||
*rows += m_row_count;
|
||||
}
|
||||
|
||||
int incomplete_record_callback(rpl_group_info *rgi);
|
||||
#endif
|
||||
|
||||
private:
|
||||
@@ -5055,7 +5058,10 @@ private:
|
||||
#endif
|
||||
|
||||
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
|
||||
int do_before_row_operations(const rpl_group_info *) override;
|
||||
Write_record *m_write_record;
|
||||
int write_row(rpl_group_info *, bool);
|
||||
int do_before_row_operations(rpl_group_info *, COPY_INFO *,
|
||||
Write_record *) override;
|
||||
int do_after_row_operations(int) override;
|
||||
int do_exec_row(rpl_group_info *) override;
|
||||
#endif
|
||||
@@ -5144,7 +5150,8 @@ protected:
|
||||
#endif
|
||||
|
||||
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
|
||||
int do_before_row_operations(const rpl_group_info *) override;
|
||||
int do_before_row_operations(rpl_group_info *rgi, COPY_INFO *,
|
||||
Write_record *) override;
|
||||
int do_after_row_operations(int) override;
|
||||
int do_exec_row(rpl_group_info *) override;
|
||||
#endif /* defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) */
|
||||
@@ -5235,7 +5242,8 @@ protected:
|
||||
#endif
|
||||
|
||||
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
|
||||
int do_before_row_operations(const rpl_group_info *const) override;
|
||||
int do_before_row_operations(rpl_group_info *rgi, COPY_INFO *,
|
||||
Write_record *) override;
|
||||
int do_after_row_operations(int) override;
|
||||
int do_exec_row(rpl_group_info *) override;
|
||||
#endif
|
||||
|
||||
@@ -5067,7 +5067,13 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
|
||||
Rows_log_event::Db_restore_ctx restore_ctx(this);
|
||||
master_had_triggers= table->master_had_triggers;
|
||||
bool transactional_table= table->file->has_transactions_and_rollback();
|
||||
table->file->prepare_for_insert(get_general_type_code() != WRITE_ROWS_EVENT);
|
||||
|
||||
Rpl_table_data rpl_data= *(RPL_TABLE_LIST*)table->pos_in_table_list;
|
||||
if (!rpl_data.is_online_alter())
|
||||
this->slave_exec_mode= (enum_slave_exec_mode)slave_exec_mode_options;
|
||||
|
||||
table->file->prepare_for_insert(get_general_type_code() != WRITE_ROWS_EVENT
|
||||
|| slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT);
|
||||
|
||||
/*
|
||||
table == NULL means that this table should not be replicated
|
||||
@@ -5078,9 +5084,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
|
||||
if (m_width == table->s->fields && bitmap_is_set_all(&m_cols))
|
||||
set_flags(COMPLETE_ROWS_F);
|
||||
|
||||
Rpl_table_data rpl_data= *(RPL_TABLE_LIST*)table->pos_in_table_list;
|
||||
|
||||
/*
|
||||
/*
|
||||
Set tables write and read sets.
|
||||
|
||||
Read_set contains all slave columns (in case we are going to fetch
|
||||
@@ -5121,11 +5125,10 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
|
||||
}
|
||||
m_table->mark_columns_per_binlog_row_image();
|
||||
|
||||
if (!rpl_data.is_online_alter())
|
||||
this->slave_exec_mode= (enum_slave_exec_mode)slave_exec_mode_options;
|
||||
|
||||
// Do event specific preparations
|
||||
error= do_before_row_operations(rgi);
|
||||
COPY_INFO copy_info;
|
||||
Write_record write_record;
|
||||
// Do event specific preparations
|
||||
error= do_before_row_operations(rgi, ©_info, &write_record);
|
||||
|
||||
/*
|
||||
Bug#56662 Assertion failed: next_insert_id == 0, file handler.cc
|
||||
@@ -5257,7 +5260,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
|
||||
/*
|
||||
@todo We should probably not call
|
||||
reset_current_stmt_binlog_format_row() from here.
|
||||
|
||||
|
||||
Note: this applies to log_event_old.cc too.
|
||||
/Sven
|
||||
*/
|
||||
@@ -6500,8 +6503,21 @@ bool Write_rows_compressed_log_event::write(Log_event_writer *writer)
|
||||
|
||||
|
||||
#if defined(HAVE_REPLICATION)
|
||||
int
|
||||
Write_rows_log_event::do_before_row_operations(const rpl_group_info *)
|
||||
|
||||
int Write_rows_log_event::incomplete_record_callback(rpl_group_info *rgi)
|
||||
{
|
||||
restore_record(m_table,record[1]);
|
||||
int error= unpack_current_row(rgi);
|
||||
if (!error && m_table->s->long_unique_table)
|
||||
error= m_table->update_virtual_fields(m_table->file, VCOL_UPDATE_FOR_WRITE);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Write_rows_log_event::do_before_row_operations(rpl_group_info *rgi,
|
||||
COPY_INFO *copy_info,
|
||||
Write_record *write_record)
|
||||
{
|
||||
int error= 0;
|
||||
|
||||
@@ -6575,6 +6591,39 @@ Write_rows_log_event::do_before_row_operations(const rpl_group_info *)
|
||||
m_table->mark_auto_increment_column(true);
|
||||
}
|
||||
|
||||
if (slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT &&
|
||||
(m_table->file->ha_table_flags() & HA_DUPLICATE_POS ||
|
||||
m_table->s->long_unique_table))
|
||||
error= m_table->file->ha_rnd_init_with_error(0);
|
||||
|
||||
if (!error)
|
||||
{
|
||||
bzero(copy_info, sizeof *copy_info);
|
||||
copy_info->handle_duplicates=
|
||||
slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT ?
|
||||
DUP_REPLACE : DUP_ERROR;
|
||||
copy_info->table_list= m_table->pos_in_table_list;
|
||||
|
||||
int (*callback)(void *, void*)= NULL;
|
||||
if (!get_flags(COMPLETE_ROWS_F))
|
||||
{
|
||||
/*
|
||||
If row is incomplete we will use the record found to fill
|
||||
missing columns.
|
||||
*/
|
||||
callback= [](void *e, void* r)->int {
|
||||
auto rgi= static_cast<rpl_group_info*>(r);
|
||||
auto event= static_cast<Write_rows_log_event*>(e);
|
||||
return event->incomplete_record_callback(rgi);
|
||||
};
|
||||
}
|
||||
new (write_record) Write_record(thd, m_table, copy_info,
|
||||
m_table->versioned(VERS_TIMESTAMP),
|
||||
m_table->triggers && do_invoke_trigger(),
|
||||
NULL, callback, this, rgi);
|
||||
m_write_record= write_record;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -6615,7 +6664,15 @@ Write_rows_log_event::do_after_row_operations(int error)
|
||||
{
|
||||
m_table->file->print_error(local_error, MYF(0));
|
||||
}
|
||||
return error? error : local_error;
|
||||
int rnd_error= 0;
|
||||
if (m_table->file->inited)
|
||||
{
|
||||
DBUG_ASSERT(slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT);
|
||||
DBUG_ASSERT(m_table->file->ha_table_flags() & HA_DUPLICATE_POS ||
|
||||
m_table->s->long_unique_table);
|
||||
rnd_error= m_table->file->ha_rnd_end();
|
||||
}
|
||||
return error? error : local_error ? local_error : rnd_error;
|
||||
}
|
||||
|
||||
bool Rows_log_event::process_triggers(trg_event_type event,
|
||||
@@ -6638,17 +6695,6 @@ bool Rows_log_event::process_triggers(trg_event_type event,
|
||||
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
/*
|
||||
Check if there are more UNIQUE keys after the given key.
|
||||
*/
|
||||
static int
|
||||
last_uniq_key(TABLE *table, uint keyno)
|
||||
{
|
||||
while (++keyno < table->s->keys)
|
||||
if (table->key_info[keyno].flags & HA_NOSAME)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -6750,22 +6796,20 @@ is_duplicate_key_error(int errcode)
|
||||
@c ha_update_row() or first deleted and then new record written.
|
||||
*/
|
||||
|
||||
int Rows_log_event::write_row(rpl_group_info *rgi, const bool overwrite)
|
||||
int Write_rows_log_event::write_row(rpl_group_info *rgi, const bool overwrite)
|
||||
{
|
||||
DBUG_ENTER("write_row");
|
||||
DBUG_ASSERT(m_table != NULL);
|
||||
DBUG_ASSERT(thd != NULL);
|
||||
|
||||
TABLE *table= m_table; // pointer to event's table
|
||||
int error;
|
||||
int UNINIT_VAR(keynum);
|
||||
const bool invoke_triggers= (m_table->triggers && do_invoke_trigger());
|
||||
auto_afree_ptr<char> key(NULL);
|
||||
|
||||
prepare_record(table, m_width, true);
|
||||
|
||||
/* unpack row into table->record[0] */
|
||||
if (unlikely((error= unpack_current_row(rgi))))
|
||||
int error= unpack_current_row(rgi);
|
||||
if (unlikely(error))
|
||||
{
|
||||
table->file->print_error(error, MYF(0));
|
||||
DBUG_RETURN(error);
|
||||
@@ -6834,176 +6878,11 @@ int Rows_log_event::write_row(rpl_group_info *rgi, const bool overwrite)
|
||||
my_sleep(20000););
|
||||
if (table->s->sequence)
|
||||
error= update_sequence();
|
||||
else while (unlikely(error= table->file->ha_write_row(table->record[0])))
|
||||
else
|
||||
{
|
||||
if (error == HA_ERR_LOCK_DEADLOCK || error == HA_ERR_LOCK_WAIT_TIMEOUT ||
|
||||
(keynum= table->file->get_dup_key(error)) < 0 || !overwrite)
|
||||
{
|
||||
DBUG_PRINT("info",("get_dup_key returns %d)", keynum));
|
||||
/*
|
||||
Deadlock, waiting for lock or just an error from the handler
|
||||
such as HA_ERR_FOUND_DUPP_KEY when overwrite is false.
|
||||
Retrieval of the duplicate key number may fail
|
||||
- either because the error was not "duplicate key" error
|
||||
- or because the information which key is not available
|
||||
*/
|
||||
table->file->print_error(error, MYF(0));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
/*
|
||||
We need to retrieve the old row into record[1] to be able to
|
||||
either update or delete the offending record. We either:
|
||||
error= m_write_record->write_record();
|
||||
|
||||
- use rnd_pos() with a row-id (available as dupp_row) to the
|
||||
offending row, if that is possible (MyISAM and Blackhole), or else
|
||||
|
||||
- use index_read_idx() with the key that is duplicated, to
|
||||
retrieve the offending row.
|
||||
*/
|
||||
if (table->file->ha_table_flags() & HA_DUPLICATE_POS)
|
||||
{
|
||||
DBUG_PRINT("info",("Locating offending record using rnd_pos()"));
|
||||
|
||||
if ((error= table->file->ha_rnd_init_with_error(0)))
|
||||
{
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
error= table->file->ha_rnd_pos(table->record[1], table->file->dup_ref);
|
||||
if (unlikely(error))
|
||||
{
|
||||
DBUG_PRINT("info",("rnd_pos() returns error %d",error));
|
||||
table->file->print_error(error, MYF(0));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
table->file->ha_rnd_end();
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_PRINT("info",("Locating offending record using index_read_idx()"));
|
||||
|
||||
if (table->file->extra(HA_EXTRA_FLUSH_CACHE))
|
||||
{
|
||||
DBUG_PRINT("info",("Error when setting HA_EXTRA_FLUSH_CACHE"));
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
|
||||
if (key.get() == NULL)
|
||||
{
|
||||
key.assign(static_cast<char*>(my_alloca(table->s->max_unique_length)));
|
||||
if (key.get() == NULL)
|
||||
{
|
||||
DBUG_PRINT("info",("Can't allocate key buffer"));
|
||||
DBUG_RETURN(ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
key_copy((uchar*)key.get(), table->record[0], table->key_info + keynum,
|
||||
0);
|
||||
error= table->file->ha_index_read_idx_map(table->record[1], keynum,
|
||||
(const uchar*)key.get(),
|
||||
HA_WHOLE_KEY,
|
||||
HA_READ_KEY_EXACT);
|
||||
if (unlikely(error))
|
||||
{
|
||||
DBUG_PRINT("info",("index_read_idx() returns %s", HA_ERR(error)));
|
||||
table->file->print_error(error, MYF(0));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Now, record[1] should contain the offending row. That
|
||||
will enable us to update it or, alternatively, delete it (so
|
||||
that we can insert the new row afterwards).
|
||||
*/
|
||||
if (table->s->long_unique_table)
|
||||
{
|
||||
/* same as for REPLACE/ODKU */
|
||||
table->move_fields(table->field, table->record[1], table->record[0]);
|
||||
table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE);
|
||||
table->move_fields(table->field, table->record[0], table->record[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
If row is incomplete we will use the record found to fill
|
||||
missing columns.
|
||||
*/
|
||||
if (!get_flags(COMPLETE_ROWS_F))
|
||||
{
|
||||
restore_record(table,record[1]);
|
||||
error= unpack_current_row(rgi);
|
||||
if (table->s->long_unique_table)
|
||||
table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_WRITE);
|
||||
}
|
||||
|
||||
DBUG_PRINT("debug",("preparing for update: before and after image"));
|
||||
DBUG_DUMP("record[1] (before)", table->record[1], table->s->reclength);
|
||||
DBUG_DUMP("record[0] (after)", table->record[0], table->s->reclength);
|
||||
|
||||
/*
|
||||
REPLACE is defined as either INSERT or DELETE + INSERT. If
|
||||
possible, we can replace it with an UPDATE, but that will not
|
||||
work on InnoDB if FOREIGN KEY checks are necessary.
|
||||
|
||||
I (Matz) am not sure of the reason for the last_uniq_key()
|
||||
check as, but I'm guessing that it's something along the
|
||||
following lines.
|
||||
|
||||
Suppose that we got the duplicate key to be a key that is not
|
||||
the last unique key for the table and we perform an update:
|
||||
then there might be another key for which the unique check will
|
||||
fail, so we're better off just deleting the row and inserting
|
||||
the correct row.
|
||||
|
||||
Additionally we don't use UPDATE if rbr triggers should be invoked -
|
||||
when triggers are used we want a simple and predictable execution path.
|
||||
*/
|
||||
if (last_uniq_key(table, keynum) && !invoke_triggers &&
|
||||
!table->file->referenced_by_foreign_key())
|
||||
{
|
||||
DBUG_PRINT("info",("Updating row using ha_update_row()"));
|
||||
error= table->file->ha_update_row(table->record[1],
|
||||
table->record[0]);
|
||||
switch (error) {
|
||||
|
||||
case HA_ERR_RECORD_IS_THE_SAME:
|
||||
DBUG_PRINT("info",("ignoring HA_ERR_RECORD_IS_THE_SAME error from"
|
||||
" ha_update_row()"));
|
||||
error= 0;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
||||
default:
|
||||
DBUG_PRINT("info",("ha_update_row() returns error %d",error));
|
||||
table->file->print_error(error, MYF(0));
|
||||
}
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_PRINT("info",("Deleting offending row and trying to write new one again"));
|
||||
if (invoke_triggers &&
|
||||
unlikely(process_triggers(TRG_EVENT_DELETE, TRG_ACTION_BEFORE,
|
||||
TRUE)))
|
||||
error= HA_ERR_GENERIC; // in case if error is not set yet
|
||||
else
|
||||
{
|
||||
if (unlikely((error= table->file->ha_delete_row(table->record[1]))))
|
||||
{
|
||||
DBUG_PRINT("info",("ha_delete_row() returns error %d",error));
|
||||
table->file->print_error(error, MYF(0));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
if (invoke_triggers &&
|
||||
unlikely(process_triggers(TRG_EVENT_DELETE, TRG_ACTION_AFTER,
|
||||
TRUE)))
|
||||
DBUG_RETURN(HA_ERR_GENERIC); // in case if error is not set yet
|
||||
}
|
||||
/* Will retry ha_write_row() with the offending row removed. */
|
||||
}
|
||||
DBUG_RETURN(error ? m_write_record->last_errno() : 0);
|
||||
}
|
||||
|
||||
if (invoke_triggers &&
|
||||
@@ -7110,7 +6989,7 @@ static bool record_compare(TABLE *table, bool vers_from_plain= false)
|
||||
/**
|
||||
Compare full record only if:
|
||||
- all fields were given values
|
||||
- there are no blob fields (otherwise we would also need
|
||||
- there are no blob fields (otherwise we would also need
|
||||
to compare blobs contents as well);
|
||||
- there are no varchar fields (otherwise we would also need
|
||||
to compare varchar contents as well);
|
||||
@@ -7794,7 +7673,9 @@ bool Delete_rows_compressed_log_event::write(Log_event_writer *writer)
|
||||
#if defined(HAVE_REPLICATION)
|
||||
|
||||
int
|
||||
Delete_rows_log_event::do_before_row_operations(const rpl_group_info *rgi)
|
||||
Delete_rows_log_event::do_before_row_operations(rpl_group_info *rgi,
|
||||
COPY_INFO*,
|
||||
Write_record*)
|
||||
{
|
||||
/*
|
||||
Increment the global status delete count variable
|
||||
@@ -7913,7 +7794,9 @@ void Update_rows_log_event::init(MY_BITMAP const *cols)
|
||||
#if defined(HAVE_REPLICATION)
|
||||
|
||||
int
|
||||
Update_rows_log_event::do_before_row_operations(const rpl_group_info *rgi)
|
||||
Update_rows_log_event::do_before_row_operations(rpl_group_info *rgi,
|
||||
COPY_INFO*,
|
||||
Write_record*)
|
||||
{
|
||||
/*
|
||||
Increment the global status update count variable
|
||||
@@ -7960,8 +7843,6 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
|
||||
return error;
|
||||
}
|
||||
|
||||
const bool history_change= m_table->versioned() ?
|
||||
!m_table->vers_end_field()->is_max() : false;
|
||||
TABLE_LIST *tl= m_table->pos_in_table_list;
|
||||
uint8 trg_event_map_save= tl->trg_event_map;
|
||||
|
||||
@@ -8012,8 +7893,12 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
|
||||
{
|
||||
if (m_vers_from_plain && m_table->versioned(VERS_TIMESTAMP))
|
||||
m_table->vers_update_fields();
|
||||
if (!history_change && !m_table->vers_end_field()->is_max())
|
||||
Field *end= m_table->vers_end_field();
|
||||
const uchar *old_ptr= end->ptr_in_record(m_table->record[1]);
|
||||
|
||||
if (end->is_max(old_ptr) && !end->is_max())
|
||||
{
|
||||
// This is a versioned delete, and we'll have to invoke ON DELETE actions
|
||||
tl->trg_event_map|= trg2bit(TRG_EVENT_DELETE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7683,7 +7683,7 @@ bool THD::binlog_for_noop_dml(bool transactional_table)
|
||||
}
|
||||
|
||||
|
||||
#if defined(DBUG_TRACE) && !defined(_lint)
|
||||
#if defined(DBUG_TRACE)
|
||||
static const char *
|
||||
show_query_type(THD::enum_binlog_query_type qtype)
|
||||
{
|
||||
@@ -7697,7 +7697,7 @@ show_query_type(THD::enum_binlog_query_type qtype)
|
||||
DBUG_ASSERT(0 <= qtype && qtype < THD::QUERY_TYPE_COUNT);
|
||||
}
|
||||
static char buf[64];
|
||||
sprintf(buf, "UNKNOWN#%d", qtype);
|
||||
snprintf(buf, sizeof(buf), "UNKNOWN#%d", qtype);
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6523,6 +6523,8 @@ public:
|
||||
int send_data(List<Item> &items) override;
|
||||
};
|
||||
|
||||
class Write_record; // defined in sql_insert.h
|
||||
|
||||
|
||||
class select_insert :public select_result_interceptor {
|
||||
public:
|
||||
@@ -6530,13 +6532,14 @@ class select_insert :public select_result_interceptor {
|
||||
TABLE_LIST *table_list;
|
||||
TABLE *table;
|
||||
List<Item> *fields;
|
||||
Write_record *write;
|
||||
ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not
|
||||
COPY_INFO info;
|
||||
bool insert_into_view;
|
||||
select_insert(THD *thd_arg, TABLE_LIST *table_list_par, TABLE *table_par,
|
||||
List<Item> *fields_par, List<Item> *update_fields,
|
||||
List<Item> *update_values, enum_duplicates duplic,
|
||||
bool ignore, select_result *sel_ret_list);
|
||||
bool ignore, select_result *sel_ret_list, Write_record *write);
|
||||
~select_insert();
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u) override;
|
||||
int prepare2(JOIN *join) override;
|
||||
@@ -6570,9 +6573,9 @@ public:
|
||||
Table_specification_st *create_info_par,
|
||||
Alter_info *alter_info_arg,
|
||||
List<Item> &select_fields,enum_duplicates duplic, bool ignore,
|
||||
TABLE_LIST *select_tables_arg):
|
||||
TABLE_LIST *select_tables_arg, Write_record *write):
|
||||
select_insert(thd_arg, table_arg, NULL, &select_fields, 0, 0, duplic,
|
||||
ignore, NULL),
|
||||
ignore, NULL, write),
|
||||
create_info(create_info_par),
|
||||
select_tables(select_tables_arg),
|
||||
alter_info(alter_info_arg),
|
||||
|
||||
@@ -288,25 +288,88 @@ int update_portion_of_time(THD *thd, TABLE *table,
|
||||
return res;
|
||||
}
|
||||
|
||||
inline
|
||||
int TABLE::delete_row()
|
||||
{
|
||||
if (!versioned(VERS_TIMESTAMP) || !vers_end_field()->is_max())
|
||||
return file->ha_delete_row(record[0]);
|
||||
/**
|
||||
Delete a record stored in:
|
||||
replace= true: record[0]
|
||||
replace= false: record[1]
|
||||
|
||||
with regard to the treat_versioned flag, which can be false for a versioned
|
||||
table in case of versioned->versioned replication.
|
||||
|
||||
For a versioned case, we detect a few conditions, under which we should delete
|
||||
a row instead of updating it to a history row.
|
||||
This includes:
|
||||
* History deletion by user;
|
||||
* History collision, in case of REPLACE or very fast sequence of dmls
|
||||
so that timestamp doesn't change;
|
||||
* History collision in the parent table
|
||||
|
||||
A normal delete is processed here as well.
|
||||
*/
|
||||
template <bool replace>
|
||||
int TABLE::delete_row(bool treat_versioned)
|
||||
{
|
||||
int err= 0;
|
||||
uchar *del_buf= record[replace ? 1 : 0];
|
||||
|
||||
bool delete_row= !treat_versioned
|
||||
|| in_use->lex->vers_conditions.delete_history
|
||||
|| versioned(VERS_TRX_ID)
|
||||
|| !vers_end_field()->is_max(
|
||||
vers_end_field()->ptr_in_record(del_buf));
|
||||
if (!delete_row)
|
||||
{
|
||||
if (replace)
|
||||
{
|
||||
store_record(this, record[2]);
|
||||
restore_record(this, record[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
store_record(this, record[1]);
|
||||
}
|
||||
vers_update_end();
|
||||
|
||||
Field *row_start= vers_start_field();
|
||||
Field *row_end= vers_end_field();
|
||||
// Don't make history row with negative lifetime
|
||||
delete_row= row_start->cmp(row_start->ptr, row_end->ptr) > 0;
|
||||
|
||||
if (likely(!delete_row))
|
||||
err= file->ha_update_row(record[1], record[0]);
|
||||
if (unlikely(err))
|
||||
{
|
||||
/*
|
||||
MDEV-23644: we get HA_ERR_FOREIGN_DUPLICATE_KEY iff we already got
|
||||
history row with same trx_id which is the result of foreign key
|
||||
action, so we don't need one more history row.
|
||||
|
||||
Additionally, delete the row if versioned record already exists.
|
||||
This happens on replace, a very fast sequence of inserts and deletes,
|
||||
or if timestamp is frozen.
|
||||
*/
|
||||
delete_row= err == HA_ERR_FOUND_DUPP_KEY
|
||||
|| err == HA_ERR_FOUND_DUPP_UNIQUE
|
||||
|| err == HA_ERR_FOREIGN_DUPLICATE_KEY;
|
||||
if (!delete_row)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (delete_row)
|
||||
del_buf= record[1];
|
||||
|
||||
if (replace)
|
||||
restore_record(this, record[2]);
|
||||
}
|
||||
|
||||
if (delete_row)
|
||||
err= file->ha_delete_row(del_buf);
|
||||
|
||||
store_record(this, record[1]);
|
||||
vers_update_end();
|
||||
int err= file->ha_update_row(record[1], record[0]);
|
||||
/*
|
||||
MDEV-23644: we get HA_ERR_FOREIGN_DUPLICATE_KEY iff we already got history
|
||||
row with same trx_id which is the result of foreign key action, so we
|
||||
don't need one more history row.
|
||||
*/
|
||||
if (err == HA_ERR_FOREIGN_DUPLICATE_KEY)
|
||||
return file->ha_delete_row(record[0]);
|
||||
return err;
|
||||
}
|
||||
|
||||
template int TABLE::delete_row<true>(bool treat_versioned);
|
||||
template int TABLE::delete_row<false>(bool treat_versioned);
|
||||
|
||||
/**
|
||||
@brief Special handling of single-table deletes after prepare phase
|
||||
@@ -1401,7 +1464,7 @@ int multi_delete::do_table_deletes(TABLE *table, SORT_INFO *sort_info,
|
||||
during ha_delete_row.
|
||||
Also, don't execute the AFTER trigger if the row operation failed.
|
||||
*/
|
||||
if (unlikely(!local_error))
|
||||
if (likely(!local_error))
|
||||
{
|
||||
deleted++;
|
||||
if (table->triggers &&
|
||||
|
||||
1063
sql/sql_insert.cc
1063
sql/sql_insert.cc
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,7 @@
|
||||
typedef List<Item> List_item;
|
||||
typedef struct st_copy_info COPY_INFO;
|
||||
|
||||
|
||||
int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
|
||||
List<Item> &fields, List_item *values,
|
||||
List<Item> &update_fields,
|
||||
@@ -46,7 +47,10 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info,
|
||||
void kill_delayed_threads(void);
|
||||
bool binlog_create_table(THD *thd, TABLE *table, bool replace);
|
||||
bool binlog_drop_table(THD *thd, TABLE *table);
|
||||
|
||||
int prepare_for_replace(TABLE *table, enum_duplicates handle_duplicates,
|
||||
bool ignore);
|
||||
int finalize_replace(TABLE *table, enum_duplicates handle_duplicates,
|
||||
bool ignore);
|
||||
static inline void restore_default_record_for_insert(TABLE *t)
|
||||
{
|
||||
restore_record(t,s->default_values);
|
||||
@@ -54,6 +58,88 @@ static inline void restore_default_record_for_insert(TABLE *t)
|
||||
t->triggers->default_extra_null_bitmap();
|
||||
}
|
||||
|
||||
|
||||
class Write_record
|
||||
{
|
||||
THD *thd;
|
||||
TABLE *table;
|
||||
COPY_INFO *info;
|
||||
|
||||
ulonglong prev_insert_id;
|
||||
ulonglong insert_id_for_cur_row= 0;
|
||||
uchar *key;
|
||||
ushort key_nr;
|
||||
|
||||
ushort last_unique_key;
|
||||
bool use_triggers;
|
||||
bool versioned;
|
||||
bool can_optimize;
|
||||
bool ignored_error;
|
||||
|
||||
int (*incomplete_records_cb)(void *arg1, void *arg2);
|
||||
void *arg1, *arg2;
|
||||
select_result *sink;
|
||||
|
||||
ushort get_last_unique_key() const;
|
||||
// FINALIZATION
|
||||
void notify_non_trans_table_modified();
|
||||
int after_insert(ha_rows *inserted);
|
||||
int after_ins_trg();
|
||||
int send_data();
|
||||
|
||||
int on_ha_error(int error);
|
||||
int restore_on_error();
|
||||
|
||||
bool is_fatal_error(int error);
|
||||
int prepare_handle_duplicate(int error);
|
||||
int locate_dup_record();
|
||||
|
||||
int replace_row(ha_rows *inserted, ha_rows *deleted);
|
||||
int insert_on_duplicate_update(ha_rows *inserted, ha_rows *updated);
|
||||
int single_insert(ha_rows *inserted);
|
||||
public:
|
||||
|
||||
/**
|
||||
@param thd thread context
|
||||
@param info COPY_INFO structure describing handling of duplicates
|
||||
and which is used for counting number of records inserted
|
||||
and deleted.
|
||||
@param sink result sink for the RETURNING clause
|
||||
@param table
|
||||
@param versioned
|
||||
@param use_triggers
|
||||
*/
|
||||
Write_record(THD *thd, TABLE *table, COPY_INFO *info,
|
||||
bool versioned, bool use_triggers, select_result *sink,
|
||||
int (*incomplete_records_cb)(void *, void *),
|
||||
void *arg1, void* arg2):
|
||||
thd(thd), table(table), info(info), insert_id_for_cur_row(0),
|
||||
key(NULL), last_unique_key(get_last_unique_key()),
|
||||
use_triggers(use_triggers), versioned(versioned),
|
||||
incomplete_records_cb(incomplete_records_cb), arg1(arg1), arg2(arg2),
|
||||
sink(sink)
|
||||
{
|
||||
if (info->handle_duplicates == DUP_REPLACE)
|
||||
{
|
||||
bool has_delete_triggers= use_triggers &&
|
||||
table->triggers->has_delete_triggers();
|
||||
bool referenced_by_fk= table->file->referenced_by_foreign_key();
|
||||
can_optimize= !referenced_by_fk && !has_delete_triggers
|
||||
&& !versioned && !table->versioned();
|
||||
}
|
||||
}
|
||||
Write_record(THD *thd, TABLE *table, COPY_INFO *info,
|
||||
select_result *sink= NULL):
|
||||
Write_record(thd, table, info, table->versioned(VERS_TIMESTAMP),
|
||||
table->triggers, sink, NULL, NULL, NULL)
|
||||
{}
|
||||
Write_record() = default; // dummy, to allow later (lazy) initializations
|
||||
|
||||
/* Main entry point, see docs in sql_insert.cc */
|
||||
int write_record();
|
||||
|
||||
int last_errno() { return info->last_errno; }
|
||||
};
|
||||
#ifdef EMBEDDED_LIBRARY
|
||||
inline void kill_delayed_threads(void) {}
|
||||
#endif
|
||||
|
||||
@@ -836,9 +836,7 @@ public:
|
||||
inline void move_elements_to(I_List<T>* new_owner) {
|
||||
base_ilist::move_elements_to(new_owner);
|
||||
}
|
||||
#ifndef _lint
|
||||
friend class I_List_iterator<T>;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -684,14 +684,9 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list,
|
||||
thd->abort_on_warning= !ignore && thd->is_strict_mode();
|
||||
thd->get_stmt_da()->reset_current_row_for_warning(1);
|
||||
|
||||
bool create_lookup_handler= handle_duplicates != DUP_ERROR;
|
||||
if ((table_list->table->file->ha_table_flags() & HA_DUPLICATE_POS))
|
||||
{
|
||||
create_lookup_handler= true;
|
||||
if ((error= table_list->table->file->ha_rnd_init_with_error(0)))
|
||||
goto err;
|
||||
}
|
||||
table->file->prepare_for_insert(create_lookup_handler);
|
||||
if (prepare_for_replace(table, info.handle_duplicates, info.ignore))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
thd_progress_init(thd, 2);
|
||||
fix_rownum_pointers(thd, thd->lex->current_select, &info.copied);
|
||||
if (table_list->table->validate_default_values_of_unset_fields(thd))
|
||||
@@ -712,8 +707,8 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list,
|
||||
set_fields, set_values, read_info,
|
||||
*ex->enclosed, skip_lines, ignore);
|
||||
|
||||
if (table_list->table->file->ha_table_flags() & HA_DUPLICATE_POS)
|
||||
table_list->table->file->ha_rnd_end();
|
||||
if (unlikely(finalize_replace(table, handle_duplicates, ignore)))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
thd_proc_info(thd, "End bulk insert");
|
||||
if (likely(!error))
|
||||
@@ -1030,6 +1025,8 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
if ((thd->progress.max_counter= read_info.file_length()) == ~(my_off_t) 0)
|
||||
progress_reports= 0;
|
||||
|
||||
Write_record write(thd, table, &info, NULL);
|
||||
|
||||
while (!read_info.read_fixed_length())
|
||||
{
|
||||
if (thd->killed)
|
||||
@@ -1110,7 +1107,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
err= write_record(thd, table, &info);
|
||||
err= write.write_record();
|
||||
table->auto_increment_field_not_null= FALSE;
|
||||
if (err)
|
||||
DBUG_RETURN(1);
|
||||
@@ -1159,6 +1156,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
if ((thd->progress.max_counter= read_info.file_length()) == ~(my_off_t) 0)
|
||||
progress_reports= 0;
|
||||
|
||||
Write_record write(thd, table, &info, NULL);
|
||||
|
||||
for (;;it.rewind())
|
||||
{
|
||||
if (thd->killed)
|
||||
@@ -1260,7 +1259,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
err= write_record(thd, table, &info);
|
||||
err= write.write_record();
|
||||
table->auto_increment_field_not_null= FALSE;
|
||||
if (err)
|
||||
DBUG_RETURN(1);
|
||||
@@ -1304,7 +1303,9 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
DBUG_ENTER("read_xml_field");
|
||||
|
||||
no_trans_update_stmt= !table->file->has_transactions_and_rollback();
|
||||
|
||||
|
||||
Write_record write(thd, table, &info, NULL);
|
||||
|
||||
for ( ; ; it.rewind())
|
||||
{
|
||||
bool err;
|
||||
@@ -1381,7 +1382,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
err= write_record(thd, table, &info);
|
||||
err= write.write_record();
|
||||
table->auto_increment_field_not_null= false;
|
||||
if (err)
|
||||
DBUG_RETURN(1);
|
||||
|
||||
@@ -4648,6 +4648,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
|
||||
select_lex->context.table_list=
|
||||
select_lex->context.first_name_resolution_table= second_table;
|
||||
res= mysql_insert_select_prepare(thd, result);
|
||||
Write_record write;
|
||||
if (!res &&
|
||||
(sel_result= new (thd->mem_root)
|
||||
select_insert(thd, first_table,
|
||||
@@ -4657,7 +4658,8 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
|
||||
&lex->value_list,
|
||||
lex->duplicates,
|
||||
lex->ignore,
|
||||
result)))
|
||||
result,
|
||||
&write)))
|
||||
{
|
||||
if (lex->analyze_stmt)
|
||||
((select_result_interceptor*)sel_result)->disable_my_ok_calls();
|
||||
|
||||
@@ -158,10 +158,8 @@ public:
|
||||
typedef I_P_List<T, B, C, I> Base;
|
||||
typedef I_P_List_iterator<T, Base> Iterator;
|
||||
typedef I_P_List_iterator<const T, Base> Const_Iterator;
|
||||
#ifndef _lint
|
||||
friend class I_P_List_iterator<T, Base>;
|
||||
friend class I_P_List_iterator<const T, Base>;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -13477,6 +13477,8 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
|
||||
|
||||
DEBUG_SYNC(thd, "wsrep_create_table_as_select");
|
||||
|
||||
Write_record write;
|
||||
|
||||
/*
|
||||
select_create is currently not re-execution friendly and
|
||||
needs to be created for every execution of a PS/SP.
|
||||
@@ -13488,7 +13490,8 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
|
||||
select_lex->item_list,
|
||||
lex->duplicates,
|
||||
lex->ignore,
|
||||
select_tables)))
|
||||
select_tables,
|
||||
&write)))
|
||||
{
|
||||
/*
|
||||
CREATE from SELECT give its SELECT_LEX for SELECT,
|
||||
|
||||
@@ -502,7 +502,7 @@ bool Sql_cmd_update::update_single_table(THD *thd)
|
||||
Currently they rely on the user checking DA for
|
||||
errors when unwinding the stack after calling Item::val_xxx().
|
||||
*/
|
||||
if (error || thd->is_error())
|
||||
if (error || thd->killed || thd->is_error())
|
||||
{
|
||||
DBUG_RETURN(1); // Error in where
|
||||
}
|
||||
|
||||
@@ -7742,6 +7742,11 @@ static void do_mark_index_columns(TABLE *table, uint index,
|
||||
table->s->primary_key != MAX_KEY && table->s->primary_key != index)
|
||||
do_mark_index_columns(table, table->s->primary_key, bitmap, read);
|
||||
|
||||
if (table->versioned(VERS_TRX_ID))
|
||||
{
|
||||
table->vers_start_field()->register_field_in_read_map();
|
||||
table->vers_end_field()->register_field_in_read_map();
|
||||
}
|
||||
}
|
||||
/*
|
||||
mark columns used by key, but don't reset other fields
|
||||
|
||||
10
sql/table.h
10
sql/table.h
@@ -1790,7 +1790,7 @@ public:
|
||||
check_assignability_all_visible_fields(values, ignore);
|
||||
}
|
||||
|
||||
bool insert_all_rows_into_tmp_table(THD *thd,
|
||||
bool insert_all_rows_into_tmp_table(THD *thd,
|
||||
TABLE *tmp_table,
|
||||
TMP_TABLE_PARAM *tmp_table_param,
|
||||
bool with_cleanup);
|
||||
@@ -1915,8 +1915,8 @@ public:
|
||||
HA_DO_RANGE_FILTER_PUSHDOWN);
|
||||
}
|
||||
|
||||
ulonglong vers_start_id() const;
|
||||
ulonglong vers_end_id() const;
|
||||
ulonglong vers_start_id(const uchar *ptr) const;
|
||||
ulonglong vers_end_id(const uchar *ptr) const;
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
bool vers_switch_partition(THD *thd, TABLE_LIST *table_list,
|
||||
Open_table_context *ot_ctx);
|
||||
@@ -1929,7 +1929,9 @@ public:
|
||||
ha_rows *rows_inserted);
|
||||
bool vers_check_update(List<Item> &items);
|
||||
static bool check_period_overlaps(const KEY &key, const uchar *lhs, const uchar *rhs);
|
||||
int delete_row();
|
||||
inline int delete_row(){ return delete_row<false>(versioned(VERS_TIMESTAMP)); }
|
||||
template <bool replace>
|
||||
int delete_row(bool versioned);
|
||||
/* Used in majority of DML (called from fill_record()) */
|
||||
bool vers_update_fields();
|
||||
/* Used in DELETE, DUP REPLACE and insert history row */
|
||||
|
||||
@@ -46,7 +46,7 @@ user_connect.h valblk.h value.h xindex.h xobject.h xtable.h)
|
||||
#
|
||||
# Definitions that are shared for all OSes
|
||||
#
|
||||
add_definitions( -DMARIADB -DFORCE_INIT_OF_VARS -Dconnect_EXPORTS)
|
||||
add_definitions( -DMARIADB -Dconnect_EXPORTS)
|
||||
add_definitions( -DHUGE_SUPPORT -DGZ_SUPPORT )
|
||||
|
||||
macro(DISABLE_WARNING W)
|
||||
|
||||
@@ -1179,7 +1179,7 @@ bool FILTER::Convert(PGLOBAL g, bool having)
|
||||
case OP_GT:
|
||||
case OP_GE:
|
||||
case OP_LT:
|
||||
case OP_LE: new(this) FILTERCMP(g); break;
|
||||
case OP_LE: new(this) FILTERCMP(g, Opc); break;
|
||||
case OP_AND: new(this) FILTERAND; break;
|
||||
case OP_OR: new(this) FILTEROR; break;
|
||||
case OP_NOT: new(this) FILTERNOT; break;
|
||||
@@ -1589,8 +1589,9 @@ void FILTER::Prints(PGLOBAL g, char *ps, uint z)
|
||||
/***********************************************************************/
|
||||
/* FILTERCMP constructor. */
|
||||
/***********************************************************************/
|
||||
FILTERCMP::FILTERCMP(PGLOBAL g)
|
||||
FILTERCMP::FILTERCMP(PGLOBAL g, OPVAL Opc)
|
||||
{
|
||||
this->Opc= Opc;
|
||||
Bt = OpBmp(g, Opc);
|
||||
} // end of FILTERCMP constructor
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ class FILTERX : public FILTER {
|
||||
class FILTERCMP : public FILTERX {
|
||||
public:
|
||||
// Constructor
|
||||
FILTERCMP(PGLOBAL g);
|
||||
FILTERCMP(PGLOBAL, OPVAL);
|
||||
|
||||
// Methods
|
||||
bool Eval(PGLOBAL) override;
|
||||
|
||||
@@ -1611,7 +1611,9 @@ bool XMLCOL::ParseXpath(PGLOBAL g, bool mode)
|
||||
if (Tdbp->Xpand)
|
||||
n = Tdbp->Limit;
|
||||
|
||||
auto oLong = Long;
|
||||
new(this) XMULCOL(Value); // Change the class of this column
|
||||
Long = oLong;
|
||||
} // endif Inod
|
||||
|
||||
Valbuf = (char*)PlugSubAlloc(g, NULL, n * (Long + 1));
|
||||
|
||||
@@ -8630,7 +8630,7 @@ ha_innobase::update_row(
|
||||
if (error == DB_SUCCESS && m_prebuilt->versioned_write
|
||||
/* Multiple UPDATE of same rows in single transaction create
|
||||
historical rows only once. */
|
||||
&& trx->id != table->vers_start_id()) {
|
||||
&& trx->id != table->vers_start_id(new_row)) {
|
||||
/* UPDATE is not used by ALTER TABLE. Just precaution
|
||||
as we don't need history generation for ALTER TABLE. */
|
||||
ut_ad(thd_sql_command(m_user_thd) != SQLCOM_ALTER_TABLE);
|
||||
@@ -8745,8 +8745,9 @@ ha_innobase::delete_row(
|
||||
|
||||
/* This is a delete */
|
||||
m_prebuilt->upd_node->is_delete = table->versioned_write(VERS_TRX_ID)
|
||||
&& table->vers_end_field()->is_max()
|
||||
&& trx->id != table->vers_start_id()
|
||||
&& table->vers_end_field()->is_max(
|
||||
table->vers_end_field()->ptr_in_record(record))
|
||||
&& trx->id != table->vers_start_id(record)
|
||||
? VERSIONED_DELETE
|
||||
: PLAIN_DELETE;
|
||||
trx->fts_next_doc_id = 0;
|
||||
@@ -8754,6 +8755,9 @@ ha_innobase::delete_row(
|
||||
ut_ad(!trx->is_bulk_insert());
|
||||
error = row_update_for_mysql(m_prebuilt);
|
||||
|
||||
ut_ad(error != DB_DUPLICATE_KEY);
|
||||
ut_ad(error != DB_FOREIGN_DUPLICATE_KEY);
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
if (error == DB_SUCCESS && trx->is_wsrep()
|
||||
&& wsrep_thd_is_local(m_user_thd)
|
||||
|
||||
@@ -2411,7 +2411,7 @@ duplicate:
|
||||
&trx_id_len);
|
||||
ut_ad(trx_id_len == DATA_TRX_ID_LEN);
|
||||
if (trx->id == trx_read_trx_id(trx_id)) {
|
||||
err = DB_FOREIGN_DUPLICATE_KEY;
|
||||
err = DB_DUPLICATE_KEY;
|
||||
}
|
||||
}
|
||||
goto func_exit;
|
||||
|
||||
@@ -237,9 +237,6 @@ end:
|
||||
}
|
||||
maria_end();
|
||||
my_exit(error);
|
||||
#ifndef _lint
|
||||
return 0; /* No compiler warning */
|
||||
#endif
|
||||
} /* main */
|
||||
|
||||
enum options_mc {
|
||||
|
||||
@@ -291,11 +291,9 @@ end:
|
||||
maria_end();
|
||||
my_end(verbose ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
|
||||
exit(error ? 2 : 0);
|
||||
#ifndef _lint
|
||||
return 0; /* No compiler warning */
|
||||
#endif
|
||||
}
|
||||
|
||||
ATTRIBUTE_NORETURN
|
||||
static void my_exit(int error)
|
||||
{
|
||||
free_defaults(default_argv);
|
||||
|
||||
@@ -165,8 +165,6 @@ my_bool _ma_ck_delete(MARIA_HA *info, MARIA_KEY *key)
|
||||
MARIA_KEY org_key;
|
||||
DBUG_ENTER("_ma_ck_delete");
|
||||
|
||||
LINT_INIT_STRUCT(org_key);
|
||||
|
||||
alloc_on_stack(*info->stack_end_ptr, key_buff, buff_alloced,
|
||||
key->keyinfo->max_store_length);
|
||||
if (!key_buff)
|
||||
|
||||
@@ -484,8 +484,6 @@ static my_bool _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEY *key,
|
||||
my_bool transactional= share->now_transactional;
|
||||
DBUG_ENTER("_ma_ck_write_btree_with_log");
|
||||
|
||||
LINT_INIT_STRUCT(org_key);
|
||||
|
||||
if (transactional)
|
||||
{
|
||||
/* Save original value as the key may change */
|
||||
|
||||
@@ -337,7 +337,7 @@ static int mrn_change_encoding(grn_ctx *ctx, const CHARSET_INFO *charset)
|
||||
return mrn::encoding::set(ctx, charset);
|
||||
}
|
||||
|
||||
#if defined DBUG_TRACE && !defined(_lint)
|
||||
#if defined DBUG_TRACE
|
||||
static const char *mrn_inspect_thr_lock_type(enum thr_lock_type lock_type)
|
||||
{
|
||||
const char *inspected = "<unknown>";
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
#define MRN_DBUG_ENTER_FUNCTION() DBUG_ENTER(__FUNCTION__)
|
||||
|
||||
#if !defined(DBUG_OFF) && !defined(_lint)
|
||||
#if !defined(DBUG_OFF)
|
||||
# define MRN_DBUG_ENTER_METHOD() \
|
||||
char method_name[MRN_MESSAGE_BUFFER_SIZE]; \
|
||||
method_name[0] = '\0'; \
|
||||
|
||||
@@ -125,9 +125,6 @@ int main(int argc, char **argv)
|
||||
my_end(check_param.testflag & T_INFO ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
|
||||
rc= (uchar) error;
|
||||
exit(rc);
|
||||
#ifndef _lint
|
||||
return 0; /* No compiler warning */
|
||||
#endif
|
||||
} /* main */
|
||||
|
||||
|
||||
|
||||
@@ -250,9 +250,6 @@ int main(int argc, char **argv)
|
||||
free_defaults(default_argv);
|
||||
my_end(verbose ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
|
||||
exit(error ? 2 : 0);
|
||||
#ifndef _lint
|
||||
return 0; /* No compiler warning */
|
||||
#endif
|
||||
}
|
||||
|
||||
enum options_mp {OPT_CHARSETS_DIR_MP=256};
|
||||
|
||||
Reference in New Issue
Block a user