Merge 10.3 into 10.4

This commit is contained in:
Marko Mäkelä 2022-03-29 11:13:18 +03:00
commit ae6e214fd8
66 changed files with 1972 additions and 197 deletions

View file

@ -211,7 +211,7 @@ fi
max_no_embedded_configs="$SSL_LIBRARY --with-plugins=max"
max_no_qc_configs="$SSL_LIBRARY --with-plugins=max --without-query-cache"
max_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-libevent --without-plugin=plugin_file_key_management --with-plugin-rocksdb=dynamic --without-plugin-tokudb --with-plugin-test_sql_discovery=DYNAMIC --with-plugin-file_key_management=DYNAMIC"
max_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-libevent --with-plugin-rocksdb=dynamic --without-plugin-tokudb --with-plugin-test_sql_discovery=DYNAMIC --with-plugin-file_key_management=DYNAMIC"
all_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-innodb_plugin --with-libevent"
#

View file

@ -4,9 +4,11 @@ organization registered in the USA.
The current main sponsors of the MariaDB Foundation are:
Alibaba Cloud https://www.alibabacloud.com/ (2017)
Intel https://www.intel.com (2022)
MariaDB Corporation https://www.mariadb.com (2013)
Microsoft https://microsoft.com/ (2017)
ServiceNow https://servicenow.com (2019)
SIT https://sit.org (2022)
Tencent Cloud https://cloud.tencent.com (2017)
Development Bank of Singapore https://dbs.com (2016)
IBM https://www.ibm.com (2017)

View file

@ -2558,6 +2558,7 @@ static Exit_status handle_event_raw_mode(PRINT_EVENT_INFO *print_event_info,
error("Could not write into log file '%s'", out_file_name);
DBUG_RETURN(ERROR_STOP);
}
fflush(result_file);
DBUG_RETURN(OK_CONTINUE);
}

View file

@ -17,20 +17,29 @@ IF(GIT_EXECUTABLE AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
${GIT_EXECUTABLE} config cmake.update-submodules yes")
ELSEIF(git_config_get_result EQUAL 128)
SET(update_result 0)
ELSEIF (cmake_update_submodules MATCHES force)
MESSAGE(STATUS "Updating submodules (forced)")
EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --force --recursive --depth=1
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE update_result)
ELSEIF (cmake_update_submodules MATCHES yes)
EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive --depth=1
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE update_result)
ELSE()
MESSAGE(STATUS "Updating submodules")
EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive --depth=1
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE update_result)
SET(UPDATE_SUBMODULES_COMMAND
"${GIT_EXECUTABLE}" submodule update --init --recursive)
# Old Git may not work with "--depth 1".
# See also: https://github.com/git/git/commit/fb43e31f2b43076e7a30c9cd00d0241cb8cf97eb
IF(NOT GIT_VERSION_STRING VERSION_LESS "2.8.0")
SET(UPDATE_SUBMODULES_COMMAND ${UPDATE_SUBMODULES_COMMAND} --depth 1)
ENDIF()
IF(cmake_update_submodules MATCHES force)
MESSAGE(STATUS "Updating submodules (forced)")
EXECUTE_PROCESS(COMMAND ${UPDATE_SUBMODULES_COMMAND} --force
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE update_result)
ELSEIF(cmake_update_submodules MATCHES yes)
EXECUTE_PROCESS(COMMAND ${UPDATE_SUBMODULES_COMMAND}
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE update_result)
ELSE()
MESSAGE(STATUS "Updating submodules")
EXECUTE_PROCESS(COMMAND ${UPDATE_SUBMODULES_COMMAND}
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE update_result)
ENDIF()
ENDIF()
ENDIF()

View file

@ -5,6 +5,8 @@ Tencent Cloud https://cloud.tencent.com Platinum Sponsor of the MariaDB Foundati
Microsoft https://microsoft.com/ Platinum Sponsor of the MariaDB Foundation
MariaDB Corporation https://mariadb.com Founding member, Platinum Sponsor of the MariaDB Foundation
ServiceNow https://servicenow.com Platinum Sponsor of the MariaDB Foundation
Intel https://www.intel.com Platinum Sponsor of the MariaDB Foundation
SIT https://sit.org Platinum Sponsor of the MariaDB Foundation
Visma https://visma.com Gold Sponsor of the MariaDB Foundation
DBS https://dbs.com Gold Sponsor of the MariaDB Foundation
IBM https://www.ibm.com Gold Sponsor of the MariaDB Foundation

View file

