1
0
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:
Nikita Malyavin
2025-09-02 14:41:22 +02:00
70 changed files with 1426 additions and 932 deletions

View File

@@ -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())

View File

@@ -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")

View File

@@ -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);

View File

@@ -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
/**

View File

@@ -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 */

View File

@@ -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
#

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -0,0 +1,2 @@
--innodb-adaptive-hash-index=ON
--innodb-buffer-pool-size=64M

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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";

View File

@@ -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;

View File

@@ -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;

View File

@@ -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
#

View File

@@ -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

View 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;

View File

@@ -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
#

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 #

View File

@@ -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

View File

@@ -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 ;

View File

@@ -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 ;

View File

@@ -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 ;

View File

@@ -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,

View File

@@ -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,

View File

@@ -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;

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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++)
{

View File

@@ -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

View File

@@ -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, &copy_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);
}
}

View File

@@ -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

View File

@@ -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),

View File

@@ -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 &&

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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
};

View File

@@ -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);

View File

@@ -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();

View File

@@ -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
};

View File

@@ -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,

View File

@@ -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
}

View File

@@ -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

View File

@@ -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 */

View File

@@ -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)

View File

@@ -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

View File

@@ -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;

View File

@@ -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));

View File

@@ -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)

View File

@@ -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;

View File

@@ -237,9 +237,6 @@ end:
}
maria_end();
my_exit(error);
#ifndef _lint
return 0; /* No compiler warning */
#endif
} /* main */
enum options_mc {

View File

@@ -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);

View File

@@ -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)

View File

@@ -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 */

View File

@@ -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>";

View File

@@ -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'; \

View File

@@ -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 */

View File

@@ -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};