diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2022-04-12 16:11:29 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2022-04-12 16:11:29 +0300 |
commit | aa3a9d1ef58a0993971cde672dafc56bca71a71e (patch) | |
tree | 7d647a5f93b50c08e09a2f1d9b9c9835a55f3c90 | |
parent | 011b332d812383adb08ba72b176b769bac060035 (diff) | |
parent | cdc0bbdd87bbe139b543916f0ab32c90e3fb4917 (diff) | |
download | mariadb-git-aa3a9d1ef58a0993971cde672dafc56bca71a71e.tar.gz |
Merge 10.6 into 10.7
37 files changed, 1009 insertions, 160 deletions
diff --git a/debian/autobake-deb.sh b/debian/autobake-deb.sh index 60532dd8e0b..b7e25abfb56 100755 --- a/debian/autobake-deb.sh +++ b/debian/autobake-deb.sh @@ -31,9 +31,12 @@ then # build is not running on Travis or Gitlab-CI sed '/-DPLUGIN_COLUMNSTORE=NO/d' -i debian/rules # Take the files and part of control from MCS directory - cp -v storage/columnstore/columnstore/debian/mariadb-plugin-columnstore.* debian/ - echo >> debian/control - sed "s/10.6/${MYSQL_VERSION_MAJOR}.${MYSQL_VERSION_MINOR}/" <storage/columnstore/columnstore/debian/control >> debian/control + if [ ! -f debian/mariadb-plugin-columnstore.install ] + then + cp -v storage/columnstore/columnstore/debian/mariadb-plugin-columnstore.* debian/ + echo >> debian/control + sed "s/10.6/${MYSQL_VERSION_MAJOR}.${MYSQL_VERSION_MINOR}/" <storage/columnstore/columnstore/debian/control >> debian/control + fi fi # Look up distro-version specific stuff @@ -137,6 +140,11 @@ case "${CODENAME}" in exit 1 esac +if [ -n "${AUTOBAKE_PREP_CONTROL_RULES_ONLY:-}" ] +then + exit 0 +fi + # Adjust changelog, add new version echo "Incrementing changelog and starting build scripts" diff --git a/debian/mariadb-server-10.7.postinst b/debian/mariadb-server-10.7.postinst index 13800b7bce2..93a1e4e8b87 100644 --- a/debian/mariadb-server-10.7.postinst +++ b/debian/mariadb-server-10.7.postinst @@ -115,7 +115,7 @@ EOF if [ -f "$mysql_datadir"/auto.cnf ] && [ -f "$mysql_datadir"/mysql/user.MYD ] && [ ! lsof -nt "$mysql_datadir"/mysql/user.MYD > /dev/null ] && [ ! -f "$mysql_datadir"/undo_001 ]; then echo "UPDATE mysql.user SET plugin='unix_socket' WHERE plugin='auth_socket';" | - /usr/sbin/mariadbd --skip-innodb --key_buffer_size=0 --default-storage-engine=MyISAM --bootstrap 2> /dev/null + mariadbd --skip-innodb --key_buffer_size=0 --default-storage-engine=MyISAM --bootstrap 2> /dev/null fi # Ensure the existence and right permissions for the database and diff --git a/debian/rules b/debian/rules index 89fcb465fb7..2b30f471ae2 100755 --- a/debian/rules +++ b/debian/rules @@ -112,7 +112,7 @@ override_dh_auto_build: @echo "RULES.$@" # Print build env info to help debug builds on different platforms dpkg-architecture - cd $(BUILDDIR) && $(MAKE) + cd $(BUILDDIR) && $(MAKE) --output-sync=target override_dh_auto_test: @echo "RULES.$@" diff --git a/debian/salsa-ci.yml b/debian/salsa-ci.yml index 9975fdc8dea..417bad0f70d 100644 --- a/debian/salsa-ci.yml +++ b/debian/salsa-ci.yml @@ -34,7 +34,7 @@ build: - mv ${CCACHE_WORK_DIR} ${CCACHE_TMP_DIR} # Run Salsa-CI .build-script equivalent, with extra devscripts so autobake-deb.sh can run 'dch' - export CCACHE_DIR=${CCACHE_TMP_DIR} - - apt-get update && eatmydata apt-get install --no-install-recommends -y ccache fakeroot build-essential devscripts + - apt-get update && eatmydata apt-get install --no-install-recommends -y ccache fakeroot build-essential devscripts lsb-release - cd ${WORKING_DIR}/${SOURCE_DIR} - eatmydata apt-get build-dep --no-install-recommends -y . - update-ccache-symlinks; ccache -z # Zero out ccache counters diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index 164e3c22348..82b88f7072d 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -1785,6 +1785,18 @@ unexpected_eof: } if (ferror(fil_in)) { +#ifdef _AIX + /* + AIX fseeko can go past eof without error. + the error occurs on read, hence output the + same error here as would show up on other + platforms. This shows up in the mtr test + innodb_zip.innochecksum_3-4k,crc32,innodb + */ + if (errno == EFBIG) { + goto unexpected_eof; + } +#endif fprintf(stderr, "Error reading " ULINTPF " bytes", physical_page_size); perror(" "); diff --git a/include/my_service_manager.h b/include/my_service_manager.h index 3eff1253f20..498fc762048 100644 --- a/include/my_service_manager.h +++ b/include/my_service_manager.h @@ -43,7 +43,12 @@ #define SD_LISTEN_FDS_START (0) #define sd_notify(X, Y) #define sd_notifyf(E, F, ...) -#define service_manager_extend_timeout(I, FMTSTR, ...) +#ifdef _WIN32 + #define service_manager_extend_timeout(I, F, ...) \ + mysqld_win_extend_service_timeout(I) +#else + #define service_manager_extend_timeout(I, FMTSTR, ...) +#endif #endif #endif /* MY_SERVICE_MANAGER_INCLUDED */ diff --git a/mysql-test/main/disabled.def b/mysql-test/main/disabled.def index d3366587ee5..02104f6a680 100644 --- a/mysql-test/main/disabled.def +++ b/mysql-test/main/disabled.def @@ -18,5 +18,3 @@ file_contents : MDEV-6526 these files are not installed anymore max_statement_time : cannot possibly work, depends on timing partition_open_files_limit : open_files_limit check broken by MDEV-18360 partition_innodb : Waiting for fix MDEV-20169 -type_enum : Waiting for fix MDEV-6978 -type_set : Waiting for fix MDEV-6978 diff --git a/mysql-test/main/information_schema.result b/mysql-test/main/information_schema.result index ad78f413ea1..0ce5cbea37d 100644 --- a/mysql-test/main/information_schema.result +++ b/mysql-test/main/information_schema.result @@ -2532,3 +2532,24 @@ progress # # End of 10.3 tests # +# +# Start of 10.5 tests +# +# +# MDEV-26507 Assertion `tmp != ((long long) 0x8000000000000000LL)' failed in TIME_from_longlong_datetime_packed +# +CREATE TABLE t1 (a int); +CREATE ALGORITHM=TEMPTABLE VIEW i AS +SELECT a.created +FROM t1 w JOIN INFORMATION_SCHEMA.routines a +WHERE a.routine_name='not existing' + ORDER BY a.last_altered; +SET SESSION sql_mode='ALLOW_INVALID_DATES'; +SELECT * FROM i; +created +SET SESSION sql_mode=DEFAULT; +DROP VIEW i; +DROP TABLE t1; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/information_schema.test b/mysql-test/main/information_schema.test index 0c403caa599..27f5dd6103d 100644 --- a/mysql-test/main/information_schema.test +++ b/mysql-test/main/information_schema.test @@ -2111,3 +2111,27 @@ select progress from information_schema.processlist limit 1; --echo # --echo # End of 10.3 tests --echo # + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-26507 Assertion `tmp != ((long long) 0x8000000000000000LL)' failed in TIME_from_longlong_datetime_packed +--echo # + +CREATE TABLE t1 (a int); +CREATE ALGORITHM=TEMPTABLE VIEW i AS + SELECT a.created + FROM t1 w JOIN INFORMATION_SCHEMA.routines a + WHERE a.routine_name='not existing' + ORDER BY a.last_altered; +SET SESSION sql_mode='ALLOW_INVALID_DATES'; +SELECT * FROM i; +SET SESSION sql_mode=DEFAULT; +DROP VIEW i; +DROP TABLE t1; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/keywords.result b/mysql-test/main/keywords.result index 2765c05b3cb..483a8f7e7e8 100644 --- a/mysql-test/main/keywords.result +++ b/mysql-test/main/keywords.result @@ -391,3 +391,424 @@ END $$ compressed 1 +# +# Testing various keywords in various contexts +# +CREATE PROCEDURE p1(query TEXT, var TEXT) +BEGIN +DECLARE errmsg TEXT DEFAULT ''; +DECLARE CONTINUE HANDLER +FOR SQLEXCEPTION +BEGIN +GET DIAGNOSTICS CONDITION 1 errmsg = MESSAGE_TEXT; +SET errmsg= REPLACE(errmsg, 'You have an error in your SQL ', '..'); +SET errmsg= REPLACE(errmsg, '; check the manual that corresponds to your MariaDB server version for the right syntax to use', '..'); +END; +SET query=REPLACE(query, '$(VAR)', var); +EXECUTE IMMEDIATE query; +SELECT CONCAT(query, '; -- ', LEFT(COALESCE(errmsg,''),40)) AS `--------`; +END; +$$ +CREATE PROCEDURE p2(query TEXT) +BEGIN +FOR row IN (SELECT word FROM t1 ORDER BY category, word) +DO +CALL p1(query, row.word); +END FOR; +END; +$$ +CREATE TABLE t1 (word TEXT, category TEXT); +INSERT INTO t1 VALUES ('non_keyword', '00 Simple identifier'); +INSERT INTO t1 VALUES ('lpad', '01 Built-in native function'); +INSERT INTO t1 VALUES ('rpad', '01 Built-in native function'); +INSERT INTO t1 VALUES ('adddate', '02 function_call_nonkeyword'); +INSERT INTO t1 VALUES ('substr', '02 function_call_nonkeyword'); +INSERT INTO t1 VALUES ('substring', '02 function_call_nonkeyword'); +INSERT INTO t1 VALUES ('trim_oracle', '02 function_call_nonkeyword'); +INSERT INTO t1 VALUES ('ascii', '03 function_call_conflict'); +INSERT INTO t1 VALUES ('replace', '03 function_call_conflict'); +INSERT INTO t1 VALUES ('weight_string', '03 function_call_conflict'); +INSERT INTO t1 VALUES ('char', '04 function_call_keyword'); +INSERT INTO t1 VALUES ('trim', '04 function_call_keyword'); +INSERT INTO t1 VALUES ('year', '04 function_call_keyword'); +INSERT INTO t1 VALUES ('create', '05 Reserved keyword'); +CALL p2('SELECT @@$(VAR)'); +-------- +SELECT @@non_keyword; -- Unknown system variable 'non_keyword' +-------- +SELECT @@lpad; -- Unknown system variable 'lpad' +-------- +SELECT @@rpad; -- Unknown system variable 'rpad' +-------- +SELECT @@adddate; -- Unknown system variable 'adddate' +-------- +SELECT @@substr; -- Unknown system variable 'substr' +-------- +SELECT @@substring; -- Unknown system variable 'substring' +-------- +SELECT @@trim_oracle; -- Unknown system variable 'trim_oracle' +-------- +SELECT @@ascii; -- Unknown system variable 'ascii' +-------- +SELECT @@replace; -- ..syntax.. near 'replace' at line 1 +-------- +SELECT @@weight_string; -- Unknown system variable 'weight_string' +-------- +SELECT @@char; -- ..syntax.. near 'char' at line 1 +-------- +SELECT @@trim; -- Unknown system variable 'trim' +-------- +SELECT @@year; -- Unknown system variable 'year' +-------- +SELECT @@create; -- ..syntax.. near 'create' at line 1 +CALL p2('SELECT @@global.$(VAR)'); +-------- +SELECT @@global.non_keyword; -- Unknown system variable 'non_keyword' +-------- +SELECT @@global.lpad; -- Unknown system variable 'lpad' +-------- +SELECT @@global.rpad; -- Unknown system variable 'rpad' +-------- +SELECT @@global.adddate; -- Unknown system variable 'adddate' +-------- +SELECT @@global.substr; -- Unknown system variable 'substr' +-------- +SELECT @@global.substring; -- Unknown system variable 'substring' +-------- +SELECT @@global.trim_oracle; -- Unknown system variable 'trim_oracle' +-------- +SELECT @@global.ascii; -- Unknown system variable 'ascii' +-------- +SELECT @@global.replace; -- Unknown system variable 'replace' +-------- +SELECT @@global.weight_string; -- Unknown system variable 'weight_string' +-------- +SELECT @@global.char; -- Unknown system variable 'char' +-------- +SELECT @@global.trim; -- Unknown system variable 'trim' +-------- +SELECT @@global.year; -- Unknown system variable 'year' +-------- +SELECT @@global.create; -- Unknown system variable 'create' +CALL p2('SELECT @@global.$(VAR)()'); +-------- +SELECT @@global.non_keyword(); -- Unknown system variable 'non_keyword' +-------- +SELECT @@global.lpad(); -- Unknown system variable 'lpad' +-------- +SELECT @@global.rpad(); -- Unknown system variable 'rpad' +-------- +SELECT @@global.adddate(); -- Unknown system variable 'adddate' +-------- +SELECT @@global.substr(); -- Unknown system variable 'substr' +-------- +SELECT @@global.substring(); -- Unknown system variable 'substring' +-------- +SELECT @@global.trim_oracle(); -- Unknown system variable 'trim_oracle' +-------- +SELECT @@global.ascii(); -- Unknown system variable 'ascii' +-------- +SELECT @@global.replace(); -- Unknown system variable 'replace' +-------- +SELECT @@global.weight_string(); -- Unknown system variable 'weight_string' +-------- +SELECT @@global.char(); -- Unknown system variable 'char' +-------- +SELECT @@global.trim(); -- Unknown system variable 'trim' +-------- +SELECT @@global.year(); -- Unknown system variable 'year' +-------- +SELECT @@global.create(); -- Unknown system variable 'create' +CALL p2('SELECT $(VAR)()'); +-------- +SELECT non_keyword(); -- FUNCTION test.non_keyword does not exist +-------- +SELECT lpad(); -- Incorrect parameter count in the call to +-------- +SELECT rpad(); -- Incorrect parameter count in the call to +-------- +SELECT adddate(); -- ..syntax.. near ')' at line 1 +-------- +SELECT substr(); -- ..syntax.. near ')' at line 1 +-------- +SELECT substring(); -- ..syntax.. near ')' at line 1 +-------- +SELECT trim_oracle(); -- ..syntax.. near ')' at line 1 +-------- +SELECT ascii(); -- ..syntax.. near ')' at line 1 +-------- +SELECT replace(); -- ..syntax.. near ')' at line 1 +-------- +SELECT weight_string(); -- ..syntax.. near ')' at line 1 +-------- +SELECT char(); -- ..syntax.. near ')' at line 1 +-------- +SELECT trim(); -- ..syntax.. near ')' at line 1 +-------- +SELECT year(); -- ..syntax.. near ')' at line 1 +-------- +SELECT create(); -- ..syntax.. near 'create()' at line 1 +CALL p2('SELECT test.$(VAR)()'); +-------- +SELECT test.non_keyword(); -- FUNCTION test.non_keyword does not exist +-------- +SELECT test.lpad(); -- FUNCTION test.lpad does not exist +-------- +SELECT test.rpad(); -- FUNCTION test.rpad does not exist +-------- +SELECT test.adddate(); -- FUNCTION test.adddate does not exist. Ch +-------- +SELECT test.substr(); -- FUNCTION test.substr does not exist. Che +-------- +SELECT test.substring(); -- FUNCTION test.substring does not exist. +-------- +SELECT test.trim_oracle(); -- FUNCTION test.trim_oracle does not exist +-------- +SELECT test.ascii(); -- FUNCTION test.ascii does not exist. Chec +-------- +SELECT test.replace(); -- FUNCTION test.replace does not exist. Ch +-------- +SELECT test.weight_string(); -- FUNCTION test.weight_string does not exi +-------- +SELECT test.char(); -- FUNCTION test.char does not exist. Check +-------- +SELECT test.trim(); -- FUNCTION test.trim does not exist. Check +-------- +SELECT test.year(); -- FUNCTION test.year does not exist. Check +-------- +SELECT test.create(); -- FUNCTION test.create does not exist. Che +CALL p2('SELECT $(VAR) FROM t1'); +-------- +SELECT non_keyword FROM t1; -- Unknown column 'non_keyword' in 'field l +-------- +SELECT lpad FROM t1; -- Unknown column 'lpad' in 'field list' +-------- +SELECT rpad FROM t1; -- Unknown column 'rpad' in 'field list' +-------- +SELECT adddate FROM t1; -- Unknown column 'adddate' in 'field list' +-------- +SELECT substr FROM t1; -- Unknown column 'substr' in 'field list' +-------- +SELECT substring FROM t1; -- Unknown column 'substring' in 'field lis +-------- +SELECT trim_oracle FROM t1; -- Unknown column 'trim_oracle' in 'field l +-------- +SELECT ascii FROM t1; -- Unknown column 'ascii' in 'field list' +-------- +SELECT replace FROM t1; -- ..syntax.. near 'FROM t1' at line 1 +-------- +SELECT weight_string FROM t1; -- Unknown column 'weight_string' in 'field +-------- +SELECT char FROM t1; -- ..syntax.. near 'FROM t1' at line 1 +-------- +SELECT trim FROM t1; -- Unknown column 'trim' in 'field list' +-------- +SELECT year FROM t1; -- Unknown column 'year' in 'field list' +-------- +SELECT create FROM t1; -- ..syntax.. near 'create FROM t1' at line +CALL p2('SELECT t1.$(VAR) FROM t1'); +-------- +SELECT t1.non_keyword FROM t1; -- Unknown column 't1.non_keyword' in 'fiel +-------- +SELECT t1.lpad FROM t1; -- Unknown column 't1.lpad' in 'field list' +-------- +SELECT t1.rpad FROM t1; -- Unknown column 't1.rpad' in 'field list' +-------- +SELECT t1.adddate FROM t1; -- Unknown column 't1.adddate' in 'field li +-------- +SELECT t1.substr FROM t1; -- Unknown column 't1.substr' in 'field lis +-------- +SELECT t1.substring FROM t1; -- Unknown column 't1.substring' in 'field +-------- +SELECT t1.trim_oracle FROM t1; -- Unknown column 't1.trim_oracle' in 'fiel +-------- +SELECT t1.ascii FROM t1; -- Unknown column 't1.ascii' in 'field list +-------- +SELECT t1.replace FROM t1; -- Unknown column 't1.replace' in 'field li +-------- +SELECT t1.weight_string FROM t1; -- Unknown column 't1.weight_string' in 'fi +-------- +SELECT t1.char FROM t1; -- Unknown column 't1.char' in 'field list' +-------- +SELECT t1.trim FROM t1; -- Unknown column 't1.trim' in 'field list' +-------- +SELECT t1.year FROM t1; -- Unknown column 't1.year' in 'field list' +-------- +SELECT t1.create FROM t1; -- Unknown column 't1.create' in 'field lis +CALL p2('DROP TABLE $(VAR)'); +-------- +DROP TABLE non_keyword; -- Unknown table 'test.non_keyword' +-------- +DROP TABLE lpad; -- Unknown table 'test.lpad' +-------- +DROP TABLE rpad; -- Unknown table 'test.rpad' +-------- +DROP TABLE adddate; -- Unknown table 'test.adddate' +-------- +DROP TABLE substr; -- Unknown table 'test.substr' +-------- +DROP TABLE substring; -- Unknown table 'test.substring' +-------- +DROP TABLE trim_oracle; -- Unknown table 'test.trim_oracle' +-------- +DROP TABLE ascii; -- Unknown table 'test.ascii' +-------- +DROP TABLE replace; -- ..syntax.. near 'replace' at line 1 +-------- +DROP TABLE weight_string; -- Unknown table 'test.weight_string' +-------- +DROP TABLE char; -- ..syntax.. near 'char' at line 1 +-------- +DROP TABLE trim; -- Unknown table 'test.trim' +-------- +DROP TABLE year; -- Unknown table 'test.year' +-------- +DROP TABLE create; -- ..syntax.. near 'create' at line 1 +CALL p2('DROP TABLE test.$(VAR)'); +-------- +DROP TABLE test.non_keyword; -- Unknown table 'test.non_keyword' +-------- +DROP TABLE test.lpad; -- Unknown table 'test.lpad' +-------- +DROP TABLE test.rpad; -- Unknown table 'test.rpad' +-------- +DROP TABLE test.adddate; -- Unknown table 'test.adddate' +-------- +DROP TABLE test.substr; -- Unknown table 'test.substr' +-------- +DROP TABLE test.substring; -- Unknown table 'test.substring' +-------- +DROP TABLE test.trim_oracle; -- Unknown table 'test.trim_oracle' +-------- +DROP TABLE test.ascii; -- Unknown table 'test.ascii' +-------- +DROP TABLE test.replace; -- Unknown table 'test.replace' +-------- +DROP TABLE test.weight_string; -- Unknown table 'test.weight_string' +-------- +DROP TABLE test.char; -- Unknown table 'test.char' +-------- +DROP TABLE test.trim; -- Unknown table 'test.trim' +-------- +DROP TABLE test.year; -- Unknown table 'test.year' +-------- +DROP TABLE test.create; -- Unknown table 'test.create' +CALL p2('CREATE FUNCTION $(VAR)() RETURNS OOPS'); +-------- +CREATE FUNCTION non_keyword() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION lpad() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION rpad() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION adddate() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION substr() RETURNS OOPS; -- ..syntax.. near 'substr() RETURNS OOPS' +-------- +CREATE FUNCTION substring() RETURNS OOPS; -- ..syntax.. near 'substring() RETURNS OOP +-------- +CREATE FUNCTION trim_oracle() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION ascii() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION replace() RETURNS OOPS; -- ..syntax.. near 'replace() RETURNS OOPS' +-------- +CREATE FUNCTION weight_string() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION char() RETURNS OOPS; -- ..syntax.. near 'char() RETURNS OOPS' at +-------- +CREATE FUNCTION trim() RETURNS OOPS; -- ..syntax.. near 'trim() RETURNS OOPS' at +-------- +CREATE FUNCTION year() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION create() RETURNS OOPS; -- ..syntax.. near 'create() RETURNS OOPS' +CALL p2('CREATE FUNCTION test.$(VAR)() RETURNS OOPS'); +-------- +CREATE FUNCTION test.non_keyword() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION test.lpad() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION test.rpad() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION test.adddate() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION test.substr() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION test.substring() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION test.trim_oracle() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION test.ascii() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION test.replace() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION test.weight_string() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION test.char() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION test.trim() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION test.year() RETURNS OOPS; -- Unknown data type: 'OOPS' +-------- +CREATE FUNCTION test.create() RETURNS OOPS; -- Unknown data type: 'OOPS' +CALL p2('DROP FUNCTION $(VAR)'); +-------- +DROP FUNCTION non_keyword; -- FUNCTION test.non_keyword does not exist +-------- +DROP FUNCTION lpad; -- FUNCTION test.lpad does not exist +-------- +DROP FUNCTION rpad; -- FUNCTION test.rpad does not exist +-------- +DROP FUNCTION adddate; -- FUNCTION test.adddate does not exist +-------- +DROP FUNCTION substr; -- FUNCTION test.substr does not exist +-------- +DROP FUNCTION substring; -- FUNCTION test.substring does not exist +-------- +DROP FUNCTION trim_oracle; -- FUNCTION test.trim_oracle does not exist +-------- +DROP FUNCTION ascii; -- FUNCTION test.ascii does not exist +-------- +DROP FUNCTION replace; -- ..syntax.. near 'replace' at line 1 +-------- +DROP FUNCTION weight_string; -- FUNCTION test.weight_string does not exi +-------- +DROP FUNCTION char; -- ..syntax.. near 'char' at line 1 +-------- +DROP FUNCTION trim; -- FUNCTION test.trim does not exist +-------- +DROP FUNCTION year; -- FUNCTION test.year does not exist +-------- +DROP FUNCTION create; -- ..syntax.. near 'create' at line 1 +CALL p2('DROP FUNCTION test.$(VAR)'); +-------- +DROP FUNCTION test.non_keyword; -- FUNCTION test.non_keyword does not exist +-------- +DROP FUNCTION test.lpad; -- FUNCTION test.lpad does not exist +-------- +DROP FUNCTION test.rpad; -- FUNCTION test.rpad does not exist +-------- +DROP FUNCTION test.adddate; -- FUNCTION test.adddate does not exist +-------- +DROP FUNCTION test.substr; -- FUNCTION test.substr does not exist +-------- +DROP FUNCTION test.substring; -- FUNCTION test.substring does not exist +-------- +DROP FUNCTION test.trim_oracle; -- FUNCTION test.trim_oracle does not exist +-------- +DROP FUNCTION test.ascii; -- FUNCTION test.ascii does not exist +-------- +DROP FUNCTION test.replace; -- FUNCTION test.replace does not exist +-------- +DROP FUNCTION test.weight_string; -- FUNCTION test.weight_string does not exi +-------- +DROP FUNCTION test.char; -- FUNCTION test.char does not exist +-------- +DROP FUNCTION test.trim; -- FUNCTION test.trim does not exist +-------- +DROP FUNCTION test.year; -- FUNCTION test.year does not exist +-------- +DROP FUNCTION test.create; -- FUNCTION test.create does not exist +DROP TABLE t1; +DROP PROCEDURE p1; +DROP PROCEDURE p2; diff --git a/mysql-test/main/keywords.test b/mysql-test/main/keywords.test index a745aada106..e6a3fc4953d 100644 --- a/mysql-test/main/keywords.test +++ b/mysql-test/main/keywords.test @@ -295,3 +295,80 @@ BEGIN NOT ATOMIC END $$ DELIMITER ;$$ + + +--echo # +--echo # Testing various keywords in various contexts +--echo # + +DELIMITER $$; +CREATE PROCEDURE p1(query TEXT, var TEXT) +BEGIN + DECLARE errmsg TEXT DEFAULT ''; + DECLARE CONTINUE HANDLER + FOR SQLEXCEPTION + BEGIN + GET DIAGNOSTICS CONDITION 1 errmsg = MESSAGE_TEXT; + SET errmsg= REPLACE(errmsg, 'You have an error in your SQL ', '..'); + SET errmsg= REPLACE(errmsg, '; check the manual that corresponds to your MariaDB server version for the right syntax to use', '..'); + END; + SET query=REPLACE(query, '$(VAR)', var); + EXECUTE IMMEDIATE query; + SELECT CONCAT(query, '; -- ', LEFT(COALESCE(errmsg,''),40)) AS `--------`; +END; +$$ +CREATE PROCEDURE p2(query TEXT) +BEGIN + FOR row IN (SELECT word FROM t1 ORDER BY category, word) + DO + CALL p1(query, row.word); + END FOR; +END; +$$ +DELIMITER ;$$ + +CREATE TABLE t1 (word TEXT, category TEXT); + +INSERT INTO t1 VALUES ('non_keyword', '00 Simple identifier'); + +INSERT INTO t1 VALUES ('lpad', '01 Built-in native function'); +INSERT INTO t1 VALUES ('rpad', '01 Built-in native function'); + +INSERT INTO t1 VALUES ('adddate', '02 function_call_nonkeyword'); +INSERT INTO t1 VALUES ('substr', '02 function_call_nonkeyword'); +INSERT INTO t1 VALUES ('substring', '02 function_call_nonkeyword'); +INSERT INTO t1 VALUES ('trim_oracle', '02 function_call_nonkeyword'); + +INSERT INTO t1 VALUES ('ascii', '03 function_call_conflict'); +INSERT INTO t1 VALUES ('replace', '03 function_call_conflict'); +INSERT INTO t1 VALUES ('weight_string', '03 function_call_conflict'); + +INSERT INTO t1 VALUES ('char', '04 function_call_keyword'); +INSERT INTO t1 VALUES ('trim', '04 function_call_keyword'); +INSERT INTO t1 VALUES ('year', '04 function_call_keyword'); + +INSERT INTO t1 VALUES ('create', '05 Reserved keyword'); + +CALL p2('SELECT @@$(VAR)'); +CALL p2('SELECT @@global.$(VAR)'); +CALL p2('SELECT @@global.$(VAR)()'); + +CALL p2('SELECT $(VAR)()'); +CALL p2('SELECT test.$(VAR)()'); + +CALL p2('SELECT $(VAR) FROM t1'); +CALL p2('SELECT t1.$(VAR) FROM t1'); + +CALL p2('DROP TABLE $(VAR)'); +CALL p2('DROP TABLE test.$(VAR)'); + +CALL p2('CREATE FUNCTION $(VAR)() RETURNS OOPS'); +CALL p2('CREATE FUNCTION test.$(VAR)() RETURNS OOPS'); + +CALL p2('DROP FUNCTION $(VAR)'); +CALL p2('DROP FUNCTION test.$(VAR)'); + +DROP TABLE t1; + +DROP PROCEDURE p1; +DROP PROCEDURE p2; diff --git a/mysql-test/main/thread_pool_info.test b/mysql-test/main/thread_pool_info.test index cd906454d8c..84dce94d778 100644 --- a/mysql-test/main/thread_pool_info.test +++ b/mysql-test/main/thread_pool_info.test @@ -1,4 +1,5 @@ source include/not_embedded.inc; +source include/not_aix.inc; let $have_plugin = `SELECT COUNT(*) FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_STATUS='ACTIVE' AND PLUGIN_NAME = 'THREAD_POOL_GROUPS'`; if(!$have_plugin) diff --git a/mysql-test/main/type_enum.result b/mysql-test/main/type_enum.result index 9b251fb414b..8d0dfefc64c 100644 --- a/mysql-test/main/type_enum.result +++ b/mysql-test/main/type_enum.result @@ -1699,7 +1699,7 @@ a ENUM('ä','ö','ü') character set utf8 default 'ü' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` enum('ä','ö','ü') CHARACTER SET utf8 DEFAULT 'ü' + `a` enum('ä','ö','ü') CHARACTER SET utf8mb3 DEFAULT 'ü' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 insert into t1 values ('ä'), ('ö'), ('ü'); select a from t1 order by a; @@ -1932,14 +1932,16 @@ ALTER TABLE t2 ADD PRIMARY KEY(c1); SELECT t1.* FROM t1 JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; c1 a +a SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; c1 a +a # t2 should NOT be eliminated EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 -1 SIMPLE t2 range PRIMARY PRIMARY 1 NULL 1 Using where; Using index +1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index DROP TABLE IF EXISTS t1,t2; CREATE TABLE t1 (c1 SET('a') CHARACTER SET latin1 PRIMARY KEY); INSERT INTO t1 VALUES ('a'); @@ -1957,14 +1959,16 @@ ALTER TABLE t2 ADD PRIMARY KEY(c1); SELECT t1.* FROM t1 JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; c1 a +a SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; c1 a +a # t2 should NOT be eliminated EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 -1 SIMPLE t2 range PRIMARY PRIMARY 1 NULL 1 Using where; Using index +1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index DROP TABLE IF EXISTS t1,t2; CREATE TABLE t1 (c1 VARCHAR(10) CHARACTER SET latin1 PRIMARY KEY); INSERT INTO t1 VALUES ('a'); @@ -1982,14 +1986,16 @@ ALTER TABLE t2 ADD PRIMARY KEY(c1); SELECT t1.* FROM t1 JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; c1 a +a SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; c1 a +a # t2 should NOT be eliminated EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 -1 SIMPLE t2 range PRIMARY PRIMARY 1 NULL 1 Using where; Using index +1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index DROP TABLE IF EXISTS t1,t2; # # MDEV-6991 GROUP_MIN_MAX optimization is erroneously applied in some cases diff --git a/mysql-test/suite/innodb/r/alter_crash_rebuild.result b/mysql-test/suite/innodb/r/alter_crash_rebuild.result new file mode 100644 index 00000000000..b4d4e8ba85a --- /dev/null +++ b/mysql-test/suite/innodb/r/alter_crash_rebuild.result @@ -0,0 +1,21 @@ +CREATE TABLE t1 (a INT NOT NULL) ENGINE=InnoDB STATS_PERSISTENT=0; +connect ddl,localhost,root; +SET DEBUG_SYNC='after_trx_committed_in_memory SIGNAL stuck WAIT_FOR ever EXECUTE 2'; +ALTER TABLE t1 ADD PRIMARY KEY(a); +connection default; +SET DEBUG_SYNC='now WAIT_FOR stuck'; +SET DEBUG_SYNC='now SIGNAL ever'; +SET DEBUG_SYNC='now WAIT_FOR stuck'; +SET GLOBAL innodb_log_checkpoint_now=ON; +# restart +disconnect ddl; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=0 +SELECT * FROM t1; +a +DROP TABLE t1; +InnoDB 0 transactions not purged diff --git a/mysql-test/suite/innodb/r/ibuf_delete.result b/mysql-test/suite/innodb/r/ibuf_delete.result new file mode 100644 index 00000000000..1481fca9bf6 --- /dev/null +++ b/mysql-test/suite/innodb/r/ibuf_delete.result @@ -0,0 +1,49 @@ +SET @buffering= @@innodb_change_buffering; +SET GLOBAL innodb_change_buffering= deletes; +SET @flush= @@innodb_flush_log_at_trx_commit; +SET GLOBAL innodb_flush_log_at_trx_commit= 0; +CREATE TABLE t1 ( +a varchar(1024), +b varchar(1024), +c varchar(1024), +d varchar(1024), +e varchar(1024), +f varchar(1024), +g varchar(1024), +h varchar(1024), +key (a), +key (b), +key (c), +key (d) +) ENGINE=InnoDB; +INSERT INTO t1 +SELECT REPEAT('x',10), REPEAT('x',13), REPEAT('x',427), REPEAT('x',244), +REPEAT('x',9), REPEAT('x',112), REPEAT('x',814), REPEAT('x',633) +FROM seq_1_to_1024; +CREATE TEMPORARY TABLE t2 ( +a varchar(1024), +b varchar(1024), +c varchar(1024), +d varchar(1024), +e varchar(1024), +f varchar(1024), +g varchar(1024), +h varchar(1024), +i varchar(1024), +j varchar(1024), +k varchar(1024), +l varchar(1024), +m varchar(1024), +key (a), +key (b), +key (c), +key (d), +key (e), +key (f) +) ENGINE=InnoDB; +SET @x=REPEAT('x',512); +INSERT INTO t2 SELECT @x, @x, @x, @x, @x, @x, @x, @x, @x, @x, @x, @x, @x +FROM seq_1_to_768; +DROP TABLE t1, t2; +SET GLOBAL innodb_change_buffering= @buffering; +SET GLOBAL innodb_flush_log_at_trx_commit= @flush; diff --git a/mysql-test/suite/innodb/t/ibuf_delete.test b/mysql-test/suite/innodb/t/ibuf_delete.test new file mode 100644 index 00000000000..82b740b6aa1 --- /dev/null +++ b/mysql-test/suite/innodb/t/ibuf_delete.test @@ -0,0 +1,67 @@ +--source include/have_innodb.inc +--source include/have_sequence.inc + +SET @buffering= @@innodb_change_buffering; +SET GLOBAL innodb_change_buffering= deletes; +SET @flush= @@innodb_flush_log_at_trx_commit; +SET GLOBAL innodb_flush_log_at_trx_commit= 0; + +CREATE TABLE t1 ( + a varchar(1024), + b varchar(1024), + c varchar(1024), + d varchar(1024), + e varchar(1024), + f varchar(1024), + g varchar(1024), + h varchar(1024), + key (a), + key (b), + key (c), + key (d) +) ENGINE=InnoDB; + +INSERT INTO t1 +SELECT REPEAT('x',10), REPEAT('x',13), REPEAT('x',427), REPEAT('x',244), +REPEAT('x',9), REPEAT('x',112), REPEAT('x',814), REPEAT('x',633) +FROM seq_1_to_1024; + +CREATE TEMPORARY TABLE t2 ( + a varchar(1024), + b varchar(1024), + c varchar(1024), + d varchar(1024), + e varchar(1024), + f varchar(1024), + g varchar(1024), + h varchar(1024), + i varchar(1024), + j varchar(1024), + k varchar(1024), + l varchar(1024), + m varchar(1024), + key (a), + key (b), + key (c), + key (d), + key (e), + key (f) +) ENGINE=InnoDB; + +SET @x=REPEAT('x',512); +INSERT INTO t2 SELECT @x, @x, @x, @x, @x, @x, @x, @x, @x, @x, @x, @x, @x +FROM seq_1_to_768; + +--disable_query_log +--let $run=1024 +while ($run) +{ + eval DELETE FROM t1 LIMIT 1 /* $run */; + --dec $run +} +--enable_query_log + +# Cleanup +DROP TABLE t1, t2; +SET GLOBAL innodb_change_buffering= @buffering; +SET GLOBAL innodb_flush_log_at_trx_commit= @flush; diff --git a/mysql-test/suite/innodb_i_s/innodb_trx.result b/mysql-test/suite/innodb_i_s/innodb_trx.result index 912ae49b760..2c4b9281c92 100644 --- a/mysql-test/suite/innodb_i_s/innodb_trx.result +++ b/mysql-test/suite/innodb_i_s/innodb_trx.result @@ -28,3 +28,21 @@ CREATE TEMPORARY TABLE t1 LIKE INFORMATION_SCHEMA.INNODB_TRX; DROP TEMPORARY TABLE t1; CREATE TEMPORARY TABLE t1 AS SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX LIMIT 0; DROP TEMPORARY TABLE t1; +# +# Start of 10.5 tests +# +# +# MDEV-26507 Assertion `tmp != ((long long) 0x8000000000000000LL)' failed in TIME_from_longlong_datetime_packed +# +CREATE ALGORITHM=TEMPTABLE VIEW i AS +SELECT a.trx_started +FROM INFORMATION_SCHEMA.innodb_lock_waits w +JOIN INFORMATION_SCHEMA.innodb_trx a +ORDER BY a.trx_wait_started; +SET SESSION sql_mode='ALLOW_INVALID_DATES'; +SELECT * FROM i; +SET SESSION sql_mode=DEFAULT; +DROP VIEW i; +# +# End of 10.5 tests +# diff --git a/mysql-test/suite/innodb_i_s/innodb_trx.test b/mysql-test/suite/innodb_i_s/innodb_trx.test index 90fa3467b50..2a66750ed9f 100644 --- a/mysql-test/suite/innodb_i_s/innodb_trx.test +++ b/mysql-test/suite/innodb_i_s/innodb_trx.test @@ -7,3 +7,28 @@ DROP TEMPORARY TABLE t1; CREATE TEMPORARY TABLE t1 AS SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX LIMIT 0; DROP TEMPORARY TABLE t1; + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-26507 Assertion `tmp != ((long long) 0x8000000000000000LL)' failed in TIME_from_longlong_datetime_packed +--echo # + +CREATE ALGORITHM=TEMPTABLE VIEW i AS + SELECT a.trx_started + FROM INFORMATION_SCHEMA.innodb_lock_waits w + JOIN INFORMATION_SCHEMA.innodb_trx a + ORDER BY a.trx_wait_started; +SET SESSION sql_mode='ALLOW_INVALID_DATES'; +--disable_result_log +SELECT * FROM i; +--enable_result_log +SET SESSION sql_mode=DEFAULT; +DROP VIEW i; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/suite/perfschema/r/threads_mysql.result b/mysql-test/suite/perfschema/r/threads_mysql.result index 40e6360fec7..d0748349af3 100644 --- a/mysql-test/suite/perfschema/r/threads_mysql.result +++ b/mysql-test/suite/perfschema/r/threads_mysql.result @@ -1,6 +1,6 @@ SET GLOBAL event_scheduler = OFF; SELECT name, type, processlist_user, processlist_host, processlist_db, -processlist_command, processlist_info, +processlist_command, processlist_info, connection_type, IF(parent_thread_id IS NULL, parent_thread_id, 'unified parent_thread_id') AS unified_parent_thread_id, role, instrumented @@ -14,6 +14,7 @@ processlist_host NULL processlist_db mysql processlist_command NULL processlist_info NULL +connection_type NULL unified_parent_thread_id NULL role NULL instrumented YES @@ -24,6 +25,7 @@ processlist_host NULL processlist_db NULL processlist_command NULL processlist_info NULL +connection_type NULL unified_parent_thread_id unified parent_thread_id role NULL instrumented YES @@ -34,13 +36,14 @@ processlist_host localhost processlist_db test processlist_command Query processlist_info SELECT name, type, processlist_user, processlist_host, processlist_db, -processlist_command, processlist_info, +processlist_command, processlist_info, connection_type, IF(parent_thread_id IS NULL, parent_thread_id, 'unified parent_thread_id') AS unified_parent_thread_id, role, instrumented FROM performance_schema.threads WHERE name LIKE 'thread/sql%' ORDER BY name +connection_type Socket unified_parent_thread_id unified parent_thread_id role NULL instrumented YES @@ -51,6 +54,7 @@ processlist_host NULL processlist_db NULL processlist_command NULL processlist_info NULL +connection_type NULL unified_parent_thread_id unified parent_thread_id role NULL instrumented YES diff --git a/mysql-test/suite/perfschema/t/threads_mysql.test b/mysql-test/suite/perfschema/t/threads_mysql.test index c33f421863e..8a021055d44 100644 --- a/mysql-test/suite/perfschema/t/threads_mysql.test +++ b/mysql-test/suite/perfschema/t/threads_mysql.test @@ -32,7 +32,7 @@ SET GLOBAL event_scheduler = OFF; # Therefore we have to disable this protocol for the next statement. --disable_ps_protocol SELECT name, type, processlist_user, processlist_host, processlist_db, - processlist_command, processlist_info, + processlist_command, processlist_info, connection_type, IF(parent_thread_id IS NULL, parent_thread_id, 'unified parent_thread_id') AS unified_parent_thread_id, role, instrumented diff --git a/mysql-test/suite/sysschema/r/v_innodb_lock_waits.result b/mysql-test/suite/sysschema/r/v_innodb_lock_waits.result index 7e44c334283..d8e2c496d13 100644 --- a/mysql-test/suite/sysschema/r/v_innodb_lock_waits.result +++ b/mysql-test/suite/sysschema/r/v_innodb_lock_waits.result @@ -56,3 +56,15 @@ blocking_trx_rows_modified bigint(21) unsigned NO NULL sql_kill_blocking_query varchar(32) YES NULL sql_kill_blocking_connection varchar(26) YES NULL SELECT * FROM sys.x$innodb_lock_waits; +# +# Start of 10.6 tests +# +# +# MDEV-26507 Assertion `tmp != ((long long) 0x8000000000000000LL)' failed in TIME_from_longlong_datetime_packed +# +SET SESSION sql_mode='ALLOW_INVALID_DATES'; +SELECT * FROM sys.x$innodb_lock_waits; +SET SESSION sql_mode=DEFAULT; +# +# End of 10.6 tests +# diff --git a/mysql-test/suite/sysschema/t/v_innodb_lock_waits.test b/mysql-test/suite/sysschema/t/v_innodb_lock_waits.test index d742f599595..b784587d2a6 100644 --- a/mysql-test/suite/sysschema/t/v_innodb_lock_waits.test +++ b/mysql-test/suite/sysschema/t/v_innodb_lock_waits.test @@ -21,3 +21,21 @@ DESC sys.x$innodb_lock_waits; SELECT * FROM sys.x$innodb_lock_waits; --enable_result_log + +--echo # +--echo # Start of 10.6 tests +--echo # + +--echo # +--echo # MDEV-26507 Assertion `tmp != ((long long) 0x8000000000000000LL)' failed in TIME_from_longlong_datetime_packed +--echo # + +SET SESSION sql_mode='ALLOW_INVALID_DATES'; +--disable_result_log +SELECT * FROM sys.x$innodb_lock_waits; +--enable_result_log +SET SESSION sql_mode=DEFAULT; + +--echo # +--echo # End of 10.6 tests +--echo # diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 90bb9a74be6..17f81f1ae9b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2783,6 +2783,12 @@ void mysqld_win_set_startup_complete() } +void mysqld_win_extend_service_timeout(DWORD sec) +{ + my_report_svc_status((DWORD)-1, 0, 2*1000*sec); +} + + void mysqld_win_set_service_name(const char *name) { if (stricmp(name, "mysql")) diff --git a/sql/mysqld.h b/sql/mysqld.h index 8c0b92c6446..48405a77e87 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -977,6 +977,7 @@ extern int mysqld_main(int argc, char **argv); extern HANDLE hEventShutdown; extern void mysqld_win_initiate_shutdown(); extern void mysqld_win_set_startup_complete(); +extern void mysqld_win_extend_service_timeout(DWORD sec); extern void mysqld_set_service_status_callback(void (*)(DWORD, DWORD, DWORD)); extern void mysqld_win_set_service_name(const char *name); #endif diff --git a/sql/winmain.cc b/sql/winmain.cc index f999767cb27..7def0aed531 100644 --- a/sql/winmain.cc +++ b/sql/winmain.cc @@ -81,7 +81,8 @@ static void report_svc_status(DWORD current_state, DWORD exit_code, DWORD wait_h return; static DWORD check_point= 1; - svc_status.dwCurrentState= current_state; + if (current_state != (DWORD)-1) + svc_status.dwCurrentState= current_state; svc_status.dwWaitHint= wait_hint; if (exit_code) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index ae814d51826..6af73eab366 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2140,15 +2140,17 @@ void buf_pool_t::watch_unset(const page_id_t id, buf_pool_t::hash_chain &chain) if (!watch_is_sentinel(*w)) { no_watch: - ut_d(const auto s=) w->unfix(); - ut_ad(~buf_page_t::LRU_MASK & s); + w->unfix(); w= nullptr; } - const auto state= w->state(); - ut_ad(~buf_page_t::LRU_MASK & state); - ut_ad(state >= buf_page_t::UNFIXED); - if (state != buf_page_t::UNFIXED + 1) - goto no_watch; + else + { + const auto state= w->state(); + ut_ad(~buf_page_t::LRU_MASK & state); + ut_ad(state >= buf_page_t::UNFIXED + 1); + if (state != buf_page_t::UNFIXED + 1) + goto no_watch; + } } if (!w) diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index bb820374266..f2b959930dc 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -68,6 +68,7 @@ Created 1/8/1996 Heikki Tuuri #include "srv0mon.h" #include "srv0start.h" #include "trx0undo.h" +#include "trx0purge.h" #include <vector> #include <algorithm> @@ -601,13 +602,13 @@ dict_index_get_nth_field_pos( } /** Parse the table file name into table name and database name. -@tparam dict_locked whether dict_sys.lock() was called -@param[in,out] db_name database name buffer -@param[in,out] tbl_name table name buffer -@param[out] db_name_len database name length -@param[out] tbl_name_len table name length +@tparam dict_frozen whether the caller holds dict_sys.latch +@param[in,out] db_name database name buffer +@param[in,out] tbl_name table name buffer +@param[out] db_name_len database name length +@param[out] tbl_name_len table name length @return whether the table name is visible to SQL */ -template<bool dict_locked> +template<bool dict_frozen> bool dict_table_t::parse_name(char (&db_name)[NAME_LEN + 1], char (&tbl_name)[NAME_LEN + 1], size_t *db_name_len, size_t *tbl_name_len) const @@ -615,7 +616,7 @@ bool dict_table_t::parse_name(char (&db_name)[NAME_LEN + 1], char db_buf[MAX_DATABASE_NAME_LEN + 1]; char tbl_buf[MAX_TABLE_NAME_LEN + 1]; - if (!dict_locked) + if (!dict_frozen) dict_sys.freeze(SRW_LOCK_CALL); /* protect against renaming */ ut_ad(dict_sys.frozen()); const size_t db_len= name.dblen(); @@ -635,7 +636,7 @@ bool dict_table_t::parse_name(char (&db_name)[NAME_LEN + 1], memcpy(tbl_buf, mdl_name.m_name + db_len + 1, tbl_len); tbl_buf[tbl_len]= 0; - if (!dict_locked) + if (!dict_frozen) dict_sys.unfreeze(); *db_name_len= filename_to_tablename(db_buf, db_name, @@ -781,7 +782,7 @@ return_without_mdl: size_t db1_len, tbl1_len; - if (!table->parse_name<!trylock>(db_buf1, tbl_buf1, &db1_len, &tbl1_len)) + if (!table->parse_name<true>(db_buf1, tbl_buf1, &db1_len, &tbl1_len)) { /* The table was renamed to #sql prefix. Release MDL (if any) for the old name and return. */ @@ -819,12 +820,14 @@ template dict_table_t* dict_acquire_mdl_shared<true> (dict_table_t*,THD*,MDL_ticket**,dict_table_op_t); /** Look up a table by numeric identifier. +@tparam purge_thd Whether the function is called by purge thread @param[in] table_id table identifier @param[in] dict_locked data dictionary locked @param[in] table_op operation to perform when opening @param[in,out] thd background thread, or NULL to not acquire MDL @param[out] mdl mdl ticket, or NULL @return table, NULL if does not exist */ +template <bool purge_thd> dict_table_t* dict_table_open_on_id(table_id_t table_id, bool dict_locked, dict_table_op_t table_op, THD *thd, @@ -837,6 +840,12 @@ dict_table_open_on_id(table_id_t table_id, bool dict_locked, if (table) { + if (purge_thd && purge_sys.must_wait_FTS()) + { + table= nullptr; + goto func_exit; + } + table->acquire(); if (thd && !dict_locked) table= dict_acquire_mdl_shared<false>(table, thd, mdl, table_op); @@ -853,7 +862,14 @@ dict_table_open_on_id(table_id_t table_id, bool dict_locked, ? DICT_ERR_IGNORE_RECOVER_LOCK : DICT_ERR_IGNORE_FK_NOKEY); if (table) + { + if (purge_thd && purge_sys.must_wait_FTS()) + { + dict_sys.unlock(); + return nullptr; + } table->acquire(); + } if (!dict_locked) { dict_sys.unlock(); @@ -867,12 +883,22 @@ dict_table_open_on_id(table_id_t table_id, bool dict_locked, } } +func_exit: if (!dict_locked) dict_sys.unfreeze(); return table; } +template dict_table_t* dict_table_open_on_id<false> +(table_id_t table_id, bool dict_locked, + dict_table_op_t table_op, THD *thd, + MDL_ticket **mdl); +template dict_table_t* dict_table_open_on_id<true> +(table_id_t table_id, bool dict_locked, + dict_table_op_t table_op, THD *thd, + MDL_ticket **mdl); + /********************************************************************//** Looks for column n position in the clustered index. @return position in internal representation of the clustered index */ diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 964a216cd39..c3d076b81d6 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1555,12 +1555,16 @@ have any other reference count. static void fts_table_no_ref_count(const char *table_name) { dict_table_t *table= dict_table_open_on_name( - table_name, false, DICT_ERR_IGNORE_TABLESPACE); + table_name, true, DICT_ERR_IGNORE_TABLESPACE); if (!table) return; while (table->get_ref_count() > 1) + { + dict_sys.unlock(); std::this_thread::sleep_for(std::chrono::milliseconds(50)); + dict_sys.lock(SRW_LOCK_CALL); + } table->release(); } @@ -1572,8 +1576,10 @@ and common table associated with the fts table. already stopped*/ void purge_sys_t::stop_FTS(const dict_table_t &table, bool already_stopped) { + dict_sys.lock(SRW_LOCK_CALL); if (!already_stopped) purge_sys.stop_FTS(); + fts_table_t fts_table; char table_name[MAX_FULL_NAME_LEN]; @@ -1582,28 +1588,31 @@ void purge_sys_t::stop_FTS(const dict_table_t &table, bool already_stopped) for (const char **suffix= fts_common_tables; *suffix; suffix++) { fts_table.suffix= *suffix; - fts_get_table_name(&fts_table, table_name, false); + fts_get_table_name(&fts_table, table_name, true); fts_table_no_ref_count(table_name); } - if (!table.fts) - return; - auto indexes= table.fts->indexes; - if (!indexes) - return; - for (ulint i= 0;i < ib_vector_size(indexes); ++i) + if (table.fts) { - const dict_index_t *index= static_cast<const dict_index_t*>( - ib_vector_getp(indexes, i)); - FTS_INIT_INDEX_TABLE(&fts_table, nullptr, FTS_INDEX_TABLE, index); - for (const fts_index_selector_t *s= fts_index_selector; - s->suffix; s++) + if (auto indexes= table.fts->indexes) { - fts_table.suffix= s->suffix; - fts_get_table_name(&fts_table, table_name, false); - fts_table_no_ref_count(table_name); + for (ulint i= 0;i < ib_vector_size(indexes); ++i) + { + const dict_index_t *index= static_cast<const dict_index_t*>( + ib_vector_getp(indexes, i)); + FTS_INIT_INDEX_TABLE(&fts_table, nullptr, FTS_INDEX_TABLE, index); + for (const fts_index_selector_t *s= fts_index_selector; + s->suffix; s++) + { + fts_table.suffix= s->suffix; + fts_get_table_name(&fts_table, table_name, true); + fts_table_no_ref_count(table_name); + } + } } } + + dict_sys.unlock(); } /** Lock the internal FTS_ tables for table, before fts_drop_tables(). diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index afdf25ce93f..416fe17b903 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -2000,7 +2000,8 @@ inline void buf_page_t::set_state(uint32_t s) { mysql_mutex_assert_owner(&buf_pool.mutex); ut_ad(s <= REMOVE_HASH || s >= UNFIXED); - ut_ad(s <= READ_FIX); + ut_ad(s < WRITE_FIX); + ut_ad(s <= READ_FIX || zip.fix == READ_FIX); zip.fix= s; } diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 7493359e16a..461b266f6fd 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2021, MariaDB Corporation. +Copyright (c) 2013, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -146,6 +146,7 @@ dict_acquire_mdl_shared(dict_table_t *table, @param[in,out] thd background thread, or NULL to not acquire MDL @param[out] mdl mdl ticket, or NULL @return table, NULL if does not exist */ +template<bool purge_thd= false> dict_table_t* dict_table_open_on_id(table_id_t table_id, bool dict_locked, dict_table_op_t table_op, THD *thd= nullptr, @@ -1566,7 +1567,7 @@ public: } else lock_wait(SRW_LOCK_ARGS(file, line)); - } + } #ifdef UNIV_PFS_RWLOCK /** Unlock the data dictionary cache. */ diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index ba335df9eb6..62116ccf745 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2021, MariaDB Corporation. +Copyright (c) 2013, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1941,17 +1941,17 @@ struct dict_table_t { /** For overflow fields returns potential max length stored inline */ inline size_t get_overflow_field_local_len() const; - /** Parse the table file name into table name and database name. - @tparam dict_locked whether dict_sys.lock() was called - @param[in,out] db_name database name buffer - @param[in,out] tbl_name table name buffer - @param[out] db_name_len database name length - @param[out] tbl_name_len table name length - @return whether the table name is visible to SQL */ - template<bool dict_locked= false> - bool parse_name(char (&db_name)[NAME_LEN + 1], - char (&tbl_name)[NAME_LEN + 1], - size_t *db_name_len, size_t *tbl_name_len) const; + /** Parse the table file name into table name and database name. + @tparam dict_frozen whether the caller holds dict_sys.latch + @param[in,out] db_name database name buffer + @param[in,out] tbl_name table name buffer + @param[out] db_name_len database name length + @param[out] tbl_name_len table name length + @return whether the table name is visible to SQL */ + template<bool dict_frozen= false> + bool parse_name(char (&db_name)[NAME_LEN + 1], + char (&tbl_name)[NAME_LEN + 1], + size_t *db_name_len, size_t *tbl_name_len) const; /** Clear the table when rolling back TRX_UNDO_EMPTY */ void clear(que_thr_t *thr); diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 75d497b2cf4..e6267a2023a 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -1027,10 +1027,14 @@ row_purge_parse_undo_rec( try_again: purge_sys.check_stop_FTS(); - node->table = dict_table_open_on_id( + node->table = dict_table_open_on_id<true>( table_id, false, DICT_TABLE_OP_NORMAL, node->purge_thd, &node->mdl_ticket); + if (!node->table && purge_sys.must_wait_FTS()) { + goto try_again; + } + if (!node->table) { /* The table has been dropped: no need to do purge and release mdl happened as a part of open process itself */ diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index f9ab0892437..7b9173837c9 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -1182,75 +1182,83 @@ int ha_spider::external_lock( int error_num = 0; SPIDER_TRX *trx; backup_error_status(); + DBUG_ENTER("ha_spider::external_lock"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider lock_type=%x", lock_type)); -#if MYSQL_VERSION_ID < 50500 - DBUG_PRINT("info",("spider thd->options=%x", (int) thd->options)); -#endif -#ifdef WITH_PARTITION_STORAGE_ENGINE - if ( - wide_handler->stage == SPD_HND_STAGE_EXTERNAL_LOCK && - wide_handler->stage_executor != this) + DBUG_PRINT("info", ("spider sql_command=%d", thd_sql_command(thd))); + + if (wide_handler->stage == SPD_HND_STAGE_EXTERNAL_LOCK) { - DBUG_RETURN(0); + /* Only the stage executor deals with table locks. */ + if (wide_handler->stage_executor != this) + { + DBUG_RETURN(0); + } + } + else + { + /* Update the stage executor when the stage changes */ + wide_handler->stage= SPD_HND_STAGE_EXTERNAL_LOCK; + wide_handler->stage_executor= this; } - wide_handler->stage = SPD_HND_STAGE_EXTERNAL_LOCK; - wide_handler->stage_executor = this; -#endif -#ifdef HANDLER_HAS_NEED_INFO_FOR_AUTO_INC - info_auto_called = FALSE; -#endif + info_auto_called = FALSE; + wide_handler->external_lock_type= lock_type; wide_handler->sql_command = thd_sql_command(thd); + + /* We treat BEGIN as if UNLOCK TABLE. */ if (wide_handler->sql_command == SQLCOM_BEGIN) + { wide_handler->sql_command = SQLCOM_UNLOCK_TABLES; + } + if (lock_type == F_UNLCK && + wide_handler->sql_command != SQLCOM_UNLOCK_TABLES) + { + DBUG_RETURN(0); + } trx = spider_get_trx(thd, TRUE, &error_num); if (error_num) + { DBUG_RETURN(error_num); + } wide_handler->trx = trx; - DBUG_PRINT("info",("spider sql_command=%d", wide_handler->sql_command)); -#ifdef HA_CAN_BULK_ACCESS - wide_handler->external_lock_cnt++; -#endif - if ( - lock_type == F_UNLCK && - wide_handler->sql_command != SQLCOM_UNLOCK_TABLES - ) - DBUG_RETURN(0); + /* Question: Why the following if block is necessary? Why here? */ if (store_error_num) + { DBUG_RETURN(store_error_num); - wide_handler->external_lock_type = lock_type; -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - if ((conn_kinds & SPIDER_CONN_KIND_MYSQL)) + } + + DBUG_ASSERT(wide_handler->sql_command != SQLCOM_RENAME_TABLE && + wide_handler->sql_command != SQLCOM_DROP_DB); + + if (wide_handler->sql_command == SQLCOM_DROP_TABLE || + wide_handler->sql_command == SQLCOM_ALTER_TABLE) { -#endif - if ( - /* SQLCOM_RENAME_TABLE and SQLCOM_DROP_DB don't come here */ - wide_handler->sql_command == SQLCOM_DROP_TABLE || - wide_handler->sql_command == SQLCOM_ALTER_TABLE - ) { - if (trx->locked_connections) - { - my_message(ER_SPIDER_ALTER_BEFORE_UNLOCK_NUM, - ER_SPIDER_ALTER_BEFORE_UNLOCK_STR, MYF(0)); - DBUG_RETURN(ER_SPIDER_ALTER_BEFORE_UNLOCK_NUM); - } - DBUG_RETURN(0); + if (trx->locked_connections) + { + my_message(ER_SPIDER_ALTER_BEFORE_UNLOCK_NUM, + ER_SPIDER_ALTER_BEFORE_UNLOCK_STR, MYF(0)); + DBUG_RETURN(ER_SPIDER_ALTER_BEFORE_UNLOCK_NUM); } - if (unlikely((error_num = spider_internal_start_trx(this)))) + DBUG_RETURN(0); + } + + if (lock_type != F_UNLCK) + { + if (unlikely((error_num= spider_internal_start_trx(this)))) { DBUG_RETURN(error_num); } -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - } else { - trans_register_ha(trx->thd, FALSE, spider_hton_ptr); - if (thd_test_options(trx->thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) - trans_register_ha(trx->thd, TRUE, spider_hton_ptr); + if (wide_handler->sql_command != SQLCOM_SELECT && + wide_handler->sql_command != SQLCOM_HA_READ) + { + trx->updated_in_this_trx= TRUE; + DBUG_PRINT("info", ("spider trx->updated_in_this_trx=TRUE")); + } } -#endif if (wide_handler->lock_table_type > 0 || wide_handler->sql_command == SQLCOM_UNLOCK_TABLES) @@ -1263,12 +1271,10 @@ int ha_spider::external_lock( } /* lock/unlock tables */ -#ifdef WITH_PARTITION_STORAGE_ENGINE if (partition_handler && partition_handler->handlers) { - uint roop_count; - for (roop_count = 0; roop_count < partition_handler->no_parts; - ++roop_count) + for (uint roop_count= 0; roop_count < partition_handler->no_parts; + ++roop_count) { if (unlikely((error_num = partition_handler->handlers[roop_count]->lock_tables()))) @@ -1276,54 +1282,13 @@ int ha_spider::external_lock( DBUG_RETURN(error_num); } } - } else { -#endif - if (unlikely((error_num = lock_tables()))) - { - DBUG_RETURN(error_num); - } -#ifdef WITH_PARTITION_STORAGE_ENGINE } -#endif - } - - DBUG_PRINT("info",("spider trx_start=%s", - trx->trx_start ? "TRUE" : "FALSE")); - /* need to check after spider_internal_start_trx() */ - if (trx->trx_start) - { - switch (wide_handler->sql_command) + else if (unlikely((error_num= lock_tables()))) { - case SQLCOM_SELECT: - case SQLCOM_HA_READ: -#ifdef HS_HAS_SQLCOM - case SQLCOM_HS_READ: -#endif - /* nothing to do */ - break; - case SQLCOM_UPDATE: - case SQLCOM_UPDATE_MULTI: -#ifdef HS_HAS_SQLCOM - case SQLCOM_HS_UPDATE: -#endif - case SQLCOM_CREATE_TABLE: - case SQLCOM_INSERT: - case SQLCOM_INSERT_SELECT: - case SQLCOM_DELETE: - case SQLCOM_LOAD: - case SQLCOM_REPLACE: - case SQLCOM_REPLACE_SELECT: - case SQLCOM_DELETE_MULTI: -#ifdef HS_HAS_SQLCOM - case SQLCOM_HS_INSERT: - case SQLCOM_HS_DELETE: -#endif - default: - trx->updated_in_this_trx = TRUE; - DBUG_PRINT("info",("spider trx->updated_in_this_trx=TRUE")); - break; + DBUG_RETURN(error_num); } } + DBUG_RETURN(0); } diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_27239.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_27239.result new file mode 100644 index 00000000000..de135972a22 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_27239.result @@ -0,0 +1,20 @@ +# +# MDEV-27239 Spider: Assertion `thd->transaction->stmt.ha_list == __null || trans == &thd->transaction->stmt' failed in ha_commit_trans on BEGIN WORK after FTWRL +# +for master_1 +for child2 +for child3 +CREATE DATABASE auto_test_local; +USE auto_test_local; +CREATE TABLE tbl_a (a INT) ENGINE=SPIDER; +FLUSH TABLE tbl_a WITH READ LOCK; +Warnings: +Error 1429 Unable to connect to foreign data source: localhost +Error 1429 Unable to connect to foreign data source: localhost +Error 1429 Unable to connect to foreign data source: localhost +Error 1429 Unable to connect to foreign data source: localhost +BEGIN; +DROP DATABASE auto_test_local; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27239.cnf b/storage/spider/mysql-test/spider/bugfix/t/mdev_27239.cnf new file mode 100644 index 00000000000..b0853e32654 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27239.cnf @@ -0,0 +1,2 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27239.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_27239.test new file mode 100644 index 00000000000..3cf4bebd369 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27239.test @@ -0,0 +1,24 @@ +--echo # +--echo # MDEV-27239 Spider: Assertion `thd->transaction->stmt.ha_list == __null || trans == &thd->transaction->stmt' failed in ha_commit_trans on BEGIN WORK after FTWRL +--echo # + +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +CREATE DATABASE auto_test_local; +USE auto_test_local; + +CREATE TABLE tbl_a (a INT) ENGINE=SPIDER; +FLUSH TABLE tbl_a WITH READ LOCK; +BEGIN; + +DROP DATABASE auto_test_local; + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log diff --git a/vio/viosocket.c b/vio/viosocket.c index f63c76c9c79..002ff274b74 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -613,7 +613,7 @@ enum enum_vio_type vio_type(Vio* vio) static const LEX_CSTRING vio_type_names[] = { - { STRING_WITH_LEN("Error") }, // cannot happen + { STRING_WITH_LEN("") }, // internal threads { STRING_WITH_LEN("TCP/IP") }, { STRING_WITH_LEN("Socket") }, { STRING_WITH_LEN("Named Pipe") }, |