Commit a76aadf7 authored by Sergei Golubchik's avatar Sergei Golubchik

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.
parent 9887d2e8
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'; SHOW VARIABLES like 'slave_skip_errors';
Variable_name Value Variable_name Value
slave_skip_errors OFF slave_skip_errors OFF
...@@ -16,7 +16,7 @@ DROP TABLE IF EXISTS t1; ...@@ -16,7 +16,7 @@ DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT); CREATE TABLE t1 (c1 INT);
LOCK TABLES t1 READ; LOCK TABLES t1 READ;
FLUSH PRIVILEGES; FLUSH PRIVILEGES;
ERROR HY000: Table 'user' was not locked with LOCK TABLES ERROR HY000: Table 'db' was not locked with LOCK TABLES
UNLOCK TABLES; UNLOCK TABLES;
DROP TABLE t1; DROP TABLE t1;
# #
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# End of 4.1 tests # 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 # Bug#43835: SHOW VARIABLES does not include 0 for slave_skip_errors
......
...@@ -327,34 +327,34 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0 ...@@ -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,0,DISCONNECT,,,0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',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,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,db,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, 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,columns_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_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,proxies_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, 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,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,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,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,WRITE,mysql,user,
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1 = PASSWORD(*****)',0 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,db,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, 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,columns_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_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,proxies_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, 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,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,db,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, 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,columns_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_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,proxies_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, 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,'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,'create table t1(id int)',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop table t1',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop table t1',0
......
...@@ -316,34 +316,34 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0 ...@@ -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,0,DISCONNECT,,,0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',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,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,db,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, 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,columns_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_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,proxies_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, 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,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,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,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,WRITE,mysql,user,
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1 = PASSWORD(*****)',0 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,db,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, 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,columns_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_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,proxies_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, 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,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,db,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, 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,columns_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_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,proxies_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, 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,'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,'create table t1(id int)',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop table t1',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop table t1',0
......
...@@ -145,43 +145,43 @@ UNLOCK TABLE; ...@@ -145,43 +145,43 @@ UNLOCK TABLE;
DROP DATABASE mysqltest2; DROP DATABASE mysqltest2;
LOCK TABLE t1 WRITE; LOCK TABLE t1 WRITE;
CREATE USER test_1@localhost; 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"); INSERT INTO t2 VALUES ("CREATE USER test_1@localhost with table locked");
UNLOCK TABLE; UNLOCK TABLE;
CREATE USER test_2@localhost; CREATE USER test_2@localhost;
LOCK TABLE t1 WRITE; LOCK TABLE t1 WRITE;
GRANT SELECT ON t1 TO test_2@localhost; 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"); INSERT INTO t2 VALUES ("GRANT select on table to user with table locked");
GRANT ALL ON f2 TO test_2@localhost; 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"); INSERT INTO t2 VALUES ("GRANT ALL ON f2 TO test_2 with table locked");
GRANT ALL ON p2 TO test_2@localhost; 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"); INSERT INTO t2 VALUES ("GRANT ALL ON p2 TO test_2 with table locked");
GRANT USAGE ON *.* TO test_2@localhost; 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"); INSERT INTO t2 VALUES ("GRANT USAGE ON *.* TO test_2 with table locked");
REVOKE ALL PRIVILEGES ON f2 FROM test_2@localhost; 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"); INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on function to user with table locked");
REVOKE ALL PRIVILEGES ON p2 FROM test_2@localhost; 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"); INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on procedure to user with table locked");
REVOKE ALL PRIVILEGES ON t1 FROM test_2@localhost; 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"); INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on table to user with table locked");
REVOKE USAGE ON *.* FROM test_2@localhost; 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"); INSERT INTO t2 VALUES ("REVOKE USAGE ON *.* TO test_2 with table locked");
RENAME USER test_2@localhost TO test_3@localhost; 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"); INSERT INTO t2 VALUES ("RENAME USER test_2 TO test_3 with table locked");
UNLOCK TABLE; UNLOCK TABLE;
RENAME USER test_2@localhost TO test_3@localhost; RENAME USER test_2@localhost TO test_3@localhost;
LOCK TABLE t1 WRITE; LOCK TABLE t1 WRITE;
DROP USER test_3@localhost; 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"); INSERT INTO t2 VALUES ("DROP USER test_3@localhost with table locked");
UNLOCK TABLE; UNLOCK TABLE;
CREATE DATABASE db; CREATE DATABASE db;
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#define MAX_SCRAMBLE_LENGTH 1024 #define MAX_SCRAMBLE_LENGTH 1024
bool mysql_user_table_is_in_short_password_format= false; bool mysql_user_table_is_in_short_password_format= false;
bool using_global_priv_table= true;
static LEX_CSTRING native_password_plugin_name= { static LEX_CSTRING native_password_plugin_name= {
STRING_WITH_LEN("mysql_native_password") STRING_WITH_LEN("mysql_native_password")
...@@ -676,7 +677,6 @@ HASH *Sp_handler_package_body::get_priv_hash() const ...@@ -676,7 +677,6 @@ HASH *Sp_handler_package_body::get_priv_hash() const
*/ */
enum enum_acl_tables enum enum_acl_tables
{ {
USER_TABLE,
DB_TABLE, DB_TABLE,
TABLES_PRIV_TABLE, TABLES_PRIV_TABLE,
COLUMNS_PRIV_TABLE, COLUMNS_PRIV_TABLE,
...@@ -685,7 +685,7 @@ enum enum_acl_tables ...@@ -685,7 +685,7 @@ enum enum_acl_tables
PROCS_PRIV_TABLE, PROCS_PRIV_TABLE,
PROXIES_PRIV_TABLE, PROXIES_PRIV_TABLE,
ROLES_MAPPING_TABLE, ROLES_MAPPING_TABLE,
TABLES_MAX // <== always the last USER_TABLE // <== always the last
}; };
// bits for open_grant_tables // bits for open_grant_tables
static const int Table_user= 1 << USER_TABLE; static const int Table_user= 1 << USER_TABLE;
...@@ -697,16 +697,17 @@ static const int Table_procs_priv= 1 << PROCS_PRIV_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_proxies_priv= 1 << PROXIES_PRIV_TABLE;
static const int Table_roles_mapping= 1 << ROLES_MAPPING_TABLE; static const int Table_roles_mapping= 1 << ROLES_MAPPING_TABLE;
static LEX_CSTRING MYSQL_TABLE_NAME[TABLES_MAX]= { static LEX_CSTRING MYSQL_TABLE_NAME[USER_TABLE+1]= {
{STRING_WITH_LEN("user")},
{STRING_WITH_LEN("db")}, {STRING_WITH_LEN("db")},
{STRING_WITH_LEN("tables_priv")}, {STRING_WITH_LEN("tables_priv")},
{STRING_WITH_LEN("columns_priv")}, {STRING_WITH_LEN("columns_priv")},
{STRING_WITH_LEN("host")}, {STRING_WITH_LEN("host")},
{STRING_WITH_LEN("procs_priv")}, {STRING_WITH_LEN("procs_priv")},
{STRING_WITH_LEN("proxies_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 Choose from either native or old password plugins when assigning a password
...@@ -814,6 +815,57 @@ class User_table: public Grant_table_base ...@@ -814,6 +815,57 @@ class User_table: public Grant_table_base
return Grant_table_base::init_read_record(info) || setup_sysvars(); 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 void get_auth(THD *thd, MEM_ROOT *root, const char **plugin, const char **authstr) const
{ {
if (have_password()) if (have_password())
...@@ -914,15 +966,6 @@ class User_table: public Grant_table_base ...@@ -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 SSL_type get_ssl_type () const
{ {
Field *f= get_field(end_priv_columns, MYSQL_TYPE_ENUM); Field *f= get_field(end_priv_columns, MYSQL_TYPE_ENUM);
...@@ -1056,11 +1099,12 @@ class User_table: public Grant_table_base ...@@ -1056,11 +1099,12 @@ class User_table: public Grant_table_base
return 1; return 1;
}; };
virtual ~User_table_tabular() {}
private: private:
friend class Grant_tables; friend class Grant_tables;
/* Only Grant_tables can instantiate this class. */ /* 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. /* 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. Usually, we only add columns to the grant tables when adding functionality.
...@@ -1084,6 +1128,7 @@ class User_table: public Grant_table_base ...@@ -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= MY_MIN(m_table->field[1]->char_length(),
USERNAME_CHAR_LENGTH); USERNAME_CHAR_LENGTH);
using_global_priv_table= false;
if (have_password()) // Password column might be missing. (MySQL 5.7.6+) if (have_password()) // Password column might be missing. (MySQL 5.7.6+)
{ {
...@@ -1140,6 +1185,48 @@ class User_table: public Grant_table_base ...@@ -1140,6 +1185,48 @@ class User_table: public Grant_table_base
Field* authstr() const { return get_field(end_priv_columns + 9, MYSQL_TYPE_BLOB); } 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 class Db_table: public Grant_table_base
{ {
public: public:
...@@ -1255,67 +1342,63 @@ class Roles_mapping_table: public Grant_table_base ...@@ -1255,67 +1342,63 @@ class Roles_mapping_table: public Grant_table_base
class Grant_tables class Grant_tables
{ {
public: public:
Grant_tables() { } Grant_tables() : p_user_table(&m_user_table_json) { }
/* Before any operation is possible on grant tables, they must be opened.
This opens the tables according to the lock type specified during
construction.
@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) int open_and_lock(THD *thd, int which_tables, enum thr_lock_type lock_type)
{ {
DBUG_ENTER("Grant_tables::open_and_lock"); 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. */ 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; TABLE_LIST *tl= tables + i;
if (which_tables & (1 << i)) if (which_tables & (1 << i))
{ {
tl->init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_TABLE_NAME[i], tl->init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_TABLE_NAME[i],
NULL, lock_type); NULL, lock_type);
tl->open_type= OT_BASE_ONLY;
tl->updating= lock_type >= TL_WRITE_ALLOW_WRITE; tl->updating= lock_type >= TL_WRITE_ALLOW_WRITE;
tl->open_strategy= i >= FIRST_OPTIONAL_TABLE if (i >= FIRST_OPTIONAL_TABLE)
? TABLE_LIST::OPEN_IF_EXISTS : TABLE_LIST::OPEN_NORMAL; tl->open_strategy= TABLE_LIST::OPEN_IF_EXISTS;
tl->next_global= tl->next_local= first; tl->next_global= tl->next_local= first;
first= tl; first= tl;
} }
else else
tl->table= NULL; tl->table= NULL;
} }
#ifdef HAVE_REPLICATION
if (lock_type >= TL_WRITE_ALLOW_WRITE && uint counter;
thd->slave_thread && !thd->spcont) 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))
{ {
/* uint unused;
GRANT and REVOKE are applied the slave in/exclusion rules as they are TABLE_LIST *tl= tables + USER_TABLE;
some kind of updates to the mysql.% tables. tl->init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_TABLE_NAME_USER,
*/ NULL, lock_type);
Rpl_filter *rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter; tl->updating= lock_type >= TL_WRITE_ALLOW_WRITE;
if (rpl_filter->is_on() && !rpl_filter->tables_ok(0, first)) p_user_table= &m_user_table_tabular;
DBUG_RETURN(1); counter++;
res= really_open(thd, tl, &unused);
} }
#endif if (res)
if (open_and_lock_tables(thd, first, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT)) DBUG_RETURN(res);
DBUG_RETURN(-1);
/* if (lock_tables(thd, first, counter, MYSQL_LOCK_IGNORE_TIMEOUT))
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); 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_db_table.set_table(tables[DB_TABLE].table);
m_tables_priv_table.set_table(tables[TABLES_PRIV_TABLE].table); m_tables_priv_table.set_table(tables[TABLES_PRIV_TABLE].table);
m_columns_priv_table.set_table(tables[COLUMNS_PRIV_TABLE].table); m_columns_priv_table.set_table(tables[COLUMNS_PRIV_TABLE].table);
...@@ -1327,7 +1410,7 @@ class Grant_tables ...@@ -1327,7 +1410,7 @@ class Grant_tables
} }
inline const User_table& user_table() const inline const User_table& user_table() const
{ return m_user_table; } { return *p_user_table; }
inline const Db_table& db_table() const inline const Db_table& db_table() const
{ return m_db_table; } { return m_db_table; }
...@@ -1351,7 +1434,38 @@ class Grant_tables ...@@ -1351,7 +1434,38 @@ class Grant_tables
{ return m_roles_mapping_table; } { return m_roles_mapping_table; }
private: 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; Db_table m_db_table;
Tables_priv_table m_tables_priv_table; Tables_priv_table m_tables_priv_table;
Columns_priv_table m_columns_priv_table; Columns_priv_table m_columns_priv_table;
...@@ -3105,7 +3219,7 @@ bool change_password(THD *thd, LEX_USER *user) ...@@ -3105,7 +3219,7 @@ bool change_password(THD *thd, LEX_USER *user)
save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
if (WSREP(thd) && !IF_WSREP(thd->wsrep_applier, 0)) 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))) if ((result= tables.open_and_lock(thd, Table_user, TL_WRITE)))
DBUG_RETURN(result != 1); DBUG_RETURN(result != 1);
...@@ -3228,7 +3342,7 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, ...@@ -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); thd->set_query(buff, query_length, system_charset_info);
// Attention!!! here is implicit goto error; // 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, ...@@ -3759,7 +3873,8 @@ static int replace_user_table(THD *thd, const User_table &user_table,
if (user_table.set_is_role(true)) if (user_table.set_is_role(true))
{ {
my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), 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); static_cast<int>(table->s->mysql_version), MYSQL_VERSION_ID);
goto end; goto end;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment