From f288d42cdbc98460e097f771a4ad015667e355fb Mon Sep 17 00:00:00 2001 From: Weijun Huang Date: Fri, 31 Mar 2023 01:18:24 +0200 Subject: MDEV-29646: sformat('Num [{:20}]', 42) gives incorrect result in view The problem is that sformat does not assign the enough space for the result string. The result string is allocated with the max_length of argument, but the correst max_length should be based on the format string. The patch fixes the problem by using MAX_BLOB_WIDTH to assign length --- mysql-test/main/func_sformat.result | 25 ++++++++++++++++++++++++- mysql-test/main/func_sformat.test | 21 +++++++++++++++++++++ sql/item_strfunc.cc | 2 +- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/func_sformat.result b/mysql-test/main/func_sformat.result index 1809cbad23b..9e8a11677b5 100644 --- a/mysql-test/main/func_sformat.result +++ b/mysql-test/main/func_sformat.result @@ -434,7 +434,7 @@ create table t1 as select sformat(_ucs2 x'003D007B007D003D', _ucs2 x'04420435044 show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `x` varchar(8) CHARACTER SET ucs2 COLLATE ucs2_general_ci DEFAULT NULL + `x` longtext CHARACTER SET ucs2 COLLATE ucs2_general_ci DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; set names latin1; @@ -468,3 +468,26 @@ set names latin1; # # End of 10.7 tests # +# +# Start of 10.8 tests +# +# +# MDEV-29646 sformat('Num [{:20}]', 42) gives incorrect result in view +# +create view v1 as select sformat('Num [{:20}]', 42); +select * from v1; +sformat('Num [{:20}]', 42) +Num [ 42] +drop view v1; +create view v1 as SELECT sformat('Square root of [{:d}] is [{:.20}]', 2, sqrt(2)); +select * from v1; +sformat('Square root of [{:d}] is [{:.20}]', 2, sqrt(2)) +Square root of [2] is [1.4142135623730951455] +drop view v1; +create table t1 (a text, b int, c text); +insert t1 values ('[{} -> {}]', 10, '{}'), ('[{:20} <- {}]', 1, '{:30}'); +select sformat(a,b,c) from t1; +sformat(a,b,c) +[10 -> {}] +[ 1 <- {:30}] +drop table t1; diff --git a/mysql-test/main/func_sformat.test b/mysql-test/main/func_sformat.test index cb7e7c8f1c1..65e4b639179 100644 --- a/mysql-test/main/func_sformat.test +++ b/mysql-test/main/func_sformat.test @@ -253,3 +253,24 @@ set names latin1; echo #; echo # End of 10.7 tests; echo #; + +echo #; +echo # Start of 10.8 tests; +echo #; + +echo #; +echo # MDEV-29646 sformat('Num [{:20}]', 42) gives incorrect result in view; +echo #; + +create view v1 as select sformat('Num [{:20}]', 42); +select * from v1; +drop view v1; + +create view v1 as SELECT sformat('Square root of [{:d}] is [{:.20}]', 2, sqrt(2)); +select * from v1; +drop view v1; + +create table t1 (a text, b int, c text); +insert t1 values ('[{} -> {}]', 10, '{}'), ('[{:20} <- {}]', 1, '{:30}'); +select sformat(a,b,c) from t1; +drop table t1; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 643c3d4cf3e..c6f00db6563 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1348,13 +1348,13 @@ bool Item_func_sformat::fix_length_and_dec() for (uint i=0 ; i < arg_count ; i++) { - char_length+= args[i]->max_char_length(); if (args[i]->result_type() == STRING_RESULT && Type_std_attributes::agg_item_set_converter(c, func_name_cstring(), args+i, 1, flags, 1)) return TRUE; } + char_length= MAX_BLOB_WIDTH; fix_char_length_ulonglong(char_length); return FALSE; } -- cgit v1.2.1 From 7cbb45d1d4b1a5e2d07b1c17c49a5ca797df8991 Mon Sep 17 00:00:00 2001 From: Tuukka Pasanen Date: Wed, 29 Mar 2023 12:28:51 +0300 Subject: MDEV-30952: Reformat Debian post and pre scripts There is several misindentation inside Debian post and pre installation scripts. False indentation with space as indent space should be 2 and indentation with tabs. --- debian/mariadb-common.postinst | 2 +- debian/mariadb-common.postrm | 2 +- debian/mariadb-server-10.6.postinst | 62 ++++++++++++++++----------------- debian/mariadb-server-10.6.postrm | 44 ++++++++++++------------ debian/mariadb-server-10.6.preinst | 68 ++++++++++++++++++------------------- debian/mariadb-server-10.6.prerm | 6 ++-- 6 files changed, 92 insertions(+), 92 deletions(-) diff --git a/debian/mariadb-common.postinst b/debian/mariadb-common.postinst index 12f65bd3d92..53d131a3929 100644 --- a/debian/mariadb-common.postinst +++ b/debian/mariadb-common.postinst @@ -35,7 +35,7 @@ case "$1" in then update-alternatives --install /etc/mysql/my.cnf my.cnf "/etc/mysql/mariadb.cnf" 500 || true fi - ;; + ;; esac #DEBHELPER# diff --git a/debian/mariadb-common.postrm b/debian/mariadb-common.postrm index d0bfa266b7d..2548733a1b9 100644 --- a/debian/mariadb-common.postrm +++ b/debian/mariadb-common.postrm @@ -10,7 +10,7 @@ case "$1" in then /usr/share/mysql-common/configure-symlinks remove mariadb "/etc/mysql/mariadb.cnf" fi - ;; + ;; esac #DEBHELPER# diff --git a/debian/mariadb-server-10.6.postinst b/debian/mariadb-server-10.6.postinst index a259a50ac55..1a83f38dd25 100644 --- a/debian/mariadb-server-10.6.postinst +++ b/debian/mariadb-server-10.6.postinst @@ -100,7 +100,7 @@ this all away. EOF fi fi - rmdir $mysql_upgradedir 2>/dev/null || true + rmdir $mysql_upgradedir 2>/dev/null || true done @@ -113,9 +113,9 @@ EOF # perform mariadb-upgrade, (MDEV-22678). To keep the impact minimal, we # skip innodb and set key-buffer-size to 0 as it isn't reused. if [ -f "$mysql_datadir"/auto.cnf ] && [ -f "$mysql_datadir"/mysql/user.MYD ] && - [ ! lsof -nt "$mysql_datadir"/mysql/user.MYD > /dev/null ] && [ ! -f "$mysql_datadir"/undo_001 ]; then - echo "UPDATE mysql.user SET plugin='unix_socket' WHERE plugin='auth_socket';" | - mariadbd --skip-innodb --key_buffer_size=0 --default-storage-engine=MyISAM --bootstrap 2> /dev/null + [ ! lsof -nt "$mysql_datadir"/mysql/user.MYD > /dev/null ] && [ ! -f "$mysql_datadir"/undo_001 ]; then + echo "UPDATE mysql.user SET plugin='unix_socket' WHERE plugin='auth_socket';" | + mariadbd --skip-innodb --key_buffer_size=0 --default-storage-engine=MyISAM --bootstrap 2> /dev/null fi # Ensure the existence and right permissions for the database and @@ -171,8 +171,8 @@ EOF # Debian: can safely run on upgrades with existing databases set +e bash /usr/bin/mariadb-install-db --rpm --cross-bootstrap --user=mysql \ - --disable-log-bin --skip-test-db 2>&1 | \ - $ERR_LOGGER + --disable-log-bin --skip-test-db 2>&1 | \ + $ERR_LOGGER set -e # On new installations root user can connect via unix_socket. @@ -188,21 +188,21 @@ EOF install -o 0 -g 0 -m 0755 -d $mysql_cfgdir fi if [ ! -e "$dc" ]; then - cat /dev/null > $dc - echo "# THIS FILE IS OBSOLETE. STOP USING IT IF POSSIBLE." >>$dc - echo "# This file exists only for backwards compatibility for" >>$dc - echo "# tools that run '--defaults-file=/etc/mysql/debian.cnf'" >>$dc - echo "# and have root level access to the local filesystem." >>$dc - echo "# With those permissions one can run 'mariadb' directly" >>$dc - echo "# anyway thanks to unix socket authentication and hence" >>$dc - echo "# this file is useless. See package README for more info." >>$dc - echo "[client]" >>$dc - echo "host = localhost" >>$dc - echo "user = root" >>$dc - echo "[mysql_upgrade]" >>$dc - echo "host = localhost" >>$dc - echo "user = root" >>$dc - echo "# THIS FILE WILL BE REMOVED IN A FUTURE DEBIAN RELEASE." >>$dc + cat /dev/null > $dc + echo "# THIS FILE IS OBSOLETE. STOP USING IT IF POSSIBLE." >>$dc + echo "# This file exists only for backwards compatibility for" >>$dc + echo "# tools that run '--defaults-file=/etc/mysql/debian.cnf'" >>$dc + echo "# and have root level access to the local filesystem." >>$dc + echo "# With those permissions one can run 'mariadb' directly" >>$dc + echo "# anyway thanks to unix socket authentication and hence" >>$dc + echo "# this file is useless. See package README for more info." >>$dc + echo "[client]" >>$dc + echo "host = localhost" >>$dc + echo "user = root" >>$dc + echo "[mysql_upgrade]" >>$dc + echo "host = localhost" >>$dc + echo "user = root" >>$dc + echo "# THIS FILE WILL BE REMOVED IN A FUTURE DEBIAN RELEASE." >>$dc fi # Keep it only root-readable, as it always was chown 0:0 $dc @@ -229,10 +229,10 @@ EOF # will think the service is masked echo "# empty placeholder" > /etc/systemd/system/mariadb.service.d/migrated-from-my.cnf-settings.conf - ;; + ;; abort-upgrade|abort-remove|abort-configure) - ;; + ;; triggered) if [ -d /run/systemd/system ]; then @@ -240,12 +240,12 @@ EOF else invoke-rc.d mariadb restart fi - ;; + ;; *) echo "postinst called with unknown argument '$1'" 1>&2 exit 1 - ;; + ;; esac db_stop # in case invoke fails @@ -263,11 +263,11 @@ fi # Modified dh_systemd_start snippet that's not added automatically if [ -d /run/systemd/system ]; then - systemctl --system daemon-reload >/dev/null || true - deb-systemd-invoke start mariadb.service >/dev/null || true -# Modified dh_installinit snippet to only run with sysvinit + systemctl --system daemon-reload >/dev/null || true + deb-systemd-invoke start mariadb.service >/dev/null || true + # Modified dh_installinit snippet to only run with sysvinit elif [ -x "/etc/init.d/mariadb" ]; then - if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then - invoke-rc.d mariadb start || exit $? - fi + if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then + invoke-rc.d mariadb start || exit $? + fi fi diff --git a/debian/mariadb-server-10.6.postrm b/debian/mariadb-server-10.6.postrm index 94ce91db31d..82fffef4eae 100644 --- a/debian/mariadb-server-10.6.postrm +++ b/debian/mariadb-server-10.6.postrm @@ -15,24 +15,24 @@ MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf" # do it himself. No database directories should be removed while the server # is running! Another mariadbd in e.g. a different chroot is fine for us. stop_server() { - # Return immediately if there are no mysqld processes running - # as there is no point in trying to shutdown in that case. - if ! pgrep -x --nslist pid --ns $$ "mysqld|mariadbd" > /dev/null; then return; fi + # Return immediately if there are no mysqld processes running + # as there is no point in trying to shutdown in that case. + if ! pgrep -x --nslist pid --ns $$ "mysqld|mariadbd" > /dev/null; then return; fi - set +e - invoke-rc.d mariadb stop - invoke-rc.d mysql stop # Backwards compatibility - errno=$? - set -e + set +e + invoke-rc.d mariadb stop + invoke-rc.d mysql stop # Backwards compatibility + errno=$? + set -e - # systemctl could emit exit code 100=no init script (fresh install) - if [ "$errno" != 0 -a "$errno" != 100 ]; then - echo "Attempt to stop MariaDB/MySQL server returned exitcode $errno" 1>&2 - echo "There is a MariaDB/MySQL server running, but we failed in our attempts to stop it." 1>&2 - echo "Stop it yourself and try again!" 1>&2 - db_stop - exit 1 - fi + # systemctl could emit exit code 100=no init script (fresh install) + if [ "$errno" != 0 -a "$errno" != 100 ]; then + echo "Attempt to stop MariaDB/MySQL server returned exitcode $errno" 1>&2 + echo "There is a MariaDB/MySQL server running, but we failed in our attempts to stop it." 1>&2 + echo "Stop it yourself and try again!" 1>&2 + db_stop + exit 1 + fi } @@ -42,11 +42,11 @@ case "$1" in stop_server sleep 2 fi - ;; + ;; *) echo "postrm called with unknown argument '$1'" 1>&2 exit 1 - ;; + ;; esac # @@ -75,9 +75,9 @@ if [ "$1" = "purge" ] && [ -f "/var/lib/mysql/debian-$MAJOR_VER.flag" ]; then if [ -d /var/lib/mysql ] then find /var/lib/mysql -mindepth 1 \ - -not -path '*/lost+found/*' -not -name 'lost+found' \ - -not -path '*/lost@002bfound/*' -not -name 'lost@002bfound' \ - -delete + -not -path '*/lost+found/*' -not -name 'lost+found' \ + -not -path '*/lost@002bfound/*' -not -name 'lost@002bfound' \ + -delete # "|| true" still needed as rmdir still exits with non-zero if # /var/lib/mysql is a mount point @@ -93,5 +93,5 @@ fi # Modified dh_systemd_start snippet that's not added automatically if [ -d /run/systemd/system ]; then - systemctl --system daemon-reload >/dev/null || true + systemctl --system daemon-reload >/dev/null || true fi diff --git a/debian/mariadb-server-10.6.preinst b/debian/mariadb-server-10.6.preinst index c865173e29e..c203e6f0ade 100644 --- a/debian/mariadb-server-10.6.preinst +++ b/debian/mariadb-server-10.6.preinst @@ -14,7 +14,7 @@ MAJOR_VER="${DPKG_MAINTSCRIPT_PACKAGE#mariadb-server-}" # Just kill the invalid insserv.conf.d directory without fallback if [ -d "/etc/insserv.conf.d/mariadb/" ]; then - rm -rf "/etc/insserv.conf.d/mariadb/" + rm -rf "/etc/insserv.conf.d/mariadb/" fi if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi @@ -28,25 +28,25 @@ mysql_upgradedir=/var/lib/mysql-upgrade # do it himself. No database directories should be removed while the server # is running! Another mariadbd in e.g. a different chroot is fine for us. stop_server() { - # Return immediately if there are no mysqld processes running on a host - # (leave containerized processes with the same name in other namespaces) - # as there is no point in trying to shutdown in that case. - if ! pgrep -x --nslist pid --ns $$ "mysqld|mariadbd" > /dev/null; then return; fi - - set +e - invoke-rc.d mariadb stop - invoke-rc.d mysql stop # Backwards compatibility - errno=$? - set -e - - # systemctl could emit exit code 100=no init script (fresh install) - if [ "$errno" != 0 -a "$errno" != 100 ]; then - echo "Attempt to stop MariaDB/MySQL server returned exitcode $errno" 1>&2 - echo "There is a MariaDB/MySQL server running, but we failed in our attempts to stop it." 1>&2 - echo "Stop it yourself and try again!" 1>&2 - db_stop - exit 1 - fi + # Return immediately if there are no mysqld processes running on a host + # (leave containerized processes with the same name in other namespaces) + # as there is no point in trying to shutdown in that case. + if ! pgrep -x --nslist pid --ns $$ "mysqld|mariadbd" > /dev/null; then return; fi + + set +e + invoke-rc.d mariadb stop + invoke-rc.d mysql stop # Backwards compatibility + errno=$? + set -e + + # systemctl could emit exit code 100=no init script (fresh install) + if [ "$errno" != 0 -a "$errno" != 100 ]; then + echo "Attempt to stop MariaDB/MySQL server returned exitcode $errno" 1>&2 + echo "There is a MariaDB/MySQL server running, but we failed in our attempts to stop it." 1>&2 + echo "Stop it yourself and try again!" 1>&2 + db_stop + exit 1 + fi } ################################ main() ########################## @@ -112,7 +112,7 @@ then fi if dpkg --compare-versions "$found_version" '>>' "$max_upgradeable_version" \ - && dpkg --compare-versions "$found_version" '<<' "10.0" + && dpkg --compare-versions "$found_version" '<<' "10.0" then downgrade_detected=true fi @@ -171,22 +171,22 @@ fi # creating mysql group if he isn't already there if ! getent group mysql >/dev/null; then - # Adding system group: mysql. - addgroup --system mysql >/dev/null + # Adding system group: mysql. + addgroup --system mysql >/dev/null fi # creating mysql user if he isn't already there if ! getent passwd mysql >/dev/null; then - # Adding system user: mysql. - adduser \ - --system \ - --disabled-login \ - --ingroup mysql \ - --no-create-home \ - --home /nonexistent \ - --gecos "MySQL Server" \ - --shell /bin/false \ - mysql >/dev/null + # Adding system user: mysql. + adduser \ + --system \ + --disabled-login \ + --ingroup mysql \ + --no-create-home \ + --home /nonexistent \ + --gecos "MySQL Server" \ + --shell /bin/false \ + mysql >/dev/null fi # end of NIS tolerance zone @@ -205,7 +205,7 @@ done # creating mysql home directory if [ ! -d $mysql_datadir ] && [ ! -L $mysql_datadir ]; then - # Use mkdir option 'Z' to create with correct SELinux context. + # Use mkdir option 'Z' to create with correct SELinux context. mkdir -Z $mysql_datadir fi diff --git a/debian/mariadb-server-10.6.prerm b/debian/mariadb-server-10.6.prerm index 8fd172da9d2..0325a80c9b6 100644 --- a/debian/mariadb-server-10.6.prerm +++ b/debian/mariadb-server-10.6.prerm @@ -5,8 +5,8 @@ set -e # Modified dh_systemd_start snippet that's not added automatically if [ -d /run/systemd/system ]; then - deb-systemd-invoke stop mariadb.service >/dev/null -# Modified dh_installinit snippet to only run with sysvinit + deb-systemd-invoke stop mariadb.service >/dev/null + # Modified dh_installinit snippet to only run with sysvinit elif [ -x "/etc/init.d/mariadb" ]; then - invoke-rc.d mariadb stop || exit $? + invoke-rc.d mariadb stop || exit $? fi -- cgit v1.2.1 From 8febdfa3428c59e93be6a2d3a437706cd0233e3f Mon Sep 17 00:00:00 2001 From: Tuukka Pasanen Date: Wed, 29 Mar 2023 12:42:12 +0300 Subject: MDEV-30952: Fix shellcheck problems on Debian scripts Commit fixes several ShellCheck found problems in Debian Pre- and Postscripts. Debian script mariadb-server-10.6.postrm contains shellcheck Fixed problems are: https://www.shellcheck.net/wiki/SC2166 -- Prefer [ p ] && [ q ] as [ p -a q... https://www.shellcheck.net/wiki/SC2006 -- Use $(...) notation instead of le... https://www.shellcheck.net/wiki/SC1091 -- Not following: /usr/share/debconf... Debian script mariadb-server-10.6.postinst contains shellcheck Fixed problems are: https://www.shellcheck.net/wiki/SC2129 -- Consider using { cmd1; cmd2; } >>... https://www.shellcheck.net/wiki/SC1091 -- Not following: /usr/share/debconf... https://www.shellcheck.net/wiki/SC1072 -- Expected test to end here (don't ... https://www.shellcheck.net/wiki/SC1073 -- Couldn't parse this test expressi... https://www.shellcheck.net/wiki/SC1009 -- The mentioned syntax error was in... Debian script mariadb-server-10.6.preinst contains shellcheck Fixed problems are: https://www.shellcheck.net/wiki/SC2231 -- Quote expansions in this for loop... https://www.shellcheck.net/wiki/SC2166 -- Prefer [ p ] && [ q ] as [ p -a q... https://www.shellcheck.net/wiki/SC2001 -- See if you can use ${variable//se... https://www.shellcheck.net/wiki/SC1091 -- Not following: /usr/share/debconf... https://www.shellcheck.net/wiki/SC1007 -- Remove space after = if trying to... --- debian/mariadb-server-10.6.postinst | 37 +++++++++++++++++++++---------------- debian/mariadb-server-10.6.postrm | 5 +++-- debian/mariadb-server-10.6.preinst | 9 +++++---- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/debian/mariadb-server-10.6.postinst b/debian/mariadb-server-10.6.postinst index 1a83f38dd25..a994209ce11 100644 --- a/debian/mariadb-server-10.6.postinst +++ b/debian/mariadb-server-10.6.postinst @@ -1,6 +1,7 @@ #!/bin/bash set -e +# shellcheck source=/dev/null . /usr/share/debconf/confmodule # Automatically set version to ease maintenance of this file @@ -112,8 +113,10 @@ EOF # This direct update is needed to enable an authentication mechanism to # perform mariadb-upgrade, (MDEV-22678). To keep the impact minimal, we # skip innodb and set key-buffer-size to 0 as it isn't reused. - if [ -f "$mysql_datadir"/auto.cnf ] && [ -f "$mysql_datadir"/mysql/user.MYD ] && - [ ! lsof -nt "$mysql_datadir"/mysql/user.MYD > /dev/null ] && [ ! -f "$mysql_datadir"/undo_001 ]; then + lsof -nt "$mysql_datadir"/mysql/user.MYD > /dev/null + lsof_rtn_code=$? + if [ -f "$mysql_datadir/auto.cnf" ] && [ -f "$mysql_datadir/mysql/user.MYD" ] && + [ ! ${lsof_rtn_code} ] && [ ! -f "$mysql_datadir/undo_001" ]; then echo "UPDATE mysql.user SET plugin='unix_socket' WHERE plugin='auth_socket';" | mariadbd --skip-innodb --key_buffer_size=0 --default-storage-engine=MyISAM --bootstrap 2> /dev/null fi @@ -189,20 +192,22 @@ EOF fi if [ ! -e "$dc" ]; then cat /dev/null > $dc - echo "# THIS FILE IS OBSOLETE. STOP USING IT IF POSSIBLE." >>$dc - echo "# This file exists only for backwards compatibility for" >>$dc - echo "# tools that run '--defaults-file=/etc/mysql/debian.cnf'" >>$dc - echo "# and have root level access to the local filesystem." >>$dc - echo "# With those permissions one can run 'mariadb' directly" >>$dc - echo "# anyway thanks to unix socket authentication and hence" >>$dc - echo "# this file is useless. See package README for more info." >>$dc - echo "[client]" >>$dc - echo "host = localhost" >>$dc - echo "user = root" >>$dc - echo "[mysql_upgrade]" >>$dc - echo "host = localhost" >>$dc - echo "user = root" >>$dc - echo "# THIS FILE WILL BE REMOVED IN A FUTURE DEBIAN RELEASE." >>$dc + { + echo "# THIS FILE IS OBSOLETE. STOP USING IT IF POSSIBLE."; + echo "# This file exists only for backwards compatibility for"; + echo "# tools that run '--defaults-file=/etc/mysql/debian.cnf'"; + echo "# and have root level access to the local filesystem."; + echo "# With those permissions one can run 'mariadb' directly"; + echo "# anyway thanks to unix socket authentication and hence"; + echo "# this file is useless. See package README for more info."; + echo "[client]"; + echo "host = localhost"; + echo "user = root"; + echo "[mysql_upgrade]"; + echo "host = localhost"; + echo "user = root"; + echo "# THIS FILE WILL BE REMOVED IN A FUTURE DEBIAN RELEASE."; + } >> $dc fi # Keep it only root-readable, as it always was chown 0:0 $dc diff --git a/debian/mariadb-server-10.6.postrm b/debian/mariadb-server-10.6.postrm index 82fffef4eae..0c847f19684 100644 --- a/debian/mariadb-server-10.6.postrm +++ b/debian/mariadb-server-10.6.postrm @@ -1,6 +1,7 @@ #!/bin/bash set -e +# shellcheck source=/dev/null . /usr/share/debconf/confmodule # Automatically set version to ease maintenance of this file @@ -26,7 +27,7 @@ stop_server() { set -e # systemctl could emit exit code 100=no init script (fresh install) - if [ "$errno" != 0 -a "$errno" != 100 ]; then + if [ "$errno" != 0 ] && [ "$errno" != 100 ]; then echo "Attempt to stop MariaDB/MySQL server returned exitcode $errno" 1>&2 echo "There is a MariaDB/MySQL server running, but we failed in our attempts to stop it." 1>&2 echo "Stop it yourself and try again!" 1>&2 @@ -38,7 +39,7 @@ stop_server() { case "$1" in purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) - if [ -n "`$MYADMIN ping 2>/dev/null`" ]; then + if [ -n "$($MYADMIN ping 2>/dev/null)" ]; then stop_server sleep 2 fi diff --git a/debian/mariadb-server-10.6.preinst b/debian/mariadb-server-10.6.preinst index c203e6f0ade..e8f9953da7c 100644 --- a/debian/mariadb-server-10.6.preinst +++ b/debian/mariadb-server-10.6.preinst @@ -7,6 +7,7 @@ # * abort-upgrade # +# shellcheck source=/dev/null . /usr/share/debconf/confmodule # Automatically set version to ease maintenance of this file @@ -40,7 +41,7 @@ stop_server() { set -e # systemctl could emit exit code 100=no init script (fresh install) - if [ "$errno" != 0 -a "$errno" != 100 ]; then + if [ "$errno" != 0 ] && [ "$errno" != 100 ]; then echo "Attempt to stop MariaDB/MySQL server returned exitcode $errno" 1>&2 echo "There is a MariaDB/MySQL server running, but we failed in our attempts to stop it." 1>&2 echo "Stop it yourself and try again!" 1>&2 @@ -57,7 +58,7 @@ max_upgradeable_version=5.7 # Check if a flag file is found that indicates a previous MariaDB or MySQL # version was installed. If multiple flags are found, check which one was # the biggest version number. -for flag in $mysql_datadir/debian-*.flag +for flag in "$mysql_datadir"/debian-*.flag do # The for loop leaves $flag as the query string if there are no results, @@ -92,7 +93,7 @@ done # Downgrade is detected if the flag version is bigger than $this_version # (e.g. 10.1 > 10.0) or the flag version is smaller than 10.0 but bigger # than $max_upgradeable_version. -if [ ! -z "$found_version" ] +if [ -n "$found_version" ] then # MySQL 8.0 in Ubuntu has a bug in packaging and the file is name wrongly @@ -134,7 +135,7 @@ fi # Don't abort dpkg if downgrade is detected (as was done previously). # Instead simply move the old datadir and create a new for this_version. -if [ ! -z "$downgrade_detected" ] +if [ -n "$downgrade_detected" ] then db_input critical "mariadb-server-$MAJOR_VER/old_data_directory_saved" || true db_go -- cgit v1.2.1 From 50cdf0b5ea8aa4b2b3f20ed8285debbff655cab9 Mon Sep 17 00:00:00 2001 From: Tuukka Pasanen Date: Thu, 30 Mar 2023 13:58:54 +0300 Subject: MDEV-30952: Reformat Debian pre- and postscripts if-clauses Debian install scripts if-clauses are not formatted as they should be. This commit formats Debian Pre and Post script if-clauses. --- debian/mariadb-server-10.6.postinst | 74 ++++++++++++++++++++++++++----------- debian/mariadb-server-10.6.postrm | 27 ++++++++++---- debian/mariadb-server-10.6.preinst | 36 ++++++++++++------ debian/mariadb-server-10.6.prerm | 6 ++- 4 files changed, 101 insertions(+), 42 deletions(-) diff --git a/debian/mariadb-server-10.6.postinst b/debian/mariadb-server-10.6.postinst index a994209ce11..eb0423c3bc7 100644 --- a/debian/mariadb-server-10.6.postinst +++ b/debian/mariadb-server-10.6.postinst @@ -7,7 +7,12 @@ set -e # Automatically set version to ease maintenance of this file MAJOR_VER="${DPKG_MAINTSCRIPT_PACKAGE#mariadb-server-}" -if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi +if [ -n "$DEBIAN_SCRIPT_DEBUG" ] +then + set -v -x + DEBIAN_SCRIPT_TRACE=1 +fi + ${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*" 1>&2 } export PATH=$PATH:/sbin:/usr/sbin:/bin:/usr/bin @@ -25,7 +30,9 @@ case "$1" in # and because changed configuration options should take effect immediately. # In case the server wasn't running at all it should be ok if the stop # script fails. I can't tell at this point because of the cleaned /run. - set +e; invoke-rc.d mariadb stop; set -e + set +e + invoke-rc.d mariadb stop + set -e # An existing /etc/init.d/mysql might be on the system if there was a # previous MySQL or MariaDB installation, since /etc/init.d files are @@ -65,21 +72,26 @@ case "$1" in # If the following symlink exists, it is a preserved copy the old data dir # created by the preinst script during a upgrade that would have otherwise # been replaced by an empty mysql dir. This should restore it. - for dir in DATADIR LOGDIR; do + for dir in DATADIR LOGDIR + do - if [ "$dir" = "DATADIR" ]; then + if [ "$dir" = "DATADIR" ] + then targetdir=$mysql_datadir else targetdir=$mysql_logdir fi savelink="$mysql_upgradedir/$dir.link" - if [ -L "$savelink" ]; then + if [ -L "$savelink" ] + then # If the targetdir was a symlink before we upgraded it is supposed # to be either still be present or not existing anymore now. - if [ -L "$targetdir" ]; then + if [ -L "$targetdir" ] + then rm "$savelink" - elif [ ! -d "$targetdir" ]; then + elif [ ! -d "$targetdir" ] + then mv "$savelink" "$targetdir" else # this should never even happen, but just in case... @@ -116,16 +128,26 @@ EOF lsof -nt "$mysql_datadir"/mysql/user.MYD > /dev/null lsof_rtn_code=$? if [ -f "$mysql_datadir/auto.cnf" ] && [ -f "$mysql_datadir/mysql/user.MYD" ] && - [ ! ${lsof_rtn_code} ] && [ ! -f "$mysql_datadir/undo_001" ]; then + [ ! ${lsof_rtn_code} ] && [ ! -f "$mysql_datadir/undo_001" ] + then echo "UPDATE mysql.user SET plugin='unix_socket' WHERE plugin='auth_socket';" | mariadbd --skip-innodb --key_buffer_size=0 --default-storage-engine=MyISAM --bootstrap 2> /dev/null fi # Ensure the existence and right permissions for the database and # log files. Use mkdir option 'Z' to create with correct SELinux context. - if [ ! -d "$mysql_statedir" ] && [ ! -L "$mysql_statedir" ]; then mkdir -Z "$mysql_statedir"; fi - if [ ! -d "$mysql_datadir" ] && [ ! -L "$mysql_datadir" ]; then mkdir -Z "$mysql_datadir" ; fi - if [ ! -d "$mysql_logdir" ] && [ ! -L "$mysql_logdir" ]; then mkdir -Z "$mysql_logdir" ; fi + if [ ! -d "$mysql_statedir" ] && [ ! -L "$mysql_statedir" ] + then + mkdir -Z "$mysql_statedir" + fi + if [ ! -d "$mysql_datadir" ] && [ ! -L "$mysql_datadir" ] + then + mkdir -Z "$mysql_datadir" + fi + if [ ! -d "$mysql_logdir" ] && [ ! -L "$mysql_logdir" ] + then + mkdir -Z "$mysql_logdir" + fi # When creating an ext3 jounal on an already mounted filesystem like e.g. # /var/lib/mysql, you get a .journal file that is not modifiable by chown. # The mysql_statedir must not be writable by the mysql user under any @@ -186,11 +208,13 @@ EOF # --defaults-file option for tools (for the sake of upgrades) # and thus need /etc/mysql/debian.cnf to exist, even if it's empty. # In the long run the goal is to obsolete this file. - dc=$mysql_cfgdir/debian.cnf; - if [ ! -d "$mysql_cfgdir" ]; then + dc="$mysql_cfgdir/debian.cnf" + if [ ! -d "$mysql_cfgdir" ] + then install -o 0 -g 0 -m 0755 -d $mysql_cfgdir fi - if [ ! -e "$dc" ]; then + if [ ! -e "$dc" ] + then cat /dev/null > $dc { echo "# THIS FILE IS OBSOLETE. STOP USING IT IF POSSIBLE."; @@ -220,8 +244,10 @@ EOF # on by default) to work both to disable a default profile, and to keep # any profile installed and maintained by users themselves. profile="/etc/apparmor.d/usr.sbin.mariadbd" - if [ -f "$profile" ] && aa-status --enabled 2>/dev/null; then - if grep -q /usr/sbin/mariadbd "$profile" 2>/dev/null ; then + if [ -f "$profile" ] && aa-status --enabled 2>/dev/null + then + if grep -q /usr/sbin/mariadbd "$profile" 2>/dev/null + then apparmor_parser -r "$profile" || true else echo "/usr/sbin/mariadbd { }" | apparmor_parser --remove 2>/dev/null || true @@ -233,14 +259,14 @@ EOF # Note that file cannot be empty, otherwise systemd version in Ubuntu Bionic # will think the service is masked echo "# empty placeholder" > /etc/systemd/system/mariadb.service.d/migrated-from-my.cnf-settings.conf - ;; abort-upgrade|abort-remove|abort-configure) ;; triggered) - if [ -d /run/systemd/system ]; then + if [ -d /run/systemd/system ] + then systemctl --system daemon-reload else invoke-rc.d mariadb restart @@ -260,19 +286,23 @@ db_stop # in case invoke fails # systemctl. If we upgrade from MySQL mysql.service may be masked, which also # means init.d script is disabled. Unmask mysql service explicitly. # Check first that the command exists, to avoid emitting any warning messages. -if [ -x "$(command -v deb-systemd-helper)" ]; then +if [ -x "$(command -v deb-systemd-helper)" ] +then deb-systemd-helper unmask mysql.service > /dev/null fi #DEBHELPER# # Modified dh_systemd_start snippet that's not added automatically -if [ -d /run/systemd/system ]; then +if [ -d /run/systemd/system ] +then systemctl --system daemon-reload >/dev/null || true deb-systemd-invoke start mariadb.service >/dev/null || true # Modified dh_installinit snippet to only run with sysvinit -elif [ -x "/etc/init.d/mariadb" ]; then - if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then +elif [ -x "/etc/init.d/mariadb" ] +then + if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] + then invoke-rc.d mariadb start || exit $? fi fi diff --git a/debian/mariadb-server-10.6.postrm b/debian/mariadb-server-10.6.postrm index 0c847f19684..41ed3ffe979 100644 --- a/debian/mariadb-server-10.6.postrm +++ b/debian/mariadb-server-10.6.postrm @@ -7,7 +7,12 @@ set -e # Automatically set version to ease maintenance of this file MAJOR_VER="${DPKG_MAINTSCRIPT_PACKAGE#mariadb-server-}" -if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi +if [ -n "$DEBIAN_SCRIPT_DEBUG" ] +then + set -v -x + DEBIAN_SCRIPT_TRACE=1 +fi + ${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*" 1>&2 } MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf" @@ -18,7 +23,10 @@ MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf" stop_server() { # Return immediately if there are no mysqld processes running # as there is no point in trying to shutdown in that case. - if ! pgrep -x --nslist pid --ns $$ "mysqld|mariadbd" > /dev/null; then return; fi + if ! pgrep -x --nslist pid --ns $$ "mysqld|mariadbd" > /dev/null + then + return + fi set +e invoke-rc.d mariadb stop @@ -27,7 +35,8 @@ stop_server() { set -e # systemctl could emit exit code 100=no init script (fresh install) - if [ "$errno" != 0 ] && [ "$errno" != 100 ]; then + if [ "$errno" != 0 ] && [ "$errno" != 100 ] + then echo "Attempt to stop MariaDB/MySQL server returned exitcode $errno" 1>&2 echo "There is a MariaDB/MySQL server running, but we failed in our attempts to stop it." 1>&2 echo "Stop it yourself and try again!" 1>&2 @@ -39,7 +48,8 @@ stop_server() { case "$1" in purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) - if [ -n "$($MYADMIN ping 2>/dev/null)" ]; then + if [ -n "$($MYADMIN ping 2>/dev/null)" ] + then stop_server sleep 2 fi @@ -55,7 +65,8 @@ esac # - Remove the mysql user only after all his owned files are purged. # - Cleanup the initscripts only if this was the last provider of them # -if [ "$1" = "purge" ] && [ -f "/var/lib/mysql/debian-$MAJOR_VER.flag" ]; then +if [ "$1" = "purge" ] && [ -f "/var/lib/mysql/debian-$MAJOR_VER.flag" ] +then # we remove the mysql user only after all his owned files are purged rm -f /var/log/mysql.{log,err}{,.0,.[1234567].gz} rm -rf /var/log/mysql @@ -63,7 +74,8 @@ if [ "$1" = "purge" ] && [ -f "/var/lib/mysql/debian-$MAJOR_VER.flag" ]; then db_input high "mariadb-server-$MAJOR_VER/postrm_remove_databases" || true db_go || true db_get "mariadb-server-$MAJOR_VER/postrm_remove_databases" || true - if [ "$RET" = "true" ]; then + if [ "$RET" = "true" ] + then # never remove the debian.cnf when the databases are still existing # else we ran into big trouble on the next install! rm -f /etc/mysql/debian.cnf @@ -93,6 +105,7 @@ fi #DEBHELPER# # Modified dh_systemd_start snippet that's not added automatically -if [ -d /run/systemd/system ]; then +if [ -d /run/systemd/system ] +then systemctl --system daemon-reload >/dev/null || true fi diff --git a/debian/mariadb-server-10.6.preinst b/debian/mariadb-server-10.6.preinst index e8f9953da7c..9a31b5c636e 100644 --- a/debian/mariadb-server-10.6.preinst +++ b/debian/mariadb-server-10.6.preinst @@ -14,11 +14,16 @@ MAJOR_VER="${DPKG_MAINTSCRIPT_PACKAGE#mariadb-server-}" # Just kill the invalid insserv.conf.d directory without fallback -if [ -d "/etc/insserv.conf.d/mariadb/" ]; then +if [ -d "/etc/insserv.conf.d/mariadb/" ] +then rm -rf "/etc/insserv.conf.d/mariadb/" fi -if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi +if [ -n "$DEBIAN_SCRIPT_DEBUG" ] +then + set -v -x + DEBIAN_SCRIPT_TRACE=1 +fi ${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*" 1>&2 } export PATH=$PATH:/sbin:/usr/sbin:/bin:/usr/bin @@ -32,7 +37,10 @@ stop_server() { # Return immediately if there are no mysqld processes running on a host # (leave containerized processes with the same name in other namespaces) # as there is no point in trying to shutdown in that case. - if ! pgrep -x --nslist pid --ns $$ "mysqld|mariadbd" > /dev/null; then return; fi + if ! pgrep -x --nslist pid --ns $$ "mysqld|mariadbd" > /dev/null + then + return + fi set +e invoke-rc.d mariadb stop @@ -41,7 +49,8 @@ stop_server() { set -e # systemctl could emit exit code 100=no init script (fresh install) - if [ "$errno" != 0 ] && [ "$errno" != 100 ]; then + if [ "$errno" != 0 ] && [ "$errno" != 100 ] + then echo "Attempt to stop MariaDB/MySQL server returned exitcode $errno" 1>&2 echo "There is a MariaDB/MySQL server running, but we failed in our attempts to stop it." 1>&2 echo "Stop it yourself and try again!" 1>&2 @@ -156,7 +165,8 @@ stop_server # If we use NIS then errors should be tolerated. It's up to the # user to ensure that the mysql user is correctly setup. # Beware that there are two ypwhich one of them needs the 2>/dev/null! -if test -n "$(which ypwhich 2>/dev/null)" && ypwhich >/dev/null 2>&1; then +if test -n "$(which ypwhich 2>/dev/null)" && ypwhich >/dev/null 2>&1 +then set +e fi @@ -171,13 +181,15 @@ fi # # creating mysql group if he isn't already there -if ! getent group mysql >/dev/null; then +if ! getent group mysql >/dev/null +then # Adding system group: mysql. addgroup --system mysql >/dev/null fi # creating mysql user if he isn't already there -if ! getent passwd mysql >/dev/null; then +if ! getent passwd mysql >/dev/null +then # Adding system user: mysql. adduser \ --system \ @@ -195,7 +207,8 @@ set -e # if there's a symlink, let's store where it's pointing, because otherwise # it's going to be lost in some situations -for dir in DATADIR LOGDIR; do +for dir in DATADIR LOGDIR +do checkdir=$(eval echo "$"$dir) if [ -L "$checkdir" ]; then # Use mkdir option 'Z' to create with correct SELinux context. @@ -205,7 +218,8 @@ for dir in DATADIR LOGDIR; do done # creating mysql home directory -if [ ! -d $mysql_datadir ] && [ ! -L $mysql_datadir ]; then +if [ ! -d $mysql_datadir ] && [ ! -L $mysql_datadir ] +then # Use mkdir option 'Z' to create with correct SELinux context. mkdir -Z $mysql_datadir fi @@ -213,7 +227,8 @@ fi # As preset blocksize of GNU df is 1024 then available bytes is $df_available_blocks * 1024 # 4096 blocks is then lower than 4 MB df_available_blocks=`LC_ALL=C BLOCKSIZE= df --output=avail "$datadir" | tail -n 1` -if [ "$df_available_blocks" -lt "4096" ]; then +if [ "$df_available_blocks" -lt "4096" ] +then echo "ERROR: There's not enough space in $mysql_datadir/" 1>&2 db_stop exit 1 @@ -232,7 +247,6 @@ find $mysql_datadir -follow -not -group mysql -print0 2>/dev/null \ | xargs -0 --no-run-if-empty chgrp mysql set -e - db_stop #DEBHELPER# diff --git a/debian/mariadb-server-10.6.prerm b/debian/mariadb-server-10.6.prerm index 0325a80c9b6..2701fa5fc36 100644 --- a/debian/mariadb-server-10.6.prerm +++ b/debian/mariadb-server-10.6.prerm @@ -4,9 +4,11 @@ set -e #DEBHELPER# # Modified dh_systemd_start snippet that's not added automatically -if [ -d /run/systemd/system ]; then +if [ -d /run/systemd/system ] +then deb-systemd-invoke stop mariadb.service >/dev/null # Modified dh_installinit snippet to only run with sysvinit -elif [ -x "/etc/init.d/mariadb" ]; then +elif [ -x "/etc/init.d/mariadb" ] +then invoke-rc.d mariadb stop || exit $? fi -- cgit v1.2.1 From 2740b657ced466c9f6945d59b78915ca6000e890 Mon Sep 17 00:00:00 2001 From: Tuukka Pasanen Date: Mon, 8 May 2023 11:35:32 +0300 Subject: MDEV-31216: Make sure that lsof does not fail on install Command lsof can fail on Debian install. Revert logic more like old one to make sure that there is no failing and still does don't boundce on shellcheck. --- debian/mariadb-server-10.6.postinst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/debian/mariadb-server-10.6.postinst b/debian/mariadb-server-10.6.postinst index eb0423c3bc7..b87ce856313 100644 --- a/debian/mariadb-server-10.6.postinst +++ b/debian/mariadb-server-10.6.postinst @@ -125,10 +125,10 @@ EOF # This direct update is needed to enable an authentication mechanism to # perform mariadb-upgrade, (MDEV-22678). To keep the impact minimal, we # skip innodb and set key-buffer-size to 0 as it isn't reused. - lsof -nt "$mysql_datadir"/mysql/user.MYD > /dev/null - lsof_rtn_code=$? - if [ -f "$mysql_datadir/auto.cnf" ] && [ -f "$mysql_datadir/mysql/user.MYD" ] && - [ ! ${lsof_rtn_code} ] && [ ! -f "$mysql_datadir/undo_001" ] + if [ -f "$mysql_datadir/auto.cnf" ] && + [ -f "$mysql_datadir/mysql/user.MYD" ] && + ! lsof -nt "$mysql_datadir"/mysql/user.MYD > /dev/null && + [ ! -f "$mysql_datadir/undo_001" ] then echo "UPDATE mysql.user SET plugin='unix_socket' WHERE plugin='auth_socket';" | mariadbd --skip-innodb --key_buffer_size=0 --default-storage-engine=MyISAM --bootstrap 2> /dev/null -- cgit v1.2.1 From afe44ef2126d74c11407266cf7d0225ac0392e61 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Wed, 10 May 2023 08:45:08 -0400 Subject: bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 017d7bd5ba5..b7bb36d6024 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=6 -MYSQL_VERSION_PATCH=13 +MYSQL_VERSION_PATCH=14 SERVER_MATURITY=stable -- cgit v1.2.1 From 38ed782f555025bd85047974483d1ac28d4213d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 11 May 2023 08:42:28 +0300 Subject: MDEV-30812 fixup: GCC 12.2.0 -Wmaybe-uninitialized best_access_path(): Simplify the logic for computing fanout. This fixes up commit 4329ec5d3b109cb0bcbee151b5800dc7b19d1945 --- sql/sql_select.cc | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 31e3e16b397..b00c7de9cbc 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8531,25 +8531,26 @@ best_access_path(JOIN *join, fanout= hash_join_fanout(join, s, remaining_tables, rnd_records, hj_start_key, &stats_found); join_sel= 1.0; // Don't do the "10% heuristic" + if (stats_found) + goto fanout_computed; } - if (!stats_found) - { - /* - No OPTIMIZER_SWITCH_HASH_JOIN_CARDINALITY or no field statistics - found. - - Take into account if there is non constant constraints used with - earlier tables in the where expression. - If yes, this will set fanout to rnd_records/4. - We estimate that there will be HASH_FANOUT (10%) - hash matches / row. - */ - if (found_constraint && !force_estimate) - rnd_records= use_found_constraint(rnd_records); - fanout= rnd_records; - join_sel= 0.1; - } + /* + No OPTIMIZER_SWITCH_HASH_JOIN_CARDINALITY or no field statistics + found. + + Take into account if there is non constant constraints used with + earlier tables in the where expression. + If yes, this will set fanout to rnd_records/4. + We estimate that there will be HASH_FANOUT (10%) + hash matches / row. + */ + if (found_constraint && !force_estimate) + rnd_records= use_found_constraint(rnd_records); + fanout= rnd_records; + join_sel= 0.1; + + fanout_computed: tmp= s->quick ? s->quick->read_time : s->scan_time(); double cmp_time= (s->records - rnd_records)/TIME_FOR_COMPARE; tmp= COST_ADD(tmp, cmp_time); -- cgit v1.2.1 From 7124911a2c08beeb9b6aebb92eb2b6bedfabe413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 11 May 2023 08:43:00 +0300 Subject: MDEV-31158: Potential hang with ROW_FORMAT=COMPRESSED tables btr_cur_need_opposite_intention(): Check also page_zip_available() so that we will escalate to exclusive index latch when a non-leaf page may have to be split further due to ROW_FORMAT=COMPRESSED page overflow. Tested by: Matthias Leich --- mysql-test/suite/innodb_zip/r/page_size.result | 21 ++++++++++++++++++++ mysql-test/suite/innodb_zip/t/page_size.test | 24 +++++++++++++++++++++++ storage/innobase/btr/btr0cur.cc | 27 +++++++++++++++++--------- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/mysql-test/suite/innodb_zip/r/page_size.result b/mysql-test/suite/innodb_zip/r/page_size.result index 47effe06884..48b954c945b 100644 --- a/mysql-test/suite/innodb_zip/r/page_size.result +++ b/mysql-test/suite/innodb_zip/r/page_size.result @@ -608,4 +608,25 @@ SET GLOBAL innodb_compression_level=0; INSERT INTO t1 VALUES (''); SET GLOBAL innodb_compression_level= @save_innodb_compression_level; DROP TABLE t1; +# +# MDEV-31158 Assertion ...MTR_MEMO_X_LOCKED in btr_attach_half_pages() +# +SET @save_compression_level=@@GLOBAL.innodb_compression_level; +SET GLOBAL innodb_compression_level=0; +CREATE TEMPORARY TABLE t(a SERIAL, prefix VARBINARY(4), pad INT); +INSERT INTO t(prefix, pad) VALUES +(_binary 0xff,160),('',19),(_binary 0x0001,253),(_binary 0x0b11,169), +(_binary 0x0b010001,23),(_binary 0x0b100001,251),(_binary 0x0d,163), +(_binary 0xb3,254),(_binary 0x96,254),(_binary 0xeb,61), +(_binary 0xf231,253),(_binary 0x1db0,253),(_binary 0x0005,101), +(_binary 0x6370,253),(_binary 0x0b12,112),(_binary 0x0b010002,23), +(_binary 0x0b100002,80),(_binary 0x181984,163),(_binary 0x181926,168), +(_binary 0xe1,176),(_binary 0xe2,187),(_binary 0xe6,254),(_binary 0xbb,51), +(_binary 0x1c,248),(_binary 0x8a,94),(_binary 0x14,254); +CREATE TABLE u(a SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, +b VARBINARY(255), KEY(b)) ENGINE=InnoDB +KEY_BLOCK_SIZE=1 ROW_FORMAT=COMPRESSED; +INSERT INTO u SELECT a,CONCAT(prefix,REPEAT(chr(0),pad)) FROM t; +DROP TABLE u, t; +SET GLOBAL innodb_compression_level=@save_compression_level; # End of 10.6 tests diff --git a/mysql-test/suite/innodb_zip/t/page_size.test b/mysql-test/suite/innodb_zip/t/page_size.test index 16d65a139cf..3455ef8ed94 100644 --- a/mysql-test/suite/innodb_zip/t/page_size.test +++ b/mysql-test/suite/innodb_zip/t/page_size.test @@ -888,4 +888,28 @@ INSERT INTO t1 VALUES (''); SET GLOBAL innodb_compression_level= @save_innodb_compression_level; DROP TABLE t1; +--echo # +--echo # MDEV-31158 Assertion ...MTR_MEMO_X_LOCKED in btr_attach_half_pages() +--echo # +--source include/have_innodb.inc + +SET @save_compression_level=@@GLOBAL.innodb_compression_level; +SET GLOBAL innodb_compression_level=0; +CREATE TEMPORARY TABLE t(a SERIAL, prefix VARBINARY(4), pad INT); +INSERT INTO t(prefix, pad) VALUES +(_binary 0xff,160),('',19),(_binary 0x0001,253),(_binary 0x0b11,169), +(_binary 0x0b010001,23),(_binary 0x0b100001,251),(_binary 0x0d,163), +(_binary 0xb3,254),(_binary 0x96,254),(_binary 0xeb,61), +(_binary 0xf231,253),(_binary 0x1db0,253),(_binary 0x0005,101), +(_binary 0x6370,253),(_binary 0x0b12,112),(_binary 0x0b010002,23), +(_binary 0x0b100002,80),(_binary 0x181984,163),(_binary 0x181926,168), +(_binary 0xe1,176),(_binary 0xe2,187),(_binary 0xe6,254),(_binary 0xbb,51), +(_binary 0x1c,248),(_binary 0x8a,94),(_binary 0x14,254); +CREATE TABLE u(a SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, + b VARBINARY(255), KEY(b)) ENGINE=InnoDB + KEY_BLOCK_SIZE=1 ROW_FORMAT=COMPRESSED; +INSERT INTO u SELECT a,CONCAT(prefix,REPEAT(chr(0),pad)) FROM t; +DROP TABLE u, t; +SET GLOBAL innodb_compression_level=@save_compression_level; + --echo # End of 10.6 tests diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 70b0ae4c32c..784e32a11c1 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -748,18 +748,24 @@ btr_cur_will_modify_tree( /** Detects whether the modifying record might need a opposite modification to the intention. -@param page page -@param lock_intention lock intention for the tree operation +@param bpage buffer pool page +@param is_clust whether this is a clustered index +@param lock_intention lock intention for the tree operation @param node_ptr_max_size the maximum size of a node pointer @param compress_limit BTR_CUR_PAGE_COMPRESS_LIMIT(index) -@param rec record (current node_ptr) -@return true if tree modification is needed */ -static bool btr_cur_need_opposite_intention(const page_t *page, +@param rec record (current node_ptr) +@return true if tree modification is needed */ +static bool btr_cur_need_opposite_intention(const buf_page_t &bpage, + bool is_clust, btr_intention_t lock_intention, ulint node_ptr_max_size, ulint compress_limit, const rec_t *rec) { + if (UNIV_LIKELY_NULL(bpage.zip.data) && + !page_zip_available(&bpage.zip, is_clust, node_ptr_max_size, 1)) + return true; + const page_t *const page= bpage.frame; if (lock_intention != BTR_INTENTION_INSERT) { /* We compensate also for btr_cur_compress_recommendation() */ @@ -1342,7 +1348,8 @@ release_tree: !btr_block_get(*index(), btr_page_get_next(block->page.frame), RW_X_LATCH, false, mtr, &err)) goto func_exit; - if (btr_cur_need_opposite_intention(block->page.frame, lock_intention, + if (btr_cur_need_opposite_intention(block->page, index()->is_clust(), + lock_intention, node_ptr_max_size, compress_limit, page_cur.rec)) goto need_opposite_intention; @@ -1398,7 +1405,8 @@ release_tree: default: break; case BTR_MODIFY_TREE: - if (btr_cur_need_opposite_intention(block->page.frame, lock_intention, + if (btr_cur_need_opposite_intention(block->page, index()->is_clust(), + lock_intention, node_ptr_max_size, compress_limit, page_cur.rec)) /* If the rec is the first or last in the page for pessimistic @@ -1948,7 +1956,7 @@ index_locked: break; if (!index->lock.have_x() && - btr_cur_need_opposite_intention(block->page.frame, + btr_cur_need_opposite_intention(block->page, index->is_clust(), lock_intention, node_ptr_max_size, compress_limit, page_cur.rec)) @@ -1995,7 +2003,8 @@ index_locked: ut_ad(latch_mode != BTR_MODIFY_TREE || upper_rw_latch == RW_X_LATCH); if (latch_mode != BTR_MODIFY_TREE); - else if (btr_cur_need_opposite_intention(block->page.frame, lock_intention, + else if (btr_cur_need_opposite_intention(block->page, index->is_clust(), + lock_intention, node_ptr_max_size, compress_limit, page_cur.rec)) { -- cgit v1.2.1