diff --git a/cmake/stack_direction.c b/cmake/stack_direction.c deleted file mode 100644 index 1f7a5d0b135..00000000000 --- a/cmake/stack_direction.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (c) 2009 Sun Microsystems, Inc. - Use is subject to license terms. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ - -/* Check stack direction (0-down, 1-up) */ -int f(int *a) -{ - int b; - return(&b > a)?1:0; -} -/* - Prevent compiler optimizations by calling function - through pointer. -*/ -volatile int (*ptr_f)(int *) = f; -int main() -{ - int a; - return ptr_f(&a); -} diff --git a/configure.cmake b/configure.cmake index faff9f40115..76f43e992d8 100644 --- a/configure.cmake +++ b/configure.cmake @@ -671,25 +671,11 @@ int main() } " HAVE_PTHREAD_YIELD_ZERO_ARG) -IF(NOT STACK_DIRECTION) - IF(CMAKE_CROSSCOMPILING AND NOT DEFINED CMAKE_CROSSCOMPILING_EMULATOR) - MESSAGE(FATAL_ERROR - "STACK_DIRECTION is not defined. Please specify -DSTACK_DIRECTION=1 " - "or -DSTACK_DIRECTION=-1 when calling cmake.") - ELSE() - TRY_RUN(STACKDIR_RUN_RESULT STACKDIR_COMPILE_RESULT - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/cmake/stack_direction.c - ) - # Test program returns 0 (down) or 1 (up). - # Convert to -1 or 1 - IF(STACKDIR_RUN_RESULT EQUAL 0) - SET(STACK_DIRECTION -1 CACHE INTERNAL "Stack grows direction") - ELSE() - SET(STACK_DIRECTION 1 CACHE INTERNAL "Stack grows direction") - ENDIF() - MESSAGE(STATUS "Checking stack direction : ${STACK_DIRECTION}") - ENDIF() +IF(STACK_DIRECTION) +ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(parisc|hppa)") + SET(STACK_DIRECTION 1 CACHE INTERNAL "Stack grows direction") +ELSE() + SET(STACK_DIRECTION -1 CACHE INTERNAL "Stack grows direction") ENDIF() # diff --git a/debian/rules b/debian/rules index 062ff03e822..96b36239ea1 100755 --- a/debian/rules +++ b/debian/rules @@ -49,16 +49,6 @@ ifeq (32,$(DEB_HOST_ARCH_BITS)) CMAKEFLAGS += -DPLUGIN_ROCKSDB=NO endif -# Cross building requires stack direction instruction -ifneq ($(DEB_BUILD_ARCH),$(DEB_HOST_ARCH)) - ifneq (,$(filter $(DEB_HOST_ARCH_CPU),alpha amd64 arm arm64 i386 ia64 m68k mips64el mipsel powerpc ppc64 ppc64el riscv64 s390x sh4 sparc64)) - CMAKEFLAGS += -DSTACK_DIRECTION=-1 - endif - ifneq (,$(filter $(DEB_HOST_ARCH_CPU),hppa)) - CMAKEFLAGS += -DSTACK_DIRECTION=1 - endif -endif - # Only attempt to build with PMEM on archs that have package libpmem-dev available # See https://packages.debian.org/search?searchon=names&keywords=libpmem-dev ifneq (,$(filter $(DEB_HOST_ARCH),amd64 arm64 ppc64el riscv64)) diff --git a/mysql-test/main/order_by_pack_big.test b/mysql-test/main/order_by_pack_big.test index 5e39d9f2988..ec8e0c12c54 100644 --- a/mysql-test/main/order_by_pack_big.test +++ b/mysql-test/main/order_by_pack_big.test @@ -112,9 +112,12 @@ set sort_buffer_size=262144*10; --source include/analyze-format.inc eval analyze format=json $query; flush status; +# Enable view-protocol after fix MDEV-27871 +--disable_view_protocol --disable_ps2_protocol eval $query; --enable_ps2_protocol +--enable_view_protocol show status like '%sort%'; set sort_buffer_size=default; @@ -126,9 +129,12 @@ set sort_buffer_size=32768; --source include/analyze-format.inc eval analyze format=json $query; flush status; +# Enable view-protocol after fix MDEV-27871 +--disable_view_protocol --disable_ps2_protocol eval $query; --enable_ps2_protocol +--enable_view_protocol show status like '%sort%'; set sort_buffer_size=default; diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result index 74734a9b7ed..4e93973782f 100644 --- a/mysql-test/main/sp.result +++ b/mysql-test/main/sp.result @@ -8930,6 +8930,31 @@ CREATE TABLE t1 (a INT); CREATE PROCEDURE p1() SELECT 1 FROM t1 PROCEDURE ANALYSE( 10, (SELECT a FROM t1)); ERROR 42000: PROCEDURE does not support subqueries or stored functions DROP TABLE t1; +# +# MDEV-23902: MariaDB crash on calling function +# +CREATE FUNCTION f2 () RETURNS VARCHAR(1) +BEGIN +DECLARE rec1 ROW TYPE OF v1; +SELECT z INTO rec1 FROM v1; +RETURN 1; +END| +CREATE FUNCTION f1 () RETURNS VARCHAR(1) RETURN f2() ; +CREATE FUNCTION f3 () RETURNS VARCHAR(1) RETURN f_not_exist(); +CREATE VIEW v1 AS SELECT f3() z; +SELECT f1(); +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +# Check that crash doen't happen in case f3 completes with success. +DROP FUNCTION f3; +CREATE FUNCTION f3 () RETURNS VARCHAR(1) RETURN '!'; +SELECT f1(); +f1() +1 +# Clean up +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP FUNCTION f3; +DROP VIEW v1; # End of 10.4 tests # # diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test index 6950fbddd65..cc244a20014 100644 --- a/mysql-test/main/sp.test +++ b/mysql-test/main/sp.test @@ -10534,6 +10534,38 @@ CREATE PROCEDURE p1() SELECT 1 FROM t1 PROCEDURE ANALYSE( 10, (SELECT a FROM t1) DROP TABLE t1; +--echo # +--echo # MDEV-23902: MariaDB crash on calling function +--echo # + +--delimiter | +CREATE FUNCTION f2 () RETURNS VARCHAR(1) +BEGIN + DECLARE rec1 ROW TYPE OF v1; + SELECT z INTO rec1 FROM v1; + RETURN 1; +END| +--delimiter ; + +CREATE FUNCTION f1 () RETURNS VARCHAR(1) RETURN f2() ; +CREATE FUNCTION f3 () RETURNS VARCHAR(1) RETURN f_not_exist(); +CREATE VIEW v1 AS SELECT f3() z; + +--error ER_VIEW_INVALID +SELECT f1(); + +--echo # Check that crash doen't happen in case f3 completes with success. +DROP FUNCTION f3; +CREATE FUNCTION f3 () RETURNS VARCHAR(1) RETURN '!'; + +SELECT f1(); + +--echo # Clean up +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP FUNCTION f3; +DROP VIEW v1; + --echo # End of 10.4 tests --echo # diff --git a/mysql-test/suite/gcol/r/innodb_virtual_purge.result b/mysql-test/suite/gcol/r/innodb_virtual_purge.result index 48a2d313382..1fcbd05f354 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_purge.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_purge.result @@ -159,4 +159,18 @@ UNIQUE(pk), KEY(e) ) ENGINE=InnoDB; DROP TABLE t1, t2; +# +# MDEV-30024 InnoDB: tried to purge non-delete-marked record +# of an index on a virtual column prefix +# +CREATE TABLE t(a BINARY(8), b CHAR(8) AS (a) VIRTUAL, KEY(b(4))) +CHARACTER SET utf8 ENGINE=InnoDB; +INSERT INTO t (a) VALUES (''),(''); +UPDATE t SET a = 'x'; +UPDATE t SET a = ''; +SET GLOBAL innodb_max_purge_lag_wait=0; +CHECK TABLE t EXTENDED; +Table Op Msg_type Msg_text +test.t check status OK +DROP TABLE t; SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_purge.test b/mysql-test/suite/gcol/t/innodb_virtual_purge.test index e9e4caf8e07..3db1b8757ff 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_purge.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_purge.test @@ -172,5 +172,19 @@ dec $n; DROP TABLE t1, t2; +--echo # +--echo # MDEV-30024 InnoDB: tried to purge non-delete-marked record +--echo # of an index on a virtual column prefix +--echo # + +CREATE TABLE t(a BINARY(8), b CHAR(8) AS (a) VIRTUAL, KEY(b(4))) +CHARACTER SET utf8 ENGINE=InnoDB; +INSERT INTO t (a) VALUES (''),(''); +UPDATE t SET a = 'x'; +UPDATE t SET a = ''; +SET GLOBAL innodb_max_purge_lag_wait=0; +CHECK TABLE t EXTENDED; +DROP TABLE t; + --source include/wait_until_count_sessions.inc SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/perfschema/r/privilege_table_io.result b/mysql-test/suite/perfschema/r/privilege_table_io.result index 94cc2b33b49..1755c89137d 100644 --- a/mysql-test/suite/perfschema/r/privilege_table_io.result +++ b/mysql-test/suite/perfschema/r/privilege_table_io.result @@ -124,6 +124,8 @@ wait/io/table/sql/handler TABLE mysql db fetch 1 wait/io/table/sql/handler TABLE mysql proxies_priv fetch 1 wait/io/table/sql/handler TABLE mysql proxies_priv fetch 1 wait/io/table/sql/handler TABLE mysql proxies_priv fetch 1 +wait/io/table/sql/handler TABLE mysql proxies_priv fetch 1 +wait/io/table/sql/handler TABLE mysql proxies_priv fetch 1 wait/io/table/sql/handler TABLE mysql roles_mapping fetch 1 wait/io/table/sql/handler TABLE mysql tables_priv fetch 1 wait/io/table/sql/handler TABLE mysql tables_priv fetch 1 diff --git a/mysql-test/suite/roles/acl_statistics.result b/mysql-test/suite/roles/acl_statistics.result index f43f692cc48..172d011400b 100644 --- a/mysql-test/suite/roles/acl_statistics.result +++ b/mysql-test/suite/roles/acl_statistics.result @@ -6,7 +6,7 @@ Acl_function_grants 0 Acl_procedure_grants 0 Acl_package_spec_grants 0 Acl_package_body_grants 0 -Acl_proxy_users 2 +Acl_proxy_users 4 Acl_role_grants 0 Acl_roles 0 Acl_table_grants 1 @@ -25,7 +25,7 @@ PROCEDURE_GRANTS 0 SELECT count(*) PROXY_USERS from mysql.proxies_priv; PROXY_USERS -2 +4 SELECT count(*) ROLE_GRANTS from mysql.roles_mapping; ROLE_GRANTS 0 @@ -71,7 +71,7 @@ Acl_function_grants 3 Acl_procedure_grants 2 Acl_package_spec_grants 0 Acl_package_body_grants 0 -Acl_proxy_users 3 +Acl_proxy_users 5 Acl_role_grants 4 Acl_roles 2 Acl_table_grants 3 @@ -90,7 +90,7 @@ PROCEDURE_GRANTS 2 SELECT count(*) PROXY_USERS from mysql.proxies_priv; PROXY_USERS -3 +5 SELECT count(*) ROLE_GRANTS from mysql.roles_mapping; ROLE_GRANTS 4 diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index cdf3072f090..bc0b6347e86 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -302,6 +302,7 @@ set @had_proxies_priv_table= @@warning_count != 0; -- and for upgrades CREATE TEMPORARY TABLE tmp_proxies_priv LIKE proxies_priv; INSERT INTO tmp_proxies_priv VALUES ('localhost', 'root', '', '', TRUE, '', now()); +REPLACE INTO tmp_proxies_priv SELECT 'localhost',IFNULL(@auth_root_socket, 'root'), '', '', TRUE, '', now() FROM DUAL; INSERT INTO proxies_priv SELECT * FROM tmp_proxies_priv WHERE @had_proxies_priv_table=0; DROP TABLE tmp_proxies_priv; diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mysql_system_tables_data.sql index 28d603cc559..85489e7866e 100644 --- a/scripts/mysql_system_tables_data.sql +++ b/scripts/mysql_system_tables_data.sql @@ -46,9 +46,9 @@ IF @auth_root_socket is not null THEN INSERT INTO global_priv SELECT * FROM tmp_user_nopasswd WHERE @had_user_table=0 AND @auth_root_socket IS NULL; INSERT INTO global_priv SELECT * FROM tmp_user_socket WHERE @had_user_table=0 AND @auth_root_socket IS NOT NULL; -DROP TABLE tmp_user_nopasswd, tmp_user_socket; CREATE TEMPORARY TABLE tmp_proxies_priv LIKE proxies_priv; -INSERT INTO tmp_proxies_priv SELECT @current_hostname, 'root', '', '', TRUE, '', now() FROM DUAL WHERE @current_hostname != 'localhost'; +INSERT INTO tmp_proxies_priv SELECT Host, User, '', '', TRUE, '', now() FROM tmp_user_nopasswd WHERE Host != 'localhost' AND @auth_root_socket IS NULL; +REPLACE INTO tmp_proxies_priv SELECT @current_hostname, IFNULL(@auth_root_socket, 'root'), '', '', TRUE, '', now() FROM DUAL WHERE @current_hostname != 'localhost'; INSERT INTO proxies_priv SELECT * FROM tmp_proxies_priv WHERE @had_proxies_priv_table=0; -DROP TABLE tmp_proxies_priv; +DROP TABLE tmp_user_nopasswd, tmp_user_socket, tmp_proxies_priv; diff --git a/sql/item.cc b/sql/item.cc index 9f964ed019a..bf0426322ed 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2910,7 +2910,7 @@ Item_sp::execute_impl(THD *thd, Item **args, uint arg_count) init_sql_alloc(key_memory_sp_head_call_root, &sp_mem_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(0)); *sp_query_arena= Query_arena(&sp_mem_root, - Query_arena::STMT_INITIALIZED_FOR_SP); + Query_arena::STMT_SP_QUERY_ARGUMENTS); } bool err_status= m_sp->execute_function(thd, args, arg_count, diff --git a/sql/sql_class.h b/sql/sql_class.h index c21fd45ec9f..c945d8d974f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1195,11 +1195,21 @@ public: Prepared statement: STMT_INITIALIZED -> STMT_PREPARED -> STMT_EXECUTED. Stored procedure: STMT_INITIALIZED_FOR_SP -> STMT_EXECUTED. Other statements: STMT_CONVENTIONAL_EXECUTION never changes. + + Special case for stored procedure arguments: STMT_SP_QUERY_ARGUMENTS + This state never changes and used for objects + whose lifetime is whole duration of function call + (sp_rcontext, it's tables and items. etc). Such objects + should be deallocated after every execution of a stored + routine. Caller's arena/memroot can't be used for + placing such objects since memory allocated on caller's + arena not freed until termination of user's session. */ enum enum_state { STMT_INITIALIZED= 0, STMT_INITIALIZED_FOR_SP= 1, STMT_PREPARED= 2, - STMT_CONVENTIONAL_EXECUTION= 3, STMT_EXECUTED= 4, STMT_ERROR= -1 + STMT_CONVENTIONAL_EXECUTION= 3, STMT_EXECUTED= 4, + STMT_SP_QUERY_ARGUMENTS= 5, STMT_ERROR= -1 }; enum_state state; @@ -4473,6 +4483,17 @@ public: inline Query_arena *activate_stmt_arena_if_needed(Query_arena *backup) { + if (state == Query_arena::STMT_SP_QUERY_ARGUMENTS) + /* + Caller uses the arena with state STMT_SP_QUERY_ARGUMENTS for stored + routine's parameters. Lifetime of these objects spans a lifetime of + stored routine call and freed every time the stored routine execution + has been completed. That is the reason why switching to statement's + arena is not performed for arguments, else we would observe increasing + of memory usage while a stored routine be called over and over again. + */ + return NULL; + /* Use the persistent arena if we are in a prepared statement or a stored procedure statement and we have not already changed to use this arena. diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index a4fc32cc5a8..c8913ec9623 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -734,9 +734,16 @@ row_vers_vc_matches_cluster( && (!compare[v_col->v_pos])) { if (ind_field->prefix_len != 0 - && !dfield_is_null(field2) - && field2->len > ind_field->prefix_len) { - field2->len = ind_field->prefix_len; + && !dfield_is_null(field2)) { + field2->len = unsigned( + dtype_get_at_most_n_mbchars( + field2->type.prtype, + field2->type.mbminlen, + field2->type.mbmaxlen, + ind_field->prefix_len, + field2->len, + static_cast + (field2->data))); } /* The index field mismatch */