mirror of
https://github.com/MariaDB/server.git
synced 2025-01-27 01:04:19 +01:00
Merge 10.5 into 10.6
This commit is contained in:
commit
3a96eba25f
51 changed files with 976 additions and 267 deletions
3
debian/control
vendored
3
debian/control
vendored
|
@ -26,8 +26,7 @@ Build-Depends: bison,
|
||||||
libjudy-dev,
|
libjudy-dev,
|
||||||
libkrb5-dev,
|
libkrb5-dev,
|
||||||
liblz4-dev,
|
liblz4-dev,
|
||||||
libncurses5-dev (>= 5.0-6~),
|
libncurses-dev,
|
||||||
libncurses5-dev:native (>= 5.0-6~),
|
|
||||||
libnuma-dev [linux-any],
|
libnuma-dev [linux-any],
|
||||||
libpam0g-dev,
|
libpam0g-dev,
|
||||||
libpcre2-dev,
|
libpcre2-dev,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
--source include/have_compress.inc
|
--source include/have_compress.inc
|
||||||
|
|
||||||
# Test that the system is using the default/standard bzip library.
|
# Test that the system is using the default/standard zlib library.
|
||||||
# If not, we have to skip the test as the compression lengths displayed
|
# If not, we have to skip the test as the compression lengths displayed
|
||||||
# in the test will not match the results from used compression library.
|
# in the test will not match the results from used compression library.
|
||||||
|
|
||||||
if (`select length(COMPRESS(space(5000))) != 33`) {
|
if (`select length(COMPRESS(space(5000))) != 33`) {
|
||||||
skip Test skipped as standard bzip is needed;
|
skip Test skipped as standard zlib is needed;
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
--source include/have_innodb.inc
|
--source include/have_innodb.inc
|
||||||
--source include/have_csv.inc
|
--source include/have_csv.inc
|
||||||
--source include/have_normal_bzip.inc
|
--source include/have_normal_zlib.inc
|
||||||
|
|
||||||
let $MYSQLD_DATADIR= `select @@datadir`;
|
let $MYSQLD_DATADIR= `select @@datadir`;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
--source include/have_innodb.inc
|
--source include/have_innodb.inc
|
||||||
|
--source include/have_normal_zlib.inc
|
||||||
--source include/master-slave.inc
|
--source include/master-slave.inc
|
||||||
--source include/have_normal_bzip.inc
|
|
||||||
|
|
||||||
--let $engine_type= myisam
|
--let $engine_type= myisam
|
||||||
--let $engine_type2= innodb
|
--let $engine_type2= innodb
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
-- source include/have_compress.inc
|
-- source include/have_compress.inc
|
||||||
-- source include/have_normal_bzip.inc
|
-- source include/have_normal_zlib.inc
|
||||||
#
|
#
|
||||||
# Test for compress and uncompress functions:
|
# Test for compress and uncompress functions:
|
||||||
#
|
#
|
||||||
|
|
|
@ -5328,5 +5328,112 @@ SELECT BIT_XOR(a) FROM t1;
|
||||||
ERROR HY000: Illegal parameter data type geometry for operation 'bit_xor('
|
ERROR HY000: Illegal parameter data type geometry for operation 'bit_xor('
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
|
# MDEV-27666 User variable not parsed as geometry variable in geometry function.
|
||||||
|
#
|
||||||
|
set @g= point(1, 1);
|
||||||
|
select ST_AsWKT(GeometryCollection(Point(44, 6), @g));
|
||||||
|
ST_AsWKT(GeometryCollection(Point(44, 6), @g))
|
||||||
|
GEOMETRYCOLLECTION(POINT(44 6),POINT(1 1))
|
||||||
|
set @g= "just a string";
|
||||||
|
select ST_AsWKT(GeometryCollection(Point(44, 6), @g));
|
||||||
|
ERROR HY000: Illegal parameter data type longblob for operation 'geometrycollection'
|
||||||
|
SET @g= LineString(Point(0,0), Point(0,1));
|
||||||
|
SELECT AsText(PointN(@g, 1));
|
||||||
|
AsText(PointN(@g, 1))
|
||||||
|
POINT(0 0)
|
||||||
|
SELECT AsText(PointN(@g, 2));
|
||||||
|
AsText(PointN(@g, 2))
|
||||||
|
POINT(0 1)
|
||||||
|
SET @g= Point(1, 1);
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`g` point DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
AsText(g)
|
||||||
|
POINT(1 1)
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET @g= MultiPoint(Point(1, 1), Point(-1,-1));
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`g` multipoint DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
AsText(g)
|
||||||
|
MULTIPOINT(1 1,-1 -1)
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET @g= LineString(Point(1, 1), Point(2,2));
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`g` linestring DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
AsText(g)
|
||||||
|
LINESTRING(1 1,2 2)
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET @g= MultiLineString(LineString(Point(1, 1), Point(2,2)),
|
||||||
|
LineString(Point(-1, -1), Point(-2,-2)));
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`g` multilinestring DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
AsText(g)
|
||||||
|
MULTILINESTRING((1 1,2 2),(-1 -1,-2 -2))
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET @g= Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)));
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`g` polygon DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
AsText(g)
|
||||||
|
POLYGON((0 0,30 0,30 30,0 0))
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET @g= MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3),
|
||||||
|
Point(3, 0), Point(0, 3))));
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`g` multipolygon DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
AsText(g)
|
||||||
|
MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET @g= GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)));
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`g` geometrycollection DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
AsText(g)
|
||||||
|
GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET @g= GeometryFromText('POINT(1 1)');
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`g` geometry DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
AsText(g)
|
||||||
|
POINT(1 1)
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
# End of 10.5 tests
|
# End of 10.5 tests
|
||||||
#
|
#
|
||||||
|
|
|
@ -3374,6 +3374,69 @@ SELECT BIT_OR(a) FROM t1;
|
||||||
SELECT BIT_XOR(a) FROM t1;
|
SELECT BIT_XOR(a) FROM t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-27666 User variable not parsed as geometry variable in geometry function.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
set @g= point(1, 1);
|
||||||
|
select ST_AsWKT(GeometryCollection(Point(44, 6), @g));
|
||||||
|
set @g= "just a string";
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||||
|
select ST_AsWKT(GeometryCollection(Point(44, 6), @g));
|
||||||
|
|
||||||
|
SET @g= LineString(Point(0,0), Point(0,1));
|
||||||
|
SELECT AsText(PointN(@g, 1));
|
||||||
|
SELECT AsText(PointN(@g, 2));
|
||||||
|
|
||||||
|
SET @g= Point(1, 1);
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
SET @g= MultiPoint(Point(1, 1), Point(-1,-1));
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
SET @g= LineString(Point(1, 1), Point(2,2));
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
SET @g= MultiLineString(LineString(Point(1, 1), Point(2,2)),
|
||||||
|
LineString(Point(-1, -1), Point(-2,-2)));
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
SET @g= Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)));
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
SET @g= MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3),
|
||||||
|
Point(3, 0), Point(0, 3))));
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
SET @g= GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)));
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
SET @g= GeometryFromText('POINT(1 1)');
|
||||||
|
CREATE TABLE t1 AS SELECT @g AS g;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT AsText(g) FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.5 tests
|
--echo # End of 10.5 tests
|
||||||
|
|
|
@ -30,6 +30,12 @@ show create table mysql_json_test;
|
||||||
ERROR HY000: Table rebuild required. Please do "ALTER TABLE `test.mysql_json_test` FORCE" or dump/reload to fix it!
|
ERROR HY000: Table rebuild required. Please do "ALTER TABLE `test.mysql_json_test` FORCE" or dump/reload to fix it!
|
||||||
select * from mysql_json_test;
|
select * from mysql_json_test;
|
||||||
ERROR HY000: Table rebuild required. Please do "ALTER TABLE `test.mysql_json_test` FORCE" or dump/reload to fix it!
|
ERROR HY000: Table rebuild required. Please do "ALTER TABLE `test.mysql_json_test` FORCE" or dump/reload to fix it!
|
||||||
|
CREATE TABLE t2 AS SELECT * FROM mysql_json_test;
|
||||||
|
ERROR HY000: Table rebuild required. Please do "ALTER TABLE `test.mysql_json_test` FORCE" or dump/reload to fix it!
|
||||||
|
CREATE TABLE t2 (a mysql_json /*new column*/) AS SELECT * FROM mysql_json_test;
|
||||||
|
ERROR HY000: 'MYSQL_JSON' is not allowed in this context
|
||||||
|
CREATE TABLE t2 (actual mysql_json /*existing column*/) AS SELECT * FROM mysql_json_test;
|
||||||
|
ERROR HY000: 'MYSQL_JSON' is not allowed in this context
|
||||||
LOCK TABLES mysql_json_test WRITE;
|
LOCK TABLES mysql_json_test WRITE;
|
||||||
ERROR HY000: Table rebuild required. Please do "ALTER TABLE `test.mysql_json_test` FORCE" or dump/reload to fix it!
|
ERROR HY000: Table rebuild required. Please do "ALTER TABLE `test.mysql_json_test` FORCE" or dump/reload to fix it!
|
||||||
alter table mysql_json_test force;
|
alter table mysql_json_test force;
|
||||||
|
@ -169,3 +175,67 @@ Total_Number_of_Tests Succesful_Tests String_is_valid_JSON
|
||||||
drop table tempty;
|
drop table tempty;
|
||||||
drop table mysql_json_test;
|
drop table mysql_json_test;
|
||||||
drop table mysql_json_test_big;
|
drop table mysql_json_test_big;
|
||||||
|
#
|
||||||
|
# MDEV-32790: Output result in show create table
|
||||||
|
# for mysql_json type should be longtext
|
||||||
|
#
|
||||||
|
create table t1(j json);
|
||||||
|
show create table t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`j` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`j`))
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
|
drop table t1;
|
||||||
|
create table t1(j mysql_json);
|
||||||
|
ERROR HY000: 'MYSQL_JSON' is not allowed in this context
|
||||||
|
create table `testjson` (
|
||||||
|
`t` json /* JSON from MySQL 5.7*/ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci;
|
||||||
|
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 'CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CH...' at line 2
|
||||||
|
create table `testjson` (
|
||||||
|
`t` json /* JSON from MySQL 5.7*/ COLLATE utf8mb4_bin NOT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci;
|
||||||
|
show create table testjson;
|
||||||
|
Table Create Table
|
||||||
|
testjson CREATE TABLE `testjson` (
|
||||||
|
`t` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`t`))
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
|
drop table testjson;
|
||||||
|
create table `testjson` (
|
||||||
|
`t` longtext /* JSON from MySQL 5.7 */ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci;
|
||||||
|
show create table testjson;
|
||||||
|
Table Create Table
|
||||||
|
testjson CREATE TABLE `testjson` (
|
||||||
|
`t` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
|
drop table testjson;
|
||||||
|
#
|
||||||
|
# MDEV-32235: mysql_json cannot be used on newly created table
|
||||||
|
#
|
||||||
|
CREATE TABLE t(j mysql_json);
|
||||||
|
ERROR HY000: 'MYSQL_JSON' is not allowed in this context
|
||||||
|
CREATE TABLE IF NOT EXISTS t(j mysql_json);
|
||||||
|
ERROR HY000: 'MYSQL_JSON' is not allowed in this context
|
||||||
|
CREATE OR REPLACE TABLE t(j mysql_json);
|
||||||
|
ERROR HY000: 'MYSQL_JSON' is not allowed in this context
|
||||||
|
CREATE TEMPORARY TABLE t(j mysql_json);
|
||||||
|
ERROR HY000: 'MYSQL_JSON' is not allowed in this context
|
||||||
|
CREATE TABLE t1 (a TEXT);
|
||||||
|
ALTER TABLE t1 MODIFY a mysql_json;
|
||||||
|
ERROR HY000: 'MYSQL_JSON' is not allowed in this context
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE FUNCTION f1() RETURNS mysql_json RETURN NULL;
|
||||||
|
ERROR HY000: 'MYSQL_JSON' is not allowed in this context
|
||||||
|
CREATE FUNCTION f1(a mysql_json) RETURNS INT RETURN 0;
|
||||||
|
ERROR HY000: 'MYSQL_JSON' is not allowed in this context
|
||||||
|
CREATE PROCEDURE p1()
|
||||||
|
BEGIN
|
||||||
|
DECLARE a mysql_json;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
ERROR HY000: 'MYSQL_JSON' is not allowed in this context
|
||||||
|
#
|
||||||
|
# End of 10.5 tests
|
||||||
|
#
|
||||||
|
|
|
@ -51,6 +51,13 @@ show create table mysql_json_test;
|
||||||
--error ER_TABLE_NEEDS_REBUILD
|
--error ER_TABLE_NEEDS_REBUILD
|
||||||
select * from mysql_json_test;
|
select * from mysql_json_test;
|
||||||
|
|
||||||
|
--error ER_TABLE_NEEDS_REBUILD
|
||||||
|
CREATE TABLE t2 AS SELECT * FROM mysql_json_test;
|
||||||
|
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||||
|
CREATE TABLE t2 (a mysql_json /*new column*/) AS SELECT * FROM mysql_json_test;
|
||||||
|
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||||
|
CREATE TABLE t2 (actual mysql_json /*existing column*/) AS SELECT * FROM mysql_json_test;
|
||||||
|
|
||||||
--error ER_TABLE_NEEDS_REBUILD
|
--error ER_TABLE_NEEDS_REBUILD
|
||||||
LOCK TABLES mysql_json_test WRITE;
|
LOCK TABLES mysql_json_test WRITE;
|
||||||
|
|
||||||
|
@ -88,3 +95,69 @@ from mysql_json_test_big;
|
||||||
drop table tempty;
|
drop table tempty;
|
||||||
drop table mysql_json_test;
|
drop table mysql_json_test;
|
||||||
drop table mysql_json_test_big;
|
drop table mysql_json_test_big;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-32790: Output result in show create table
|
||||||
|
--echo # for mysql_json type should be longtext
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
create table t1(j json);
|
||||||
|
show create table t1;
|
||||||
|
drop table t1;
|
||||||
|
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||||
|
create table t1(j mysql_json);
|
||||||
|
# `json` type should not have character set and collation other than utf8mb4_bin
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
create table `testjson` (
|
||||||
|
`t` json /* JSON from MySQL 5.7*/ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci;
|
||||||
|
|
||||||
|
# By removing character set from `json` field query should work and
|
||||||
|
# expand to `longtext` with characterset
|
||||||
|
create table `testjson` (
|
||||||
|
`t` json /* JSON from MySQL 5.7*/ COLLATE utf8mb4_bin NOT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci;
|
||||||
|
show create table testjson;
|
||||||
|
drop table testjson;
|
||||||
|
|
||||||
|
# `longtext` that is alias can have character set
|
||||||
|
create table `testjson` (
|
||||||
|
`t` longtext /* JSON from MySQL 5.7 */ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci;
|
||||||
|
show create table testjson;
|
||||||
|
drop table testjson;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-32235: mysql_json cannot be used on newly created table
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||||
|
CREATE TABLE t(j mysql_json);
|
||||||
|
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||||
|
CREATE TABLE IF NOT EXISTS t(j mysql_json);
|
||||||
|
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||||
|
CREATE OR REPLACE TABLE t(j mysql_json);
|
||||||
|
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||||
|
CREATE TEMPORARY TABLE t(j mysql_json);
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a TEXT);
|
||||||
|
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||||
|
ALTER TABLE t1 MODIFY a mysql_json;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||||
|
CREATE FUNCTION f1() RETURNS mysql_json RETURN NULL;
|
||||||
|
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||||
|
CREATE FUNCTION f1(a mysql_json) RETURNS INT RETURN 0;
|
||||||
|
DELIMITER $$;
|
||||||
|
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||||
|
CREATE PROCEDURE p1()
|
||||||
|
BEGIN
|
||||||
|
DECLARE a mysql_json;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # End of 10.5 tests
|
||||||
|
--echo #
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
--source include/have_log_bin.inc
|
--source include/have_log_bin.inc
|
||||||
--source include/have_binlog_format_row.inc
|
--source include/have_binlog_format_row.inc
|
||||||
--source include/have_normal_bzip.inc
|
--source include/have_normal_zlib.inc
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
--source include/have_log_bin.inc
|
--source include/have_log_bin.inc
|
||||||
--source include/have_binlog_format_statement.inc
|
--source include/have_binlog_format_statement.inc
|
||||||
--source include/have_normal_bzip.inc
|
--source include/have_normal_zlib.inc
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# mysqlbinlog: compressed query event
|
# mysqlbinlog: compressed query event
|
||||||
|
|
|
@ -9309,6 +9309,18 @@ json_detailed(json_extract(trace, '$**.in_to_subquery_conversion'))
|
||||||
set in_predicate_conversion_threshold=@tmp;
|
set in_predicate_conversion_threshold=@tmp;
|
||||||
drop table t0;
|
drop table t0;
|
||||||
#
|
#
|
||||||
|
# MDEV-29298: INSERT ... SELECT Does not produce an optimizer trace
|
||||||
|
#
|
||||||
|
create table t1 (a int, b int);
|
||||||
|
create table t2 (a int, b int);
|
||||||
|
insert into t1 values (1,1), (2,2), (3,3), (4,4), (5,5);
|
||||||
|
set optimizer_trace=1;
|
||||||
|
insert into t2 select * from t1 where a<= b and a>4;
|
||||||
|
select QUERY, LENGTH(trace)>1 from information_schema.optimizer_trace;
|
||||||
|
QUERY LENGTH(trace)>1
|
||||||
|
insert into t2 select * from t1 where a<= b and a>4 1
|
||||||
|
drop table t1, t2;
|
||||||
|
#
|
||||||
# End of 10.5 tests
|
# End of 10.5 tests
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
|
@ -869,6 +869,20 @@ set in_predicate_conversion_threshold=@tmp;
|
||||||
drop table t0;
|
drop table t0;
|
||||||
--enable_view_protocol
|
--enable_view_protocol
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-29298: INSERT ... SELECT Does not produce an optimizer trace
|
||||||
|
--echo #
|
||||||
|
create table t1 (a int, b int);
|
||||||
|
create table t2 (a int, b int);
|
||||||
|
insert into t1 values (1,1), (2,2), (3,3), (4,4), (5,5);
|
||||||
|
set optimizer_trace=1;
|
||||||
|
|
||||||
|
insert into t2 select * from t1 where a<= b and a>4;
|
||||||
|
|
||||||
|
select QUERY, LENGTH(trace)>1 from information_schema.optimizer_trace;
|
||||||
|
|
||||||
|
drop table t1, t2;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.5 tests
|
--echo # End of 10.5 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
|
12
mysql-test/suite/binlog/r/binlog_gis_user_var_stm.result
Normal file
12
mysql-test/suite/binlog/r/binlog_gis_user_var_stm.result
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
SET @g0= POINT(1,1);
|
||||||
|
SET @g1= Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)));
|
||||||
|
CREATE TABLE t1 AS SELECT @g0 AS g0, @g1 AS g1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
include/show_binlog_events.inc
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Gtid # # GTID #-#-#
|
||||||
|
master-bin.000001 # User var # # @`g0`=/*point*/_binary X'000000000101000000000000000000F03F000000000000F03F' COLLATE binary
|
||||||
|
master-bin.000001 # User var # # @`g1`=/*polygon*/_binary X'0000000001030000000100000004000000000000000000000000000000000000000000000000003E4000000000000000000000000000003E400000000000003E4000000000000000000000000000000000' COLLATE binary
|
||||||
|
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 AS SELECT @g0 AS g0, @g1 AS g1
|
||||||
|
master-bin.000001 # Gtid # # GTID #-#-#
|
||||||
|
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
|
15
mysql-test/suite/binlog/t/binlog_gis_user_var_stm.test
Normal file
15
mysql-test/suite/binlog/t/binlog_gis_user_var_stm.test
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
--source include/not_embedded.inc
|
||||||
|
--source include/have_binlog_format_statement.inc
|
||||||
|
--source include/have_geometry.inc
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
reset master; # get rid of previous tests binlog
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
SET @g0= POINT(1,1);
|
||||||
|
SET @g1= Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)));
|
||||||
|
CREATE TABLE t1 AS SELECT @g0 AS g0, @g1 AS g1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--let $binlog_file = LAST
|
||||||
|
source include/show_binlog_events.inc;
|
|
@ -1,6 +1,6 @@
|
||||||
--source include/have_innodb.inc
|
--source include/have_innodb.inc
|
||||||
--source include/have_csv.inc
|
--source include/have_csv.inc
|
||||||
--source include/have_normal_bzip.inc
|
--source include/have_normal_zlib.inc
|
||||||
|
|
||||||
SET sql_mode=ORACLE;
|
SET sql_mode=ORACLE;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
# MDEV-32242 innodb.doublewrite test case always is skipped
|
# MDEV-32242 innodb.doublewrite test case always is skipped
|
||||||
#
|
#
|
||||||
create table t1 (f1 int primary key, f2 blob) engine=innodb stats_persistent=0;
|
create table t1 (f1 int primary key, f2 blob) stats_persistent=0, engine=innodb;
|
||||||
start transaction;
|
start transaction;
|
||||||
insert into t1 values(1, repeat('#',12));
|
insert into t1 values(1, repeat('#',12));
|
||||||
insert into t1 values(2, repeat('+',12));
|
insert into t1 values(2, repeat('+',12));
|
||||||
|
@ -19,6 +19,7 @@ XA PREPARE 'x';
|
||||||
disconnect dml;
|
disconnect dml;
|
||||||
connection default;
|
connection default;
|
||||||
flush table t1 for export;
|
flush table t1 for export;
|
||||||
|
# Kill the server
|
||||||
# restart
|
# restart
|
||||||
FOUND 1 /InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile/ in mysqld.1.err
|
FOUND 1 /InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile/ in mysqld.1.err
|
||||||
FOUND 1 /InnoDB: Recovered page \[page id: space=[1-9][0-9]*, page number=3\]/ in mysqld.1.err
|
FOUND 1 /InnoDB: Recovered page \[page id: space=[1-9][0-9]*, page number=3\]/ in mysqld.1.err
|
||||||
|
@ -33,5 +34,27 @@ f1 f2
|
||||||
3 ////////////
|
3 ////////////
|
||||||
4 ------------
|
4 ------------
|
||||||
5 ............
|
5 ............
|
||||||
|
connect dml,localhost,root,,;
|
||||||
|
XA START 'x';
|
||||||
|
insert into t1 values (6, repeat('%', @@innodb_page_size/2));
|
||||||
|
XA END 'x';
|
||||||
|
XA PREPARE 'x';
|
||||||
|
disconnect dml;
|
||||||
|
connection default;
|
||||||
|
flush table t1 for export;
|
||||||
|
# Kill the server
|
||||||
|
# restart
|
||||||
|
FOUND 1 /InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile/ in mysqld.1.err
|
||||||
|
XA ROLLBACK 'x';
|
||||||
|
check table t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check status OK
|
||||||
|
select f1, f2 from t1;
|
||||||
|
f1 f2
|
||||||
|
1 ############
|
||||||
|
2 ++++++++++++
|
||||||
|
3 ////////////
|
||||||
|
4 ------------
|
||||||
|
5 ............
|
||||||
drop table t1;
|
drop table t1;
|
||||||
# End of 10.5 tests
|
# End of 10.5 tests
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:");
|
||||||
SET GLOBAL innodb_file_per_table=ON;
|
SET GLOBAL innodb_file_per_table=ON;
|
||||||
FLUSH TABLES;
|
FLUSH TABLES;
|
||||||
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
|
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||||
|
|
|
@ -17,6 +17,7 @@ call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile");
|
||||||
call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: ");
|
call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: ");
|
||||||
call mtr.add_suppression("InnoDB: Inconsistent tablespace ID in .*t1\\.ibd");
|
call mtr.add_suppression("InnoDB: Inconsistent tablespace ID in .*t1\\.ibd");
|
||||||
call mtr.add_suppression("\\[Warning\\] Found 1 prepared XA transactions");
|
call mtr.add_suppression("\\[Warning\\] Found 1 prepared XA transactions");
|
||||||
|
call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:");
|
||||||
--enable_query_log
|
--enable_query_log
|
||||||
|
|
||||||
let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
|
let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
|
||||||
|
@ -24,7 +25,7 @@ let MYSQLD_DATADIR=`select @@datadir`;
|
||||||
let ALGO=`select @@innodb_checksum_algorithm`;
|
let ALGO=`select @@innodb_checksum_algorithm`;
|
||||||
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err;
|
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err;
|
||||||
|
|
||||||
create table t1 (f1 int primary key, f2 blob) engine=innodb stats_persistent=0;
|
create table t1 (f1 int primary key, f2 blob) stats_persistent=0, engine=innodb;
|
||||||
|
|
||||||
start transaction;
|
start transaction;
|
||||||
insert into t1 values(1, repeat('#',12));
|
insert into t1 values(1, repeat('#',12));
|
||||||
|
@ -38,7 +39,7 @@ commit work;
|
||||||
SET GLOBAL innodb_fast_shutdown = 0;
|
SET GLOBAL innodb_fast_shutdown = 0;
|
||||||
let $shutdown_timeout=;
|
let $shutdown_timeout=;
|
||||||
--source include/restart_mysqld.inc
|
--source include/restart_mysqld.inc
|
||||||
|
--source ../include/no_checkpoint_start.inc
|
||||||
connect (dml,localhost,root,,);
|
connect (dml,localhost,root,,);
|
||||||
XA START 'x';
|
XA START 'x';
|
||||||
insert into t1 values (6, repeat('%', @@innodb_page_size/2));
|
insert into t1 values (6, repeat('%', @@innodb_page_size/2));
|
||||||
|
@ -50,8 +51,8 @@ connection default;
|
||||||
flush table t1 for export;
|
flush table t1 for export;
|
||||||
|
|
||||||
let $restart_parameters=;
|
let $restart_parameters=;
|
||||||
let $shutdown_timeout=0;
|
--let CLEANUP_IF_CHECKPOINT=drop table t1, unexpected_checkpoint;
|
||||||
--source include/shutdown_mysqld.inc
|
--source ../include/no_checkpoint_end.inc
|
||||||
|
|
||||||
perl;
|
perl;
|
||||||
use IO::Handle;
|
use IO::Handle;
|
||||||
|
@ -119,6 +120,35 @@ let SEARCH_PATTERN=InnoDB: Recovered page \[page id: space=[1-9][0-9]*, page num
|
||||||
XA ROLLBACK 'x';
|
XA ROLLBACK 'x';
|
||||||
check table t1;
|
check table t1;
|
||||||
select f1, f2 from t1;
|
select f1, f2 from t1;
|
||||||
|
|
||||||
|
--source ../include/no_checkpoint_start.inc
|
||||||
|
connect (dml,localhost,root,,);
|
||||||
|
XA START 'x';
|
||||||
|
insert into t1 values (6, repeat('%', @@innodb_page_size/2));
|
||||||
|
XA END 'x';
|
||||||
|
XA PREPARE 'x';
|
||||||
|
disconnect dml;
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
flush table t1 for export;
|
||||||
|
|
||||||
|
let $restart_parameters=;
|
||||||
|
--source ../include/no_checkpoint_end.inc
|
||||||
|
|
||||||
|
# Zero out the first page in file and try to recover from dblwr
|
||||||
|
perl;
|
||||||
|
use IO::Handle;
|
||||||
|
open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}test/t1.ibd") or die;
|
||||||
|
syswrite(FILE, chr(0) x $ENV{INNODB_PAGE_SIZE});
|
||||||
|
close FILE;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
--source include/start_mysqld.inc
|
||||||
|
let SEARCH_PATTERN=InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile;
|
||||||
|
--source include/search_pattern_in_file.inc
|
||||||
|
XA ROLLBACK 'x';
|
||||||
|
check table t1;
|
||||||
|
select f1, f2 from t1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
--echo # End of 10.5 tests
|
--echo # End of 10.5 tests
|
||||||
|
|
|
@ -17,6 +17,7 @@ call mtr.add_suppression("Plugin 'InnoDB' (init function returned error|registra
|
||||||
call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile");
|
call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile");
|
||||||
call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: ");
|
call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: ");
|
||||||
call mtr.add_suppression("InnoDB: Inconsistent tablespace ID in .*t1\\.ibd");
|
call mtr.add_suppression("InnoDB: Inconsistent tablespace ID in .*t1\\.ibd");
|
||||||
|
call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:");
|
||||||
--enable_query_log
|
--enable_query_log
|
||||||
|
|
||||||
let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
|
let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
# Embedded server does not support crashing
|
# Embedded server does not support crashing
|
||||||
--source include/not_embedded.inc
|
--source include/not_embedded.inc
|
||||||
|
|
||||||
|
call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:");
|
||||||
|
|
||||||
SET GLOBAL innodb_file_per_table=ON;
|
SET GLOBAL innodb_file_per_table=ON;
|
||||||
FLUSH TABLES;
|
FLUSH TABLES;
|
||||||
|
|
||||||
|
@ -174,6 +176,7 @@ call mtr.add_suppression("InnoDB: Table test/u[123] in the InnoDB data dictionar
|
||||||
call mtr.add_suppression("InnoDB: Cannot replay rename of tablespace.*");
|
call mtr.add_suppression("InnoDB: Cannot replay rename of tablespace.*");
|
||||||
call mtr.add_suppression("InnoDB: Attempted to open a previously opened tablespace");
|
call mtr.add_suppression("InnoDB: Attempted to open a previously opened tablespace");
|
||||||
call mtr.add_suppression("InnoDB: Recovery cannot access file");
|
call mtr.add_suppression("InnoDB: Recovery cannot access file");
|
||||||
|
call mtr.add_suppression("InnoDB: Cannot read first page in datafile:");
|
||||||
FLUSH TABLES;
|
FLUSH TABLES;
|
||||||
--enable_query_log
|
--enable_query_log
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
--source include/have_innodb.inc
|
--source include/have_innodb.inc
|
||||||
--source include/have_sequence.inc
|
--source include/have_sequence.inc
|
||||||
--source include/innodb_page_size_small.inc
|
--source include/innodb_page_size_small.inc
|
||||||
--source include/have_normal_bzip.inc
|
--source include/have_normal_zlib.inc
|
||||||
|
|
||||||
call mtr.add_suppression("InnoDB: Cannot add field .* in table .* because after adding it, the row size is .* which is greater than maximum allowed size (.*) for a record on index leaf page.");
|
call mtr.add_suppression("InnoDB: Cannot add field .* in table .* because after adding it, the row size is .* which is greater than maximum allowed size (.*) for a record on index leaf page.");
|
||||||
|
|
||||||
|
|
21
mysql-test/suite/rpl/r/rpl_gis_user_var.result
Normal file
21
mysql-test/suite/rpl/r/rpl_gis_user_var.result
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
include/master-slave.inc
|
||||||
|
[connection master]
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
connection master;
|
||||||
|
SET @p=POINT(1,1);
|
||||||
|
CREATE TABLE t1 AS SELECT @p AS p;
|
||||||
|
connection slave;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`p` point DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
|
SELECT ST_AsWKT(p) FROM t1;
|
||||||
|
ST_AsWKT(p)
|
||||||
|
POINT(1 1)
|
||||||
|
connection master;
|
||||||
|
DROP TABLE t1;
|
||||||
|
connection slave;
|
||||||
|
include/rpl_end.inc
|
18
mysql-test/suite/rpl/t/rpl_gis_user_var.test
Normal file
18
mysql-test/suite/rpl/t/rpl_gis_user_var.test
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
--source include/have_geometry.inc
|
||||||
|
--source include/master-slave.inc
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo #
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
SET @p=POINT(1,1);
|
||||||
|
CREATE TABLE t1 AS SELECT @p AS p;
|
||||||
|
sync_slave_with_master;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT ST_AsWKT(p) FROM t1;
|
||||||
|
connection master;
|
||||||
|
DROP TABLE t1;
|
||||||
|
sync_slave_with_master;
|
||||||
|
|
||||||
|
--source include/rpl_end.inc
|
|
@ -37,6 +37,11 @@ public:
|
||||||
Field *make_table_field(MEM_ROOT *, const LEX_CSTRING *,
|
Field *make_table_field(MEM_ROOT *, const LEX_CSTRING *,
|
||||||
const Record_addr &, const Type_all_attributes &,
|
const Record_addr &, const Type_all_attributes &,
|
||||||
TABLE_SHARE *) const override;
|
TABLE_SHARE *) const override;
|
||||||
|
bool Column_definition_fix_attributes(Column_definition *c) const override
|
||||||
|
{
|
||||||
|
my_error(ER_NOT_ALLOWED_IN_THIS_CONTEXT, MYF(0), "MYSQL_JSON");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
void Column_definition_reuse_fix_attributes(THD *thd,
|
void Column_definition_reuse_fix_attributes(THD *thd,
|
||||||
Column_definition *def,
|
Column_definition *def,
|
||||||
const Field *field) const override;
|
const Field *field) const override;
|
||||||
|
@ -62,7 +67,7 @@ public:
|
||||||
bool parse_mysql(String *dest, const char *data, size_t length) const;
|
bool parse_mysql(String *dest, const char *data, size_t length) const;
|
||||||
bool send(Protocol *protocol) { return Field::send(protocol); }
|
bool send(Protocol *protocol) { return Field::send(protocol); }
|
||||||
void sql_type(String &s) const
|
void sql_type(String &s) const
|
||||||
{ s.set_ascii(STRING_WITH_LEN("json /* MySQL 5.7 */")); }
|
{ s.set_ascii(STRING_WITH_LEN("mysql_json /* JSON from MySQL 5.7 */")); }
|
||||||
/* this will make ALTER TABLE to consider it different from built-in field */
|
/* this will make ALTER TABLE to consider it different from built-in field */
|
||||||
Compression_method *compression_method() const { return (Compression_method*)1; }
|
Compression_method *compression_method() const { return (Compression_method*)1; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -79,9 +79,9 @@ static int user_variables_fill(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||||
else
|
else
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
const LEX_CSTRING *tmp= var->unsigned_flag ?
|
const LEX_CSTRING *tmp= var->type_handler()->is_unsigned() ?
|
||||||
&unsigned_result_types[var->type] :
|
&unsigned_result_types[var->type_handler()->result_type()] :
|
||||||
&result_types[var->type];
|
&result_types[var->type_handler()->result_type()];
|
||||||
field[2]->store(tmp->str, tmp->length, system_charset_info);
|
field[2]->store(tmp->str, tmp->length, system_charset_info);
|
||||||
|
|
||||||
if (var->charset())
|
if (var->charset())
|
||||||
|
|
|
@ -40,7 +40,8 @@ static bool debug_decrement_counter(const LEX_CSTRING *name)
|
||||||
THD *thd= current_thd;
|
THD *thd= current_thd;
|
||||||
user_var_entry *entry= (user_var_entry*)
|
user_var_entry *entry= (user_var_entry*)
|
||||||
my_hash_search(&thd->user_vars, (uchar*) name->str, name->length);
|
my_hash_search(&thd->user_vars, (uchar*) name->str, name->length);
|
||||||
if (!entry || entry->type != INT_RESULT || ! entry->value)
|
if (!entry || !entry->value ||
|
||||||
|
entry->type_handler()->result_type() != INT_RESULT)
|
||||||
return 0;
|
return 0;
|
||||||
(*(ulonglong*) entry->value)= (*(ulonglong*) entry->value)-1;
|
(*(ulonglong*) entry->value)= (*(ulonglong*) entry->value)-1;
|
||||||
return !*(ulonglong*) entry->value;
|
return !*(ulonglong*) entry->value;
|
||||||
|
|
|
@ -4645,7 +4645,6 @@ user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name,
|
||||||
entry->length=0;
|
entry->length=0;
|
||||||
entry->update_query_id=0;
|
entry->update_query_id=0;
|
||||||
entry->set_charset(NULL);
|
entry->set_charset(NULL);
|
||||||
entry->unsigned_flag= 0;
|
|
||||||
/*
|
/*
|
||||||
If we are here, we were called from a SET or a query which sets a
|
If we are here, we were called from a SET or a query which sets a
|
||||||
variable. Imagine it is this:
|
variable. Imagine it is this:
|
||||||
|
@ -4657,7 +4656,7 @@ user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name,
|
||||||
by Item_func_get_user_var (because that's not necessary).
|
by Item_func_get_user_var (because that's not necessary).
|
||||||
*/
|
*/
|
||||||
entry->used_query_id=current_thd->query_id;
|
entry->used_query_id=current_thd->query_id;
|
||||||
entry->type=STRING_RESULT;
|
entry->set_handler(&type_handler_long_blob);
|
||||||
memcpy((char*) entry->name.str, name->str, name->length+1);
|
memcpy((char*) entry->name.str, name->str, name->length+1);
|
||||||
if (my_hash_insert(hash,(uchar*) entry))
|
if (my_hash_insert(hash,(uchar*) entry))
|
||||||
{
|
{
|
||||||
|
@ -4733,9 +4732,12 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
|
||||||
switch (args[0]->result_type()) {
|
switch (args[0]->result_type()) {
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
case TIME_RESULT:
|
case TIME_RESULT:
|
||||||
set_handler(type_handler_long_blob.
|
if (args[0]->field_type() == MYSQL_TYPE_GEOMETRY)
|
||||||
type_handler_adjusted_to_max_octet_length(max_length,
|
set_handler(args[0]->type_handler());
|
||||||
collation.collation));
|
else
|
||||||
|
set_handler(type_handler_long_blob.
|
||||||
|
type_handler_adjusted_to_max_octet_length(max_length,
|
||||||
|
collation.collation));
|
||||||
break;
|
break;
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
set_handler(&type_handler_double);
|
set_handler(&type_handler_double);
|
||||||
|
@ -4860,9 +4862,9 @@ bool Item_func_set_user_var::register_field_in_bitmap(void *arg)
|
||||||
|
|
||||||
bool
|
bool
|
||||||
update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
|
update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
|
||||||
Item_result type, CHARSET_INFO *cs,
|
const Type_handler *th, CHARSET_INFO *cs)
|
||||||
bool unsigned_arg)
|
|
||||||
{
|
{
|
||||||
|
entry->set_handler(th);
|
||||||
if (set_null)
|
if (set_null)
|
||||||
{
|
{
|
||||||
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
|
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
|
||||||
|
@ -4873,7 +4875,7 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (type == STRING_RESULT)
|
if (th->result_type() == STRING_RESULT)
|
||||||
length++; // Store strings with end \0
|
length++; // Store strings with end \0
|
||||||
if (length <= extra_size)
|
if (length <= extra_size)
|
||||||
{
|
{
|
||||||
|
@ -4902,20 +4904,18 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type == STRING_RESULT)
|
if (th->result_type() == STRING_RESULT)
|
||||||
{
|
{
|
||||||
length--; // Fix length change above
|
length--; // Fix length change above
|
||||||
entry->value[length]= 0; // Store end \0
|
entry->value[length]= 0; // Store end \0
|
||||||
}
|
}
|
||||||
if (length)
|
if (length)
|
||||||
memmove(entry->value, ptr, length);
|
memmove(entry->value, ptr, length);
|
||||||
if (type == DECIMAL_RESULT)
|
if (th->result_type() == DECIMAL_RESULT)
|
||||||
((my_decimal*)entry->value)->fix_buffer_pointer();
|
((my_decimal*)entry->value)->fix_buffer_pointer();
|
||||||
entry->length= length;
|
entry->length= length;
|
||||||
entry->set_charset(cs);
|
entry->set_charset(cs);
|
||||||
entry->unsigned_flag= unsigned_arg;
|
|
||||||
}
|
}
|
||||||
entry->type=type;
|
|
||||||
#ifdef USER_VAR_TRACKING
|
#ifdef USER_VAR_TRACKING
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
THD *thd= current_thd;
|
THD *thd= current_thd;
|
||||||
|
@ -4928,9 +4928,8 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Item_func_set_user_var::update_hash(void *ptr, size_t length,
|
Item_func_set_user_var::update_hash(void *ptr, size_t length,
|
||||||
Item_result res_type,
|
const Type_handler *th,
|
||||||
CHARSET_INFO *cs,
|
CHARSET_INFO *cs)
|
||||||
bool unsigned_arg)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
If we set a variable explicitly to NULL then keep the old
|
If we set a variable explicitly to NULL then keep the old
|
||||||
|
@ -4944,9 +4943,8 @@ Item_func_set_user_var::update_hash(void *ptr, size_t length,
|
||||||
else
|
else
|
||||||
null_value= args[0]->null_value;
|
null_value= args[0]->null_value;
|
||||||
if (null_value && null_item)
|
if (null_value && null_item)
|
||||||
res_type= m_var_entry->type; // Don't change type of item
|
th= m_var_entry->type_handler(); // Don't change type of item
|
||||||
if (::update_hash(m_var_entry, null_value,
|
if (::update_hash(m_var_entry, null_value, ptr, length, th, cs))
|
||||||
ptr, length, res_type, cs, unsigned_arg))
|
|
||||||
{
|
{
|
||||||
null_value= 1;
|
null_value= 1;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -4962,7 +4960,7 @@ double user_var_entry::val_real(bool *null_value)
|
||||||
if ((*null_value= (value == 0)))
|
if ((*null_value= (value == 0)))
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|
||||||
switch (type) {
|
switch (type_handler()->result_type()) {
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
return *(double*) value;
|
return *(double*) value;
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
|
@ -4987,7 +4985,7 @@ longlong user_var_entry::val_int(bool *null_value) const
|
||||||
if ((*null_value= (value == 0)))
|
if ((*null_value= (value == 0)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (type) {
|
switch (type_handler()->result_type()) {
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
return (longlong) *(double*) value;
|
return (longlong) *(double*) value;
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
|
@ -5016,12 +5014,12 @@ String *user_var_entry::val_str(bool *null_value, String *str,
|
||||||
if ((*null_value= (value == 0)))
|
if ((*null_value= (value == 0)))
|
||||||
return (String*) 0;
|
return (String*) 0;
|
||||||
|
|
||||||
switch (type) {
|
switch (type_handler()->result_type()) {
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
str->set_real(*(double*) value, decimals, charset());
|
str->set_real(*(double*) value, decimals, charset());
|
||||||
break;
|
break;
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
if (!unsigned_flag)
|
if (!type_handler()->is_unsigned())
|
||||||
str->set(*(longlong*) value, charset());
|
str->set(*(longlong*) value, charset());
|
||||||
else
|
else
|
||||||
str->set(*(ulonglong*) value, charset());
|
str->set(*(ulonglong*) value, charset());
|
||||||
|
@ -5048,7 +5046,7 @@ my_decimal *user_var_entry::val_decimal(bool *null_value, my_decimal *val)
|
||||||
if ((*null_value= (value == 0)))
|
if ((*null_value= (value == 0)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (type) {
|
switch (type_handler()->result_type()) {
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
double2my_decimal(E_DEC_FATAL_ERROR, *(double*) value, val);
|
double2my_decimal(E_DEC_FATAL_ERROR, *(double*) value, val);
|
||||||
break;
|
break;
|
||||||
|
@ -5187,33 +5185,37 @@ Item_func_set_user_var::update()
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
{
|
{
|
||||||
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
|
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
|
||||||
REAL_RESULT, &my_charset_numeric, 0);
|
&type_handler_double, &my_charset_numeric);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
{
|
{
|
||||||
res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
|
res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
|
||||||
INT_RESULT, &my_charset_numeric, unsigned_flag);
|
unsigned_flag ? (Type_handler *) &type_handler_ulonglong :
|
||||||
|
(Type_handler *) &type_handler_slonglong,
|
||||||
|
&my_charset_numeric);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
{
|
{
|
||||||
if (!save_result.vstr) // Null value
|
if (!save_result.vstr) // Null value
|
||||||
res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, 0);
|
res= update_hash((void*) 0, 0, &type_handler_long_blob, &my_charset_bin);
|
||||||
else
|
else
|
||||||
res= update_hash((void*) save_result.vstr->ptr(),
|
res= update_hash((void*) save_result.vstr->ptr(),
|
||||||
save_result.vstr->length(), STRING_RESULT,
|
save_result.vstr->length(),
|
||||||
save_result.vstr->charset(), 0);
|
field_type() == MYSQL_TYPE_GEOMETRY ?
|
||||||
|
type_handler() : &type_handler_long_blob,
|
||||||
|
save_result.vstr->charset());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
{
|
{
|
||||||
if (!save_result.vdec) // Null value
|
if (!save_result.vdec) // Null value
|
||||||
res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin, 0);
|
res= update_hash((void*) 0, 0, &type_handler_newdecimal, &my_charset_bin);
|
||||||
else
|
else
|
||||||
res= update_hash((void*) save_result.vdec,
|
res= update_hash((void*) save_result.vdec,
|
||||||
sizeof(my_decimal), DECIMAL_RESULT,
|
sizeof(my_decimal), &type_handler_newdecimal,
|
||||||
&my_charset_numeric, 0);
|
&my_charset_numeric);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ROW_RESULT:
|
case ROW_RESULT:
|
||||||
|
@ -5605,9 +5607,8 @@ get_var_with_binlog(THD *thd, enum_sql_command sql_command,
|
||||||
user_var_event->value= (char*) user_var_event +
|
user_var_event->value= (char*) user_var_event +
|
||||||
ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
|
ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
|
||||||
user_var_event->user_var_event= var_entry;
|
user_var_event->user_var_event= var_entry;
|
||||||
user_var_event->type= var_entry->type;
|
user_var_event->th= var_entry->type_handler();
|
||||||
user_var_event->charset_number= var_entry->charset()->number;
|
user_var_event->charset_number= var_entry->charset()->number;
|
||||||
user_var_event->unsigned_flag= var_entry->unsigned_flag;
|
|
||||||
if (!var_entry->value)
|
if (!var_entry->value)
|
||||||
{
|
{
|
||||||
/* NULL value*/
|
/* NULL value*/
|
||||||
|
@ -5650,9 +5651,9 @@ bool Item_func_get_user_var::fix_length_and_dec()
|
||||||
*/
|
*/
|
||||||
if (likely(!error && m_var_entry))
|
if (likely(!error && m_var_entry))
|
||||||
{
|
{
|
||||||
unsigned_flag= m_var_entry->unsigned_flag;
|
unsigned_flag= m_var_entry->type_handler()->is_unsigned();
|
||||||
max_length= (uint32)m_var_entry->length;
|
max_length= (uint32)m_var_entry->length;
|
||||||
switch (m_var_entry->type) {
|
switch (m_var_entry->type_handler()->result_type()) {
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
collation.set(&my_charset_numeric, DERIVATION_NUMERIC);
|
collation.set(&my_charset_numeric, DERIVATION_NUMERIC);
|
||||||
fix_char_length(DBL_DIG + 8);
|
fix_char_length(DBL_DIG + 8);
|
||||||
|
@ -5671,6 +5672,8 @@ bool Item_func_get_user_var::fix_length_and_dec()
|
||||||
collation.set(m_var_entry->charset(), DERIVATION_IMPLICIT);
|
collation.set(m_var_entry->charset(), DERIVATION_IMPLICIT);
|
||||||
max_length= MAX_BLOB_WIDTH - 1;
|
max_length= MAX_BLOB_WIDTH - 1;
|
||||||
set_handler(&type_handler_long_blob);
|
set_handler(&type_handler_long_blob);
|
||||||
|
if (m_var_entry->type_handler()->field_type() == MYSQL_TYPE_GEOMETRY)
|
||||||
|
set_handler(m_var_entry->type_handler());
|
||||||
break;
|
break;
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
collation.set(&my_charset_numeric, DERIVATION_NUMERIC);
|
collation.set(&my_charset_numeric, DERIVATION_NUMERIC);
|
||||||
|
@ -5743,7 +5746,7 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
|
||||||
DBUG_ASSERT(thd->lex->exchange);
|
DBUG_ASSERT(thd->lex->exchange);
|
||||||
if (!(entry= get_variable(&thd->user_vars, &org_name, 1)))
|
if (!(entry= get_variable(&thd->user_vars, &org_name, 1)))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
entry->type= STRING_RESULT;
|
entry->set_handler(&type_handler_long_blob);
|
||||||
/*
|
/*
|
||||||
Let us set the same collation which is used for loading
|
Let us set the same collation which is used for loading
|
||||||
of fields in LOAD DATA INFILE.
|
of fields in LOAD DATA INFILE.
|
||||||
|
@ -5759,15 +5762,14 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
|
||||||
|
|
||||||
void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
|
void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
|
||||||
{
|
{
|
||||||
::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs, 0 /* unsigned_arg */);
|
::update_hash(entry, TRUE, 0, 0, &type_handler_long_blob, cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_user_var_as_out_param::set_value(const char *str, uint length,
|
void Item_user_var_as_out_param::set_value(const char *str, uint length,
|
||||||
CHARSET_INFO* cs)
|
CHARSET_INFO* cs)
|
||||||
{
|
{
|
||||||
::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
|
::update_hash(entry, FALSE, (void*)str, length, &type_handler_long_blob, cs);
|
||||||
0 /* unsigned_arg */);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3447,8 +3447,8 @@ public:
|
||||||
String *str_result(String *str) override;
|
String *str_result(String *str) override;
|
||||||
my_decimal *val_decimal_result(my_decimal *) override;
|
my_decimal *val_decimal_result(my_decimal *) override;
|
||||||
bool is_null_result() override;
|
bool is_null_result() override;
|
||||||
bool update_hash(void *ptr, size_t length, enum Item_result type,
|
bool update_hash(void *ptr, size_t length, const Type_handler *th,
|
||||||
CHARSET_INFO *cs, bool unsigned_arg);
|
CHARSET_INFO *cs);
|
||||||
bool send(Protocol *protocol, st_value *buffer) override;
|
bool send(Protocol *protocol, st_value *buffer) override;
|
||||||
void make_send_field(THD *thd, Send_field *tmp_field) override;
|
void make_send_field(THD *thd, Send_field *tmp_field) override;
|
||||||
bool check(bool use_result_field);
|
bool check(bool use_result_field);
|
||||||
|
@ -4289,7 +4289,6 @@ double my_double_round(double value, longlong dec, bool dec_unsigned,
|
||||||
extern bool volatile mqh_used;
|
extern bool volatile mqh_used;
|
||||||
|
|
||||||
bool update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
|
bool update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
|
||||||
Item_result type, CHARSET_INFO *cs,
|
const Type_handler *th, CHARSET_INFO *cs);
|
||||||
bool unsigned_arg);
|
|
||||||
|
|
||||||
#endif /* ITEM_FUNC_INCLUDED */
|
#endif /* ITEM_FUNC_INCLUDED */
|
||||||
|
|
10
sql/log.cc
10
sql/log.cc
|
@ -6830,18 +6830,12 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
|
||||||
BINLOG_USER_VAR_EVENT *user_var_event;
|
BINLOG_USER_VAR_EVENT *user_var_event;
|
||||||
get_dynamic(&thd->user_var_events,(uchar*) &user_var_event, i);
|
get_dynamic(&thd->user_var_events,(uchar*) &user_var_event, i);
|
||||||
|
|
||||||
/* setting flags for user var log event */
|
|
||||||
uchar flags= User_var_log_event::UNDEF_F;
|
|
||||||
if (user_var_event->unsigned_flag)
|
|
||||||
flags|= User_var_log_event::UNSIGNED_F;
|
|
||||||
|
|
||||||
User_var_log_event e(thd, user_var_event->user_var_event->name.str,
|
User_var_log_event e(thd, user_var_event->user_var_event->name.str,
|
||||||
user_var_event->user_var_event->name.length,
|
user_var_event->user_var_event->name.length,
|
||||||
user_var_event->value,
|
user_var_event->value,
|
||||||
user_var_event->length,
|
user_var_event->length,
|
||||||
user_var_event->type,
|
user_var_event->th->user_var_log_event_data_type(
|
||||||
user_var_event->charset_number,
|
user_var_event->charset_number),
|
||||||
flags,
|
|
||||||
using_trans,
|
using_trans,
|
||||||
direct);
|
direct);
|
||||||
if (write_event(&e, cache_data, file))
|
if (write_event(&e, cache_data, file))
|
||||||
|
|
|
@ -2907,6 +2907,41 @@ XA_prepare_log_event(const uchar *buf,
|
||||||
User_var_log_event methods
|
User_var_log_event methods
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
bool Log_event_data_type::unpack_optional_attributes(const char *pos,
|
||||||
|
const char *end)
|
||||||
|
|
||||||
|
{
|
||||||
|
for ( ; pos < end; )
|
||||||
|
{
|
||||||
|
switch (*pos) {
|
||||||
|
case CHUNK_SIGNED:
|
||||||
|
m_is_unsigned= false;
|
||||||
|
pos++;
|
||||||
|
continue;
|
||||||
|
case CHUNK_UNSIGNED:
|
||||||
|
m_is_unsigned= true;
|
||||||
|
pos++;
|
||||||
|
continue;
|
||||||
|
case CHUNK_DATA_TYPE_NAME:
|
||||||
|
{
|
||||||
|
pos++;
|
||||||
|
if (pos >= end)
|
||||||
|
return true;
|
||||||
|
uint length= (uchar) *pos++;
|
||||||
|
if (pos + length > end)
|
||||||
|
return true;
|
||||||
|
m_data_type_name= {pos, length};
|
||||||
|
pos+= length;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break; // Unknown chunk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
User_var_log_event::
|
User_var_log_event::
|
||||||
User_var_log_event(const uchar *buf, uint event_len,
|
User_var_log_event(const uchar *buf, uint event_len,
|
||||||
const Format_description_log_event* description_event)
|
const Format_description_log_event* description_event)
|
||||||
|
@ -2916,7 +2951,8 @@ User_var_log_event(const uchar *buf, uint event_len,
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
bool error= false;
|
bool error= false;
|
||||||
const uchar *buf_start= buf, *buf_end= buf + event_len;
|
const uchar *const buf_start= buf;
|
||||||
|
const char *buf_end= reinterpret_cast<const char*>(buf) + event_len;
|
||||||
|
|
||||||
/* The Post-Header is empty. The Variable Data part begins immediately. */
|
/* The Post-Header is empty. The Variable Data part begins immediately. */
|
||||||
buf+= description_event->common_header_len +
|
buf+= description_event->common_header_len +
|
||||||
|
@ -2944,11 +2980,8 @@ User_var_log_event(const uchar *buf, uint event_len,
|
||||||
|
|
||||||
buf+= UV_NAME_LEN_SIZE + name_len;
|
buf+= UV_NAME_LEN_SIZE + name_len;
|
||||||
is_null= (bool) *buf;
|
is_null= (bool) *buf;
|
||||||
flags= User_var_log_event::UNDEF_F; // defaults to UNDEF_F
|
|
||||||
if (is_null)
|
if (is_null)
|
||||||
{
|
{
|
||||||
type= STRING_RESULT;
|
|
||||||
charset_number= my_charset_bin.number;
|
|
||||||
val_len= 0;
|
val_len= 0;
|
||||||
val= 0;
|
val= 0;
|
||||||
}
|
}
|
||||||
|
@ -2963,8 +2996,8 @@ User_var_log_event(const uchar *buf, uint event_len,
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
type= (Item_result) buf[UV_VAL_IS_NULL];
|
m_type= (Item_result) buf[UV_VAL_IS_NULL];
|
||||||
charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE);
|
m_charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE);
|
||||||
val_len= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
|
val_len= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
|
||||||
UV_CHARSET_NUMBER_SIZE);
|
UV_CHARSET_NUMBER_SIZE);
|
||||||
|
|
||||||
|
@ -2977,20 +3010,14 @@ User_var_log_event(const uchar *buf, uint event_len,
|
||||||
the flags value.
|
the flags value.
|
||||||
|
|
||||||
Old events will not have this extra byte, thence,
|
Old events will not have this extra byte, thence,
|
||||||
we keep the flags set to UNDEF_F.
|
we keep m_is_unsigned==false.
|
||||||
*/
|
*/
|
||||||
size_t bytes_read= (val + val_len) - (char*) buf_start;
|
const char *pos= val + val_len;
|
||||||
if (bytes_read > event_len)
|
if (pos > buf_end || unpack_optional_attributes(pos, buf_end))
|
||||||
{
|
{
|
||||||
error= true;
|
error= true;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if ((data_written - bytes_read) > 0)
|
|
||||||
{
|
|
||||||
flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
|
|
||||||
UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE +
|
|
||||||
val_len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
|
|
@ -57,6 +57,8 @@
|
||||||
|
|
||||||
#include "rpl_gtid.h"
|
#include "rpl_gtid.h"
|
||||||
|
|
||||||
|
#include "log_event_data_type.h"
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
#ifndef MYSQL_CLIENT
|
#ifndef MYSQL_CLIENT
|
||||||
class String;
|
class String;
|
||||||
|
@ -3284,33 +3286,27 @@ private:
|
||||||
@section User_var_log_event_binary_format Binary Format
|
@section User_var_log_event_binary_format Binary Format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class User_var_log_event: public Log_event
|
|
||||||
|
class User_var_log_event: public Log_event, public Log_event_data_type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum {
|
|
||||||
UNDEF_F= 0,
|
|
||||||
UNSIGNED_F= 1
|
|
||||||
};
|
|
||||||
const char *name;
|
const char *name;
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
const char *val;
|
const char *val;
|
||||||
size_t val_len;
|
size_t val_len;
|
||||||
Item_result type;
|
|
||||||
uint charset_number;
|
|
||||||
bool is_null;
|
bool is_null;
|
||||||
uchar flags;
|
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
bool deferred;
|
bool deferred;
|
||||||
query_id_t query_id;
|
query_id_t query_id;
|
||||||
User_var_log_event(THD* thd_arg, const char *name_arg, size_t name_len_arg,
|
User_var_log_event(THD* thd_arg, const char *name_arg, size_t name_len_arg,
|
||||||
const char *val_arg, size_t val_len_arg,
|
const char *val_arg, size_t val_len_arg,
|
||||||
Item_result type_arg,
|
const Log_event_data_type &data_type,
|
||||||
uint charset_number_arg, uchar flags_arg,
|
|
||||||
bool using_trans, bool direct)
|
bool using_trans, bool direct)
|
||||||
:Log_event(thd_arg, 0, using_trans),
|
:Log_event(thd_arg, 0, using_trans),
|
||||||
|
Log_event_data_type(data_type),
|
||||||
name(name_arg), name_len(name_len_arg), val(val_arg),
|
name(name_arg), name_len(name_len_arg), val(val_arg),
|
||||||
val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg),
|
val_len(val_len_arg),
|
||||||
flags(flags_arg), deferred(false)
|
deferred(false)
|
||||||
{
|
{
|
||||||
is_null= !val;
|
is_null= !val;
|
||||||
if (direct)
|
if (direct)
|
||||||
|
|
|
@ -2436,7 +2436,7 @@ bool User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (m_type) {
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
double real_val;
|
double real_val;
|
||||||
char real_buf[FMT_G_BUFSIZE(14)];
|
char real_buf[FMT_G_BUFSIZE(14)];
|
||||||
|
@ -2448,8 +2448,7 @@ bool User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
|
||||||
break;
|
break;
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
char int_buf[22];
|
char int_buf[22];
|
||||||
longlong10_to_str(uint8korr(val), int_buf,
|
longlong10_to_str(uint8korr(val), int_buf, is_unsigned() ? 10 : -10);
|
||||||
((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10));
|
|
||||||
if (my_b_printf(&cache, ":=%s%s\n", int_buf,
|
if (my_b_printf(&cache, ":=%s%s\n", int_buf,
|
||||||
print_event_info->delimiter))
|
print_event_info->delimiter))
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -2504,7 +2503,7 @@ bool User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
|
||||||
people want to mysqlbinlog|mysql into another server not supporting the
|
people want to mysqlbinlog|mysql into another server not supporting the
|
||||||
character set. But there's not much to do about this and it's unlikely.
|
character set. But there's not much to do about this and it's unlikely.
|
||||||
*/
|
*/
|
||||||
if (!(cs= get_charset(charset_number, MYF(0))))
|
if (!(cs= get_charset(m_charset_number, MYF(0))))
|
||||||
{ /*
|
{ /*
|
||||||
Generate an unusable command (=> syntax error) is probably the best
|
Generate an unusable command (=> syntax error) is probably the best
|
||||||
thing we can do here.
|
thing we can do here.
|
||||||
|
|
74
sql/log_event_data_type.h
Normal file
74
sql/log_event_data_type.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/* Copyright (c) 2024, 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 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; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||||
|
|
||||||
|
#ifndef LOG_EVENT_DATA_TYPE_H
|
||||||
|
#define LOG_EVENT_DATA_TYPE_H
|
||||||
|
|
||||||
|
class Log_event_data_type
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CHUNK_SIGNED= 0,
|
||||||
|
CHUNK_UNSIGNED= 1,
|
||||||
|
CHUNK_DATA_TYPE_NAME= 2
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
LEX_CSTRING m_data_type_name;
|
||||||
|
Item_result m_type;
|
||||||
|
uint m_charset_number;
|
||||||
|
bool m_is_unsigned;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Log_event_data_type()
|
||||||
|
:m_data_type_name({NULL,0}),
|
||||||
|
m_type(STRING_RESULT),
|
||||||
|
m_charset_number(my_charset_bin.number),
|
||||||
|
m_is_unsigned(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Log_event_data_type(const LEX_CSTRING &data_type_name_arg,
|
||||||
|
Item_result type_arg,
|
||||||
|
uint charset_number_arg,
|
||||||
|
bool is_unsigned_arg)
|
||||||
|
:m_data_type_name(data_type_name_arg),
|
||||||
|
m_type(type_arg),
|
||||||
|
m_charset_number(charset_number_arg),
|
||||||
|
m_is_unsigned(is_unsigned_arg)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
const LEX_CSTRING & data_type_name() const
|
||||||
|
{
|
||||||
|
return m_data_type_name;
|
||||||
|
}
|
||||||
|
Item_result type() const
|
||||||
|
{
|
||||||
|
return m_type;
|
||||||
|
}
|
||||||
|
uint charset_number() const
|
||||||
|
{
|
||||||
|
return m_charset_number;
|
||||||
|
}
|
||||||
|
bool is_unsigned() const
|
||||||
|
{
|
||||||
|
return m_is_unsigned;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unpack_optional_attributes(const char *str, const char *end);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LOG_EVENT_DATA_TYPE_H
|
|
@ -4218,11 +4218,16 @@ bool XA_prepare_log_event::write()
|
||||||
#if defined(HAVE_REPLICATION)
|
#if defined(HAVE_REPLICATION)
|
||||||
static bool
|
static bool
|
||||||
user_var_append_name_part(THD *thd, String *buf,
|
user_var_append_name_part(THD *thd, String *buf,
|
||||||
const char *name, size_t name_len)
|
const char *name, size_t name_len,
|
||||||
|
const LEX_CSTRING &data_type_name)
|
||||||
{
|
{
|
||||||
return buf->append('@') ||
|
return buf->append('@') ||
|
||||||
append_identifier(thd, buf, name, name_len) ||
|
append_identifier(thd, buf, name, name_len) ||
|
||||||
buf->append('=');
|
buf->append('=') ||
|
||||||
|
(data_type_name.length &&
|
||||||
|
(buf->append(STRING_WITH_LEN("/*")) ||
|
||||||
|
buf->append(data_type_name.str, data_type_name.length) ||
|
||||||
|
buf->append(STRING_WITH_LEN("*/"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void User_var_log_event::pack_info(Protocol* protocol)
|
void User_var_log_event::pack_info(Protocol* protocol)
|
||||||
|
@ -4232,14 +4237,15 @@ void User_var_log_event::pack_info(Protocol* protocol)
|
||||||
char buf_mem[FN_REFLEN+7];
|
char buf_mem[FN_REFLEN+7];
|
||||||
String buf(buf_mem, sizeof(buf_mem), system_charset_info);
|
String buf(buf_mem, sizeof(buf_mem), system_charset_info);
|
||||||
buf.length(0);
|
buf.length(0);
|
||||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len) ||
|
if (user_var_append_name_part(protocol->thd, &buf, name, name_len,
|
||||||
|
m_data_type_name) ||
|
||||||
buf.append(NULL_clex_str))
|
buf.append(NULL_clex_str))
|
||||||
return;
|
return;
|
||||||
protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
|
protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (m_type) {
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
{
|
{
|
||||||
double real_val;
|
double real_val;
|
||||||
|
@ -4248,7 +4254,8 @@ void User_var_log_event::pack_info(Protocol* protocol)
|
||||||
String buf(buf_mem, sizeof(buf_mem), system_charset_info);
|
String buf(buf_mem, sizeof(buf_mem), system_charset_info);
|
||||||
float8get(real_val, val);
|
float8get(real_val, val);
|
||||||
buf.length(0);
|
buf.length(0);
|
||||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len) ||
|
if (user_var_append_name_part(protocol->thd, &buf, name, name_len,
|
||||||
|
m_data_type_name) ||
|
||||||
buf.append(buf2, my_gcvt(real_val, MY_GCVT_ARG_DOUBLE,
|
buf.append(buf2, my_gcvt(real_val, MY_GCVT_ARG_DOUBLE,
|
||||||
MY_GCVT_MAX_FIELD_WIDTH, buf2, NULL)))
|
MY_GCVT_MAX_FIELD_WIDTH, buf2, NULL)))
|
||||||
return;
|
return;
|
||||||
|
@ -4261,10 +4268,11 @@ void User_var_log_event::pack_info(Protocol* protocol)
|
||||||
char buf_mem[FN_REFLEN + 22];
|
char buf_mem[FN_REFLEN + 22];
|
||||||
String buf(buf_mem, sizeof(buf_mem), system_charset_info);
|
String buf(buf_mem, sizeof(buf_mem), system_charset_info);
|
||||||
buf.length(0);
|
buf.length(0);
|
||||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len) ||
|
if (user_var_append_name_part(protocol->thd, &buf, name, name_len,
|
||||||
|
m_data_type_name) ||
|
||||||
buf.append(buf2,
|
buf.append(buf2,
|
||||||
longlong10_to_str(uint8korr(val), buf2,
|
longlong10_to_str(uint8korr(val), buf2,
|
||||||
((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10))-buf2))
|
(is_unsigned() ? 10 : -10))-buf2))
|
||||||
return;
|
return;
|
||||||
protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
|
protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
|
||||||
break;
|
break;
|
||||||
|
@ -4277,7 +4285,8 @@ void User_var_log_event::pack_info(Protocol* protocol)
|
||||||
String str(buf2, sizeof(buf2), &my_charset_bin);
|
String str(buf2, sizeof(buf2), &my_charset_bin);
|
||||||
buf.length(0);
|
buf.length(0);
|
||||||
my_decimal((const uchar *) (val + 2), val[0], val[1]).to_string(&str);
|
my_decimal((const uchar *) (val + 2), val[0], val[1]).to_string(&str);
|
||||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len) ||
|
if (user_var_append_name_part(protocol->thd, &buf, name, name_len,
|
||||||
|
m_data_type_name) ||
|
||||||
buf.append(str))
|
buf.append(str))
|
||||||
return;
|
return;
|
||||||
protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
|
protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
|
||||||
|
@ -4291,7 +4300,7 @@ void User_var_log_event::pack_info(Protocol* protocol)
|
||||||
String buf(buf_mem, sizeof(buf_mem), system_charset_info);
|
String buf(buf_mem, sizeof(buf_mem), system_charset_info);
|
||||||
CHARSET_INFO *cs;
|
CHARSET_INFO *cs;
|
||||||
buf.length(0);
|
buf.length(0);
|
||||||
if (!(cs= get_charset(charset_number, MYF(0))))
|
if (!(cs= get_charset(m_charset_number, MYF(0))))
|
||||||
{
|
{
|
||||||
if (buf.append(STRING_WITH_LEN("???")))
|
if (buf.append(STRING_WITH_LEN("???")))
|
||||||
return;
|
return;
|
||||||
|
@ -4300,7 +4309,8 @@ void User_var_log_event::pack_info(Protocol* protocol)
|
||||||
{
|
{
|
||||||
size_t old_len;
|
size_t old_len;
|
||||||
char *beg, *end;
|
char *beg, *end;
|
||||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len) ||
|
if (user_var_append_name_part(protocol->thd, &buf, name, name_len,
|
||||||
|
m_data_type_name) ||
|
||||||
buf.append('_') ||
|
buf.append('_') ||
|
||||||
buf.append(cs->cs_name) ||
|
buf.append(cs->cs_name) ||
|
||||||
buf.append(' '))
|
buf.append(' '))
|
||||||
|
@ -4348,10 +4358,10 @@ bool User_var_log_event::write()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buf1[1]= type;
|
buf1[1]= m_type;
|
||||||
int4store(buf1 + 2, charset_number);
|
int4store(buf1 + 2, m_charset_number);
|
||||||
|
|
||||||
switch (type) {
|
switch (m_type) {
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
float8store(buf2, *(double*) val);
|
float8store(buf2, *(double*) val);
|
||||||
break;
|
break;
|
||||||
|
@ -4381,15 +4391,28 @@ bool User_var_log_event::write()
|
||||||
buf1_length= 10;
|
buf1_length= 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Length of the whole event */
|
uchar data_type_name_chunk_signature= (uchar) CHUNK_DATA_TYPE_NAME;
|
||||||
event_length= sizeof(buf)+ name_len + buf1_length + val_len + unsigned_len;
|
uint data_type_name_chunk_signature_length= m_data_type_name.length ? 1 : 0;
|
||||||
|
uchar data_type_name_length_length= m_data_type_name.length ? 1 : 0;
|
||||||
|
|
||||||
|
/* Length of the whole event */
|
||||||
|
event_length= sizeof(buf)+ name_len + buf1_length + val_len + unsigned_len +
|
||||||
|
data_type_name_chunk_signature_length +
|
||||||
|
data_type_name_length_length +
|
||||||
|
(uint) m_data_type_name.length;
|
||||||
|
|
||||||
|
uchar unsig= m_is_unsigned ? CHUNK_UNSIGNED : CHUNK_SIGNED;
|
||||||
|
uchar data_type_name_length= (uchar) m_data_type_name.length;
|
||||||
return write_header(event_length) ||
|
return write_header(event_length) ||
|
||||||
write_data(buf, sizeof(buf)) ||
|
write_data(buf, sizeof(buf)) ||
|
||||||
write_data(name, name_len) ||
|
write_data(name, name_len) ||
|
||||||
write_data(buf1, buf1_length) ||
|
write_data(buf1, buf1_length) ||
|
||||||
write_data(pos, val_len) ||
|
write_data(pos, val_len) ||
|
||||||
write_data(&flags, unsigned_len) ||
|
write_data(&unsig, unsigned_len) ||
|
||||||
|
write_data(&data_type_name_chunk_signature,
|
||||||
|
data_type_name_chunk_signature_length) ||
|
||||||
|
write_data(&data_type_name_length, data_type_name_length_length) ||
|
||||||
|
write_data(m_data_type_name.str, (uint) m_data_type_name.length) ||
|
||||||
write_footer();
|
write_footer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4413,7 +4436,7 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi)
|
||||||
current_thd->query_id= query_id; /* recreating original time context */
|
current_thd->query_id= query_id; /* recreating original time context */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(charset= get_charset(charset_number, MYF(MY_WME))))
|
if (!(charset= get_charset(m_charset_number, MYF(MY_WME))))
|
||||||
{
|
{
|
||||||
rgi->rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
|
rgi->rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
|
||||||
ER_THD(thd, ER_SLAVE_FATAL_ERROR),
|
ER_THD(thd, ER_SLAVE_FATAL_ERROR),
|
||||||
|
@ -4432,7 +4455,7 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (m_type) {
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
if (val_len != 8)
|
if (val_len != 8)
|
||||||
{
|
{
|
||||||
|
@ -4496,13 +4519,10 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi)
|
||||||
if (e->fix_fields(thd, 0))
|
if (e->fix_fields(thd, 0))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
/*
|
const Type_handler *th= Type_handler::handler_by_log_event_data_type(thd,
|
||||||
A variable can just be considered as a table with
|
*this);
|
||||||
a single record and with a single column. Thus, like
|
e->update_hash((void*) val, val_len, th, charset);
|
||||||
a column value, it could always have IMPLICIT derivation.
|
|
||||||
*/
|
|
||||||
e->update_hash((void*) val, val_len, type, charset,
|
|
||||||
(flags & User_var_log_event::UNSIGNED_F));
|
|
||||||
if (!is_deferred())
|
if (!is_deferred())
|
||||||
free_root(thd->mem_root, 0);
|
free_root(thd->mem_root, 0);
|
||||||
else
|
else
|
||||||
|
|
|
@ -103,7 +103,8 @@ inline bool sql_command_can_be_traced(enum enum_sql_command sql_command)
|
||||||
sql_command == SQLCOM_UPDATE ||
|
sql_command == SQLCOM_UPDATE ||
|
||||||
sql_command == SQLCOM_DELETE ||
|
sql_command == SQLCOM_DELETE ||
|
||||||
sql_command == SQLCOM_DELETE_MULTI ||
|
sql_command == SQLCOM_DELETE_MULTI ||
|
||||||
sql_command == SQLCOM_UPDATE_MULTI;
|
sql_command == SQLCOM_UPDATE_MULTI ||
|
||||||
|
sql_command == SQLCOM_INSERT_SELECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void opt_trace_print_expanded_query(THD *thd, SELECT_LEX *select_lex,
|
void opt_trace_print_expanded_query(THD *thd, SELECT_LEX *select_lex,
|
||||||
|
|
|
@ -134,7 +134,7 @@ int binlog_defragment(THD *thd)
|
||||||
entry[k]=
|
entry[k]=
|
||||||
(user_var_entry*) my_hash_search(&thd->user_vars, (uchar*) name[k].str,
|
(user_var_entry*) my_hash_search(&thd->user_vars, (uchar*) name[k].str,
|
||||||
name[k].length);
|
name[k].length);
|
||||||
if (!entry[k] || entry[k]->type != STRING_RESULT)
|
if (!entry[k] || entry[k]->type_handler()->result_type() != STRING_RESULT)
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), name[k].str);
|
my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), name[k].str);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -159,7 +159,8 @@ int binlog_defragment(THD *thd)
|
||||||
gathered_length += entry[k]->length;
|
gathered_length += entry[k]->length;
|
||||||
}
|
}
|
||||||
for (uint k=0; k < 2; k++)
|
for (uint k=0; k < 2; k++)
|
||||||
update_hash(entry[k], true, NULL, 0, STRING_RESULT, &my_charset_bin, 0);
|
update_hash(entry[k], true, NULL, 0,
|
||||||
|
&type_handler_long_blob, &my_charset_bin);
|
||||||
|
|
||||||
DBUG_ASSERT(gathered_length == thd->lex->comment.length);
|
DBUG_ASSERT(gathered_length == thd->lex->comment.length);
|
||||||
|
|
||||||
|
|
|
@ -278,9 +278,8 @@ typedef struct st_user_var_events
|
||||||
user_var_entry *user_var_event;
|
user_var_entry *user_var_event;
|
||||||
char *value;
|
char *value;
|
||||||
size_t length;
|
size_t length;
|
||||||
Item_result type;
|
const Type_handler *th;
|
||||||
uint charset_number;
|
uint charset_number;
|
||||||
bool unsigned_flag;
|
|
||||||
} BINLOG_USER_VAR_EVENT;
|
} BINLOG_USER_VAR_EVENT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7133,7 +7132,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
// this is needed for user_vars hash
|
// this is needed for user_vars hash
|
||||||
class user_var_entry
|
class user_var_entry: public Type_handler_hybrid_field_type
|
||||||
{
|
{
|
||||||
CHARSET_INFO *m_charset;
|
CHARSET_INFO *m_charset;
|
||||||
public:
|
public:
|
||||||
|
@ -7142,8 +7141,6 @@ class user_var_entry
|
||||||
char *value;
|
char *value;
|
||||||
size_t length;
|
size_t length;
|
||||||
query_id_t update_query_id, used_query_id;
|
query_id_t update_query_id, used_query_id;
|
||||||
Item_result type;
|
|
||||||
bool unsigned_flag;
|
|
||||||
|
|
||||||
double val_real(bool *null_value);
|
double val_real(bool *null_value);
|
||||||
longlong val_int(bool *null_value) const;
|
longlong val_int(bool *null_value) const;
|
||||||
|
|
|
@ -510,7 +510,7 @@ static enum enum_binlog_checksum_alg get_binlog_checksum_value_at_connect(THD *
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(entry->type == STRING_RESULT);
|
DBUG_ASSERT(entry->type_handler()->result_type() == STRING_RESULT);
|
||||||
String str;
|
String str;
|
||||||
uint dummy_errors;
|
uint dummy_errors;
|
||||||
str.copy(entry->value, entry->length, &my_charset_bin, &my_charset_bin,
|
str.copy(entry->value, entry->length, &my_charset_bin, &my_charset_bin,
|
||||||
|
|
|
@ -2242,6 +2242,34 @@ Type_handler::get_handler_by_real_type(enum_field_types type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Type_handler *
|
||||||
|
Type_handler::handler_by_log_event_data_type(THD *thd,
|
||||||
|
const Log_event_data_type &type)
|
||||||
|
{
|
||||||
|
if (type.data_type_name().length)
|
||||||
|
{
|
||||||
|
const Type_handler *th= handler_by_name(thd, type.data_type_name());
|
||||||
|
if (th)
|
||||||
|
return th;
|
||||||
|
}
|
||||||
|
switch (type.type()) {
|
||||||
|
case STRING_RESULT:
|
||||||
|
case ROW_RESULT:
|
||||||
|
case TIME_RESULT:
|
||||||
|
break;
|
||||||
|
case REAL_RESULT:
|
||||||
|
return &type_handler_double;
|
||||||
|
case INT_RESULT:
|
||||||
|
if (type.is_unsigned())
|
||||||
|
return &type_handler_ulonglong;
|
||||||
|
return &type_handler_slonglong;
|
||||||
|
case DECIMAL_RESULT:
|
||||||
|
return &type_handler_newdecimal;
|
||||||
|
}
|
||||||
|
return &type_handler_long_blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create a DOUBLE field by default.
|
Create a DOUBLE field by default.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include "sql_type_string.h"
|
#include "sql_type_string.h"
|
||||||
#include "sql_type_real.h"
|
#include "sql_type_real.h"
|
||||||
#include "compat56.h"
|
#include "compat56.h"
|
||||||
|
#include "log_event_data_type.h"
|
||||||
|
|
||||||
C_MODE_START
|
C_MODE_START
|
||||||
#include <ma_dyncol.h>
|
#include <ma_dyncol.h>
|
||||||
C_MODE_END
|
C_MODE_END
|
||||||
|
@ -3685,6 +3687,9 @@ public:
|
||||||
static const Type_handler *handler_by_name(THD *thd, const LEX_CSTRING &name);
|
static const Type_handler *handler_by_name(THD *thd, const LEX_CSTRING &name);
|
||||||
static const Type_handler *handler_by_name_or_error(THD *thd,
|
static const Type_handler *handler_by_name_or_error(THD *thd,
|
||||||
const LEX_CSTRING &name);
|
const LEX_CSTRING &name);
|
||||||
|
static const Type_handler *handler_by_log_event_data_type(
|
||||||
|
THD *thd,
|
||||||
|
const Log_event_data_type &type);
|
||||||
static const Type_handler *odbc_literal_type_handler(const LEX_CSTRING *str);
|
static const Type_handler *odbc_literal_type_handler(const LEX_CSTRING *str);
|
||||||
static const Type_handler *blob_type_handler(uint max_octet_length);
|
static const Type_handler *blob_type_handler(uint max_octet_length);
|
||||||
static const Type_handler *string_type_handler(uint max_octet_length);
|
static const Type_handler *string_type_handler(uint max_octet_length);
|
||||||
|
@ -3969,6 +3974,12 @@ public:
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual Log_event_data_type user_var_log_event_data_type(uint charset_nr) const
|
||||||
|
{
|
||||||
|
return Log_event_data_type({NULL,0}/*data type name*/, result_type(),
|
||||||
|
charset_nr, is_unsigned());
|
||||||
|
}
|
||||||
virtual uint Column_definition_gis_options_image(uchar *buff,
|
virtual uint Column_definition_gis_options_image(uchar *buff,
|
||||||
const Column_definition &def)
|
const Column_definition &def)
|
||||||
const
|
const
|
||||||
|
|
|
@ -82,6 +82,13 @@ public:
|
||||||
Field *make_conversion_table_field(MEM_ROOT *root,
|
Field *make_conversion_table_field(MEM_ROOT *root,
|
||||||
TABLE *table, uint metadata,
|
TABLE *table, uint metadata,
|
||||||
const Field *target) const override;
|
const Field *target) const override;
|
||||||
|
Log_event_data_type user_var_log_event_data_type(uint charset_nr)
|
||||||
|
const override
|
||||||
|
{
|
||||||
|
return Log_event_data_type(name().lex_cstring(), result_type(),
|
||||||
|
charset_nr, false/*unsigned*/);
|
||||||
|
}
|
||||||
|
|
||||||
uint Column_definition_gis_options_image(uchar *buff,
|
uint Column_definition_gis_options_image(uchar *buff,
|
||||||
const Column_definition &def)
|
const Column_definition &def)
|
||||||
const override;
|
const override;
|
||||||
|
|
|
@ -338,11 +338,14 @@ func_exit:
|
||||||
os_file_flush(file);
|
os_file_flush(file);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
for (ulint i= 0; i < size * 2; i++, page += srv_page_size)
|
{
|
||||||
if (mach_read_from_8(my_assume_aligned<8>(page + FIL_PAGE_LSN)))
|
alignas(8) char checkpoint[8];
|
||||||
/* Each valid page header must contain a nonzero FIL_PAGE_LSN field. */
|
mach_write_to_8(checkpoint, log_sys.next_checkpoint_lsn);
|
||||||
|
for (auto i= size * 2; i--; page += srv_page_size)
|
||||||
|
if (memcmp_aligned<8>(page + FIL_PAGE_LSN, checkpoint, 8) >= 0)
|
||||||
|
/* Valid pages are not older than the log checkpoint. */
|
||||||
recv_sys.dblwr.add(page);
|
recv_sys.dblwr.add(page);
|
||||||
|
}
|
||||||
err= DB_SUCCESS;
|
err= DB_SUCCESS;
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
|
@ -436,12 +436,22 @@ Datafile::validate_for_recovery()
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_space_id) {
|
||||||
|
m_space_id = recv_sys.dblwr.find_first_page(
|
||||||
|
m_filepath, m_handle);
|
||||||
|
if (m_space_id) {
|
||||||
|
m_defer= false;
|
||||||
|
goto free_first_page;
|
||||||
|
} else return err;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_defer) {
|
if (!m_defer) {
|
||||||
err = find_space_id();
|
err = find_space_id();
|
||||||
if (err != DB_SUCCESS || m_space_id == 0) {
|
if (err != DB_SUCCESS || m_space_id == 0) {
|
||||||
ib::error() << "Datafile '" << m_filepath
|
sql_print_error(
|
||||||
<< "' is corrupted. Cannot determine "
|
"InnoDB: Datafile '%s' is corrupted."
|
||||||
"the space ID from the first 64 pages.";
|
" Cannot determine the space ID from"
|
||||||
|
" the first 64 pages.", m_filepath);
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -454,7 +464,7 @@ Datafile::validate_for_recovery()
|
||||||
m_space_id, m_filepath, m_handle)) {
|
m_space_id, m_filepath, m_handle)) {
|
||||||
return m_defer ? err : DB_CORRUPTION;
|
return m_defer ? err : DB_CORRUPTION;
|
||||||
}
|
}
|
||||||
|
free_first_page:
|
||||||
/* Free the previously read first page and then re-validate. */
|
/* Free the previously read first page and then re-validate. */
|
||||||
free_first_page();
|
free_first_page();
|
||||||
m_defer = false;
|
m_defer = false;
|
||||||
|
@ -502,11 +512,11 @@ err_exit:
|
||||||
return DB_SUCCESS;
|
return DB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ib::info() << error_txt << " in datafile: " << m_filepath
|
sql_print_error("InnoDB: %s in datafile: %s, Space ID: %zu, "
|
||||||
<< ", Space ID:" << m_space_id << ", Flags: "
|
"Flags: %zu", error_txt, m_filepath,
|
||||||
<< m_flags;
|
m_space_id, m_flags);
|
||||||
m_is_valid = false;
|
m_is_valid = false;
|
||||||
return(DB_CORRUPTION);
|
return DB_CORRUPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the whole page is blank. */
|
/* Check if the whole page is blank. */
|
||||||
|
|
|
@ -573,7 +573,7 @@ SysTablespace::read_lsn_and_check_flags(lsn_t* flushed_lsn)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = it->read_first_page(
|
err = it->read_first_page(
|
||||||
m_ignore_read_only ? false : srv_read_only_mode);
|
m_ignore_read_only && srv_read_only_mode);
|
||||||
|
|
||||||
if (err != DB_SUCCESS) {
|
if (err != DB_SUCCESS) {
|
||||||
return(err);
|
return(err);
|
||||||
|
@ -587,20 +587,17 @@ SysTablespace::read_lsn_and_check_flags(lsn_t* flushed_lsn)
|
||||||
|
|
||||||
/* Check the contents of the first page of the
|
/* Check the contents of the first page of the
|
||||||
first datafile. */
|
first datafile. */
|
||||||
for (int retry = 0; retry < 2; ++retry) {
|
err = it->validate_first_page(flushed_lsn);
|
||||||
|
|
||||||
err = it->validate_first_page(flushed_lsn);
|
if (err != DB_SUCCESS) {
|
||||||
|
if (recv_sys.dblwr.restore_first_page(
|
||||||
if (err != DB_SUCCESS
|
|
||||||
&& (retry == 1
|
|
||||||
|| recv_sys.dblwr.restore_first_page(
|
|
||||||
it->m_space_id, it->m_filepath,
|
it->m_space_id, it->m_filepath,
|
||||||
it->handle()))) {
|
it->handle())) {
|
||||||
|
|
||||||
it->close();
|
it->close();
|
||||||
|
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
err = it->read_first_page(
|
||||||
|
m_ignore_read_only && srv_read_only_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the tablespace space ID matches the
|
/* Make sure the tablespace space ID matches the
|
||||||
|
|
|
@ -105,7 +105,8 @@ public:
|
||||||
If we are upgrading from a version before MySQL 4.1, then this
|
If we are upgrading from a version before MySQL 4.1, then this
|
||||||
function performs the necessary update operations to support
|
function performs the necessary update operations to support
|
||||||
innodb_file_per_table. If we are in a crash recovery, this function
|
innodb_file_per_table. If we are in a crash recovery, this function
|
||||||
loads the pages from double write buffer into memory.
|
loads the pages from double write buffer which are not older than
|
||||||
|
the checkpoint into memory.
|
||||||
@param file File handle
|
@param file File handle
|
||||||
@param path Path name of file
|
@param path Path name of file
|
||||||
@return DB_SUCCESS or error code */
|
@return DB_SUCCESS or error code */
|
||||||
|
|
|
@ -51,6 +51,11 @@ ATTRIBUTE_COLD MY_ATTRIBUTE((nonnull, warn_unused_result))
|
||||||
@return whether the page was recovered correctly */
|
@return whether the page was recovered correctly */
|
||||||
bool recv_recover_page(fil_space_t* space, buf_page_t* bpage);
|
bool recv_recover_page(fil_space_t* space, buf_page_t* bpage);
|
||||||
|
|
||||||
|
/** Read the latest checkpoint information from log file
|
||||||
|
and store it in log_sys.next_checkpoint and recv_sys.mlog_checkpoint_lsn
|
||||||
|
@return error code or DB_SUCCESS */
|
||||||
|
dberr_t recv_recovery_read_max_checkpoint();
|
||||||
|
|
||||||
/** Start recovering from a redo log checkpoint.
|
/** Start recovering from a redo log checkpoint.
|
||||||
@param[in] flush_lsn FIL_PAGE_FILE_FLUSH_LSN
|
@param[in] flush_lsn FIL_PAGE_FILE_FLUSH_LSN
|
||||||
of first system tablespace page
|
of first system tablespace page
|
||||||
|
@ -147,7 +152,18 @@ struct recv_dblwr_t
|
||||||
@param file tablespace file handle
|
@param file tablespace file handle
|
||||||
@return whether the operation failed */
|
@return whether the operation failed */
|
||||||
bool restore_first_page(
|
bool restore_first_page(
|
||||||
ulint space_id, const char *name, os_file_t file);
|
ulint space_id, const char *name, pfs_os_file_t file);
|
||||||
|
|
||||||
|
/** Restore the first page of the given tablespace from
|
||||||
|
doublewrite buffer.
|
||||||
|
1) Find the page which has page_no as 0
|
||||||
|
2) Read first 3 pages from tablespace file
|
||||||
|
3) Compare the space_ids from the pages with page0 which
|
||||||
|
was retrieved from doublewrite buffer
|
||||||
|
@param name tablespace filepath
|
||||||
|
@param file tablespace file handle
|
||||||
|
@return space_id or 0 in case of error */
|
||||||
|
uint32_t find_first_page(const char *name, pfs_os_file_t file);
|
||||||
|
|
||||||
typedef std::deque<byte*, ut_allocator<byte*> > list;
|
typedef std::deque<byte*, ut_allocator<byte*> > list;
|
||||||
|
|
||||||
|
|
|
@ -4408,6 +4408,46 @@ done:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dberr_t recv_recovery_read_max_checkpoint()
|
||||||
|
{
|
||||||
|
ut_ad(srv_operation <= SRV_OPERATION_EXPORT_RESTORED ||
|
||||||
|
srv_operation == SRV_OPERATION_RESTORE ||
|
||||||
|
srv_operation == SRV_OPERATION_RESTORE_EXPORT);
|
||||||
|
ut_d(mysql_mutex_lock(&buf_pool.mutex));
|
||||||
|
ut_ad(UT_LIST_GET_LEN(buf_pool.LRU) == 0);
|
||||||
|
ut_ad(UT_LIST_GET_LEN(buf_pool.unzip_LRU) == 0);
|
||||||
|
ut_d(mysql_mutex_unlock(&buf_pool.mutex));
|
||||||
|
|
||||||
|
if (srv_force_recovery >= SRV_FORCE_NO_LOG_REDO)
|
||||||
|
{
|
||||||
|
sql_print_information("InnoDB: innodb_force_recovery=6 skips redo log apply");
|
||||||
|
return DB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql_mutex_lock(&log_sys.mutex);
|
||||||
|
ulint max_cp;
|
||||||
|
dberr_t err= recv_find_max_checkpoint(&max_cp);
|
||||||
|
|
||||||
|
if (err != DB_SUCCESS)
|
||||||
|
recv_sys.recovered_lsn= log_sys.get_lsn();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byte* buf= log_sys.checkpoint_buf;
|
||||||
|
err= log_sys.log.read(max_cp, {buf, OS_FILE_LOG_BLOCK_SIZE});
|
||||||
|
if (err == DB_SUCCESS)
|
||||||
|
{
|
||||||
|
log_sys.next_checkpoint_no=
|
||||||
|
mach_read_from_8(buf + LOG_CHECKPOINT_NO);
|
||||||
|
log_sys.next_checkpoint_lsn=
|
||||||
|
mach_read_from_8(buf + LOG_CHECKPOINT_LSN);
|
||||||
|
recv_sys.mlog_checkpoint_lsn=
|
||||||
|
mach_read_from_8(buf + LOG_CHECKPOINT_END_LSN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mysql_mutex_unlock(&log_sys.mutex);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/** Start recovering from a redo log checkpoint.
|
/** Start recovering from a redo log checkpoint.
|
||||||
@param[in] flush_lsn FIL_PAGE_FILE_FLUSH_LSN
|
@param[in] flush_lsn FIL_PAGE_FILE_FLUSH_LSN
|
||||||
of first system tablespace page
|
of first system tablespace page
|
||||||
|
@ -4415,12 +4455,8 @@ of first system tablespace page
|
||||||
dberr_t
|
dberr_t
|
||||||
recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
|
recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
|
||||||
{
|
{
|
||||||
ulint max_cp_field;
|
|
||||||
lsn_t checkpoint_lsn;
|
|
||||||
bool rescan = false;
|
bool rescan = false;
|
||||||
ib_uint64_t checkpoint_no;
|
|
||||||
lsn_t contiguous_lsn;
|
lsn_t contiguous_lsn;
|
||||||
byte* buf;
|
|
||||||
dberr_t err = DB_SUCCESS;
|
dberr_t err = DB_SUCCESS;
|
||||||
|
|
||||||
ut_ad(srv_operation <= SRV_OPERATION_EXPORT_RESTORED
|
ut_ad(srv_operation <= SRV_OPERATION_EXPORT_RESTORED
|
||||||
|
@ -4438,27 +4474,11 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
|
||||||
return(DB_SUCCESS);
|
return(DB_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
recv_sys.recovery_on = true;
|
|
||||||
|
|
||||||
mysql_mutex_lock(&log_sys.mutex);
|
mysql_mutex_lock(&log_sys.mutex);
|
||||||
|
uint64_t checkpoint_no= log_sys.next_checkpoint_no;
|
||||||
err = recv_find_max_checkpoint(&max_cp_field);
|
lsn_t checkpoint_lsn= log_sys.next_checkpoint_lsn;
|
||||||
|
const lsn_t end_lsn= recv_sys.mlog_checkpoint_lsn;
|
||||||
if (err != DB_SUCCESS) {
|
recv_sys.recovery_on = true;
|
||||||
|
|
||||||
recv_sys.recovered_lsn = log_sys.get_lsn();
|
|
||||||
mysql_mutex_unlock(&log_sys.mutex);
|
|
||||||
return(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = log_sys.checkpoint_buf;
|
|
||||||
if ((err= log_sys.log.read(max_cp_field, {buf, OS_FILE_LOG_BLOCK_SIZE}))) {
|
|
||||||
mysql_mutex_unlock(&log_sys.mutex);
|
|
||||||
return(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN);
|
|
||||||
checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
|
|
||||||
|
|
||||||
/* Start reading the log from the checkpoint lsn. The variable
|
/* Start reading the log from the checkpoint lsn. The variable
|
||||||
contiguous_lsn contains an lsn up to which the log is known to
|
contiguous_lsn contains an lsn up to which the log is known to
|
||||||
|
@ -4467,8 +4487,6 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
|
||||||
|
|
||||||
ut_ad(RECV_SCAN_SIZE <= srv_log_buffer_size);
|
ut_ad(RECV_SCAN_SIZE <= srv_log_buffer_size);
|
||||||
|
|
||||||
const lsn_t end_lsn = mach_read_from_8(
|
|
||||||
buf + LOG_CHECKPOINT_END_LSN);
|
|
||||||
|
|
||||||
ut_ad(recv_sys.pages.empty());
|
ut_ad(recv_sys.pages.empty());
|
||||||
contiguous_lsn = checkpoint_lsn;
|
contiguous_lsn = checkpoint_lsn;
|
||||||
|
@ -4849,8 +4867,52 @@ byte *recv_dblwr_t::find_page(const page_id_t page_id,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t recv_dblwr_t::find_first_page(const char *name, pfs_os_file_t file)
|
||||||
|
{
|
||||||
|
os_offset_t file_size= os_file_get_size(file);
|
||||||
|
if (file_size != (os_offset_t) -1)
|
||||||
|
{
|
||||||
|
for (const page_t *page : pages)
|
||||||
|
{
|
||||||
|
uint32_t space_id= page_get_space_id(page);
|
||||||
|
if (page_get_page_no(page) > 0 || space_id == 0)
|
||||||
|
next_page:
|
||||||
|
continue;
|
||||||
|
uint32_t flags= mach_read_from_4(
|
||||||
|
FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page);
|
||||||
|
page_id_t page_id(space_id, 0);
|
||||||
|
size_t page_size= fil_space_t::physical_size(flags);
|
||||||
|
if (file_size < 4 * page_size)
|
||||||
|
goto next_page;
|
||||||
|
byte *read_page=
|
||||||
|
static_cast<byte*>(aligned_malloc(3 * page_size, page_size));
|
||||||
|
/* Read 3 pages from the file and match the space id
|
||||||
|
with the space id which is stored in
|
||||||
|
doublewrite buffer page. */
|
||||||
|
if (os_file_read(IORequestRead, file, read_page, page_size,
|
||||||
|
3 * page_size, nullptr) != DB_SUCCESS)
|
||||||
|
goto next_page;
|
||||||
|
for (ulint j= 0; j <= 2; j++)
|
||||||
|
{
|
||||||
|
byte *cur_page= read_page + j * page_size;
|
||||||
|
if (buf_is_zeroes(span<const byte>(cur_page, page_size)))
|
||||||
|
return 0;
|
||||||
|
if (mach_read_from_4(cur_page + FIL_PAGE_OFFSET) != j + 1 ||
|
||||||
|
memcmp(cur_page + FIL_PAGE_SPACE_ID,
|
||||||
|
page + FIL_PAGE_SPACE_ID, 4) ||
|
||||||
|
buf_page_is_corrupted(false, cur_page, flags))
|
||||||
|
goto next_page;
|
||||||
|
}
|
||||||
|
if (!restore_first_page(space_id, name, file))
|
||||||
|
return space_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool recv_dblwr_t::restore_first_page(ulint space_id, const char *name,
|
bool recv_dblwr_t::restore_first_page(ulint space_id, const char *name,
|
||||||
os_file_t file)
|
pfs_os_file_t file)
|
||||||
{
|
{
|
||||||
const page_id_t page_id(space_id, 0);
|
const page_id_t page_id(space_id, 0);
|
||||||
const byte* page= find_page(page_id);
|
const byte* page= find_page(page_id);
|
||||||
|
@ -4858,10 +4920,11 @@ bool recv_dblwr_t::restore_first_page(ulint space_id, const char *name,
|
||||||
{
|
{
|
||||||
/* If the first page of the given user tablespace is not there
|
/* If the first page of the given user tablespace is not there
|
||||||
in the doublewrite buffer, then the recovery is going to fail
|
in the doublewrite buffer, then the recovery is going to fail
|
||||||
now. Hence this is treated as error. */
|
now. Report error only when doublewrite buffer is not empty */
|
||||||
ib::error()
|
if (pages.size())
|
||||||
<< "Corrupted page " << page_id << " of datafile '"
|
ib::error() << "Corrupted page " << page_id << " of datafile '"
|
||||||
<< name <<"' could not be found in the doublewrite buffer.";
|
<< name <<"' could not be found in the "
|
||||||
|
<<"doublewrite buffer.";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -296,9 +296,6 @@ static dberr_t create_log_file(bool create_new_db, lsn_t lsn,
|
||||||
log_sys.log.create();
|
log_sys.log.create();
|
||||||
|
|
||||||
log_sys.log.open_file(logfile0);
|
log_sys.log.open_file(logfile0);
|
||||||
if (!fil_system.sys_space->open(create_new_db)) {
|
|
||||||
return DB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a log checkpoint. */
|
/* Create a log checkpoint. */
|
||||||
mysql_mutex_lock(&log_sys.mutex);
|
mysql_mutex_lock(&log_sys.mutex);
|
||||||
|
@ -1261,40 +1258,6 @@ dberr_t srv_start(bool create_new_db)
|
||||||
|
|
||||||
/* Check if undo tablespaces and redo log files exist before creating
|
/* Check if undo tablespaces and redo log files exist before creating
|
||||||
a new system tablespace */
|
a new system tablespace */
|
||||||
if (create_new_db) {
|
|
||||||
err = srv_check_undo_redo_logs_exists();
|
|
||||||
if (err != DB_SUCCESS) {
|
|
||||||
return(srv_init_abort(DB_ERROR));
|
|
||||||
}
|
|
||||||
recv_sys.debug_free();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open or create the data files. */
|
|
||||||
ulint sum_of_new_sizes;
|
|
||||||
|
|
||||||
err = srv_sys_space.open_or_create(
|
|
||||||
false, create_new_db, &sum_of_new_sizes, &flushed_lsn);
|
|
||||||
|
|
||||||
switch (err) {
|
|
||||||
case DB_SUCCESS:
|
|
||||||
break;
|
|
||||||
case DB_CANNOT_OPEN_FILE:
|
|
||||||
ib::error()
|
|
||||||
<< "Could not open or create the system tablespace. If"
|
|
||||||
" you tried to add new data files to the system"
|
|
||||||
" tablespace, and it failed here, you should now"
|
|
||||||
" edit innodb_data_file_path in my.cnf back to what"
|
|
||||||
" it was, and remove the new ibdata files InnoDB"
|
|
||||||
" created in this failed attempt. InnoDB only wrote"
|
|
||||||
" those files full of zeros, but did not yet use"
|
|
||||||
" them in any way. But be careful: do not remove"
|
|
||||||
" old data files which contain your precious data!";
|
|
||||||
/* fall through */
|
|
||||||
default:
|
|
||||||
/* Other errors might come from Datafile::validate_first_page() */
|
|
||||||
return(srv_init_abort(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
srv_log_file_size_requested = srv_log_file_size;
|
srv_log_file_size_requested = srv_log_file_size;
|
||||||
|
|
||||||
if (innodb_encrypt_temporary_tables && !log_crypt_init()) {
|
if (innodb_encrypt_temporary_tables && !log_crypt_init()) {
|
||||||
|
@ -1304,18 +1267,17 @@ dberr_t srv_start(bool create_new_db)
|
||||||
std::string logfile0;
|
std::string logfile0;
|
||||||
bool create_new_log = create_new_db;
|
bool create_new_log = create_new_db;
|
||||||
if (create_new_db) {
|
if (create_new_db) {
|
||||||
|
err = srv_check_undo_redo_logs_exists();
|
||||||
|
if (err != DB_SUCCESS) {
|
||||||
|
return(srv_init_abort(DB_ERROR));
|
||||||
|
}
|
||||||
|
recv_sys.debug_free();
|
||||||
flushed_lsn = log_sys.get_lsn();
|
flushed_lsn = log_sys.get_lsn();
|
||||||
log_sys.set_flushed_lsn(flushed_lsn);
|
log_sys.set_flushed_lsn(flushed_lsn);
|
||||||
|
|
||||||
err = create_log_file(true, flushed_lsn, logfile0);
|
err = create_log_file(true, flushed_lsn, logfile0);
|
||||||
|
|
||||||
if (err != DB_SUCCESS) {
|
if (err != DB_SUCCESS) {
|
||||||
for (Tablespace::const_iterator
|
|
||||||
i = srv_sys_space.begin();
|
|
||||||
i != srv_sys_space.end(); i++) {
|
|
||||||
os_file_delete(innodb_data_file_key,
|
|
||||||
i->filepath());
|
|
||||||
}
|
|
||||||
return(srv_init_abort(err));
|
return(srv_init_abort(err));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1330,51 +1292,84 @@ dberr_t srv_start(bool create_new_db)
|
||||||
}
|
}
|
||||||
|
|
||||||
create_new_log = srv_log_file_size == 0;
|
create_new_log = srv_log_file_size == 0;
|
||||||
if (create_new_log) {
|
if (!create_new_log) {
|
||||||
if (flushed_lsn < lsn_t(1000)) {
|
srv_log_file_found = log_file_found;
|
||||||
ib::error()
|
|
||||||
<< "Cannot create log file because"
|
log_sys.log.open_file(get_log_file_path());
|
||||||
" data files are corrupt or the"
|
|
||||||
" database was not shut down cleanly"
|
log_sys.log.create();
|
||||||
" after creating the data files.";
|
|
||||||
return srv_init_abort(DB_ERROR);
|
if (!log_set_capacity(
|
||||||
|
srv_log_file_size_requested)) {
|
||||||
|
return(srv_init_abort(DB_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
srv_log_file_size = srv_log_file_size_requested;
|
/* Enable checkpoints in the page cleaner. */
|
||||||
|
recv_sys.recovery_on = false;
|
||||||
|
|
||||||
err = create_log_file(false, flushed_lsn, logfile0);
|
err= recv_recovery_read_max_checkpoint();
|
||||||
|
|
||||||
if (err == DB_SUCCESS) {
|
|
||||||
err = create_log_file_rename(flushed_lsn,
|
|
||||||
logfile0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err != DB_SUCCESS) {
|
if (err != DB_SUCCESS) {
|
||||||
return(srv_init_abort(err));
|
return srv_init_abort(err);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Suppress the message about
|
/* Open or create the data files. */
|
||||||
crash recovery. */
|
ulint sum_of_new_sizes;
|
||||||
flushed_lsn = log_sys.get_lsn();
|
|
||||||
goto file_checked;
|
err = srv_sys_space.open_or_create(
|
||||||
|
false, create_new_db, &sum_of_new_sizes, &flushed_lsn);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case DB_SUCCESS:
|
||||||
|
break;
|
||||||
|
case DB_CANNOT_OPEN_FILE:
|
||||||
|
sql_print_error("InnoDB: Could not open or create the system"
|
||||||
|
" tablespace. If you tried to add new data files"
|
||||||
|
" to the system tablespace, and it failed here,"
|
||||||
|
" you should now edit innodb_data_file_path"
|
||||||
|
" in my.cnf back to what it was, and remove the"
|
||||||
|
" new ibdata files InnoDB created in this failed"
|
||||||
|
" attempt. InnoDB only wrote those files full of"
|
||||||
|
" zeros, but did not yet use them in any way. But"
|
||||||
|
" be careful: do not remove old data files which"
|
||||||
|
" contain your precious data!");
|
||||||
|
/* fall through */
|
||||||
|
default:
|
||||||
|
/* Other errors might come from Datafile::validate_first_page() */
|
||||||
|
return(srv_init_abort(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!create_new_db && create_new_log) {
|
||||||
|
if (flushed_lsn < lsn_t(1000)) {
|
||||||
|
sql_print_error(
|
||||||
|
"InnoDB: Cannot create log file because"
|
||||||
|
" data files are corrupt or the"
|
||||||
|
" database was not shut down cleanly"
|
||||||
|
" after creating the data files.");
|
||||||
|
return srv_init_abort(DB_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
srv_log_file_found = log_file_found;
|
srv_log_file_size = srv_log_file_size_requested;
|
||||||
|
|
||||||
log_sys.log.open_file(get_log_file_path());
|
err = create_log_file(false, flushed_lsn, logfile0);
|
||||||
|
if (err == DB_SUCCESS) {
|
||||||
log_sys.log.create();
|
err = create_log_file_rename(flushed_lsn, logfile0);
|
||||||
|
|
||||||
if (!log_set_capacity(srv_log_file_size_requested)) {
|
|
||||||
return(srv_init_abort(DB_ERROR));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable checkpoints in the page cleaner. */
|
if (err != DB_SUCCESS) {
|
||||||
recv_sys.recovery_on = false;
|
return(srv_init_abort(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Suppress the message about
|
||||||
|
crash recovery. */
|
||||||
|
flushed_lsn = log_sys.get_lsn();
|
||||||
|
goto file_checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_checked:
|
file_checked:
|
||||||
/* Open log file and data files in the systemtablespace: we keep
|
/* Open data files in the systemtablespace: we keep
|
||||||
them open until database shutdown */
|
them open until database shutdown */
|
||||||
ut_d(fil_system.sys_space->recv_size = srv_sys_space_size_debug);
|
ut_d(fil_system.sys_space->recv_size = srv_sys_space_size_debug);
|
||||||
|
|
||||||
|
|
|
@ -1909,7 +1909,7 @@ int spider_conn_queue_loop_check(
|
||||||
loop_check_buf[lex_str.length] = '\0';
|
loop_check_buf[lex_str.length] = '\0';
|
||||||
DBUG_PRINT("info", ("spider param name=%s", lex_str.str));
|
DBUG_PRINT("info", ("spider param name=%s", lex_str.str));
|
||||||
loop_check = get_variable(&thd->user_vars, &lex_str, FALSE);
|
loop_check = get_variable(&thd->user_vars, &lex_str, FALSE);
|
||||||
if (!loop_check || loop_check->type != STRING_RESULT)
|
if (!loop_check || loop_check->type_handler()->result_type() != STRING_RESULT)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("spider client is not Spider"));
|
DBUG_PRINT("info", ("spider client is not Spider"));
|
||||||
lex_str.str = "";
|
lex_str.str = "";
|
||||||
|
|
|
@ -4913,7 +4913,7 @@ SPIDER_SHARE *spider_get_share(
|
||||||
((char *) lex_str.str)[lex_str.length] = '\0';
|
((char *) lex_str.str)[lex_str.length] = '\0';
|
||||||
DBUG_PRINT("info",("spider loop check param name=%s", lex_str.str));
|
DBUG_PRINT("info",("spider loop check param name=%s", lex_str.str));
|
||||||
loop_check = get_variable(&thd->user_vars, &lex_str, FALSE);
|
loop_check = get_variable(&thd->user_vars, &lex_str, FALSE);
|
||||||
if (loop_check && loop_check->type == STRING_RESULT)
|
if (loop_check && loop_check->type_handler()->result_type() == STRING_RESULT)
|
||||||
{
|
{
|
||||||
lex_str.length = top_share->path.length + spider_unique_id.length + 1;
|
lex_str.length = top_share->path.length + spider_unique_id.length + 1;
|
||||||
lex_str.str = loop_check_buf + buf_sz - top_share->path.length -
|
lex_str.str = loop_check_buf + buf_sz - top_share->path.length -
|
||||||
|
|
Loading…
Add table
Reference in a new issue