@ -2913,5 +2913,30 @@ t1 CREATE TABLE `t1` (
DROP TABLE t1;
SET NAMES utf8;
#
# MDEV-28078 Garbage on multiple equal ENUMs with tricky character sets
#
CREATE TABLE t1 (
c1 ENUM ('a','b') CHARACTER SET utf32 DEFAULT 'a',
c2 ENUM ('a','b') CHARACTER SET utf32 DEFAULT 'a'
);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` enum('a','b') CHARACTER SET utf32 DEFAULT 'a',
`c2` enum('a','b') CHARACTER SET utf32 DEFAULT 'a'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (
c1 ENUM ('00000061','00000062') DEFAULT '00000061' COLLATE latin1_bin,
c2 ENUM ('a','b') DEFAULT 'a' COLLATE utf32_general_ci
);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` enum('00000061','00000062') CHARACTER SET latin1 COLLATE latin1_bin DEFAULT '00000061',
`c2` enum('a','b') CHARACTER SET utf32 DEFAULT 'a'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# End of 10.2 tests
#

View file

@ -1067,6 +1067,25 @@ DROP TABLE t1;
SET NAMES utf8;
--echo #
--echo # MDEV-28078 Garbage on multiple equal ENUMs with tricky character sets
--echo #
CREATE TABLE t1 (
c1 ENUM ('a','b') CHARACTER SET utf32 DEFAULT 'a',
c2 ENUM ('a','b') CHARACTER SET utf32 DEFAULT 'a'
);
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (
c1 ENUM ('00000061','00000062') DEFAULT '00000061' COLLATE latin1_bin,
c2 ENUM ('a','b') DEFAULT 'a' COLLATE utf32_general_ci
);
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # End of 10.2 tests
--echo #

View file

@ -207,4 +207,19 @@ ERROR 23000: Duplicate entry '0000-00-00 00:00:00' for key 'f2k'
DROP VIEW v1;
DROP TABLE t3,t4;
SET @@sql_mode=@save_sql_mode;
#
# End of 10.2 tests
#
#
# MDEV-28095 crash in multi-update and implicit grouping
#
CREATE TABLE t1 (a int) engine=innodb;
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2 (b int);
INSERT INTO t2 VALUES (1),(2);
UPDATE t1 NATURAL JOIN t2 SET a = 1 ORDER BY AVG (a) ;
ERROR HY000: Invalid use of group function
DROP TABLE t1, t2;
#
# End of 10.3 tests
#

View file

@ -243,4 +243,23 @@ DROP VIEW v1;
DROP TABLE t3,t4;
SET @@sql_mode=@save_sql_mode;
--echo #
--echo # End of 10.2 tests
--echo #
--echo #
--echo # MDEV-28095 crash in multi-update and implicit grouping
--echo #
CREATE TABLE t1 (a int) engine=innodb;
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2 (b int);
INSERT INTO t2 VALUES (1),(2);
--error ER_INVALID_GROUP_FUNC_USE
UPDATE t1 NATURAL JOIN t2 SET a = 1 ORDER BY AVG (a) ;
DROP TABLE t1, t2;
--echo #
--echo # End of 10.3 tests
--echo #

View file

@ -732,3 +732,30 @@ a b
4 4
drop table t1;
SET @@in_predicate_conversion_threshold= default;
#
# MDEV-27937: Prepared statement with ? in the list if IN predicate
#
set in_predicate_conversion_threshold=2;
create table t1 (id int, a int, b int);
insert into t1 values (1,3,30), (2,7,70), (3,1,10);
prepare stmt from "
select * from t1 where a in (7, ?, 5, 1);
";
execute stmt using 3;
id a b
1 3 30
2 7 70
3 1 10
deallocate prepare stmt;
prepare stmt from "
select * from t1 where (a,b) in ((7,70), (3,?), (5,50), (1,10));
";
execute stmt using 30;
id a b
1 3 30
2 7 70
3 1 10
deallocate prepare stmt;
drop table t1;
set in_predicate_conversion_threshold=default;
# End of 10.3 tests

View file

@ -428,3 +428,29 @@ eval $query;
drop table t1;
SET @@in_predicate_conversion_threshold= default;
--echo #
--echo # MDEV-27937: Prepared statement with ? in the list if IN predicate
--echo #
set in_predicate_conversion_threshold=2;
create table t1 (id int, a int, b int);
insert into t1 values (1,3,30), (2,7,70), (3,1,10);
prepare stmt from "
select * from t1 where a in (7, ?, 5, 1);
";
execute stmt using 3;
deallocate prepare stmt;
prepare stmt from "
select * from t1 where (a,b) in ((7,70), (3,?), (5,50), (1,10));
";
execute stmt using 30;
deallocate prepare stmt;
drop table t1;
set in_predicate_conversion_threshold=default;
--echo # End of 10.3 tests

View file

@ -40,3 +40,23 @@ utf8mb4_string xxx😎yyy
#
# End of 10.1 tests
#
#
# Start of 10.3 tests
#
#
# MDEV-28131 Unexpected warning while selecting from information_schema.processlist
#
connect conn1, localhost, root,,;
connection conn1;
SELECT SLEEP(1000);
connection default;
SELECT progress FROM information_schema.processlist WHERE info='SELECT SLEEP(1000)';
progress
0.000
connection conn1;
Got one of the listed errors
connection default;
disconnect conn1;
#
# End of 10.3 tests
#

View file

@ -70,3 +70,38 @@ SELECT INFO, INFO_BINARY, 'xxx😎yyy' AS utf8mb4_string FROM INFORMATION_SCHEMA
--echo #
--echo # End of 10.1 tests
--echo #
--echo #
--echo # Start of 10.3 tests
--echo #
--echo #
--echo # MDEV-28131 Unexpected warning while selecting from information_schema.processlist
--echo #
connect (conn1, localhost, root,,);
connection conn1;
let $ID= `select connection_id()`;
send SELECT SLEEP(1000);
connection default;
let $wait_timeout= 10;
let $wait_condition=select count(*)=1 from information_schema.processlist
where state='User sleep' and info='SELECT SLEEP(1000)';
--source include/wait_condition.inc
SELECT progress FROM information_schema.processlist WHERE info='SELECT SLEEP(1000)';
disable_query_log;
eval kill $ID;
enable_query_log;
let $wait_timeout= 10;
let $wait_condition=select count(*)=0 from information_schema.processlist
where state='User sleep' and info='SELECT SLEEP(1000)';
--source include/wait_condition.inc
connection conn1;
--error 2013,ER_CONNECTION_KILLED
reap;
connection default;
disconnect conn1;
--echo #
--echo # End of 10.3 tests
--echo #

View file

@ -737,3 +737,66 @@ rec.en1
c
DROP PROCEDURE p1;
DROP TABLE t1;
#
# MDEV-26009: Server crash when calling twice procedure using FOR-loop
#
CREATE TABLE t1 ( id int, name varchar(24));
INSERT INTO t1 values (1, 'x'), (2, 'y'), (3, 'z');
create function get_name(_id int) returns varchar(24)
return (select name from t1 where id = _id);
select get_name(id) from t1;
get_name(id)
x
y
z
create procedure test_proc()
begin
declare _cur cursor for select get_name(id) from t1;
for row in _cur do select 1; end for;
end;
^^
call test_proc();
1
1
1
1
1
1
call test_proc();
1
1
1
1
1
1
drop procedure test_proc;
drop function get_name;
drop table t1;
CREATE TABLE t1 (id int, name varchar(24));
INSERT INTO t1 (id, name) VALUES (1, 'x'),(2, 'y'),(3, 'z');
create function get_name(_id int) returns varchar(24)
return (select name from t1 where id = _id);
create view v1 as select get_name(id) from t1;
create procedure test_proc()
begin
declare _cur cursor for select 1 from v1;
for row in _cur do select 1; end for;
end$$
call test_proc();
1
1
1
1
1
1
call test_proc();
1
1
1
1
1
1
drop procedure test_proc;
drop view v1;
drop function get_name;
drop table t1;

View file

@ -744,3 +744,59 @@ DELIMITER ;$$
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
--echo #
--echo # MDEV-26009: Server crash when calling twice procedure using FOR-loop
--echo #
CREATE TABLE t1 ( id int, name varchar(24));
INSERT INTO t1 values (1, 'x'), (2, 'y'), (3, 'z');
create function get_name(_id int) returns varchar(24)
return (select name from t1 where id = _id);
select get_name(id) from t1;
delimiter ^^;
create procedure test_proc()
begin
declare _cur cursor for select get_name(id) from t1;
for row in _cur do select 1; end for;
end;
^^
delimiter ;^^
call test_proc();
call test_proc();
drop procedure test_proc;
drop function get_name;
drop table t1;
CREATE TABLE t1 (id int, name varchar(24));
INSERT INTO t1 (id, name) VALUES (1, 'x'),(2, 'y'),(3, 'z');
create function get_name(_id int) returns varchar(24)
return (select name from t1 where id = _id);
create view v1 as select get_name(id) from t1;
delimiter $$;
create procedure test_proc()
begin
declare _cur cursor for select 1 from v1;
for row in _cur do select 1; end for;
end$$
delimiter ;$$
call test_proc();
call test_proc();
drop procedure test_proc;
drop view v1;
drop function get_name;
drop table t1;

View file

@ -6851,6 +6851,34 @@ id bar
Drop View v1;
Drop table t1;
#
# MDEV-24281: Execution of PREPARE from CREATE VIEW statement
#
create table t1 (s1 int);
insert into t1 values (3), (7), (1);
prepare stmt from "
create view v1 as select 's1', s1, 1 as My_exp_s1 from t1;
";
execute stmt;
deallocate prepare stmt;
show create view v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 's1' AS `My_exp_1_s1`,`t1`.`s1` AS `s1`,1 AS `My_exp_s1` from `t1` latin1 latin1_swedish_ci
select * from v1;
My_exp_1_s1 s1 My_exp_s1
s1 3 1
s1 7 1
s1 1 1
drop view v1;
prepare stmt from "
create view v1 as select 's1', s1, 1 as My_exp_s1 from t1;
";
execute stmt;
execute stmt;
ERROR 42S01: Table 'v1' already exists
deallocate prepare stmt;
drop view v1;
drop table t1;
#
# End of 10.3 tests
#
#

View file

@ -6577,6 +6577,32 @@ SELECT v.id, v.foo AS bar FROM v1 v
Drop View v1;
Drop table t1;
--echo #
--echo # MDEV-24281: Execution of PREPARE from CREATE VIEW statement
--echo #
create table t1 (s1 int);
insert into t1 values (3), (7), (1);
prepare stmt from "
create view v1 as select 's1', s1, 1 as My_exp_s1 from t1;
";
execute stmt;
deallocate prepare stmt;
show create view v1;
select * from v1;
drop view v1;
prepare stmt from "
create view v1 as select 's1', s1, 1 as My_exp_s1 from t1;
";
execute stmt;
--error ER_TABLE_EXISTS_ERROR
execute stmt;
deallocate prepare stmt;
drop view v1;
drop table t1;
--echo #
--echo # End of 10.3 tests
--echo #

View file

@ -0,0 +1,6 @@
ALTER TABLE mysql.gtid_slave_pos ENGINE=innodb;
# Restart the server so mysqld reads the gtid_slave_pos using innodb
# Set gtid_slave_pos should not hang
SET GLOBAL gtid_slave_pos=@@gtid_binlog_pos;
COMMIT;
RESET MASTER;

View file

@ -0,0 +1,7 @@
CREATE TABLE t1 (a int);
FLUSH LOGS;
INSERT INTO t1 VALUES (1);
# timeout TIMEOUT MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=MASTER_MYPORT --stop-never --result-file=MYSQLTEST_VARDIR/tmp/ master-bin.000001
# MYSQL_BINLOG MYSQLTEST_VARDIR/tmp/master-bin.000002 > MYSQLTEST_VARDIR/tmp/local-bin.000002.out
FOUND 1 /GTID 0-1-2/ in local-bin.000002.out
DROP TABLE t1;

View file

@ -0,0 +1 @@
--autocommit=0

View file

@ -0,0 +1,45 @@
#
# Purpose:
# When the mysql.gtid_slave_pos table uses the InnoDB engine, and mysqld
# starts, it reads the table and begins a transaction. After mysqld reads the
# value, it should end the transaction and release all associated locks.
# The bug reported in DBAAS-7828 shows that when autocommit is off, the locks
# are not released, resulting in indefinite hangs on future attempts to change
# gtid_slave_pos. This test ensures its fix such that the locks are properly
# released.
#
# References:
# DBAAS-7828: Primary/replica: configuration change of "autocommit=0" can
# not be applied
#
--source include/have_innodb.inc
--source include/have_log_bin.inc
# Reading gtid_slave_pos table is format independent so just use one for
# reduced test time
--source include/have_binlog_format_row.inc
--let old_slave_pos_engine= query_get_value(SHOW TABLE STATUS FROM mysql LIKE 'gtid_slave_pos', Engine, 1)
# Use a transactional engine
ALTER TABLE mysql.gtid_slave_pos ENGINE=innodb;
--echo # Restart the server so mysqld reads the gtid_slave_pos using innodb
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--shutdown_server
--source include/wait_until_disconnected.inc
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--enable_reconnect
--source include/wait_until_connected_again.inc
--echo # Set gtid_slave_pos should not hang
SET GLOBAL gtid_slave_pos=@@gtid_binlog_pos;
COMMIT;
# Revert table type
--disable_query_log
--eval ALTER TABLE mysql.gtid_slave_pos ENGINE=$old_slave_pos_engine
--enable_query_log
RESET MASTER;

View file

@ -0,0 +1,45 @@
#
# Purpose:
# When using mariadb-binlog with options for --raw and --stop-never, events
# from the master's currently active log file should be written to their
# respective log file specified by --result-file, and shown on-disk. This test
# ensures that the log files on disk, created by mariadb-binlog, have the most
# up-to-date events from the master.
#
# Methodology:
# On the master, rotate to a newly active binlog file and write an event to
# it. Read the master's binlog using mariadb-binlog with --raw and --stop-never
# and write the data to an intermediary binlog file (a timeout is used on this
# command to ensure it exits). Read the local intermediary binlog file to ensure
# that the master's most recent event exists in the local file.
#
# References:
# MDEV-14608: mysqlbinlog lastest backupfile size is 0
#
--source include/linux.inc
--source include/have_log_bin.inc
# Create newly active log
CREATE TABLE t1 (a int);
FLUSH LOGS;
INSERT INTO t1 VALUES (1);
# Read binlog data from master to intermediary result file
--let TIMEOUT=1
--echo # timeout TIMEOUT MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=MASTER_MYPORT --stop-never --result-file=MYSQLTEST_VARDIR/tmp/ master-bin.000001
--error 124 # Error 124 means timeout was reached
--exec timeout $TIMEOUT $MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --stop-never --result-file=$MYSQLTEST_VARDIR/tmp/ master-bin.000001
# Ensure the binlog output has the most recent events from the master
--echo # MYSQL_BINLOG MYSQLTEST_VARDIR/tmp/master-bin.000002 > MYSQLTEST_VARDIR/tmp/local-bin.000002.out
--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/tmp/master-bin.000002 > $MYSQLTEST_VARDIR/tmp/local-bin.000002.out
--let SEARCH_PATTERN= GTID 0-1-2
--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/local-bin.000002.out
--source include/search_pattern_in_file.inc
# Cleanup
DROP TABLE t1;
--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000001
--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000002
--remove_file $MYSQLTEST_VARDIR/tmp/local-bin.000002.out

View file

@ -2962,3 +2962,311 @@ END $$
CALL xyz.xyz123(17,18,@R);
DROP PACKAGE xyz;
DROP TABLE t1;
#
# MDEV-28166 sql_mode=ORACLE: fully qualified package function calls do not work: db.pkg.func()
#
SELECT `db `.pkg.func();
ERROR 42000: Incorrect database name 'db '
SELECT db.`pkg `.func();
ERROR 42000: Incorrect routine name 'pkg '
SELECT db.pkg.`func `();
ERROR 42000: Incorrect routine name 'func '
CREATE DATABASE db1;
USE db1;
CREATE PACKAGE pkg1 AS
FUNCTION f1 RETURN TEXT;
FUNCTION f2_db1_pkg1_f1 RETURN TEXT;
FUNCTION f2_pkg1_f1 RETURN TEXT;
FUNCTION f2_f1 RETURN TEXT;
END;
$$
CREATE PACKAGE BODY pkg1
AS
FUNCTION f1 RETURN TEXT IS
BEGIN
RETURN 'This is db1.pkg1.f1';
END;
FUNCTION f2_db1_pkg1_f1 RETURN TEXT IS
BEGIN
RETURN db1.pkg1.f1();
END;
FUNCTION f2_pkg1_f1 RETURN TEXT IS
BEGIN
RETURN pkg1.f1();
END;
FUNCTION f2_f1 RETURN TEXT IS
BEGIN
RETURN f1();
END;
END;
$$
USE db1;
SELECT pkg1.f2_db1_pkg1_f1();
pkg1.f2_db1_pkg1_f1()
This is db1.pkg1.f1
SELECT pkg1.f2_pkg1_f1();
pkg1.f2_pkg1_f1()
This is db1.pkg1.f1
SELECT pkg1.f2_f1();
pkg1.f2_f1()
This is db1.pkg1.f1
SELECT db1.pkg1.f2_db1_pkg1_f1();
db1.pkg1.f2_db1_pkg1_f1()
This is db1.pkg1.f1
SELECT db1.pkg1.f2_pkg1_f1();
db1.pkg1.f2_pkg1_f1()
This is db1.pkg1.f1
SELECT db1.pkg1.f2_f1();
db1.pkg1.f2_f1()
This is db1.pkg1.f1
USE test;
SELECT db1.pkg1.f2_db1_pkg1_f1();
db1.pkg1.f2_db1_pkg1_f1()
This is db1.pkg1.f1
SELECT db1.pkg1.f2_pkg1_f1();
db1.pkg1.f2_pkg1_f1()
This is db1.pkg1.f1
SELECT db1.pkg1.f2_f1();
db1.pkg1.f2_f1()
This is db1.pkg1.f1
DROP DATABASE db1;
CREATE DATABASE db1;
CREATE DATABASE db2;
CREATE PACKAGE db1.pkg1 AS
FUNCTION f1 RETURN TEXT;
END;
$$
CREATE PACKAGE BODY db1.pkg1 AS
FUNCTION f1 RETURN TEXT AS
BEGIN
RETURN 'This is db1.pkg1.f1';
END;
END;
$$
CREATE PACKAGE db2.pkg1 AS
FUNCTION f1 RETURN TEXT;
FUNCTION var1 RETURN TEXT;
FUNCTION var2 RETURN TEXT;
END;
$$
CREATE PACKAGE BODY db2.pkg1 AS
m_var1 TEXT;
m_var2 TEXT;
FUNCTION f1 RETURN TEXT AS
BEGIN
RETURN 'This is db2.pkg1.f1';
END;
FUNCTION var1 RETURN TEXT AS
BEGIN
RETURN m_var1;
END;
FUNCTION var2 RETURN TEXT AS
BEGIN
RETURN m_var2;
END;
BEGIN
m_var1:= db1.pkg1.f1();
m_var2:= db2.pkg1.f1();
END;
$$
SELECT db2.pkg1.var1(), db2.pkg1.var2();
db2.pkg1.var1() db2.pkg1.var2()
This is db1.pkg1.f1 This is db2.pkg1.f1
DROP DATABASE db1;
DROP DATABASE db2;
CREATE PACKAGE pkg1 AS
FUNCTION f1(a TEXT) RETURN TEXT;
END;
$$
CREATE PACKAGE BODY pkg1 AS
FUNCTION f1(a TEXT) RETURN TEXT AS
BEGIN
RETURN a;
END;
END;
$$
SELECT test.pkg1.f1('xxx');
test.pkg1.f1('xxx')
xxx
SELECT test.pkg1.f1('xxx' AS a);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'AS a)' at line 1
DROP PACKAGE pkg1;
#
# MDEV-19328 sql_mode=ORACLE: Package function in VIEW
#
SET sql_mode=ORACLE;
CREATE PACKAGE test1 AS
FUNCTION f_test RETURN number;
END test1;
$$
CREATE PACKAGE BODY test1
AS
FUNCTION f_test RETURN NUMBER IS
BEGIN
RETURN 1;
END;
END test1;
$$
SET sql_mode=ORACLE;
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test();
SELECT * FROM v_test;
c1
1
SHOW CREATE VIEW v_test;
View v_test
Create View CREATE VIEW "v_test" AS select 1 AS "c1" from DUAL where 1 = "test"."test1"."f_test"()
character_set_client latin1
collation_connection latin1_swedish_ci
SET sql_mode=DEFAULT;
SELECT * FROM v_test;
c1
1
SHOW CREATE VIEW v_test;
View v_test
Create View CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_test` AS select 1 AS `c1` from DUAL where 1 = `test`.`test1`.`f_test`()
character_set_client latin1
collation_connection latin1_swedish_ci
DROP VIEW v_test;
SET sql_mode=DEFAULT;
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test();
ERROR 42000: FUNCTION test1.f_test does not exist
SET sql_mode=ORACLE;
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test.test1.f_test();
SELECT * FROM v_test;
c1
1
SHOW CREATE VIEW v_test;
View v_test
Create View CREATE VIEW "v_test" AS select 1 AS "c1" from DUAL where 1 = "test"."test1"."f_test"()
character_set_client latin1
collation_connection latin1_swedish_ci
SET sql_mode=DEFAULT;
SELECT * FROM v_test;
c1
1
SHOW CREATE VIEW v_test;
View v_test
Create View CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_test` AS select 1 AS `c1` from DUAL where 1 = `test`.`test1`.`f_test`()
character_set_client latin1
collation_connection latin1_swedish_ci
DROP VIEW v_test;
SET sql_mode=DEFAULT;
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test.test1.f_test();
SELECT * FROM v_test;
c1
1
SHOW CREATE VIEW v_test;
View v_test
Create View CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_test` AS select 1 AS `c1` from DUAL where 1 = `test`.`test1`.`f_test`()
character_set_client latin1
collation_connection latin1_swedish_ci
SET sql_mode=ORACLE;
SELECT * FROM v_test;
c1
1
SHOW CREATE VIEW v_test;
View v_test
Create View CREATE VIEW "v_test" AS select 1 AS "c1" from DUAL where 1 = "test"."test1"."f_test"()
character_set_client latin1
collation_connection latin1_swedish_ci
DROP VIEW v_test;
SET sql_mode=ORACLE;
DROP PACKAGE test1;
#
# MDEV-19804 sql_mode=ORACLE: call procedure in packages
#
CALL `db1 `.pkg.p;
ERROR 42000: Incorrect database name 'db1 '
CALL db1.`pkg `.p;
ERROR 42000: Incorrect routine name 'pkg '
CALL db1.pkg.`p `;
ERROR 42000: Incorrect routine name 'p '
SET sql_mode=ORACLE;
CREATE PACKAGE pkg1 as
PROCEDURE p1();
END;
$$
CREATE PACKAGE BODY pkg1 as
PROCEDURE p1() as
BEGIN
SELECT 'test-function' AS c1;
END;
END;
$$
CALL pkg1.p1;
c1
test-function
CALL test.pkg1.p1;
c1
test-function
SET sql_mode=DEFAULT;
CALL test.pkg1.p1;
c1
test-function
SET sql_mode=ORACLE;
BEGIN
CALL pkg1.p1;
CALL test.pkg1.p1;
END
$$
c1
test-function
c1
test-function
BEGIN
pkg1.p1;
test.pkg1.p1;
END
$$
c1
test-function
c1
test-function
DROP PACKAGE pkg1;
CREATE DATABASE db1;
CREATE PACKAGE db1.pkg1 AS
PROCEDURE p1(a OUT TEXT);
END;
$$
CREATE PACKAGE BODY db1.pkg1 AS
PROCEDURE p1(a OUT TEXT) AS
BEGIN
a:= 'This is db1.pkg1.p1';
END;
END;
$$
CREATE DATABASE db2;
CREATE PACKAGE db2.pkg1 AS
FUNCTION var1 RETURN TEXT;
PROCEDURE p1(a OUT TEXT);
PROCEDURE p2_db1_pkg1_p1;
END;
$$
CREATE PACKAGE BODY db2.pkg1 AS
m_var1 TEXT;
FUNCTION var1 RETURN TEXT AS
BEGIN
RETURN m_var1;
END;
PROCEDURE p1(a OUT TEXT) AS
BEGIN
a:= 'This is db2.pkg1.p1';
END;
PROCEDURE p2_db1_pkg1_p1 AS
a TEXT;
BEGIN
db1.pkg1.p1(a);
SELECT a;
END;
BEGIN
db1.pkg1.p1(m_var1);
END;
$$
SELECT db2.pkg1.var1();
db2.pkg1.var1()
This is db1.pkg1.p1
CALL db2.pkg1.p2_db1_pkg1_p1;
a
This is db1.pkg1.p1
DROP DATABASE db1;
DROP DATABASE db2;

View file

@ -2689,3 +2689,330 @@ DELIMITER ;$$
CALL xyz.xyz123(17,18,@R);
DROP PACKAGE xyz;
DROP TABLE t1;
--echo #
--echo # MDEV-28166 sql_mode=ORACLE: fully qualified package function calls do not work: db.pkg.func()
--echo #
--error ER_WRONG_DB_NAME
SELECT `db `.pkg.func();
--error ER_SP_WRONG_NAME
SELECT db.`pkg `.func();
--error ER_SP_WRONG_NAME
SELECT db.pkg.`func `();
CREATE DATABASE db1;
USE db1;
DELIMITER $$;
CREATE PACKAGE pkg1 AS
FUNCTION f1 RETURN TEXT;
FUNCTION f2_db1_pkg1_f1 RETURN TEXT;
FUNCTION f2_pkg1_f1 RETURN TEXT;
FUNCTION f2_f1 RETURN TEXT;
END;
$$
CREATE PACKAGE BODY pkg1
AS
FUNCTION f1 RETURN TEXT IS
BEGIN
RETURN 'This is db1.pkg1.f1';
END;
FUNCTION f2_db1_pkg1_f1 RETURN TEXT IS
BEGIN
RETURN db1.pkg1.f1();
END;
FUNCTION f2_pkg1_f1 RETURN TEXT IS
BEGIN
RETURN pkg1.f1();
END;
FUNCTION f2_f1 RETURN TEXT IS
BEGIN
RETURN f1();
END;
END;
$$
DELIMITER ;$$
USE db1;
SELECT pkg1.f2_db1_pkg1_f1();
SELECT pkg1.f2_pkg1_f1();
SELECT pkg1.f2_f1();
SELECT db1.pkg1.f2_db1_pkg1_f1();
SELECT db1.pkg1.f2_pkg1_f1();
SELECT db1.pkg1.f2_f1();
USE test;
SELECT db1.pkg1.f2_db1_pkg1_f1();
SELECT db1.pkg1.f2_pkg1_f1();
SELECT db1.pkg1.f2_f1();
DROP DATABASE db1;
#
# Testing db.pkg.func() in the package initialization section
#
CREATE DATABASE db1;
CREATE DATABASE db2;
DELIMITER $$;
CREATE PACKAGE db1.pkg1 AS
FUNCTION f1 RETURN TEXT;
END;
$$
CREATE PACKAGE BODY db1.pkg1 AS
FUNCTION f1 RETURN TEXT AS
BEGIN
RETURN 'This is db1.pkg1.f1';
END;
END;
$$
DELIMITER ;$$
DELIMITER $$;
CREATE PACKAGE db2.pkg1 AS
FUNCTION f1 RETURN TEXT;
FUNCTION var1 RETURN TEXT;
FUNCTION var2 RETURN TEXT;
END;
$$
CREATE PACKAGE BODY db2.pkg1 AS
m_var1 TEXT;
m_var2 TEXT;
FUNCTION f1 RETURN TEXT AS
BEGIN
RETURN 'This is db2.pkg1.f1';
END;
FUNCTION var1 RETURN TEXT AS
BEGIN
RETURN m_var1;
END;
FUNCTION var2 RETURN TEXT AS
BEGIN
RETURN m_var2;
END;
BEGIN
m_var1:= db1.pkg1.f1();
m_var2:= db2.pkg1.f1();
END;
$$
DELIMITER ;$$
SELECT db2.pkg1.var1(), db2.pkg1.var2();
DROP DATABASE db1;
DROP DATABASE db2;
#
# Make sure fully qualified package function call does not support AS syntax:
# SELECT db.pkg.func(10 AS a);
#
DELIMITER $$;
CREATE PACKAGE pkg1 AS
FUNCTION f1(a TEXT) RETURN TEXT;
END;
$$
CREATE PACKAGE BODY pkg1 AS
FUNCTION f1(a TEXT) RETURN TEXT AS
BEGIN
RETURN a;
END;
END;
$$
DELIMITER ;$$
SELECT test.pkg1.f1('xxx');
--error ER_PARSE_ERROR
SELECT test.pkg1.f1('xxx' AS a);
DROP PACKAGE pkg1;
--echo #
--echo # MDEV-19328 sql_mode=ORACLE: Package function in VIEW
--echo #
SET sql_mode=ORACLE;
DELIMITER $$;
CREATE PACKAGE test1 AS
FUNCTION f_test RETURN number;
END test1;
$$
CREATE PACKAGE BODY test1
AS
FUNCTION f_test RETURN NUMBER IS
BEGIN
RETURN 1;
END;
END test1;
$$
DELIMITER ;$$
SET sql_mode=ORACLE;
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test();
SELECT * FROM v_test;
--vertical_results
SHOW CREATE VIEW v_test;
--horizontal_results
SET sql_mode=DEFAULT;
SELECT * FROM v_test;
--vertical_results
SHOW CREATE VIEW v_test;
--horizontal_results
DROP VIEW v_test;
SET sql_mode=DEFAULT;
--error ER_SP_DOES_NOT_EXIST
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test();
SET sql_mode=ORACLE;
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test.test1.f_test();
SELECT * FROM v_test;
--vertical_results
SHOW CREATE VIEW v_test;
--horizontal_results
SET sql_mode=DEFAULT;
SELECT * FROM v_test;
--vertical_results
SHOW CREATE VIEW v_test;
--horizontal_results
DROP VIEW v_test;
SET sql_mode=DEFAULT;
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test.test1.f_test();
SELECT * FROM v_test;
--vertical_results
SHOW CREATE VIEW v_test;
--horizontal_results
SET sql_mode=ORACLE;
SELECT * FROM v_test;
--vertical_results
SHOW CREATE VIEW v_test;
--horizontal_results
DROP VIEW v_test;
SET sql_mode=ORACLE;
DROP PACKAGE test1;
--echo #
--echo # MDEV-19804 sql_mode=ORACLE: call procedure in packages
--echo #
--error ER_WRONG_DB_NAME
CALL `db1 `.pkg.p;
--error ER_SP_WRONG_NAME
CALL db1.`pkg `.p;
--error ER_SP_WRONG_NAME
CALL db1.pkg.`p `;
SET sql_mode=ORACLE;
DELIMITER $$;
CREATE PACKAGE pkg1 as
PROCEDURE p1();
END;
$$
CREATE PACKAGE BODY pkg1 as
PROCEDURE p1() as
BEGIN
SELECT 'test-function' AS c1;
END;
END;
$$
DELIMITER ;$$
CALL pkg1.p1;
CALL test.pkg1.p1;
# In sql_mode=DEFAULT we support fully qualified package function names
# (this is needed for VIEWs). Let's make sure we also support fully
# qualified package procedure names, for symmetry
SET sql_mode=DEFAULT;
CALL test.pkg1.p1;
SET sql_mode=ORACLE;
DELIMITER $$;
BEGIN
CALL pkg1.p1;
CALL test.pkg1.p1;
END
$$
DELIMITER ;$$
DELIMITER $$;
BEGIN
pkg1.p1;
test.pkg1.p1;
END
$$
DELIMITER ;$$
DROP PACKAGE pkg1;
#
# Testing packages in different databases calling each other
# in routines and in the initialization section.
#
CREATE DATABASE db1;
DELIMITER $$;
CREATE PACKAGE db1.pkg1 AS
PROCEDURE p1(a OUT TEXT);
END;
$$
CREATE PACKAGE BODY db1.pkg1 AS
PROCEDURE p1(a OUT TEXT) AS
BEGIN
a:= 'This is db1.pkg1.p1';
END;
END;
$$
DELIMITER ;$$
CREATE DATABASE db2;
DELIMITER $$;
CREATE PACKAGE db2.pkg1 AS
FUNCTION var1 RETURN TEXT;
PROCEDURE p1(a OUT TEXT);
PROCEDURE p2_db1_pkg1_p1;
END;
$$
CREATE PACKAGE BODY db2.pkg1 AS
m_var1 TEXT;
FUNCTION var1 RETURN TEXT AS
BEGIN
RETURN m_var1;
END;
PROCEDURE p1(a OUT TEXT) AS
BEGIN
a:= 'This is db2.pkg1.p1';
END;
PROCEDURE p2_db1_pkg1_p1 AS
a TEXT;
BEGIN
db1.pkg1.p1(a);
SELECT a;
END;
BEGIN
db1.pkg1.p1(m_var1);
END;
$$
DELIMITER ;$$
SELECT db2.pkg1.var1();
CALL db2.pkg1.p2_db1_pkg1_p1;
DROP DATABASE db1;
DROP DATABASE db2;

View file

@ -1,5 +1,10 @@
--echo Killing server ...
if (!$kill_signal)
{
--let $kill_signal = KILL
}
# Write file to make mysql-test-run.pl expect the crash, but don't start it
--let $_server_id= `SELECT @@server_id`
--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect
@ -7,13 +12,15 @@
# Kill the connected server
--disable_reconnect
--let KILL_SIGNAL_VALUE = $kill_signal
--let KILL_NODE_PIDFILE = `SELECT @@pid_file`
--perl
my $kill_sig = $ENV{'KILL_SIGNAL_VALUE'};
my $pid_filename = $ENV{'KILL_NODE_PIDFILE'};
my $mysqld_pid = `cat $pid_filename`;
chomp($mysqld_pid);
system("kill -9 $mysqld_pid");
system("kill -s $kill_sig $mysqld_pid");
exit(0);
EOF

View file

@ -18,6 +18,7 @@ SET SESSION wsrep_on=ON;
connection node_1;
UPDATE t1 SET f2 = 'd' WHERE f1 > 3;
connection node_2;
Killing server ...
connection node_1;
UPDATE t1 SET f2 = 'e' WHERE f1 > 4;
connection node_2;

View file

@ -61,19 +61,7 @@ UPDATE t1 SET f2 = 'd' WHERE f1 > 3;
# Kill node #2 while IST is in progress
--connection node_2
# Kill the connected server
--disable_reconnect
--perl
my $pid_filename = $ENV{'KILL_NODE_PIDFILE'};
my $mysqld_pid = `cat $pid_filename`;
chomp($mysqld_pid);
system("kill -9 $mysqld_pid");
exit(0);
EOF
--source include/wait_until_disconnected.inc
--source include/kill_galera.inc
--connection node_1
--source include/wait_until_connected_again.inc

View file

@ -0,0 +1,41 @@
connection node_1;
connection node_1;
connection node_2;
connection node_3;
connection node_1;
SET GLOBAL innodb_max_dirty_pages_pct=99;
SET GLOBAL innodb_max_dirty_pages_pct_lwm=99;
connection node_1;
CREATE TABLE t1 (f1 INTEGER, f2 varchar(1024)) Engine=InnoDB;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
INSERT INTO t1 (f2) SELECT REPEAT('x', 1024) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
connection node_2;
Killing node #3 to free ports for garbd ...
connection node_3;
connection node_1;
SET GLOBAL debug_dbug = "+d,sync.wsrep_donor_state";
Starting garbd ...
SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_donor_state_reached";
SET GLOBAL innodb_max_dirty_pages_pct_lwm=0;
SET GLOBAL innodb_max_dirty_pages_pct=0;
SET SESSION debug_sync = "now SIGNAL signal.wsrep_donor_state";
SET GLOBAL debug_dbug = "";
SET debug_sync='RESET';
connection node_2;
Killing garbd ...
connection node_1;
connection node_2;
DROP TABLE t1;
DROP TABLE ten;
Restarting node #3 to satisfy MTR's end-of-test checks
connection node_3;
connection node_1;
SET GLOBAL innodb_max_dirty_pages_pct = 75.000000;
SET GLOBAL innodb_max_dirty_pages_pct_lwm = 0.000000;
connection node_1;
CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)");
connection node_2;
CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)");
connection node_3;
CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)");

View file

@ -0,0 +1,13 @@
!include ../galera_3nodes.cnf
[mysqld]
wsrep_sst_method=rsync
[mysqld.1]
wsrep_node_name=node1
[mysqld.2]
wsrep_node_name=node2
[mysqld.3]
wsrep_node_name=node3

View file

@ -0,0 +1,134 @@
#
# A very basic test for the galera arbitrator. We shut down node #3 and use its port allocation to start garbd.
# As MTR does not allow multiple servers to be down at the same time, we are limited as to what we can test.
#
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_garbd.inc
--source include/big_test.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
--connection node_1
# Save original auto_increment_offset values.
--let $node_1=node_1
--let $node_2=node_2
--let $node_3=node_3
--let $galera_connection_name = node_3
--let $galera_server_number = 3
--source include/galera_connect.inc
--source suite/galera/include/galera_base_port.inc
--let $NODE_GALERAPORT_3 = $_NODE_GALERAPORT
--source ../galera/include/auto_increment_offset_save.inc
# Save galera ports
--connection node_1
--source suite/galera/include/galera_base_port.inc
--let $NODE_GALERAPORT_1 = $_NODE_GALERAPORT
--let $datadir= `SELECT @@datadir`
--let $innodb_max_dirty_pages_pct = `SELECT @@innodb_max_dirty_pages_pct`
--let $innodb_max_dirty_pages_pct_lwm = `SELECT @@innodb_max_dirty_pages_pct_lwm`
SET GLOBAL innodb_max_dirty_pages_pct=99;
SET GLOBAL innodb_max_dirty_pages_pct_lwm=99;
--connection node_1
CREATE TABLE t1 (f1 INTEGER, f2 varchar(1024)) Engine=InnoDB;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
INSERT INTO t1 (f2) SELECT REPEAT('x', 1024) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
--connection node_2
--source suite/galera/include/galera_base_port.inc
--let $NODE_GALERAPORT_2 = $_NODE_GALERAPORT
--echo Killing node #3 to free ports for garbd ...
--connection node_3
--source include/shutdown_mysqld.inc
--connection node_1
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
# stop SST donor thread when node is in donor state
SET GLOBAL debug_dbug = "+d,sync.wsrep_donor_state";
--echo Starting garbd ...
--exec $MTR_GARBD_EXE --address "gcomm://127.0.0.1:$NODE_GALERAPORT_1" --group my_wsrep_cluster --donor node1 --sst backup --options 'base_port=$NODE_GALERAPORT_3' > $MYSQL_TMP_DIR/garbd.log 2>&1 &
SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_donor_state_reached";
#
# get hash of data directory contents before BP dirty page flushing
#
--exec find $datadir -type f ! -name tables_flushed ! -name backup_sst_complete -exec md5sum {} \; | md5sum >$MYSQLTEST_VARDIR/tmp/innodb_before
# this should force buffer pool flushing, if not already done by donor state change transfer
SET GLOBAL innodb_max_dirty_pages_pct_lwm=0;
SET GLOBAL innodb_max_dirty_pages_pct=0;
--disable_query_log
--disable_result_log
select f1 from t1;
select * from ten;
--enable_result_log
--enable_query_log
#
#
# record the hash of data directory contents after BP dirty page flushing
#
--exec find $datadir -type f ! -name tables_flushed ! -name backup_sst_complete -exec md5sum {} \; | md5sum >$MYSQLTEST_VARDIR/tmp/innodb_after
# there should be no disk writes
--diff_files $MYSQLTEST_VARDIR/tmp/innodb_before $MYSQLTEST_VARDIR/tmp/innodb_after
SET SESSION debug_sync = "now SIGNAL signal.wsrep_donor_state";
SET GLOBAL debug_dbug = "";
SET debug_sync='RESET';
--connection node_2
#
# garbd will die automatically, because of the backup SST script
# but just to be sure, sending explicit kill here, as well
#
--echo Killing garbd ...
# FreeBSD's /bin/pkill only supports short versions of the options:
# -o Select only the oldest (least recently started)
# -f Match against full argument lists
--error 0,1
--exec pkill -o -f garbd.*$NODE_GALERAPORT_3
--connection node_1
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
--connection node_2
DROP TABLE t1;
DROP TABLE ten;
--echo Restarting node #3 to satisfy MTR's end-of-test checks
--connection node_3
let $restart_noprint=2;
--source include/start_mysqld.inc
--connection node_1
--eval SET GLOBAL innodb_max_dirty_pages_pct = $innodb_max_dirty_pages_pct
--eval SET GLOBAL innodb_max_dirty_pages_pct_lwm = $innodb_max_dirty_pages_pct_lwm
--source ../galera/include/auto_increment_offset_restore.inc
--connection node_1
CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)");
--connection node_2
CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)");
--connection node_3
CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)");

View file

@ -0,0 +1,30 @@
include/rpl_init.inc [topology=1->2->3]
call mtr.add_suppression('Unsafe statement written to the binary log using ');
connection server_1;
set binlog_format=statement;
#first bug
create table t1 (a int);
create temporary table tmp like t1;
load data local infile 'MYSQLTEST_VARDIR/load_data' INTO TABLE tmp;
insert into t1 select * from tmp;
#second bug
create table t2 (a int);
create temporary table tmp2 like t2;
insert into tmp2 values(10);
update tmp2 set a = 20 limit 1;
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted
insert into t2 select * from tmp2;
connection server_2;
connection server_3;
#t1 should have 2 rows
select count(*) = 2 from t1;
count(*) = 2
1
#t2 should have 1 rows with a = 20
select * from t2;
a
20
connection server_1;
drop table t1, t2, tmp, tmp2;
include/rpl_end.inc

View file

@ -0,0 +1,8 @@
!include ../my.cnf
[mysqld.3]
log-slave-updates
[ENV]
SERVER_MYPORT_3= @mysqld.3.port
SERVER_MYSOCK_3= @mysqld.3.socket

View file

@ -0,0 +1,56 @@
#
# MDEV-24667 LOAD DATA INFILE/inserted rows not written to binlog
#
# In this test we will have a replication configuration like 1->2->3
# 1 will have statement format
# 2 and 3 will have mixed format
# We will make some updates on temporary table which are unsafe , So 2 must
# Log these queries in row format, Since it is on tmp table , It wont be logged
# So the next query which copies the data from tmp table to normal must be logged
# into the row format. Instead of checking for the binlog We will compare the
# results on the 3, If no binlog is lost(ie it is logged into row format), There
# should not be any data loss.
--let $rpl_topology=1->2->3
--source include/rpl_init.inc
--source include/have_binlog_format_mixed.inc
call mtr.add_suppression('Unsafe statement written to the binary log using ');
--connection server_1
set binlog_format=statement;
--echo #first bug
create table t1 (a int);
create temporary table tmp like t1;
--write_file $MYSQLTEST_VARDIR/load_data
1
2
EOF
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval load data local infile '$MYSQLTEST_VARDIR/load_data' INTO TABLE tmp;
insert into t1 select * from tmp;
--echo #second bug
create table t2 (a int);
#insert into t2 values(10);
create temporary table tmp2 like t2;
insert into tmp2 values(10);
update tmp2 set a = 20 limit 1;
insert into t2 select * from tmp2;
--save_master_pos
--connection server_2
--sync_with_master
--save_master_pos
--connection server_3
--sync_with_master
--echo #t1 should have 2 rows
select count(*) = 2 from t1;
--echo #t2 should have 1 rows with a = 20
select * from t2;
# cleanup
--connection server_1
drop table t1, t2, tmp, tmp2;
--remove_file $MYSQLTEST_VARDIR/load_data
--source include/rpl_end.inc

View file

@ -46,12 +46,15 @@ static BOOL win_rename_with_retries(const char *from, const char *to)
for (int retry= RENAME_MAX_RETRIES; retry--;)
{
DWORD ret = MoveFileEx(from, to,
BOOL ret= MoveFileEx(from, to,
MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
DBUG_ASSERT(fp == NULL || (ret == FALSE && GetLastError() == ERROR_SHARING_VIOLATION));
if (ret)
return ret;
if (!ret && (GetLastError() == ERROR_SHARING_VIOLATION))
DWORD last_error= GetLastError();
if (last_error == ERROR_SHARING_VIOLATION ||
last_error == ERROR_ACCESS_DENIED)
{
#ifndef DBUG_OFF
/*

View file

@ -2352,6 +2352,9 @@ int get_db_mysql57(MYSQL_THD thd, char **name, size_t *len)
#ifdef __x86_64__
db_off= 608;
db_len_off= 616;
#elif __aarch64__
db_off= 632;
db_len_off= 640;
#else
db_off= 0;
db_len_off= 0;
@ -2362,6 +2365,9 @@ int get_db_mysql57(MYSQL_THD thd, char **name, size_t *len)
#ifdef __x86_64__
db_off= 536;
db_len_off= 544;
#elif __aarch64__
db_off= 552;
db_len_off= 560;
#else
db_off= 0;
db_len_off= 0;

View file

@ -275,6 +275,7 @@ ELSE()
wsrep_sst_mysqldump
wsrep_sst_rsync
wsrep_sst_mariabackup
wsrep_sst_backup
)
# The following script is sourced from other SST scripts, so it should
# not be made executable.

View file

@ -541,7 +541,7 @@ mysqld_install_cmd_line()
{
"$mysqld_bootstrap" $defaults $defaults_group_suffix "$mysqld_opt" --bootstrap $silent_startup\
"--basedir=$basedir" "--datadir=$ldata" --log-warnings=0 --enforce-storage-engine="" \
"--plugin-dir=${plugindir}" --loose-disable-plugin-file-key-management \
"--plugin-dir=${plugindir}" \
$args --max_allowed_packet=8M \
--net_buffer_length=16K
}

View file

@ -1,5 +1,5 @@
-- Copyright (C) 2003, 2013 Oracle and/or its affiliates.
-- Copyright (C) 2010, 2018 MariaDB Corporation
-- Copyright (C) 2010, 2022, MariaDB Corporation
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
@ -744,6 +744,13 @@ ALTER TABLE help_topic MODIFY url TEXT NOT NULL;
# MDEV-7383 - varbinary on mix/max of column_stats
alter table column_stats modify min_value varbinary(255) DEFAULT NULL, modify max_value varbinary(255) DEFAULT NULL;
# MDEV-21873: 10.2 to 10.3 upgrade doesn't remove semi-sync reference from
# mysql.plugin table.
# As per suggested fix, check INFORMATION_SCHEMA.PLUGINS
# and if semisync plugins aren't there, delete them from mysql.plugin.
DELETE FROM mysql.plugin WHERE name="rpl_semi_sync_master" AND NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME="rpl_semi_sync_master");
DELETE FROM mysql.plugin WHERE name="rpl_semi_sync_slave" AND NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME="rpl_semi_sync_slave");
--
-- Ensure that all tables are of type Aria and transactional
--

112
scripts/wsrep_sst_backup.sh Normal file
View file

@ -0,0 +1,112 @@
#!/usr/bin/env bash
set -ue
# Copyright (C) 2017-2021 MariaDB
# Copyright (C) 2010-2014 Codership Oy
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston
# MA 02110-1335 USA.
# This is a reference script for rsync-based state snapshot transfer
RSYNC_REAL_PID=0 # rsync process id
STUNNEL_REAL_PID=0 # stunnel process id
OS="$(uname)"
[ "$OS" = 'Darwin' ] && export -n LD_LIBRARY_PATH
# Setting the path for lsof on CentOS
export PATH="/usr/sbin:/sbin:$PATH"
. $(dirname "$0")/wsrep_sst_common
MAGIC_FILE="$WSREP_SST_OPT_DATA/backup_sst_complete"
rm -rf "$MAGIC_FILE"
WSREP_LOG_DIR=${WSREP_LOG_DIR:-""}
# if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf
if [ -z "$WSREP_LOG_DIR" ]; then
WSREP_LOG_DIR=$(parse_cnf mysqld innodb-log-group-home-dir '')
fi
if [ -n "$WSREP_LOG_DIR" ]; then
# handle both relative and absolute paths
WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; mkdir -p "$WSREP_LOG_DIR"; cd $WSREP_LOG_DIR; pwd -P)
else
# default to datadir
WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; pwd -P)
fi
if [ "$WSREP_SST_OPT_ROLE" = 'donor' ]
then
[ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE"
RC=0
if [ $WSREP_SST_OPT_BYPASS -eq 0 ]; then
FLUSHED="$WSREP_SST_OPT_DATA/tables_flushed"
ERROR="$WSREP_SST_OPT_DATA/sst_error"
[ -f "$FLUSHED" ] && rm -f "$FLUSHED"
[ -f "$ERROR" ] && rm -f "$ERROR"
echo "flush tables"
# Wait for :
# (a) Tables to be flushed, AND
# (b) Cluster state ID & wsrep_gtid_domain_id to be written to the file, OR
# (c) ERROR file, in case flush tables operation failed.
while [ ! -r "$FLUSHED" ] && \
! grep -q -F ':' '--' "$FLUSHED" >/dev/null 2>&1
do
# Check whether ERROR file exists.
if [ -f "$ERROR" ]; then
# Flush tables operation failed.
rm -f "$ERROR"
exit 255
fi
sleep 0.2
done
STATE=$(cat "$FLUSHED")
rm -f "$FLUSHED"
else # BYPASS
wsrep_log_info "Bypassing state dump."
fi
echo 'continue' # now server can resume updating data
echo "$STATE" > "$MAGIC_FILE"
echo "done $STATE"
elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]
then
wsrep_log_error "Unrecognized role: '$WSREP_SST_OPT_ROLE'"
exit 22 # EINVAL
else
wsrep_log_error "Unrecognized role: '$WSREP_SST_OPT_ROLE'"
exit 22 # EINVAL
fi
exit 0

View file

@ -42,6 +42,8 @@ struct show_table_contributors_st show_table_contributors[]= {
{"Microsoft", "https://microsoft.com/", "Platinum Sponsor of the MariaDB Foundation"},
{"MariaDB Corporation", "https://mariadb.com", "Founding member, Platinum Sponsor of the MariaDB Foundation"},
{"ServiceNow", "https://servicenow.com", "Platinum Sponsor of the MariaDB Foundation"},
{"Intel", "https://www.intel.com", "Platinum Sponsor of the MariaDB Foundation"},
{"SIT", "https://sit.org", "Platinum Sponsor of the MariaDB Foundation"},
{"Visma", "https://visma.com", "Gold Sponsor of the MariaDB Foundation"},
{"DBS", "https://dbs.com", "Gold Sponsor of the MariaDB Foundation"},
{"IBM", "https://www.ibm.com", "Gold Sponsor of the MariaDB Foundation"},

View file

@ -2,7 +2,7 @@
#define HANDLER_INCLUDED
/*
Copyright (c) 2000, 2019, Oracle and/or its affiliates.
Copyright (c) 2009, 2021, MariaDB
Copyright (c) 2009, 2022, MariaDB
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -5001,7 +5001,7 @@ static inline const char *ha_resolve_storage_engine_name(const handlerton *db_ty
static inline bool ha_check_storage_engine_flag(const handlerton *db_type, uint32 flag)
{
return db_type == NULL ? FALSE : MY_TEST(db_type->flags & flag);
return db_type && (db_type->flags & flag);
}
static inline bool ha_storage_engine_is_enabled(const handlerton *db_type)

View file

@ -2676,9 +2676,11 @@ Item_sp::func_name(THD *thd) const
/* Calculate length to avoid reallocation of string for sure */
size_t len= (((m_name->m_explicit_name ? m_name->m_db.length : 0) +
m_name->m_name.length)*2 + //characters*quoting
2 + // ` and `
2 + // quotes for the function name
2 + // quotes for the package name
(m_name->m_explicit_name ?
3 : 0) + // '`', '`' and '.' for the db
1 + // '.' between package and function
1 + // end of string
ALIGN_SIZE(1)); // to avoid String reallocation
String qname((char *)alloc_root(thd->mem_root, len), len,
@ -2690,7 +2692,21 @@ Item_sp::func_name(THD *thd) const
append_identifier(thd, &qname, &m_name->m_db);
qname.append('.');
}
append_identifier(thd, &qname, &m_name->m_name);
if (m_sp && m_sp->m_handler == &sp_handler_package_function)
{
/*
In case of a package function split `pkg.func` and print
quoted `pkg` and `func` separately, so the entire result looks like:
`db`.`pkg`.`func`
*/
Database_qualified_name tmp= Database_qualified_name::split(m_name->m_name);
DBUG_ASSERT(tmp.m_db.length);
append_identifier(thd, &qname, &tmp.m_db);
qname.append('.');
append_identifier(thd, &qname, &tmp.m_name);
}
else
append_identifier(thd, &qname, &m_name->m_name);
return qname.c_ptr_safe();
}

View file

@ -4695,10 +4695,11 @@ void Item_func_in::mark_as_condition_AND_part(TABLE_LIST *embedding)
Query_arena *arena, backup;
arena= thd->activate_stmt_arena_if_needed(&backup);
if (to_be_transformed_into_in_subq(thd))
if (!transform_into_subq_checked)
{
transform_into_subq= true;
thd->lex->current_select->in_funcs.push_back(this, thd->mem_root);
if ((transform_into_subq= to_be_transformed_into_in_subq(thd)))
thd->lex->current_select->in_funcs.push_back(this, thd->mem_root);
transform_into_subq_checked= true;
}
if (arena)

View file

@ -2345,6 +2345,7 @@ protected:
SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
Field *field, Item *value);
bool transform_into_subq;
bool transform_into_subq_checked;
public:
/// An array of values, created when the bisection lookup method is used
in_vector *array;
@ -2367,6 +2368,7 @@ public:
Item_func_opt_neg(thd, list),
Predicant_to_list_comparator(thd, arg_count - 1),
transform_into_subq(false),
transform_into_subq_checked(false),
array(0), have_null(0),
arg_types_compatible(FALSE), emb_on_expr_nest(0)
{ }

View file

@ -1669,7 +1669,7 @@ end:
{
table->file->ha_index_or_rnd_end();
ha_commit_trans(thd, FALSE);
ha_commit_trans(thd, TRUE);
trans_commit(thd);
}
if (table_opened)
{

View file

@ -1229,6 +1229,7 @@ int Repl_semi_sync_master::flush_net(THD *thd,
net_clear(net, 0);
net->pkt_nr++;
net->compress_pkt_nr++;
result = 0;
rpl_semi_sync_master_net_wait_num++;

View file

@ -3471,6 +3471,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
lex_query_tables_own_last= m_lex->query_tables_own_last;
prelocking_tables= *lex_query_tables_own_last;
*lex_query_tables_own_last= NULL;
m_lex->query_tables_last= m_lex->query_tables_own_last;
m_lex->mark_as_requiring_prelocking(NULL);
}
thd->rollback_item_tree_changes();

View file

@ -4195,13 +4195,13 @@ public:
*/
DBUG_PRINT("debug",
("temporary_tables: %s, in_sub_stmt: %s, system_thread: %s",
YESNO(has_thd_temporary_tables()), YESNO(in_sub_stmt),
YESNO(has_temporary_tables()), YESNO(in_sub_stmt),
show_system_thread(system_thread)));
if (in_sub_stmt == 0)
{
if (wsrep_binlog_format() == BINLOG_FORMAT_ROW)
set_current_stmt_binlog_format_row();
else if (!has_thd_temporary_tables())
else if (!has_temporary_tables())
set_current_stmt_binlog_format_stmt();
}
DBUG_VOID_RETURN;
@ -6852,6 +6852,19 @@ public:
}
void copy(MEM_ROOT *mem_root, const LEX_CSTRING &db,
const LEX_CSTRING &name);
static Database_qualified_name split(const LEX_CSTRING &txt)
{
DBUG_ASSERT(txt.str[txt.length] == '\0'); // Expect 0-terminated input
const char *dot= strchr(txt.str, '.');
if (!dot)
return Database_qualified_name(NULL, 0, txt.str, txt.length);
size_t dblen= dot - txt.str;
Lex_cstring db(txt.str, dblen);
Lex_cstring name(txt.str + dblen + 1, txt.length - dblen - 1);
return Database_qualified_name(db, name);
}
// Export db and name as a qualified name string: 'db.name'
size_t make_qname(char *dst, size_t dstlen) const
{

View file

@ -8493,6 +8493,40 @@ bool LEX::call_statement_start(THD *thd, const LEX_CSTRING *name1,
}
bool LEX::call_statement_start(THD *thd, const LEX_CSTRING &db,
const LEX_CSTRING &pkg,
const LEX_CSTRING &proc)
{
Database_qualified_name q_db_pkg(db, pkg);
Database_qualified_name q_pkg_proc(pkg, proc);
sp_name *spname;
sql_command= SQLCOM_CALL;
if (check_db_name((LEX_STRING*) const_cast<LEX_CSTRING*>(&db)))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
return NULL;
}
if (check_routine_name(&pkg) ||
check_routine_name(&proc))
return NULL;
// Concat `pkg` and `name` to `pkg.name`
LEX_CSTRING pkg_dot_proc;
if (q_pkg_proc.make_qname(thd->mem_root, &pkg_dot_proc) ||
check_ident_length(&pkg_dot_proc) ||
!(spname= new (thd->mem_root) sp_name(&db, &pkg_dot_proc, true)))
return NULL;
sp_handler_package_function.add_used_routine(thd->lex, thd, spname);
sp_handler_package_body.add_used_routine(thd->lex, thd, &q_db_pkg);
return !(m_sql_cmd= new (thd->mem_root) Sql_cmd_call(spname,
&sp_handler_package_procedure));
}
sp_package *LEX::get_sp_package() const
{
return sphead ? sphead->get_package() : NULL;
@ -8750,6 +8784,56 @@ Item *LEX::make_item_func_call_generic(THD *thd, Lex_ident_cli_st *cdb,
}
/*
Create a 3-step qualified function call.
Currently it's possible for package routines only, e.g.:
SELECT db.pkg.func();
*/
Item *LEX::make_item_func_call_generic(THD *thd,
Lex_ident_cli_st *cdb,
Lex_ident_cli_st *cpkg,
Lex_ident_cli_st *cfunc,
List<Item> *args)
{
static Lex_cstring dot(".", 1);
Lex_ident_sys db(thd, cdb), pkg(thd, cpkg), func(thd, cfunc);
Database_qualified_name q_db_pkg(db, pkg);
Database_qualified_name q_pkg_func(pkg, func);
sp_name *qname;
if (db.is_null() || pkg.is_null() || func.is_null())
return NULL; // EOM
if (check_db_name((LEX_STRING*) static_cast<LEX_CSTRING*>(&db)))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
return NULL;
}
if (check_routine_name(&pkg) ||
check_routine_name(&func))
return NULL;
// Concat `pkg` and `name` to `pkg.name`
LEX_CSTRING pkg_dot_func;
if (q_pkg_func.make_qname(thd->mem_root, &pkg_dot_func) ||
check_ident_length(&pkg_dot_func) ||
!(qname= new (thd->mem_root) sp_name(&db, &pkg_dot_func, true)))
return NULL;
sp_handler_package_function.add_used_routine(thd->lex, thd, qname);
sp_handler_package_body.add_used_routine(thd->lex, thd, &q_db_pkg);
thd->lex->safe_to_cache_query= 0;
if (args && args->elements > 0)
return new (thd->mem_root) Item_func_sp(thd, thd->lex->current_context(),
qname, &sp_handler_package_function,
*args);
return new (thd->mem_root) Item_func_sp(thd, thd->lex->current_context(),
qname, &sp_handler_package_function);
}
Item *LEX::create_item_qualified_asterisk(THD *thd,
const Lex_ident_sys_st *name)
{

View file

@ -3798,6 +3798,9 @@ public:
bool call_statement_start(THD *thd, const LEX_CSTRING *name);
bool call_statement_start(THD *thd, const LEX_CSTRING *name1,
const LEX_CSTRING *name2);
bool call_statement_start(THD *thd, const LEX_CSTRING &name1,
const LEX_CSTRING &name2,
const LEX_CSTRING &name3);
sp_variable *find_variable(const LEX_CSTRING *name,
sp_pcontext **ctx,
const Sp_rcontext_handler **rh) const;
@ -4024,6 +4027,11 @@ public:
Item *make_item_func_substr(THD *thd, Item *a, Item *b);
Item *make_item_func_call_generic(THD *thd, Lex_ident_cli_st *db,
Lex_ident_cli_st *name, List<Item> *args);
Item *make_item_func_call_generic(THD *thd,
Lex_ident_cli_st *db,
Lex_ident_cli_st *pkg,
Lex_ident_cli_st *name,
List<Item> *args);
my_var *create_outvar(THD *thd, const LEX_CSTRING *name);
/*

View file

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
Copyright (c) 2009, 2020, MariaDB
Copyright (c) 2009, 2022, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -3375,6 +3375,16 @@ static my_bool processlist_callback(THD *tmp, processlist_callback_arg *arg)
arg->table->field[11]->store((double) tmp->progress.counter /
(double) max_counter*100.0);
}
else
{
/*
This is a DECIMAL column without DEFAULT.
restore_record() fills its Field::ptr to zero bytes,
according to pack_length(). But an array of zero bytes
is not a valid decimal. Set it explicitly to 0.
*/
arg->table->field[11]->store((longlong) 0, true);
}
mysql_mutex_unlock(&tmp->LOCK_thd_data);
}

View file

@ -9807,22 +9807,24 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
create_info->used_fields |= HA_CREATE_USED_ROW_FORMAT;
}
handlerton * const old_db_type= table->s->db_type();
handlerton *new_db_type= create_info->db_type;
DBUG_PRINT("info", ("old type: %s new type: %s",
ha_resolve_storage_engine_name(table->s->db_type()),
ha_resolve_storage_engine_name(create_info->db_type)));
if (ha_check_storage_engine_flag(table->s->db_type(), HTON_ALTER_NOT_SUPPORTED))
ha_resolve_storage_engine_name(old_db_type),
ha_resolve_storage_engine_name(new_db_type)));
if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED))
{
DBUG_PRINT("info", ("doesn't support alter"));
my_error(ER_ILLEGAL_HA, MYF(0), hton_name(table->s->db_type())->str,
my_error(ER_ILLEGAL_HA, MYF(0), hton_name(old_db_type)->str,
alter_ctx.db.str, alter_ctx.table_name.str);
DBUG_RETURN(true);
}
if (ha_check_storage_engine_flag(create_info->db_type,
HTON_ALTER_NOT_SUPPORTED))
if (ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
{
DBUG_PRINT("info", ("doesn't support alter"));
my_error(ER_ILLEGAL_HA, MYF(0), hton_name(create_info->db_type)->str,
my_error(ER_ILLEGAL_HA, MYF(0), hton_name(new_db_type)->str,
alter_ctx.new_db.str, alter_ctx.new_name.str);
DBUG_RETURN(true);
}
@ -9980,6 +9982,17 @@ do_continue:;
DBUG_RETURN(true);
}
}
/*
If the old table had partitions and we are doing ALTER TABLE ...
engine= <new_engine>, the new table must preserve the original
partitioning. This means that the new engine is still the
partitioning engine, not the engine specified in the parser.
This is discovered in prep_alter_part_table, which in such case
updates create_info->db_type.
It's therefore important that the assignment below is done
after prep_alter_part_table.
*/
new_db_type= create_info->db_type;
#endif
if (mysql_prepare_alter_table(thd, table, create_info, alter_info,
@ -10060,7 +10073,7 @@ do_continue:;
Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
|| is_inplace_alter_impossible(table, create_info, alter_info)
|| IF_PARTITIONING((partition_changed &&
!(table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)), 0))
!(old_db_type->partition_flags() & HA_USE_AUTO_PARTITION)), 0))
{
if (alter_info->algorithm(thd) ==
Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
@ -10078,22 +10091,10 @@ do_continue:;
request table rebuild. Set ALTER_RECREATE flag to force table
rebuild.
*/
if (create_info->db_type == table->s->db_type() &&
if (new_db_type == old_db_type &&
create_info->used_fields & HA_CREATE_USED_ENGINE)
alter_info->flags|= ALTER_RECREATE;
/*
If the old table had partitions and we are doing ALTER TABLE ...
engine= <new_engine>, the new table must preserve the original
partitioning. This means that the new engine is still the
partitioning engine, not the engine specified in the parser.
This is discovered in prep_alter_part_table, which in such case
updates create_info->db_type.
It's therefore important that the assignment below is done
after prep_alter_part_table.
*/
handlerton *new_db_type= create_info->db_type;
handlerton *old_db_type= table->s->db_type();
TABLE *new_table= NULL;
ha_rows copied=0,deleted=0;

View file

@ -899,8 +899,6 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
if (!transform_into_subq)
return this;
transform_into_subq= false;
List<List_item> values;
LEX *lex= thd->lex;
@ -1057,15 +1055,38 @@ uint32 Item_func_in::max_length_of_left_expr()
bool Item_func_in::to_be_transformed_into_in_subq(THD *thd)
{
bool is_row_list= args[1]->type() == Item::ROW_ITEM;
uint values_count= arg_count-1;
if (args[1]->type() == Item::ROW_ITEM)
if (is_row_list)
values_count*= ((Item_row *)(args[1]))->cols();
if (thd->variables.in_subquery_conversion_threshold == 0 ||
thd->variables.in_subquery_conversion_threshold > values_count)
return false;
if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_PREPARE))
return true;
/* Occurence of '?' in IN list is checked only for PREPARE <stmt> commands */
for (uint i=1; i < arg_count; i++)
{
if (!is_row_list)
{
if (args[i]->type() == Item::PARAM_ITEM)
return false;
}
else
{
Item_row *row_list= (Item_row *)(args[i]);
for (uint j=0; j < row_list->cols(); j++)
{
if (row_list->element_index(j)->type() == Item::PARAM_ITEM)
return false;
}
}
}
return true;
}

View file

@ -2288,6 +2288,11 @@ multi_update::initialize_tables(JOIN *join)
if (unlikely((thd->variables.option_bits & OPTION_SAFE_UPDATES) &&
error_if_full_join(join)))
DBUG_RETURN(1);
if (join->implicit_grouping)
{
my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0));
DBUG_RETURN(1);
}
main_table=join->join_tab->table;
table_to_update= 0;

View file

@ -97,7 +97,8 @@ static void make_unique_view_field_name(THD *thd, Item *target,
itc.rewind();
}
target->orig_name= target->name.str;
if (!target->orig_name)
target->orig_name= target->name.str;
target->set_name(thd, buff, name_len, system_charset_info);
}

View file

@ -3336,9 +3336,29 @@ sp_suid:
;
call:
CALL_SYM sp_name
CALL_SYM ident
{
if (unlikely(Lex->call_statement_start(thd, $2)))
if (unlikely(Lex->call_statement_start(thd, &$2)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| CALL_SYM ident '.' ident
{
if (unlikely(Lex->call_statement_start(thd, &$2, &$4)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| CALL_SYM ident '.' ident '.' ident
{
if (unlikely(Lex->call_statement_start(thd, $2, $4, $6)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
@ -11451,6 +11471,11 @@ function_call_generic:
if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, $5))))
MYSQL_YYABORT;
}
| ident_cli '.' ident_cli '.' ident_cli '(' opt_expr_list ')'
{
if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, &$5, $7))))
MYSQL_YYABORT;
}
;
fulltext_options:

View file

@ -3138,9 +3138,29 @@ sp_suid:
;
call:
CALL_SYM sp_name
CALL_SYM ident
{
if (unlikely(Lex->call_statement_start(thd, $2)))
if (unlikely(Lex->call_statement_start(thd, &$2)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| CALL_SYM ident '.' ident
{
if (unlikely(Lex->call_statement_start(thd, &$2, &$4)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| CALL_SYM ident '.' ident '.' ident
{
if (unlikely(Lex->call_statement_start(thd, $2, $4, $6)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
@ -4054,12 +4074,30 @@ sp_statement:
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| ident_directly_assignable '.' ident
{
if (unlikely(Lex->call_statement_start(thd, &$1, &$3)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| ident_directly_assignable '.' ident '.' ident
{
if (unlikely(Lex->call_statement_start(thd, $1, $3, $5)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
sp_proc_stmt_statement:
@ -11549,6 +11587,11 @@ function_call_generic:
if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, $5))))
MYSQL_YYABORT;
}
| ident_cli '.' ident_cli '.' ident_cli '(' opt_expr_list ')'
{
if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, &$5, $7))))
MYSQL_YYABORT;
}
;
fulltext_options:

View file

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
Copyright (c) 2008, 2021, MariaDB
Copyright (c) 2008, 2022, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1627,6 +1627,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
MEM_ROOT *old_root= thd->mem_root;
Virtual_column_info **table_check_constraints;
bool *interval_unescaped= NULL;
extra2_fields extra2;
DBUG_ENTER("TABLE_SHARE::init_from_binary_frm_image");
@ -2047,6 +2048,13 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
goto err;
if (interval_count)
{
if (!(interval_unescaped= (bool*) my_alloca(interval_count * sizeof(bool))))
goto err;
bzero(interval_unescaped, interval_count * sizeof(bool));
}
field_ptr= share->field;
table_check_constraints= share->check_constraints;
read_length=(uint) (share->fields * field_pack_length +
@ -2323,11 +2331,17 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (share->mysql_version < 100200)
attr.pack_flag&= ~FIELDFLAG_LONG_DECIMAL;
if (interval_nr && attr.charset->mbminlen > 1)
if (interval_nr && attr.charset->mbminlen > 1 &&
!interval_unescaped[interval_nr - 1])
{
/* Unescape UCS2 intervals from HEX notation */
/*
Unescape UCS2/UTF16/UTF32 intervals from HEX notation.
Note, ENUM/SET columns with equal value list share a single
copy of TYPELIB. Unescape every TYPELIB only once.
*/
TYPELIB *interval= share->intervals + interval_nr - 1;
unhex_type2(interval);
interval_unescaped[interval_nr - 1]= true;
}
#ifndef TO_BE_DELETED_ON_PRODUCTION
@ -3060,6 +3074,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
share->error= OPEN_FRM_OK;
thd->status_var.opened_shares++;
thd->mem_root= old_root;
my_afree(interval_unescaped);
DBUG_RETURN(0);
err:
@ -3074,6 +3089,7 @@ err:
open_table_error(share, OPEN_FRM_CORRUPTED, share->open_errno);
thd->mem_root= old_root;
my_afree(interval_unescaped);
DBUG_RETURN(HA_ERR_NOT_A_TABLE);
}

View file

@ -873,7 +873,7 @@ void THD::restore_tmp_table_share(TMP_TABLE_SHARE *share)
@return false Temporary tables exist
true No temporary table exist
*/
inline bool THD::has_temporary_tables()
bool THD::has_temporary_tables()
{
DBUG_ENTER("THD::has_temporary_tables");
bool result=

View file

@ -830,7 +830,16 @@ static uint get_interval_id(uint *int_count,List<Create_field> &create_fields,
while ((field=it++) != last_field)
{
if (field->interval_id && field->interval->count == interval->count)
/*
ENUM/SET columns with equal value lists share a single
copy of the underlying TYPELIB.
Fields with different mbminlen can't reuse TYPELIBs, because:
- mbminlen==1 are written to FRM as is
- mbminlen>1 are written to FRM in hex-encoded format
*/
if (field->interval_id &&
field->interval->count == interval->count &&
field->charset->mbminlen == last_field->charset->mbminlen)
{
const char **a,**b;
for (a=field->interval->type_names, b=interval->type_names ;

View file

@ -1,4 +1,4 @@
/* Copyright 2008-2020 Codership Oy <http://www.codership.com>
/* Copyright 2008-2022 Codership Oy <http://www.codership.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -32,6 +32,7 @@
#include <cstdio>
#include <cstdlib>
#include "debug_sync.h"
#include <my_service_manager.h>
@ -1504,6 +1505,33 @@ static int run_sql_command(THD *thd, const char *query)
return 0;
}
static void sst_disallow_writes (THD* thd, bool yes)
{
char query_str[64]= { 0, };
ssize_t const query_max= sizeof(query_str) - 1;
CHARSET_INFO *current_charset;
current_charset= thd->variables.character_set_client;
if (!is_supported_parser_charset(current_charset))
{
/* Do not use non-supported parser character sets */
WSREP_WARN("Current client character set is non-supported parser character set: %s", current_charset->csname);
thd->variables.character_set_client= &my_charset_latin1;
WSREP_WARN("For SST temporally setting character set to : %s",
my_charset_latin1.csname);
}
snprintf (query_str, query_max, "SET GLOBAL innodb_disallow_writes=%d",
yes ? 1 : 0);
if (run_sql_command(thd, query_str))
{
WSREP_ERROR("Failed to disallow InnoDB writes");
}
thd->variables.character_set_client= current_charset;
}
static int sst_flush_tables(THD* thd)
{
@ -1565,6 +1593,11 @@ static int sst_flush_tables(THD* thd)
else
{
WSREP_INFO("Tables flushed.");
/* disable further disk IO */
sst_disallow_writes(thd, true);
WSREP_INFO("Disabled further disk IO.");
/*
Tables have been flushed. Create a file with cluster state ID and
wsrep_gtid_domain_id.
@ -1574,6 +1607,9 @@ static int sst_flush_tables(THD* thd)
(long long)wsrep_locked_seqno, wsrep_gtid_domain_id);
err= sst_create_file(flush_success, content);
if (err)
WSREP_INFO("Creating file for flush_success failed %d",err);
const char base_name[]= "tables_flushed";
ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2;
char *real_name= (char*) malloc(full_len);
@ -1613,34 +1649,6 @@ static int sst_flush_tables(THD* thd)
return err;
}
static void sst_disallow_writes (THD* thd, bool yes)
{
char query_str[64]= { 0, };
ssize_t const query_max= sizeof(query_str) - 1;
CHARSET_INFO *current_charset;
current_charset= thd->variables.character_set_client;
if (!is_supported_parser_charset(current_charset))
{
/* Do not use non-supported parser character sets */
WSREP_WARN("Current client character set is non-supported parser character set: %s", current_charset->csname);
thd->variables.character_set_client= &my_charset_latin1;
WSREP_WARN("For SST temporally setting character set to : %s",
my_charset_latin1.csname);
}
snprintf (query_str, query_max, "SET GLOBAL innodb_disallow_writes=%d",
yes ? 1 : 0);
if (run_sql_command(thd, query_str))
{
WSREP_ERROR("Failed to disallow InnoDB writes");
}
thd->variables.character_set_client= current_charset;
}
static void* sst_donor_thread (void* a)
{
sst_thread_arg* arg= (sst_thread_arg*)a;
@ -1688,8 +1696,7 @@ wait_signal:
err= sst_flush_tables (thd.ptr);
if (!err)
{
sst_disallow_writes (thd.ptr, true);
/*
/*
Lets also keep statements that modify binary logs (like RESET LOGS,
RESET MASTER) from proceeding until the files have been transferred
to the joiner node.
@ -1700,6 +1707,18 @@ wait_signal:
}
locked= true;
WSREP_INFO("Donor state reached");
DBUG_EXECUTE_IF("sync.wsrep_donor_state",
{
const char act[]=
"now "
"SIGNAL sync.wsrep_donor_state_reached "
"WAIT_FOR signal.wsrep_donor_state";
assert(!debug_sync_set_action(thd.ptr,
STRING_WITH_LEN(act)));
};);
goto wait_signal;
}
}

View file

@ -2,7 +2,7 @@
Copyright (c) 1995, 2021, Oracle and/or its affiliates.
Copyright (c) 2008, Google Inc.
Copyright (c) 2013, 2021, MariaDB Corporation.
Copyright (c) 2013, 2022, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@ -1021,9 +1021,6 @@ buf_page_is_corrupted(
size_t checksum_field1 = 0;
size_t checksum_field2 = 0;
uint32_t crc32 = 0;
bool crc32_inited = false;
bool crc32_chksum = false;
const ulint zip_size = fil_space_t::zip_size(fsp_flags);
ulint page_type = mach_read_from_2(read_buf + FIL_PAGE_TYPE);
@ -1119,9 +1116,14 @@ buf_page_is_corrupted(
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
return !buf_page_is_checksum_valid_none(
read_buf, checksum_field1, checksum_field2);
case SRV_CHECKSUM_ALGORITHM_NONE:
/* should have returned false earlier */
break;
case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
case SRV_CHECKSUM_ALGORITHM_CRC32:
case SRV_CHECKSUM_ALGORITHM_INNODB:
const uint32_t crc32 = buf_calc_page_crc32(read_buf);
if (buf_page_is_checksum_valid_none(read_buf,
checksum_field1, checksum_field2)) {
#ifdef UNIV_INNOCHECKSUM
@ -1137,16 +1139,13 @@ buf_page_is_corrupted(
" crc32 = " UINT32PF "; recorded = " ULINTPF ";\n",
cur_page_num,
buf_calc_page_new_checksum(read_buf),
buf_calc_page_crc32(read_buf),
crc32,
checksum_field1);
}
#endif /* UNIV_INNOCHECKSUM */
return false;
}
crc32_chksum = curr_algo == SRV_CHECKSUM_ALGORITHM_CRC32
|| curr_algo == SRV_CHECKSUM_ALGORITHM_FULL_CRC32;
/* Very old versions of InnoDB only stored 8 byte lsn to the
start and the end of the page. */
@ -1157,81 +1156,33 @@ buf_page_is_corrupted(
!= mach_read_from_4(read_buf + FIL_PAGE_LSN)
&& checksum_field2 != BUF_NO_CHECKSUM_MAGIC) {
if (crc32_chksum) {
crc32 = buf_calc_page_crc32(read_buf);
crc32_inited = true;
DBUG_EXECUTE_IF(
"page_intermittent_checksum_mismatch", {
static int page_counter;
if (page_counter++ == 2) return true;
});
DBUG_EXECUTE_IF(
"page_intermittent_checksum_mismatch", {
static int page_counter;
if (page_counter++ == 2) {
crc32++;
}
});
if (checksum_field2 != crc32
&& checksum_field2
!= buf_calc_page_old_checksum(read_buf)) {
return true;
}
} else {
ut_ad(curr_algo
== SRV_CHECKSUM_ALGORITHM_INNODB);
if (checksum_field2
!= buf_calc_page_old_checksum(read_buf)) {
crc32 = buf_calc_page_crc32(read_buf);
crc32_inited = true;
if (checksum_field2 != crc32) {
return true;
}
}
if ((checksum_field1 != crc32
|| checksum_field2 != crc32)
&& checksum_field2
!= buf_calc_page_old_checksum(read_buf)) {
return true;
}
}
if (checksum_field1 == 0
|| checksum_field1 == BUF_NO_CHECKSUM_MAGIC) {
} else if (crc32_chksum) {
if (!crc32_inited) {
crc32 = buf_calc_page_crc32(read_buf);
crc32_inited = true;
}
if (checksum_field1 != crc32
switch (checksum_field1) {
case 0:
case BUF_NO_CHECKSUM_MAGIC:
break;
default:
if ((checksum_field1 != crc32
|| checksum_field2 != crc32)
&& checksum_field1
!= buf_calc_page_new_checksum(read_buf)) {
return true;
}
} else {
ut_ad(curr_algo == SRV_CHECKSUM_ALGORITHM_INNODB);
if (checksum_field1
!= buf_calc_page_new_checksum(read_buf)) {
if (!crc32_inited) {
crc32 = buf_calc_page_crc32(read_buf);
crc32_inited = true;
}
if (checksum_field1 != crc32) {
return true;
}
}
}
if (crc32_inited
&& ((checksum_field1 == crc32
&& checksum_field2 != crc32)
|| (checksum_field1 != crc32
&& checksum_field2 == crc32))) {
return true;
}
break;
case SRV_CHECKSUM_ALGORITHM_NONE:
/* should have returned false earlier */
break;
}

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2021, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, 2021, MariaDB Corporation.
Copyright (c) 2014, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -2625,10 +2625,11 @@ fil_make_filepath(
if (path != NULL) {
memcpy(full_name, path, path_len);
len = path_len;
full_name[len] = '\0';
os_normalize_path(full_name);
}
full_name[len] = '\0';
os_normalize_path(full_name);
if (trim_name) {
/* Find the offset of the last DIR separator and set it to
null in order to strip off the old basename from this path. */

View file

@ -2273,9 +2273,7 @@ fts_trx_table_create(
fts_trx_table_t* ftt;
ftt = static_cast<fts_trx_table_t*>(
mem_heap_alloc(fts_trx->heap, sizeof(*ftt)));
memset(ftt, 0x0, sizeof(*ftt));
mem_heap_zalloc(fts_trx->heap, sizeof *ftt));
ftt->table = table;
ftt->fts_trx = fts_trx;

View file

@ -1,4 +1,5 @@
/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
@ -24,6 +25,9 @@
#include <my_sys.h>
#include <pfs_global.h>
#include <string.h>
#ifdef HAVE_MEMALIGN
# include <malloc.h>
#endif
bool pfs_initialized= false;
@ -43,7 +47,17 @@ void *pfs_malloc(size_t size, myf)
if (--stub_alloc_fails_after_count <= 0)
return NULL;
#ifndef PFS_ALIGNEMENT
void *ptr= malloc(size);
#elif defined HAVE_MEMALIGN
void *ptr= memalign(PFS_ALIGNEMENT, size);
#elif defined HAVE_ALIGNED_MALLOC
void *ptr= _aligned_malloc(size, PFS_ALIGNEMENT);
#else
void *ptr;
if (posix_memalign(&ptr, PFS_ALIGNEMENT, size))
ptr= NULL;
#endif
if (ptr != NULL)
memset(ptr, 0, size);
return ptr;

View file

@ -1128,13 +1128,21 @@ int decimal2ulonglong(const decimal_t *from, ulonglong *to)
for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
{
ulonglong y=x;
x=x*DIG_BASE + *buf++;
if (unlikely(y > ((ulonglong) ULONGLONG_MAX/DIG_BASE) || x < y))
/*
Check that the decimal is bigger than any possible integer.
Do it before we do the x*=DIB_BASE to avoid integer
overflow.
*/
if (unlikely (
x >= ULONGLONG_MAX/DIG_BASE &&
(x > ULONGLONG_MAX/DIG_BASE ||
*buf > (dec1) (ULONGLONG_MAX%DIG_BASE))))
{
*to=ULONGLONG_MAX;
return E_DEC_OVERFLOW;
}
x=x*DIG_BASE + *buf++;
}
*to=x;
for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
@ -1151,23 +1159,29 @@ int decimal2longlong(const decimal_t *from, longlong *to)
for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
{
longlong y=x;
/*
Check that the decimal is less than any possible integer.
Do it before we do the x*=DIB_BASE to avoid integer
overflow.
Attention: trick!
we're calculating -|from| instead of |from| here
because |LONGLONG_MIN| > LONGLONG_MAX
so we can convert -9223372036854775808 correctly
so we can convert -9223372036854775808 correctly.
*/
x=x*DIG_BASE - *buf++;
if (unlikely(y < (LONGLONG_MIN/DIG_BASE) || x > y))
if (unlikely (
x <= LONGLONG_MIN/DIG_BASE &&
(x < LONGLONG_MIN/DIG_BASE ||
*buf > (dec1) (-(LONGLONG_MIN%DIG_BASE)))))
{
/*
the decimal is bigger than any possible integer
return border integer depending on the sign
the decimal is bigger than any possible integer
return border integer depending on the sign
*/
*to= from->sign ? LONGLONG_MIN : LONGLONG_MAX;
return E_DEC_OVERFLOW;
}
x=x*DIG_BASE - *buf++;
}
/* boundary case: 9223372036854775808 */
if (unlikely(from->sign==0 && x == LONGLONG_MIN))