diff options
author | Sergei Golubchik <serg@mariadb.org> | 2018-11-22 16:16:53 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2018-12-12 00:31:04 +0100 |
commit | a76aadf7bc54e750e2474a080777e346ddbffc0d (patch) | |
tree | 90b7e0a77b49a1c762bc1091a4cb0d904f65581b | |
parent | 9887d2e881b49dcfaea9b1af7f7ac62648032085 (diff) | |
download | mariadb-git-a76aadf7bc54e750e2474a080777e346ddbffc0d.tar.gz |
MDEV-17658 change the structure of mysql.user table
Introduce User_table_tabular(mysql.user) and User_table_json(mysql.global_priv).
The latter is not implemented.
Automatic fallback to the old implementation works.
Results change because privilege tables are opened in a different
order now.
-rw-r--r-- | mysql-test/main/not_embedded_server.result | 4 | ||||
-rw-r--r-- | mysql-test/main/not_embedded_server.test | 2 | ||||
-rw-r--r-- | mysql-test/suite/plugins/r/server_audit.result | 8 | ||||
-rw-r--r-- | mysql-test/suite/plugins/r/thread_pool_server_audit.result | 8 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result | 22 | ||||
-rw-r--r-- | sql/sql_acl.cc | 229 |
6 files changed, 194 insertions, 79 deletions
diff --git a/mysql-test/main/not_embedded_server.result b/mysql-test/main/not_embedded_server.result index ba68ca8619b..bc794ce48c8 100644 --- a/mysql-test/main/not_embedded_server.result +++ b/mysql-test/main/not_embedded_server.result @@ -1,4 +1,4 @@ -call mtr.add_suppression("Can't open and lock privilege tables: Table 'user' was not locked with LOCK TABLES"); +call mtr.add_suppression("Can't open and lock privilege tables: Table 'db' was not locked with LOCK TABLES"); SHOW VARIABLES like 'slave_skip_errors'; Variable_name Value slave_skip_errors OFF @@ -16,7 +16,7 @@ DROP TABLE IF EXISTS t1; CREATE TABLE t1 (c1 INT); LOCK TABLES t1 READ; FLUSH PRIVILEGES; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'db' was not locked with LOCK TABLES UNLOCK TABLES; DROP TABLE t1; # diff --git a/mysql-test/main/not_embedded_server.test b/mysql-test/main/not_embedded_server.test index b2cbdba6850..20f75db25d5 100644 --- a/mysql-test/main/not_embedded_server.test +++ b/mysql-test/main/not_embedded_server.test @@ -6,7 +6,7 @@ # End of 4.1 tests -call mtr.add_suppression("Can't open and lock privilege tables: Table 'user' was not locked with LOCK TABLES"); +call mtr.add_suppression("Can't open and lock privilege tables: Table 'db' was not locked with LOCK TABLES"); # # Bug#43835: SHOW VARIABLES does not include 0 for slave_skip_errors diff --git a/mysql-test/suite/plugins/r/server_audit.result b/mysql-test/suite/plugins/r/server_audit.result index c7f05f8581a..17ae393b846 100644 --- a/mysql-test/suite/plugins/r/server_audit.result +++ b/mysql-test/suite/plugins/r/server_audit.result @@ -327,34 +327,34 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0 TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, -TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u1 IDENTIFIED BY *****',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u1 IDENTIFIED BY *****',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'GRANT ALL ON sa_db TO u2 IDENTIFIED BY *****',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1 = PASSWORD(*****)',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, -TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop user u1, u2, u3',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create table t1(id int)',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop table t1',0 diff --git a/mysql-test/suite/plugins/r/thread_pool_server_audit.result b/mysql-test/suite/plugins/r/thread_pool_server_audit.result index 91fbf8c27d9..f83b00b2c9b 100644 --- a/mysql-test/suite/plugins/r/thread_pool_server_audit.result +++ b/mysql-test/suite/plugins/r/thread_pool_server_audit.result @@ -316,34 +316,34 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0 TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, -TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u1 IDENTIFIED BY *****',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u1 IDENTIFIED BY *****',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'GRANT ALL ON sa_db TO u2 IDENTIFIED BY *****',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1 = PASSWORD(*****)',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, -TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop user u1, u2, u3',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create table t1(id int)',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop table t1',0 diff --git a/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result index e8e95ab7c4c..45070949f79 100644 --- a/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result +++ b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result @@ -145,43 +145,43 @@ UNLOCK TABLE; DROP DATABASE mysqltest2; LOCK TABLE t1 WRITE; CREATE USER test_1@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'db' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("CREATE USER test_1@localhost with table locked"); UNLOCK TABLE; CREATE USER test_2@localhost; LOCK TABLE t1 WRITE; GRANT SELECT ON t1 TO test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'tables_priv' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("GRANT select on table to user with table locked"); GRANT ALL ON f2 TO test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'tables_priv' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("GRANT ALL ON f2 TO test_2 with table locked"); GRANT ALL ON p2 TO test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'tables_priv' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("GRANT ALL ON p2 TO test_2 with table locked"); GRANT USAGE ON *.* TO test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'db' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("GRANT USAGE ON *.* TO test_2 with table locked"); REVOKE ALL PRIVILEGES ON f2 FROM test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'tables_priv' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on function to user with table locked"); REVOKE ALL PRIVILEGES ON p2 FROM test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'tables_priv' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on procedure to user with table locked"); REVOKE ALL PRIVILEGES ON t1 FROM test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'tables_priv' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on table to user with table locked"); REVOKE USAGE ON *.* FROM test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'db' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("REVOKE USAGE ON *.* TO test_2 with table locked"); RENAME USER test_2@localhost TO test_3@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'db' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("RENAME USER test_2 TO test_3 with table locked"); UNLOCK TABLE; RENAME USER test_2@localhost TO test_3@localhost; LOCK TABLE t1 WRITE; DROP USER test_3@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'db' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("DROP USER test_3@localhost with table locked"); UNLOCK TABLE; CREATE DATABASE db; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 54306bb0e7e..96195d4e1ea 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -60,6 +60,7 @@ #define MAX_SCRAMBLE_LENGTH 1024 bool mysql_user_table_is_in_short_password_format= false; +bool using_global_priv_table= true; static LEX_CSTRING native_password_plugin_name= { STRING_WITH_LEN("mysql_native_password") @@ -676,7 +677,6 @@ HASH *Sp_handler_package_body::get_priv_hash() const */ enum enum_acl_tables { - USER_TABLE, DB_TABLE, TABLES_PRIV_TABLE, COLUMNS_PRIV_TABLE, @@ -685,7 +685,7 @@ enum enum_acl_tables PROCS_PRIV_TABLE, PROXIES_PRIV_TABLE, ROLES_MAPPING_TABLE, - TABLES_MAX // <== always the last + USER_TABLE // <== always the last }; // bits for open_grant_tables static const int Table_user= 1 << USER_TABLE; @@ -697,16 +697,17 @@ static const int Table_procs_priv= 1 << PROCS_PRIV_TABLE; static const int Table_proxies_priv= 1 << PROXIES_PRIV_TABLE; static const int Table_roles_mapping= 1 << ROLES_MAPPING_TABLE; -static LEX_CSTRING MYSQL_TABLE_NAME[TABLES_MAX]= { - {STRING_WITH_LEN("user")}, +static LEX_CSTRING MYSQL_TABLE_NAME[USER_TABLE+1]= { {STRING_WITH_LEN("db")}, {STRING_WITH_LEN("tables_priv")}, {STRING_WITH_LEN("columns_priv")}, {STRING_WITH_LEN("host")}, {STRING_WITH_LEN("procs_priv")}, {STRING_WITH_LEN("proxies_priv")}, - {STRING_WITH_LEN("roles_mapping")} + {STRING_WITH_LEN("roles_mapping")}, + {STRING_WITH_LEN("global_priv")} }; +static LEX_CSTRING MYSQL_TABLE_NAME_USER={STRING_WITH_LEN("user")}; /** Choose from either native or old password plugins when assigning a password @@ -814,6 +815,57 @@ class User_table: public Grant_table_base return Grant_table_base::init_read_record(info) || setup_sysvars(); } + virtual LEX_CSTRING& name() const = 0; + virtual void get_auth(THD *, MEM_ROOT *, const char **, const char **) const= 0; + virtual void set_auth(const char *, size_t, const char *, size_t) const = 0; + virtual ulong get_access() const = 0; + virtual void set_access(ulong rights, bool revoke) const = 0; + + char *get_host(MEM_ROOT *root) const + { return ::get_field(root, m_table->field[0]); } + int set_host(const char *s, size_t l) const + { return m_table->field[0]->store(s, l, system_charset_info); }; + char *get_user(MEM_ROOT *root) const + { return ::get_field(root, m_table->field[1]); } + int set_user(const char *s, size_t l) const + { return m_table->field[1]->store(s, l, system_charset_info); }; + + virtual SSL_type get_ssl_type () const = 0; + virtual int set_ssl_type (SSL_type x) const = 0; + virtual const char* get_ssl_cipher (MEM_ROOT *root) const = 0; + virtual int set_ssl_cipher (const char *s, size_t l) const = 0; + virtual const char* get_x509_issuer (MEM_ROOT *root) const = 0; + virtual int set_x509_issuer (const char *s, size_t l) const = 0; + virtual const char* get_x509_subject (MEM_ROOT *root) const = 0; + virtual int set_x509_subject (const char *s, size_t l) const = 0; + virtual longlong get_max_questions () const = 0; + virtual int set_max_questions (longlong x) const = 0; + virtual longlong get_max_updates () const = 0; + virtual int set_max_updates (longlong x) const = 0; + virtual longlong get_max_connections () const = 0; + virtual int set_max_connections (longlong x) const = 0; + virtual longlong get_max_user_connections () const = 0; + virtual int set_max_user_connections (longlong x) const = 0; + virtual double get_max_statement_time () const = 0; + virtual int set_max_statement_time (double x) const = 0; + virtual bool get_is_role () const = 0; + virtual int set_is_role (bool x) const = 0; + virtual const char* get_default_role (MEM_ROOT *root) const = 0; + virtual int set_default_role (const char *s, size_t l) const = 0; + + virtual ~User_table() {} + private: + friend class Grant_tables; + virtual int setup_sysvars() const = 0; +}; + +/* MySQL-3.23 to MariaDB 10.3 `user` table */ +class User_table_tabular: public User_table +{ + public: + + LEX_CSTRING& name() const { return MYSQL_TABLE_NAME_USER; } + void get_auth(THD *thd, MEM_ROOT *root, const char **plugin, const char **authstr) const { if (have_password()) @@ -914,15 +966,6 @@ class User_table: public Grant_table_base } } - char *get_host(MEM_ROOT *root) const - { return ::get_field(root, m_table->field[0]); } - int set_host(const char *s, size_t l) const - { return m_table->field[0]->store(s, l, system_charset_info); }; - char *get_user(MEM_ROOT *root) const - { return ::get_field(root, m_table->field[1]); } - int set_user(const char *s, size_t l) const - { return m_table->field[1]->store(s, l, system_charset_info); }; - SSL_type get_ssl_type () const { Field *f= get_field(end_priv_columns, MYSQL_TYPE_ENUM); @@ -1056,11 +1099,12 @@ class User_table: public Grant_table_base return 1; }; + virtual ~User_table_tabular() {} private: friend class Grant_tables; /* Only Grant_tables can instantiate this class. */ - User_table() {} + User_table_tabular() {} /* The user table is a bit different compared to the other Grant tables. Usually, we only add columns to the grant tables when adding functionality. @@ -1084,6 +1128,7 @@ class User_table: public Grant_table_base { username_char_length= MY_MIN(m_table->field[1]->char_length(), USERNAME_CHAR_LENGTH); + using_global_priv_table= false; if (have_password()) // Password column might be missing. (MySQL 5.7.6+) { @@ -1140,6 +1185,48 @@ class User_table: public Grant_table_base Field* authstr() const { return get_field(end_priv_columns + 9, MYSQL_TYPE_BLOB); } }; +/* MariaDB 10.4 and up `global_priv` table */ +class User_table_json: public User_table +{ + LEX_CSTRING& name() const { return MYSQL_TABLE_NAME[USER_TABLE]; } + void get_auth(THD *, MEM_ROOT *, const char **, const char **) const + { DBUG_ASSERT(0); } + void set_auth(const char *, size_t, const char *, size_t) const + { DBUG_ASSERT(0); } + ulong get_access() const + { DBUG_ASSERT(0); return 0; } + void set_access(ulong rights, bool revoke) const + { DBUG_ASSERT(0); } + + SSL_type get_ssl_type () const { DBUG_ASSERT(0); return SSL_TYPE_NONE; } + int set_ssl_type (SSL_type x) const { DBUG_ASSERT(0); return 0; } + const char* get_ssl_cipher (MEM_ROOT *root) const { DBUG_ASSERT(0); return 0; } + int set_ssl_cipher (const char *s, size_t l) const { DBUG_ASSERT(0); return 0; } + const char* get_x509_issuer (MEM_ROOT *root) const { DBUG_ASSERT(0); return 0; } + int set_x509_issuer (const char *s, size_t l) const { DBUG_ASSERT(0); return 0; } + const char* get_x509_subject (MEM_ROOT *root) const { DBUG_ASSERT(0); return 0; } + int set_x509_subject (const char *s, size_t l) const { DBUG_ASSERT(0); return 0; } + longlong get_max_questions () const { DBUG_ASSERT(0); return 0; } + int set_max_questions (longlong x) const { DBUG_ASSERT(0); return 0; } + longlong get_max_updates () const { DBUG_ASSERT(0); return 0; } + int set_max_updates (longlong x) const { DBUG_ASSERT(0); return 0; } + longlong get_max_connections () const { DBUG_ASSERT(0); return 0; } + int set_max_connections (longlong x) const { DBUG_ASSERT(0); return 0; } + longlong get_max_user_connections () const { DBUG_ASSERT(0); return 0; } + int set_max_user_connections (longlong x) const { DBUG_ASSERT(0); return 0; } + double get_max_statement_time () const { DBUG_ASSERT(0); return 0; } + int set_max_statement_time (double x) const { DBUG_ASSERT(0); return 0; } + bool get_is_role () const { DBUG_ASSERT(0); return 0; } + int set_is_role (bool x) const { DBUG_ASSERT(0); return 0; } + const char* get_default_role (MEM_ROOT *root) const { DBUG_ASSERT(0); return 0; } + int set_default_role (const char *s, size_t l) const { DBUG_ASSERT(0); return 0; } + + ~User_table_json() {} + private: + friend class Grant_tables; + int setup_sysvars() const { DBUG_ASSERT(0); return 1; } +}; + class Db_table: public Grant_table_base { public: @@ -1255,67 +1342,63 @@ class Roles_mapping_table: public Grant_table_base class Grant_tables { public: - Grant_tables() { } - - /* Before any operation is possible on grant tables, they must be opened. - This opens the tables according to the lock type specified during - construction. + Grant_tables() : p_user_table(&m_user_table_json) { } - @retval 1 replication filters matched. Abort the operation, - but return OK (!) - @retval 0 tables were opened successfully - @retval -1 error, tables could not be opened - */ int open_and_lock(THD *thd, int which_tables, enum thr_lock_type lock_type) { DBUG_ENTER("Grant_tables::open_and_lock"); - TABLE_LIST tables[TABLES_MAX], *first= NULL; + TABLE_LIST tables[USER_TABLE+1], *first= NULL; DBUG_ASSERT(which_tables); /* At least one table must be opened. */ - for (int i=TABLES_MAX-1; i >=0; i--) + /* + We can read privilege tables even when !initialized. + This can be acl_load() - server startup or FLUSH PRIVILEGES + */ + if (lock_type >= TL_WRITE_ALLOW_WRITE && !initialized) + { + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables"); + DBUG_RETURN(-1); + } + + for (int i=USER_TABLE; i >=0; i--) { TABLE_LIST *tl= tables + i; if (which_tables & (1 << i)) { tl->init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_TABLE_NAME[i], NULL, lock_type); - tl->open_type= OT_BASE_ONLY; tl->updating= lock_type >= TL_WRITE_ALLOW_WRITE; - tl->open_strategy= i >= FIRST_OPTIONAL_TABLE - ? TABLE_LIST::OPEN_IF_EXISTS : TABLE_LIST::OPEN_NORMAL; + if (i >= FIRST_OPTIONAL_TABLE) + tl->open_strategy= TABLE_LIST::OPEN_IF_EXISTS; tl->next_global= tl->next_local= first; first= tl; } else tl->table= NULL; } -#ifdef HAVE_REPLICATION - if (lock_type >= TL_WRITE_ALLOW_WRITE && - thd->slave_thread && !thd->spcont) + + uint counter; + int res= really_open(thd, first, &counter); + + /* if User_table_json wasn't found, let's try User_table_tabular */ + if (!res && (which_tables & Table_user) && !(tables[USER_TABLE].table)) { - /* - GRANT and REVOKE are applied the slave in/exclusion rules as they are - some kind of updates to the mysql.% tables. - */ - Rpl_filter *rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter; - if (rpl_filter->is_on() && !rpl_filter->tables_ok(0, first)) - DBUG_RETURN(1); + uint unused; + TABLE_LIST *tl= tables + USER_TABLE; + tl->init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_TABLE_NAME_USER, + NULL, lock_type); + tl->updating= lock_type >= TL_WRITE_ALLOW_WRITE; + p_user_table= &m_user_table_tabular; + counter++; + res= really_open(thd, tl, &unused); } -#endif - if (open_and_lock_tables(thd, first, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT)) - DBUG_RETURN(-1); + if (res) + DBUG_RETURN(res); - /* - We can read privilege tables even when !initialized. - This can be acl_load() - server startup or FLUSH PRIVILEGES - */ - if (lock_type >= TL_WRITE_ALLOW_WRITE && !initialized) - { - my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables"); + if (lock_tables(thd, first, counter, MYSQL_LOCK_IGNORE_TIMEOUT)) DBUG_RETURN(-1); - } - m_user_table.set_table(tables[USER_TABLE].table); + p_user_table->set_table(tables[USER_TABLE].table); m_db_table.set_table(tables[DB_TABLE].table); m_tables_priv_table.set_table(tables[TABLES_PRIV_TABLE].table); m_columns_priv_table.set_table(tables[COLUMNS_PRIV_TABLE].table); @@ -1327,7 +1410,7 @@ class Grant_tables } inline const User_table& user_table() const - { return m_user_table; } + { return *p_user_table; } inline const Db_table& db_table() const { return m_db_table; } @@ -1351,7 +1434,38 @@ class Grant_tables { return m_roles_mapping_table; } private: - User_table m_user_table; + + /* Before any operation is possible on grant tables, they must be opened. + + @retval 1 replication filters matched. Abort the operation, + but return OK (!) + @retval 0 tables were opened successfully + @retval -1 error, tables could not be opened + */ + int really_open(THD *thd, TABLE_LIST* tables, uint *counter) + { + DBUG_ENTER("Grant_tables::really_open:"); +#ifdef HAVE_REPLICATION + if (tables->lock_type >= TL_WRITE_ALLOW_WRITE && + thd->slave_thread && !thd->spcont) + { + /* + GRANT and REVOKE are applied the slave in/exclusion rules as they are + some kind of updates to the mysql.% tables. + */ + Rpl_filter *rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter; + if (rpl_filter->is_on() && !rpl_filter->tables_ok(0, tables)) + DBUG_RETURN(1); + } +#endif + if (open_tables(thd, &tables, counter, MYSQL_LOCK_IGNORE_TIMEOUT)) + DBUG_RETURN(-1); + DBUG_RETURN(0); + } + + User_table *p_user_table; + User_table_json m_user_table_json; + User_table_tabular m_user_table_tabular; Db_table m_db_table; Tables_priv_table m_tables_priv_table; Columns_priv_table m_columns_priv_table; @@ -3105,7 +3219,7 @@ bool change_password(THD *thd, LEX_USER *user) save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); if (WSREP(thd) && !IF_WSREP(thd->wsrep_applier, 0)) - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, (char*)"user", NULL); + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); if ((result= tables.open_and_lock(thd, Table_user, TL_WRITE))) DBUG_RETURN(result != 1); @@ -3228,7 +3342,7 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, { thd->set_query(buff, query_length, system_charset_info); // Attention!!! here is implicit goto error; - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, (char*)"user", NULL); + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); } /* @@ -3759,7 +3873,8 @@ static int replace_user_table(THD *thd, const User_table &user_table, if (user_table.set_is_role(true)) { my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), - "user", ROLE_ASSIGN_COLUMN_IDX + 1, user_table.num_fields(), + user_table.name().str, + ROLE_ASSIGN_COLUMN_IDX + 1, user_table.num_fields(), static_cast<int>(table->s->mysql_version), MYSQL_VERSION_ID); goto end; } |