summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-06-02 10:25:11 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2020-06-02 10:25:11 +0300
commit8300f639a14afeb379c224e10dab9d99d31cecbd (patch)
treec67c0a5afc6062b99ec21194a99b81d3633f8c38
parent804761a844906c7f7bd11139a366a5dfc1d8bcd6 (diff)
parent50641db2d11ad8a2228f7938d851e52decb71a9b (diff)
downloadmariadb-git-8300f639a14afeb379c224e10dab9d99d31cecbd.tar.gz
Merge 10.2 into 10.3
-rw-r--r--CMakeLists.txt3
-rw-r--r--cmake/FindBISON.cmake8
-rw-r--r--mysql-test/suite/roles/set_default_role_for.result4
-rw-r--r--mysql-test/suite/roles/set_default_role_invalid.result87
-rw-r--r--mysql-test/suite/roles/set_default_role_invalid.test107
-rw-r--r--mysql-test/suite/roles/set_role-recursive.result2
-rw-r--r--sql/item_xmlfunc.cc3
-rw-r--r--sql/set_var.cc16
-rw-r--r--sql/set_var.h3
-rw-r--r--sql/sql_acl.cc170
-rw-r--r--sql/sql_acl.h5
-rw-r--r--sql/sql_statistics.cc306
-rw-r--r--sql/sql_statistics.h1
-rw-r--r--sql/table.cc4
-rw-r--r--sql/table.h91
-rw-r--r--storage/connect/CMakeLists.txt2
-rw-r--r--storage/innobase/btr/btr0cur.cc2
-rw-r--r--storage/innobase/buf/buf0buf.cc2
-rw-r--r--storage/innobase/buf/buf0flu.cc6
-rw-r--r--storage/innobase/buf/buf0lru.cc21
-rw-r--r--storage/innobase/handler/ha_innodb.cc2
-rw-r--r--storage/innobase/include/que0que.h12
-rw-r--r--storage/innobase/include/que0que.ic15
-rw-r--r--storage/innobase/include/trx0roll.h11
-rw-r--r--storage/innobase/row/row0umod.cc2
-rw-r--r--storage/innobase/row/row0upd.cc3
-rw-r--r--storage/innobase/trx/trx0roll.cc13
-rw-r--r--storage/mroonga/mrn_table.cpp2
28 files changed, 513 insertions, 390 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8412e58b72c..e7c22af70e2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,6 +19,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7)
IF(POLICY CMP0022)
CMAKE_POLICY(SET CMP0022 NEW)
ENDIF()
+IF(POLICY CMP0048)
+ CMAKE_POLICY(SET CMP0048 NEW)
+ENDIF()
IF(POLICY CMP0054)
CMAKE_POLICY(SET CMP0054 NEW)
ENDIF()
diff --git a/cmake/FindBISON.cmake b/cmake/FindBISON.cmake
new file mode 100644
index 00000000000..28ae3f8fecb
--- /dev/null
+++ b/cmake/FindBISON.cmake
@@ -0,0 +1,8 @@
+IF(DEFINED BISON_EXECUTABLE)
+ SET(bison_quiet QUIET)
+ENDIF()
+
+set(orig_CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH})
+unset(CMAKE_MODULE_PATH)
+find_package(BISON ${BISON_FIND_VERSION} ${bison_quiet} ${BISON_FIND_REQUIRED})
+set(CMAKE_MODULE_PATH ${orig_CMAKE_MODULE_PATH})
diff --git a/mysql-test/suite/roles/set_default_role_for.result b/mysql-test/suite/roles/set_default_role_for.result
index f88dc83dfd9..a3cd896ee84 100644
--- a/mysql-test/suite/roles/set_default_role_for.result
+++ b/mysql-test/suite/roles/set_default_role_for.result
@@ -14,7 +14,7 @@ set default role role_a for user_a@localhost;
set default role invalid_role for user_a@localhost;
ERROR OP000: Invalid role specification `invalid_role`
set default role role_b for user_a@localhost;
-ERROR OP000: Invalid role specification `role_b`
+ERROR OP000: User `user_a@localhost` has not been granted role `role_b`
set default role role_b for user_b@localhost;
show grants;
Grants for user_a@localhost
@@ -36,7 +36,7 @@ user host default_role
user_a localhost role_a
user_b localhost role_b
set default role role_b for current_user;
-ERROR OP000: Invalid role specification `role_b`
+ERROR OP000: User `user_a@localhost` has not been granted role `role_b`
show grants;
Grants for user_b@localhost
GRANT `role_b` TO `user_b`@`localhost`
diff --git a/mysql-test/suite/roles/set_default_role_invalid.result b/mysql-test/suite/roles/set_default_role_invalid.result
index 4a3b88f0ef8..9ebe3069b4c 100644
--- a/mysql-test/suite/roles/set_default_role_invalid.result
+++ b/mysql-test/suite/roles/set_default_role_invalid.result
@@ -38,3 +38,90 @@ ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'us
drop role test_role;
drop role not_granted_role;
drop user test_user@localhost;
+#
+# MDEV-22312: Bad error message for SET DEFAULT ROLE when user account
+# is not granted the role
+#
+CREATE USER a;
+CREATE USER b;
+CREATE ROLE r1;
+CREATE ROLE r2;
+SET DEFAULT ROLE r1 FOR a;
+ERROR OP000: User `a@%` has not been granted role `r1`
+GRANT r1 TO b;
+GRANT r2 TO b;
+SET DEFAULT ROLE r1 FOR b;
+# Change user b
+SELECT CURRENT_ROLE;
+CURRENT_ROLE
+r1
+SET ROLE r2;
+SELECT CURRENT_ROLE;
+CURRENT_ROLE
+r2
+SET DEFAULT ROLE r1 FOR a;
+ERROR 42000: Access denied for user 'b'@'%' to database 'mysql'
+SET DEFAULT ROLE r2;
+# Change user root (session 1: select_priv to b)
+GRANT SELECT ON mysql.* TO b;
+# Change user b (session 1: select_priv)
+SHOW GRANTS FOR b;
+Grants for b@%
+GRANT `r1` TO `b`@`%`
+GRANT `r2` TO `b`@`%`
+GRANT USAGE ON *.* TO `b`@`%`
+GRANT SELECT ON `mysql`.* TO `b`@`%`
+SET DEFAULT ROLE r1 FOR a;
+ERROR 42000: Access denied for user 'b'@'%' to database 'mysql'
+SELECT CURRENT_ROLE;
+CURRENT_ROLE
+r2
+SET DEFAULT ROLE NONE;
+SELECT CURRENT_ROLE;
+CURRENT_ROLE
+r2
+SET DEFAULT ROLE current_role FOR current_user;
+SET DEFAULT ROLE invalid_role;
+ERROR OP000: Invalid role specification `invalid_role`
+SET DEFAULT ROLE invalid_role FOR a;
+ERROR 42000: Access denied for user 'b'@'%' to database 'mysql'
+SET DEFAULT ROLE none FOR a;
+ERROR 42000: Access denied for user 'b'@'%' to database 'mysql'
+# Change user root (session 2: adding update_priv to user b)
+GRANT UPDATE ON mysql.* TO b;
+# Change user b
+SHOW GRANTS FOR b;
+Grants for b@%
+GRANT `r1` TO `b`@`%`
+GRANT `r2` TO `b`@`%`
+GRANT USAGE ON *.* TO `b`@`%`
+GRANT SELECT, UPDATE ON `mysql`.* TO `b`@`%`
+SET DEFAULT ROLE r1 FOR a;
+ERROR OP000: User `a@%` has not been granted role `r1`
+SET DEFAULT ROLE invalid_role;
+ERROR OP000: Invalid role specification `invalid_role`
+SET DEFAULT ROLE invalid_role FOR a;
+ERROR OP000: Invalid role specification `invalid_role`
+SET DEFAULT ROLE none FOR a;
+# Change user root (session 3: Grant role to user a)
+GRANT r1 TO a;
+SET DEFAULT ROLE r1 FOR a;
+# Change user a (verify session 3)
+SELECT CURRENT_ROLE;
+CURRENT_ROLE
+r1
+SET DEFAULT ROLE None;
+# Change user b (session 3: role granted to user a)
+SET DEFAULT ROLE r1 FOR a;
+SET DEFAULT ROLE r2 FOR a;
+ERROR OP000: User `a@%` has not been granted role `r2`
+SET DEFAULT ROLE invalid_role;
+ERROR OP000: Invalid role specification `invalid_role`
+SET DEFAULT ROLE invalid_role FOR a;
+ERROR OP000: Invalid role specification `invalid_role`
+SELECT user, host, default_role FROM mysql.user where user='a' or user='b';
+user host default_role
+a % r1
+b % r2
+DROP ROLE r1, r2;
+DROP USER a, b;
diff --git a/mysql-test/suite/roles/set_default_role_invalid.test b/mysql-test/suite/roles/set_default_role_invalid.test
index 8e72e316d4b..02fca1107e2 100644
--- a/mysql-test/suite/roles/set_default_role_invalid.test
+++ b/mysql-test/suite/roles/set_default_role_invalid.test
@@ -60,3 +60,110 @@ change_user 'root';
drop role test_role;
drop role not_granted_role;
drop user test_user@localhost;
+
+--echo #
+--echo # MDEV-22312: Bad error message for SET DEFAULT ROLE when user account
+--echo # is not granted the role
+--echo #
+
+CREATE USER a;
+CREATE USER b;
+CREATE ROLE r1;
+CREATE ROLE r2;
+# Role has not been granted to user a, but the role is visible to current_user
+--error ER_INVALID_ROLE
+SET DEFAULT ROLE r1 FOR a;
+# Granting roles to user b
+GRANT r1 TO b;
+GRANT r2 TO b;
+# After granting the role, role can be set as default
+SET DEFAULT ROLE r1 FOR b;
+
+--echo # Change user b
+change_user b;
+SELECT CURRENT_ROLE;
+SET ROLE r2;
+SELECT CURRENT_ROLE;
+# User b has no UPDATE_PRIV for mysql.user
+--error ER_DBACCESS_DENIED_ERROR
+SET DEFAULT ROLE r1 FOR a;
+SET DEFAULT ROLE r2;
+
+--echo # Change user root (session 1: select_priv to b)
+change_user root;
+# Let's grant select_priv to user b
+GRANT SELECT ON mysql.* TO b;
+
+--echo # Change user b (session 1: select_priv)
+change_user b;
+SHOW GRANTS FOR b;
+# User must have update_priv before setting the role
+--error ER_DBACCESS_DENIED_ERROR
+SET DEFAULT ROLE r1 FOR a;
+# Testing the `CURRENT_ROLE` as a special case
+SELECT CURRENT_ROLE;
+SET DEFAULT ROLE NONE;
+SELECT CURRENT_ROLE;
+SET DEFAULT ROLE current_role FOR current_user;
+# Testing of non-existing role
+--error ER_INVALID_ROLE
+SET DEFAULT ROLE invalid_role;
+# Testing of non-existing role for different user
+--error ER_DBACCESS_DENIED_ERROR
+SET DEFAULT ROLE invalid_role FOR a;
+# Testing the `None` role for different user
+-- error ER_DBACCESS_DENIED_ERROR
+SET DEFAULT ROLE none FOR a;
+
+--echo # Change user root (session 2: adding update_priv to user b)
+change_user root;
+# update_priv are enough
+GRANT UPDATE ON mysql.* TO b;
+
+--echo # Change user b
+change_user b;
+SHOW GRANTS FOR b;
+# In all tests in session user a has not been granted the role
+# Testing setting role for different user, should fail with new error
+--error ER_INVALID_ROLE
+SET DEFAULT ROLE r1 FOR a;
+# Testing of non-existing role
+--error ER_INVALID_ROLE
+SET DEFAULT ROLE invalid_role;
+# Testing of non-existing role for different user with update_priv
+--error ER_INVALID_ROLE
+SET DEFAULT ROLE invalid_role FOR a;
+# Testing the `None` role for different user with update_priv
+SET DEFAULT ROLE none FOR a;
+
+--echo # Change user root (session 3: Grant role to user a)
+change_user root;
+# After granting the privilege for a, user b can set default role
+GRANT r1 TO a;
+SET DEFAULT ROLE r1 FOR a;
+
+--echo # Change user a (verify session 3)
+change_user a;
+SELECT CURRENT_ROLE;
+SET DEFAULT ROLE None;
+
+--echo # Change user b (session 3: role granted to user a)
+change_user b;
+# This should set role because b has update_priv
+SET DEFAULT ROLE r1 FOR a;
+# Testing non-granted role r2 still should fail
+-- error ER_INVALID_ROLE
+SET DEFAULT ROLE r2 FOR a;
+# Testing of non-existing role
+--error ER_INVALID_ROLE
+SET DEFAULT ROLE invalid_role;
+# Testing of non-existing role for different user
+--error ER_INVALID_ROLE
+SET DEFAULT ROLE invalid_role FOR a;
+
+# Clear the workspace
+change_user root;
+--sorted_result
+SELECT user, host, default_role FROM mysql.user where user='a' or user='b';
+DROP ROLE r1, r2;
+DROP USER a, b;
diff --git a/mysql-test/suite/roles/set_role-recursive.result b/mysql-test/suite/roles/set_role-recursive.result
index 945cadfb2b2..d9fb3f11849 100644
--- a/mysql-test/suite/roles/set_role-recursive.result
+++ b/mysql-test/suite/roles/set_role-recursive.result
@@ -66,7 +66,7 @@ Grants for test_user@localhost
GRANT USAGE ON *.* TO `test_user`@`localhost`
GRANT `test_role1` TO `test_user`@`localhost`
set role test_role2;
-ERROR OP000: Invalid role specification `test_role2`
+ERROR OP000: User `test_user@localhost` has not been granted role `test_role2`
select current_user(), current_role();
current_user() current_role()
test_user@localhost NULL
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index 6017a0fa8af..c413969e3df 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -815,7 +815,6 @@ String *Item_nodeset_func_attributebyname::val_nodeset(String *nodeset)
String *Item_nodeset_func_predicate::val_nodeset(String *str)
{
Item_nodeset_func *nodeset_func= (Item_nodeset_func*) args[0];
- Item_func *comp_func= (Item_func*)args[1];
uint pos= 0, size;
prepare(str);
size= (uint)(fltend - fltbeg);
@@ -825,7 +824,7 @@ String *Item_nodeset_func_predicate::val_nodeset(String *str)
((XPathFilter*)(&nodeset_func->context_cache))->append_element(flt->num,
flt->pos,
size);
- if (comp_func->val_int())
+ if (args[1]->val_int())
((XPathFilter*)str)->append_element(flt->num, pos++);
}
return str;
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 3711ec64aeb..eb2b9234db3 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -973,8 +973,17 @@ int set_var_default_role::check(THD *thd)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
real_user= get_current_user(thd, user);
- int status= acl_check_set_default_role(thd, real_user->host.str, real_user->user.str);
- return status;
+ real_role= role.str;
+ if (role.str == current_role.str)
+ {
+ if (!thd->security_ctx->priv_role[0])
+ real_role= "NONE";
+ else
+ real_role= thd->security_ctx->priv_role;
+ }
+
+ return acl_check_set_default_role(thd, real_user->host.str,
+ real_user->user.str, real_role);
#else
return 0;
#endif
@@ -985,7 +994,8 @@ int set_var_default_role::update(THD *thd)
#ifndef NO_EMBEDDED_ACCESS_CHECKS
Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
thd->m_reprepare_observer= 0;
- int res= acl_set_default_role(thd, real_user->host.str, real_user->user.str, role.str);
+ int res= acl_set_default_role(thd, real_user->host.str, real_user->user.str,
+ real_role);
thd->m_reprepare_observer= save_reprepare_observer;
return res;
#else
diff --git a/sql/set_var.h b/sql/set_var.h
index 7530d3eaff5..12e025e4696 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -1,7 +1,7 @@
#ifndef SET_VAR_INCLUDED
#define SET_VAR_INCLUDED
/* Copyright (c) 2002, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2014, SkySQL Ab.
+ Copyright (c) 2009, 2020, MariaDB
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
@@ -352,6 +352,7 @@ class set_var_default_role: public set_var_base
{
LEX_USER *user, *real_user;
LEX_CSTRING role;
+ const char *real_role;
public:
set_var_default_role(LEX_USER *user_arg, LEX_CSTRING role_arg) :
user(user_arg), role(role_arg) {}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index e29fd0345da..58711d0a9d0 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2018, Oracle and/or its affiliates.
- Copyright (c) 2009, 2018, MariaDB
+ Copyright (c) 2009, 2020, MariaDB
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
@@ -84,7 +84,6 @@ LEX_CSTRING current_user= { STRING_WITH_LEN("*current_user") };
LEX_CSTRING current_role= { STRING_WITH_LEN("*current_role") };
LEX_CSTRING current_user_and_current_role= { STRING_WITH_LEN("*current_user_and_current_role") };
-
#ifndef NO_EMBEDDED_ACCESS_CHECKS
static plugin_ref old_password_plugin;
#endif
@@ -2520,8 +2519,43 @@ bool acl_getroot(Security_context *sctx, const char *user, const char *host,
DBUG_RETURN(res);
}
-static int check_user_can_set_role(const char *user, const char *host,
- const char *ip, const char *rolename, ulonglong *access)
+static int check_role_is_granted_callback(ACL_USER_BASE *grantee, void *data)
+{
+ LEX_CSTRING *rolename= static_cast<LEX_CSTRING *>(data);
+ if (rolename->length == grantee->user.length &&
+ !strcmp(rolename->str, grantee->user.str))
+ return -1; // End search, we've found our role.
+
+ /* Keep looking, we haven't found our role yet. */
+ return 0;
+}
+
+/*
+ unlike find_user_exact and find_user_wild,
+ this function finds anonymous users too, it's when a
+ user is not empty, but priv_user (acl_user->user) is empty.
+*/
+static ACL_USER *find_user_or_anon(const char *host, const char *user, const char *ip)
+{
+ ACL_USER *result= NULL;
+ mysql_mutex_assert_owner(&acl_cache->lock);
+ for (uint i=0; i < acl_users.elements; i++)
+ {
+ ACL_USER *acl_user_tmp= dynamic_element(&acl_users, i, ACL_USER*);
+ if ((!acl_user_tmp->user.str ||
+ !strcmp(user, acl_user_tmp->user.str)) &&
+ compare_hostname(&acl_user_tmp->host, host, ip))
+ {
+ result= acl_user_tmp;
+ break;
+ }
+ }
+ return result;
+}
+
+static int check_user_can_set_role(THD *thd, const char *user, const char *host,
+ const char *ip, const char *rolename,
+ ulonglong *access)
{
ACL_ROLE *role;
ACL_USER_BASE *acl_user_base;
@@ -2538,10 +2572,7 @@ static int check_user_can_set_role(const char *user, const char *host,
/* get the current user */
acl_user= find_user_wild(host, user, ip);
if (acl_user == NULL)
- {
- my_error(ER_INVALID_CURRENT_USER, MYF(0));
- result= -1;
- }
+ result= ER_INVALID_CURRENT_USER;
else if (access)
*access= acl_user->access;
@@ -2551,9 +2582,9 @@ static int check_user_can_set_role(const char *user, const char *host,
role= find_acl_role(rolename);
/* According to SQL standard, the same error message must be presented */
- if (role == NULL) {
- my_error(ER_INVALID_ROLE, MYF(0), rolename);
- result= -1;
+ if (role == NULL)
+ {
+ result= ER_INVALID_ROLE;
goto end;
}
@@ -2574,7 +2605,6 @@ static int check_user_can_set_role(const char *user, const char *host,
/* According to SQL standard, the same error message must be presented */
if (!is_granted)
{
- my_error(ER_INVALID_ROLE, MYF(0), rolename);
result= 1;
goto end;
}
@@ -2583,17 +2613,66 @@ static int check_user_can_set_role(const char *user, const char *host,
{
*access = acl_user->access | role->access;
}
+
end:
mysql_mutex_unlock(&acl_cache->lock);
- return result;
+ /* We present different error messages depending if the user has sufficient
+ privileges to know if the INVALID_ROLE exists. */
+ switch (result)
+ {
+ case ER_INVALID_CURRENT_USER:
+ my_error(ER_INVALID_CURRENT_USER, MYF(0), rolename);
+ break;
+ case ER_INVALID_ROLE:
+ /* Role doesn't exist at all */
+ my_error(ER_INVALID_ROLE, MYF(0), rolename);
+ break;
+ case 1:
+ StringBuffer<1024> c_usr;
+ LEX_CSTRING role_lex;
+ /* First, check if current user can see mysql database. */
+ bool read_access= !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 1);
+
+ role_lex.str= rolename;
+ role_lex.length= strlen(rolename);
+ mysql_mutex_lock(&acl_cache->lock);
+ ACL_USER *cur_user= find_user_or_anon(thd->security_ctx->priv_host,
+ thd->security_ctx->priv_user,
+ thd->security_ctx->ip);
+
+ /* If the current user does not have select priv to mysql database,
+ see if the current user can discover the role if it was granted to him.
+ */
+ if (cur_user && (read_access ||
+ traverse_role_graph_down(cur_user, &role_lex,
+ check_role_is_granted_callback,
+ NULL) == -1))
+ {
+ /* Role is not granted but current user can see the role */
+ c_usr.append(user, strlen(user));
+ c_usr.append('@');
+ c_usr.append(host, strlen(host));
+ my_printf_error(ER_INVALID_ROLE, "User %`s has not been granted role %`s",
+ MYF(0), c_usr.c_ptr(), rolename);
+ }
+ else
+ {
+ /* Role is not granted and current user cannot see the role */
+ my_error(ER_INVALID_ROLE, MYF(0), rolename);
+ }
+ mysql_mutex_unlock(&acl_cache->lock);
+ break;
+ }
+
+ return result;
}
+
int acl_check_setrole(THD *thd, const char *rolename, ulonglong *access)
{
- /* Yes! priv_user@host. Don't ask why - that's what check_access() does. */
- return check_user_can_set_role(thd->security_ctx->priv_user,
- thd->security_ctx->host, thd->security_ctx->ip, rolename, access);
+ return check_user_can_set_role(thd, thd->security_ctx->priv_user,
+ thd->security_ctx->host, thd->security_ctx->ip, rolename, access);
}
@@ -3374,9 +3453,12 @@ WSREP_ERROR_LABEL:
DBUG_RETURN(result);
}
-int acl_check_set_default_role(THD *thd, const char *host, const char *user)
+int acl_check_set_default_role(THD *thd, const char *host, const char *user,
+ const char *role)
{
- return check_alter_user(thd, host, user);
+ DBUG_ENTER("acl_check_set_default_role");
+ DBUG_RETURN(check_alter_user(thd, host, user) ||
+ check_user_can_set_role(thd, user, host, NULL, role, NULL));
}
int acl_set_default_role(THD *thd, const char *host, const char *user,
@@ -3397,16 +3479,6 @@ int acl_set_default_role(THD *thd, const char *host, const char *user,
DBUG_PRINT("enter",("host: '%s' user: '%s' rolename: '%s'",
safe_str(user), safe_str(host), safe_str(rolename)));
- if (rolename == current_role.str) {
- if (!thd->security_ctx->priv_role[0])
- rolename= "NONE";
- else
- rolename= thd->security_ctx->priv_role;
- }
-
- if (check_user_can_set_role(user, host, host, rolename, NULL))
- DBUG_RETURN(result);
-
if (!strcasecmp(rolename, "NONE"))
clear_role= TRUE;
@@ -3571,31 +3643,6 @@ bool is_acl_user(const char *host, const char *user)
return res;
}
-
-/*
- unlike find_user_exact and find_user_wild,
- this function finds anonymous users too, it's when a
- user is not empty, but priv_user (acl_user->user) is empty.
-*/
-static ACL_USER *find_user_or_anon(const char *host, const char *user, const char *ip)
-{
- ACL_USER *result= NULL;
- mysql_mutex_assert_owner(&acl_cache->lock);
- for (uint i=0; i < acl_users.elements; i++)
- {
- ACL_USER *acl_user_tmp= dynamic_element(&acl_users, i, ACL_USER*);
- if ((!acl_user_tmp->user.str ||
- !strcmp(user, acl_user_tmp->user.str)) &&
- compare_hostname(&acl_user_tmp->host, host, ip))
- {
- result= acl_user_tmp;
- break;
- }
- }
- return result;
-}
-
-
/*
Find first entry that matches the specified user@host pair
*/
@@ -3900,7 +3947,7 @@ static bool test_if_create_new_users(THD *thd)
if (!(db_access & INSERT_ACL))
{
if (check_grant(thd, INSERT_ACL, &tl, FALSE, UINT_MAX, TRUE))
- create_new_users=0;
+ create_new_users=0;
}
}
return create_new_users;
@@ -9225,17 +9272,6 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc)
mysql_mutex_unlock(&acl_cache->lock);
}
-static int check_role_is_granted_callback(ACL_USER_BASE *grantee, void *data)
-{
- LEX_CSTRING *rolename= static_cast<LEX_CSTRING *>(data);
- if (rolename->length == grantee->user.length &&
- !strcmp(rolename->str, grantee->user.str))
- return -1; // End search, we've found our role.
-
- /* Keep looking, we haven't found our role yet. */
- return 0;
-}
-
/*
Modify a privilege table.
@@ -11125,7 +11161,7 @@ acl_check_proxy_grant_access(THD *thd, const char *host, const char *user,
Security context in THD contains two pairs of (user,host):
1. (user,host) pair referring to inbound connection.
2. (priv_user,priv_host) pair obtained from mysql.user table after doing
- authnetication of incoming connection.
+ authentication of incoming connection.
Privileges should be checked wrt (priv_user, priv_host) tuple, because
(user,host) pair obtained from inbound connection may have different
values than what is actually stored in mysql.user table and while granting
@@ -11544,7 +11580,7 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
ulong j,test_access= want_access & ~GRANT_ACL;
for (priv_id=0, j = SELECT_ACL;j <= GLOBAL_ACLS; priv_id++,j <<= 1)
{
- if (test_access & j)
+ if (test_access & j)
{
if (update_schema_privilege(thd, table, buff, 0, 0, 0, 0,
command_array[priv_id],
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 7989367ec44..dc8a085c96c 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -2,7 +2,7 @@
#define SQL_ACL_INCLUDED
/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
- Copyright (c) 2017, MariaDB Corporation.
+ Copyright (c) 2017, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -417,7 +417,8 @@ bool acl_check_proxy_grant_access (THD *thd, const char *host, const char *user,
bool with_grant);
int acl_setrole(THD *thd, const char *rolename, ulonglong access);
int acl_check_setrole(THD *thd, const char *rolename, ulonglong *access);
-int acl_check_set_default_role(THD *thd, const char *host, const char *user);
+int acl_check_set_default_role(THD *thd, const char *host, const char *user,
+ const char *role);
int acl_set_default_role(THD *thd, const char *host, const char *user,
const char *rolename);
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index 83013b8b1e7..b65f460c896 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -1,5 +1,5 @@
/* Copyright (C) 2009 MySQL AB
- Copyright (c) 2019, MariaDB Corporation.
+ Copyright (c) 2019, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -2214,27 +2214,13 @@ static int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *table_share)
DBUG_ENTER("alloc_statistics_for_table_share");
- DEBUG_SYNC(thd, "statistics_mem_alloc_start1");
- DEBUG_SYNC(thd, "statistics_mem_alloc_start2");
-
- mysql_mutex_lock(&table_share->LOCK_share);
-
- if (stats_cb->stats_can_be_read)
- {
- mysql_mutex_unlock(&table_share->LOCK_share);
- DBUG_RETURN(0);
- }
-
Table_statistics *table_stats= stats_cb->table_stats;
if (!table_stats)
{
table_stats= (Table_statistics *) alloc_root(&stats_cb->mem_root,
sizeof(Table_statistics));
if (!table_stats)
- {
- mysql_mutex_unlock(&table_share->LOCK_share);
DBUG_RETURN(1);
- }
memset(table_stats, 0, sizeof(Table_statistics));
stats_cb->table_stats= table_stats;
}
@@ -2300,89 +2286,11 @@ static int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *table_share)
}
}
}
-
- if (column_stats && index_stats && idx_avg_frequency)
- stats_cb->stats_can_be_read= TRUE;
-
- mysql_mutex_unlock(&table_share->LOCK_share);
-
- DBUG_RETURN(0);
+ DBUG_RETURN(column_stats && index_stats && idx_avg_frequency ? 0 : 1);
}
/**
- @brief
- Allocate memory for the histogram used by a table share
-
- @param
- thd Thread handler
- @param
- table_share Table share for which the memory for histogram data is allocated
- @param
- is_safe TRUE <-> at any time only one thread can perform the function
-
- @note
- The function allocates the memory for the histogram built for a table in the
- table's share memory with the intention to read the data there from the
- system persistent statistical table mysql.column_stats,
- The memory is allocated in the table_share's mem_root.
- If the parameter is_safe is TRUE then it is guaranteed that at any given time
- only one thread is executed the code of the function.
-
- @retval
- 0 If the memory for all statistical data has been successfully allocated
- @retval
- 1 Otherwise
-
- @note
- Currently the function always is called with the parameter is_safe set
- to FALSE.
-*/
-
-static
-int alloc_histograms_for_table_share(THD* thd, TABLE_SHARE *table_share,
- bool is_safe)
-{
- TABLE_STATISTICS_CB *stats_cb= &table_share->stats_cb;
-
- DBUG_ENTER("alloc_histograms_for_table_share");
-
- if (!is_safe)
- mysql_mutex_lock(&table_share->LOCK_share);
-
- if (stats_cb->histograms_can_be_read)
- {
- if (!is_safe)
- mysql_mutex_unlock(&table_share->LOCK_share);
- DBUG_RETURN(0);
- }
-
- Table_statistics *table_stats= stats_cb->table_stats;
- ulong total_hist_size= table_stats->total_hist_size;
-
- if (total_hist_size && !table_stats->histograms)
- {
- uchar *histograms= (uchar *) alloc_root(&stats_cb->mem_root,
- total_hist_size);
- if (!histograms)
- {
- if (!is_safe)
- mysql_mutex_unlock(&table_share->LOCK_share);
- DBUG_RETURN(1);
- }
- memset(histograms, 0, total_hist_size);
- table_stats->histograms= histograms;
- stats_cb->histograms_can_be_read= TRUE;
- }
-
- if (!is_safe)
- mysql_mutex_unlock(&table_share->LOCK_share);
-
- DBUG_RETURN(0);
-
-}
-
-/**
@brief
Initialize the aggregation fields to collect statistics on a column
@@ -2923,15 +2831,26 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
Field **field_ptr;
KEY *key_info, *key_info_end;
TABLE_SHARE *table_share= table->s;
- Table_statistics *read_stats= table_share->stats_cb.table_stats;
enum_check_fields old_check_level= thd->count_cuted_fields;
DBUG_ENTER("read_statistics_for_table");
+ DEBUG_SYNC(thd, "statistics_mem_alloc_start1");
+ DEBUG_SYNC(thd, "statistics_mem_alloc_start2");
+
+ if (!table_share->stats_cb.start_stats_load())
+ DBUG_RETURN(table_share->stats_cb.stats_are_ready() ? 0 : 1);
+
+ if (alloc_statistics_for_table_share(thd, table_share))
+ {
+ table_share->stats_cb.abort_stats_load();
+ DBUG_RETURN(1);
+ }
/* Don't write warnings for internal field conversions */
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
/* Read statistics from the statistical table table_stats */
+ Table_statistics *read_stats= table_share->stats_cb.table_stats;
stat_table= stat_tables[TABLE_STAT].table;
Table_stat table_stat(stat_table, table);
table_stat.set_key_fields();
@@ -2948,7 +2867,7 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
column_stat.get_stat_values();
total_hist_size+= table_field->read_stats->histogram.get_size();
}
- read_stats->total_hist_size= total_hist_size;
+ table_share->stats_cb.total_hist_size= total_hist_size;
/* Read statistics from the statistical table index_stats */
stat_table= stat_tables[INDEX_STAT].table;
@@ -3010,9 +2929,8 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
}
}
- table->stats_is_read= TRUE;
thd->count_cuted_fields= old_check_level;
-
+ table_share->stats_cb.end_stats_load();
DBUG_RETURN(0);
}
@@ -3052,71 +2970,6 @@ void delete_stat_values_for_table_share(TABLE_SHARE *table_share)
/**
@brief
- Check whether any statistics is to be read for tables from a table list
-
- @param
- thd The thread handle
- @param
- tables The tables list for whose tables the check is to be done
-
- @details
- The function checks whether for any of the tables opened and locked for
- a statement statistics from statistical tables is needed to be read.
-
- @retval
- TRUE statistics for any of the tables is needed to be read
- @retval
- FALSE Otherwise
-*/
-
-static
-bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables)
-{
- if (!tables)
- return FALSE;
-
- /*
- Do not read statistics for any query that explicity involves
- statistical tables, failure to to do so we may end up
- in a deadlock.
- */
-
- for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
- {
- if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table)
- {
- TABLE_SHARE *table_share= tl->table->s;
- if (table_share &&
- table_share->table_category != TABLE_CATEGORY_USER
- && is_stat_table(&tl->db, &tl->alias))
- return FALSE;
- }
- }
-
- for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
- {
- if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table)
- {
- TABLE_SHARE *table_share= tl->table->s;
- if (table_share &&
- table_share->stats_cb.stats_can_be_read &&
- (!table_share->stats_cb.stats_is_read ||
- (!table_share->stats_cb.histograms_are_read &&
- thd->variables.optimizer_use_condition_selectivity > 3)))
- return TRUE;
- if (table_share->stats_cb.stats_is_read)
- tl->table->stats_is_read= TRUE;
- if (table_share->stats_cb.histograms_are_read)
- tl->table->histograms_are_read= TRUE;
- }
- }
-
- return FALSE;
-}
-
-
-/**
- @brief
Read histogram for a table from the persistent statistical tables
@param
@@ -3150,26 +3003,25 @@ bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables)
static
int read_histograms_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
{
- TABLE_SHARE *table_share= table->s;
-
+ TABLE_STATISTICS_CB *stats_cb= &table->s->stats_cb;
DBUG_ENTER("read_histograms_for_table");
- if (!table_share->stats_cb.histograms_can_be_read)
+ if (stats_cb->start_histograms_load())
{
- (void) alloc_histograms_for_table_share(thd, table_share, FALSE);
- }
- if (table_share->stats_cb.histograms_can_be_read &&
- !table_share->stats_cb.histograms_are_read)
- {
- Field **field_ptr;
- uchar *histogram= table_share->stats_cb.table_stats->histograms;
- TABLE *stat_table= stat_tables[COLUMN_STAT].table;
- Column_stat column_stat(stat_table, table);
- for (field_ptr= table_share->field; *field_ptr; field_ptr++)
+ uchar *histogram= (uchar *) alloc_root(&stats_cb->mem_root,
+ stats_cb->total_hist_size);
+ if (!histogram)
+ {
+ stats_cb->abort_histograms_load();
+ DBUG_RETURN(1);
+ }
+ memset(histogram, 0, stats_cb->total_hist_size);
+
+ Column_stat column_stat(stat_tables[COLUMN_STAT].table, table);
+ for (Field **field_ptr= table->s->field; *field_ptr; field_ptr++)
{
Field *table_field= *field_ptr;
- uint hist_size= table_field->read_stats->histogram.get_size();
- if (hist_size)
+ if (uint hist_size= table_field->read_stats->histogram.get_size())
{
column_stat.set_key_fields(table_field);
table_field->read_stats->histogram.set_values(histogram);
@@ -3177,8 +3029,9 @@ int read_histograms_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
histogram+= hist_size;
}
}
+ stats_cb->end_histograms_load();
}
-
+ table->histograms_are_read= true;
DBUG_RETURN(0);
}
@@ -3226,6 +3079,23 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables)
}
+static void dump_stats_from_share_to_table(TABLE *table)
+{
+ TABLE_SHARE *table_share= table->s;
+ KEY *key_info= table_share->key_info;
+ KEY *key_info_end= key_info + table_share->keys;
+ KEY *table_key_info= table->key_info;
+ for ( ; key_info < key_info_end; key_info++, table_key_info++)
+ table_key_info->read_stats= key_info->read_stats;
+
+ Field **field_ptr= table_share->field;
+ Field **table_field_ptr= table->field;
+ for ( ; *field_ptr; field_ptr++, table_field_ptr++)
+ (*table_field_ptr)->read_stats= (*field_ptr)->read_stats;
+ table->stats_is_read= true;
+}
+
+
int read_statistics_for_tables(THD *thd, TABLE_LIST *tables)
{
TABLE_LIST stat_tables[STATISTICS_TABLES];
@@ -3236,38 +3106,42 @@ int read_statistics_for_tables(THD *thd, TABLE_LIST *tables)
if (thd->bootstrap || thd->variables.use_stat_tables == NEVER)
DBUG_RETURN(0);
+ bool found_stat_table= false;
+ bool statistics_for_tables_is_needed= false;
+
for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
{
- if (tl->table)
+ TABLE_SHARE *table_share;
+ if (!tl->is_view_or_derived() && tl->table && (table_share= tl->table->s) &&
+ table_share->tmp_table == NO_TMP_TABLE)
{
- TABLE_SHARE *table_share= tl->table->s;
- if (table_share && table_share->table_category == TABLE_CATEGORY_USER &&
- table_share->tmp_table == NO_TMP_TABLE)
+ if (table_share->table_category == TABLE_CATEGORY_USER)
{
- if (table_share->stats_cb.stats_can_be_read ||
- !alloc_statistics_for_table_share(thd, table_share))
+ if (table_share->stats_cb.stats_are_ready())
{
- if (table_share->stats_cb.stats_can_be_read)
- {
- KEY *key_info= table_share->key_info;
- KEY *key_info_end= key_info + table_share->keys;
- KEY *table_key_info= tl->table->key_info;
- for ( ; key_info < key_info_end; key_info++, table_key_info++)
- table_key_info->read_stats= key_info->read_stats;
- Field **field_ptr= table_share->field;
- Field **table_field_ptr= tl->table->field;
- for ( ; *field_ptr; field_ptr++, table_field_ptr++)
- (*table_field_ptr)->read_stats= (*field_ptr)->read_stats;
- tl->table->stats_is_read= table_share->stats_cb.stats_is_read;
- }
+ if (!tl->table->stats_is_read)
+ dump_stats_from_share_to_table(tl->table);
+ tl->table->histograms_are_read=
+ table_share->stats_cb.histograms_are_ready();
+ if (table_share->stats_cb.histograms_are_ready() ||
+ thd->variables.optimizer_use_condition_selectivity <= 3)
+ continue;
}
+ statistics_for_tables_is_needed= true;
}
+ else if (is_stat_table(&tl->db, &tl->alias))
+ found_stat_table= true;
}
}
DEBUG_SYNC(thd, "statistics_read_start");
- if (!statistics_for_tables_is_needed(thd, tables))
+ /*
+ Do not read statistics for any query that explicity involves
+ statistical tables, failure to to do so we may end up
+ in a deadlock.
+ */
+ if (found_stat_table || !statistics_for_tables_is_needed)
DBUG_RETURN(0);
if (open_stat_tables(thd, stat_tables, &open_tables_backup, FALSE))
@@ -3275,32 +3149,22 @@ int read_statistics_for_tables(THD *thd, TABLE_LIST *tables)
for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
{
- if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table)
- {
- TABLE_SHARE *table_share= tl->table->s;
- if (table_share && !(table_share->table_category == TABLE_CATEGORY_USER))
- continue;
-
- if (table_share &&
- table_share->stats_cb.stats_can_be_read &&
- !table_share->stats_cb.stats_is_read)
+ TABLE_SHARE *table_share;
+ if (!tl->is_view_or_derived() && tl->table && (table_share= tl->table->s) &&
+ table_share->tmp_table == NO_TMP_TABLE &&
+ table_share->table_category == TABLE_CATEGORY_USER)
+ {
+ if (!tl->table->stats_is_read)
{
- (void) read_statistics_for_table(thd, tl->table, stat_tables);
- table_share->stats_cb.stats_is_read= TRUE;
+ if (!read_statistics_for_table(thd, tl->table, stat_tables))
+ dump_stats_from_share_to_table(tl->table);
+ else
+ continue;
}
- if (table_share->stats_cb.stats_is_read)
- tl->table->stats_is_read= TRUE;
- if (thd->variables.optimizer_use_condition_selectivity > 3 &&
- table_share && table_share->stats_cb.stats_can_be_read &&
- !table_share->stats_cb.histograms_are_read)
- {
+ if (thd->variables.optimizer_use_condition_selectivity > 3)
(void) read_histograms_for_table(thd, tl->table, stat_tables);
- table_share->stats_cb.histograms_are_read= TRUE;
- }
- if (table_share->stats_cb.histograms_are_read)
- tl->table->histograms_are_read= TRUE;
}
- }
+ }
close_system_tables(thd, &open_tables_backup);
diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h
index a69dd340dd7..c6b4fed30fa 100644
--- a/sql/sql_statistics.h
+++ b/sql/sql_statistics.h
@@ -268,7 +268,6 @@ public:
Column_statistics *column_stats; /* Array of statistical data for columns */
Index_statistics *index_stats; /* Array of statistical data for indexes */
ulong *idx_avg_frequency; /* Array of records per key for index prefixes */
- ulong total_hist_size; /* Total size of all histograms */
uchar *histograms; /* Sequence of histograms */
};
diff --git a/sql/table.cc b/sql/table.cc
index 7d09985094c..1877c3b7c76 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -443,10 +443,6 @@ void TABLE_SHARE::destroy()
delete_stat_values_for_table_share(this);
delete sequence;
free_root(&stats_cb.mem_root, MYF(0));
- stats_cb.stats_can_be_read= FALSE;
- stats_cb.stats_is_read= FALSE;
- stats_cb.histograms_can_be_read= FALSE;
- stats_cb.histograms_are_read= FALSE;
/* The mutexes are initialized only for shares that are part of the TDC */
if (tmp_table == NO_TMP_TABLE)
diff --git a/sql/table.h b/sql/table.h
index 940f135bcf1..2bad6cbf32f 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -581,15 +581,94 @@ enum open_frm_error {
from persistent statistical tables
*/
-struct TABLE_STATISTICS_CB
+class TABLE_STATISTICS_CB
{
+ class Statistics_state
+ {
+ enum state_codes
+ {
+ EMPTY, /** data is not loaded */
+ LOADING, /** data is being loaded in some connection */
+ READY /** data is loaded and available for use */
+ };
+ int32 state;
+
+ public:
+ /** No state copy */
+ Statistics_state &operator=(const Statistics_state &) { return *this; }
+
+ /** Checks if data loading have been completed */
+ bool is_ready() const
+ {
+ return my_atomic_load32_explicit(const_cast<int32*>(&state),
+ MY_MEMORY_ORDER_ACQUIRE) == READY;
+ }
+
+ /**
+ Sets mutual exclusion for data loading
+
+ If stats are in LOADING state, waits until state change.
+
+ @return
+ @retval true atomic EMPTY -> LOADING transfer completed, ok to load
+ @retval false stats are in READY state, no need to load
+ */
+ bool start_load()
+ {
+ for (;;)
+ {
+ int32 expected= EMPTY;
+ if (my_atomic_cas32_weak_explicit(&state, &expected, LOADING,
+ MY_MEMORY_ORDER_RELAXED,
+ MY_MEMORY_ORDER_RELAXED))
+ return true;
+ if (expected == READY)
+ return false;
+ (void) LF_BACKOFF();
+ }
+ }
+
+ /** Marks data available for subsequent use */
+ void end_load()
+ {
+ DBUG_ASSERT(my_atomic_load32_explicit(&state, MY_MEMORY_ORDER_RELAXED) ==
+ LOADING);
+ my_atomic_store32_explicit(&state, READY, MY_MEMORY_ORDER_RELEASE);
+ }
+
+ /** Restores empty state on error (e.g. OOM) */
+ void abort_load()
+ {
+ DBUG_ASSERT(my_atomic_load32_explicit(&state, MY_MEMORY_ORDER_RELAXED) ==
+ LOADING);
+ my_atomic_store32_explicit(&state, EMPTY, MY_MEMORY_ORDER_RELAXED);
+ }
+ };
+
+ class Statistics_state stats_state;
+ class Statistics_state hist_state;
+
+public:
MEM_ROOT mem_root; /* MEM_ROOT to allocate statistical data for the table */
Table_statistics *table_stats; /* Structure to access the statistical data */
- bool stats_can_be_read; /* Memory for statistical data is allocated */
- bool stats_is_read; /* Statistical data for table has been read
- from statistical tables */
- bool histograms_can_be_read;
- bool histograms_are_read;
+ ulong total_hist_size; /* Total size of all histograms */
+
+ bool histograms_are_ready() const
+ {
+ return !total_hist_size || hist_state.is_ready();
+ }
+
+ bool start_histograms_load()
+ {
+ return total_hist_size && hist_state.start_load();
+ }
+
+ void end_histograms_load() { hist_state.end_load(); }
+ void abort_histograms_load() { hist_state.abort_load(); }
+ bool stats_are_ready() const { return stats_state.is_ready(); }
+ bool start_stats_load() { return stats_state.start_load(); }
+ void end_stats_load() { stats_state.end_load(); }
+ void abort_stats_load() { stats_state.abort_load(); }
};
/**
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt
index 199a8a3fa8b..0af3a02a09d 100644
--- a/storage/connect/CMakeLists.txt
+++ b/storage/connect/CMakeLists.txt
@@ -318,7 +318,7 @@ ENDIF(CONNECT_WITH_MONGO)
OPTION(CONNECT_WITH_REST "Compile CONNECT storage engine with REST support" ON)
IF(CONNECT_WITH_REST)
- MESSAGE(STATUS "=====> REST support is ON")
+ MESSAGE_ONCE(CONNECT_WITH_REST "REST support is ON")
SET(CONNECT_SOURCES ${CONNECT_SOURCES} tabrest.cpp tabrest.h)
add_definitions(-DREST_SUPPORT)
FIND_PACKAGE(cpprestsdk QUIET)
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index a2364299135..5ff19e9aaf6 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -4286,7 +4286,7 @@ btr_cur_optimistic_update(
ULINT_UNDEFINED, heap);
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!rec_offs_any_null_extern(rec, *offsets)
- || trx_is_recv(thr_get_trx(thr)));
+ || thr_get_trx(thr) == trx_roll_crash_recv_trx);
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
const bool is_metadata = update->info_bits == REC_INFO_METADATA;
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 9a32f4cbd14..750e9da181f 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -4677,7 +4677,7 @@ evict_from_pool:
buf_pool->mutex or block->mutex. */
{
- bool success = buf_zip_decompress(block, TRUE);
+ bool success = buf_zip_decompress(block, false);
if (!success) {
buf_pool_mutex_enter(buf_pool);
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index b116ca919fd..243f3a18019 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -1071,10 +1071,8 @@ buf_flush_write_block_low(
case BUF_BLOCK_ZIP_DIRTY:
frame = bpage->zip.data;
- mach_write_to_8(frame + FIL_PAGE_LSN,
- bpage->newest_modification);
-
- ut_a(page_zip_verify_checksum(frame, bpage->size.physical()));
+ buf_flush_update_zip_checksum(frame, bpage->size.physical(),
+ bpage->newest_modification);
break;
case BUF_BLOCK_FILE_PAGE:
frame = bpage->zip.data;
diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc
index 40fed0617e7..2baa7ab0780 100644
--- a/storage/innobase/buf/buf0lru.cc
+++ b/storage/innobase/buf/buf0lru.cc
@@ -1616,27 +1616,6 @@ func_exit:
UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
srv_page_size);
- if (b != NULL) {
-
- /* Compute and stamp the compressed page
- checksum while not holding any mutex. The
- block is already half-freed
- (BUF_BLOCK_REMOVE_HASH) and removed from
- buf_pool->page_hash, thus inaccessible by any
- other thread. */
-
- ut_ad(b->size.is_compressed());
-
- const uint32_t checksum = page_zip_calc_checksum(
- b->zip.data,
- b->size.physical(),
- static_cast<srv_checksum_algorithm_t>(
- srv_checksum_algorithm));
-
- mach_write_to_4(b->zip.data + FIL_PAGE_SPACE_OR_CHKSUM,
- checksum);
- }
-
buf_pool_mutex_enter(buf_pool);
if (b != NULL) {
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index af849c09729..e3971126761 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -3688,7 +3688,7 @@ static int innodb_init_params()
pages, even for larger pages */
if (srv_page_size > UNIV_PAGE_SIZE_DEF
&& innobase_buffer_pool_size < (24 * 1024 * 1024)) {
- ib::info() << "innodb_page_size="
+ ib::error() << "innodb_page_size="
<< srv_page_size << " requires "
<< "innodb_buffer_pool_size > 24M current "
<< innobase_buffer_pool_size;
diff --git a/storage/innobase/include/que0que.h b/storage/innobase/include/que0que.h
index 66dc00f5d10..b46393e37d2 100644
--- a/storage/innobase/include/que0que.h
+++ b/storage/innobase/include/que0que.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2019, MariaDB Corporation.
+Copyright (c) 2017, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -169,16 +169,6 @@ trx_t*
thr_get_trx(
/*========*/
que_thr_t* thr); /*!< in: query thread */
-/*******************************************************************//**
-Determines if this thread is rolling back an incomplete transaction
-in crash recovery.
-@return TRUE if thr is rolling back an incomplete transaction in crash
-recovery */
-UNIV_INLINE
-ibool
-thr_is_recv(
-/*========*/
- const que_thr_t* thr); /*!< in: query thread */
/***********************************************************************//**
Gets the type of a graph node. */
UNIV_INLINE
diff --git a/storage/innobase/include/que0que.ic b/storage/innobase/include/que0que.ic
index 5b775820df7..1c3ac242bf2 100644
--- a/storage/innobase/include/que0que.ic
+++ b/storage/innobase/include/que0que.ic
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -36,20 +37,6 @@ thr_get_trx(
return(thr->graph->trx);
}
-/*******************************************************************//**
-Determines if this thread is rolling back an incomplete transaction
-in crash recovery.
-@return TRUE if thr is rolling back an incomplete transaction in crash
-recovery */
-UNIV_INLINE
-ibool
-thr_is_recv(
-/*========*/
- const que_thr_t* thr) /*!< in: query thread */
-{
- return(trx_is_recv(thr->graph->trx));
-}
-
/***********************************************************************//**
Gets the first thr in a fork. */
UNIV_INLINE
diff --git a/storage/innobase/include/trx0roll.h b/storage/innobase/include/trx0roll.h
index d2b873c5647..a23b57ccc3e 100644
--- a/storage/innobase/include/trx0roll.h
+++ b/storage/innobase/include/trx0roll.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2019, MariaDB Corporation.
+Copyright (c) 2015, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -35,15 +35,6 @@ extern bool trx_rollback_is_active;
extern const trx_t* trx_roll_crash_recv_trx;
/*******************************************************************//**
-Determines if this transaction is rolling back an incomplete transaction
-in crash recovery.
-@return TRUE if trx is an incomplete transaction that is being rolled
-back in crash recovery */
-ibool
-trx_is_recv(
-/*========*/
- const trx_t* trx); /*!< in: transaction */
-/*******************************************************************//**
Returns a transaction savepoint taken at this point in time.
@return savepoint */
trx_savept_t
diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc
index c71bf2643a6..2ac54c4025e 100644
--- a/storage/innobase/row/row0umod.cc
+++ b/storage/innobase/row/row0umod.cc
@@ -913,7 +913,7 @@ row_undo_mod_upd_del_sec(
does not exist. However, this situation may
only occur during the rollback of incomplete
transactions. */
- ut_a(thr_is_recv(thr));
+ ut_a(thr_get_trx(thr) == trx_roll_crash_recv_trx);
} else {
err = row_undo_mod_del_mark_or_remove_sec(
node, thr, index, entry);
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index ea08e0c2787..b858a81c294 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -1884,7 +1884,8 @@ row_upd_changes_ord_field_binary_func(
when the server had crashed before
storing the field. */
ut_ad(thr->graph->trx->is_recovered);
- ut_ad(trx_is_recv(thr->graph->trx));
+ ut_ad(thr->graph->trx
+ == trx_roll_crash_recv_trx);
return(TRUE);
}
diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc
index c06e181a097..f2b108edf39 100644
--- a/storage/innobase/trx/trx0roll.cc
+++ b/storage/innobase/trx/trx0roll.cc
@@ -593,19 +593,6 @@ trx_release_savepoint_for_mysql(
}
/*******************************************************************//**
-Determines if this transaction is rolling back an incomplete transaction
-in crash recovery.
-@return TRUE if trx is an incomplete transaction that is being rolled
-back in crash recovery */
-ibool
-trx_is_recv(
-/*========*/
- const trx_t* trx) /*!< in: transaction */
-{
- return(trx == trx_roll_crash_recv_trx);
-}
-
-/*******************************************************************//**
Returns a transaction savepoint taken at this point in time.
@return savepoint */
trx_savept_t
diff --git a/storage/mroonga/mrn_table.cpp b/storage/mroonga/mrn_table.cpp
index 09bac98c153..eedb03544d0 100644
--- a/storage/mroonga/mrn_table.cpp
+++ b/storage/mroonga/mrn_table.cpp
@@ -932,7 +932,7 @@ MRN_SHARE *mrn_get_share(const char *table_name, TABLE *table, int *error)
share->wrap_key_info = NULL;
share->wrap_primary_key = MAX_KEY;
}
- memcpy(wrap_table_share, table->s, sizeof(*wrap_table_share));
+ *wrap_table_share= *table->s;
mrn_init_sql_alloc(current_thd, &(wrap_table_share->mem_root));
wrap_table_share->keys = share->wrap_keys;
wrap_table_share->key_info = share->wrap_key_info;