From 8b0fb154f767daf0870d751957a402fe12622848 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 10 Jan 2024 00:32:50 +0100 Subject: [PATCH 01/34] MDEV-33093 plugin/disks/information_schema_disks.cc doesn't compile on Solaris second part of the fix by Rainer Orth --- config.h.cmake | 1 + plugin/disks/CMakeLists.txt | 2 ++ plugin/disks/information_schema_disks.cc | 9 ++++----- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/config.h.cmake b/config.h.cmake index da2fc539bab..56c2bc3bcdc 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -72,6 +72,7 @@ #cmakedefine HAVE_SYS_IPC_H 1 #cmakedefine HAVE_SYS_MALLOC_H 1 #cmakedefine HAVE_SYS_MMAN_H 1 +#cmakedefine HAVE_SYS_MNTENT_H 1 #cmakedefine HAVE_SYS_NDIR_H 1 #cmakedefine HAVE_SYS_PTE_H 1 #cmakedefine HAVE_SYS_PTEM_H 1 diff --git a/plugin/disks/CMakeLists.txt b/plugin/disks/CMakeLists.txt index e4cf0dc1de3..408a4324d1b 100644 --- a/plugin/disks/CMakeLists.txt +++ b/plugin/disks/CMakeLists.txt @@ -5,6 +5,8 @@ CHECK_SYMBOL_EXISTS (getmntent "sys/mnttab.h" HAVE_GETMNTENT_IN_SYS_MNTAB) CHECK_SYMBOL_EXISTS (setmntent "mntent.h" HAVE_SETMNTENT) CHECK_SYMBOL_EXISTS (getmntinfo "sys/types.h;sys/mount.h" HAVE_GETMNTINFO) +CHECK_INCLUDE_FILES (sys/mntent.h HAVE_SYS_MNTENT_H) + IF (HAVE_GETMNTINFO) CHECK_CXX_SOURCE_COMPILES(" #include diff --git a/plugin/disks/information_schema_disks.cc b/plugin/disks/information_schema_disks.cc index 1be8fce37fa..cbc749ff603 100644 --- a/plugin/disks/information_schema_disks.cc +++ b/plugin/disks/information_schema_disks.cc @@ -19,19 +19,18 @@ #include #if defined(HAVE_GETMNTENT) #include -#elif defined(HAVE_SYS_MNTENT) -#include -#elif !defined(HAVE_GETMNTINFO_TAKES_statvfs) +#elif defined(HAVE_GETMNTINFO) && !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) #include #define HAVE_GETMNTENT +#if defined(HAVE_SYS_MNTENT_H) +#include +#endif #endif #include #include From d277a63c749bd49c9025da4efdd3008d22180dc0 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 28 Nov 2023 14:56:23 +1100 Subject: [PATCH 02/34] MDEV-31101 Re-enable spider/bugfix.mdev_29904 The spider init bug fixes remove any race conditions during spider init. Also remove the add_suppressions in spider/bugfix.mdev_27575 which is a similar issue. --- storage/spider/mysql-test/spider/bugfix/disabled.def | 1 - storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result | 2 -- storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test | 4 ---- 3 files changed, 7 deletions(-) diff --git a/storage/spider/mysql-test/spider/bugfix/disabled.def b/storage/spider/mysql-test/spider/bugfix/disabled.def index 99443c854e5..e19ea07b76b 100644 --- a/storage/spider/mysql-test/spider/bugfix/disabled.def +++ b/storage/spider/mysql-test/spider/bugfix/disabled.def @@ -1,2 +1 @@ wait_timeout : MDEV-26045 -mdev_29904 : MDEV-31101 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result index 4899f191ada..91af2c8f1e0 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result @@ -4,8 +4,6 @@ for master_1 for child2 for child3 -call mtr.add_suppression("\\[ERROR\\] Table 'mysql.spider_table_sts' doesn't exist"); -call mtr.add_suppression("\\[ERROR\\] Server shutdown in progress"); SET GLOBAL default_tmp_storage_engine=spider; # restart SET GLOBAL default_storage_engine=Spider; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test index 6f291c6f690..79a08489bae 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test @@ -7,10 +7,6 @@ --enable_result_log --enable_query_log -# These suppressions are a workaround and should not be needed once -# MDEV-29870 is done. -call mtr.add_suppression("\\[ERROR\\] Table 'mysql.spider_table_sts' doesn't exist"); -call mtr.add_suppression("\\[ERROR\\] Server shutdown in progress"); SET GLOBAL default_tmp_storage_engine=spider; --source include/restart_mysqld.inc From 88c46aba753c0094ea16dc707bb76cc5254806c8 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Thu, 11 Jan 2024 12:32:26 +1100 Subject: [PATCH 03/34] MDEV-32997 Disable spider/bugfix.mdev_27575 until we find a solution The failure described in MDEV-32997 is happening a bit too often and polluting the CI results. --- storage/spider/mysql-test/spider/bugfix/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/spider/mysql-test/spider/bugfix/disabled.def b/storage/spider/mysql-test/spider/bugfix/disabled.def index e19ea07b76b..559feeff4bd 100644 --- a/storage/spider/mysql-test/spider/bugfix/disabled.def +++ b/storage/spider/mysql-test/spider/bugfix/disabled.def @@ -1 +1,2 @@ wait_timeout : MDEV-26045 +mdev_27575 : MDEV-32997 From f807a9f874a8079d95bc71c9f27216e4d952f157 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 11 Jan 2024 11:21:32 +0100 Subject: [PATCH 04/34] MDEV-31523 Using two temporary tables in OPTIMIZE TABLE lead to crash Fixed typo in mysql_admin_table which cused call of close_unused_temporary_table_instances alwas for the first table instead of the current table. Added ASSERT that close_unused_temporary_table_instances should not remove all instances of user created temporary table. --- mysql-test/main/temp_table.result | 16 ++++++++++++++++ mysql-test/main/temp_table.test | 16 ++++++++++++++++ sql/sql_admin.cc | 2 +- sql/temporary_tables.cc | 5 +++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/temp_table.result b/mysql-test/main/temp_table.result index e5bb0d54306..33ea1700474 100644 --- a/mysql-test/main/temp_table.result +++ b/mysql-test/main/temp_table.result @@ -602,3 +602,19 @@ DROP TEMPORARY TABLE t1; # # End of 10.2 tests # +# +# MDEV-31523: Using two temporary tables in OPTIMIZE TABLE lead to crash +# +CREATE TEMPORARY TABLE t1 (c INT) ENGINE=MyISAM; +CREATE TEMPORARY TABLE t2 (c INT) ENGINE=MyISAM; +optimize TABLE t1,t2; +Table Op Msg_type Msg_text +test.t1 optimize status Table is already up to date +test.t2 optimize status Table is already up to date +SHOW TABLES; +Tables_in_test +# in 11.2 and above here should be listed above used temporary tables +DROP TEMPORARY TABLE t1, t2; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/temp_table.test b/mysql-test/main/temp_table.test index 9e639ffce2c..e1e671f5ae9 100644 --- a/mysql-test/main/temp_table.test +++ b/mysql-test/main/temp_table.test @@ -661,3 +661,19 @@ DROP TEMPORARY TABLE t1; --echo # --echo # End of 10.2 tests --echo # + +--echo # +--echo # MDEV-31523: Using two temporary tables in OPTIMIZE TABLE lead to crash +--echo # + +CREATE TEMPORARY TABLE t1 (c INT) ENGINE=MyISAM; +CREATE TEMPORARY TABLE t2 (c INT) ENGINE=MyISAM; +optimize TABLE t1,t2; +SHOW TABLES; +--echo # in 11.2 and above here should be listed above used temporary tables + +DROP TEMPORARY TABLE t1, t2; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 66dfc93f45d..09deef9f590 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -776,7 +776,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, if (lock_type == TL_WRITE && table->mdl_request.type > MDL_SHARED_WRITE) { if (table->table->s->tmp_table) - thd->close_unused_temporary_table_instances(tables); + thd->close_unused_temporary_table_instances(table); else { if (wait_while_table_is_used(thd, table->table, HA_EXTRA_NOT_USED)) diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc index 05e32d78b7f..4ffae3d53bf 100644 --- a/sql/temporary_tables.cc +++ b/sql/temporary_tables.cc @@ -1577,6 +1577,11 @@ void THD::close_unused_temporary_table_instances(const TABLE_LIST *tl) { /* Note: removing current list element doesn't invalidate iterator. */ share->all_tmp_tables.remove(table); + /* + At least one instance should be left (guaratead by calling this + function for table which is opened and the table is under processing) + */ + DBUG_ASSERT(share->all_tmp_tables.front()); free_temporary_table(table); } } From 653cb195d30bca678b5b175157f0f34206c3761d Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 15 Jan 2024 13:01:22 +0530 Subject: [PATCH 05/34] MDEV-26740 Inplace alter rebuild increases file size PageBulk::init(): Unnecessary reserves the extent before allocating a page for bulk insert. btr_page_alloc() capable of handing the extending of tablespace. --- .../suite/innodb_zip/r/innochecksum_3.result | 2 -- storage/innobase/btr/btr0bulk.cc | 17 ++++------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/mysql-test/suite/innodb_zip/r/innochecksum_3.result b/mysql-test/suite/innodb_zip/r/innochecksum_3.result index 7de90721d64..89830fbbf62 100644 --- a/mysql-test/suite/innodb_zip/r/innochecksum_3.result +++ b/mysql-test/suite/innodb_zip/r/innochecksum_3.result @@ -173,7 +173,6 @@ Filename::tab#.ibd #::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - #::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - #::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - -#::# | Freshly allocated page | - # Variables used by page type dump for ibdata1 Variables (--variable-name=value) @@ -208,7 +207,6 @@ Filename::tab#.ibd #::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - #::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - #::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - -#::# | Freshly allocated page | - [6]: check the valid lower bound values for option # allow-mismatches,page,start-page,end-page [9]: check the both short and long options "page" and "start-page" when diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index f7afc575ed5..a39a96b4b04 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -70,24 +70,15 @@ PageBulk::init() alloc_mtr.start(); m_index->set_modified(alloc_mtr); - ulint n_reserved; - bool success; - success = fsp_reserve_free_extents(&n_reserved, - m_index->table->space, - 1, FSP_NORMAL, &alloc_mtr); - if (!success) { - alloc_mtr.commit(); - m_mtr.commit(); - return(DB_OUT_OF_FILE_SPACE); - } - /* Allocate a new page. */ new_block = btr_page_alloc(m_index, 0, FSP_UP, m_level, &alloc_mtr, &m_mtr); - m_index->table->space->release_free_extents(n_reserved); - alloc_mtr.commit(); + if (!new_block) { + m_mtr.commit(); + return DB_OUT_OF_FILE_SPACE; + } new_page = buf_block_get_frame(new_block); new_page_zip = buf_block_get_page_zip(new_block); From 9c059a4f1cbff28634cced9f02da5a0279e6f242 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 17 Jan 2024 10:33:02 +1100 Subject: [PATCH 06/34] Spider: no need to check for ubsan when running ubsan tests It's ok to run these tests without ubsan too, and we get some tests for free. --- .../mysql-test/spider/bugfix/r/mdev_26541.result | 15 --------------- .../mysql-test/spider/bugfix/t/mdev_26541.test | 6 ++---- .../mysql-test/spider/bugfix/t/mdev_28998.test | 5 +---- .../mysql-test/spider/bugfix/t/mdev_30981.test | 11 ++++------- 4 files changed, 7 insertions(+), 30 deletions(-) diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_26541.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_26541.result index 72921d2e695..35a9d9167a6 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_26541.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_26541.result @@ -2,18 +2,3 @@ # MDEV-26541 Undefined symbol: _ZTI12ha_partition when attempting to use ha_spider.so in UBSAN builds # INSTALL SONAME 'ha_spider.so'; -DROP FUNCTION spider_flush_table_mon_cache; -DROP FUNCTION spider_copy_tables; -DROP FUNCTION spider_ping_table; -DROP FUNCTION spider_bg_direct_sql; -DROP FUNCTION spider_direct_sql; -UNINSTALL SONAME IF EXISTS "ha_spider"; -DROP TABLE IF EXISTS mysql.spider_xa; -DROP TABLE IF EXISTS mysql.spider_xa_member; -DROP TABLE IF EXISTS mysql.spider_xa_failed_log; -DROP TABLE IF EXISTS mysql.spider_tables; -DROP TABLE IF EXISTS mysql.spider_link_mon_servers; -DROP TABLE IF EXISTS mysql.spider_link_failed_log; -DROP TABLE IF EXISTS mysql.spider_table_position_for_recovery; -DROP TABLE IF EXISTS mysql.spider_table_sts; -DROP TABLE IF EXISTS mysql.spider_table_crd; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_26541.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_26541.test index bf6cb255d02..add5f621441 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_26541.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_26541.test @@ -2,10 +2,7 @@ --echo # MDEV-26541 Undefined symbol: _ZTI12ha_partition when attempting to use ha_spider.so in UBSAN builds --echo # -if (`select not(count(*)) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like "%UBSAN%"`) -{ ---skip test needs to be run with UBSAN -} +# this test should be checked with ubsan # init spider @@ -20,4 +17,5 @@ while (!$PLUGIN_EXIST) `SELECT COUNT(*) FROM mysql.func WHERE name = '$PLUGIN_NAME'`; } +--disable_query_log --source ../../include/clean_up_spider.inc 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 66e3a15addb..51d4c5c9660 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test @@ -2,10 +2,7 @@ --echo # MDEV-28998 ASAN errors in spider_fields::free_conn_holder or spider_create_group_by_handler --echo # -if (`select not(count(*)) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like "%ASAN%"`) -{ ---skip test needs to be run with ASAN -} +# this test should be checked with ubsan --disable_query_log --disable_result_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_30981.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_30981.test index cc24ce82ce4..ca3f000c819 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_30981.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_30981.test @@ -2,21 +2,18 @@ --echo # MDEV-30981 Spider UBSAN: null pointer passed as argument 2, which is declared to never be null in spider_create_trx_alter_table on ALTER --echo # -if (`select not(count(*)) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like "%UBSAN%"`) -{ ---skip test needs to be run with UBSAN -} - +# this test should be checked with ubsan + --disable_query_log --disable_result_log --source ../../t/test_init.inc --enable_result_log --enable_query_log - + CREATE TABLE t (c INT) ENGINE=Spider PARTITION BY LIST (c) (PARTITION p VALUES IN (1,2)); ALTER TABLE t ENGINE=InnoDB; drop table t; - + --disable_query_log --disable_result_log --source ../t/test_deinit.inc From 8e337e016ff882862d4d2f32488b5142370ff8da Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 17 Jan 2024 10:45:05 +0100 Subject: [PATCH 07/34] new WolfSSL v5.6.6-stable --- extra/wolfssl/user_settings.h.in | 5 +++++ extra/wolfssl/wolfssl | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/extra/wolfssl/user_settings.h.in b/extra/wolfssl/user_settings.h.in index 425f6f154b9..baa64fcdfbe 100644 --- a/extra/wolfssl/user_settings.h.in +++ b/extra/wolfssl/user_settings.h.in @@ -28,6 +28,11 @@ #define NO_OLD_TIMEVAL_NAME #define HAVE_SECURE_RENEGOTIATION #define HAVE_EXTENDED_MASTER +/* + Following is workaround about a WolfSSL 5.6.6 bug. + The bug is about undefined sessionCtxSz during compilation. +*/ +#define WOLFSSL_SESSION_ID_CTX /* TLSv1.3 definitions (all needed to build) */ #define WOLFSSL_TLS13 diff --git a/extra/wolfssl/wolfssl b/extra/wolfssl/wolfssl index 3b3c175af0e..66596ad9e1d 160000 --- a/extra/wolfssl/wolfssl +++ b/extra/wolfssl/wolfssl @@ -1 +1 @@ -Subproject commit 3b3c175af0e993ffaae251871421e206cc41963f +Subproject commit 66596ad9e1d7efa8479656872cf09c9c1870a02e From 615f4a8c9e6679322c4b788d8bbc573e53267f05 Mon Sep 17 00:00:00 2001 From: Robin Newhouse Date: Thu, 7 Dec 2023 00:16:28 +0000 Subject: [PATCH 08/34] MDEV-32587 Allow json exponential notation starting with zero Modify the NS_ZERO state in the JSON number parser to allow exponential notation with a zero coefficient (e.g. 0E-4). The NS_ZERO state transition on 'E' was updated to move to the NS_EX state rather than returning a syntax error. Similar change was made for the NS_ZE1 (negative zero) starter state. This allows accepted number grammar to include cases like: - 0E4 - -0E-10 which were previously disallowed. Numeric parsing remains the same for all other states. Test cases are added to func_json.test to validate parsing for various exponential numbers starting with zero coefficients. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services. --- mysql-test/main/func_json.result | 33 ++++++++++++++++++++++++++++++++ mysql-test/main/func_json.test | 16 ++++++++++++++++ strings/json_lib.c | 6 +++--- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 4b42c1def16..5d80ad2a7fc 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -1300,5 +1300,38 @@ f foo SET @@COLLATION_CONNECTION= @old_collation_connection; # +# MDEV-32587 JSON_VALID fail to validate integer zero in scientific notation +# +select JSON_VALID(' {"number": 1E-4}'); +JSON_VALID(' {"number": 1E-4}') +1 +select JSON_VALID(' {"number": 0E-4}'); +JSON_VALID(' {"number": 0E-4}') +1 +select JSON_VALID(' {"number": 0.0}'); +JSON_VALID(' {"number": 0.0}') +1 +select JSON_VALID(' {"number": 0.1E-4}'); +JSON_VALID(' {"number": 0.1E-4}') +1 +select JSON_VALID(' {"number": 0e-4}'); +JSON_VALID(' {"number": 0e-4}') +1 +select JSON_VALID(' {"number": -0E-4}'); +JSON_VALID(' {"number": -0E-4}') +1 +select JSON_VALUE(' {"number": 0E-4}', '$.number'); +JSON_VALUE(' {"number": 0E-4}', '$.number') +0E-4 +select JSON_VALID(' {"number": 00E-4}'); +JSON_VALID(' {"number": 00E-4}') +0 +select JSON_VALID(' {"number": 01E-4}'); +JSON_VALID(' {"number": 01E-4}') +0 +select JSON_VALID(' {"number": 0E-4.0}'); +JSON_VALID(' {"number": 0E-4.0}') +0 +# # End of 10.4 tests # diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index eed433aa118..a271dac3dca 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -840,6 +840,22 @@ SELECT JSON_VALUE('["foo"]', '$**[0]') AS f; SET @@COLLATION_CONNECTION= @old_collation_connection; +--echo # +--echo # MDEV-32587 JSON_VALID fail to validate integer zero in scientific notation +--echo # +# Passing +select JSON_VALID(' {"number": 1E-4}'); +select JSON_VALID(' {"number": 0E-4}'); +select JSON_VALID(' {"number": 0.0}'); +select JSON_VALID(' {"number": 0.1E-4}'); +select JSON_VALID(' {"number": 0e-4}'); +select JSON_VALID(' {"number": -0E-4}'); +select JSON_VALUE(' {"number": 0E-4}', '$.number'); +# Failing +select JSON_VALID(' {"number": 00E-4}'); +select JSON_VALID(' {"number": 01E-4}'); +select JSON_VALID(' {"number": 0E-4.0}'); + --echo # --echo # End of 10.4 tests --echo # diff --git a/strings/json_lib.c b/strings/json_lib.c index 781172f0340..3b9b169e2d1 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -467,12 +467,12 @@ enum json_num_states { static int json_num_states[NS_NUM_STATES][N_NUM_CLASSES]= { -/* - + 0 1..9 POINT E END_OK ERROR */ +/* - + 0 1..9 POINT E END_OK ERROR */ /*OK*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, /*GO*/ { NS_GO1, JE_SYN, NS_Z, NS_INT, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, /*GO1*/ { JE_SYN, JE_SYN, NS_Z1, NS_INT, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, -/*ZERO*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, JE_SYN, NS_OK, JE_BAD_CHR }, -/*ZE1*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, JE_SYN, NS_OK, JE_BAD_CHR }, +/*ZERO*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, NS_EX, NS_OK, JE_BAD_CHR }, +/*ZE1*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, NS_EX, NS_OK, JE_BAD_CHR }, /*INT*/ { JE_SYN, JE_SYN, NS_INT, NS_INT, NS_FRAC, NS_EX, NS_OK, JE_BAD_CHR }, /*FRAC*/ { JE_SYN, JE_SYN, NS_FRAC, NS_FRAC,JE_SYN, NS_EX, NS_OK, JE_BAD_CHR }, /*EX*/ { NS_EX, NS_EX, NS_EX1, NS_EX1, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, From ee1407f74dc063a851e1fe41b980ccc1ce4c01bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 18 Jan 2024 11:00:27 +0200 Subject: [PATCH 09/34] MDEV-32268: GNU libc posix_fallocate() may be extremely slow os_file_set_size(): Let us invoke the Linux system call fallocate(2) directly, because the GNU libc posix_fallocate() implements a fallback that writes to the file 1 byte every 4096 or fewer bytes. In one environment, invoking fallocate() directly would lead to 4 times the file growth rate during ALTER TABLE. Presumably, what happened was that the NFS server used a smaller allocation block size than 4096 bytes and therefore created a heavily fragmented sparse file when posix_fallocate() was used. For example, extending a file by 4 MiB would create 1,024 file fragments. When the file is actually being written to with data, it would be "unsparsed". The built-in EOPNOTSUPP fallback in os_file_set_size() writes a buffer of 1 MiB of NUL bytes. This was always used on musl libc and other Linux implementations of posix_fallocate(). --- storage/innobase/os/os0file.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 71e48da0dec..075f838ebb1 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -4934,8 +4934,18 @@ fallback: return true; } current_size &= ~4095ULL; +# ifdef __linux__ + if (!fallocate(file, 0, current_size, + size - current_size)) { + err = 0; + break; + } + + err = errno; +# else err = posix_fallocate(file, current_size, size - current_size); +# endif } } while (err == EINTR && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED); From 2ef01d003483edd01ff1c524b6e5f52238c7abec Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Sat, 30 Dec 2023 19:42:10 -0500 Subject: [PATCH 10/34] wsrep scripts fixes for working on OpenBSD --- scripts/wsrep_sst_common.sh | 6 +++--- scripts/wsrep_sst_rsync.sh | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 4e177073872..63d2d4ef6d1 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -1166,9 +1166,9 @@ is_local_ip() # the domain name check: if [ "${2:-0}" -eq 0 ]; then # We consider all the names of a given host to be local addresses: - [ "$1" = "$(hostname -s)" -o \ - "$1" = "$(hostname -f)" -o \ - "$1" = "$(hostname -d)" ] && return 0 + [ "$1" = "$(hostname -s 2>/dev/null)" -o \ + "$1" = "$(hostname -f 2>/dev/null)" -o \ + "$1" = "$(hostname -d 2>/dev/null)" ] && return 0 fi # If the address contains anything other than digits # and separators, it is not a local address: diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index ade9bb491e5..3dc5da7a48e 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -475,9 +475,9 @@ EOF # Preparing binlog files for transfer: wsrep_log_info "Preparing binlog files for transfer:" tar_type=0 - if tar --help | grep -qw -F -- '--transform'; then + if tar --help 2>/dev/null | grep -qw -F -- '--transform'; then tar_type=1 - elif tar --version | grep -qw -E '^bsdtar'; then + elif tar --version 2>/dev/null | grep -qw -E '^bsdtar'; then tar_type=2 fi if [ $tar_type -eq 2 ]; then @@ -980,7 +980,7 @@ EOF fi # Extracting binlog files: wsrep_log_info "Extracting binlog files:" - if tar --version | grep -qw -E '^bsdtar'; then + if tar --version 2>/dev/null | grep -qw -E '^bsdtar'; then tar -tf "$BINLOG_TAR_FILE" > "$tmpfile" && \ tar -xvf "$BINLOG_TAR_FILE" > /dev/null || RC=$? else From e8041c70656d2ebfcee8cf7343f944148b17946b Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Thu, 18 Jan 2024 20:59:00 -0800 Subject: [PATCH 11/34] MDEV-33270 Failure to call SP invoking another SP with parameter requiring type conversion This patch corrects the fix for MDEV-32569. The latter has not taken into account the fact not each statement uses the SELECT_LEX structure. In particular CALL statements do not use such structure. However the parameter passed to the stored procedure used in such a statement may require an invocation of Type_std_attributes::agg_item_set_converter(). Approved by Oleksandr Byelkin --- mysql-test/main/sp.result | 15 +++++++++++++++ mysql-test/main/sp.test | 20 ++++++++++++++++++++ sql/item.cc | 5 ++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result index 567597383bb..2f733107e8a 100644 --- a/mysql-test/main/sp.result +++ b/mysql-test/main/sp.result @@ -8960,5 +8960,20 @@ DROP FUNCTION f1; DROP FUNCTION f2; DROP FUNCTION f3; DROP VIEW v1; +# +# MDEV-33270: Call of SP invoking another SP with a parameter +# requiring type conversion +# +SET NAMES latin1; +CREATE PROCEDURE p1 (a text) BEGIN SELECT a; END | +CREATE PROCEDURE p2 () CALL p1(concat('x',_utf8'x')) | +CALL p2(); +a +xx +CALL p2(); +a +xx +DROP PROCEDURE p1; +DROP PROCEDURE p2; # End of 10.4 tests # diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test index c11ea23080b..50d9a611db9 100644 --- a/mysql-test/main/sp.test +++ b/mysql-test/main/sp.test @@ -10567,5 +10567,25 @@ DROP FUNCTION f2; DROP FUNCTION f3; DROP VIEW v1; +--echo # +--echo # MDEV-33270: Call of SP invoking another SP with a parameter +--echo # requiring type conversion +--echo # + +SET NAMES latin1; + +--delimiter | + +CREATE PROCEDURE p1 (a text) BEGIN SELECT a; END | +CREATE PROCEDURE p2 () CALL p1(concat('x',_utf8'x')) | + +--delimiter ; + +CALL p2(); +CALL p2(); + +DROP PROCEDURE p1; +DROP PROCEDURE p2; + --echo # End of 10.4 tests --echo # diff --git a/sql/item.cc b/sql/item.cc index 6d30d63bc11..04b689f51af 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2586,7 +2586,10 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll, return TRUE; if (!thd->stmt_arena->is_conventional() && - thd->lex->current_select->first_cond_optimization) + ((!thd->lex->current_select && + (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute() || + thd->stmt_arena->is_stmt_prepare_or_first_stmt_execute())) || + thd->lex->current_select->first_cond_optimization)) { Query_arena *arena, backup; arena= thd->activate_stmt_arena_if_needed(&backup); From 7e8e51eb3ad1ffd1bf8ec9c5dc23038e0e2e4b9c Mon Sep 17 00:00:00 2001 From: Sisi Huang Date: Thu, 11 Jan 2024 23:02:34 -0800 Subject: [PATCH 12/34] MDEV-32990 federatedx time_zone round trips Modified `federatedx_io_mysql::actual_query` to set the time zone to '+00:00' only upon establishing a new connection instead of with each query execution. --- storage/federatedx/federatedx_io_mysql.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/storage/federatedx/federatedx_io_mysql.cc b/storage/federatedx/federatedx_io_mysql.cc index cf620d59986..5c96982cf59 100644 --- a/storage/federatedx/federatedx_io_mysql.cc +++ b/storage/federatedx/federatedx_io_mysql.cc @@ -451,11 +451,14 @@ int federatedx_io_mysql::actual_query(const char *buffer, size_t length) get_port(), get_socket(), 0)) DBUG_RETURN(ER_CONNECT_TO_FOREIGN_DATA_SOURCE); + + if ((error= mysql_real_query(&mysql, STRING_WITH_LEN("set time_zone='+00:00'")))) + DBUG_RETURN(error); + mysql.reconnect= 1; } - if (!(error= mysql_real_query(&mysql, STRING_WITH_LEN("set time_zone='+00:00'")))) - error= mysql_real_query(&mysql, buffer, (ulong)length); + error= mysql_real_query(&mysql, buffer, (ulong)length); DBUG_RETURN(error); } From 3cd8875145b2c1dffe1f12510fbf92bf1a8f2fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 16 Jan 2024 08:02:32 +0200 Subject: [PATCH 13/34] MDEV-14448: Ctrl-C should not exit the client This patch introduces the following behaviour for Linux while maintaining old behaviour for Windows: Ctrl + C (sigint) clears the current buffer and redraws the prompt. Ctrl-C no longer exits the client if no query is running. Ctrl-C kills the current running query if there is one. If there is an error communicating with the server while trying to issue a KILL QUERY, the client exits. This is in line with the past behaviour of Ctrl-C. On Linux Ctrl-D can be used to close the client. On Windows Ctrl-C and Ctrl-BREAK still exits the client if no query is running. Windows can also exit the client via \q or exit. == Implementation details == The Linux implementation has two corner cases, based on which library is used: libreadline or libedit, both are handled in code to achieve the same user experience. Additional code is taken from MySQL, ensuring there is identical behaviour on Windows, to MySQL's mysql client implementation for other CTRL- related signals. * The CTRL_CLOSE, CTRL_LOGOFF, CTRL_SHUTDOWN will issue the equivalent of CTRL-C and "end" the program. This ensures that the query is killed when the client is closed by closing the terminal, logging off the user or shutting down the system. The latter two signals are not sent for interactive applications, but it handles the case when a user has defined a service to use mysql client to issue a command. See https://learn.microsoft.com/en-us/windows/console/handlerroutine This patch is built on top of the initial work done by Anel Husakovic . Closes #2815 --- client/mysql.cc | 173 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 139 insertions(+), 34 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 214b0d51a32..befa0e9b113 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -89,6 +89,7 @@ extern "C" { #undef bcmp // Fix problem with new readline #if defined(__WIN__) #include +#include #else # ifdef __APPLE__ # include @@ -170,6 +171,9 @@ static int connect_flag=CLIENT_INTERACTIVE; static my_bool opt_binary_mode= FALSE; static my_bool opt_connect_expired_password= FALSE; static int interrupted_query= 0; +#ifdef USE_LIBEDIT_INTERFACE +static int sigint_received= 0; +#endif static char *current_host,*current_db,*current_user=0,*opt_password=0, *current_prompt=0, *delimiter_str= 0, *default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME, @@ -1072,7 +1076,32 @@ extern "C" sig_handler handle_sigint(int sig); static sig_handler window_resize(int sig); #endif +static void end_in_sig_handler(int sig); +static bool kill_query(const char *reason); +#ifdef _WIN32 +static BOOL WINAPI ctrl_handler_windows(DWORD fdwCtrlType) +{ + switch (fdwCtrlType) + { + // Handle the CTRL-C signal. + case CTRL_C_EVENT: + case CTRL_BREAK_EVENT: + handle_sigint(SIGINT); + return TRUE; // this means that the signal is handled + case CTRL_CLOSE_EVENT: + case CTRL_LOGOFF_EVENT: + case CTRL_SHUTDOWN_EVENT: + kill_query("Terminate"); + end_in_sig_handler(SIGINT + 1); + aborted= 1; + } + // This means to pass the signal to the next handler. This allows + // my_cgets and the internal ReadConsole call to exit and gracefully + // abort the program. + return FALSE; +} +#endif const char DELIMITER_NAME[]= "delimiter"; const uint DELIMITER_NAME_LEN= sizeof(DELIMITER_NAME) - 1; inline bool is_delimiter_command(char *name, ulong len) @@ -1205,11 +1234,12 @@ int main(int argc,char *argv[]) if (!status.batch) ignore_errors=1; // Don't abort monitor - if (opt_sigint_ignore) - signal(SIGINT, SIG_IGN); - else - signal(SIGINT, handle_sigint); // Catch SIGINT to clean up - signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up +#ifndef _WIN32 + signal(SIGINT, handle_sigint); // Catch SIGINT to clean up + signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up +#else + SetConsoleCtrlHandler(ctrl_handler_windows, TRUE); +#endif #if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL) /* Readline will call this if it installs a handler */ @@ -1376,30 +1406,35 @@ static bool do_connect(MYSQL *mysql, const char *host, const char *user, } -/* - This function handles sigint calls - If query is in process, kill query - If 'source' is executed, abort source command - no query in process, terminate like previous behavior - */ +void end_in_sig_handler(int sig) +{ +#ifdef _WIN32 + /* + When SIGINT is raised on Windows, the OS creates a new thread to handle the + interrupt. Once that thread completes, the main thread continues running + only to find that it's resources have already been free'd when the sigint + handler called mysql_end(). + */ + mysql_thread_end(); +#else + mysql_end(sig); +#endif +} -sig_handler handle_sigint(int sig) + +/* + Kill a running query. Returns true if we were unable to connect to the server. +*/ +bool kill_query(const char *reason) { char kill_buffer[40]; MYSQL *kill_mysql= NULL; - /* terminate if no query being executed, or we already tried interrupting */ - if (!executing_query || (interrupted_query == 2)) - { - tee_fprintf(stdout, "Ctrl-C -- exit!\n"); - goto err; - } - kill_mysql= mysql_init(kill_mysql); if (!do_connect(kill_mysql,current_host, current_user, opt_password, "", 0)) { - tee_fprintf(stdout, "Ctrl-C -- sorry, cannot connect to server to kill query, giving up ...\n"); - goto err; + tee_fprintf(stdout, "%s -- sorry, cannot connect to server to kill query, giving up ...\n", reason); + return true; } /* First time try to kill the query, second time the connection */ @@ -1414,27 +1449,65 @@ sig_handler handle_sigint(int sig) (interrupted_query == 1) ? "QUERY " : "", mysql_thread_id(&mysql)); if (verbose) - tee_fprintf(stdout, "Ctrl-C -- sending \"%s\" to server ...\n", + tee_fprintf(stdout, "%s -- sending \"%s\" to server ...\n", reason, kill_buffer); mysql_real_query(kill_mysql, kill_buffer, (uint) strlen(kill_buffer)); mysql_close(kill_mysql); - tee_fprintf(stdout, "Ctrl-C -- query killed. Continuing normally.\n"); + if (interrupted_query == 1) + tee_fprintf(stdout, "%s -- query killed.\n", reason); + else + tee_fprintf(stdout, "%s -- connection killed.\n", reason); + if (in_com_source) aborted= 1; // Abort source command - return; + return false; +} + +/* + This function handles sigint calls + If query is in process, kill query + If 'source' is executed, abort source command + no query in process, regenerate prompt. +*/ +sig_handler handle_sigint(int sig) +{ + if (opt_sigint_ignore) + return; -err: -#ifdef _WIN32 /* - When SIGINT is raised on Windows, the OS creates a new thread to handle the - interrupt. Once that thread completes, the main thread continues running - only to find that it's resources have already been free'd when the sigint - handler called mysql_end(). + On Unix only, if no query is being executed just clear the prompt, + don't exit. On Windows we exit. */ - mysql_thread_end(); + if (!executing_query) + { +#ifndef _WIN32 + tee_fprintf(stdout, "^C\n"); +#ifdef USE_LIBEDIT_INTERFACE + /* Libedit will regenerate it outside of the signal handler. */ + sigint_received= 1; #else - mysql_end(sig); -#endif + rl_on_new_line(); // Regenerate the prompt on a newline + rl_replace_line("", 0); // Clear the previous text + rl_redisplay(); +#endif +#else // WIN32 + tee_fprintf(stdout, "Ctrl-C -- exit!\n"); + end_in_sig_handler(sig); +#endif + return; + } + + /* + When executing a query, this newline makes the prompt look like so: + ^C + Ctrl-C -- query killed. + */ + tee_fprintf(stdout, "\n"); + if (kill_query("Ctrl-C")) + { + aborted= 1; + end_in_sig_handler(sig); + } } @@ -1973,6 +2046,12 @@ static int get_options(int argc, char **argv) return(0); } +static inline void reset_prompt(char *in_string, bool *ml_comment) { + glob_buffer.length(0); + *ml_comment = false; + *in_string = 0; +} + static int read_and_execute(bool interactive) { #if defined(__WIN__) @@ -2063,7 +2142,7 @@ static int read_and_execute(bool interactive) size_t clen; do { - line= my_cgets((char*)tmpbuf.ptr(), tmpbuf.alloced_length()-1, &clen); + line= my_cgets((char*)tmpbuf.ptr(), tmpbuf.alloced_length()-1, &clen); buffer.append(line, clen); /* if we got buffer fully filled than there is a chance that @@ -2085,8 +2164,34 @@ static int read_and_execute(bool interactive) the readline/libedit library. */ if (line) + { free(line); + glob_buffer.length(0); + } line= readline(prompt); +#ifdef USE_LIBEDIT_INTERFACE + /* + libedit handles interrupts different than libreadline. + libreadline has its own signal handlers, thus a sigint during readline + doesn't force readline to return null string. + + However libedit returns null if the interrupt signal is raised. + We can also get an empty string when ctrl+d is pressed (EoF). + + We need this sigint_received flag, to differentiate between the two + cases. This flag is only set during our handle_sigint function when + LIBEDIT_INTERFACE is used. + */ + if (!line && sigint_received) + { + // User asked to clear the input. + sigint_received= 0; + reset_prompt(&in_string, &ml_comment); + continue; + } + // For safety, we always mark this as cleared. + sigint_received= 0; +#endif #endif /* defined(__WIN__) */ /* From 01ca57ec1615015e163123fa1882bcc278c81b9a Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 17 Jan 2024 07:14:11 -0700 Subject: [PATCH 14/34] MDEV-32168: Postpush fix for rpl_domain_id_filter_master_crash While a replica may be reading events from the primary, the primary is killed. Left to its own devices, the IO thread may or may not stop in error, depending on what it is doing when its connection to the primary is killed (e.g. a failed read results in an error, whereas if the IO thread is idly waiting for events when the connection dies, it will enter into a reconnect loop and reconnect). MDEV-32168 changed the test to always wait for the reconnect, thus breaking the error case, as the IO thread would be stopped at a time of expecting it to be running. The fix is to manually stop/start the IO thread to ensure it is in a consistent state. Note that rpl_domain_id_filter_master_crash.test will need additional changes after fixing MDEV-33268 Reviewed By: ============ Kristian Nielsen --- .../rpl_domain_id_filter_master_crash.result | 5 +++-- .../t/rpl_domain_id_filter_master_crash.test | 20 +++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result b/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result index 4169a2ddc26..a54ff99b591 100644 --- a/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result +++ b/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result @@ -38,8 +38,9 @@ connection master; include/rpl_start_server.inc [server_number=1] # Master has restarted successfully connection slave; -include/wait_for_slave_io_to_start.inc -include/wait_for_slave_sql_to_start.inc +include/stop_slave_sql.inc +include/stop_slave_io.inc +include/start_slave.inc select * from ti; a 1 diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test index b1fa9af33a4..cdfdc098f5a 100644 --- a/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test @@ -67,10 +67,26 @@ connection master; save_master_pos; --connection slave + +# Left to its own devices, the IO thread may or may not stop in error, +# depending on what it is doing when its connection to the primary is killed +# (e.g. a failed read results in an error, whereas if the IO thread is idly +# waiting for events when the connection dies, it will enter into a reconnect +# loop and reconnect). So we manually stop/start the IO thread to ensure it is +# in a consistent state +# +# FIXME: We shouldn't need to stop/start the SQL thread here, but due to +# MDEV-33268, we have to. So after fixing 33268, this should only stop/start +# the IO thread. Note the SQL thread must be stopped first due to an invalid +# DBUG_ASSERT in the IO thread's stop logic that depends on the state of the +# SQL thread (also reported and to be fixed in the same ticket). +# +--source include/stop_slave_sql.inc --let rpl_allow_error=1 ---source include/wait_for_slave_io_to_start.inc +--source include/stop_slave_io.inc --let rpl_allow_error= ---source include/wait_for_slave_sql_to_start.inc +--source include/start_slave.inc + sync_with_master; select * from ti; select * from tm; From a9172b8a436a9e403aee63a16f9a5655b9c98e9b Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 22 Jan 2024 15:27:58 +0100 Subject: [PATCH 15/34] Update minizip files for connect enginbe from last zlib 1.3. --- storage/connect/zip.c | 369 ++++++++++++++++++------------------------ storage/connect/zip.h | 292 ++++++++++++++++----------------- 2 files changed, 303 insertions(+), 358 deletions(-) diff --git a/storage/connect/zip.c b/storage/connect/zip.c index f6a10601968..3d3d4caddef 100644 --- a/storage/connect/zip.c +++ b/storage/connect/zip.c @@ -14,8 +14,8 @@ Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data - It is used when recreting zip archive with RAW when deleting items from a zip. - ZIP64 data is automaticly added to items that needs it, and existing ZIP64 data need to be removed. + It is used when recreating zip archive with RAW when deleting items from a zip. + ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed. Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer @@ -25,15 +25,13 @@ #include #include #include +#include #include #include "zlib.h" #include "zip.h" -#include "my_attribute.h" #ifdef STDC # include -# include -# include #endif #ifdef NO_ERRNO_H extern int errno; @@ -48,7 +46,7 @@ /* compile with -Dlocal if your debugger can't find static symbols */ #ifndef VERSIONMADEBY -# define VERSIONMADEBY (0x0) /* platform depedent */ +# define VERSIONMADEBY (0x0) /* platform dependent */ #endif #ifndef Z_BUFSIZE @@ -62,9 +60,6 @@ #ifndef ALLOC # define ALLOC(size) (malloc(size)) #endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif /* #define SIZECENTRALDIRITEM (0x2e) @@ -117,7 +112,7 @@ typedef struct linkedlist_datablock_internal_s struct linkedlist_datablock_internal_s* next_datablock; uLong avail_in_this_block; uLong filled_in_this_block; - uLong unused; /* for future use and alignement */ + uLong unused; /* for future use and alignment */ unsigned char data[SIZEDATA_INDATABLOCK]; } linkedlist_datablock_internal; @@ -139,40 +134,40 @@ typedef struct uInt pos_in_buffered_data; /* last written byte in buffered_data */ ZPOS64_T pos_local_header; /* offset of the local header of the file - currenty writing */ + currently writing */ char* central_header; /* central header data for the current file */ uLong size_centralExtra; uLong size_centralheader; /* size of the central header for cur file */ uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ uLong flag; /* flag of the file currently writing */ - int method; /* compression method of file currenty wr.*/ + int method; /* compression method of file currently wr.*/ int raw; /* 1 for directly writing raw data */ Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ uLong dosDate; uLong crc32; int encrypt; - int zip64; /* Add ZIP64 extened information in the extra field */ + int zip64; /* Add ZIP64 extended information in the extra field */ ZPOS64_T pos_zip64extrainfo; ZPOS64_T totalCompressedData; ZPOS64_T totalUncompressedData; #ifndef NOCRYPT unsigned long keys[3]; /* keys defining the pseudo-random sequence */ const z_crc_t* pcrc_32_tab; - int crypt_header_size; + unsigned crypt_header_size; #endif } curfile64_info; typedef struct { zlib_filefunc64_32_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ + voidpf filestream; /* io structure of the zipfile */ linkedlist_data central_dir;/* datablock with central dir in construction*/ int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ - curfile64_info ci; /* info on the file curretly writing */ + curfile64_info ci; /* info on the file currently writing */ ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ - ZPOS64_T add_position_when_writting_offset; + ZPOS64_T add_position_when_writing_offset; ZPOS64_T number_entry; #ifndef NO_ADDFILEINEXISTINGZIP @@ -187,8 +182,7 @@ typedef struct #include "crypt.h" #endif -local linkedlist_datablock_internal* allocate_new_datablock() -{ +local linkedlist_datablock_internal* allocate_new_datablock(void) { linkedlist_datablock_internal* ldi; ldi = (linkedlist_datablock_internal*) ALLOC(sizeof(linkedlist_datablock_internal)); @@ -201,30 +195,26 @@ local linkedlist_datablock_internal* allocate_new_datablock() return ldi; } -local void free_datablock(linkedlist_datablock_internal* ldi) -{ +local void free_datablock(linkedlist_datablock_internal* ldi) { while (ldi!=NULL) { linkedlist_datablock_internal* ldinext = ldi->next_datablock; - TRYFREE(ldi); + free(ldi); ldi = ldinext; } } -local void init_linkedlist(linkedlist_data* ll) -{ +local void init_linkedlist(linkedlist_data* ll) { ll->first_block = ll->last_block = NULL; } -local void free_linkedlist(linkedlist_data* ll) -{ +local void free_linkedlist(linkedlist_data* ll) { free_datablock(ll->first_block); ll->first_block = ll->last_block = NULL; } -local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) -{ +local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) { linkedlist_datablock_internal* ldi; const unsigned char* from_copy; @@ -239,7 +229,7 @@ local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) } ldi = ll->last_block; - from_copy = (unsigned char*)buf; + from_copy = (const unsigned char*)buf; while (len>0) { @@ -284,9 +274,7 @@ local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) */ -local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); -local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) -{ +local int zip64local_putValue(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) { unsigned char buf[8]; int n; for (n = 0; n < nbByte; n++) @@ -302,15 +290,13 @@ local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, } } - if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) + if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,(uLong)nbByte)!=(uLong)nbByte) return ZIP_ERRNO; else return ZIP_OK; } -local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); -local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) -{ +local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) { unsigned char* buf=(unsigned char*)dest; int n; for (n = 0; n < nbByte; n++) { @@ -330,25 +316,21 @@ local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) /****************************************************************************/ -local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) -{ +local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) { uLong year = (uLong)ptm->tm_year; if (year>=1980) year-=1980; else if (year>=80) year-=80; return - (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | - ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); + (uLong) (((uLong)(ptm->tm_mday) + (32 * (uLong)(ptm->tm_mon+1)) + (512 * year)) << 16) | + (((uLong)ptm->tm_sec/2) + (32 * (uLong)ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); } /****************************************************************************/ -local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); - -local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) -{ +local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int* pi) { unsigned char c; int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); if (err==1) @@ -369,10 +351,7 @@ local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,vo /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets */ -local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ +local int zip64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) { uLong x ; int i = 0; int err; @@ -391,10 +370,7 @@ local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, return err; } -local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ +local int zip64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) { uLong x ; int i = 0; int err; @@ -421,11 +397,8 @@ local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, return err; } -local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); - -local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) -{ +local int zip64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) { ZPOS64_T x; int i = 0; int err; @@ -476,10 +449,7 @@ local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def Locate the Central directory of a zipfile (at the end, just before the global comment) */ -local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ +local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; @@ -519,18 +489,18 @@ local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) break; - for (i=(int)uReadSize-3; (i--)>0;) { + for (i=(int)uReadSize-3; (i--)>0;) if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) { - uPosFound = uReadPos+i; + uPosFound = uReadPos+(unsigned)i; break; } - } + if (uPosFound!=0) break; } - TRYFREE(buf); + free(buf); return uPosFound; } @@ -538,10 +508,7 @@ local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before the global comment) */ -local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ +local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; @@ -587,7 +554,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib // Signature "0x07064b50" Zip64 end of central directory locater if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) { - uPosFound = uReadPos+i; + uPosFound = uReadPos+(unsigned)i; break; } } @@ -596,7 +563,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib break; } - TRYFREE(buf); + free(buf); if (uPosFound == 0) return 0; @@ -638,8 +605,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib return relativeOffset; } -static int LoadCentralDirectoryRecord(zip64_internal* pziinit) -{ +local int LoadCentralDirectoryRecord(zip64_internal* pziinit) { int err=ZIP_OK; ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ @@ -649,9 +615,9 @@ static int LoadCentralDirectoryRecord(zip64_internal* pziinit) uLong uL; uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ + spanning ZIP, unsupported, always 0*/ uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ + for spanning ZIP, unsupported, always 0*/ ZPOS64_T number_entry; ZPOS64_T number_entry_CD; /* total number of entries in the central dir @@ -808,7 +774,7 @@ static int LoadCentralDirectoryRecord(zip64_internal* pziinit) } byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); - pziinit->add_position_when_writting_offset = byte_before_the_zipfile; + pziinit->add_position_when_writing_offset = byte_before_the_zipfile; { ZPOS64_T size_central_dir_to_read = size_central_dir; @@ -831,7 +797,7 @@ static int LoadCentralDirectoryRecord(zip64_internal* pziinit) size_central_dir_to_read-=read_this; } - TRYFREE(buf_read); + free(buf_read); } pziinit->begin_pos = byte_before_the_zipfile; pziinit->number_entry = number_entry_CD; @@ -847,8 +813,7 @@ static int LoadCentralDirectoryRecord(zip64_internal* pziinit) /************************************************************/ -static zipFile zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) -{ +extern zipFile ZEXPORT zipOpen3(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) { zip64_internal ziinit; zip64_internal* zi; int err=ZIP_OK; @@ -876,7 +841,7 @@ static zipFile zipOpen3 (const void *pathname, int append, zipcharpc* globalcomm ziinit.in_opened_file_inzip = 0; ziinit.ci.stream_initialised = 0; ziinit.number_entry = 0; - ziinit.add_position_when_writting_offset = 0; + ziinit.add_position_when_writing_offset = 0; init_linkedlist(&(ziinit.central_dir)); @@ -906,9 +871,9 @@ static zipFile zipOpen3 (const void *pathname, int append, zipcharpc* globalcomm if (err != ZIP_OK) { # ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(ziinit.globalcomment); + free(ziinit.globalcomment); # endif /* !NO_ADDFILEINEXISTINGZIP*/ - TRYFREE(zi); + free(zi); return NULL; } else @@ -918,8 +883,7 @@ static zipFile zipOpen3 (const void *pathname, int append, zipcharpc* globalcomm } } -extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) -{ +extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) { if (pzlib_filefunc32_def != NULL) { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; @@ -930,8 +894,7 @@ extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* gl return zipOpen3(pathname, append, globalcomment, NULL); } -extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) -{ +extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) { if (pzlib_filefunc_def != NULL) { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; @@ -946,18 +909,15 @@ extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* -extern zipFile ZEXPORT zipOpen (const char* pathname, int append) -{ +extern zipFile ZEXPORT zipOpen(const char* pathname, int append) { return zipOpen3((const void*)pathname,append,NULL,NULL); } -extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) -{ +extern zipFile ZEXPORT zipOpen64(const void* pathname, int append) { return zipOpen3(pathname,append,NULL,NULL); } -static int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) -{ +local int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) { /* write the local header */ int err; uInt size_filename = (uInt)strlen(filename); @@ -1035,8 +995,8 @@ static int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2); - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)HeaderID,2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)DataSize,2); err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); @@ -1053,24 +1013,24 @@ static int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize unnecessary allocations. */ -extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting __attribute__((unused)), - uLong versionMadeBy, uLong flagBase, int zip64) -{ +extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase, int zip64) { zip64_internal* zi; uInt size_filename; uInt size_comment; uInt i; int err = ZIP_OK; -#ifdef NOCRYPT +# ifdef NOCRYPT + (crcForCrypting); if (password != NULL) return ZIP_PARAMERROR; -#endif +# endif if (file == NULL) return ZIP_PARAMERROR; @@ -1164,7 +1124,7 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, if(zi->ci.pos_local_header >= 0xffffffff) zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); else - zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset,4); + zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4); for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); @@ -1262,35 +1222,33 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, return err; } -extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, - uLong versionMadeBy, uLong flagBase) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, versionMadeBy, flagBase, 0); +extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, versionMadeBy, flagBase, 0); } -extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, VERSIONMADEBY, 0, 0); +extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, 0); } extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, @@ -1298,70 +1256,64 @@ extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, c const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, VERSIONMADEBY, 0, zip64); + const char* password, uLong crcForCrypting, int zip64) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, zip64); } extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, 0); + const char* comment, int method, int level, int raw) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); } extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, zip64); + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, int zip64) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); } -extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void*extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, 0, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, zip64); +extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int zip64) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); } -extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void*extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, 0, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, 0); +extern int ZEXPORT zipOpenNewFileInZip(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); } -local int zip64FlushWriteBuffer(zip64_internal* zi) -{ +local int zip64FlushWriteBuffer(zip64_internal* zi) { int err=ZIP_OK; if (zi->ci.encrypt != 0) @@ -1399,8 +1351,7 @@ local int zip64FlushWriteBuffer(zip64_internal* zi) return err; } -extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len) -{ +extern int ZEXPORT zipWriteInFileInZip(zipFile file, const void* buf, unsigned int len) { zip64_internal* zi; int err=ZIP_OK; @@ -1450,7 +1401,7 @@ extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned in else #endif { - zi->ci.stream.next_in = (Bytef*)buf; + zi->ci.stream.next_in = (Bytef*)(uintptr_t)buf; zi->ci.stream.avail_in = len; while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) @@ -1501,17 +1452,15 @@ extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned in return err; } -extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) -{ +extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, uLong crc32) { return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); } -extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) -{ +extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32) { zip64_internal* zi; ZPOS64_T compressed_size; uLong invalidValue = 0xffffffff; - short datasize = 0; + unsigned datasize = 0; int err=ZIP_OK; if (file == NULL) @@ -1742,15 +1691,13 @@ extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_s return err; } -extern int ZEXPORT zipCloseFileInZip (zipFile file) -{ +extern int ZEXPORT zipCloseFileInZip(zipFile file) { return zipCloseFileInZipRaw (file,0,0); } -static int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) -{ +local int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) { int err = ZIP_OK; - ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset; + ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset; err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); @@ -1769,8 +1716,7 @@ static int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T return err; } -static int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ +local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK; uLong Zip64DataSize = 44; @@ -1803,13 +1749,13 @@ static int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ { - ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); } return err; } -static int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ + +local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK; /*signature*/ @@ -1844,20 +1790,19 @@ static int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_cent if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ { - ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; if(pos >= 0xffffffff) { err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4); } else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4); } return err; } -static int Write_GlobalComment(zip64_internal* zi, const char* global_comment) -{ +local int Write_GlobalComment(zip64_internal* zi, const char* global_comment) { int err = ZIP_OK; uInt size_global_comment = 0; @@ -1874,8 +1819,7 @@ static int Write_GlobalComment(zip64_internal* zi, const char* global_comment) return err; } -extern int ZEXPORT zipClose (zipFile file, const char* global_comment) -{ +extern int ZEXPORT zipClose(zipFile file, const char* global_comment) { zip64_internal* zi; int err = 0; uLong size_centraldir = 0; @@ -1916,7 +1860,7 @@ extern int ZEXPORT zipClose (zipFile file, const char* global_comment) } free_linkedlist(&(zi->central_dir)); - pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; if(pos >= 0xffffffff || zi->number_entry > 0xFFFF) { ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); @@ -1936,15 +1880,14 @@ extern int ZEXPORT zipClose (zipFile file, const char* global_comment) err = ZIP_ERRNO; #ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(zi->globalcomment); + free(zi->globalcomment); #endif - TRYFREE(zi); + free(zi); return err; } -extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader) -{ +extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader) { char* p = pData; int size = 0; char* pNewHeader; @@ -1954,10 +1897,10 @@ extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHe int retVal = ZIP_OK; - if(pData == NULL || *dataLen < 4) + if(pData == NULL || dataLen == NULL || *dataLen < 4) return ZIP_PARAMERROR; - pNewHeader = (char*)ALLOC(*dataLen); + pNewHeader = (char*)ALLOC((unsigned)*dataLen); pTmp = pNewHeader; while(p < (pData + *dataLen)) @@ -1996,7 +1939,7 @@ extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHe else retVal = ZIP_ERRNO; - TRYFREE(pNewHeader); + free(pNewHeader); return retVal; } diff --git a/storage/connect/zip.h b/storage/connect/zip.h index 8aaebb62343..5fc08413241 100644 --- a/storage/connect/zip.h +++ b/storage/connect/zip.h @@ -88,12 +88,12 @@ typedef voidp zipFile; /* tm_zip contain date/time info */ typedef struct tm_zip_s { - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ + int tm_sec; /* seconds after the minute - [0,59] */ + int tm_min; /* minutes after the hour - [0,59] */ + int tm_hour; /* hours since midnight - [0,23] */ + int tm_mday; /* day of the month - [1,31] */ + int tm_mon; /* months since January - [0,11] */ + int tm_year; /* years - [1980..2044] */ } tm_zip; typedef struct @@ -113,8 +113,8 @@ typedef const char* zipcharpc; #define APPEND_STATUS_CREATEAFTER (1) #define APPEND_STATUS_ADDINZIP (2) -extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); -extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); +extern zipFile ZEXPORT zipOpen(const char *pathname, int append); +extern zipFile ZEXPORT zipOpen64(const void *pathname, int append); /* Create a zipfile. pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on @@ -131,41 +131,46 @@ extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); /* Note : there is no delete function into a zipfile. If you want delete file into a zipfile, you must open a zipfile, and create another - Of couse, you can use RAW reading and writing to copy the file you did not want delte + Of course, you can use RAW reading and writing to copy the file you did not want delete */ -extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, +extern zipFile ZEXPORT zipOpen2(const char *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def); + +extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment, - zlib_filefunc_def* pzlib_filefunc_def)); + zlib_filefunc64_def* pzlib_filefunc_def); -extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname, - int append, - zipcharpc* globalcomment, - zlib_filefunc64_def* pzlib_filefunc_def)); +extern zipFile ZEXPORT zipOpen3(const void *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc64_32_def* pzlib_filefunc64_32_def); -extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level)); +extern int ZEXPORT zipOpenNewFileInZip(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level); -extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int zip64)); +extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int zip64); /* Open a file in the ZIP for writing. @@ -184,70 +189,69 @@ extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, */ -extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw)); +extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw); -extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int zip64)); +extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int zip64); /* Same than zipOpenNewFileInZip, except if raw=1, we write raw file */ -extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting)); +extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting); -extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - int zip64 - )); +extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + int zip64); /* Same than zipOpenNewFileInZip2, except @@ -256,47 +260,45 @@ extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, crcForCrypting : crc of file to compress (needed for crypting) */ -extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - uLong versionMadeBy, - uLong flagBase - )); +extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase); -extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - uLong versionMadeBy, - uLong flagBase, - int zip64 - )); +extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase, + int zip64); /* Same than zipOpenNewFileInZip4, except versionMadeBy : value for Version made by field @@ -304,25 +306,25 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, */ -extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, - const void* buf, - unsigned len)); +extern int ZEXPORT zipWriteInFileInZip(zipFile file, + const void* buf, + unsigned len); /* Write data in the zipfile */ -extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +extern int ZEXPORT zipCloseFileInZip(zipFile file); /* Close the current file in the zipfile */ -extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, - uLong uncompressed_size, - uLong crc32)); +extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, + uLong uncompressed_size, + uLong crc32); -extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, - ZPOS64_T uncompressed_size, - uLong crc32)); +extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, + ZPOS64_T uncompressed_size, + uLong crc32); /* Close the current file in the zipfile, for file opened with @@ -330,14 +332,14 @@ extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, uncompressed_size and crc32 are value for the uncompressed size */ -extern int ZEXPORT zipClose OF((zipFile file, - const char* global_comment)); +extern int ZEXPORT zipClose(zipFile file, + const char* global_comment); /* Close the zipfile */ -extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader)); +extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader); /* zipRemoveExtraInfoBlock - Added by Mathias Svensson From 15bd7e0b89eef3c85fbca61b4d738decbbc27dd3 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 22 Jan 2024 15:39:09 +0100 Subject: [PATCH 16/34] "New" version of CC (in fact no changes) --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index ae565eea90d..f1a72768d42 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit ae565eea90dd3053a5a7857e7cdad93342dbc645 +Subproject commit f1a72768d4256416e5c0bf01b254c303f6135bd0 From 81d01855fecbf60b87dbac5b44d3db7c0e6f37ef Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 23 Jan 2024 13:22:58 +0400 Subject: [PATCH 17/34] MDEV-28651 quote(NULL) returns incorrect result in view ('NU' instead of 'NULL') Item_func_quote did not calculate its max_length correctly for nullable arguments. Fix: In case if the argument is nullable, reserve at least 4 characters so the string "NULL" fits. --- mysql-test/main/func_str.result | 27 +++++++++++++++++++++++++++ mysql-test/main/func_str.test | 22 ++++++++++++++++++++++ sql/item_strfunc.h | 3 +++ 3 files changed, 52 insertions(+) diff --git a/mysql-test/main/func_str.result b/mysql-test/main/func_str.result index b4f25c34848..a47c149fb0d 100644 --- a/mysql-test/main/func_str.result +++ b/mysql-test/main/func_str.result @@ -5286,3 +5286,30 @@ ERROR 42000: Incorrect parameter count in the call to native function 'DECODE' # # End of 10.4 tests # +# +# Start of 10.5 tests +# +# +# MDEV-28651 quote(NULL) returns incorrect result in view ('NU' instead of 'NULL') +# +CREATE VIEW v1 AS SELECT quote(NULL); +SELECT * FROM v1; +quote(NULL) +NULL +DESCRIBE v1; +Field Type Null Key Default Extra +quote(NULL) varbinary(4) YES NULL +CREATE TABLE t1 AS SELECT * FROM v1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `quote(NULL)` varbinary(4) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT * FROM t1; +quote(NULL) +NULL +DROP TABLE t1; +DROP VIEW v1; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/func_str.test b/mysql-test/main/func_str.test index b452ed1fe90..69161349720 100644 --- a/mysql-test/main/func_str.test +++ b/mysql-test/main/func_str.test @@ -2329,3 +2329,25 @@ SELECT DECODE(NULL, NULL, NULL); --echo # --echo # End of 10.4 tests --echo # + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-28651 quote(NULL) returns incorrect result in view ('NU' instead of 'NULL') +--echo # + +CREATE VIEW v1 AS SELECT quote(NULL); +SELECT * FROM v1; +DESCRIBE v1; +CREATE TABLE t1 AS SELECT * FROM v1; +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +DROP VIEW v1; + + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index f9dba473e71..e770c3bff98 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -1504,6 +1504,9 @@ public: collation.set(args[0]->collation); ulonglong max_result_length= (ulonglong) args[0]->max_length * 2 + 2 * collation.collation->mbmaxlen; + // NULL argument is returned as a string "NULL" without quotes + if (args[0]->maybe_null) + set_if_bigger(max_result_length, 4 * collation.collation->mbmaxlen); max_length= (uint32) MY_MIN(max_result_length, MAX_BLOB_WIDTH); return FALSE; } From 27459b413deb1e21c2e9686e36ab44788a132b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 23 Jan 2024 16:24:27 +0200 Subject: [PATCH 18/34] MDEV-14448: Ctrl-C should not exit client Undo any Windows behaviour changes. --- client/mysql.cc | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index befa0e9b113..fe086f29dac 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -89,7 +89,6 @@ extern "C" { #undef bcmp // Fix problem with new readline #if defined(__WIN__) #include -#include #else # ifdef __APPLE__ # include @@ -1079,29 +1078,6 @@ static sig_handler window_resize(int sig); static void end_in_sig_handler(int sig); static bool kill_query(const char *reason); -#ifdef _WIN32 -static BOOL WINAPI ctrl_handler_windows(DWORD fdwCtrlType) -{ - switch (fdwCtrlType) - { - // Handle the CTRL-C signal. - case CTRL_C_EVENT: - case CTRL_BREAK_EVENT: - handle_sigint(SIGINT); - return TRUE; // this means that the signal is handled - case CTRL_CLOSE_EVENT: - case CTRL_LOGOFF_EVENT: - case CTRL_SHUTDOWN_EVENT: - kill_query("Terminate"); - end_in_sig_handler(SIGINT + 1); - aborted= 1; - } - // This means to pass the signal to the next handler. This allows - // my_cgets and the internal ReadConsole call to exit and gracefully - // abort the program. - return FALSE; -} -#endif const char DELIMITER_NAME[]= "delimiter"; const uint DELIMITER_NAME_LEN= sizeof(DELIMITER_NAME) - 1; inline bool is_delimiter_command(char *name, ulong len) @@ -1234,12 +1210,11 @@ int main(int argc,char *argv[]) if (!status.batch) ignore_errors=1; // Don't abort monitor -#ifndef _WIN32 - signal(SIGINT, handle_sigint); // Catch SIGINT to clean up + if (opt_sigint_ignore) + signal(SIGINT, SIG_IGN); + else + signal(SIGINT, handle_sigint); // Catch SIGINT to clean up signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up -#else - SetConsoleCtrlHandler(ctrl_handler_windows, TRUE); -#endif #if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL) /* Readline will call this if it installs a handler */ @@ -1471,9 +1446,6 @@ bool kill_query(const char *reason) */ sig_handler handle_sigint(int sig) { - if (opt_sigint_ignore) - return; - /* On Unix only, if no query is being executed just clear the prompt, don't exit. On Windows we exit. From 2bc940f7c940d792ef71058ed0c44660820bed8c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 20 Jan 2024 11:01:46 +0100 Subject: [PATCH 19/34] disable perfschema in mtr bootstrap should fix numerous failures of main.bootstrap tets --- mysql-test/mysql-test-run.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 789d97278fc..f75f0fe64df 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3076,6 +3076,7 @@ sub mysql_install_db { mtr_add_arg($args, "--core-file"); mtr_add_arg($args, "--console"); mtr_add_arg($args, "--character-set-server=latin1"); + mtr_add_arg($args, "--disable-performance-schema"); if ( $opt_debug ) { From db9fad1562b37b8d362bb48a35ac8d0bd9d00b4c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 21 Jan 2024 23:20:07 +0100 Subject: [PATCH 20/34] cleanup: main.log_tables test --- mysql-test/main/log_tables.result | 97 ++++++++++------ mysql-test/main/log_tables.test | 183 +++++++++++------------------- 2 files changed, 129 insertions(+), 151 deletions(-) diff --git a/mysql-test/main/log_tables.result b/mysql-test/main/log_tables.result index 553b4929bb5..e77de1b13ee 100644 --- a/mysql-test/main/log_tables.result +++ b/mysql-test/main/log_tables.result @@ -1,14 +1,9 @@ SET SQL_MODE=""; -SET @old_general_log_state = @@global.general_log; SET @old_log_output= @@global.log_output; SET @old_slow_query_log= @@global.slow_query_log; SET @old_general_log= @@global.general_log; SET @old_long_query_time= @@session.long_query_time; use mysql; -SET @saved_long_query_time = @@long_query_time; -SET @saved_log_output = @@log_output; -SET @saved_general_log = @@GLOBAL.general_log; -SET @saved_slow_query_log = @@GLOBAL.slow_query_log; truncate table general_log; select * from general_log; event_time user_host thread_id server_id command_type argument @@ -120,6 +115,9 @@ show open tables; Database Table In_use Name_locked SET GLOBAL GENERAL_LOG=ON; SET GLOBAL SLOW_QUERY_LOG=ON; +# +# Bug#23924 general_log truncates queries with character set introducers. +# truncate table mysql.general_log; set names binary; select _koi8r'ÔÅÓÔ' as test; @@ -131,6 +129,9 @@ TIMESTAMP USER_HOST THREAD_ID 1 Query set names binary TIMESTAMP USER_HOST THREAD_ID 1 Query select _koi8r'\xD4\xC5\xD3\xD4' as test TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.general_log set names utf8; +# +# Bug #16905 Log tables: unicode statements are logged incorrectly +# truncate table mysql.general_log; set names utf8; create table bug16905 (s char(15) character set utf8 default 'пуÑто'); @@ -142,6 +143,9 @@ TIMESTAMP USER_HOST THREAD_ID 1 Query create table bug16905 (s char(15) characte TIMESTAMP USER_HOST THREAD_ID 1 Query insert into bug16905 values ('новое') TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.general_log drop table bug16905; +# +# Bug #17600: Invalid data logged into mysql.slow_log +# truncate table mysql.slow_log; set session long_query_time=1; select sleep(2); @@ -150,7 +154,11 @@ sleep(2) select * from mysql.slow_log; start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text thread_id rows_affected TIMESTAMP USER_HOST QUERY_TIME 00:00:00.000000 1 0 mysql 0 0 1 select sleep(2) THREAD_ID 0 -set @@session.long_query_time = @saved_long_query_time; +set @@session.long_query_time = @old_long_query_time; +# +# Bug #18559 log tables cannot change engine, and gets deadlocked when +# dropping w/ log on +# alter table mysql.general_log engine=myisam; ERROR HY000: You cannot 'ALTER' a log table if logging is enabled alter table mysql.slow_log engine=myisam; @@ -232,7 +240,7 @@ TIMESTAMP USER_HOST THREAD_ID 1 Query truncate table mysql.slow_log TIMESTAMP USER_HOST THREAD_ID 1 Query set session long_query_time=1 TIMESTAMP USER_HOST THREAD_ID 1 Query select sleep(2) TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.slow_log -TIMESTAMP USER_HOST THREAD_ID 1 Query set @@session.long_query_time = @saved_long_query_time +TIMESTAMP USER_HOST THREAD_ID 1 Query set @@session.long_query_time = @old_long_query_time TIMESTAMP USER_HOST THREAD_ID 1 Query alter table mysql.general_log engine=myisam TIMESTAMP USER_HOST THREAD_ID 1 Query alter table mysql.slow_log engine=myisam TIMESTAMP USER_HOST THREAD_ID 1 Query drop table mysql.general_log @@ -300,17 +308,20 @@ ON UPDATE CURRENT_TIMESTAMP, set global general_log='ON'; set global slow_query_log='ON'; use test; +# +# Bug #20139 Infinite loop after "FLUSH" and "LOCK tabX, general_log" +# flush tables with read lock; unlock tables; use mysql; lock tables general_log read local, help_category read local; ERROR HY000: You can't use locks with log tables unlock tables; +# +# Bug #17544 Cannot do atomic log rotate and +# Bug #21785 Server crashes after rename of the log table +# SET SESSION long_query_time = 1000; -drop table if exists mysql.renamed_general_log; -drop table if exists mysql.renamed_slow_log; -drop table if exists mysql.general_log_new; -drop table if exists mysql.slow_log_new; use mysql; RENAME TABLE general_log TO renamed_general_log; ERROR HY000: Cannot rename 'general_log'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to 'general_log' @@ -356,13 +367,16 @@ set global slow_query_log='ON'; ERROR 42S02: Table 'mysql.slow_log' doesn't exist RENAME TABLE general_log2 TO general_log; RENAME TABLE slow_log2 TO slow_log; -SET SESSION long_query_time = @saved_long_query_time; +SET SESSION long_query_time = @old_long_query_time; set global general_log='ON'; set global slow_query_log='ON'; flush logs; flush logs; drop table renamed_general_log, renamed_slow_log; use test; +# +# Bug #21966 Strange warnings on repair of the log tables +# use mysql; repair table general_log; Table Op Msg_type Msg_text @@ -380,6 +394,10 @@ slow_log slow_log_new drop table slow_log_new, general_log_new; use test; +# +# Bug#69953 / MDEV-4851 +# Log tables should be modifable on LOG_OUTPUT != TABLE +# SET GLOBAL LOG_OUTPUT = 'FILE'; SET GLOBAL slow_query_log = 1; SET GLOBAL general_log = 1; @@ -388,6 +406,10 @@ ALTER TABLE mysql.general_log ADD COLUMN comment_text TEXT NOT NULL; SET GLOBAL LOG_OUTPUT = 'NONE'; ALTER TABLE mysql.slow_log DROP COLUMN comment_text; ALTER TABLE mysql.general_log DROP COLUMN comment_text; +# +# Bug#27857 (Log tables supplies the wrong value for generating +# AUTO_INCREMENT numbers) +# SET GLOBAL LOG_OUTPUT = 'TABLE'; SET GLOBAL general_log = 0; FLUSH LOGS; @@ -451,16 +473,15 @@ START_TIME USER_HOST QUERY_TIME 00:00:00.000000 1 0 test 0 0 1 SELECT "My own sl START_TIME USER_HOST QUERY_TIME 00:00:00.000000 1 0 test 0 0 1 SELECT "My own slow query", sleep(2) THREAD_ID 0 3 START_TIME USER_HOST QUERY_TIME 00:00:00.000000 1 0 test 0 0 1 SELECT "My own slow query", sleep(2) THREAD_ID 0 4 SET GLOBAL slow_query_log = 0; -SET SESSION long_query_time =@saved_long_query_time; +SET SESSION long_query_time =@old_long_query_time; FLUSH LOGS; ALTER TABLE mysql.slow_log DROP COLUMN seq; ALTER TABLE mysql.slow_log ENGINE = CSV; SET GLOBAL general_log = @old_general_log; SET GLOBAL slow_query_log = @old_slow_query_log; -drop procedure if exists proc25422_truncate_slow; -drop procedure if exists proc25422_truncate_general; -drop procedure if exists proc25422_alter_slow; -drop procedure if exists proc25422_alter_general; +# +# Bug#25422 (Hang with log tables) +# use test// create procedure proc25422_truncate_slow (loops int) begin @@ -485,26 +506,26 @@ end// create procedure proc25422_alter_slow (loops int) begin declare v1 int default 0; +declare old_log_state int default @@global.slow_query_log; declare ER_BAD_LOG_STATEMENT condition for 1575; declare continue handler for ER_BAD_LOG_STATEMENT begin end; while v1 < loops do -set @old_log_state = @@global.slow_query_log; set global slow_query_log = 'OFF'; alter table mysql.slow_log engine = CSV; -set global slow_query_log = @old_log_state; +set global slow_query_log = old_log_state; set v1 = v1 + 1; end while; end// create procedure proc25422_alter_general (loops int) begin declare v1 int default 0; +declare old_log_state int default @@global.general_log; declare ER_BAD_LOG_STATEMENT condition for 1575; declare continue handler for ER_BAD_LOG_STATEMENT begin end; while v1 < loops do -set @old_log_state = @@global.general_log; set global general_log = 'OFF'; alter table mysql.general_log engine = CSV; -set global general_log = @old_log_state; +set global general_log = old_log_state; set v1 = v1 + 1; end while; end// @@ -563,17 +584,19 @@ drop procedure proc25422_truncate_slow; drop procedure proc25422_truncate_general; drop procedure proc25422_alter_slow; drop procedure proc25422_alter_general; +# +# Bug#23044 (Warnings on flush of a log table) +# FLUSH TABLE mysql.general_log; show warnings; Level Code Message FLUSH TABLE mysql.slow_log; show warnings; Level Code Message -DROP TABLE IF EXISTS `db_17876.slow_log_data`; -DROP TABLE IF EXISTS `db_17876.general_log_data`; -DROP PROCEDURE IF EXISTS `db_17876.archiveSlowLog`; -DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`; -DROP DATABASE IF EXISTS `db_17876`; +# +# Bug#17876 (Truncating mysql.slow_log in a SP after using cursor locks the +# thread) +# CREATE DATABASE db_17876; CREATE TABLE `db_17876.slow_log_data` ( `start_time` timestamp(6) default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, @@ -686,6 +709,9 @@ DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`; DROP DATABASE IF EXISTS `db_17876`; SET GLOBAL general_log = @old_general_log; SET GLOBAL slow_query_log = @old_slow_query_log; +# +# Bug#21557 entries in the general query log truncated at 1000 characters. +# select CONNECTION_ID() into @thread_id; truncate table mysql.general_log; set global general_log = on; @@ -902,9 +928,9 @@ Execute select '000 001 002 003 004 005 006 007 008 009010 011 012 013 014 015 0 Query set global general_log = off deallocate prepare long_query; set global general_log = @old_general_log; -DROP TABLE IF EXISTS log_count; -DROP TABLE IF EXISTS slow_log_copy; -DROP TABLE IF EXISTS general_log_copy; +# +# Bug#34306: Can't make copy of log tables when server binary log is enabled +# CREATE TABLE log_count (count BIGINT(21)); SET GLOBAL general_log = ON; SET GLOBAL slow_query_log = ON; @@ -926,9 +952,12 @@ CREATE TABLE general_log_copy SELECT * FROM mysql.general_log; INSERT INTO general_log_copy SELECT * FROM mysql.general_log; INSERT INTO log_count (count) VALUES ((SELECT count(*) FROM mysql.general_log)); DROP TABLE general_log_copy; -SET GLOBAL general_log = @saved_general_log; -SET GLOBAL slow_query_log = @saved_slow_query_log; +SET GLOBAL general_log = @old_general_log; +SET GLOBAL slow_query_log = @old_slow_query_log; DROP TABLE log_count; +# +# Bug #31700: thd->examined_row_count not incremented for 'const' type queries +# SET SESSION long_query_time = 0; SET GLOBAL slow_query_log = ON; FLUSH LOGS; @@ -954,9 +983,10 @@ TIMESTAMP 1 1 SELECT SQL_NO_CACHE 'Bug#31700 - KEY', f1,f2,f3,SLEEP(1.1) FROM t1 TIMESTAMP 1 1 SELECT SQL_NO_CACHE 'Bug#31700 - PK', f1,f2,f3,SLEEP(1.1) FROM t1 WHERE f1=2 DROP TABLE t1; TRUNCATE TABLE mysql.slow_log; +# +# Bug #47924 main.log_tables times out sporadically +# use mysql; -drop table if exists renamed_general_log; -drop table if exists renamed_slow_log; RENAME TABLE general_log TO renamed_general_log; ERROR HY000: Cannot rename 'general_log'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to 'general_log' RENAME TABLE slow_log TO renamed_slow_log; @@ -964,7 +994,6 @@ ERROR HY000: Cannot rename 'slow_log'. When logging enabled, rename to/from log use test; flush tables with read lock; unlock tables; -SET @@session.long_query_time= @old_long_query_time; SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; SET @@global.general_log= @old_general_log; diff --git a/mysql-test/main/log_tables.test b/mysql-test/main/log_tables.test index 9d964b8090b..b54b154cf05 100644 --- a/mysql-test/main/log_tables.test +++ b/mysql-test/main/log_tables.test @@ -1,13 +1,9 @@ # this test needs multithreaded mysqltest -- source include/not_embedded.inc -# -# Basic log tables test -# -# check that CSV engine was compiled in + --source include/have_csv.inc SET SQL_MODE=""; -SET @old_general_log_state = @@global.general_log; SET @old_log_output= @@global.log_output; SET @old_slow_query_log= @@global.slow_query_log; SET @old_general_log= @@global.general_log; @@ -16,16 +12,9 @@ SET @old_long_query_time= @@session.long_query_time; --disable_ps_protocol use mysql; -# Capture initial settings of system variables -# so that we can revert to old state after manipulation for testing -# NOTE: PLEASE USE THESE VALUES TO 'RESET' SYSTEM VARIABLES -# Capturing old values within the tests results in loss of values -# due to people not paying attention to previous tests' changes, captures -# or improper cleanup -SET @saved_long_query_time = @@long_query_time; -SET @saved_log_output = @@log_output; -SET @saved_general_log = @@GLOBAL.general_log; -SET @saved_slow_query_log = @@GLOBAL.slow_query_log; +# +# Basic log tables test +# # # Check that log tables work and we can do basic selects. This also @@ -147,9 +136,9 @@ show open tables; SET GLOBAL GENERAL_LOG=ON; SET GLOBAL SLOW_QUERY_LOG=ON; -# -# Bug#23924 general_log truncates queries with character set introducers. -# +--echo # +--echo # Bug#23924 general_log truncates queries with character set introducers. +--echo # truncate table mysql.general_log; set names binary; select _koi8r'ÔÅÓÔ' as test; @@ -157,9 +146,9 @@ select _koi8r' select * from mysql.general_log; set names utf8; -# -# Bug #16905 Log tables: unicode statements are logged incorrectly -# +--echo # +--echo # Bug #16905 Log tables: unicode statements are logged incorrectly +--echo # truncate table mysql.general_log; set names utf8; @@ -169,21 +158,21 @@ insert into bug16905 values ('новое'); select * from mysql.general_log; drop table bug16905; -# -# Bug #17600: Invalid data logged into mysql.slow_log -# +--echo # +--echo # Bug #17600: Invalid data logged into mysql.slow_log +--echo # truncate table mysql.slow_log; set session long_query_time=1; select sleep(2); --replace_column 1 TIMESTAMP 2 USER_HOST 3 QUERY_TIME 12 THREAD_ID select * from mysql.slow_log; -set @@session.long_query_time = @saved_long_query_time; +set @@session.long_query_time = @old_long_query_time; -# -# Bug #18559 log tables cannot change engine, and gets deadlocked when -# dropping w/ log on -# +--echo # +--echo # Bug #18559 log tables cannot change engine, and gets deadlocked when +--echo # dropping w/ log on +--echo # # check that appropriate error messages are given when one attempts to alter # or drop a log tables, while corresponding logs are enabled @@ -322,9 +311,9 @@ set global general_log='ON'; set global slow_query_log='ON'; use test; -# -# Bug #20139 Infinite loop after "FLUSH" and "LOCK tabX, general_log" -# +--echo # +--echo # Bug #20139 Infinite loop after "FLUSH" and "LOCK tabX, general_log" +--echo # flush tables with read lock; unlock tables; @@ -333,18 +322,12 @@ use mysql; lock tables general_log read local, help_category read local; unlock tables; -# -# Bug #17544 Cannot do atomic log rotate and -# Bug #21785 Server crashes after rename of the log table -# +--echo # +--echo # Bug #17544 Cannot do atomic log rotate and +--echo # Bug #21785 Server crashes after rename of the log table +--echo # SET SESSION long_query_time = 1000; ---disable_warnings -drop table if exists mysql.renamed_general_log; -drop table if exists mysql.renamed_slow_log; -drop table if exists mysql.general_log_new; -drop table if exists mysql.slow_log_new; ---enable_warnings use mysql; # Should result in error @@ -399,7 +382,7 @@ set global slow_query_log='ON'; RENAME TABLE general_log2 TO general_log; RENAME TABLE slow_log2 TO slow_log; -SET SESSION long_query_time = @saved_long_query_time; +SET SESSION long_query_time = @old_long_query_time; # this should work set global general_log='ON'; @@ -427,13 +410,6 @@ use test; # TODO: improve filtering of expected errors in master.err in # mysql-test-run.pl (based on the test name ?), and uncomment this test. -# --disable_warnings -# drop table if exists mysql.bad_general_log; -# drop table if exists mysql.bad_slow_log; -# drop table if exists mysql.general_log_hide; -# drop table if exists mysql.slow_log_hide; -# --enable_warnings -# # create table mysql.bad_general_log (a int) engine= CSV; # create table mysql.bad_slow_log (a int) engine= CSV; # @@ -459,9 +435,9 @@ use test; # drop table mysql.bad_general_log; # drop table mysql.bad_slow_log; -# -# Bug #21966 Strange warnings on repair of the log tables -# +--echo # +--echo # Bug #21966 Strange warnings on repair of the log tables +--echo # use mysql; # check that no warning occurs on repair of the log tables @@ -474,11 +450,10 @@ show tables like "%log%"; drop table slow_log_new, general_log_new; use test; -# -# Bug#69953 / MDEV-4851 -# Log tables should be modifable on LOG_OUTPUT != TABLE -# -# +--echo # +--echo # Bug#69953 / MDEV-4851 +--echo # Log tables should be modifable on LOG_OUTPUT != TABLE +--echo # SET GLOBAL LOG_OUTPUT = 'FILE'; SET GLOBAL slow_query_log = 1; @@ -492,10 +467,10 @@ ALTER TABLE mysql.slow_log DROP COLUMN comment_text; ALTER TABLE mysql.general_log DROP COLUMN comment_text; -# -# Bug#27857 (Log tables supplies the wrong value for generating -# AUTO_INCREMENT numbers) -# +--echo # +--echo # Bug#27857 (Log tables supplies the wrong value for generating +--echo # AUTO_INCREMENT numbers) +--echo # SET GLOBAL LOG_OUTPUT = 'TABLE'; @@ -554,7 +529,7 @@ SELECT "My own slow query", sleep(2); SELECT * FROM mysql.slow_log WHERE seq >= 2 LIMIT 3; SET GLOBAL slow_query_log = 0; -SET SESSION long_query_time =@saved_long_query_time; +SET SESSION long_query_time =@old_long_query_time; FLUSH LOGS; ALTER TABLE mysql.slow_log DROP COLUMN seq; @@ -563,16 +538,9 @@ ALTER TABLE mysql.slow_log ENGINE = CSV; SET GLOBAL general_log = @old_general_log; SET GLOBAL slow_query_log = @old_slow_query_log; -# -# Bug#25422 (Hang with log tables) -# - ---disable_warnings -drop procedure if exists proc25422_truncate_slow; -drop procedure if exists proc25422_truncate_general; -drop procedure if exists proc25422_alter_slow; -drop procedure if exists proc25422_alter_general; ---enable_warnings +--echo # +--echo # Bug#25422 (Hang with log tables) +--echo # delimiter //; @@ -602,14 +570,14 @@ end// create procedure proc25422_alter_slow (loops int) begin declare v1 int default 0; + declare old_log_state int default @@global.slow_query_log; declare ER_BAD_LOG_STATEMENT condition for 1575; declare continue handler for ER_BAD_LOG_STATEMENT begin end; while v1 < loops do - set @old_log_state = @@global.slow_query_log; set global slow_query_log = 'OFF'; alter table mysql.slow_log engine = CSV; - set global slow_query_log = @old_log_state; + set global slow_query_log = old_log_state; set v1 = v1 + 1; end while; end// @@ -617,14 +585,14 @@ end// create procedure proc25422_alter_general (loops int) begin declare v1 int default 0; + declare old_log_state int default @@global.general_log; declare ER_BAD_LOG_STATEMENT condition for 1575; declare continue handler for ER_BAD_LOG_STATEMENT begin end; while v1 < loops do - set @old_log_state = @@global.general_log; set global general_log = 'OFF'; alter table mysql.general_log engine = CSV; - set global general_log = @old_log_state; + set global general_log = old_log_state; set v1 = v1 + 1; end while; end// @@ -713,9 +681,9 @@ drop procedure proc25422_alter_general; --enable_ps_protocol -# -# Bug#23044 (Warnings on flush of a log table) -# +--echo # +--echo # Bug#23044 (Warnings on flush of a log table) +--echo # FLUSH TABLE mysql.general_log; show warnings; @@ -723,18 +691,10 @@ show warnings; FLUSH TABLE mysql.slow_log; show warnings; -# -# Bug#17876 (Truncating mysql.slow_log in a SP after using cursor locks the -# thread) -# - ---disable_warnings -DROP TABLE IF EXISTS `db_17876.slow_log_data`; -DROP TABLE IF EXISTS `db_17876.general_log_data`; -DROP PROCEDURE IF EXISTS `db_17876.archiveSlowLog`; -DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`; -DROP DATABASE IF EXISTS `db_17876`; ---enable_warnings +--echo # +--echo # Bug#17876 (Truncating mysql.slow_log in a SP after using cursor locks the +--echo # thread) +--echo # CREATE DATABASE db_17876; @@ -872,9 +832,9 @@ DROP DATABASE IF EXISTS `db_17876`; SET GLOBAL general_log = @old_general_log; SET GLOBAL slow_query_log = @old_slow_query_log; -# -# Bug#21557 entries in the general query log truncated at 1000 characters. -# +--echo # +--echo # Bug#21557 entries in the general query log truncated at 1000 characters. +--echo # select CONNECTION_ID() into @thread_id; --disable_ps_protocol @@ -992,15 +952,9 @@ select command_type, argument from mysql.general_log where thread_id = @thread_i deallocate prepare long_query; set global general_log = @old_general_log; -# -# Bug#34306: Can't make copy of log tables when server binary log is enabled -# - ---disable_warnings -DROP TABLE IF EXISTS log_count; -DROP TABLE IF EXISTS slow_log_copy; -DROP TABLE IF EXISTS general_log_copy; ---enable_warnings +--echo # +--echo # Bug#34306: Can't make copy of log tables when server binary log is enabled +--echo # CREATE TABLE log_count (count BIGINT(21)); @@ -1030,14 +984,14 @@ INSERT INTO general_log_copy SELECT * FROM mysql.general_log; INSERT INTO log_count (count) VALUES ((SELECT count(*) FROM mysql.general_log)); DROP TABLE general_log_copy; -SET GLOBAL general_log = @saved_general_log; -SET GLOBAL slow_query_log = @saved_slow_query_log; +SET GLOBAL general_log = @old_general_log; +SET GLOBAL slow_query_log = @old_slow_query_log; DROP TABLE log_count; -# -# Bug #31700: thd->examined_row_count not incremented for 'const' type queries -# +--echo # +--echo # Bug #31700: thd->examined_row_count not incremented for 'const' type queries +--echo # SET SESSION long_query_time = 0; SET GLOBAL slow_query_log = ON; @@ -1064,16 +1018,12 @@ DROP TABLE t1; TRUNCATE TABLE mysql.slow_log; -# -# Bug #47924 main.log_tables times out sporadically -# +--echo # +--echo # Bug #47924 main.log_tables times out sporadically +--echo # use mysql; # Should result in error ---disable_warnings -drop table if exists renamed_general_log; -drop table if exists renamed_slow_log; ---enable_warnings --error ER_CANT_RENAME_LOG_TABLE RENAME TABLE general_log TO renamed_general_log; --error ER_CANT_RENAME_LOG_TABLE @@ -1083,7 +1033,6 @@ use test; flush tables with read lock; unlock tables; -SET @@session.long_query_time= @old_long_query_time; SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; From dcb814c44ec28e8cf011047407cc7304e93e466a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 21 Jan 2024 23:28:54 +0100 Subject: [PATCH 21/34] MDEV-11628 mysql.slow_log reports incorrect start time use thd->start_time for the "start_time" column of the slow_log table. "current_time" here refers to the current_time() function return value not to the actual *current* time. also fixes MDEV-33267 User with minimal permissions can intentionally corrupt mysql.slow_log table --- mysql-test/main/log_tables.result | 28 ++++++++++++++++++++++++++++ mysql-test/main/log_tables.test | 18 ++++++++++++++++++ sql/log.cc | 2 +- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/log_tables.result b/mysql-test/main/log_tables.result index e77de1b13ee..5c628458e7a 100644 --- a/mysql-test/main/log_tables.result +++ b/mysql-test/main/log_tables.result @@ -994,6 +994,34 @@ ERROR HY000: Cannot rename 'slow_log'. When logging enabled, rename to/from log use test; flush tables with read lock; unlock tables; +# +# MDEV-33267 User with minimal permissions can intentionally corrupt mysql.slow_log table +# +truncate mysql.slow_log; +set global log_output= 'TABLE'; +create user u@localhost; +set slow_query_log=on, long_query_time=0.1; +select 'before evil-doing', sleep(0.2); +before evil-doing sleep(0.2) +before evil-doing 0 +connect con1,localhost,u,,; +set @@timestamp= 2147483647; +set slow_query_log=on, long_query_time=0.1; +select 'evil-doing', sleep(1.1); +evil-doing sleep(1.1) +evil-doing 0 +disconnect con1; +connection default; +select 'after evil-doing', sleep(0.2); +after evil-doing sleep(0.2) +after evil-doing 0 +select distinct sql_text from mysql.slow_log where sql_text like '%evil%'; +sql_text +select 'before evil-doing', sleep(0.2) +select 'evil-doing', sleep(1.1) +select 'after evil-doing', sleep(0.2) +set global log_output=default; +drop user u@localhost; SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; SET @@global.general_log= @old_general_log; diff --git a/mysql-test/main/log_tables.test b/mysql-test/main/log_tables.test index b54b154cf05..1169f2b094c 100644 --- a/mysql-test/main/log_tables.test +++ b/mysql-test/main/log_tables.test @@ -1033,6 +1033,24 @@ use test; flush tables with read lock; unlock tables; +--echo # +--echo # MDEV-33267 User with minimal permissions can intentionally corrupt mysql.slow_log table +--echo # +truncate mysql.slow_log; +set global log_output= 'TABLE'; +create user u@localhost; +set slow_query_log=on, long_query_time=0.1; +select 'before evil-doing', sleep(0.2); +--connect (con1,localhost,u,,) +set @@timestamp= 2147483647; +set slow_query_log=on, long_query_time=0.1; +select 'evil-doing', sleep(1.1); +--disconnect con1 +--connection default +select 'after evil-doing', sleep(0.2); +select distinct sql_text from mysql.slow_log where sql_text like '%evil%'; +set global log_output=default; +drop user u@localhost; SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; diff --git a/sql/log.cc b/sql/log.cc index 75199000b85..32c8ad46321 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1334,7 +1334,7 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, size_t query_length, query_utime= (current_utime - thd->start_utime); lock_utime= (thd->utime_after_lock - thd->start_utime); my_hrtime_t current_time= { hrtime_from_time(thd->start_time) + - thd->start_time_sec_part + query_utime }; + thd->start_time_sec_part }; if (!query || thd->get_command() == COM_STMT_PREPARE) { From 8bb464899f1658522cc9740fdb73120d7190dca0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 22 Jan 2024 18:01:37 +0100 Subject: [PATCH 22/34] cleanup: unused and undefined methods --- sql/field.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/sql/field.h b/sql/field.h index 836de2d1bd6..4a95a6e0556 100644 --- a/sql/field.h +++ b/sql/field.h @@ -4060,9 +4060,6 @@ public: bool compatible_field_size(uint field_metadata, const Relay_log_info *rli, uint16 mflags, int *order_var) const override; uint row_pack_length() const override { return field_length; } - int pack_cmp(const uchar *a,const uchar *b,uint key_length, - bool insert_or_update); - int pack_cmp(const uchar *b,uint key_length,bool insert_or_update); uint packed_col_length(const uchar *to, uint length) override; uint max_packed_col_length(uint max_length) override; uint size_of() const override { return sizeof *this; } From 14d00fdb15b47c7f06768f39d5d8473ed47bdd18 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 22 Jan 2024 18:17:05 +0100 Subject: [PATCH 23/34] cleanup: MY_STRNNCOLLSP_NCHARS_EMULATE_TRIMMED_TRAILING_SPACES no need to use it when both arguments have the same length --- sql/field.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/field.cc b/sql/field.cc index 53dc5f2e15a..9e1e0931ef1 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7562,7 +7562,7 @@ int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr) const a_ptr, field_length, b_ptr, field_length, Field_string::char_length(), - MY_STRNNCOLLSP_NCHARS_EMULATE_TRIMMED_TRAILING_SPACES); + 0); } From a7ee3bc58bc23ad7ac5ced54dc745d0e65bee524 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 22 Jan 2024 18:02:11 +0100 Subject: [PATCH 24/34] MDEV-29954 Unique hash key on column prefix is computed incorrectly use the original, not the truncated, field in the long unique prefix, that is, in the hash(left(field, length)) expression. because MyISAM CHECK/REPAIR in compute_vcols() moves table->field but not prefix fields from keyparts. Also, implement Field_string::cmp_prefix() for prefix comparison of CHAR columns to work. --- mysql-test/main/long_unique_bugs.result | 9 +++++++++ mysql-test/main/long_unique_bugs.test | 8 ++++++++ sql/field.cc | 13 +++++++++++++ sql/field.h | 2 ++ sql/key.cc | 2 +- sql/table.cc | 5 ++--- 6 files changed, 35 insertions(+), 4 deletions(-) diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result index e5c14afd9c4..30ba3d0af9a 100644 --- a/mysql-test/main/long_unique_bugs.result +++ b/mysql-test/main/long_unique_bugs.result @@ -651,5 +651,14 @@ f1 f2 f3 f4 f5 f6 f7 4 00004 0001009089999 netstes psit e drop table t1; # +# MDEV-29954 Unique hash key on column prefix is computed incorrectly +# +create table t1 (c char(10),unique key a using hash (c(1))); +insert into t1 values (0); +check table t1 extended; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; +# # End of 10.5 tests # diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test index 5fed7c72d9a..12367b1deb8 100644 --- a/mysql-test/main/long_unique_bugs.test +++ b/mysql-test/main/long_unique_bugs.test @@ -634,6 +634,14 @@ replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netst select * from t1; drop table t1; +--echo # +--echo # MDEV-29954 Unique hash key on column prefix is computed incorrectly +--echo # +create table t1 (c char(10),unique key a using hash (c(1))); +insert into t1 values (0); +check table t1 extended; +drop table t1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/sql/field.cc b/sql/field.cc index 9e1e0931ef1..fc828dcc86c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7566,6 +7566,19 @@ int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr) const } +int Field_string::cmp_prefix(const uchar *a_ptr, const uchar *b_ptr, + size_t prefix_char_len) const +{ + size_t field_len= table->field[field_index]->field_length; + + return field_charset()->coll->strnncollsp_nchars(field_charset(), + a_ptr, field_len, + b_ptr, field_len, + prefix_char_len, + 0); +} + + void Field_string::sort_string(uchar *to,uint length) { #ifdef DBUG_ASSERT_EXISTS diff --git a/sql/field.h b/sql/field.h index 4a95a6e0556..aeb2ae0d20a 100644 --- a/sql/field.h +++ b/sql/field.h @@ -4038,6 +4038,8 @@ public: String *val_str(String *, String *) override; my_decimal *val_decimal(my_decimal *) override; int cmp(const uchar *,const uchar *) const override; + int cmp_prefix(const uchar *a, const uchar *b, size_t prefix_char_len) const + override; void sort_string(uchar *buff,uint length) override; void update_data_type_statistics(Data_type_statistics *st) const override { diff --git a/sql/key.cc b/sql/key.cc index d801bcc982b..2fa7d7066a4 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -605,7 +605,7 @@ int key_rec_cmp(void *key_p, uchar *first_rec, uchar *second_rec) } /* No null values in the fields - We use the virtual method cmp_max with a max length parameter. + We use the virtual method cmp_prefix with a max length parameter. For most field types this translates into a cmp without max length. The exceptions are the BLOB and VARCHAR field types that take the max length into account. diff --git a/sql/table.cc b/sql/table.cc index a5e33052d3f..f3d186f4d9d 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1272,12 +1272,11 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, if (keypart->key_part_flag & HA_PART_KEY_SEG) { int length= keypart->length/keypart->field->charset()->mbmaxlen; + Field *kpf= table->field[keypart->field->field_index]; list_item= new (mem_root) Item_func_left(thd, - new (mem_root) Item_field(thd, keypart->field), + new (mem_root) Item_field(thd, kpf), new (mem_root) Item_int(thd, length)); list_item->fix_fields(thd, NULL); - keypart->field->vcol_info= - table->field[keypart->field->field_index]->vcol_info; } else list_item= new (mem_root) Item_field(thd, keypart->field); From 7c2f0822223a342d1ec4d8ec12c64291d7379492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 23 Jan 2024 18:38:22 +0200 Subject: [PATCH 25/34] Improve READLINE_V5 detection More in depth check to cover all used readline functions. --- cmake/readline.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/readline.cmake b/cmake/readline.cmake index 9c35d8c7d22..55a2867d2a3 100644 --- a/cmake/readline.cmake +++ b/cmake/readline.cmake @@ -114,6 +114,9 @@ MACRO (MYSQL_FIND_SYSTEM_READLINE) { rl_completion_func_t *func1= (rl_completion_func_t*)0; rl_compentry_func_t *func2= (rl_compentry_func_t*)0; + rl_on_new_line(); + rl_replace_line(\"\", 0); + rl_redisplay(); }" NEW_READLINE_INTERFACE) From 3699a7e1a90e17cfc016518fc4922b94d2dbe6be Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 11 Jan 2024 15:01:00 +1100 Subject: [PATCH 26/34] macos: Fix CMAKE_OSX_ARCHITECTURES when not set When CMAKE_OSX_ARCHITECTURES isn't set we end up with "Packaging as: mariadb-10.4.33-osx10.19-x86_64" on arm64 builders. Instead of implying 64bit is x86, use CMAKE_SYSTEM_PROCESSOR to form the filename. --- cmake/package_name.cmake | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cmake/package_name.cmake b/cmake/package_name.cmake index ce13a446fe6..ab0c1d44de8 100644 --- a/cmake/package_name.cmake +++ b/cmake/package_name.cmake @@ -99,11 +99,7 @@ IF(NOT VERSION) SET(DEFAULT_MACHINE "${CMAKE_OSX_ARCHITECTURES}") ENDIF() ELSE() - IF(64BIT) - SET(DEFAULT_MACHINE "x86_64") - ELSE() - SET(DEFAULT_MACHINE "i386") - ENDIF() + SET(DEFAULT_MACHINE ${CMAKE_SYSTEM_PROCESSOR}) ENDIF() IF(DEFAULT_MACHINE MATCHES "i386") From f738cc9876fee50909a9a5f5740617e95d46cf54 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 24 Nov 2023 13:23:56 +0400 Subject: [PATCH 27/34] MDEV-29095 REGEXP_REPLACE treats empty strings different than REPLACE in ORACLE mode Turning REGEXP_REPLACE into two schema-qualified functions: - mariadb_schema.regexp_replace() - oracle_schema.regexp_replace() Fixing oracle_schema.regexp_replace(subj,pattern,replacement) to treat NULL in "replacement" as an empty string. Adding new classes implementing oracle_schema.regexp_replace(): - Item_func_regexp_replace_oracle - Create_func_regexp_replace_oracle Adding helper methods: - String *Item::val_str_null_to_empty(String *to) - String *Item::val_str_null_to_empty(String *to, bool null_to_empty) and reusing these methods in both Item_func_replace and Item_func_regexp_replace. --- .../compat/oracle/r/func_qualified.result | 79 +++++++++++++++++++ .../oracle/r/func_regexp_replace.result | 34 ++++++++ .../suite/compat/oracle/t/func_qualified.test | 1 + .../compat/oracle/t/func_regexp_replace.test | 26 ++++++ sql/item.h | 13 +++ sql/item_create.cc | 38 ++++++--- sql/item_strfunc.cc | 34 +++----- sql/item_strfunc.h | 40 +++++++++- 8 files changed, 230 insertions(+), 35 deletions(-) create mode 100644 mysql-test/suite/compat/oracle/r/func_regexp_replace.result create mode 100644 mysql-test/suite/compat/oracle/t/func_regexp_replace.test diff --git a/mysql-test/suite/compat/oracle/r/func_qualified.result b/mysql-test/suite/compat/oracle/r/func_qualified.result index f8224b7ce81..4750a625ebd 100644 --- a/mysql-test/suite/compat/oracle/r/func_qualified.result +++ b/mysql-test/suite/compat/oracle/r/func_qualified.result @@ -1772,6 +1772,85 @@ Level Code Message Note 1003 select trim(both ' ' from 'a') AS "oracle_schema.TRIM(BOTH ' ' FROM 'a')" Warnings: Note 1003 select trim(both ' ' from 'a') AS "oracle_schema.TRIM(BOTH ' ' FROM 'a')" +CALL p3('REGEXP_REPLACE(''test'',''t'','''')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT REGEXP_REPLACE('test','t','') +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 +Level Code Message +Note 1003 select regexp_replace('test','t','') AS `REGEXP_REPLACE('test','t','')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REGEXP_REPLACE('test','t','') +errmsg +ERROR: FUNCTION unknown_schema.REGEXP_REPLACE does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REGEXP_REPLACE('test','t','') +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 +Level Code Message +Note 1003 select regexp_replace('test','t','') AS `mariadb_schema.REGEXP_REPLACE('test','t','')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REGEXP_REPLACE('test','t','') +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 +Level Code Message +Note 1003 select regexp_replace('test','t','') AS `maxdb_schema.REGEXP_REPLACE('test','t','')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REGEXP_REPLACE('test','t','') +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 +Level Code Message +Note 1003 select oracle_schema.regexp_replace('test','t','') AS `oracle_schema.REGEXP_REPLACE('test','t','')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT REGEXP_REPLACE('test','t','') +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 +Level Code Message +Note 1003 select regexp_replace('test','t','') AS "REGEXP_REPLACE('test','t','')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REGEXP_REPLACE('test','t','') +errmsg +ERROR: FUNCTION unknown_schema.REGEXP_REPLACE does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REGEXP_REPLACE('test','t','') +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 +Level Code Message +Note 1003 select mariadb_schema.regexp_replace('test','t','') AS "mariadb_schema.REGEXP_REPLACE('test','t','')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REGEXP_REPLACE('test','t','') +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 +Level Code Message +Note 1003 select mariadb_schema.regexp_replace('test','t','') AS "maxdb_schema.REGEXP_REPLACE('test','t','')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REGEXP_REPLACE('test','t','') +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 +Level Code Message +Note 1003 select regexp_replace('test','t','') AS "oracle_schema.REGEXP_REPLACE('test','t','')" +Warnings: +Note 1003 select regexp_replace('test','t','') AS "oracle_schema.REGEXP_REPLACE('test','t','')" CALL p3('CONCAT_OPERATOR_ORACLE(''a'')'); ---------- sql_mode='' qualifier='' diff --git a/mysql-test/suite/compat/oracle/r/func_regexp_replace.result b/mysql-test/suite/compat/oracle/r/func_regexp_replace.result new file mode 100644 index 00000000000..7d0c5f79611 --- /dev/null +++ b/mysql-test/suite/compat/oracle/r/func_regexp_replace.result @@ -0,0 +1,34 @@ +SET sql_mode=ORACLE; +# +# MDEV-29095 REGEXP_REPLACE treats empty strings different than REPLACE in ORACLE mode +# +CREATE TABLE t1 (replacement VARCHAR(10)); +INSERT INTO t1 VALUES (NULL), (''); +SELECT replacement, REGEXP_REPLACE('abba','a',replacement) FROM t1 ORDER BY replacement; +replacement REGEXP_REPLACE('abba','a',replacement) +NULL bb + bb +DROP TABLE t1; +SELECT REGEXP_REPLACE('abba','a',null); +REGEXP_REPLACE('abba','a',null) +bb +EXPLAIN EXTENDED SELECT REPLACE('abba','a',null) ; +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 replace('abba','a',NULL) AS "REPLACE('abba','a',null)" +CREATE VIEW v1 AS SELECT REPLACE('abba','a',null) ; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE VIEW "v1" AS select replace('abba','a',NULL) AS "REPLACE('abba','a',null)" latin1 latin1_swedish_ci +SELECT * FROM v1; +REPLACE('abba','a',null) +bb +SET sql_mode=DEFAULT; +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 oracle_schema.replace('abba','a',NULL) AS `REPLACE('abba','a',null)` latin1 latin1_swedish_ci +SELECT * FROM v1; +REPLACE('abba','a',null) +bb +DROP VIEW v1; diff --git a/mysql-test/suite/compat/oracle/t/func_qualified.test b/mysql-test/suite/compat/oracle/t/func_qualified.test index 842015dbbd6..f2c019ec063 100644 --- a/mysql-test/suite/compat/oracle/t/func_qualified.test +++ b/mysql-test/suite/compat/oracle/t/func_qualified.test @@ -165,6 +165,7 @@ CALL p3('TRIM(1,2)'); CALL p3('TRIM(''a'')'); CALL p3('TRIM(BOTH '' '' FROM ''a'')'); +CALL p3('REGEXP_REPLACE(''test'',''t'','''')'); # Deprecated compatibility XXX_ORACLE functions. # These functions are implemented as simple native functions diff --git a/mysql-test/suite/compat/oracle/t/func_regexp_replace.test b/mysql-test/suite/compat/oracle/t/func_regexp_replace.test new file mode 100644 index 00000000000..8841d524c4a --- /dev/null +++ b/mysql-test/suite/compat/oracle/t/func_regexp_replace.test @@ -0,0 +1,26 @@ +SET sql_mode=ORACLE; + +--echo # +--echo # MDEV-29095 REGEXP_REPLACE treats empty strings different than REPLACE in ORACLE mode +--echo # + +#SELECT REGEXP_REPLACE(null,'a','b') ; +#SELECT REGEXP_REPLACE('ab',null,'b') ; +#SELECT REGEXP_REPLACE('ab','a',null) ; +#SELECT REGEXP_REPLACE('ab',null,null) ; + +CREATE TABLE t1 (replacement VARCHAR(10)); +INSERT INTO t1 VALUES (NULL), (''); +SELECT replacement, REGEXP_REPLACE('abba','a',replacement) FROM t1 ORDER BY replacement; +DROP TABLE t1; + +SELECT REGEXP_REPLACE('abba','a',null); +EXPLAIN EXTENDED SELECT REPLACE('abba','a',null) ; + +CREATE VIEW v1 AS SELECT REPLACE('abba','a',null) ; +SHOW CREATE VIEW v1; +SELECT * FROM v1; +SET sql_mode=DEFAULT; +SHOW CREATE VIEW v1; +SELECT * FROM v1; +DROP VIEW v1; diff --git a/sql/item.h b/sql/item.h index 4e756f81c3f..3d971230413 100644 --- a/sql/item.h +++ b/sql/item.h @@ -904,6 +904,19 @@ public: expressions with subqueries in the ORDER/GROUP clauses. */ String *val_str() { return val_str(&str_value); } + String *val_str_null_to_empty(String *to) + { + String *res= val_str(to); + if (res) + return res; + to->set_charset(collation.collation); + to->length(0); + return to; + } + String *val_str_null_to_empty(String *to, bool null_to_empty) + { + return null_to_empty ? val_str_null_to_empty(to) : val_str(to); + } virtual Item_func *get_item_func() { return NULL; } const MY_LOCALE *locale_from_val_str(); diff --git a/sql/item_create.cc b/sql/item_create.cc index 43c869c05ef..12d7232f5f6 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -2666,7 +2666,10 @@ protected: class Create_func_regexp_replace : public Create_func_arg3 { public: - virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3); + Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) override + { + return new (thd->mem_root) Item_func_regexp_replace(thd, arg1, arg2, arg3); + } static Create_func_regexp_replace s_singleton; @@ -2675,6 +2678,28 @@ protected: virtual ~Create_func_regexp_replace() = default; }; +Create_func_regexp_replace Create_func_regexp_replace::s_singleton; + + +class Create_func_regexp_replace_oracle : public Create_func_arg3 +{ +public: + Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) override + { + return new (thd->mem_root) Item_func_regexp_replace_oracle(thd, arg1, + arg2, arg3); + } + + static Create_func_regexp_replace_oracle s_singleton; + +protected: + Create_func_regexp_replace_oracle() = default; + virtual ~Create_func_regexp_replace_oracle() = default; +}; + +Create_func_regexp_replace_oracle + Create_func_regexp_replace_oracle::s_singleton; + class Create_func_regexp_substr : public Create_func_arg2 { @@ -6464,15 +6489,6 @@ Create_func_regexp_instr::create_2_arg(THD *thd, Item *arg1, Item *arg2) } -Create_func_regexp_replace Create_func_regexp_replace::s_singleton; - -Item* -Create_func_regexp_replace::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) -{ - return new (thd->mem_root) Item_func_regexp_replace(thd, arg1, arg2, arg3); -} - - Create_func_regexp_substr Create_func_regexp_substr::s_singleton; Item* @@ -7616,6 +7632,8 @@ const Native_func_registry func_array_oracle_overrides[] = { { STRING_WITH_LEN("LENGTH") }, BUILDER(Create_func_char_length)}, { { STRING_WITH_LEN("LPAD") }, BUILDER(Create_func_lpad_oracle)}, { { STRING_WITH_LEN("LTRIM") }, BUILDER(Create_func_ltrim_oracle)}, + { { STRING_WITH_LEN("REGEXP_REPLACE") }, + BUILDER(Create_func_regexp_replace_oracle)}, { { STRING_WITH_LEN("RPAD") }, BUILDER(Create_func_rpad_oracle)}, { { STRING_WITH_LEN("RTRIM") }, BUILDER(Create_func_rtrim_oracle)}, diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 0373d2a94a6..697d4fdf2ea 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1149,8 +1149,7 @@ bool Item_func_reverse::fix_length_and_dec() Fix that this works with binary strings when using USE_MB */ -String *Item_func_replace::val_str_internal(String *str, - String *empty_string_for_null) +String *Item_func_replace::val_str_internal(String *str, bool null_to_empty) { DBUG_ASSERT(fixed == 1); String *res,*res2,*res3; @@ -1168,13 +1167,8 @@ String *Item_func_replace::val_str_internal(String *str, res=args[0]->val_str(str); if (args[0]->null_value) goto null; - res2=args[1]->val_str(&tmp_value); - if (args[1]->null_value) - { - if (!empty_string_for_null) - goto null; - res2= empty_string_for_null; - } + if (!(res2= args[1]->val_str_null_to_empty(&tmp_value, null_to_empty))) + goto null; res->set_charset(collation.collation); #ifdef USE_MB @@ -1191,12 +1185,8 @@ String *Item_func_replace::val_str_internal(String *str, if (binary_cmp && (offset=res->strstr(*res2)) < 0) return res; #endif - if (!(res3=args[2]->val_str(&tmp_value2))) - { - if (!empty_string_for_null) - goto null; - res3= empty_string_for_null; - } + if (!(res3= args[2]->val_str_null_to_empty(&tmp_value2, null_to_empty))) + goto null; from_length= res2->length(); to_length= res3->length(); @@ -1279,7 +1269,7 @@ redo: } while ((offset=res->strstr(*res2,(uint) offset)) >= 0); } - if (empty_string_for_null && !res->length()) + if (null_to_empty && !res->length()) goto null; return res; @@ -1385,20 +1375,22 @@ bool Item_func_regexp_replace::append_replacement(String *str, } -String *Item_func_regexp_replace::val_str(String *str) +String *Item_func_regexp_replace::val_str_internal(String *str, + bool null_to_empty) { DBUG_ASSERT(fixed == 1); char buff0[MAX_FIELD_WIDTH]; char buff2[MAX_FIELD_WIDTH]; String tmp0(buff0,sizeof(buff0),&my_charset_bin); String tmp2(buff2,sizeof(buff2),&my_charset_bin); - String *source= args[0]->val_str(&tmp0); - String *replace= args[2]->val_str(&tmp2); + String *source, *replace; LEX_CSTRING src, rpl; int startoffset= 0; - if ((null_value= (args[0]->null_value || args[2]->null_value || - re.recompile(args[1])))) + if ((null_value= + (!(source= args[0]->val_str(&tmp0)) || + !(replace= args[2]->val_str_null_to_empty(&tmp2, null_to_empty)) || + re.recompile(args[1])))) return (String *) 0; if (!(source= re.convert_if_needed(source, &re.subject_converter)) || diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 826c7f784af..4fe7dd03d9c 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -353,12 +353,13 @@ public: class Item_func_replace :public Item_str_func { String tmp_value,tmp_value2; +protected: + String *val_str_internal(String *str, bool null_to_empty); public: Item_func_replace(THD *thd, Item *org, Item *find, Item *replace): Item_str_func(thd, org, find, replace) {} - String *val_str(String *to) { return val_str_internal(to, NULL); }; + String *val_str(String *to) { return val_str_internal(to, false); }; bool fix_length_and_dec(); - String *val_str_internal(String *str, String *empty_string_for_null); const Schema *schema() const { return &mariadb_schema; } void print(String *str, enum_query_type query_type) { @@ -377,7 +378,7 @@ class Item_func_replace_oracle :public Item_func_replace public: Item_func_replace_oracle(THD *thd, Item *org, Item *find, Item *replace): Item_func_replace(thd, org, find, replace) {} - String *val_str(String *to) { return val_str_internal(to, &tmp_emtpystr); }; + String *val_str(String *to) { return val_str_internal(to, true); }; const Schema *schema() const { return &oracle_schema_ref; } void print(String *str, enum_query_type query_type) { @@ -401,10 +402,18 @@ class Item_func_regexp_replace :public Item_str_func bool append_replacement(String *str, const LEX_CSTRING *source, const LEX_CSTRING *replace); +protected: + String *val_str_internal(String *str, bool null_to_empty); public: Item_func_regexp_replace(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {} + const Schema *schema() const { return &mariadb_schema; } + void print(String *str, enum_query_type query_type) + { + print_sql_mode_qualified_name(str, query_type); + print_args_parenthesized(str, query_type); + } void cleanup() { DBUG_ENTER("Item_func_regex::cleanup"); @@ -412,7 +421,10 @@ public: re.cleanup(); DBUG_VOID_RETURN; } - String *val_str(String *str); + String *val_str(String *str) + { + return val_str_internal(str, false); + } bool fix_fields(THD *thd, Item **ref); bool fix_length_and_dec(); const char *func_name() const { return "regexp_replace"; } @@ -420,6 +432,26 @@ public: }; +class Item_func_regexp_replace_oracle: public Item_func_regexp_replace +{ +public: + Item_func_regexp_replace_oracle(THD *thd, Item *a, Item *b, Item *c) + :Item_func_regexp_replace(thd, a, b, c) + {} + const Schema *schema() const { return &oracle_schema_ref; } + bool fix_length_and_dec() + { + bool rc= Item_func_regexp_replace::fix_length_and_dec(); + maybe_null= true; // Empty result is converted to NULL + return rc; + } + String *val_str(String *str) + { + return val_str_internal(str, true); + } +}; + + class Item_func_regexp_substr :public Item_str_func { Regexp_processor_pcre re; From 97fcafb9ece62cd813e2dfe05ba59787229ae04b Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 10 Jan 2024 15:35:25 +0400 Subject: [PATCH 28/34] MDEV-32837 long unique does not work like unique key when using replace write_record() when performing REPLACE has an optimization: - if the unique violation happened in the last unique key, then do UPDATE - otherwise, do DELETE+INSERT This patch changes the way of detecting if this optimization can be applied if the table has long (hash based) unique (i.e. UNIQUE..USING HASH) constraints. Problem: The old condition did not take into account that TABLE_SHARE and TABLE see long uniques differently: - TABLE_SHARE sees as HA_KEY_ALG_LONG_HASH and HA_NOSAME - TABLE sees as usual non-unique indexes So the old condition could erroneously decide that the UPDATE optimization is possible when there are still some unique hash constraints in the table. Fix: - If the current key is a long unique, it now works as follows: UPDATE can be done if the current long unique is the last long unique, and there are no in-engine (normal) uniques. - For in-engine uniques nothing changes, it still works as before: If the current key is an in-engine (normal) unique: UPDATE can be done if it is the last normal unique. --- mysql-test/main/long_unique_bugs.result | 15 +++ mysql-test/main/long_unique_bugs.test | 13 +++ .../long_unique_bugs_no_sp_protocol.result | 95 +++++++++++++++++++ .../main/long_unique_bugs_no_sp_protocol.test | 68 +++++++++++++ sql/sql_insert.cc | 25 ++++- 5 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 mysql-test/main/long_unique_bugs_no_sp_protocol.result create mode 100644 mysql-test/main/long_unique_bugs_no_sp_protocol.test diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result index 30ba3d0af9a..81482e68417 100644 --- a/mysql-test/main/long_unique_bugs.result +++ b/mysql-test/main/long_unique_bugs.result @@ -660,5 +660,20 @@ Table Op Msg_type Msg_text test.t1 check status OK drop table t1; # +# MDEV-32837 long unique does not work like unique key when using replace +# +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +REPLACE INTO t1 VALUES (3,1,1); +SELECT * FROM t1 ORDER BY a; +a b c +2 2 2 +3 1 1 +REPLACE INTO t1 VALUES (3,2,2); +SELECT * FROM t1; +a b c +3 2 2 +DROP TABLE t1; +# # End of 10.5 tests # diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test index 12367b1deb8..2441dfa59e8 100644 --- a/mysql-test/main/long_unique_bugs.test +++ b/mysql-test/main/long_unique_bugs.test @@ -642,6 +642,19 @@ insert into t1 values (0); check table t1 extended; drop table t1; + +--echo # +--echo # MDEV-32837 long unique does not work like unique key when using replace +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +REPLACE INTO t1 VALUES (3,1,1); +SELECT * FROM t1 ORDER BY a; +REPLACE INTO t1 VALUES (3,2,2); +SELECT * FROM t1; +DROP TABLE t1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/long_unique_bugs_no_sp_protocol.result b/mysql-test/main/long_unique_bugs_no_sp_protocol.result new file mode 100644 index 00000000000..0776a130167 --- /dev/null +++ b/mysql-test/main/long_unique_bugs_no_sp_protocol.result @@ -0,0 +1,95 @@ +# +# Start of 10.5 tests +# +# +# MDEV-32837 long unique does not work like unique key when using replace +# +# +# Normal unique key + long unique key +# +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,1,1); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +Variable_name Value +Handler_delete 1 +Handler_read_key 2 +Handler_read_rnd 1 +Handler_write 1 +SELECT * FROM t1 ORDER BY a; +a b c +2 2 2 +3 1 1 +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,2,2); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +Variable_name Value +Handler_delete 1 +Handler_read_key 3 +Handler_read_rnd 2 +Handler_update 1 +Handler_write 1 +SELECT * FROM t1; +a b c +3 2 2 +DROP TABLE t1; +# +# Two long unique keys +# +CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE KEY a (a) USING HASH,UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,1,1); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +Variable_name Value +Handler_read_key 3 +Handler_read_rnd 1 +Handler_update 1 +SELECT * FROM t1 ORDER BY a; +a b c +2 2 2 +3 1 1 +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,2,2); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +Variable_name Value +Handler_delete 1 +Handler_read_key 4 +Handler_read_rnd 2 +Handler_update 1 +SELECT * FROM t1; +a b c +3 2 2 +DROP TABLE t1; +# +# One long unique key +# +CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,1,1); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +Variable_name Value +Handler_read_key 1 +Handler_read_rnd 1 +Handler_update 1 +SELECT * FROM t1 ORDER BY a; +a b c +2 2 2 +3 1 1 +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,2,2); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +Variable_name Value +Handler_read_key 1 +Handler_read_rnd 1 +Handler_update 1 +SELECT * FROM t1; +a b c +3 1 1 +3 2 2 +DROP TABLE t1; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/long_unique_bugs_no_sp_protocol.test b/mysql-test/main/long_unique_bugs_no_sp_protocol.test new file mode 100644 index 00000000000..6bfa6182096 --- /dev/null +++ b/mysql-test/main/long_unique_bugs_no_sp_protocol.test @@ -0,0 +1,68 @@ +if (`SELECT $SP_PROTOCOL > 0`) +{ + --skip Test requires: sp-protocol disabled +} + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-32837 long unique does not work like unique key when using replace +--echo # + +# This test produces different Handler commands in the SHOW STATUS output +# with --sp-protocol. So it's here, in this *.test file with --sp-protocol disabled. + +--echo # +--echo # Normal unique key + long unique key +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,1,1); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +SELECT * FROM t1 ORDER BY a; +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,2,2); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +SELECT * FROM t1; +DROP TABLE t1; + +--echo # +--echo # Two long unique keys +--echo # + +CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE KEY a (a) USING HASH,UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,1,1); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +SELECT * FROM t1 ORDER BY a; +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,2,2); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +SELECT * FROM t1; +DROP TABLE t1; + +--echo # +--echo # One long unique key +--echo # + +CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,1,1); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +SELECT * FROM t1 ORDER BY a; +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,2,2); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +SELECT * FROM t1; +DROP TABLE t1; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index ec9e379768f..b3314e075f0 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1728,7 +1728,7 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, /* Check if there is more uniq keys after field */ -static int last_uniq_key(TABLE *table,uint keynr) +static int last_uniq_key(TABLE *table, const KEY *key, uint keynr) { /* When an underlying storage engine informs that the unique key @@ -1748,7 +1748,7 @@ static int last_uniq_key(TABLE *table,uint keynr) return 0; while (++keynr < table->s->keys) - if (table->key_info[keynr].flags & HA_NOSAME) + if (key[keynr].flags & HA_NOSAME) return 0; return 1; } @@ -2064,8 +2064,27 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink) tables which have ON UPDATE but have no ON DELETE triggers, we just should not expose this fact to users by invoking ON UPDATE triggers. + + Note, TABLE_SHARE and TABLE see long uniques differently: + - TABLE_SHARE sees as HA_KEY_ALG_LONG_HASH and HA_NOSAME + - TABLE sees as usual non-unique indexes */ - if (last_uniq_key(table,key_nr) && + bool is_long_unique= table->s->key_info && + table->s->key_info[key_nr].algorithm == + HA_KEY_ALG_LONG_HASH; + if ((is_long_unique ? + /* + We have a long unique. Test that there are no in-engine + uniques and the current long unique is the last long unique. + */ + !(table->key_info[0].flags & HA_NOSAME) && + last_uniq_key(table, table->s->key_info, key_nr) : + /* + We have a normal key - not a long unique. + Test is the current normal key is unique and + it is the last normal unique. + */ + last_uniq_key(table, table->key_info, key_nr)) && !table->file->referenced_by_foreign_key() && (!table->triggers || !table->triggers->has_delete_triggers())) { From 1070575a890ad5fa52af01297b439073f63846a5 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Mon, 8 Jan 2024 17:50:19 +1100 Subject: [PATCH 29/34] MDEV-33191 spider: fix dbton_id when iterating over links There are two array fields in spider_share with similar names: share->use_sql_dbton_ids that maps from i to the i-th dbton used by share. Thus it should be used only when i iterates over all distinct dbtons used by share. share->sql_dbton_ids that maps from i to the dbton used by the i-th link of the share. Thus it should be used only when i iterates over all links of a share. We correct instances where share->sql_dbton_ids should be used instead of share->use_sql_dbton_ids. --- storage/spider/ha_spider.cc | 4 ++-- .../mysql-test/spider/bugfix/r/mdev_33191.result | 10 ++++++++++ .../spider/mysql-test/spider/bugfix/t/mdev_33191.test | 11 +++++++++++ storage/spider/spd_db_conn.cc | 2 +- storage/spider/spd_db_include.h | 6 ++++++ storage/spider/spd_include.h | 10 ++++++++++ 6 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_33191.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_33191.test diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index 24ee6c5e902..89d86a9ca75 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -8392,7 +8392,7 @@ int ha_spider::ft_read_internal( } } else { #endif - uint dbton_id = share->use_sql_dbton_ids[roop_count]; + uint dbton_id = share->sql_dbton_ids[roop_count]; spider_db_handler *dbton_hdl = dbton_handler[dbton_id]; SPIDER_CONN *conn = conns[roop_count]; pthread_mutex_assert_not_owner(&conn->mta_conn_mutex); @@ -13135,7 +13135,7 @@ int ha_spider::drop_tmp_tables() ) { if (spider_bit_is_set(result_list.tmp_table_created, roop_count)) { - uint dbton_id = share->use_sql_dbton_ids[roop_count]; + uint dbton_id = share->sql_dbton_ids[roop_count]; spider_db_handler *dbton_hdl = dbton_handler[dbton_id]; SPIDER_CONN *conn = conns[roop_count]; pthread_mutex_assert_not_owner(&conn->mta_conn_mutex); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_33191.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_33191.result new file mode 100644 index 00000000000..7ab2e952213 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_33191.result @@ -0,0 +1,10 @@ +INSTALL SONAME 'ha_spider'; +set spider_same_server_link=on; +CREATE TABLE t2(c INT); +CREATE TABLE t1(c INT) ENGINE=Spider COMMENT='socket "$SOCKET", user "root", table "t2 t3"'; +ALTER TABLE t1 ENGINE=Spider; +TRUNCATE TABLE t1; +ERROR 42S02: Table 'test.t3' doesn't exist +drop table t1, t2; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33191.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_33191.test new file mode 100644 index 00000000000..90709127f46 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33191.test @@ -0,0 +1,11 @@ +INSTALL SONAME 'ha_spider'; +set spider_same_server_link=on; +CREATE TABLE t2(c INT); +--let $SOCKET=`SELECT @@global.socket` +evalp CREATE TABLE t1(c INT) ENGINE=Spider COMMENT='socket "$SOCKET", user "root", table "t2 t3"'; +ALTER TABLE t1 ENGINE=Spider; +--error ER_NO_SUCH_TABLE +TRUNCATE TABLE t1; +drop table t1, t2; +--disable_query_log +--source ../../include/clean_up_spider.inc diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index 5b96bfec3cd..52fde02ad0c 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -8215,7 +8215,7 @@ int spider_db_delete_all_rows( spider->conn_link_idx, roop_count, share->link_count, SPIDER_LINK_STATUS_RECOVERY) ) { - uint dbton_id = share->use_sql_dbton_ids[roop_count]; + uint dbton_id = share->sql_dbton_ids[roop_count]; spider_db_handler *dbton_hdl = spider->dbton_handler[dbton_id]; conn = spider->conns[roop_count]; pthread_mutex_assert_not_owner(&conn->mta_conn_mutex); diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index ee6202bf334..5add9fac3e4 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -1836,6 +1836,12 @@ enum spider_db_access_type SPIDER_DB_ACCESS_TYPE_NOSQL }; +/* + Type of singletons based on the type of the remote database. + + All such singletons are stored in the array `spider_dbton', see + `spider_db_init()'. +*/ typedef struct st_spider_dbton { uint dbton_id; diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index f3df1ed8378..0e72ce26696 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -1358,6 +1358,7 @@ typedef struct st_spider_share uint *hs_read_conn_keys_lengths; uint *hs_write_conn_keys_lengths; #endif + /* The index in `spider_dbton' of each data node link. */ uint *sql_dbton_ids; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) uint *hs_dbton_ids; @@ -1447,14 +1448,23 @@ typedef struct st_spider_share uchar dbton_bitmap[spider_bitmap_size(SPIDER_DBTON_SIZE)]; spider_db_share *dbton_share[SPIDER_DBTON_SIZE]; uint use_dbton_count; + /* Actual size is `use_dbton_count'. Values are the indices of item + in `spider_dbton'. */ uint use_dbton_ids[SPIDER_DBTON_SIZE]; + /* Inverse map of `use_dbton_ids'. */ uint dbton_id_to_seq[SPIDER_DBTON_SIZE]; uint use_sql_dbton_count; + /* Actual size is `use_sql_dbton_count'. Values are the indices of + item in `spider_dbton'. */ uint use_sql_dbton_ids[SPIDER_DBTON_SIZE]; + /* Inverse map of `use_sql_dbton_ids'. */ uint sql_dbton_id_to_seq[SPIDER_DBTON_SIZE]; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) uint use_hs_dbton_count; + /* Actual size is `use_hs_dbton_count'. Values are the indices of + item in `spider_dbton'. */ uint use_hs_dbton_ids[SPIDER_DBTON_SIZE]; + /* Inverse map of `use_hs_dbton_ids'. */ uint hs_dbton_id_to_seq[SPIDER_DBTON_SIZE]; #endif From 0f59810b9944929d2b3ffb64f6d197cf9a20e358 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 10 Sep 2021 02:20:16 +0200 Subject: [PATCH 30/34] MDEV-26579 Support minor MSI in Windows installer. With this patch, 4-component MSI version can be used, e.g by setting TINY_VERSION variable in CMake, or by adding a string, e.g MYSQL_VERSION_EXTRA=-2 which sets TINY_VERSION to 2, and also changes the package name. The 4-component MSI versions do not support MSI major upgrades, only minor ones, i.e do not reinstall components, just update existing ones based on versioning rules. To support these rules, add DefaultVersion for the files that won't otherwise be versioned - headers, static and import libraries, pdbs, text - xml, python and perl scripts Also silence WiX warning that MSI won't store hashes for those files anymore. --- cmake/mysql_version.cmake | 4 +++- win/packaging/create_msi.cmake | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/cmake/mysql_version.cmake b/cmake/mysql_version.cmake index cb12bf14b86..2924d6a0096 100644 --- a/cmake/mysql_version.cmake +++ b/cmake/mysql_version.cmake @@ -55,7 +55,9 @@ IF(NOT "${MAJOR_VERSION}" MATCHES "[0-9]+" OR NOT "${PATCH_VERSION}" MATCHES "[0-9]+") MESSAGE(FATAL_ERROR "VERSION file cannot be parsed.") ENDIF() - + IF((NOT TINY_VERSION) AND (EXTRA_VERSION MATCHES "[\\-][0-9]+")) + STRING(REPLACE "-" "" TINY_VERSION "${EXTRA_VERSION}") + ENDIF() SET(VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}${EXTRA_VERSION}") MESSAGE(STATUS "MariaDB ${VERSION}") SET(MYSQL_BASE_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}" CACHE INTERNAL "MySQL Base version") diff --git a/win/packaging/create_msi.cmake b/win/packaging/create_msi.cmake index f992915cd22..1b6f66d0f2c 100644 --- a/win/packaging/create_msi.cmake +++ b/win/packaging/create_msi.cmake @@ -248,6 +248,13 @@ FUNCTION(TRAVERSE_FILES dir topdir file file_comp dir_root) FILE(APPEND ${file} "\n") SET(NONEXEFILES) + FOREACH(v MAJOR_VERSION MINOR_VERSION PATCH_VERSION TINY_VERSION) + IF(NOT ${v}) + MESSAGE(FATAL_ERROR "${v} is not set") + ENDIF() + ENDFOREACH() + SET(default_version "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}.${TINY_VERSION}") + FOREACH(f ${all_files}) IF(NOT IS_DIRECTORY ${f}) FILE(RELATIVE_PATH rel ${topdir} ${f}) @@ -267,6 +274,7 @@ FUNCTION(TRAVERSE_FILES dir topdir file file_comp dir_root) FILE(APPEND ${file} " ${${id}.COMPONENT_CONDITION}\n") ENDIF() FILE(APPEND ${file} " \n${${id}.FILE_EXTRA}") ELSE() @@ -396,7 +404,7 @@ ENDIF() EXECUTE_PROCESS( COMMAND ${LIGHT_EXECUTABLE} -v -ext WixUIExtension -ext WixUtilExtension - -ext WixFirewallExtension -sice:ICE61 ${SILENCE_VCREDIST_MSM_WARNINGS} + -ext WixFirewallExtension -sice:ICE61 -sw1103 ${SILENCE_VCREDIST_MSM_WARNINGS} mysql_server.wixobj extra.wixobj -out ${CPACK_PACKAGE_FILE_NAME}.msi ${EXTRA_LIGHT_ARGS} ) From b62f25c6509c1b3c0a055316403850b0a8015179 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 10 Sep 2021 09:38:40 +0200 Subject: [PATCH 31/34] MDEV-26579 fixup --- cmake/mysql_version.cmake | 8 +++----- win/packaging/create_msi.cmake | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/cmake/mysql_version.cmake b/cmake/mysql_version.cmake index 2924d6a0096..2d4ed95478f 100644 --- a/cmake/mysql_version.cmake +++ b/cmake/mysql_version.cmake @@ -50,13 +50,15 @@ MACRO(GET_MYSQL_VERSION) MYSQL_GET_CONFIG_VALUE("MYSQL_VERSION_EXTRA" EXTRA_VERSION) MYSQL_GET_CONFIG_VALUE("SERVER_MATURITY" SERVER_MATURITY) -IF(NOT "${MAJOR_VERSION}" MATCHES "[0-9]+" OR + IF(NOT "${MAJOR_VERSION}" MATCHES "[0-9]+" OR NOT "${MINOR_VERSION}" MATCHES "[0-9]+" OR NOT "${PATCH_VERSION}" MATCHES "[0-9]+") MESSAGE(FATAL_ERROR "VERSION file cannot be parsed.") ENDIF() IF((NOT TINY_VERSION) AND (EXTRA_VERSION MATCHES "[\\-][0-9]+")) STRING(REPLACE "-" "" TINY_VERSION "${EXTRA_VERSION}") + ELSE() + SET(TINY_VERSION "0") ENDIF() SET(VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}${EXTRA_VERSION}") MESSAGE(STATUS "MariaDB ${VERSION}") @@ -120,10 +122,6 @@ ENDIF() IF(MSVC) # Tiny version is used to identify the build, it can be set with cmake -DTINY_VERSION= # to bzr revno for example (in the CI builds) - IF(NOT TINY_VERSION) - SET(TINY_VERSION "0") - ENDIF() - GET_FILENAME_COMPONENT(MYSQL_CMAKE_SCRIPT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) SET(FILETYPE VFT_APP) diff --git a/win/packaging/create_msi.cmake b/win/packaging/create_msi.cmake index 1b6f66d0f2c..83a8882f823 100644 --- a/win/packaging/create_msi.cmake +++ b/win/packaging/create_msi.cmake @@ -249,8 +249,8 @@ FUNCTION(TRAVERSE_FILES dir topdir file file_comp dir_root) SET(NONEXEFILES) FOREACH(v MAJOR_VERSION MINOR_VERSION PATCH_VERSION TINY_VERSION) - IF(NOT ${v}) - MESSAGE(FATAL_ERROR "${v} is not set") + IF(NOT DEFINED ${v}) + MESSAGE(FATAL_ERROR "${v} is not defined") ENDIF() ENDFOREACH() SET(default_version "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}.${TINY_VERSION}") From e96a05948b98c4e034ad31eef55936d349d141e7 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 26 Jan 2024 10:48:54 +0100 Subject: [PATCH 32/34] update C/C --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index f1a72768d42..9155b19b462 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit f1a72768d4256416e5c0bf01b254c303f6135bd0 +Subproject commit 9155b19b462ac15fc69d0b58ae51370b7523ced5 From 112eb14f7e0611371522f1555af2c74bd3eb3247 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Fri, 26 Jan 2024 10:34:40 -0700 Subject: [PATCH 33/34] MDEV-27850: rpl_seconds_behind_master_spike debug_sync fix A debug_sync signal could remain for the SQL thread that should have begun a wait_for upon seeing a GTID event, but would instead see the old signal and continue on without waiting. This broke an "idle" condition in SHOW SLAVE STATUS which should have automatically negated Seconds_Behind_Master. Instead, because the SQL thread had already processed the GTID event, it set sql_thread_caught_up to false, and thereby calculated the value of Seconds_behind_master, when the test expected 0. This patch fixes this by resetting the debug_sync state before creating a new transaction which sends a GTID event to the replica --- mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test index d96863a14c2..9e73e6678a2 100644 --- a/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test +++ b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test @@ -132,6 +132,7 @@ while (!$caught_up) } sleep 0.1; } +set debug_sync="RESET"; --enable_query_log --connection master From c75905cacbd2e8429dc5abd00835e099227851b2 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Mon, 29 Jan 2024 15:17:57 -0700 Subject: [PATCH 34/34] MDEV-33327: rpl_seconds_behind_master_spike Sensitive to IO Thread Stop Position rpl.rpl_seconds_behind_master_spike uses the DEBUG_SYNC mechanism to count how many format descriptor events (FDEs) have been executed, to attempt to pause on a specific relay log FDE after executing transactions. However, depending on when the IO thread is stopped, it can send an extra FDE before sending the transactions, forcing the test to pause before executing any transactions, resulting in a table not existing, that is attempted to be read for COUNT. This patch fixes this by no longer counting FDEs, but rather by programmatically waiting until the SQL thread has executed the transaction and then automatically activating the DEBUG_SYNC point to trigger at the next relay log FDE. --- .../rpl/r/rpl_seconds_behind_master_spike.result | 8 ++------ .../rpl/t/rpl_seconds_behind_master_spike.test | 9 ++------- sql/slave.cc | 15 +++++++++++++-- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result b/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result index bb71f6c92b0..3234a512d86 100644 --- a/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result +++ b/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result @@ -3,7 +3,8 @@ include/master-slave.inc connection slave; include/stop_slave.inc SET @save_dbug= @@GLOBAL.debug_dbug; -SET @@global.debug_dbug="+d,pause_sql_thread_on_fde,negate_clock_diff_with_master"; +SET @@global.debug_dbug="+d,pause_sql_thread_on_relay_fde_after_trans"; +SET @@global.debug_dbug="+d,negate_clock_diff_with_master"; include/start_slave.inc # Future events must be logged at least 2 seconds after # the slave starts @@ -15,11 +16,6 @@ insert into t1 values (1); # event in its relay log flush logs; connection slave; -# Ignore FDEs that happen before the CREATE/INSERT commands -SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; -SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; -SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; -SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; # On the next FDE, the slave should have the master CREATE/INSERT events SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; select count(*)=1 from t1; diff --git a/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test index 9e73e6678a2..cd6311c5e19 100644 --- a/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test +++ b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test @@ -27,7 +27,8 @@ --connection slave --source include/stop_slave.inc SET @save_dbug= @@GLOBAL.debug_dbug; -SET @@global.debug_dbug="+d,pause_sql_thread_on_fde,negate_clock_diff_with_master"; +SET @@global.debug_dbug="+d,pause_sql_thread_on_relay_fde_after_trans"; +SET @@global.debug_dbug="+d,negate_clock_diff_with_master"; --source include/start_slave.inc --let $sleep_time=2 @@ -46,12 +47,6 @@ insert into t1 values (1); flush logs; --connection slave ---echo # Ignore FDEs that happen before the CREATE/INSERT commands -SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; -SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; -SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; -SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; - --echo # On the next FDE, the slave should have the master CREATE/INSERT events SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; select count(*)=1 from t1; diff --git a/sql/slave.cc b/sql/slave.cc index f4d76e447cd..d37b00f2888 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4301,6 +4301,15 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, { Gtid_log_event *gev= static_cast(ev); +#ifdef ENABLED_DEBUG_SYNC + DBUG_EXECUTE_IF( + "pause_sql_thread_on_relay_fde_after_trans", + { + DBUG_SET("-d,pause_sql_thread_on_relay_fde_after_trans"); + DBUG_SET("+d,pause_sql_thread_on_next_relay_fde"); + }); +#endif + /* For GTID, allocate a new sub_id for the given domain_id. The sub_id must be allocated in increasing order of binlog order. @@ -4451,12 +4460,14 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, #endif /* WITH_WSREP */ #ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF( - "pause_sql_thread_on_fde", - if (ev && typ == FORMAT_DESCRIPTION_EVENT) { + "pause_sql_thread_on_next_relay_fde", + if (ev && typ == FORMAT_DESCRIPTION_EVENT && + ((Format_description_log_event *) ev)->is_relay_log_event()) { DBUG_ASSERT(!debug_sync_set_action( thd, STRING_WITH_LEN( "now SIGNAL paused_on_fde WAIT_FOR sql_thread_continue"))); + DBUG_SET("-d,pause_sql_thread_on_next_relay_fde"); }); #endif