diff --git a/cmake/os/WindowsCache.cmake b/cmake/os/WindowsCache.cmake index 6cd19262a3c76..c1048661aaa32 100644 --- a/cmake/os/WindowsCache.cmake +++ b/cmake/os/WindowsCache.cmake @@ -242,7 +242,6 @@ SET(HAVE_TERMCAP_H CACHE INTERNAL "") SET(HAVE_TERMIOS_H CACHE INTERNAL "") SET(HAVE_TERMIO_H CACHE INTERNAL "") SET(HAVE_TERM_H CACHE INTERNAL "") -SET(HAVE_THR_SETCONCURRENCY CACHE INTERNAL "") SET(HAVE_THR_YIELD CACHE INTERNAL "") SET(HAVE_TIME 1 CACHE INTERNAL "") SET(HAVE_TIMES CACHE INTERNAL "") diff --git a/config.h.cmake b/config.h.cmake index e8712d16ba6a6..733c407af8e6f 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -232,7 +232,6 @@ #cmakedefine HAVE_STRTOUL 1 #cmakedefine HAVE_STRTOULL 1 #cmakedefine HAVE_TELL 1 -#cmakedefine HAVE_THR_SETCONCURRENCY 1 #cmakedefine HAVE_THR_YIELD 1 #cmakedefine HAVE_TIME 1 #cmakedefine HAVE_TIMES 1 diff --git a/configure.cmake b/configure.cmake index dbd77a6e00f11..c2706b5050265 100644 --- a/configure.cmake +++ b/configure.cmake @@ -418,7 +418,6 @@ CHECK_FUNCTION_EXISTS (strtoul HAVE_STRTOUL) CHECK_FUNCTION_EXISTS (strtoull HAVE_STRTOULL) CHECK_FUNCTION_EXISTS (strcasecmp HAVE_STRCASECMP) CHECK_FUNCTION_EXISTS (tell HAVE_TELL) -CHECK_FUNCTION_EXISTS (thr_setconcurrency HAVE_THR_SETCONCURRENCY) CHECK_FUNCTION_EXISTS (thr_yield HAVE_THR_YIELD) CHECK_FUNCTION_EXISTS (vasprintf HAVE_VASPRINTF) CHECK_FUNCTION_EXISTS (vsnprintf HAVE_VSNPRINTF) diff --git a/debian/control b/debian/control index 8685c2d8ea2ab..2f0264b68e5ea 100644 --- a/debian/control +++ b/debian/control @@ -30,8 +30,7 @@ Build-Depends: bison, liblz4-dev, liblzma-dev, liblzo2-dev, - libncurses5-dev (>= 5.0-6~), - libncurses5-dev:native (>= 5.0-6~), + libncurses-dev, libnuma-dev [linux-any], libpam0g-dev, libpcre2-dev, diff --git a/include/my_pthread.h b/include/my_pthread.h index b340d56e88f5e..ca32fecc064aa 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -147,9 +147,6 @@ int pthread_cancel(pthread_t thread); #ifndef _REENTRANT #define _REENTRANT #endif -#ifdef HAVE_THR_SETCONCURRENCY -#include /* Probably solaris */ -#endif #ifdef HAVE_SCHED_H #include #endif @@ -618,9 +615,6 @@ extern int my_rw_trywrlock(my_rw_lock_t *); #define GETHOSTBYADDR_BUFF_SIZE 2048 -#ifndef HAVE_THR_SETCONCURRENCY -#define thr_setconcurrency(A) pthread_dummy(0) -#endif #if !defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && ! defined(pthread_attr_setstacksize) #define pthread_attr_setstacksize(A,B) pthread_dummy(0) #endif diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index 14c752511c702..a5763a029ce47 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -531,7 +531,13 @@ struct st_mysql_plugin const char *author; /* plugin author (for I_S.PLUGINS) */ const char *descr; /* general descriptive text (for I_S.PLUGINS) */ int license; /* the plugin license (PLUGIN_LICENSE_XXX) */ - int (*init)(void *); /* the function to invoke when plugin is loaded */ + /* + The function to invoke when plugin is loaded. Plugin + initialisation done here should defer any ALTER TABLE queries to + after the ddl recovery is done, in the signal_ddl_recovery_done() + callback called by ha_signal_ddl_recovery_done(). + */ + int (*init)(void *); int (*deinit)(void *);/* the function to invoke when plugin is unloaded */ unsigned int version; /* plugin version (for I_S.PLUGINS) */ struct st_mysql_show_var *status_vars; @@ -555,7 +561,13 @@ struct st_maria_plugin const char *author; /* plugin author (for SHOW PLUGINS) */ const char *descr; /* general descriptive text (for SHOW PLUGINS ) */ int license; /* the plugin license (PLUGIN_LICENSE_XXX) */ - int (*init)(void *); /* the function to invoke when plugin is loaded */ + /* + The function to invoke when plugin is loaded. Plugin + initialisation done here should defer any ALTER TABLE queries to + after the ddl recovery is done, in the signal_ddl_recovery_done() + callback called by ha_signal_ddl_recovery_done(). + */ + int (*init)(void *); int (*deinit)(void *);/* the function to invoke when plugin is unloaded */ unsigned int version; /* plugin version (for SHOW PLUGINS) */ struct st_mysql_show_var *status_vars; diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index c22127f08074e..0be844fbd208d 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -634,8 +634,6 @@ int init_embedded_server(int argc, char **argv, char **groups) udf_init(); #endif - (void) thr_setconcurrency(concurrency); // 10 by default - if (flush_time && flush_time != ~(ulong) 0L) start_handle_manager(); diff --git a/mysql-test/include/have_normal_bzip.inc b/mysql-test/include/have_normal_zlib.inc similarity index 67% rename from mysql-test/include/have_normal_bzip.inc rename to mysql-test/include/have_normal_zlib.inc index 36c06274398c8..a4531e687bcec 100644 --- a/mysql-test/include/have_normal_bzip.inc +++ b/mysql-test/include/have_normal_zlib.inc @@ -1,9 +1,9 @@ --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 # in the test will not match the results from used compression library. if (`select length(COMPRESS(space(5000))) != 33`) { - skip Test skipped as standard bzip is needed; + skip Test skipped as standard zlib is needed; } diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 41d943e3522b5..c72717578cbd5 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -892,6 +892,12 @@ sub collect_one_test_case { } my @no_combs = grep { $test_combs{$_} == 1 } keys %test_combs; if (@no_combs) { + if ($::opt_skip_not_found) { + push @{$tinfo->{combinations}}, @no_combs; + $tinfo->{'skip'}= 1; + $tinfo->{'comment'}= "combination not found"; + return $tinfo; + } mtr_error("Could not run $name with '".( join(',', sort @no_combs))."' combination(s)"); } diff --git a/mysql-test/main/cast.test b/mysql-test/main/cast.test index ce4b1f6a5749e..5a0f87beb696d 100644 --- a/mysql-test/main/cast.test +++ b/mysql-test/main/cast.test @@ -768,14 +768,11 @@ INSERT INTO t1 VALUES (-1.0); SELECT * FROM t1; DROP TABLE t1; -#enable after MDEV-32645 is fixed ---disable_view_protocol SELECT CAST(-1e0 AS UNSIGNED); CREATE TABLE t1 (a BIGINT UNSIGNED); INSERT INTO t1 VALUES (-1e0); SELECT * FROM t1; DROP TABLE t1; ---enable_view_protocol SELECT CAST(-1e308 AS UNSIGNED); CREATE TABLE t1 (a BIGINT UNSIGNED); diff --git a/mysql-test/main/column_compression.test b/mysql-test/main/column_compression.test index 642399be1f650..5fa8192df3b8c 100644 --- a/mysql-test/main/column_compression.test +++ b/mysql-test/main/column_compression.test @@ -1,6 +1,6 @@ --source include/have_innodb.inc --source include/have_csv.inc ---source include/have_normal_bzip.inc +--source include/have_normal_zlib.inc let $MYSQLD_DATADIR= `select @@datadir`; diff --git a/mysql-test/main/column_compression_rpl.test b/mysql-test/main/column_compression_rpl.test index df8e889016b8b..18992f33f3c76 100644 --- a/mysql-test/main/column_compression_rpl.test +++ b/mysql-test/main/column_compression_rpl.test @@ -1,6 +1,6 @@ --source include/have_innodb.inc +--source include/have_normal_zlib.inc --source include/master-slave.inc ---source include/have_normal_bzip.inc --let $engine_type= myisam --let $engine_type2= innodb diff --git a/mysql-test/main/cte_nonrecursive.result b/mysql-test/main/cte_nonrecursive.result index 316e39b455ad4..88c2749294805 100644 --- a/mysql-test/main/cte_nonrecursive.result +++ b/mysql-test/main/cte_nonrecursive.result @@ -2636,4 +2636,49 @@ a 1 1 DROP TABLE t1; +# +# MDEV-31657: CTE with the same name as base table used twice +# in another CTE +# +create table t (a int); +insert into t values (3), (7), (1); +with +t as (select * from t), +cte as (select t1.a as t1a, t2.a as t2a from t as t1, t as t2 where t1.a=t2.a) +select * from cte; +t1a t2a +3 3 +7 7 +1 1 +create table s (a int); +insert into s values (1), (4), (7); +with +t as (select * from t), +s as (select a-1 as a from s), +cte as (select t.a as ta, s.a as sa from t, s where t.a=s.a +union +select t.a+1, s.a+1 from t, s where t.a=s.a+1) +select * from cte; +ta sa +3 3 +2 1 +8 7 +with +t as (select * from t), +cte as (select t.a as ta, s.a as sa from t, s where t.a=s.a +union +select t.a+1, s.a+1 from t, s where t.a=s.a), +s as (select a+10 as a from s) +select * from cte; +ta sa +1 1 +7 7 +2 2 +8 8 +drop table t,s; +with +t as (select * from t), +cte as (select t1.a as t1a, t2.a as t2a from t as t1, t as t2 where t1.a=t2.a) +select * from cte; +ERROR 42S02: Table 'test.t' doesn't exist # End of 10.4 tests diff --git a/mysql-test/main/cte_nonrecursive.test b/mysql-test/main/cte_nonrecursive.test index aa573a764549b..bebf02eafd937 100644 --- a/mysql-test/main/cte_nonrecursive.test +++ b/mysql-test/main/cte_nonrecursive.test @@ -1979,4 +1979,50 @@ SELECT * FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-31657: CTE with the same name as base table used twice +--echo # in another CTE +--echo # + +create table t (a int); +insert into t values (3), (7), (1); + +let $q1= +with +t as (select * from t), +cte as (select t1.a as t1a, t2.a as t2a from t as t1, t as t2 where t1.a=t2.a) +select * from cte; + +eval $q1; + +create table s (a int); +insert into s values (1), (4), (7); + +let $q2= +with +t as (select * from t), +s as (select a-1 as a from s), +cte as (select t.a as ta, s.a as sa from t, s where t.a=s.a + union + select t.a+1, s.a+1 from t, s where t.a=s.a+1) +select * from cte; + +eval $q2; + +let $q3= +with +t as (select * from t), +cte as (select t.a as ta, s.a as sa from t, s where t.a=s.a + union + select t.a+1, s.a+1 from t, s where t.a=s.a), +s as (select a+10 as a from s) +select * from cte; + +eval $q3; + +drop table t,s; + +--ERROR ER_NO_SUCH_TABLE +eval $q1; + --echo # End of 10.4 tests diff --git a/mysql-test/main/func_compress.test b/mysql-test/main/func_compress.test index 221dddd59f558..d18af140ed385 100644 --- a/mysql-test/main/func_compress.test +++ b/mysql-test/main/func_compress.test @@ -1,5 +1,5 @@ -- source include/have_compress.inc --- source include/have_normal_bzip.inc +-- source include/have_normal_zlib.inc # # Test for compress and uncompress functions: # diff --git a/mysql-test/main/gis.result b/mysql-test/main/gis.result index 99d41aad0f5a2..d8d424897fba6 100644 --- a/mysql-test/main/gis.result +++ b/mysql-test/main/gis.result @@ -5328,5 +5328,112 @@ SELECT BIT_XOR(a) FROM t1; ERROR HY000: Illegal parameter data type geometry for operation 'bit_xor(' 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 # diff --git a/mysql-test/main/gis.test b/mysql-test/main/gis.test index e68b1f140b22e..7b071acd2b058 100644 --- a/mysql-test/main/gis.test +++ b/mysql-test/main/gis.test @@ -3374,6 +3374,69 @@ SELECT BIT_OR(a) FROM t1; SELECT BIT_XOR(a) FROM 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 # End of 10.5 tests diff --git a/mysql-test/main/mysql_json_table_recreate.result b/mysql-test/main/mysql_json_table_recreate.result index 207dde9d8ad2c..a61377fe21d57 100644 --- a/mysql-test/main/mysql_json_table_recreate.result +++ b/mysql-test/main/mysql_json_table_recreate.result @@ -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! 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 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; 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; @@ -169,3 +175,67 @@ Total_Number_of_Tests Succesful_Tests String_is_valid_JSON drop table tempty; drop table mysql_json_test; 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 +# diff --git a/mysql-test/main/mysql_json_table_recreate.test b/mysql-test/main/mysql_json_table_recreate.test index a399b546591b2..a6f1d3194aeb1 100644 --- a/mysql-test/main/mysql_json_table_recreate.test +++ b/mysql-test/main/mysql_json_table_recreate.test @@ -51,6 +51,13 @@ show create table mysql_json_test; --error ER_TABLE_NEEDS_REBUILD 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 LOCK TABLES mysql_json_test WRITE; @@ -88,3 +95,69 @@ from mysql_json_test_big; drop table tempty; drop table mysql_json_test; 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 # diff --git a/mysql-test/main/mysqlbinlog_row_compressed.test b/mysql-test/main/mysqlbinlog_row_compressed.test index be9736347c96c..03868d3e6b35e 100644 --- a/mysql-test/main/mysqlbinlog_row_compressed.test +++ b/mysql-test/main/mysqlbinlog_row_compressed.test @@ -4,7 +4,7 @@ --source include/have_log_bin.inc --source include/have_binlog_format_row.inc ---source include/have_normal_bzip.inc +--source include/have_normal_zlib.inc # # diff --git a/mysql-test/main/mysqlbinlog_stmt_compressed.test b/mysql-test/main/mysqlbinlog_stmt_compressed.test index 08db2009d6067..4a65124339d7d 100644 --- a/mysql-test/main/mysqlbinlog_stmt_compressed.test +++ b/mysql-test/main/mysqlbinlog_stmt_compressed.test @@ -4,7 +4,7 @@ --source include/have_log_bin.inc --source include/have_binlog_format_statement.inc ---source include/have_normal_bzip.inc +--source include/have_normal_zlib.inc # # # mysqlbinlog: compressed query event diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result index 047a440960d14..b7fbc74a51bc4 100644 --- a/mysql-test/main/opt_trace.result +++ b/mysql-test/main/opt_trace.result @@ -12469,6 +12469,18 @@ json_detailed(json_extract(trace, '$**.in_to_subquery_conversion')) set in_predicate_conversion_threshold=@tmp; 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 # # diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test index 1a4f0c4b04165..f69a200f629b2 100644 --- a/mysql-test/main/opt_trace.test +++ b/mysql-test/main/opt_trace.test @@ -846,6 +846,20 @@ set in_predicate_conversion_threshold=@tmp; drop table t0; --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 # End of 10.5 tests --echo # diff --git a/mysql-test/main/subselect_nulls_innodb.result b/mysql-test/main/subselect_nulls_innodb.result new file mode 100644 index 0000000000000..2cab41760b314 --- /dev/null +++ b/mysql-test/main/subselect_nulls_innodb.result @@ -0,0 +1,27 @@ +# +# MDEV-32090 Index does not handle null-safe equals operator correctly in join +# +CREATE TEMPORARY TABLE t1 ( +`id` int(10) unsigned NOT NULL, +`number` int(10) unsigned DEFAULT 0, +`name` varchar(47) DEFAULT NULL, +`street` mediumint(8) unsigned DEFAULT NULL, +PRIMARY KEY (`id`), +KEY `streetNumber` (`street`,`number`,`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +INSERT INTO t1 (id, number, name, street) VALUES (100733476, 14, NULL, 1115569); +SELECT +b1.id +FROM +t1 b1 +INNER JOIN t1 b2 ON ( +b1.street = b2.street +AND b1.number <=> b2.number +AND b1.name <=> b2.name +); +id +100733476 +DROP TABLE t1; +# +# End of 10.11 tests +# diff --git a/mysql-test/main/subselect_nulls_innodb.test b/mysql-test/main/subselect_nulls_innodb.test new file mode 100644 index 0000000000000..79d572a2e0e3b --- /dev/null +++ b/mysql-test/main/subselect_nulls_innodb.test @@ -0,0 +1,32 @@ +--source include/have_innodb.inc + +--echo # +--echo # MDEV-32090 Index does not handle null-safe equals operator correctly in join +--echo # + +CREATE TEMPORARY TABLE t1 ( + `id` int(10) unsigned NOT NULL, + `number` int(10) unsigned DEFAULT 0, + `name` varchar(47) DEFAULT NULL, + `street` mediumint(8) unsigned DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `streetNumber` (`street`,`number`,`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + +INSERT INTO t1 (id, number, name, street) VALUES (100733476, 14, NULL, 1115569); + +SELECT + b1.id +FROM + t1 b1 + INNER JOIN t1 b2 ON ( + b1.street = b2.street + AND b1.number <=> b2.number + AND b1.name <=> b2.name + ); + +DROP TABLE t1; + +--echo # +--echo # End of 10.11 tests +--echo # diff --git a/mysql-test/main/type_float.result b/mysql-test/main/type_float.result index 9f01f22b3c770..877cdec864eb8 100644 --- a/mysql-test/main/type_float.result +++ b/mysql-test/main/type_float.result @@ -1171,6 +1171,43 @@ d 50 fdbl 123.456.789,12345678000000000000000000000000000000 fdec 123.456.789,12345678900000000000000000000000000000 # +# MDEV-32645 CAST(AS UNSIGNED) fails with --view-protocol +# +SELECT +CAST(-1e0 AS UNSIGNED), +CAST(--2e0 AS UNSIGNED), +CAST(---3e0 AS UNSIGNED), +CAST(----4e0 AS UNSIGNED); +CAST(-1e0 AS UNSIGNED) CAST(--2e0 AS UNSIGNED) CAST(---3e0 AS UNSIGNED) CAST(----4e0 AS UNSIGNED) +0 2 0 4 +Warnings: +Note 1916 Got overflow when converting '-1' to UNSIGNED BIGINT. Value truncated +Note 1916 Got overflow when converting '-3' to UNSIGNED BIGINT. Value truncated +EXPLAIN EXTENDED SELECT +CAST(-1e0 AS UNSIGNED), +CAST(--2e0 AS UNSIGNED), +CAST(---3e0 AS UNSIGNED), +CAST(----4e0 AS UNSIGNED); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select cast(-1e0 as unsigned) AS `CAST(-1e0 AS UNSIGNED)`,cast(2e0 as unsigned) AS `CAST(--2e0 AS UNSIGNED)`,cast(-3e0 as unsigned) AS `CAST(---3e0 AS UNSIGNED)`,cast(4e0 as unsigned) AS `CAST(----4e0 AS UNSIGNED)` +CREATE VIEW v1 AS SELECT +CAST(-1e0 AS UNSIGNED), +CAST(--2e0 AS UNSIGNED), +CAST(---3e0 AS UNSIGNED), +CAST(----4e0 AS UNSIGNED); +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(-1e0 as unsigned) AS `CAST(-1e0 AS UNSIGNED)`,cast(2e0 as unsigned) AS `CAST(--2e0 AS UNSIGNED)`,cast(-3e0 as unsigned) AS `CAST(---3e0 AS UNSIGNED)`,cast(4e0 as unsigned) AS `CAST(----4e0 AS UNSIGNED)` latin1 latin1_swedish_ci +SELECT * FROM v1; +CAST(-1e0 AS UNSIGNED) CAST(--2e0 AS UNSIGNED) CAST(---3e0 AS UNSIGNED) CAST(----4e0 AS UNSIGNED) +0 2 0 4 +Warnings: +Note 1916 Got overflow when converting '-1' to UNSIGNED BIGINT. Value truncated +Note 1916 Got overflow when converting '-3' to UNSIGNED BIGINT. Value truncated +DROP VIEW v1; +# # End of 10.4 tests # # diff --git a/mysql-test/main/type_float.test b/mysql-test/main/type_float.test index 12e3f070fdeb3..c90d8b8aa7907 100644 --- a/mysql-test/main/type_float.test +++ b/mysql-test/main/type_float.test @@ -716,6 +716,32 @@ $$ DELIMITER ;$$ --horizontal_results +--echo # +--echo # MDEV-32645 CAST(AS UNSIGNED) fails with --view-protocol +--echo # + +SELECT + CAST(-1e0 AS UNSIGNED), + CAST(--2e0 AS UNSIGNED), + CAST(---3e0 AS UNSIGNED), + CAST(----4e0 AS UNSIGNED); + +EXPLAIN EXTENDED SELECT + CAST(-1e0 AS UNSIGNED), + CAST(--2e0 AS UNSIGNED), + CAST(---3e0 AS UNSIGNED), + CAST(----4e0 AS UNSIGNED); + +CREATE VIEW v1 AS SELECT + CAST(-1e0 AS UNSIGNED), + CAST(--2e0 AS UNSIGNED), + CAST(---3e0 AS UNSIGNED), + CAST(----4e0 AS UNSIGNED); + +SHOW CREATE VIEW v1; +SELECT * FROM v1; +DROP VIEW v1; + --echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/suite/binlog/r/binlog_gis_user_var_stm.result b/mysql-test/suite/binlog/r/binlog_gis_user_var_stm.result new file mode 100644 index 0000000000000..e467c9c89b457 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_gis_user_var_stm.result @@ -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 */ diff --git a/mysql-test/suite/binlog/t/binlog_gis_user_var_stm.test b/mysql-test/suite/binlog/t/binlog_gis_user_var_stm.test new file mode 100644 index 0000000000000..7e789cd7ae44d --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_gis_user_var_stm.test @@ -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; diff --git a/mysql-test/suite/compat/oracle/t/column_compression.test b/mysql-test/suite/compat/oracle/t/column_compression.test index 01d4977ba961f..e8d55000bc62e 100644 --- a/mysql-test/suite/compat/oracle/t/column_compression.test +++ b/mysql-test/suite/compat/oracle/t/column_compression.test @@ -1,6 +1,6 @@ --source include/have_innodb.inc --source include/have_csv.inc ---source include/have_normal_bzip.inc +--source include/have_normal_zlib.inc SET sql_mode=ORACLE; diff --git a/mysql-test/suite/federated/update.result b/mysql-test/suite/federated/update.result new file mode 100644 index 0000000000000..1905f80ed71f1 --- /dev/null +++ b/mysql-test/suite/federated/update.result @@ -0,0 +1,36 @@ +connect master,127.0.0.1,root,,test,$MASTER_MYPORT,; +connect slave,127.0.0.1,root,,test,$SLAVE_MYPORT,; +connection master; +CREATE DATABASE federated; +connection slave; +CREATE DATABASE federated; +# +# MDEV-32984 Update federated table and column privileges +# +connection slave; +create database db1; +create user my@localhost identified by '1qaz2wsx'; +create table db1.t1 ( +f1 int auto_increment primary key, +f2 varchar(50), +f3 varchar(50), +unique (f2) +); +grant insert, select (f1, f2, f3), update (f3) on db1.t1 to my@localhost; +connection master; +create table tt1 engine=federated connection='mysql://my:1qaz2wsx@localhost:$SLAVE_MYPORT/db1/t1'; +insert into tt1 (f2,f3) values ('test','123'); +select * from tt1; +f1 f2 f3 +1 test 123 +update tt1 set f3='123456' where f2='test'; +drop table tt1; +connection slave; +drop database db1; +drop user my@localhost; +connection master; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; +connection slave; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/suite/federated/update.test b/mysql-test/suite/federated/update.test new file mode 100644 index 0000000000000..5a0414f1e1a0d --- /dev/null +++ b/mysql-test/suite/federated/update.test @@ -0,0 +1,32 @@ +source include/federated.inc; +source have_federatedx.inc; + +--echo # +--echo # MDEV-32984 Update federated table and column privileges +--echo # +connection slave; +create database db1; +create user my@localhost identified by '1qaz2wsx'; +create table db1.t1 ( + f1 int auto_increment primary key, + f2 varchar(50), + f3 varchar(50), + unique (f2) +); +grant insert, select (f1, f2, f3), update (f3) on db1.t1 to my@localhost; + +connection master; +evalp create table tt1 engine=federated connection='mysql://my:1qaz2wsx@localhost:$SLAVE_MYPORT/db1/t1'; +insert into tt1 (f2,f3) values ('test','123'); +select * from tt1; +update tt1 set f3='123456' where f2='test'; + +drop table tt1; + +connection slave; +drop database db1; +drop user my@localhost; + +source include/federated_cleanup.inc; + + diff --git a/mysql-test/suite/innodb/r/doublewrite.result b/mysql-test/suite/innodb/r/doublewrite.result index 0c4f2c3fe6577..65ff203a28e23 100644 --- a/mysql-test/suite/innodb/r/doublewrite.result +++ b/mysql-test/suite/innodb/r/doublewrite.result @@ -1,7 +1,7 @@ # # 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; insert into t1 values(1, repeat('#',12)); insert into t1 values(2, repeat('+',12)); @@ -19,6 +19,7 @@ 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 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 //////////// 4 ------------ 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; # End of 10.5 tests diff --git a/mysql-test/suite/innodb/r/lock_move_wait_lock_race.result b/mysql-test/suite/innodb/r/lock_move_wait_lock_race.result index 572fbc9b1d191..c78102d9c3b1d 100644 --- a/mysql-test/suite/innodb/r/lock_move_wait_lock_race.result +++ b/mysql-test/suite/innodb/r/lock_move_wait_lock_race.result @@ -1,4 +1,5 @@ -CREATE TABLE t (pk int PRIMARY KEY, c varchar(10)) ENGINE=InnoDB; +CREATE TABLE t (pk int PRIMARY KEY, c varchar(10)) +STATS_PERSISTENT=0 ENGINE=InnoDB; INSERT INTO t VALUES (10, "0123456789"); connection default; BEGIN; diff --git a/mysql-test/suite/innodb/r/log_file_name.result b/mysql-test/suite/innodb/r/log_file_name.result index 7ac212916de00..1839c9bc1e0ae 100644 --- a/mysql-test/suite/innodb/r/log_file_name.result +++ b/mysql-test/suite/innodb/r/log_file_name.result @@ -1,3 +1,4 @@ +call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:"); FLUSH TABLES; CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; # restart diff --git a/mysql-test/suite/innodb/t/doublewrite.test b/mysql-test/suite/innodb/t/doublewrite.test index 33813dabdc4a3..541e4d23a1914 100644 --- a/mysql-test/suite/innodb/t/doublewrite.test +++ b/mysql-test/suite/innodb/t/doublewrite.test @@ -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: Inconsistent tablespace ID in .*t1\\.ibd"); 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 let INNODB_PAGE_SIZE=`select @@innodb_page_size`; @@ -24,7 +25,7 @@ let MYSQLD_DATADIR=`select @@datadir`; let ALGO=`select @@innodb_checksum_algorithm`; 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; insert into t1 values(1, repeat('#',12)); @@ -38,7 +39,7 @@ commit work; SET GLOBAL innodb_fast_shutdown = 0; let $shutdown_timeout=; --source include/restart_mysqld.inc - +--source ../include/no_checkpoint_start.inc connect (dml,localhost,root,,); XA START 'x'; insert into t1 values (6, repeat('%', @@innodb_page_size/2)); @@ -50,8 +51,8 @@ connection default; flush table t1 for export; let $restart_parameters=; -let $shutdown_timeout=0; ---source include/shutdown_mysqld.inc +--let CLEANUP_IF_CHECKPOINT=drop table t1, unexpected_checkpoint; +--source ../include/no_checkpoint_end.inc perl; 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'; check table 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; --echo # End of 10.5 tests diff --git a/mysql-test/suite/innodb/t/doublewrite_debug.test b/mysql-test/suite/innodb/t/doublewrite_debug.test index ebae84e2211b1..ab7fd8eba22e6 100644 --- a/mysql-test/suite/innodb/t/doublewrite_debug.test +++ b/mysql-test/suite/innodb/t/doublewrite_debug.test @@ -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: Checksum mismatch in datafile: "); 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 let INNODB_PAGE_SIZE=`select @@innodb_page_size`; diff --git a/mysql-test/suite/innodb/t/lock_move_wait_lock_race.test b/mysql-test/suite/innodb/t/lock_move_wait_lock_race.test index 3a04c7127c821..0f88f8d9d0f09 100644 --- a/mysql-test/suite/innodb/t/lock_move_wait_lock_race.test +++ b/mysql-test/suite/innodb/t/lock_move_wait_lock_race.test @@ -3,7 +3,8 @@ --source include/have_debug.inc --source include/have_debug_sync.inc -CREATE TABLE t (pk int PRIMARY KEY, c varchar(10)) ENGINE=InnoDB; +CREATE TABLE t (pk int PRIMARY KEY, c varchar(10)) +STATS_PERSISTENT=0 ENGINE=InnoDB; INSERT INTO t VALUES (10, "0123456789"); --connection default diff --git a/mysql-test/suite/innodb/t/log_file_name.test b/mysql-test/suite/innodb/t/log_file_name.test index f95a56c7e8b04..9707a1535af69 100644 --- a/mysql-test/suite/innodb/t/log_file_name.test +++ b/mysql-test/suite/innodb/t/log_file_name.test @@ -7,6 +7,7 @@ # Embedded server does not support crashing --source include/not_embedded.inc +call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:"); FLUSH TABLES; CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; @@ -172,6 +173,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: Attempted to open a previously opened tablespace"); call mtr.add_suppression("InnoDB: Recovery cannot access file"); +call mtr.add_suppression("InnoDB: Cannot read first page in datafile:"); FLUSH TABLES; --enable_query_log diff --git a/mysql-test/suite/innodb/t/row_size_error_log_warnings_3.test b/mysql-test/suite/innodb/t/row_size_error_log_warnings_3.test index dab9bcfa86429..24029a48aa430 100644 --- a/mysql-test/suite/innodb/t/row_size_error_log_warnings_3.test +++ b/mysql-test/suite/innodb/t/row_size_error_log_warnings_3.test @@ -1,7 +1,7 @@ --source include/have_innodb.inc --source include/have_sequence.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."); diff --git a/mysql-test/suite/rpl/r/rpl_gis_user_var.result b/mysql-test/suite/rpl/r/rpl_gis_user_var.result new file mode 100644 index 0000000000000..c6aab9e03f0f3 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_gis_user_var.result @@ -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 diff --git a/mysql-test/suite/rpl/t/rpl_gis_user_var.test b/mysql-test/suite/rpl/t/rpl_gis_user_var.test new file mode 100644 index 0000000000000..8edd8cb930939 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gis_user_var.test @@ -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 diff --git a/mysql-test/suite/sql_sequence/alter.result b/mysql-test/suite/sql_sequence/alter.result index ae95bfb9cc1fb..75da828c59c79 100644 --- a/mysql-test/suite/sql_sequence/alter.result +++ b/mysql-test/suite/sql_sequence/alter.result @@ -253,6 +253,55 @@ NEXTVAL(s) 1 DROP SEQUENCE s; # +# MDEV-33169 Alter sequence 2nd ps fails while alter sequence 2nd time (no ps) succeeds +# +create sequence s; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM +alter sequence s maxvalue 123; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 123 increment by 1 cache 1000 nocycle ENGINE=MyISAM +alter sequence s maxvalue 123; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 123 increment by 1 cache 1000 nocycle ENGINE=MyISAM +drop sequence s; +create sequence s; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM +prepare stmt from 'alter sequence s maxvalue 123'; +execute stmt; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 123 increment by 1 cache 1000 nocycle ENGINE=MyISAM +execute stmt; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 123 increment by 1 cache 1000 nocycle ENGINE=MyISAM +deallocate prepare stmt; +drop sequence s; +create sequence s; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM +create procedure p() alter sequence s maxvalue 123; +call p; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 123 increment by 1 cache 1000 nocycle ENGINE=MyISAM +call p; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 123 increment by 1 cache 1000 nocycle ENGINE=MyISAM +drop procedure p; +drop sequence s; +# +# End of 10.4 tests +# +# # MDEV-31607 ER_DUP_KEY in mysql.table_stats upon REANME on sequence # CREATE SEQUENCE s1 ENGINE=InnoDB; @@ -266,3 +315,6 @@ s2 CREATE SEQUENCE `s2` start with 1 minvalue 1 maxvalue 9223372036854775806 inc DROP SEQUENCE s2; RENAME TABLE s1 TO s2; DROP SEQUENCE s2; +# +# End of 10.6 tests +# diff --git a/mysql-test/suite/sql_sequence/alter.test b/mysql-test/suite/sql_sequence/alter.test index 20ac6b2cb923a..7b14055d8922a 100644 --- a/mysql-test/suite/sql_sequence/alter.test +++ b/mysql-test/suite/sql_sequence/alter.test @@ -167,6 +167,41 @@ ALTER TABLE s ORDER BY cache_size; SELECT NEXTVAL(s); DROP SEQUENCE s; +--echo # +--echo # MDEV-33169 Alter sequence 2nd ps fails while alter sequence 2nd time (no ps) succeeds +--echo # +create sequence s; +show create sequence s; +alter sequence s maxvalue 123; +show create sequence s; +alter sequence s maxvalue 123; +show create sequence s; +drop sequence s; + +create sequence s; +show create sequence s; +prepare stmt from 'alter sequence s maxvalue 123'; +execute stmt; +show create sequence s; +execute stmt; +show create sequence s; +deallocate prepare stmt; +drop sequence s; + +create sequence s; +show create sequence s; +create procedure p() alter sequence s maxvalue 123; +call p; +show create sequence s; +call p; +show create sequence s; +drop procedure p; +drop sequence s; + +--echo # +--echo # End of 10.4 tests +--echo # + --echo # --echo # MDEV-31607 ER_DUP_KEY in mysql.table_stats upon REANME on sequence --echo # @@ -180,3 +215,7 @@ RENAME TABLE s1 TO s2; DROP SEQUENCE s2; --enable_ps2_protocol + +--echo # +--echo # End of 10.6 tests +--echo # diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index b98775e109911..4e2db2035885d 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -786,7 +786,6 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) mysql_mutex_unlock(&LOCK_thread_count); DBUG_PRINT("info",("signal thread created")); - thr_setconcurrency(3); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); printf("Main thread: %s\n",my_thread_name()); for (i=0 ; i < 2 ; i++) diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index c1ec062309bcd..214ff01bfbf3a 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -1783,9 +1783,6 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) error,errno); exit(1); } -#endif -#ifdef HAVE_THR_SETCONCURRENCY - (void) thr_setconcurrency(2); #endif for (i=0 ; i < array_elements(lock_counts) ; i++) { diff --git a/mysys/thr_timer.c b/mysys/thr_timer.c index f87c1f755557c..d3627fea9830e 100644 --- a/mysys/thr_timer.c +++ b/mysys/thr_timer.c @@ -533,7 +533,6 @@ static void run_test() mysql_mutex_init(0, &LOCK_thread_count, MY_MUTEX_INIT_FAST); mysql_cond_init(0, &COND_thread_count, NULL); - thr_setconcurrency(3); pthread_attr_init(&thr_attr); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); printf("Main thread: %s\n",my_thread_name()); diff --git a/plugin/auth_pam/testing/pam_mariadb_mtr.c b/plugin/auth_pam/testing/pam_mariadb_mtr.c index 108aeb941ac88..de34f5d8866b9 100644 --- a/plugin/auth_pam/testing/pam_mariadb_mtr.c +++ b/plugin/auth_pam/testing/pam_mariadb_mtr.c @@ -10,8 +10,8 @@ #include #include -#include #include +#include #define N 3 diff --git a/plugin/disks/information_schema_disks.cc b/plugin/disks/information_schema_disks.cc index 18195b910444c..c97d46be03f4d 100644 --- a/plugin/disks/information_schema_disks.cc +++ b/plugin/disks/information_schema_disks.cc @@ -19,10 +19,14 @@ #include #if defined(HAVE_GETMNTENT) #include +#elif defined(HAVE_SYS_MNTENT) +#include #elif !defined(HAVE_GETMNTINFO_TAKES_statvfs) /* getmntinfo (the not NetBSD variants) */ #include +#if defined(HAVE_SYS_UCRED) #include +#endif #include #endif #if defined(HAVE_GETMNTENT_IN_SYS_MNTAB) diff --git a/plugin/type_mysql_json/type.cc b/plugin/type_mysql_json/type.cc index a39c4ad200690..331e3bb26ab3e 100644 --- a/plugin/type_mysql_json/type.cc +++ b/plugin/type_mysql_json/type.cc @@ -37,6 +37,11 @@ class Type_handler_mysql_json: public Type_handler_blob Field *make_table_field(MEM_ROOT *, const LEX_CSTRING *, const Record_addr &, const Type_all_attributes &, 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, Column_definition *def, const Field *field) const override; @@ -74,7 +79,7 @@ class Field_mysql_json: public Field_blob bool parse_mysql(String *dest, const char *data, size_t length) const; bool send(Protocol *protocol) { return Field::send(protocol); } 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 */ Compression_method *compression_method() const { return (Compression_method*)1; } }; diff --git a/plugin/user_variables/user_variables.cc b/plugin/user_variables/user_variables.cc index df2ab4af1f89d..79c9670435480 100644 --- a/plugin/user_variables/user_variables.cc +++ b/plugin/user_variables/user_variables.cc @@ -79,9 +79,9 @@ static int user_variables_fill(THD *thd, TABLE_LIST *tables, COND *cond) else return 1; - const LEX_CSTRING *tmp= var->unsigned_flag ? - &unsigned_result_types[var->type] : - &result_types[var->type]; + const LEX_CSTRING *tmp= var->type_handler()->is_unsigned() ? + &unsigned_result_types[var->type_handler()->result_type()] : + &result_types[var->type_handler()->result_type()]; field[2]->store(tmp->str, tmp->length, system_charset_info); if (var->charset()) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index a4445612bebbf..177cbf52c6ae1 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -192,21 +192,38 @@ $opt{quiet} = 0 if $opt{debug}; $opt{allowold} = 1 if $opt{keepold}; # --- connect to the database --- +## Socket takes precedence. my $dsn; -$dsn = ";host=" . (defined($opt{host}) ? $opt{host} : "localhost"); -$dsn .= ";port=$opt{port}" if $opt{port}; -$dsn .= ";mariadb_socket=$opt{socket}" if $opt{socket}; +my $prefix= 'mysql'; -# use mariadb_read_default_group=mysqlhotcopy so that [client] and -# [mysqlhotcopy] groups will be read from standard options files. +if (eval {DBI->install_driver("MariaDB")}) { + $dsn ="DBI:MariaDB:;"; + $prefix= 'mariadb'; +} +else { + $dsn = "DBI:mysql:;"; +} -my $dbh = DBI->connect("DBI:MariaDB:$dsn;mariadb_read_default_group=mysqlhotcopy", - $opt{user}, $opt{password}, +if ($opt{socket} and -S $opt{socket}) +{ + $dsn .= "${prefix}_socket=$opt{socket}"; +} +else { - RaiseError => 1, - PrintError => 0, - AutoCommit => 1, -}); + $dsn .= "host=" . $opt{host}; + if ($opt{host} ne "localhost") + { + $dsn .= ";port=". $opt{port}; + } +} + +$dsn .= ";mariadb_read_default_group=mysqlhotcopy"; + +# use mariadb_read_default_group=mysqlhotcopy so that [client] and +# [mysqlhotcopy] groups will be read from standard options files. +# make the connection to MariaDB +my $dbh= DBI->connect($dsn, $opt{user}, $opt{password}, { RaiseError => 1, PrintError => 0}) || + die("Can't make a connection to the MariaDB server.\n The error: $DBI::errstr"); # --- check that checkpoint table exists if specified --- if ( $opt{checkpoint} ) { @@ -274,6 +291,8 @@ if ( defined $opt{regexp} ) { $sth_dbs->execute; while ( my ($db_name) = $sth_dbs->fetchrow_array ) { next if $db_name =~ m/^information_schema$/i; + next if $db_name =~ m/^performance_schema$/i; + next if $db_name =~ m/^sys$/i; push @db_desc, { 'src' => $db_name, 't_regex' => $t_regex } if ( $db_name =~ m/$opt{regexp}/o ); } } diff --git a/sql/debug.cc b/sql/debug.cc index a24cc4e407e35..38131232487ac 100644 --- a/sql/debug.cc +++ b/sql/debug.cc @@ -40,7 +40,8 @@ bool debug_decrement_counter(const LEX_CSTRING *name) THD *thd= current_thd; user_var_entry *entry= (user_var_entry*) 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; (*(ulonglong*) entry->value)= (*(ulonglong*) entry->value)-1; return !*(ulonglong*) entry->value; diff --git a/sql/handler.cc b/sql/handler.cc index 2eb5b1e03339b..0270e20620315 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1001,7 +1001,8 @@ static my_bool signal_ddl_recovery_done(THD *, plugin_ref plugin, void *) { handlerton *hton= plugin_hton(plugin); if (hton->signal_ddl_recovery_done) - (hton->signal_ddl_recovery_done)(hton); + if ((hton->signal_ddl_recovery_done)(hton)) + plugin_ref_to_int(plugin)->state= PLUGIN_IS_DELETED; return 0; } diff --git a/sql/handler.h b/sql/handler.h index d9b02978b949c..b0777347cf3e3 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1498,7 +1498,7 @@ struct handlerton const LEX_CUSTRING *version, ulonglong create_id); /* Called for all storage handlers after ddl recovery is done */ - void (*signal_ddl_recovery_done)(handlerton *hton); + int (*signal_ddl_recovery_done)(handlerton *hton); /* Called at startup to update default engine costs */ void (*update_optimizer_costs)(OPTIMIZER_COSTS *costs); diff --git a/sql/item.cc b/sql/item.cc index f6fdc115746a7..0078fa13d5c98 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7057,7 +7057,25 @@ Item *Item_float::neg(THD *thd) else if (value < 0 && max_length) max_length--; value= -value; - presentation= 0; + if (presentation) + { + if (*presentation == '-') + { + // Strip double minus: -(-1) -> '1' instead of '--1' + presentation++; + } + else + { + size_t presentation_length= strlen(presentation); + if (char *tmp= (char*) thd->alloc(presentation_length + 2)) + { + tmp[0]= '-'; + // Copy with the trailing '\0' + memcpy(tmp + 1, presentation, presentation_length + 1); + presentation= tmp; + } + } + } name= null_clex_str; return this; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 9b6d63685ff33..dd056ac4d689f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4651,7 +4651,6 @@ user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name, entry->length=0; entry->update_query_id=0; entry->set_charset(NULL); - entry->unsigned_flag= 0; /* If we are here, we were called from a SET or a query which sets a variable. Imagine it is this: @@ -4663,7 +4662,7 @@ user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name, by Item_func_get_user_var (because that's not necessary). */ 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); if (my_hash_insert(hash,(uchar*) entry)) { @@ -4739,9 +4738,12 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref) switch (args[0]->result_type()) { case STRING_RESULT: case TIME_RESULT: - set_handler(type_handler_long_blob. - type_handler_adjusted_to_max_octet_length(max_length, - collation.collation)); + if (args[0]->field_type() == MYSQL_TYPE_GEOMETRY) + set_handler(args[0]->type_handler()); + else + set_handler(type_handler_long_blob. + type_handler_adjusted_to_max_octet_length(max_length, + collation.collation)); break; case REAL_RESULT: set_handler(&type_handler_double); @@ -4866,9 +4868,9 @@ bool Item_func_set_user_var::register_field_in_bitmap(void *arg) bool update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, - Item_result type, CHARSET_INFO *cs, - bool unsigned_arg) + const Type_handler *th, CHARSET_INFO *cs) { + entry->set_handler(th); if (set_null) { char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry)); @@ -4879,7 +4881,7 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, } else { - if (type == STRING_RESULT) + if (th->result_type() == STRING_RESULT) length++; // Store strings with end \0 if (length <= extra_size) { @@ -4908,20 +4910,18 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, return 1; } } - if (type == STRING_RESULT) + if (th->result_type() == STRING_RESULT) { length--; // Fix length change above entry->value[length]= 0; // Store end \0 } if (length) memmove(entry->value, ptr, length); - if (type == DECIMAL_RESULT) + if (th->result_type() == DECIMAL_RESULT) ((my_decimal*)entry->value)->fix_buffer_pointer(); entry->length= length; entry->set_charset(cs); - entry->unsigned_flag= unsigned_arg; } - entry->type=type; #ifdef USER_VAR_TRACKING #ifndef EMBEDDED_LIBRARY THD *thd= current_thd; @@ -4934,9 +4934,8 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, bool Item_func_set_user_var::update_hash(void *ptr, size_t length, - Item_result res_type, - CHARSET_INFO *cs, - bool unsigned_arg) + const Type_handler *th, + CHARSET_INFO *cs) { /* If we set a variable explicitly to NULL then keep the old @@ -4950,9 +4949,8 @@ Item_func_set_user_var::update_hash(void *ptr, size_t length, else null_value= args[0]->null_value; if (null_value && null_item) - res_type= m_var_entry->type; // Don't change type of item - if (::update_hash(m_var_entry, null_value, - ptr, length, res_type, cs, unsigned_arg)) + th= m_var_entry->type_handler(); // Don't change type of item + if (::update_hash(m_var_entry, null_value, ptr, length, th, cs)) { null_value= 1; return 1; @@ -4968,7 +4966,7 @@ double user_var_entry::val_real(bool *null_value) if ((*null_value= (value == 0))) return 0.0; - switch (type) { + switch (type_handler()->result_type()) { case REAL_RESULT: return *(double*) value; case INT_RESULT: @@ -4993,7 +4991,7 @@ longlong user_var_entry::val_int(bool *null_value) const if ((*null_value= (value == 0))) return 0; - switch (type) { + switch (type_handler()->result_type()) { case REAL_RESULT: return (longlong) *(double*) value; case INT_RESULT: @@ -5022,12 +5020,12 @@ String *user_var_entry::val_str(bool *null_value, String *str, if ((*null_value= (value == 0))) return (String*) 0; - switch (type) { + switch (type_handler()->result_type()) { case REAL_RESULT: str->set_real(*(double*) value, decimals, charset()); break; case INT_RESULT: - if (!unsigned_flag) + if (!type_handler()->is_unsigned()) str->set(*(longlong*) value, charset()); else str->set(*(ulonglong*) value, charset()); @@ -5054,7 +5052,7 @@ my_decimal *user_var_entry::val_decimal(bool *null_value, my_decimal *val) if ((*null_value= (value == 0))) return 0; - switch (type) { + switch (type_handler()->result_type()) { case REAL_RESULT: double2my_decimal(E_DEC_FATAL_ERROR, *(double*) value, val); break; @@ -5193,33 +5191,37 @@ Item_func_set_user_var::update() case REAL_RESULT: { res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal), - REAL_RESULT, &my_charset_numeric, 0); + &type_handler_double, &my_charset_numeric); break; } case INT_RESULT: { 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; } case STRING_RESULT: { 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 res= update_hash((void*) save_result.vstr->ptr(), - save_result.vstr->length(), STRING_RESULT, - save_result.vstr->charset(), 0); + save_result.vstr->length(), + field_type() == MYSQL_TYPE_GEOMETRY ? + type_handler() : &type_handler_long_blob, + save_result.vstr->charset()); break; } case DECIMAL_RESULT: { 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 res= update_hash((void*) save_result.vdec, - sizeof(my_decimal), DECIMAL_RESULT, - &my_charset_numeric, 0); + sizeof(my_decimal), &type_handler_newdecimal, + &my_charset_numeric); break; } case ROW_RESULT: @@ -5611,9 +5613,8 @@ get_var_with_binlog(THD *thd, enum_sql_command sql_command, user_var_event->value= (char*) user_var_event + ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)); 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->unsigned_flag= var_entry->unsigned_flag; if (!var_entry->value) { /* NULL value*/ @@ -5655,9 +5656,9 @@ bool Item_func_get_user_var::fix_length_and_dec(THD *thd) */ 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; - switch (m_var_entry->type) { + switch (m_var_entry->type_handler()->result_type()) { case REAL_RESULT: collation.set(&my_charset_numeric, DERIVATION_NUMERIC); fix_char_length(DBL_DIG + 8); @@ -5676,6 +5677,8 @@ bool Item_func_get_user_var::fix_length_and_dec(THD *thd) collation.set(m_var_entry->charset(), DERIVATION_IMPLICIT); max_length= MAX_BLOB_WIDTH - 1; 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; case DECIMAL_RESULT: collation.set(&my_charset_numeric, DERIVATION_NUMERIC); @@ -5748,7 +5751,7 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref) DBUG_ASSERT(thd->lex->exchange); if (!(entry= get_variable(&thd->user_vars, &org_name, 1))) return TRUE; - entry->type= STRING_RESULT; + entry->set_handler(&type_handler_long_blob); /* Let us set the same collation which is used for loading of fields in LOAD DATA INFILE. @@ -5764,15 +5767,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) { - ::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, CHARSET_INFO* cs) { - ::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs, - 0 /* unsigned_arg */); + ::update_hash(entry, FALSE, (void*)str, length, &type_handler_long_blob, cs); } diff --git a/sql/item_func.h b/sql/item_func.h index 8ff22588efc6a..1f185eff8693f 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -3447,8 +3447,8 @@ class Item_func_set_user_var :public Item_func_user_var String *str_result(String *str) override; my_decimal *val_decimal_result(my_decimal *) override; bool is_null_result() override; - bool update_hash(void *ptr, size_t length, enum Item_result type, - CHARSET_INFO *cs, bool unsigned_arg); + bool update_hash(void *ptr, size_t length, const Type_handler *th, + CHARSET_INFO *cs); bool send(Protocol *protocol, st_value *buffer) override; void make_send_field(THD *thd, Send_field *tmp_field) override; bool check(bool use_result_field); @@ -4295,7 +4295,6 @@ double my_double_round(double value, longlong dec, bool dec_unsigned, extern bool volatile mqh_used; bool update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, - Item_result type, CHARSET_INFO *cs, - bool unsigned_arg); + const Type_handler *th, CHARSET_INFO *cs); #endif /* ITEM_FUNC_INCLUDED */ diff --git a/sql/log.cc b/sql/log.cc index a9f59c8c9a1a2..6a26bb1b496a1 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6984,18 +6984,12 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) BINLOG_USER_VAR_EVENT *user_var_event; 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_event->user_var_event->name.length, user_var_event->value, user_var_event->length, - user_var_event->type, - user_var_event->charset_number, - flags, + user_var_event->th->user_var_log_event_data_type( + user_var_event->charset_number), using_trans, direct); if (write_event(&e, cache_data, file)) diff --git a/sql/log_event.cc b/sql/log_event.cc index cd15bbb5e50e7..aebacbe96234c 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2704,6 +2704,41 @@ XA_prepare_log_event(const uchar *buf, 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(const uchar *buf, uint event_len, const Format_description_log_event* description_event) @@ -2713,7 +2748,8 @@ User_var_log_event(const uchar *buf, uint event_len, #endif { 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(buf) + event_len; /* The Post-Header is empty. The Variable Data part begins immediately. */ buf+= description_event->common_header_len + @@ -2741,11 +2777,8 @@ User_var_log_event(const uchar *buf, uint event_len, buf+= UV_NAME_LEN_SIZE + name_len; is_null= (bool) *buf; - flags= User_var_log_event::UNDEF_F; // defaults to UNDEF_F if (is_null) { - type= STRING_RESULT; - charset_number= my_charset_bin.number; val_len= 0; val= 0; } @@ -2760,8 +2793,8 @@ User_var_log_event(const uchar *buf, uint event_len, goto err; } - type= (Item_result) buf[UV_VAL_IS_NULL]; - charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE); + m_type= (Item_result) buf[UV_VAL_IS_NULL]; + 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 + UV_CHARSET_NUMBER_SIZE); @@ -2774,20 +2807,14 @@ User_var_log_event(const uchar *buf, uint event_len, the flags value. 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; - if (bytes_read > event_len) + const char *pos= val + val_len; + if (pos > buf_end || unpack_optional_attributes(pos, buf_end)) { error= true; 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: diff --git a/sql/log_event.h b/sql/log_event.h index df8addddea02f..5508c278f459b 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -57,6 +57,8 @@ #include "rpl_gtid.h" +#include "log_event_data_type.h" + /* Forward declarations */ #ifndef MYSQL_CLIENT class String; @@ -2943,33 +2945,27 @@ class XA_prepare_log_event: public Xid_apply_log_event @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: - enum { - UNDEF_F= 0, - UNSIGNED_F= 1 - }; const char *name; size_t name_len; const char *val; size_t val_len; - Item_result type; - uint charset_number; bool is_null; - uchar flags; #ifdef MYSQL_SERVER bool deferred; query_id_t query_id; 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, - Item_result type_arg, - uint charset_number_arg, uchar flags_arg, + const Log_event_data_type &data_type, bool using_trans, bool direct) :Log_event(thd_arg, 0, using_trans), + Log_event_data_type(data_type), name(name_arg), name_len(name_len_arg), val(val_arg), - val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg), - flags(flags_arg), deferred(false) + val_len(val_len_arg), + deferred(false) { is_null= !val; if (direct) diff --git a/sql/log_event_client.cc b/sql/log_event_client.cc index 2a224ef5c7c1b..3529afa97a0dd 100644 --- a/sql/log_event_client.cc +++ b/sql/log_event_client.cc @@ -2372,7 +2372,7 @@ bool User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) } else { - switch (type) { + switch (m_type) { case REAL_RESULT: double real_val; char real_buf[FMT_G_BUFSIZE(14)]; @@ -2384,8 +2384,7 @@ bool User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) break; case INT_RESULT: char int_buf[22]; - longlong10_to_str(uint8korr(val), int_buf, - ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10)); + longlong10_to_str(uint8korr(val), int_buf, is_unsigned() ? 10 : -10); if (my_b_printf(&cache, ":=%s%s\n", int_buf, print_event_info->delimiter)) goto err; @@ -2440,7 +2439,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 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 thing we can do here. diff --git a/sql/log_event_data_type.h b/sql/log_event_data_type.h new file mode 100644 index 0000000000000..e3b2039a63c5d --- /dev/null +++ b/sql/log_event_data_type.h @@ -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 diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 3993ec933b528..306aa7c29f732 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -3848,11 +3848,16 @@ bool XA_prepare_log_event::write() #if defined(HAVE_REPLICATION) static bool 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('@') || 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) @@ -3862,14 +3867,15 @@ void User_var_log_event::pack_info(Protocol* protocol) char buf_mem[FN_REFLEN+7]; String buf(buf_mem, sizeof(buf_mem), system_charset_info); 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)) return; protocol->store(buf.ptr(), buf.length(), &my_charset_bin); } else { - switch (type) { + switch (m_type) { case REAL_RESULT: { double real_val; @@ -3878,7 +3884,8 @@ void User_var_log_event::pack_info(Protocol* protocol) String buf(buf_mem, sizeof(buf_mem), system_charset_info); float8get(real_val, val); 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, MY_GCVT_MAX_FIELD_WIDTH, buf2, NULL))) return; @@ -3891,10 +3898,11 @@ void User_var_log_event::pack_info(Protocol* protocol) char buf_mem[FN_REFLEN + 22]; String buf(buf_mem, sizeof(buf_mem), system_charset_info); 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, longlong10_to_str(uint8korr(val), buf2, - ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10))-buf2)) + (is_unsigned() ? 10 : -10))-buf2)) return; protocol->store(buf.ptr(), buf.length(), &my_charset_bin); break; @@ -3907,7 +3915,8 @@ void User_var_log_event::pack_info(Protocol* protocol) String str(buf2, sizeof(buf2), &my_charset_bin); buf.length(0); 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)) return; protocol->store(buf.ptr(), buf.length(), &my_charset_bin); @@ -3923,7 +3932,7 @@ void User_var_log_event::pack_info(Protocol* protocol) String buf(buf_mem, sizeof(buf_mem), system_charset_info); CHARSET_INFO *cs; 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("???"))) return; @@ -3932,7 +3941,8 @@ void User_var_log_event::pack_info(Protocol* protocol) { size_t old_len; 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(cs->cs_name) || buf.append(' ')) @@ -3980,10 +3990,10 @@ bool User_var_log_event::write() } else { - buf1[1]= type; - int4store(buf1 + 2, charset_number); + buf1[1]= m_type; + int4store(buf1 + 2, m_charset_number); - switch (type) { + switch (m_type) { case REAL_RESULT: float8store(buf2, *(double*) val); break; @@ -4013,15 +4023,28 @@ bool User_var_log_event::write() buf1_length= 10; } + uchar data_type_name_chunk_signature= (uchar) CHUNK_DATA_TYPE_NAME; + 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; + 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) || write_data(buf, sizeof(buf)) || write_data(name, name_len) || write_data(buf1, buf1_length) || 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(); } @@ -4045,7 +4068,7 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi) 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, ER_THD(thd, ER_SLAVE_FATAL_ERROR), @@ -4064,7 +4087,7 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi) } else { - switch (type) { + switch (m_type) { case REAL_RESULT: if (val_len != 8) { @@ -4128,13 +4151,10 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi) if (e->fix_fields(thd, 0)) DBUG_RETURN(1); - /* - A variable can just be considered as a table with - a single record and with a single column. Thus, like - 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)); + const Type_handler *th= Type_handler::handler_by_log_event_data_type(thd, + *this); + e->update_hash((void*) val, val_len, th, charset); + if (!is_deferred()) free_root(thd->mem_root, 0); else @@ -6511,7 +6531,7 @@ Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability indexed and it cannot have a DEFAULT value). */ m_table->auto_increment_field_not_null= FALSE; - m_table->mark_auto_increment_column(); + m_table->mark_auto_increment_column(true); } return error; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a05df909b31f3..22c69ced56a0e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5251,6 +5251,14 @@ static int init_server_components() us_to_ms(global_system_variables.optimizer_scan_setup_cost); } + /* + Plugins may not be completed because system table DDLs are only + run after the ddl recovery done. Therefore between the + plugin_init() call and the ha_signal_ddl_recovery_done() call + below only things related to preparation for recovery should be + done and nothing else, and definitely not anything assuming that + all plugins have been initialised. + */ if (plugin_init(&remaining_argc, remaining_argv, (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) | (opt_abort ? PLUGIN_INIT_SKIP_INITIALIZATION : 0))) @@ -5826,8 +5834,6 @@ int mysqld_main(int argc, char **argv) SYSVAR_AUTOSIZE(my_thread_stack_size, new_thread_stack_size); } - (void) thr_setconcurrency(concurrency); // 10 by default - select_thread=pthread_self(); select_thread_in_use=1; @@ -6905,8 +6911,8 @@ struct my_option my_long_options[]= #endif }; -static int show_queries(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_queries(THD *thd, SHOW_VAR *var, void *, + system_status_var *, enum_var_type) { var->type= SHOW_LONGLONG; var->value= &thd->query_id; @@ -6914,16 +6920,16 @@ static int show_queries(THD *thd, SHOW_VAR *var, char *buff, } -static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_net_compression(THD *thd, SHOW_VAR *var, void *, + system_status_var *, enum_var_type) { var->type= SHOW_MY_BOOL; var->value= &thd->net.compress; return 0; } -static int show_starttime(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_starttime(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -6932,8 +6938,8 @@ static int show_starttime(THD *thd, SHOW_VAR *var, char *buff, } #ifdef ENABLED_PROFILING -static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_flushstatustime(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -6943,32 +6949,28 @@ static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff, #endif #ifdef HAVE_REPLICATION -static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_rpl_status(THD *, SHOW_VAR *var, void *, system_status_var *, + enum_var_type) { var->type= SHOW_CHAR; var->value= const_cast(rpl_status_type[(int)rpl_status]); return 0; } -static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_slave_running(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { - Master_info *mi= NULL; - bool UNINIT_VAR(tmp); - - var->type= SHOW_MY_BOOL; - var->value= buff; - - if ((mi= get_master_info(&thd->variables.default_master_connection, - Sql_condition::WARN_LEVEL_NOTE))) + if (Master_info *mi= + get_master_info(&thd->variables.default_master_connection, + Sql_condition::WARN_LEVEL_NOTE)) { - tmp= (my_bool) (mi->slave_running == MYSQL_SLAVE_RUN_READING && - mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN); + *((my_bool*) buff)= + (mi->slave_running == MYSQL_SLAVE_RUN_READING && + mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN); mi->release(); + var->type= SHOW_MY_BOOL; + var->value= buff; } - if (mi) - *((my_bool *)buff)= tmp; else var->type= SHOW_UNDEF; return 0; @@ -6978,7 +6980,8 @@ static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff, /* How many masters this slave is connected to */ -static int show_slaves_running(THD *thd, SHOW_VAR *var, char *buff) +static int show_slaves_running(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONGLONG; var->value= buff; @@ -6989,19 +6992,17 @@ static int show_slaves_running(THD *thd, SHOW_VAR *var, char *buff) } -static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { - Master_info *mi; - - var->type= SHOW_LONGLONG; - var->value= buff; - - if ((mi= get_master_info(&thd->variables.default_master_connection, - Sql_condition::WARN_LEVEL_NOTE))) + if (Master_info *mi= + get_master_info(&thd->variables.default_master_connection, + Sql_condition::WARN_LEVEL_NOTE)) { *((longlong *)buff)= mi->received_heartbeats; mi->release(); + var->type= SHOW_LONGLONG; + var->value= buff; } else var->type= SHOW_UNDEF; @@ -7009,19 +7010,17 @@ static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff, } -static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_heartbeat_period(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { - Master_info *mi; - - var->type= SHOW_CHAR; - var->value= buff; - - if ((mi= get_master_info(&thd->variables.default_master_connection, - Sql_condition::WARN_LEVEL_NOTE))) + if (Master_info *mi= + get_master_info(&thd->variables.default_master_connection, + Sql_condition::WARN_LEVEL_NOTE)) { - sprintf(buff, "%.3f", mi->heartbeat_period); + sprintf(static_cast(buff), "%.3f", mi->heartbeat_period); mi->release(); + var->type= SHOW_CHAR; + var->value= buff; } else var->type= SHOW_UNDEF; @@ -7031,19 +7030,20 @@ static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff, #endif /* HAVE_REPLICATION */ -static int show_max_used_connections_time(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_max_used_connections_time(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_CHAR; var->value= buff; - get_date(buff, GETDATE_DATE_TIME | GETDATE_FIXEDLENGTH, max_used_connections_time); + get_date(static_cast(buff), + GETDATE_DATE_TIME | GETDATE_FIXEDLENGTH, max_used_connections_time); return 0; } -static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_open_tables(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7051,8 +7051,8 @@ static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_prepared_stmt_count(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_prepared_stmt_count(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7062,8 +7062,8 @@ static int show_prepared_stmt_count(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_table_definitions(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7082,8 +7082,8 @@ static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff, inside an Event. */ -static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_ssl_get_version(THD *thd, SHOW_VAR *var, void *, + system_status_var *, enum_var_type) { var->type= SHOW_CHAR; if( thd->vio_ok() && thd->net.vio->ssl_arg ) @@ -7093,8 +7093,8 @@ static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7105,8 +7105,8 @@ static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7121,8 +7121,8 @@ static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7134,8 +7134,8 @@ static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_CHAR; if( thd->vio_ok() && thd->net.vio->ssl_arg ) @@ -7145,9 +7145,10 @@ static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, void *buf, + system_status_var *, enum_var_type) { + char *buff= static_cast(buf); var->type= SHOW_CHAR; var->value= buff; if (thd->vio_ok() && thd->net.vio->ssl_arg) @@ -7232,8 +7233,8 @@ my_asn1_time_to_string(const ASN1_TIME *time, char *buf, size_t len) */ static int -show_ssl_get_server_not_before(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +show_ssl_get_server_not_before(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_CHAR; if(thd->vio_ok() && thd->net.vio->ssl_arg) @@ -7242,7 +7243,7 @@ show_ssl_get_server_not_before(THD *thd, SHOW_VAR *var, char *buff, X509 *cert= SSL_get_certificate(ssl); const ASN1_TIME *not_before= X509_get0_notBefore(cert); - var->value= my_asn1_time_to_string(not_before, buff, + var->value= my_asn1_time_to_string(not_before, static_cast(buff), SHOW_VAR_FUNC_BUFF_SIZE); if (!var->value) return 1; @@ -7266,8 +7267,8 @@ show_ssl_get_server_not_before(THD *thd, SHOW_VAR *var, char *buff, */ static int -show_ssl_get_server_not_after(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +show_ssl_get_server_not_after(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_CHAR; if(thd->vio_ok() && thd->net.vio->ssl_arg) @@ -7276,7 +7277,7 @@ show_ssl_get_server_not_after(THD *thd, SHOW_VAR *var, char *buff, X509 *cert= SSL_get_certificate(ssl); const ASN1_TIME *not_after= X509_get0_notAfter(cert); - var->value= my_asn1_time_to_string(not_after, buff, + var->value= my_asn1_time_to_string(not_after, static_cast(buff), SHOW_VAR_FUNC_BUFF_SIZE); if (!var->value) return 1; @@ -7330,7 +7331,7 @@ static int show_default_keycache(THD *thd, SHOW_VAR *var, void *buff, } -static int show_memory_used(THD *thd, SHOW_VAR *var, char *buff, +static int show_memory_used(THD *thd, SHOW_VAR *var, void *buff, struct system_status_var *status_var, enum enum_var_type scope) { @@ -7386,8 +7387,8 @@ static int debug_status_func(THD *thd, SHOW_VAR *var, void *buff, #endif #ifdef HAVE_POOL_OF_THREADS -static int show_threadpool_idle_threads(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_threadpool_idle_threads(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_INT; var->value= buff; @@ -7396,8 +7397,8 @@ static int show_threadpool_idle_threads(THD *thd, SHOW_VAR *var, char *buff, } -static int show_threadpool_threads(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_threadpool_threads(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_INT; var->value= buff; diff --git a/sql/opt_trace.cc b/sql/opt_trace.cc index 1008690ccaa70..93090acfb9652 100644 --- a/sql/opt_trace.cc +++ b/sql/opt_trace.cc @@ -103,7 +103,8 @@ inline bool sql_command_can_be_traced(enum enum_sql_command sql_command) sql_command == SQLCOM_UPDATE || sql_command == SQLCOM_DELETE || 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, diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 16d96f8a09809..0e985a95cfe6f 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -8385,11 +8385,6 @@ bool check_grant(THD *thd, privilege_t want_access, TABLE_LIST *tables, INSERT_ACL : SELECT_ACL); } - if (tl->with || !tl->db.str || - (tl->select_lex && - (tl->with= tl->select_lex->find_table_def_in_with_clauses(tl)))) - continue; - const ACL_internal_table_access *access= get_cached_table_access(&t_ref->grant.m_internal, t_ref->get_db_name(), @@ -12171,8 +12166,8 @@ static my_bool count_column_grants(void *grant_table, This must be performed under the mutex in order to make sure the iteration does not fail. */ -static int show_column_grants(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_column_grants(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum enum_var_type scope) { var->type= SHOW_ULONG; var->value= buff; @@ -12188,8 +12183,8 @@ static int show_column_grants(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_database_grants(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_database_grants(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum enum_var_type scope) { var->type= SHOW_UINT; var->value= buff; diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index e71c701523872..118b361eb79b8 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -137,7 +137,7 @@ int binlog_defragment(THD *thd) entry[k]= (user_var_entry*) my_hash_search(&thd->user_vars, (uchar*) name[k].str, 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); return -1; @@ -162,7 +162,8 @@ int binlog_defragment(THD *thd) gathered_length += entry[k]->length; } 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); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 3b43a71612442..2bd7996da626b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -727,7 +727,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) wsrep_wfc() #endif /*WITH_WSREP */ { - ulong tmp; bzero(&variables, sizeof(variables)); /* @@ -879,14 +878,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) tablespace_op=FALSE; - /* - Initialize the random generator. We call my_rnd() without a lock as - it's not really critical if two threads modifies the structure at the - same time. We ensure that we have an unique number foreach thread - by adding the address of the stack. - */ - tmp= (ulong) (my_rnd(&sql_rand) * 0xffffffff); - my_rnd_init(&rand, tmp + (ulong)((size_t) &rand), tmp + (ulong) ::global_query_id); substitute_null_with_insert_id = FALSE; lock_info.mysql_thd= (void *)this; @@ -1313,6 +1304,17 @@ void THD::init() /* Set to handle counting of aborted connections */ userstat_running= opt_userstat_running; last_global_update_time= current_connect_time= time(NULL); + + /* + Initialize the random generator. We call my_rnd() without a lock as + it's not really critical if two threads modify the structure at the + same time. We ensure that we have a unique number for each thread + by adding the address of this THD. + */ + ulong tmp= (ulong) (my_rnd(&sql_rand) * 0xffffffff); + my_rnd_init(&rand, tmp + (ulong)(intptr) this, + (ulong)(my_timer_cycles() + global_query_id)); + #ifndef EMBEDDED_LIBRARY session_tracker.enable(this); #endif //EMBEDDED_LIBRARY diff --git a/sql/sql_class.h b/sql/sql_class.h index 5d02ced817bdf..99303c27d8ab2 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -281,9 +281,8 @@ typedef struct st_user_var_events user_var_entry *user_var_event; char *value; size_t length; - Item_result type; + const Type_handler *th; uint charset_number; - bool unsigned_flag; } BINLOG_USER_VAR_EVENT; /* @@ -7148,7 +7147,7 @@ class Qualified_column_ident: public Table_ident // 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; public: @@ -7157,8 +7156,6 @@ class user_var_entry char *value; size_t length; query_id_t update_query_id, used_query_id; - Item_result type; - bool unsigned_flag; double val_real(bool *null_value); longlong val_int(bool *null_value) const; diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 1dbb265452a03..5b3db9bca1d89 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -106,6 +106,7 @@ bool LEX::check_dependencies_in_with_clauses() @param tables Points to the beginning of the sub-chain @param tables_last Points to the address with the sub-chain barrier + @param excl_spec Ignore the definition with this spec @details The method resolves tables references to CTE from the chain of @@ -147,7 +148,8 @@ bool LEX::check_dependencies_in_with_clauses() */ bool LEX::resolve_references_to_cte(TABLE_LIST *tables, - TABLE_LIST **tables_last) + TABLE_LIST **tables_last, + st_select_lex_unit *excl_spec) { With_element *with_elem= 0; @@ -156,7 +158,8 @@ bool LEX::resolve_references_to_cte(TABLE_LIST *tables, if (tbl->derived) continue; if (!tbl->db.str && !tbl->with) - tbl->with= tbl->select_lex->find_table_def_in_with_clauses(tbl); + tbl->with= tbl->select_lex->find_table_def_in_with_clauses(tbl, + excl_spec); if (!tbl->with) // no CTE matches table reference tbl { if (only_cte_resolution) @@ -244,7 +247,7 @@ LEX::check_cte_dependencies_and_resolve_references() return true; if (!with_cte_resolution) return false; - if (resolve_references_to_cte(query_tables, query_tables_last)) + if (resolve_references_to_cte(query_tables, query_tables_last, NULL)) return true; return false; } @@ -388,6 +391,7 @@ bool With_element::check_dependencies_in_spec() @param table The reference to the table that is looked for @param barrier The barrier with element for the search + @param excl_spec Ignore the definition with this spec @details The function looks through the elements of this with clause trying to find @@ -401,12 +405,15 @@ bool With_element::check_dependencies_in_spec() */ With_element *With_clause::find_table_def(TABLE_LIST *table, - With_element *barrier) + With_element *barrier, + st_select_lex_unit *excl_spec) { for (With_element *with_elem= with_list.first; with_elem != barrier; with_elem= with_elem->next) { + if (excl_spec && with_elem->spec == excl_spec) + continue; if (my_strcasecmp(system_charset_info, with_elem->get_name_str(), table->table_name.str) == 0 && !table->is_fqtn) @@ -466,7 +473,7 @@ With_element *find_table_def_in_with_clauses(TABLE_LIST *tbl, top_unit->with_element && top_unit->with_element->get_owner() == with_clause) barrier= top_unit->with_element; - found= with_clause->find_table_def(tbl, barrier); + found= with_clause->find_table_def(tbl, barrier, NULL); if (found) break; } @@ -521,10 +528,11 @@ void With_element::check_dependencies_in_select(st_select_lex *sl, { With_clause *with_clause= sl->master_unit()->with_clause; if (with_clause) - tbl->with= with_clause->find_table_def(tbl, NULL); + tbl->with= with_clause->find_table_def(tbl, NULL, NULL); if (!tbl->with) tbl->with= owner->find_table_def(tbl, - owner->with_recursive ? NULL : this); + owner->with_recursive ? NULL : this, + NULL); } if (!tbl->with) tbl->with= find_table_def_in_with_clauses(tbl, ctxt); @@ -1101,7 +1109,8 @@ st_select_lex_unit *With_element::clone_parsed_spec(LEX *old_lex, */ lex->only_cte_resolution= old_lex->only_cte_resolution; if (lex->resolve_references_to_cte(lex->query_tables, - lex->query_tables_last)) + lex->query_tables_last, + spec)) { res= NULL; goto err; @@ -1304,6 +1313,7 @@ bool With_element::is_anchor(st_select_lex *sel) Search for the definition of the given table referred in this select node @param table reference to the table whose definition is searched for + @param excl_spec ignore the definition with this spec @details The method looks for the definition of the table whose reference is occurred @@ -1316,7 +1326,8 @@ bool With_element::is_anchor(st_select_lex *sel) NULL - otherwise */ -With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) +With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table, + st_select_lex_unit *excl_spec) { With_element *found= NULL; With_clause *containing_with_clause= NULL; @@ -1333,7 +1344,7 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) With_clause *attached_with_clause= sl->get_with_clause(); if (attached_with_clause && attached_with_clause != containing_with_clause && - (found= attached_with_clause->find_table_def(table, NULL))) + (found= attached_with_clause->find_table_def(table, NULL, excl_spec))) break; master_unit= sl->master_unit(); outer_sl= master_unit->outer_select(); @@ -1343,7 +1354,8 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) containing_with_clause= with_elem->get_owner(); With_element *barrier= containing_with_clause->with_recursive ? NULL : with_elem; - if ((found= containing_with_clause->find_table_def(table, barrier))) + if ((found= containing_with_clause->find_table_def(table, barrier, + excl_spec))) break; if (outer_sl && !outer_sl->get_with_element()) break; diff --git a/sql/sql_cte.h b/sql/sql_cte.h index 6a1f67d32585c..1da7c6c323aed 100644 --- a/sql/sql_cte.h +++ b/sql/sql_cte.h @@ -325,7 +325,8 @@ class With_element : public Sql_alloc friend bool LEX::resolve_references_to_cte(TABLE_LIST *tables, - TABLE_LIST **tables_last); + TABLE_LIST **tables_last, + st_select_lex_unit *excl_spec); }; const uint max_number_of_elements_in_with_clause= sizeof(table_map)*8; @@ -425,7 +426,8 @@ class With_clause : public Sql_alloc void move_anchors_ahead(); - With_element *find_table_def(TABLE_LIST *table, With_element *barrier); + With_element *find_table_def(TABLE_LIST *table, With_element *barrier, + st_select_lex_unit *excl_spec); With_element *find_table_def_in_with_clauses(TABLE_LIST *table); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index fecfc43db7a9b..3151f237f9c63 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1594,7 +1594,8 @@ class st_select_lex: public st_select_lex_node master_unit()->cloned_from->with_element : master_unit()->with_element; } - With_element *find_table_def_in_with_clauses(TABLE_LIST *table); + With_element *find_table_def_in_with_clauses(TABLE_LIST *table, + st_select_lex_unit * excl_spec); bool check_unrestricted_recursive(bool only_standard_compliant); bool check_subqueries_with_recursive_references(); void collect_grouping_fields_for_derived(THD *thd, ORDER *grouping_list); @@ -4890,7 +4891,8 @@ struct LEX: public Query_tables_list bool check_dependencies_in_with_clauses(); bool check_cte_dependencies_and_resolve_references(); bool resolve_references_to_cte(TABLE_LIST *tables, - TABLE_LIST **tables_last); + TABLE_LIST **tables_last, + st_select_lex_unit *excl_spec); /** Turn on the SELECT_DESCRIBE flag for every SELECT_LEX involved into diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index eee82c75706db..ba91339ee20ad 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -510,7 +510,7 @@ static enum enum_binlog_checksum_alg get_binlog_checksum_value_at_connect(THD * } else { - DBUG_ASSERT(entry->type == STRING_RESULT); + DBUG_ASSERT(entry->type_handler()->result_type() == STRING_RESULT); String str; uint dummy_errors; str.copy(entry->value, entry->length, &my_charset_bin, &my_charset_bin, diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index f5652bd88860e..f6d7c310a2fcc 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -921,6 +921,7 @@ bool Sql_cmd_alter_sequence::execute(THD *thd) TABLE_LIST *first_table= lex->query_tables; TABLE *table; sequence_definition *new_seq= lex->create_info.seq_create_info; + uint saved_used_fields= new_seq->used_fields; SEQUENCE *seq; No_such_table_error_handler no_such_table_handler; DBUG_ENTER("Sql_cmd_alter_sequence::execute"); @@ -1042,5 +1043,6 @@ bool Sql_cmd_alter_sequence::execute(THD *thd) my_ok(thd); end: + new_seq->used_fields= saved_used_fields; DBUG_RETURN(error); } diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 2cc9bb22f9bc4..a086e338996b5 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -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. */ diff --git a/sql/sql_type.h b/sql/sql_type.h index 8215a3ee75930..5ce1744761066 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -30,6 +30,8 @@ #include "sql_type_string.h" #include "sql_type_real.h" #include "compat56.h" +#include "log_event_data_type.h" + C_MODE_START #include C_MODE_END @@ -3673,6 +3675,9 @@ class Type_handler static const Type_handler *handler_by_name(THD *thd, const LEX_CSTRING &name); static const Type_handler *handler_by_name_or_error(THD *thd, 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 *blob_type_handler(uint max_octet_length); static const Type_handler *string_type_handler(uint max_octet_length); @@ -3957,6 +3962,12 @@ class Type_handler { 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, const Column_definition &def) const diff --git a/sql/sql_type_geom.h b/sql/sql_type_geom.h index d86d118118770..14d3d062ef94a 100644 --- a/sql/sql_type_geom.h +++ b/sql/sql_type_geom.h @@ -82,6 +82,13 @@ class Type_handler_geometry: public Type_handler_string_result Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, 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, const Column_definition &def) const override; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 25fa92cdafcd6..cb39ef001fcb9 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -297,7 +297,8 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local) { if (!tbl->with && tbl->select_lex) - tbl->with= tbl->select_lex->find_table_def_in_with_clauses(tbl); + tbl->with= tbl->select_lex->find_table_def_in_with_clauses(tbl, + NULL); /* Ensure that we have some privileges on this table, more strict check will be done on column level after preparation, diff --git a/sql/table.cc b/sql/table.cc index e4f59f0fcea62..96130c9501190 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -7701,7 +7701,7 @@ inline void TABLE::mark_index_columns_for_read(uint index) always set and sometimes read. */ -void TABLE::mark_auto_increment_column() +void TABLE::mark_auto_increment_column(bool is_insert) { DBUG_ASSERT(found_next_number_field); /* @@ -7709,7 +7709,8 @@ void TABLE::mark_auto_increment_column() store() to check overflow of auto_increment values */ bitmap_set_bit(read_set, found_next_number_field->field_index); - bitmap_set_bit(write_set, found_next_number_field->field_index); + if (is_insert) + bitmap_set_bit(write_set, found_next_number_field->field_index); if (s->next_number_keypart) mark_index_columns_for_read(s->next_number_index); file->column_bitmaps_signal(); @@ -7834,7 +7835,7 @@ void TABLE::mark_columns_needed_for_update() else { if (found_next_number_field) - mark_auto_increment_column(); + mark_auto_increment_column(false); } if (file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) @@ -7910,7 +7911,7 @@ void TABLE::mark_columns_needed_for_insert() triggers->mark_fields_used(TRG_EVENT_INSERT); } if (found_next_number_field) - mark_auto_increment_column(); + mark_auto_increment_column(true); if (default_field) mark_default_fields_for_write(TRUE); if (s->versioned) diff --git a/sql/table.h b/sql/table.h index aaee3ff5c579a..7095abdf41772 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1608,7 +1608,7 @@ struct TABLE void mark_index_columns_no_reset(uint index, MY_BITMAP *bitmap); void mark_index_columns_for_read(uint index); void restore_column_maps_after_keyread(MY_BITMAP *backup); - void mark_auto_increment_column(void); + void mark_auto_increment_column(bool insert_fl); void mark_columns_needed_for_update(void); void mark_columns_needed_for_delete(void); void mark_columns_needed_for_insert(void); diff --git a/sql/table_cache.cc b/sql/table_cache.cc index 0039c96a00186..91292e18d72c9 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -1213,8 +1213,8 @@ int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument, } -int show_tc_active_instances(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +int show_tc_active_instances(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum enum_var_type scope) { var->type= SHOW_UINT; var->value= buff; diff --git a/sql/table_cache.h b/sql/table_cache.h index 433df5e032865..71704ff2ed082 100644 --- a/sql/table_cache.h +++ b/sql/table_cache.h @@ -87,8 +87,8 @@ extern int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument, bool no_dups= false); extern uint tc_records(void); -int show_tc_active_instances(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope); +int show_tc_active_instances(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum enum_var_type scope); extern void tc_purge(); extern void tc_add_table(THD *thd, TABLE *table); extern void tc_release_table(TABLE *table); diff --git a/storage/connect/tabvct.cpp b/storage/connect/tabvct.cpp index 9cf5f41d1feec..f5710688d3c5c 100644 --- a/storage/connect/tabvct.cpp +++ b/storage/connect/tabvct.cpp @@ -71,11 +71,6 @@ #include "tabvct.h" #include "valblk.h" -#if defined(UNIX) -//add dummy strerror (NGC) -char *strerror(int num); -#endif // UNIX - /***********************************************************************/ /* External function. */ /***********************************************************************/ diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index e9aea35533be5..e2702adc880d2 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -336,11 +336,14 @@ dberr_t buf_dblwr_t::init_or_load_pages(pfs_os_file_t file, const char *path) os_file_flush(file); } 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))) - /* Each valid page header must contain a nonzero FIL_PAGE_LSN field. */ + { + alignas(8) char checkpoint[8]; + 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); - + } err= DB_SUCCESS; goto func_exit; } diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index cafff419b0581..5cbc18c1c97ea 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -435,12 +435,22 @@ Datafile::validate_for_recovery() 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) { err = find_space_id(); if (err != DB_SUCCESS || m_space_id == 0) { - ib::error() << "Datafile '" << m_filepath - << "' is corrupted. Cannot determine " - "the space ID from the first 64 pages."; + sql_print_error( + "InnoDB: Datafile '%s' is corrupted." + " Cannot determine the space ID from" + " the first 64 pages.", m_filepath); return(err); } } @@ -453,7 +463,7 @@ Datafile::validate_for_recovery() m_space_id, m_filepath, m_handle)) { return m_defer ? err : DB_CORRUPTION; } - +free_first_page: /* Free the previously read first page and then re-validate. */ free_first_page(); m_defer = false; @@ -492,11 +502,11 @@ dberr_t Datafile::validate_first_page() return DB_SUCCESS; } - ib::info() << error_txt << " in datafile: " << m_filepath - << ", Space ID:" << m_space_id << ", Flags: " - << m_flags; + sql_print_error("InnoDB: %s in datafile: %s, Space ID: %zu, " + "Flags: %zu", error_txt, m_filepath, + m_space_id, m_flags); m_is_valid = false; - return(DB_CORRUPTION); + return DB_CORRUPTION; } /* Check if the whole page is blank. */ diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc index e4a43e481f81b..4ac9da50281d4 100644 --- a/storage/innobase/fsp/fsp0sysspace.cc +++ b/storage/innobase/fsp/fsp0sysspace.cc @@ -33,6 +33,7 @@ Refactored 2013-7-26 by Kevin Lewis #include "os0file.h" #include "row0mysql.h" #include "buf0dblwr.h" +#include "log.h" /** The server header file is included to access opt_initialize global variable. If server passes the option for create/open DB to SE, we should remove such @@ -568,7 +569,7 @@ inline dberr_t SysTablespace::read_lsn_and_check_flags() } 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) { return(err); @@ -582,47 +583,62 @@ inline dberr_t SysTablespace::read_lsn_and_check_flags() /* Check the contents of the first page of the first datafile. */ - for (int retry = 0; retry < 2; ++retry) { + err = it->validate_first_page(); - err = it->validate_first_page(); - - if (err != DB_SUCCESS - && (retry == 1 - || recv_sys.dblwr.restore_first_page( + if (err != DB_SUCCESS) { + if (recv_sys.dblwr.restore_first_page( it->m_space_id, it->m_filepath, - it->handle()))) { - + it->handle())) { it->close(); - return(err); } + err = it->read_first_page( + m_ignore_read_only && srv_read_only_mode); } /* Make sure the tablespace space ID matches the space ID on the first page of the first datafile. */ - if (space_id() != it->m_space_id) { - - ib::error() - << "The data file '" << it->filepath() - << "' has the wrong space ID. It should be " - << space_id() << ", but " << it->m_space_id - << " was found"; - + if (err != DB_SUCCESS || space_id() != it->m_space_id) { + sql_print_error("InnoDB: The data file '%s'" + " has the wrong space ID." + " It should be " UINT32PF ", but " UINT32PF + " was found", it->filepath(), + space_id(), it->m_space_id); it->close(); - - return(err); + return err; } - if (srv_operation == SRV_OPERATION_NORMAL) { + if (srv_force_recovery != 6 + && srv_operation == SRV_OPERATION_NORMAL + && !log_sys.next_checkpoint_lsn + && log_sys.format == log_t::FORMAT_3_23) { + + log_sys.latch.wr_lock(SRW_LOCK_CALL); /* Prepare for possible upgrade from 0-sized ib_logfile0. */ - ut_ad(!log_sys.next_checkpoint_lsn); log_sys.next_checkpoint_lsn = mach_read_from_8( it->m_first_page + 26/*FIL_PAGE_FILE_FLUSH_LSN*/); + if (log_sys.next_checkpoint_lsn < 8204) { + /* Before MDEV-14425, InnoDB had a minimum LSN + of 8192+12=8204. Likewise, mariadb-backup + --prepare would create an empty ib_logfile0 + after applying the log. We will allow an + upgrade from such an empty log. */ + sql_print_error("InnoDB: ib_logfile0 is " + "empty, and LSN is unknown."); + err = DB_CORRUPTION; + } else { + log_sys.last_checkpoint_lsn = + recv_sys.lsn = recv_sys.file_checkpoint = + log_sys.next_checkpoint_lsn; + log_sys.set_recovered_lsn(log_sys.next_checkpoint_lsn); + log_sys.next_checkpoint_no = 0; + } + + log_sys.latch.wr_unlock(); } it->close(); - - return(DB_SUCCESS); + return err; } /** Check if a file can be opened in the correct mode. diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 0e1b7b9ab66c8..1ca6ec16397d6 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2049,7 +2049,7 @@ static void drop_garbage_tables_after_restore() ut_d(purge_sys.resume_FTS()); } -static void innodb_ddl_recovery_done(handlerton*) +static int innodb_ddl_recovery_done(handlerton*) { ut_ad(!ddl_recovery_done); ut_d(ddl_recovery_done= true); @@ -2060,6 +2060,7 @@ static void innodb_ddl_recovery_done(handlerton*) drop_garbage_tables_after_restore(); srv_init_purge_tasks(); } + return 0; } /********************************************************************//** diff --git a/storage/innobase/include/buf0dblwr.h b/storage/innobase/include/buf0dblwr.h index 9932b0e521ff4..6e7662d9b81be 100644 --- a/storage/innobase/include/buf0dblwr.h +++ b/storage/innobase/include/buf0dblwr.h @@ -105,7 +105,8 @@ class buf_dblwr_t If we are upgrading from a version before MySQL 4.1, then this function performs the necessary update operations to support 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 path Path name of file @return DB_SUCCESS or error code */ diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index cdce87384f13d..ecc0b91e80f6d 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -180,9 +180,6 @@ struct log_t /* On ARM, we do more spinning */ typedef srw_spin_lock log_rwlock; typedef pthread_mutex_wrapper log_lsn_lock; -#elif defined _WIN32 - typedef srw_lock log_rwlock; - typedef pthread_mutex_wrapper log_lsn_lock; #else typedef srw_lock log_rwlock; typedef srw_mutex log_lsn_lock; diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index d4e8242b51374..1fe0d7e69769f 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -44,6 +44,11 @@ ATTRIBUTE_COLD MY_ATTRIBUTE((nonnull, warn_unused_result)) @return whether the page was recovered correctly */ 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.file_checkpoint +@return error code or DB_SUCCESS */ +dberr_t recv_recovery_read_checkpoint(); + /** Start recovering from a redo log checkpoint. of first system tablespace page @return error code or DB_SUCCESS */ @@ -114,7 +119,19 @@ struct recv_dblwr_t @param name tablespace filepath @param file tablespace file handle @return whether the operation failed */ - bool restore_first_page(uint32_t space_id, const char *name, os_file_t file); + bool restore_first_page(uint32_t 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 > list; diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 3ddd2e98fee8b..0f4f8afa15b34 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -140,6 +140,15 @@ class purge_sys_t bool m_initialized{false}; /** whether purge is enabled; protected by latch and std::atomic */ std::atomic m_enabled{false}; + /** The primary candidate for iterator::free_history() is + rseg=trx_sys.rseg_array[skipped_rseg]. This field may be changed + after invoking rseg.set_skip_allocation() and rseg.clear_skip_allocation() + and while holding the exclusive rseg.latch. + + This may only be 0 if innodb_undo_tablespaces=0, because rollback segment + 0 always resides in the system tablespace and would never be used when + dedicated undo tablespaces are in use. */ + Atomic_relaxed skipped_rseg; public: /** whether purge is active (may hold table handles) */ std::atomic m_active{false}; @@ -197,6 +206,11 @@ class purge_sys_t return undo_no <= other.undo_no; } + /** Remove unnecessary history data from a rollback segment. + @param rseg rollback segment + @return error code */ + inline dberr_t free_history_rseg(trx_rseg_t &rseg) const; + /** Free the undo pages up to this. */ dberr_t free_history() const; @@ -240,14 +254,15 @@ class purge_sys_t by the pq_mutex */ mysql_mutex_t pq_mutex; /*!< Mutex protecting purge_queue */ - /** Undo tablespace file truncation (only accessed by the - srv_purge_coordinator_thread) */ - struct { - /** The undo tablespace that is currently being truncated */ - fil_space_t* current; - /** The undo tablespace that was last truncated */ - fil_space_t* last; - } truncate; + /** innodb_undo_log_truncate=ON state; + only modified by purge_coordinator_callback() */ + struct { + /** The undo tablespace that is currently being truncated */ + Atomic_relaxed current; + /** The number of the undo tablespace that was last truncated, + relative from srv_undo_space_id_start */ + uint32_t last; + } truncate_undo_space; /** Create the instance */ void create(); @@ -357,6 +372,26 @@ class purge_sys_t typically via purge_sys_t::view_guard. */ return view.sees(id); } + +private: + /** Enable the use of a rollback segment and advance skipped_rseg, + after iterator::free_history_rseg() had invoked + rseg.set_skip_allocation(). */ + inline void rseg_enable(trx_rseg_t &rseg); + + /** Try to start truncating a tablespace. + @param id undo tablespace identifier + @param size the maximum desired undo tablespace size, in pages + @return undo tablespace whose truncation was started + @retval nullptr if truncation is not currently possible */ + inline fil_space_t *undo_truncate_try(uint32_t id, uint32_t size); +public: + /** Check if innodb_undo_log_truncate=ON needs to be handled. + This is only to be called by purge_coordinator_callback(). + @return undo tablespace chosen by innodb_undo_log_truncate=ON + @retval nullptr if truncation is not currently possible */ + fil_space_t *truncating_tablespace(); + /** A wrapper around trx_sys_t::clone_oldest_view(). */ template void clone_oldest_view() diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h index 43e0c290d63d5..7fa43047b186c 100644 --- a/storage/innobase/include/trx0rseg.h +++ b/storage/innobase/include/trx0rseg.h @@ -73,14 +73,15 @@ struct alignas(CPU_LEVEL1_DCACHE_LINESIZE) trx_rseg_t /** Reference counter to track is_persistent() transactions, with SKIP flag. */ std::atomic ref; - +public: /** Whether undo tablespace truncation is pending */ static constexpr uint32_t SKIP= 1; /** Transaction reference count multiplier */ static constexpr uint32_t REF= 2; + /** @return the reference count and flags */ uint32_t ref_load() const { return ref.load(std::memory_order_relaxed); } - +private: /** Set the SKIP bit */ void ref_set_skip() { diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 9a4264a723b5b..3fa41fdfc7457 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -1191,6 +1191,11 @@ class trx_sys_t return count; } + /** Disable further allocation of transactions in a rollback segment + that are subject to innodb_undo_log_truncate=ON + @param space undo tablespace that will be truncated */ + inline void undo_truncate_start(fil_space_t &space); + /** Set the undo log empty value */ void set_undo_non_empty(bool val) { diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index b2ec0716d6708..f9b225d732dbf 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -1672,20 +1672,6 @@ dberr_t recv_sys_t::find_checkpoint() { if (wrong_size) return DB_CORRUPTION; - if (log_sys.next_checkpoint_lsn < 8204) - { - /* Before MDEV-14425, InnoDB had a minimum LSN of 8192+12=8204. - Likewise, mariadb-backup --prepare would create an empty - ib_logfile0 after applying the log. We will allow an upgrade - from such an empty log. - - If a user replaces the redo log with an empty file and the - FIL_PAGE_FILE_FLUSH_LSN field was zero in the system - tablespace (see SysTablespace::read_lsn_and_check_flags()) we - must refuse to start up. */ - sql_print_error("InnoDB: ib_logfile0 is empty, and LSN is unknown."); - return DB_CORRUPTION; - } lsn= log_sys.next_checkpoint_lsn; log_sys.format= log_t::FORMAT_3_23; goto upgrade; @@ -4453,12 +4439,36 @@ static dberr_t recv_rename_files() return err; } +dberr_t recv_recovery_read_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; + } + + log_sys.latch.wr_lock(SRW_LOCK_CALL); + dberr_t err= recv_sys.find_checkpoint(); + log_sys.latch.wr_unlock(); + return err; +} + /** Start recovering from a redo log checkpoint. of first system tablespace page @return error code or DB_SUCCESS */ dberr_t recv_recovery_from_checkpoint_start() { - bool rescan = false; + bool rescan = false; + dberr_t err = DB_SUCCESS; ut_ad(srv_operation <= SRV_OPERATION_EXPORT_RESTORED || srv_operation == SRV_OPERATION_RESTORE @@ -4471,20 +4481,12 @@ dberr_t recv_recovery_from_checkpoint_start() if (srv_force_recovery >= SRV_FORCE_NO_LOG_REDO) { sql_print_information("InnoDB: innodb_force_recovery=6" " skips redo log apply"); - return(DB_SUCCESS); + return err; } recv_sys.recovery_on = true; log_sys.latch.wr_lock(SRW_LOCK_CALL); - - dberr_t err = recv_sys.find_checkpoint(); - if (err != DB_SUCCESS) { -early_exit: - log_sys.latch.wr_unlock(); - return err; - } - log_sys.set_capacity(); /* Start reading the log from the checkpoint lsn. The variable @@ -4494,7 +4496,9 @@ dberr_t recv_recovery_from_checkpoint_start() ut_ad(recv_sys.pages.empty()); if (log_sys.format == log_t::FORMAT_3_23) { - goto early_exit; +early_exit: + log_sys.latch.wr_unlock(); + return err; } if (log_sys.is_latest()) { @@ -4788,7 +4792,7 @@ byte *recv_dblwr_t::find_page(const page_id_t page_id, } bool recv_dblwr_t::restore_first_page(uint32_t space_id, const char *name, - os_file_t file) + pfs_os_file_t file) { const page_id_t page_id(space_id, 0); const byte* page= find_page(page_id); @@ -4796,10 +4800,10 @@ bool recv_dblwr_t::restore_first_page(uint32_t space_id, const char *name, { /* If the first page of the given user tablespace is not there in the doublewrite buffer, then the recovery is going to fail - now. Hence this is treated as error. */ - ib::error() - << "Corrupted page " << page_id << " of datafile '" - << name <<"' could not be found in the doublewrite buffer."; + now. Report error only when doublewrite buffer is not empty */ + if (pages.size()) + ib::error() << "Corrupted page " << page_id << " of datafile '" + << name << "' could not be found in the doublewrite buffer."; return true; } @@ -4813,3 +4817,47 @@ bool recv_dblwr_t::restore_first_page(uint32_t space_id, const char *name, IORequestWrite, name, file, page, 0, physical_size) != DB_SUCCESS; } + +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(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(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; +} diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 054893bf4cce7..3d24b97a21ae6 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1439,7 +1439,8 @@ inline void purge_coordinator_state::do_purge() ulint n_pages_handled= trx_purge(n_threads, history_size); if (!trx_sys.history_exists()) goto no_history; - if (purge_sys.truncate.current || srv_shutdown_state != SRV_SHUTDOWN_NONE) + if (purge_sys.truncating_tablespace() || + srv_shutdown_state != SRV_SHUTDOWN_NONE) { purge_truncation_task.wait(); trx_purge_truncate_history(); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 447470e99793f..9e69d8bb23210 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1369,6 +1369,10 @@ dberr_t srv_start(bool create_new_db) ut_ad(buf_page_cleaner_is_active); } + if (innodb_encrypt_temporary_tables && !log_crypt_init()) { + return srv_init_abort(DB_ERROR); + } + /* Check if undo tablespaces and redo log files exist before creating a new system tablespace */ if (create_new_db) { @@ -1377,6 +1381,11 @@ dberr_t srv_start(bool create_new_db) return(srv_init_abort(DB_ERROR)); } recv_sys.debug_free(); + } else { + err = recv_recovery_read_checkpoint(); + if (err != DB_SUCCESS) { + return srv_init_abort(err); + } } /* Open or create the data files. */ @@ -1401,12 +1410,9 @@ dberr_t srv_start(bool create_new_db) " 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 (innodb_encrypt_temporary_tables && !log_crypt_init()) { - return srv_init_abort(DB_ERROR); + /* Other errors might be flagged by + Datafile::validate_first_page() */ + return srv_init_abort(err); } if (create_new_db) { @@ -1422,10 +1428,10 @@ dberr_t srv_start(bool create_new_db) return srv_init_abort(err); } - srv_undo_space_id_start= 1; + srv_undo_space_id_start = 1; } - /* Open log file and data files in the systemtablespace: we keep + /* Open data files in the system tablespace: we keep them open until database shutdown */ ut_d(fil_system.sys_space->recv_size = srv_sys_space_size_debug); diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index add4db962d54b..9a295e0b2c1d0 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -169,10 +169,15 @@ void purge_sys_t::create() ut_ad(this == &purge_sys); ut_ad(!m_initialized); ut_ad(!enabled()); + ut_ad(!m_active); + /* If innodb_undo_tablespaces>0, the rollback segment 0 + (which always resides in the system tablespace) will + never be used; @see trx_assign_rseg_low() */ + skipped_rseg= srv_undo_tablespaces > 0; m_paused= 0; query= purge_graph_build(); next_stored= false; - rseg= NULL; + rseg= nullptr; page_no= 0; offset= 0; hdr_page_no= 0; @@ -180,8 +185,8 @@ void purge_sys_t::create() latch.SRW_LOCK_INIT(trx_purge_latch_key); end_latch.init(); mysql_mutex_init(purge_sys_pq_mutex_key, &pq_mutex, nullptr); - truncate.current= NULL; - truncate.last= NULL; + truncate_undo_space.current= nullptr; + truncate_undo_space.last= 0; m_initialized= true; } @@ -385,17 +390,50 @@ static void trx_purge_free_segment(buf_block_t *rseg_hdr, buf_block_t *block, block->page.frame, &mtr)); } +void purge_sys_t::rseg_enable(trx_rseg_t &rseg) +{ + ut_ad(this == &purge_sys); +#ifndef SUX_LOCK_GENERIC + ut_ad(rseg.latch.is_write_locked()); +#endif + uint8_t skipped= skipped_rseg; + ut_ad(skipped < TRX_SYS_N_RSEGS); + if (&rseg == &trx_sys.rseg_array[skipped]) + { + /* If this rollback segment is subject to innodb_undo_log_truncate=ON, + we must not clear the flag. But we will advance purge_sys.skipped_rseg + to be able to choose another candidate for this soft truncation, and + to prevent the following scenario: + + (1) purge_sys_t::iterator::free_history_rseg() had invoked + rseg.set_skip_allocation() + (2) undo log truncation had completed on this rollback segment + (3) SET GLOBAL innodb_undo_log_truncate=OFF + (4) purge_sys_t::iterator::free_history_rseg() would not be able to + invoke rseg.set_skip_allocation() on any other rollback segment + before this rseg has grown enough */ + if (truncate_undo_space.current != rseg.space) + rseg.clear_skip_allocation(); + skipped++; + /* If innodb_undo_tablespaces>0, the rollback segment 0 + (which always resides in the system tablespace) will + never be used; @see trx_assign_rseg_low() */ + if (!(skipped&= (TRX_SYS_N_RSEGS - 1)) && srv_undo_tablespaces) + skipped++; + skipped_rseg= skipped; + } +} + /** Remove unnecessary history data from a rollback segment. @param rseg rollback segment @param limit truncate anything before this -@param all whether everything can be truncated @return error code */ -static dberr_t -trx_purge_truncate_rseg_history(trx_rseg_t &rseg, - const purge_sys_t::iterator &limit, bool all) +inline dberr_t purge_sys_t::iterator::free_history_rseg(trx_rseg_t &rseg) const { fil_addr_t hdr_addr; mtr_t mtr; + bool freed= false; + uint32_t rseg_ref= 0; mtr.start(); @@ -405,6 +443,8 @@ trx_purge_truncate_rseg_history(trx_rseg_t &rseg, { func_exit: mtr.commit(); + if (freed && (rseg.SKIP & rseg_ref)) + purge_sys.rseg_enable(rseg); return err; } @@ -426,16 +466,40 @@ trx_purge_truncate_rseg_history(trx_rseg_t &rseg, const trx_id_t undo_trx_no= mach_read_from_8(b->page.frame + hdr_addr.boffset + TRX_UNDO_TRX_NO); - if (undo_trx_no >= limit.trx_no) + if (undo_trx_no >= trx_no) { - if (undo_trx_no == limit.trx_no) - err = trx_undo_truncate_start(&rseg, hdr_addr.page, - hdr_addr.boffset, limit.undo_no); + if (undo_trx_no == trx_no) + err= trx_undo_truncate_start(&rseg, hdr_addr.page, + hdr_addr.boffset, undo_no); goto func_exit; } - - if (!all) - goto func_exit; + else + { + rseg_ref= rseg.ref_load(); + if (rseg_ref >= rseg.REF || !purge_sys.sees(rseg.needs_purge)) + { + /* We cannot clear this entire rseg because trx_assign_rseg_low() + has already chosen it for a future trx_undo_assign(), or + because some recently started transaction needs purging. + + If this invocation could not reduce rseg.history_size at all + (!freed), we will try to ensure progress and prevent our + starvation by disabling one rollback segment for future + trx_assign_rseg_low() invocations until a future invocation has + made progress and invoked purge_sys_t::rseg_enable(rseg) on that + rollback segment. */ + + if (!(rseg.SKIP & rseg_ref) && !freed && + ut_d(!trx_rseg_n_slots_debug &&) + &rseg == &trx_sys.rseg_array[purge_sys.skipped_rseg]) + /* If rseg.space == purge_sys.truncate_undo_space.current + the following will be a no-op. A possible conflict + with innodb_undo_log_truncate=ON will be handled in + purge_sys_t::rseg_enable(). */ + rseg.set_skip_allocation(); + goto func_exit; + } + } fil_addr_t prev_hdr_addr= flst_get_prev_addr(b->page.frame + hdr_addr.boffset + @@ -498,6 +562,7 @@ trx_purge_truncate_rseg_history(trx_rseg_t &rseg, mtr.commit(); ut_ad(rseg.history_size > 0); rseg.history_size--; + freed= true; mtr.start(); rseg_hdr->page.lock.x_lock(); ut_ad(rseg_hdr->page.id() == rseg.page_id()); @@ -552,9 +617,7 @@ dberr_t purge_sys_t::iterator::free_history() const ut_ad(rseg.is_persistent()); log_free_check(); rseg.latch.wr_lock(SRW_LOCK_CALL); - dberr_t err= - trx_purge_truncate_rseg_history(rseg, *this, !rseg.is_referenced() && - purge_sys.sees(rseg.needs_purge)); + dberr_t err= free_history_rseg(rseg); rseg.latch.wr_unlock(); if (err) return err; @@ -562,6 +625,62 @@ dberr_t purge_sys_t::iterator::free_history() const return DB_SUCCESS; } +inline void trx_sys_t::undo_truncate_start(fil_space_t &space) +{ + ut_ad(this == &trx_sys); + /* Undo tablespace always are a single file. */ + ut_a(UT_LIST_GET_LEN(space.chain) == 1); + fil_node_t *file= UT_LIST_GET_FIRST(space.chain); + /* The undo tablespace files are never closed. */ + ut_ad(file->is_open()); + sql_print_information("InnoDB: Starting to truncate %s", file->name); + + for (auto &rseg : rseg_array) + if (rseg.space == &space) + { + /* Prevent a race with purge_sys_t::iterator::free_history_rseg() */ + rseg.latch.rd_lock(SRW_LOCK_CALL); + /* Once set, this rseg will not be allocated to subsequent + transactions, but we will wait for existing active + transactions to finish. */ + rseg.set_skip_allocation(); + rseg.latch.rd_unlock(); + } +} + +inline fil_space_t *purge_sys_t::undo_truncate_try(uint32_t id, uint32_t size) +{ + ut_ad(srv_is_undo_tablespace(id)); + fil_space_t *space= fil_space_get(id); + if (space && space->get_size() > size) + { + truncate_undo_space.current= space; + trx_sys.undo_truncate_start(*space); + return space; + } + return nullptr; +} + +fil_space_t *purge_sys_t::truncating_tablespace() +{ + ut_ad(this == &purge_sys); + + fil_space_t *space= truncate_undo_space.current; + if (space || srv_undo_tablespaces_active < 2 || !srv_undo_log_truncate) + return space; + + const uint32_t size= uint32_t(srv_max_undo_log_size >> srv_page_size_shift); + for (uint32_t i= truncate_undo_space.last, j= i;; ) + { + if (fil_space_t *s= undo_truncate_try(srv_undo_space_id_start + i, size)) + return s; + ++i; + i%= srv_undo_tablespaces_active; + if (i == j) + return nullptr; + } +} + #if defined __GNUC__ && __GNUC__ == 4 && !defined __clang__ # if defined __arm__ || defined __aarch64__ /* Work around an internal compiler error in GCC 4.8.5 */ @@ -587,55 +706,14 @@ TRANSACTIONAL_TARGET void trx_purge_truncate_history() head.undo_no= 0; } - if (head.free_history() != DB_SUCCESS || srv_undo_tablespaces_active < 2) + if (head.free_history() != DB_SUCCESS) return; - while (srv_undo_log_truncate) + while (fil_space_t *space= purge_sys.truncating_tablespace()) { - if (!purge_sys.truncate.current) - { - const ulint threshold= - ulint(srv_max_undo_log_size >> srv_page_size_shift); - for (uint32_t i= purge_sys.truncate.last - ? purge_sys.truncate.last->id - srv_undo_space_id_start : 0, - j= i;; ) - { - const uint32_t space_id= srv_undo_space_id_start + i; - ut_ad(srv_is_undo_tablespace(space_id)); - fil_space_t *space= fil_space_get(space_id); - ut_a(UT_LIST_GET_LEN(space->chain) == 1); - - if (space && space->get_size() > threshold) - { - purge_sys.truncate.current= space; - break; - } - - ++i; - i %= srv_undo_tablespaces_active; - if (i == j) - return; - } - } - - fil_space_t &space= *purge_sys.truncate.current; - /* Undo tablespace always are a single file. */ - fil_node_t *file= UT_LIST_GET_FIRST(space.chain); - /* The undo tablespace files are never closed. */ - ut_ad(file->is_open()); - - DBUG_LOG("undo", "marking for truncate: " << file->name); - - for (auto &rseg : trx_sys.rseg_array) - if (rseg.space == &space) - /* Once set, this rseg will not be allocated to subsequent - transactions, but we will wait for existing active - transactions to finish. */ - rseg.set_skip_allocation(); - for (auto &rseg : trx_sys.rseg_array) { - if (rseg.space != &space) + if (rseg.space != space) continue; rseg.latch.rd_lock(SRW_LOCK_CALL); @@ -668,8 +746,9 @@ TRANSACTIONAL_TARGET void trx_purge_truncate_history() rseg.latch.rd_unlock(); } - sql_print_information("InnoDB: Truncating %s", file->name); - trx_purge_cleanse_purge_queue(space); + const char *file_name= UT_LIST_GET_FIRST(space->chain)->name; + sql_print_information("InnoDB: Truncating %s", file_name); + trx_purge_cleanse_purge_queue(*space); /* Lock all modified pages of the tablespace. @@ -686,12 +765,12 @@ TRANSACTIONAL_TARGET void trx_purge_truncate_history() /* Adjust the tablespace metadata. */ mysql_mutex_lock(&fil_system.mutex); - if (space.crypt_data) + if (space->crypt_data) { - space.reacquire(); + space->reacquire(); mysql_mutex_unlock(&fil_system.mutex); - fil_space_crypt_close_tablespace(&space); - space.release(); + fil_space_crypt_close_tablespace(space); + space->release(); } else mysql_mutex_unlock(&fil_system.mutex); @@ -703,17 +782,17 @@ TRANSACTIONAL_TARGET void trx_purge_truncate_history() mtr_t mtr; mtr.start(); - mtr.x_lock_space(&space); + mtr.x_lock_space(space); /* Associate the undo tablespace with mtr. During mtr::commit_shrink(), InnoDB can use the undo tablespace object to clear all freed ranges */ - mtr.set_named_space(&space); - mtr.trim_pages(page_id_t(space.id, size)); - ut_a(fsp_header_init(&space, size, &mtr) == DB_SUCCESS); + mtr.set_named_space(space); + mtr.trim_pages(page_id_t(space->id, size)); + ut_a(fsp_header_init(space, size, &mtr) == DB_SUCCESS); for (auto &rseg : trx_sys.rseg_array) { - if (rseg.space != &space) + if (rseg.space != space) continue; ut_ad(!rseg.is_referenced()); @@ -722,7 +801,7 @@ TRANSACTIONAL_TARGET void trx_purge_truncate_history() possibly before this server had been started up. */ dberr_t err; - buf_block_t *rblock= trx_rseg_header_create(&space, + buf_block_t *rblock= trx_rseg_header_create(space, &rseg - trx_sys.rseg_array, trx_sys.get_max_trx_id(), &mtr, &err); @@ -735,7 +814,7 @@ TRANSACTIONAL_TARGET void trx_purge_truncate_history() rseg.reinit(rblock->page.id().page_no()); } - mtr.commit_shrink(space, size); + mtr.commit_shrink(*space, size); /* No mutex; this is only updated by the purge coordinator. */ export_vars.innodb_undo_truncations++; @@ -757,10 +836,10 @@ TRANSACTIONAL_TARGET void trx_purge_truncate_history() log_buffer_flush_to_disk(); DBUG_SUICIDE();); - sql_print_information("InnoDB: Truncated %s", file->name); - purge_sys.truncate.last= purge_sys.truncate.current; - ut_ad(&space == purge_sys.truncate.current); - purge_sys.truncate.current= nullptr; + sql_print_information("InnoDB: Truncated %s", file_name); + ut_ad(space == purge_sys.truncate_undo_space.current); + purge_sys.truncate_undo_space.current= nullptr; + purge_sys.truncate_undo_space.last= space->id - srv_undo_space_id_start; } } diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index d17f84248f12d..566a753fe9eb4 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -902,15 +902,13 @@ trx_undo_truncate_start( trx_undo_rec_t* last_rec; mtr_t mtr; + ut_ad(rseg->is_persistent()); + if (!limit) { return DB_SUCCESS; } loop: - mtr_start(&mtr); - - if (!rseg->is_persistent()) { - mtr.set_log_mode(MTR_LOG_NO_REDO); - } + mtr.start(); dberr_t err; const buf_block_t* undo_page; diff --git a/storage/maria/unittest/ma_pagecache_consist.c b/storage/maria/unittest/ma_pagecache_consist.c index ff4a2bcb33a5a..938e5b102c951 100644 --- a/storage/maria/unittest/ma_pagecache_consist.c +++ b/storage/maria/unittest/ma_pagecache_consist.c @@ -403,10 +403,6 @@ int main(int argc __attribute__((unused)), exit(1); } -#ifdef HAVE_THR_SETCONCURRENCY - thr_setconcurrency(2); -#endif - if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, TEST_PAGE_SIZE, 0, 0)) == 0) { diff --git a/storage/maria/unittest/ma_pagecache_rwconsist.c b/storage/maria/unittest/ma_pagecache_rwconsist.c index 24c30245bac63..e059ac4551158 100644 --- a/storage/maria/unittest/ma_pagecache_rwconsist.c +++ b/storage/maria/unittest/ma_pagecache_rwconsist.c @@ -272,10 +272,6 @@ int main(int argc __attribute__((unused)), exit(1); } -#ifdef HAVE_THR_SETCONCURRENCY - thr_setconcurrency(2); -#endif - if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, TEST_PAGE_SIZE, 0, 0)) == 0) { diff --git a/storage/maria/unittest/ma_pagecache_rwconsist2.c b/storage/maria/unittest/ma_pagecache_rwconsist2.c index c92bec3ca41d1..28d3bb8dcb8c9 100644 --- a/storage/maria/unittest/ma_pagecache_rwconsist2.c +++ b/storage/maria/unittest/ma_pagecache_rwconsist2.c @@ -268,10 +268,6 @@ int main(int argc __attribute__((unused)), exit(1); } -#ifdef HAVE_THR_SETCONCURRENCY - thr_setconcurrency(2); -#endif - if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, TEST_PAGE_SIZE, 0, 0)) == 0) { diff --git a/storage/maria/unittest/ma_pagecache_single.c b/storage/maria/unittest/ma_pagecache_single.c index de2ecaecfc45a..9009e59c24535 100644 --- a/storage/maria/unittest/ma_pagecache_single.c +++ b/storage/maria/unittest/ma_pagecache_single.c @@ -795,10 +795,6 @@ int main(int argc __attribute__((unused)), exit(1); } -#ifdef HAVE_THR_SETCONCURRENCY - thr_setconcurrency(2); -#endif - if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, TEST_PAGE_SIZE, 0, MYF(MY_WME))) == 0) { diff --git a/storage/maria/unittest/ma_test_loghandler_multithread-t.c b/storage/maria/unittest/ma_test_loghandler_multithread-t.c index ec097ede0361a..be6046abab47f 100644 --- a/storage/maria/unittest/ma_test_loghandler_multithread-t.c +++ b/storage/maria/unittest/ma_test_loghandler_multithread-t.c @@ -331,10 +331,6 @@ int main(int argc __attribute__((unused)), exit(1); } -#ifdef HAVE_THR_SETCONCURRENCY - thr_setconcurrency(2); -#endif - if (ma_control_file_open(TRUE, TRUE, TRUE)) { fprintf(stderr, "Can't init control file (%d)\n", errno); diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index 3c5b23f559fc9..103ce50dd6378 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -3541,7 +3541,8 @@ CSphSEStats * sphinx_get_stats ( THD * thd, SHOW_VAR * out ) return 0; } -int sphinx_showfunc_total ( THD * thd, SHOW_VAR * out, char * ) +static int sphinx_showfunc_total ( THD * thd, SHOW_VAR * out, void *, + system_status_var *, enum_var_type ) { CSphSEStats * pStats = sphinx_get_stats ( thd, out ); if ( pStats ) @@ -3552,7 +3553,8 @@ int sphinx_showfunc_total ( THD * thd, SHOW_VAR * out, char * ) return 0; } -int sphinx_showfunc_total_found ( THD * thd, SHOW_VAR * out, char * ) +static int sphinx_showfunc_total_found ( THD * thd, SHOW_VAR * out, void *, + system_status_var *, enum_var_type ) { CSphSEStats * pStats = sphinx_get_stats ( thd, out ); if ( pStats ) @@ -3563,7 +3565,8 @@ int sphinx_showfunc_total_found ( THD * thd, SHOW_VAR * out, char * ) return 0; } -int sphinx_showfunc_time ( THD * thd, SHOW_VAR * out, char * ) +static int sphinx_showfunc_time ( THD * thd, SHOW_VAR * out, void *, + system_status_var *, enum_var_type ) { CSphSEStats * pStats = sphinx_get_stats ( thd, out ); if ( pStats ) @@ -3574,7 +3577,8 @@ int sphinx_showfunc_time ( THD * thd, SHOW_VAR * out, char * ) return 0; } -int sphinx_showfunc_word_count ( THD * thd, SHOW_VAR * out, char * ) +static int sphinx_showfunc_word_count ( THD * thd, SHOW_VAR * out, void *, + system_status_var *, enum_var_type ) { CSphSEStats * pStats = sphinx_get_stats ( thd, out ); if ( pStats ) @@ -3585,9 +3589,11 @@ int sphinx_showfunc_word_count ( THD * thd, SHOW_VAR * out, char * ) return 0; } -int sphinx_showfunc_words ( THD * thd, SHOW_VAR * out, char * sBuffer ) +static int sphinx_showfunc_words ( THD * thd, SHOW_VAR * out, void * buf, + system_status_var *, enum_var_type ) { #if MYSQL_VERSION_ID>50100 + char *sBuffer = static_cast(buf); if ( sphinx_hton_ptr ) { CSphTLS * pTls = (CSphTLS *) thd_get_ha_data ( thd, sphinx_hton_ptr ); @@ -3642,7 +3648,8 @@ int sphinx_showfunc_words ( THD * thd, SHOW_VAR * out, char * sBuffer ) return 0; } -int sphinx_showfunc_error ( THD * thd, SHOW_VAR * out, char * ) +static int sphinx_showfunc_error ( THD * thd, SHOW_VAR * out, void *, + system_status_var *, enum_var_type ) { CSphSEStats * pStats = sphinx_get_stats ( thd, out ); out->type = SHOW_CHAR; diff --git a/storage/sphinx/ha_sphinx.h b/storage/sphinx/ha_sphinx.h index f5651fc6eb579..db41b7bd2fb85 100644 --- a/storage/sphinx/ha_sphinx.h +++ b/storage/sphinx/ha_sphinx.h @@ -178,12 +178,6 @@ class ha_sphinx final : public handler bool sphinx_show_status ( THD * thd ); #endif -int sphinx_showfunc_total_found ( THD *, SHOW_VAR *, char * ); -int sphinx_showfunc_total ( THD *, SHOW_VAR *, char * ); -int sphinx_showfunc_time ( THD *, SHOW_VAR *, char * ); -int sphinx_showfunc_word_count ( THD *, SHOW_VAR *, char * ); -int sphinx_showfunc_words ( THD *, SHOW_VAR *, char * ); - // // $Id: ha_sphinx.h 4818 2014-09-24 08:53:38Z tomat $ // diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index 05fff7201df14..09cf619323721 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -8506,7 +8506,10 @@ int ha_spider::create( if ( thd->lex->create_info.or_replace() && (error_num = spider_delete_tables( - table_tables, tmp_share.table_name, &dummy)) + table_tables, tmp_share.table_name, &dummy)) && + /* In this context, no key found in mysql.spider_tables means + the Spider table does not exist */ + error_num != HA_ERR_KEY_NOT_FOUND ) { goto error; } @@ -8913,6 +8916,10 @@ int ha_spider::delete_table( (error_num = spider_delete_tables( table_tables, name, &old_link_count)) ) { + /* In this context, no key found in mysql.spider_tables means + the Spider table does not exist */ + if (error_num == HA_ERR_KEY_NOT_FOUND) + error_num= HA_ERR_NO_SUCH_TABLE; goto error; } spider_sys_close_table(current_thd, &open_tables_backup); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_26151.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_26151.result index b0a430e0e212e..326b84a030e4b 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_26151.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_26151.result @@ -6,6 +6,9 @@ for child2 for child3 set @old_spider_bgs_mode= @@spider_bgs_mode; set session spider_bgs_mode=1; +set spider_same_server_link=1; +set @old_spider_same_server_link=@@global.spider_same_server_link; +set global spider_same_server_link=1; CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table td (a int, PRIMARY KEY (a)); create table ts (a int, PRIMARY KEY (a)) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv_mdev_26151",TABLE "td", casual_read "3"'; @@ -26,6 +29,7 @@ min(a) drop table td, ts; drop server srv_mdev_26151; set session spider_bgs_mode=@old_spider_bgs_mode; +set global spider_same_server_link=@old_spider_same_server_link; for master_1 for child2 for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28739_simple.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28739_simple.result index db232f8a6d373..1c337c3d2dd4c 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_28739_simple.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28739_simple.result @@ -5,6 +5,7 @@ for master_1 for child2 for child3 set global query_cache_type= on; +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t2 (c int); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28856.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28856.result index fae3cc6b6ce76..7e4fd3cd08466 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_28856.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28856.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); # testing monitoring_* diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28998.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28998.result index d664b090af6ec..e92fb19957567 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_28998.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28998.result @@ -4,8 +4,7 @@ for master_1 for child2 for child3 -set @old_spider_disable_group_by_handler=@@spider_disable_group_by_handler; -set spider_disable_group_by_handler=1; +set spider_same_server_link=1; CREATE SERVER s FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2); @@ -17,7 +16,6 @@ a 2 DROP TABLE t2, t1_SPIDER, t1; drop server s; -set spider_disable_group_by_handler=@old_spider_disable_group_by_handler; for master_1 for child2 for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29002.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29002.result new file mode 100644 index 0000000000000..894f51c5e3670 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29002.result @@ -0,0 +1,34 @@ +for master_1 +for child2 +for child3 +SET spider_same_server_link= on; +CREATE SERVER s FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +CREATE TABLE t (a INT); +CREATE TABLE t1_spider (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't'"; +CREATE TABLE t2_spider (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't'"; +SELECT * FROM t1_spider, t2_spider; +a a +SELECT table_name, index_name, cardinality FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name IN ('t1_spider','t2_spider'); +table_name index_name cardinality +RENAME TABLE t1_spider TO t3_spider; +SELECT * FROM t3_spider; +a +DROP TABLE t3_spider, t2_spider, t; +drop server s; +CREATE TABLE t1 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",HOST "srv",TABLE "t"'; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",HOST "srv",TABLE "t"'; +CREATE TABLE t3 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",HOST "srv",TABLE "t"'; +SHOW TABLE STATUS; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary +t1 SPIDER 10 NULL 0 0 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL Unable to connect to foreign data source: srv 0 +t2 SPIDER 10 NULL 0 0 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL Unable to connect to foreign data source: srv 0 +t3 SPIDER 10 NULL 0 0 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL Unable to connect to foreign data source: srv 0 +Warnings: +Warning 1429 Unable to connect to foreign data source: srv +Warning 1429 Unable to connect to foreign data source: srv +Warning 1429 Unable to connect to foreign data source: srv +drop table t1, t2, t3; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result index af4bef1efa987..f58ab605e111c 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER s FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 (a INT); CREATE TABLE t2 (b INT); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29456.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29456.result index 4d9095830d1e5..365c3d6373ad3 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_29456.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29456.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t1 (c int); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29502.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29502.result index 54c5e9a6473ef..7749898eb6f02 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_29502.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29502.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t (a INT); INSERT INTO t VALUES (23),(48); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29963.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29963.result index 17390346a9934..604515964f3fb 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_29963.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29963.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t (a INT) ENGINE=Spider; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_30014.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_30014.result index fd05aa155e44c..e971f323b49c7 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_30014.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_30014.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t1 (c int); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_30170.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_30170.result new file mode 100644 index 0000000000000..2183447bfa375 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_30170.result @@ -0,0 +1,7 @@ +install soname 'ha_spider'; +DROP TABLE non_existing_table; +ERROR 42S02: Unknown table 'test.non_existing_table' +create or replace table non_existing_table (c int) engine=Spider; +drop table non_existing_table; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result index 58873d2c6e55c..cefa5248d44f7 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_31338.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_31338.result index 62b06336ff6b5..f156cf38a15c2 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_31338.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_31338.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t (c BLOB) ENGINE=InnoDB; CREATE TABLE ts (c BLOB) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_31524.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_31524.result index c1aa7a1f035ba..268779678b813 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_31524.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_31524.result @@ -5,6 +5,7 @@ for master_1 for child2 for child3 SET @old_spider_read_only_mode = @@session.spider_read_only_mode; +set spider_same_server_link=1; CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); set session spider_read_only_mode = default; create table t2 (c int); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result index 94b76de7df477..5197abd3fb6dc 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 ( a bigint(20) NOT NULL, b bigint(20) DEFAULT 0, PRIMARY KEY (a)); CREATE TABLE t2 ( a bigint(20) NOT NULL, b bigint(20) DEFAULT 0, PRIMARY KEY (a)) ENGINE=SPIDER COMMENT='srv "srv", WRAPPER "mysql", TABLE "t1"'; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_31996.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_31996.result index 04d7e88467635..cbc91432dbc3b 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_31996.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_31996.result @@ -1,6 +1,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); set session spider_delete_all_rows_type=0; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_32986.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_32986.result index bdc580d421ac4..c3bdef9870d92 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_32986.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_32986.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t2 (c varchar(16)); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_33008.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_33008.result new file mode 100644 index 0000000000000..3bcb4bb038ab8 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_33008.result @@ -0,0 +1,25 @@ +for master_1 +for child2 +for child3 +set spider_same_server_link=on; +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`code` varchar(10) DEFAULT NULL, +PRIMARY KEY (`id`) +); +create table t1 ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `code` varchar(10) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=SPIDER DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"' +drop table t1, t2; +drop server srv; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/self_reference_multi.result b/storage/spider/mysql-test/spider/bugfix/r/self_reference_multi.result index 196e48d5a52dd..0118f57578faf 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/self_reference_multi.result +++ b/storage/spider/mysql-test/spider/bugfix/r/self_reference_multi.result @@ -4,6 +4,9 @@ for child3 MDEV-6268 SPIDER table with no COMMENT clause causes queries to wait forever +set spider_same_server_link=1; +set @old_spider_same_server_link=@@global.spider_same_server_link; +set global spider_same_server_link=1; CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t2 (c int); create table t1 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv_self_reference_multi",TABLE "t2"'; @@ -17,6 +20,7 @@ select * from t2; ERROR HY000: An infinite loop is detected when opening table test.t0 drop table t0, t1, t2; drop server srv_self_reference_multi; +set global spider_same_server_link=@old_spider_same_server_link; for master_1 for child2 for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/signal_ddl_fail.result b/storage/spider/mysql-test/spider/bugfix/r/signal_ddl_fail.result new file mode 100644 index 0000000000000..c86e600b2c1b2 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/signal_ddl_fail.result @@ -0,0 +1,8 @@ +# +# MDEV-32559 Move alter table statements in spider init queries to be executed in the signal_ddl_recovery_done callback +# +select * from mysql.plugin; +name dl +# +# end of test signal_ddl_fail +# diff --git a/storage/spider/mysql-test/spider/bugfix/r/spider_join_with_non_spider.result b/storage/spider/mysql-test/spider/bugfix/r/spider_join_with_non_spider.result index b9c1c5c9de550..420ca657a339d 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/spider_join_with_non_spider.result +++ b/storage/spider/mysql-test/spider/bugfix/r/spider_join_with_non_spider.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t1 (c int); create table t2 (d int); diff --git a/storage/spider/mysql-test/spider/bugfix/r/subquery.result b/storage/spider/mysql-test/spider/bugfix/r/subquery.result index c6ea45e2dc0a4..280f57155bdb8 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/subquery.result +++ b/storage/spider/mysql-test/spider/bugfix/r/subquery.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t1 (c1 int); create table t2 (c2 int); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_26151.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_26151.test index f9e157d33e60d..dcf1438fb8088 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_26151.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_26151.test @@ -14,6 +14,10 @@ --let $srv=srv_mdev_26151 set @old_spider_bgs_mode= @@spider_bgs_mode; set session spider_bgs_mode=1; +set spider_same_server_link=1; +set @old_spider_same_server_link=@@global.spider_same_server_link; +set global spider_same_server_link=1; + evalp CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); # casual_read != 0 && casual_read != 1 @@ -42,6 +46,7 @@ drop table td, ts; eval drop server $srv; set session spider_bgs_mode=@old_spider_bgs_mode; +set global spider_same_server_link=@old_spider_same_server_link; --disable_query_log --disable_result_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28739_simple.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28739_simple.test index 7a011520bb6e7..feff85df6b37e 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_28739_simple.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28739_simple.test @@ -12,6 +12,7 @@ #set @@global.debug_dbug="d:t:i:o,mysqld.trace"; set global query_cache_type= on; +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t2 (c int); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28856.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28856.test index 4f23168ec1b57..a1642f7a9cdbe 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_28856.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28856.test @@ -9,6 +9,7 @@ # This test covers some table params under consideration for inclusion # in the engine-defined options to be implemented in MDEV-28856. +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test index d67011ca8379b..66e3a15addbd1 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test @@ -12,9 +12,7 @@ if (`select not(count(*)) from information_schema.system_variables where variabl --source ../../t/test_init.inc --enable_result_log --enable_query_log -# FIXME: this is a workaround. -set @old_spider_disable_group_by_handler=@@spider_disable_group_by_handler; -set spider_disable_group_by_handler=1; +set spider_same_server_link=1; evalp CREATE SERVER s FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 (a INT); @@ -27,7 +25,6 @@ SELECT * FROM t2; # Cleanup DROP TABLE t2, t1_SPIDER, t1; drop server s; -set spider_disable_group_by_handler=@old_spider_disable_group_by_handler; --disable_query_log --disable_result_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29002.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29002.test new file mode 100644 index 0000000000000..51620a5a23c91 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29002.test @@ -0,0 +1,32 @@ +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log +SET spider_same_server_link= on; +evalp CREATE SERVER s FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); + +CREATE TABLE t (a INT); +CREATE TABLE t1_spider (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't'"; +CREATE TABLE t2_spider (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't'"; +SELECT * FROM t1_spider, t2_spider; +SELECT table_name, index_name, cardinality FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name IN ('t1_spider','t2_spider'); +RENAME TABLE t1_spider TO t3_spider; +SELECT * FROM t3_spider; + +DROP TABLE t3_spider, t2_spider, t; +drop server s; + +# case by roel +CREATE TABLE t1 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",HOST "srv",TABLE "t"'; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",HOST "srv",TABLE "t"'; +CREATE TABLE t3 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",HOST "srv",TABLE "t"'; +SHOW TABLE STATUS; +drop table t1, t2, t3; + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29163.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29163.test index ac116fd0e4fef..2e56583d8311a 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_29163.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29163.test @@ -6,6 +6,7 @@ --source ../../t/test_init.inc --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER s FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 (a INT); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29456.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29456.test index 16291f82075f2..89d53227c6c5d 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_29456.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29456.test @@ -8,6 +8,7 @@ --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29502.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29502.test index 88591f803f5d0..bacf50731250c 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_29502.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29502.test @@ -8,6 +8,7 @@ --enable_result_log --enable_query_log +set spider_same_server_link=1; --let $srv=srv_mdev_29502 evalp CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29963.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29963.test index ab7a4ded07cdc..93b38c7963c60 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_29963.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29963.test @@ -7,6 +7,7 @@ --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_30014.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_30014.test index 4dc3dafab24ac..9c59adc80dd02 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_30014.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_30014.test @@ -7,6 +7,7 @@ --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_30170.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_30170.test new file mode 100644 index 0000000000000..690268432d33e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_30170.test @@ -0,0 +1,8 @@ +install soname 'ha_spider'; +--error ER_BAD_TABLE_ERROR +DROP TABLE non_existing_table; +# Test that create or replace a non existing spider table work +create or replace table non_existing_table (c int) engine=Spider; +drop table non_existing_table; +--disable_query_log +--source ../../include/clean_up_spider.inc diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_30392.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_30392.test index 03417013b0749..36e06f3f3c467 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_30392.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_30392.test @@ -6,6 +6,7 @@ --source ../../t/test_init.inc --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 (a INT); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_31338.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_31338.test index e628c3b921d64..a3698c9771723 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_31338.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_31338.test @@ -9,6 +9,7 @@ --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t (c BLOB) ENGINE=InnoDB; CREATE TABLE ts (c BLOB) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_31524.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_31524.test index 64cbf4154aa12..a5942fad2b303 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_31524.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_31524.test @@ -10,6 +10,7 @@ --let $srv=srv_mdev_31524 SET @old_spider_read_only_mode = @@session.spider_read_only_mode; +set spider_same_server_link=1; evalp CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); # when the user does not set var nor the table option, the default diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_31645.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_31645.test index bec9dd6c3162b..4dfe3b57e5019 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_31645.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_31645.test @@ -6,6 +6,7 @@ --source ../../t/test_init.inc --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 ( a bigint(20) NOT NULL, b bigint(20) DEFAULT 0, PRIMARY KEY (a)); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_31996.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_31996.test index 3e823790c8274..93b004a06ebe9 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_31996.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_31996.test @@ -4,6 +4,7 @@ --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32986.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_32986.test index 94081d24ad809..144387452f7c2 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_32986.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32986.test @@ -6,6 +6,7 @@ --source ../../t/test_init.inc --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33008.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_33008.test new file mode 100644 index 0000000000000..48d9a4f01ec72 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33008.test @@ -0,0 +1,24 @@ +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log +set spider_same_server_link=on; +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `code` varchar(10) DEFAULT NULL, + PRIMARY KEY (`id`) +); +create table t1 ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +show create table t1; +drop table t1, t2; + +drop server srv; +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/self_reference_multi.test b/storage/spider/mysql-test/spider/bugfix/t/self_reference_multi.test index 2ac927d99b3f4..4263560baa1e2 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/self_reference_multi.test +++ b/storage/spider/mysql-test/spider/bugfix/t/self_reference_multi.test @@ -8,6 +8,9 @@ --echo MDEV-6268 SPIDER table with no COMMENT clause causes queries to wait forever --echo +set spider_same_server_link=1; +set @old_spider_same_server_link=@@global.spider_same_server_link; +set global spider_same_server_link=1; --let $srv=srv_self_reference_multi evalp CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t2 (c int); @@ -22,6 +25,7 @@ select * from t1; select * from t2; drop table t0, t1, t2; eval drop server $srv; +set global spider_same_server_link=@old_spider_same_server_link; --disable_query_log --disable_result_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.opt b/storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.opt new file mode 100644 index 0000000000000..d883df7bed296 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.opt @@ -0,0 +1,2 @@ +--plugin-load-add=ha_spider +--debug-dbug=d,fail_spider_ddl_recovery_done diff --git a/storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.test b/storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.test new file mode 100644 index 0000000000000..f13eae3a06293 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.test @@ -0,0 +1,10 @@ +--source include/have_debug.inc +--echo # +--echo # MDEV-32559 Move alter table statements in spider init queries to be executed in the signal_ddl_recovery_done callback +--echo # +# This test tests that failure in ddl_recovery callback causes the +# plugin to be deinitialized. +select * from mysql.plugin; +--echo # +--echo # end of test signal_ddl_fail +--echo # diff --git a/storage/spider/mysql-test/spider/bugfix/t/spider_join_with_non_spider.test b/storage/spider/mysql-test/spider/bugfix/t/spider_join_with_non_spider.test index 7b5d38014ed99..294b469a8a559 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/spider_join_with_non_spider.test +++ b/storage/spider/mysql-test/spider/bugfix/t/spider_join_with_non_spider.test @@ -8,6 +8,7 @@ --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t1 (c int); create table t2 (d int); diff --git a/storage/spider/mysql-test/spider/bugfix/t/subquery.test b/storage/spider/mysql-test/spider/bugfix/t/subquery.test index 7a50719603d56..70238a524a6ed 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/subquery.test +++ b/storage/spider/mysql-test/spider/bugfix/t/subquery.test @@ -6,6 +6,7 @@ --source ../../t/test_init.inc --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t1 (c1 int); create table t2 (c2 int); diff --git a/storage/spider/mysql-test/spider/r/variable_deprecation.result b/storage/spider/mysql-test/spider/r/variable_deprecation.result index cea36ff224074..be964ce4c398f 100644 --- a/storage/spider/mysql-test/spider/r/variable_deprecation.result +++ b/storage/spider/mysql-test/spider/r/variable_deprecation.result @@ -75,8 +75,6 @@ Warning 1287 '@@spider_load_crd_at_startup' is deprecated and will be removed in SHOW VARIABLES LIKE "spider_load_crd_at_startup"; Variable_name Value spider_load_crd_at_startup 0 -DROP TABLE tbl_a; -DROP TABLE tbl_b; # MDEV-28008 Deprecate spider_crd_mode and spider_sts_mode SET spider_crd_mode = 1; Warnings: diff --git a/storage/spider/mysql-test/spider/t/variable_deprecation.test b/storage/spider/mysql-test/spider/t/variable_deprecation.test index 3ed8dcf5ec65f..6159b25b053b3 100644 --- a/storage/spider/mysql-test/spider/t/variable_deprecation.test +++ b/storage/spider/mysql-test/spider/t/variable_deprecation.test @@ -47,9 +47,6 @@ SHOW VARIABLES LIKE "spider_load_sts_at_startup"; SET GLOBAL spider_load_crd_at_startup = 0; SHOW VARIABLES LIKE "spider_load_crd_at_startup"; -DROP TABLE tbl_a; -DROP TABLE tbl_b; - --echo # MDEV-28008 Deprecate spider_crd_mode and spider_sts_mode SET spider_crd_mode = 1; SHOW VARIABLES LIKE "spider_crd_mode"; diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index d8288ef1383b1..b2079f5286f9c 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -1199,13 +1199,7 @@ int spider_conn_queue_and_merge_loop_check( lcptr->flag = SPIDER_LOP_CHK_MERAGED; lcptr->next = NULL; if (!conn->loop_check_meraged_first) - { conn->loop_check_meraged_first = lcptr; - conn->loop_check_meraged_last = lcptr; - } else { - conn->loop_check_meraged_last->next = lcptr; - conn->loop_check_meraged_last = lcptr; - } } DBUG_RETURN(0); @@ -1298,7 +1292,7 @@ int spider_conn_queue_loop_check( loop_check_buf[lex_str.length] = '\0'; DBUG_PRINT("info", ("spider param name=%s", lex_str.str)); 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")); lex_str.str = ""; diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index f774296c06e37..0c7f69f7b5cf2 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -1531,10 +1531,13 @@ int spider_db_mbase_result::fetch_index_for_discover_table_structure( } DBUG_RETURN(0); } - if (num_fields() != 13) + if (num_fields() < 13) { - DBUG_PRINT("info",("spider num_fields != 13")); - my_printf_error(ER_SPIDER_UNKNOWN_NUM, ER_SPIDER_UNKNOWN_STR, MYF(0)); + DBUG_PRINT("info",("spider num_fields < 13")); + my_printf_error(ER_SPIDER_CANT_NUM, ER_SPIDER_CANT_STR1, MYF(0), + "fetch index for table structure discovery because of " + "wrong number of columns in SHOW INDEX FROM output: ", + num_fields()); DBUG_RETURN(ER_SPIDER_UNKNOWN_NUM); } bool first = TRUE; @@ -1931,7 +1934,7 @@ int spider_db_mbase::connect( if (!spider_param_same_server_link(thd)) { - if (!strcmp(tgt_host, my_localhost)) + if (!strcmp(tgt_host, my_localhost) || !tgt_host || !tgt_host[0]) { if (!strcmp(tgt_socket, *spd_mysqld_unix_port)) { @@ -1941,7 +1944,7 @@ int spider_db_mbase::connect( DBUG_RETURN(ER_SPIDER_SAME_SERVER_LINK_NUM); } } else if (!strcmp(tgt_host, "127.0.0.1") || - !strcmp(tgt_host, glob_hostname)) + !strcmp(tgt_host, glob_hostname) || !tgt_host || !tgt_host[0]) { if (tgt_port == (long) *spd_mysqld_port) { diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index 8ce18e401b08d..cc7301449c230 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -793,7 +793,6 @@ typedef struct st_spider_conn SPIDER_CONN_LOOP_CHECK *loop_check_ignored_first; SPIDER_CONN_LOOP_CHECK *loop_check_ignored_last; SPIDER_CONN_LOOP_CHECK *loop_check_meraged_first; - SPIDER_CONN_LOOP_CHECK *loop_check_meraged_last; } SPIDER_CONN; typedef struct st_spider_lgtm_tblhnd_share diff --git a/storage/spider/spd_param.cc b/storage/spider/spd_param.cc index 62414dd1aa75f..9712c95d363c4 100644 --- a/storage/spider/spd_param.cc +++ b/storage/spider/spd_param.cc @@ -110,7 +110,7 @@ extern volatile ulonglong spider_mon_table_cache_version_req; } extern handlerton *spider_hton_ptr; -static void spider_trx_status_var(THD *thd, SHOW_VAR *var, char *buff, +static void spider_trx_status_var(THD *thd, SHOW_VAR *var, void *buff, ulonglong SPIDER_TRX::*counter) { DBUG_ENTER("spider_direct_update"); @@ -126,35 +126,40 @@ static void spider_trx_status_var(THD *thd, SHOW_VAR *var, char *buff, } -static int spider_direct_update(THD *thd, SHOW_VAR *var, char *buff) +static int spider_direct_update(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { DBUG_ENTER("spider_direct_update"); spider_trx_status_var(thd, var, buff, &SPIDER_TRX::direct_update_count); DBUG_RETURN(0); } -static int spider_direct_delete(THD *thd, SHOW_VAR *var, char *buff) +static int spider_direct_delete(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { DBUG_ENTER("spider_direct_delete"); spider_trx_status_var(thd, var, buff, &SPIDER_TRX::direct_delete_count); DBUG_RETURN(0); } -static int spider_direct_order_limit(THD *thd, SHOW_VAR *var, char *buff) +static int spider_direct_order_limit(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { DBUG_ENTER("spider_direct_order_limit"); spider_trx_status_var(thd, var, buff, &SPIDER_TRX::direct_order_limit_count); DBUG_RETURN(0); } -static int spider_direct_aggregate(THD *thd, SHOW_VAR *var, char *buff) +static int spider_direct_aggregate(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { DBUG_ENTER("spider_direct_aggregate"); spider_trx_status_var(thd, var, buff, &SPIDER_TRX::direct_aggregate_count); DBUG_RETURN(0); } -static int spider_parallel_search(THD *thd, SHOW_VAR *var, char *buff) +static int spider_parallel_search(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { DBUG_ENTER("spider_parallel_search"); spider_trx_status_var(thd, var, buff, &SPIDER_TRX::parallel_search_count); diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc index af3371cd040f8..08eea15a76efb 100644 --- a/storage/spider/spd_sys_table.cc +++ b/storage/spider/spd_sys_table.cc @@ -1764,6 +1764,16 @@ int spider_delete_xa_member( DBUG_RETURN(0); } +/** + Delete a Spider table from mysql.spider_tables. + + @param table The table mysql.spider_tables + @param name The name of the Spider table to delete + @param old_link_count The number of links in the deleted table + + @retval 0 Success + @retval nonzero Failure +*/ int spider_delete_tables( TABLE *table, const char *name, @@ -1779,10 +1789,20 @@ int spider_delete_tables( { spider_store_tables_link_idx(table, roop_count); if ((error_num = spider_check_sys_table(table, table_key))) - break; + { + /* There's a problem with finding the first record for the + spider table, likely because it does not exist. Fail */ + if (roop_count == 0) + DBUG_RETURN(error_num); + /* At least one row has been deleted for the Spider table. + Success */ + else + break; + } else { if ((error_num = spider_delete_sys_table_row(table))) { + /* There's a problem deleting the row. Fail */ DBUG_RETURN(error_num); } } diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index fcef02070f7da..fe3eea248547b 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -4443,7 +4443,7 @@ int spider_check_for_self_reference(THD *thd, const TABLE_SHARE *share) DBUG_PRINT("info",("spider loop check param name=%s", target.c_ptr())); key = target.to_lex_cstring(); const user_var_entry *loop_check= get_variable(&thd->user_vars, &key, FALSE); - if (loop_check && loop_check->type == STRING_RESULT) + if (loop_check && loop_check->type_handler()->result_type() == STRING_RESULT) { String expected(0); expected.append(spider_unique_id); @@ -6014,9 +6014,10 @@ bool spider_init_system_tables() Spider is typically loaded before ddl_recovery, but DDL statements cannot be executed before ddl_recovery, so we delay system table creation. */ -static void spider_after_ddl_recovery(handlerton *) +static int spider_after_ddl_recovery(handlerton *) { - spider_init_system_tables(); + DBUG_EXECUTE_IF("fail_spider_ddl_recovery_done", return 1;); + return spider_init_system_tables(); } int spider_db_init( @@ -6038,16 +6039,6 @@ int spider_db_init( #ifdef HTON_CAN_READ_CONNECT_STRING_IN_PARTITION spider_hton->flags |= HTON_CAN_READ_CONNECT_STRING_IN_PARTITION; #endif - /* spider_hton->db_type = DB_TYPE_SPIDER; */ - /* - spider_hton->savepoint_offset; - spider_hton->savepoint_set = spider_savepoint_set; - spider_hton->savepoint_rollback = spider_savepoint_rollback; - spider_hton->savepoint_release = spider_savepoint_release; - spider_hton->create_cursor_read_view = spider_create_cursor_read_view; - spider_hton->set_cursor_read_view = spider_set_cursor_read_view; - spider_hton->close_cursor_read_view = spider_close_cursor_read_view; - */ spider_hton->panic = spider_panic; spider_hton->signal_ddl_recovery_done= spider_after_ddl_recovery; spider_hton->close_connection = spider_close_connection; @@ -6106,10 +6097,6 @@ int spider_db_init( if (pthread_attr_init(&spider_pt_attr)) goto error_pt_attr_init; -/* - if (pthread_attr_setdetachstate(&spider_pt_attr, PTHREAD_CREATE_DETACHED)) - goto error_pt_attr_setstate; -*/ if (mysql_mutex_init(spd_key_mutex_tbl, &spider_tbl_mutex, MY_MUTEX_INIT_FAST))