github.com/dolthub/go-mysql-server@v0.18.0/enginetest/queries/priv_auth_queries.go (about)

     1  // Copyright 2022 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package queries
    16  
    17  import (
    18  	"testing"
    19  	"time"
    20  
    21  	"gopkg.in/src-d/go-errors.v1"
    22  
    23  	sqle "github.com/dolthub/go-mysql-server"
    24  	"github.com/dolthub/go-mysql-server/sql"
    25  	"github.com/dolthub/go-mysql-server/sql/mysql_db"
    26  	"github.com/dolthub/go-mysql-server/sql/plan"
    27  	"github.com/dolthub/go-mysql-server/sql/types"
    28  )
    29  
    30  // UserPrivilegeTest is used to define a test on the user and privilege systems. These tests always have the root
    31  // account available, and the root account is used with any queries in the SetUpScript.
    32  type UserPrivilegeTest struct {
    33  	Name        string
    34  	SetUpScript []string
    35  	Assertions  []UserPrivilegeTestAssertion
    36  }
    37  
    38  // UserPrivilegeTestAssertion is within a UserPrivilegeTest to assert functionality.
    39  type UserPrivilegeTestAssertion struct {
    40  	User           string
    41  	Host           string
    42  	Query          string
    43  	Expected       []sql.Row
    44  	ExpectedErr    *errors.Kind
    45  	ExpectedErrStr string
    46  }
    47  
    48  // QuickPrivilegeTest specifically tests privileges on a predefined user (tester@localhost) using predefined tables and
    49  // databases. Every test here can easily be represented by a UserPrivilegeTest, however this is intended to test
    50  // specific privileges at a large scale, meaning there may be thousands of these tests, and hence the test data should
    51  // be as small as possible.
    52  //
    53  // All queries will be run as a root user with full privileges (intended for setup), with the last query running as the
    54  // testing user (tester@localhost). For example, the first query may grant a SELECT privilege, while the second query
    55  // is the SELECT query. Of note, the current database as set by the context is retained when switching from the root
    56  // user to the test user. This does not mean that the test user automatically gains access to the database, but this is
    57  // used for any queries that (incorrectly) only work with the current database.
    58  //
    59  // ExpectingErr should be set when an error is expected, and it does not matter what the error is so long that it is one
    60  // of the errors related to privilege checking (meaning a failed INSERT due to a missing column is NOT caught). If
    61  // ExpectingErr is set and an error is given to ExpectedErr, then it is enforced that the error matches. However, if
    62  // ExpectingErr is set and ExpectedErr is nil, then any privilege checking error will match.
    63  //
    64  // Expected makes a distinction between the nil value and the empty value. A nil value means that we do not care about
    65  // the result, only that it did not error (unless one of the error-asserting fields are set). A non-nil value asserts
    66  // that the returned value matches our Expected value. If the returned value is nil, then we make a special case to
    67  // match the non-nil empty row with it, due to the aforementioned distinction.
    68  //
    69  // Statements that are run before every test (the state that all tests start with):
    70  // CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY, v1 BIGINT);
    71  // CREATE TABLE mydb.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT);
    72  // CREATE TABLE otherdb.test (pk BIGINT PRIMARY KEY, v1 BIGINT);
    73  // CREATE TABLE otherdb.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT);
    74  // INSERT INTO mydb.test VALUES (0, 0), (1, 1);
    75  // INSERT INTO mydb.test2 VALUES (0, 1), (1, 2);
    76  // INSERT INTO otherdb.test VALUES (1, 1), (2, 2);
    77  // INSERT INTO otherdb.test2 VALUES (1, 1), (2, 2);
    78  type QuickPrivilegeTest struct {
    79  	Queries      []string
    80  	Expected     []sql.Row
    81  	ExpectedErr  *errors.Kind
    82  	ExpectingErr bool
    83  }
    84  
    85  // ServerAuthenticationTest is used to define a test on the server authentication system. These tests always have the
    86  // root account available, and the root account is used with any queries in the SetUpScript. The SetUpFunc is run before
    87  // the SetUpScript.
    88  type ServerAuthenticationTest struct {
    89  	Name        string
    90  	SetUpFunc   func(ctx *sql.Context, t *testing.T, engine *sqle.Engine)
    91  	SetUpScript []string
    92  	Assertions  []ServerAuthenticationTestAssertion
    93  }
    94  
    95  // ServerAuthenticationTestAssertion is within a ServerAuthenticationTest to assert functionality.
    96  type ServerAuthenticationTestAssertion struct {
    97  	Username        string
    98  	Password        string
    99  	Query           string
   100  	ExpectedErr     bool
   101  	ExpectedErrKind *errors.Kind
   102  	ExpectedErrStr  string
   103  }
   104  
   105  // UserPrivTests test the user and privilege systems. These tests always have the root account available, and the root
   106  // account is used with any queries in the SetUpScript.
   107  var UserPrivTests = []UserPrivilegeTest{
   108  	{
   109  		Name: "Binlog replication privileges",
   110  		SetUpScript: []string{
   111  			"CREATE USER user@localhost;",
   112  			"CREATE USER 'replica-admin'@localhost;",
   113  			"CREATE USER 'replica-client'@localhost;",
   114  			"CREATE USER 'replica-reload'@localhost;",
   115  			// REPLICATION_SLAVE_ADMIN allows: start replica,
   116  			"GRANT REPLICATION_SLAVE_ADMIN ON *.* TO 'replica-admin'@localhost;",
   117  			// REPLICATION CLIENT allows: show replica status
   118  			"GRANT REPLICATION CLIENT ON *.* to 'replica-client'@localhost;",
   119  			// RELOAD allows: reset replica
   120  			"GRANT RELOAD ON *.* TO 'replica-reload'@localhost;",
   121  		},
   122  		Assertions: []UserPrivilegeTestAssertion{
   123  			// START REPLICA
   124  			{
   125  				User:        "user",
   126  				Host:        "localhost",
   127  				Query:       "START REPLICA",
   128  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   129  			},
   130  			{
   131  				// ErrNoReplicationController means the priv check passed
   132  				User:        "replica-admin",
   133  				Host:        "localhost",
   134  				Query:       "START REPLICA",
   135  				ExpectedErr: plan.ErrNoReplicationController,
   136  			},
   137  			{
   138  				User:        "replica-client",
   139  				Host:        "localhost",
   140  				Query:       "START REPLICA",
   141  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   142  			},
   143  			{
   144  				User:        "replica-reload",
   145  				Host:        "localhost",
   146  				Query:       "START REPLICA",
   147  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   148  			},
   149  			{
   150  				User:        "root",
   151  				Host:        "localhost",
   152  				Query:       "START REPLICA",
   153  				ExpectedErr: plan.ErrNoReplicationController,
   154  			},
   155  
   156  			// STOP REPLICA
   157  			{
   158  				User:        "user",
   159  				Host:        "localhost",
   160  				Query:       "STOP REPLICA",
   161  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   162  			},
   163  			{
   164  				// ErrNoReplicationController means the priv check passed
   165  				User:        "replica-admin",
   166  				Host:        "localhost",
   167  				Query:       "STOP REPLICA",
   168  				ExpectedErr: plan.ErrNoReplicationController,
   169  			},
   170  			{
   171  				User:        "replica-client",
   172  				Host:        "localhost",
   173  				Query:       "STOP REPLICA",
   174  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   175  			},
   176  			{
   177  				User:        "replica-reload",
   178  				Host:        "localhost",
   179  				Query:       "STOP REPLICA",
   180  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   181  			},
   182  			{
   183  				User:        "root",
   184  				Host:        "localhost",
   185  				Query:       "STOP REPLICA",
   186  				ExpectedErr: plan.ErrNoReplicationController,
   187  			},
   188  
   189  			// RESET REPLICA
   190  			{
   191  				User:        "user",
   192  				Host:        "localhost",
   193  				Query:       "RESET REPLICA",
   194  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   195  			},
   196  			{
   197  				User:        "replica-admin",
   198  				Host:        "localhost",
   199  				Query:       "RESET REPLICA",
   200  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   201  			},
   202  			{
   203  				User:        "replica-client",
   204  				Host:        "localhost",
   205  				Query:       "RESET REPLICA",
   206  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   207  			},
   208  			{
   209  				// ErrNoReplicationController means the priv check passed
   210  				User:        "replica-reload",
   211  				Host:        "localhost",
   212  				Query:       "RESET REPLICA",
   213  				ExpectedErr: plan.ErrNoReplicationController,
   214  			},
   215  			{
   216  				User:        "root",
   217  				Host:        "localhost",
   218  				Query:       "RESET REPLICA",
   219  				ExpectedErr: plan.ErrNoReplicationController,
   220  			},
   221  
   222  			// SHOW REPLICA STATUS
   223  			{
   224  				User:        "user",
   225  				Host:        "localhost",
   226  				Query:       "SHOW REPLICA STATUS;",
   227  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   228  			},
   229  			{
   230  				User:        "replica-admin",
   231  				Host:        "localhost",
   232  				Query:       "SHOW REPLICA STATUS;",
   233  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   234  			},
   235  			{
   236  				User:     "replica-client",
   237  				Host:     "localhost",
   238  				Query:    "SHOW REPLICA STATUS;",
   239  				Expected: []sql.Row{},
   240  			},
   241  			{
   242  				User:        "replica-reload",
   243  				Host:        "localhost",
   244  				Query:       "SHOW REPLICA STATUS;",
   245  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   246  			},
   247  			{
   248  				User:     "root",
   249  				Host:     "localhost",
   250  				Query:    "SHOW REPLICA STATUS;",
   251  				Expected: []sql.Row{},
   252  			},
   253  
   254  			// CHANGE REPLICATION SOURCE
   255  			{
   256  				User:        "user",
   257  				Host:        "localhost",
   258  				Query:       "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';",
   259  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   260  			},
   261  			{
   262  				// ErrNoReplicationController means the priv check passed
   263  				User:        "replica-admin",
   264  				Host:        "localhost",
   265  				Query:       "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';",
   266  				ExpectedErr: plan.ErrNoReplicationController,
   267  			},
   268  			{
   269  				User:        "replica-client",
   270  				Host:        "localhost",
   271  				Query:       "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';",
   272  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   273  			},
   274  			{
   275  				User:        "replica-reload",
   276  				Host:        "localhost",
   277  				Query:       "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';",
   278  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   279  			},
   280  			{
   281  				User:        "root",
   282  				Host:        "localhost",
   283  				Query:       "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';",
   284  				ExpectedErr: plan.ErrNoReplicationController,
   285  			},
   286  
   287  			// CHANGE REPLICATION FILTER
   288  			{
   289  				User:        "user",
   290  				Host:        "localhost",
   291  				Query:       "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);",
   292  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   293  			},
   294  			{
   295  				// ErrNoReplicationController means the priv check passed
   296  				User:        "replica-admin",
   297  				Host:        "localhost",
   298  				Query:       "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);",
   299  				ExpectedErr: plan.ErrNoReplicationController,
   300  			},
   301  			{
   302  				User:        "replica-client",
   303  				Host:        "localhost",
   304  				Query:       "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);",
   305  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   306  			},
   307  			{
   308  				User:        "replica-reload",
   309  				Host:        "localhost",
   310  				Query:       "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);",
   311  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   312  			},
   313  			{
   314  				User:        "root",
   315  				Host:        "localhost",
   316  				Query:       "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);",
   317  				ExpectedErr: plan.ErrNoReplicationController,
   318  			},
   319  		},
   320  	},
   321  	{
   322  		Name: "Basic database and table name visibility",
   323  		SetUpScript: []string{
   324  			"CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY);",
   325  			"INSERT INTO mydb.test VALUES (1);",
   326  			"CREATE USER tester@localhost;",
   327  			"CREATE ROLE test_role;",
   328  			"GRANT SELECT ON mydb.* TO test_role;",
   329  		},
   330  		Assertions: []UserPrivilegeTestAssertion{
   331  			{
   332  				User:        "tester",
   333  				Host:        "localhost",
   334  				Query:       "SELECT * FROM mydb.test;/*1*/",
   335  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
   336  			},
   337  			{
   338  				User:        "tester",
   339  				Host:        "localhost",
   340  				Query:       "SELECT * FROM mydb.test2;/*1*/",
   341  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
   342  			},
   343  			{
   344  				User:     "root",
   345  				Host:     "localhost",
   346  				Query:    "GRANT SELECT ON *.* TO tester@localhost;",
   347  				Expected: []sql.Row{{types.NewOkResult(0)}},
   348  			},
   349  			{
   350  				User:     "tester",
   351  				Host:     "localhost",
   352  				Query:    "SELECT * FROM mydb.test;/*2*/",
   353  				Expected: []sql.Row{{1}},
   354  			},
   355  			{
   356  				User:        "tester",
   357  				Host:        "localhost",
   358  				Query:       "SELECT * FROM mydb.test2;/*2*/",
   359  				ExpectedErr: sql.ErrTableNotFound,
   360  			},
   361  			{
   362  				User:     "root",
   363  				Host:     "localhost",
   364  				Query:    "REVOKE SELECT ON *.* FROM tester@localhost;",
   365  				Expected: []sql.Row{{types.NewOkResult(0)}},
   366  			},
   367  			{ // Ensure we've reverted to initial state (all SELECTs after REVOKEs are doing this)
   368  				User:        "tester",
   369  				Host:        "localhost",
   370  				Query:       "SELECT * FROM mydb.test;/*3*/",
   371  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
   372  			},
   373  			{
   374  				User:        "tester",
   375  				Host:        "localhost",
   376  				Query:       "SELECT * FROM mydb.test2;/*3*/",
   377  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
   378  			},
   379  			{
   380  				User:     "root",
   381  				Host:     "localhost",
   382  				Query:    "GRANT SELECT ON mydb.* TO tester@localhost;",
   383  				Expected: []sql.Row{{types.NewOkResult(0)}},
   384  			},
   385  			{
   386  				User:     "tester",
   387  				Host:     "localhost",
   388  				Query:    "SELECT * FROM mydb.test;/*4*/",
   389  				Expected: []sql.Row{{1}},
   390  			},
   391  			{
   392  				User:        "tester",
   393  				Host:        "localhost",
   394  				Query:       "SELECT * FROM mydb.test2;/*4*/",
   395  				ExpectedErr: sql.ErrTableNotFound,
   396  			},
   397  			{
   398  				User:     "root",
   399  				Host:     "localhost",
   400  				Query:    "REVOKE SELECT ON mydb.* FROM tester@localhost;",
   401  				Expected: []sql.Row{{types.NewOkResult(0)}},
   402  			},
   403  			{
   404  				User:        "tester",
   405  				Host:        "localhost",
   406  				Query:       "SELECT * FROM mydb.test;/*5*/",
   407  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
   408  			},
   409  			{
   410  				User:        "tester",
   411  				Host:        "localhost",
   412  				Query:       "SELECT * FROM mydb.test2;/*5*/",
   413  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
   414  			},
   415  			{
   416  				User:     "root",
   417  				Host:     "localhost",
   418  				Query:    "GRANT SELECT ON mydb.test TO tester@localhost;",
   419  				Expected: []sql.Row{{types.NewOkResult(0)}},
   420  			},
   421  			{
   422  				User:     "tester",
   423  				Host:     "localhost",
   424  				Query:    "SELECT * FROM mydb.test;/*6*/",
   425  				Expected: []sql.Row{{1}},
   426  			},
   427  			{
   428  				User:        "tester",
   429  				Host:        "localhost",
   430  				Query:       "SELECT * FROM mydb.test2;/*6*/",
   431  				ExpectedErr: sql.ErrTableAccessDeniedForUser,
   432  			},
   433  			{
   434  				User:     "root",
   435  				Host:     "localhost",
   436  				Query:    "REVOKE SELECT ON mydb.test FROM tester@localhost;",
   437  				Expected: []sql.Row{{types.NewOkResult(0)}},
   438  			},
   439  			{
   440  				User:        "tester",
   441  				Host:        "localhost",
   442  				Query:       "SELECT * FROM mydb.test;/*7*/",
   443  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
   444  			},
   445  			{
   446  				User:        "tester",
   447  				Host:        "localhost",
   448  				Query:       "SELECT * FROM mydb.test2;/*7*/",
   449  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
   450  			},
   451  			{
   452  				User:     "root",
   453  				Host:     "localhost",
   454  				Query:    "GRANT SELECT ON mydb.test2 TO tester@localhost;",
   455  				Expected: []sql.Row{{types.NewOkResult(0)}},
   456  			},
   457  			{
   458  				User:        "tester",
   459  				Host:        "localhost",
   460  				Query:       "SELECT * FROM mydb.test;/*8*/",
   461  				ExpectedErr: sql.ErrTableAccessDeniedForUser,
   462  			},
   463  			{
   464  				User:        "tester",
   465  				Host:        "localhost",
   466  				Query:       "SELECT * FROM mydb.test2;/*8*/",
   467  				ExpectedErr: sql.ErrTableNotFound,
   468  			},
   469  			{
   470  				User:     "root",
   471  				Host:     "localhost",
   472  				Query:    "REVOKE SELECT ON mydb.test2 FROM tester@localhost;",
   473  				Expected: []sql.Row{{types.NewOkResult(0)}},
   474  			},
   475  			{
   476  				User:        "tester",
   477  				Host:        "localhost",
   478  				Query:       "SELECT * FROM mydb.test;/*9*/",
   479  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
   480  			},
   481  			{
   482  				User:        "tester",
   483  				Host:        "localhost",
   484  				Query:       "SELECT * FROM mydb.test2;/*9*/",
   485  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
   486  			},
   487  			{
   488  				User:     "root",
   489  				Host:     "localhost",
   490  				Query:    "GRANT test_role TO tester@localhost;",
   491  				Expected: []sql.Row{{types.NewOkResult(0)}},
   492  			},
   493  			{
   494  				User:     "tester",
   495  				Host:     "localhost",
   496  				Query:    "SELECT * FROM mydb.test;/*10*/",
   497  				Expected: []sql.Row{{1}},
   498  			},
   499  			{
   500  				User:        "tester",
   501  				Host:        "localhost",
   502  				Query:       "SELECT * FROM mydb.test2;/*10*/",
   503  				ExpectedErr: sql.ErrTableNotFound,
   504  			},
   505  		},
   506  	},
   507  	{
   508  		Name: "Basic user creation",
   509  		SetUpScript: []string{
   510  			"CREATE USER testuser@`127.0.0.1`;",
   511  		},
   512  		Assertions: []UserPrivilegeTestAssertion{
   513  			{
   514  				Query:       "CREATE USER testuser@`127.0.0.1`;",
   515  				ExpectedErr: sql.ErrUserCreationFailure,
   516  			},
   517  			{
   518  				Query:    "CREATE USER IF NOT EXISTS testuser@`127.0.0.1`;",
   519  				Expected: []sql.Row{{types.NewOkResult(0)}},
   520  			},
   521  			{
   522  				Query:    "INSERT INTO mysql.user (Host, User) VALUES ('localhost', 'testuser2');",
   523  				Expected: []sql.Row{{types.NewOkResult(1)}},
   524  			},
   525  			{
   526  				Query: "SELECT * FROM mysql.user WHERE User = 'root';",
   527  				Expected: []sql.Row{
   528  					{
   529  						"localhost",             // Host
   530  						"root",                  // User
   531  						"Y",                     // Select_priv
   532  						"Y",                     // Insert_priv
   533  						"Y",                     // Update_priv
   534  						"Y",                     // Delete_priv
   535  						"Y",                     // Create_priv
   536  						"Y",                     // Drop_priv
   537  						"Y",                     // Reload_priv
   538  						"Y",                     // Shutdown_priv
   539  						"Y",                     // Process_priv
   540  						"Y",                     // File_priv
   541  						"Y",                     // Grant_priv
   542  						"Y",                     // References_priv
   543  						"Y",                     // Index_priv
   544  						"Y",                     // Alter_priv
   545  						"Y",                     // Show_db_priv
   546  						"Y",                     // Super_priv
   547  						"Y",                     // Create_tmp_table_priv
   548  						"Y",                     // Lock_tables_priv
   549  						"Y",                     // Execute_priv
   550  						"Y",                     // Repl_slave_priv
   551  						"Y",                     // Repl_client_priv
   552  						"Y",                     // Create_view_priv
   553  						"Y",                     // Show_view_priv
   554  						"Y",                     // Create_routine_priv
   555  						"Y",                     // Alter_routine_priv
   556  						"Y",                     // Create_user_priv
   557  						"Y",                     // Event_priv
   558  						"Y",                     // Trigger_priv
   559  						"Y",                     // Create_tablespace_priv
   560  						"",                      // ssl_type
   561  						[]byte(""),              // ssl_cipher
   562  						[]byte(""),              // x509_issuer
   563  						[]byte(""),              // x509_subject
   564  						uint32(0),               // max_questions
   565  						uint32(0),               // max_updates
   566  						uint32(0),               // max_connections
   567  						uint32(0),               // max_user_connections
   568  						"mysql_native_password", // plugin
   569  						"",                      // authentication_string
   570  						"N",                     // password_expired
   571  						time.Unix(1, 0).UTC(),   // password_last_changed
   572  						nil,                     // password_lifetime
   573  						"N",                     // account_locked
   574  						"Y",                     // Create_role_priv
   575  						"Y",                     // Drop_role_priv
   576  						nil,                     // Password_reuse_history
   577  						nil,                     // Password_reuse_time
   578  						nil,                     // Password_require_current
   579  						nil,                     // User_attributes
   580  						"",                      // identity
   581  					},
   582  				},
   583  			},
   584  			{
   585  				Query: "SELECT Host, User FROM mysql.user;",
   586  				Expected: []sql.Row{
   587  					{"localhost", "root"},
   588  					{"localhost", "testuser2"},
   589  					{"127.0.0.1", "testuser"},
   590  				},
   591  			},
   592  		},
   593  	},
   594  	{
   595  		Name: "Dynamic privilege support",
   596  		SetUpScript: []string{
   597  			"CREATE USER testuser@localhost;",
   598  			"GRANT REPLICATION_SLAVE_ADMIN ON *.* TO testuser@localhost;",
   599  			"GRANT CLONE_ADMIN ON *.* TO testuser@localhost;",
   600  		},
   601  		Assertions: []UserPrivilegeTestAssertion{
   602  			{
   603  				Query: "SELECT user, host from mysql.user",
   604  				Expected: []sql.Row{
   605  					{"root", "localhost"},
   606  					{"testuser", "localhost"},
   607  				},
   608  			},
   609  			{
   610  				User:  "root",
   611  				Host:  "localhost",
   612  				Query: "SHOW GRANTS FOR testuser@localhost;",
   613  				Expected: []sql.Row{
   614  					{"GRANT USAGE ON *.* TO `testuser`@`localhost`"},
   615  					{"GRANT CLONE_ADMIN, REPLICATION_SLAVE_ADMIN ON *.* TO `testuser`@`localhost`"},
   616  				},
   617  			},
   618  			{
   619  				// Dynamic privileges may only be applied globally
   620  				User:        "root",
   621  				Host:        "localhost",
   622  				Query:       "GRANT REPLICATION_SLAVE_ADMIN ON mydb.* TO 'testuser'@'localhost';",
   623  				ExpectedErr: sql.ErrGrantRevokeIllegalPrivilegeWithMessage,
   624  			},
   625  			{
   626  				// Dynamic privileges may only be applied globally
   627  				User:        "root",
   628  				Host:        "localhost",
   629  				Query:       "GRANT REPLICATION_SLAVE_ADMIN ON mydb.mytable TO 'testuser'@'localhost';",
   630  				ExpectedErr: sql.ErrGrantRevokeIllegalPrivilegeWithMessage,
   631  			},
   632  			{
   633  				// Dynamic privileges may only be applied globally
   634  				User:        "root",
   635  				Host:        "localhost",
   636  				Query:       "REVOKE REPLICATION_SLAVE_ADMIN ON mydb.* FROM 'testuser'@'localhost';",
   637  				ExpectedErr: sql.ErrGrantRevokeIllegalPrivilegeWithMessage,
   638  			},
   639  			{
   640  				// Dynamic privileges may only be applied globally
   641  				User:        "root",
   642  				Host:        "localhost",
   643  				Query:       "REVOKE REPLICATION_SLAVE_ADMIN ON mydb.mytable FROM 'testuser'@'localhost';",
   644  				ExpectedErr: sql.ErrGrantRevokeIllegalPrivilegeWithMessage,
   645  			},
   646  		},
   647  	},
   648  	{
   649  		Name: "user creation no host",
   650  		SetUpScript: []string{
   651  			"CREATE USER testuser;",
   652  		},
   653  		Assertions: []UserPrivilegeTestAssertion{
   654  			{
   655  				Query: "SELECT user, host from mysql.user",
   656  				Expected: []sql.Row{
   657  					{"root", "localhost"},
   658  					{"testuser", "%"},
   659  				},
   660  			},
   661  		},
   662  	},
   663  	{
   664  		Name: "grants at various scopes no host",
   665  		SetUpScript: []string{
   666  			"CREATE USER tester;",
   667  			"GRANT SELECT ON *.* to tester",
   668  			"GRANT SELECT ON db.* to tester",
   669  			"GRANT SELECT ON db.tbl to tester",
   670  		},
   671  		Assertions: []UserPrivilegeTestAssertion{
   672  			{
   673  				User:  "root",
   674  				Host:  "localhost",
   675  				Query: "SHOW GRANTS FOR tester@localhost;",
   676  				Expected: []sql.Row{
   677  					{"GRANT SELECT ON *.* TO `tester`@`%`"},
   678  					{"GRANT SELECT ON `db`.* TO `tester`@`%`"},
   679  					{"GRANT SELECT ON `db`.`tbl` TO `tester`@`%`"},
   680  				},
   681  			},
   682  		},
   683  	},
   684  	{
   685  		Name: "procedure grants and restrictions",
   686  		SetUpScript: []string{
   687  			"CREATE USER granted@localhost",
   688  			"GRANT EXECUTE ON mydb.* TO granted@localhost",
   689  			"GRANT EXECUTE ON PROCEDURE mydb.memory_admin_only TO granted@localhost", // Explicit grant on admin only proc
   690  			"CREATE USER denied@localhost",
   691  			"GRANT EXECUTE ON mydb.* TO denied@localhost", // Access to DB, but not to admin proc.
   692  			"CREATE USER targeted@localhost",
   693  			"GRANT EXECUTE ON PROCEDURE mydb.memory_admin_only TO targeted@localhost", // Explicit grant on admin only proc, even though no access to DB.
   694  			"CREATE USER noaccess@localhost",                                          // Ensure this user can't run any procedure
   695  		},
   696  		Assertions: []UserPrivilegeTestAssertion{
   697  			{
   698  				User:     "granted",
   699  				Host:     "localhost",
   700  				Query:    "CALL mydb.memory_admin_only(1,2)",
   701  				Expected: []sql.Row{{3}},
   702  			},
   703  			{
   704  				User:     "denied",
   705  				Host:     "localhost",
   706  				Query:    "CALL mydb.memory_variadic_add(3,2)", // Verify this user _can_ access non-admin proc
   707  				Expected: []sql.Row{{5}},
   708  			},
   709  			{
   710  				User:           "denied",
   711  				Host:           "localhost",
   712  				Query:          "CALL mydb.memory_admin_only(1,2)",
   713  				ExpectedErrStr: "command denied to user 'denied'@'localhost'",
   714  			},
   715  			{
   716  				User:           "targeted",
   717  				Host:           "localhost",
   718  				Query:          "CALL mydb.memory_variadic_add(3,2)", // Verify this user _can't_ access non-admin proc
   719  				ExpectedErrStr: "command denied to user 'targeted'@'localhost'",
   720  			},
   721  			{
   722  				User:     "targeted",
   723  				Host:     "localhost",
   724  				Query:    "CALL mydb.memory_admin_only(7,2)",
   725  				Expected: []sql.Row{{9}},
   726  			},
   727  			{
   728  				User:           "noaccess",
   729  				Host:           "localhost",
   730  				Query:          "CALL mydb.memory_variadic_add(3,2)", // Verify this user can't access non-admin proc
   731  				ExpectedErrStr: "Access denied for user 'noaccess'@'localhost' to database 'mydb'",
   732  			},
   733  			{
   734  				User:           "noaccess",
   735  				Host:           "localhost",
   736  				Query:          "CALL mydb.memory_admin_only(1,2)",
   737  				ExpectedErrStr: "Access denied for user 'noaccess'@'localhost' to database 'mydb'",
   738  			},
   739  		},
   740  	},
   741  	{
   742  		Name: "Valid users without privileges may use the dual table",
   743  		SetUpScript: []string{
   744  			"CREATE USER tester@localhost;",
   745  		},
   746  		Assertions: []UserPrivilegeTestAssertion{
   747  			{
   748  				User:     "tester",
   749  				Host:     "localhost",
   750  				Query:    "SELECT 1+2;",
   751  				Expected: []sql.Row{{3}},
   752  			},
   753  			{
   754  				User:           "noexist",
   755  				Host:           "localhost",
   756  				Query:          "SELECT 1+2;",
   757  				ExpectedErrStr: "Access denied for user 'noexist' (errno 1045) (sqlstate 28000)",
   758  			},
   759  		},
   760  	},
   761  	{
   762  		Name: "Basic SELECT and INSERT privilege checking",
   763  		SetUpScript: []string{
   764  			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
   765  			"INSERT INTO test VALUES (1), (2), (3);",
   766  			"CREATE USER tester@localhost;",
   767  		},
   768  		Assertions: []UserPrivilegeTestAssertion{
   769  			{
   770  				User:        "tester",
   771  				Host:        "localhost",
   772  				Query:       "INSERT INTO test VALUES (4);",
   773  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
   774  			},
   775  			{
   776  				User:     "root",
   777  				Host:     "localhost",
   778  				Query:    "GRANT INSERT ON *.* TO tester@localhost;",
   779  				Expected: []sql.Row{{types.NewOkResult(0)}},
   780  			},
   781  			{
   782  				User:     "tester",
   783  				Host:     "localhost",
   784  				Query:    "INSERT INTO test VALUES (4);",
   785  				Expected: []sql.Row{{types.NewOkResult(1)}},
   786  			},
   787  			{
   788  				User:        "tester",
   789  				Host:        "localhost",
   790  				Query:       "SELECT * FROM test;",
   791  				ExpectedErr: sql.ErrPrivilegeCheckFailed,
   792  			},
   793  			{
   794  				User:     "root",
   795  				Host:     "localhost",
   796  				Query:    "SELECT * FROM test;",
   797  				Expected: []sql.Row{{1}, {2}, {3}, {4}},
   798  			},
   799  			{
   800  				User:     "root",
   801  				Host:     "localhost",
   802  				Query:    "GRANT SELECT ON *.* TO tester@localhost;",
   803  				Expected: []sql.Row{{types.NewOkResult(0)}},
   804  			},
   805  			{
   806  				User:     "tester",
   807  				Host:     "localhost",
   808  				Query:    "SELECT * FROM test;",
   809  				Expected: []sql.Row{{1}, {2}, {3}, {4}},
   810  			},
   811  		},
   812  	},
   813  	{
   814  		Name: "Database-level privileges exist",
   815  		SetUpScript: []string{
   816  			"CREATE USER tester@localhost;",
   817  		},
   818  		Assertions: []UserPrivilegeTestAssertion{
   819  			{
   820  				User:     "root",
   821  				Host:     "localhost",
   822  				Query:    "GRANT SELECT, UPDATE, EXECUTE ON mydb.* TO tester@localhost;",
   823  				Expected: []sql.Row{{types.NewOkResult(0)}},
   824  			},
   825  			{
   826  				User:     "root",
   827  				Host:     "localhost",
   828  				Query:    "SELECT * FROM mysql.db;",
   829  				Expected: []sql.Row{{"localhost", "mydb", "tester", "Y", "N", "Y", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "Y", "N", "N"}},
   830  			},
   831  			{
   832  				User:     "root",
   833  				Host:     "localhost",
   834  				Query:    "REVOKE UPDATE ON mydb.* FROM tester@localhost;",
   835  				Expected: []sql.Row{{types.NewOkResult(0)}},
   836  			},
   837  			{
   838  				User:     "root",
   839  				Host:     "localhost",
   840  				Query:    "SELECT * FROM mysql.db;",
   841  				Expected: []sql.Row{{"localhost", "mydb", "tester", "Y", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "Y", "N", "N"}},
   842  			},
   843  			{
   844  				User:  "root",
   845  				Host:  "localhost",
   846  				Query: "UPDATE mysql.db SET Insert_priv = 'Y' WHERE User = 'tester';",
   847  				Expected: []sql.Row{{types.OkResult{
   848  					RowsAffected: 1,
   849  					InsertID:     0,
   850  					Info: plan.UpdateInfo{
   851  						Matched:  1,
   852  						Updated:  1,
   853  						Warnings: 0,
   854  					},
   855  				}}},
   856  			},
   857  			{
   858  				User:     "root",
   859  				Host:     "localhost",
   860  				Query:    "SELECT * FROM mysql.db;",
   861  				Expected: []sql.Row{{"localhost", "mydb", "tester", "Y", "Y", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "Y", "N", "N"}},
   862  			},
   863  		},
   864  	},
   865  	{
   866  		Name: "Table-level privileges exist",
   867  		SetUpScript: []string{
   868  			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
   869  			"CREATE USER tester@localhost;",
   870  		},
   871  		Assertions: []UserPrivilegeTestAssertion{
   872  			{
   873  				User:     "root",
   874  				Host:     "localhost",
   875  				Query:    "GRANT SELECT, DELETE, DROP ON mydb.test TO tester@localhost;",
   876  				Expected: []sql.Row{{types.NewOkResult(0)}},
   877  			},
   878  			{
   879  				User:     "root",
   880  				Host:     "localhost",
   881  				Query:    "SELECT * FROM mysql.tables_priv;",
   882  				Expected: []sql.Row{{"localhost", "mydb", "tester", "test", "", time.Unix(1, 0).UTC(), "Select,Delete,Drop", ""}},
   883  			},
   884  			{
   885  				User:     "root",
   886  				Host:     "localhost",
   887  				Query:    "REVOKE DELETE ON mydb.test FROM tester@localhost;",
   888  				Expected: []sql.Row{{types.NewOkResult(0)}},
   889  			},
   890  			{
   891  				User:     "root",
   892  				Host:     "localhost",
   893  				Query:    "SELECT * FROM mysql.tables_priv;",
   894  				Expected: []sql.Row{{"localhost", "mydb", "tester", "test", "", time.Unix(1, 0).UTC(), "Select,Drop", ""}},
   895  			},
   896  			{
   897  				User:  "root",
   898  				Host:  "localhost",
   899  				Query: "UPDATE mysql.tables_priv SET table_priv = 'References,Index' WHERE User = 'tester';",
   900  				Expected: []sql.Row{{types.OkResult{
   901  					RowsAffected: 1,
   902  					InsertID:     0,
   903  					Info: plan.UpdateInfo{
   904  						Matched:  1,
   905  						Updated:  1,
   906  						Warnings: 0,
   907  					},
   908  				}}},
   909  			},
   910  			{
   911  				User:     "root",
   912  				Host:     "localhost",
   913  				Query:    "SELECT * FROM mysql.tables_priv;",
   914  				Expected: []sql.Row{{"localhost", "mydb", "tester", "test", "", time.Unix(1, 0).UTC(), "References,Index", ""}},
   915  			},
   916  		},
   917  	},
   918  	{
   919  		Name: "GRANT Procedure and function privileges reflect in mysql.procs_priv",
   920  		SetUpScript: []string{
   921  			"CREATE USER tester1@localhost;",
   922  			"CREATE USER tester2@localhost;",
   923  			"GRANT EXECUTE ON PROCEDURE mydb.proc1 TO tester1@localhost;",
   924  			"GRANT GRANT OPTION ON PROCEDURE mydb.proc1 TO tester1@localhost;",
   925  			"GRANT ALTER ROUTINE ON PROCEDURE mydb.proc2 TO tester1@localhost;",
   926  			"GRANT GRANT OPTION ON PROCEDURE mydb.proc1 TO tester2@localhost;",
   927  		},
   928  		Assertions: []UserPrivilegeTestAssertion{
   929  			{
   930  				User:  "root",
   931  				Host:  "localhost",
   932  				Query: "SELECT Routine_name,Routine_type,proc_priv from mysql.procs_priv WHERE User = 'tester1'",
   933  				Expected: []sql.Row{
   934  					{"proc1", "PROCEDURE", "Grant,Execute"},
   935  					{"proc2", "PROCEDURE", "Alter Routine"},
   936  				},
   937  			},
   938  			{
   939  				User:     "root",
   940  				Host:     "localhost",
   941  				Query:    "SELECT Routine_name,Routine_type,proc_priv from mysql.procs_priv WHERE User = 'tester2'",
   942  				Expected: []sql.Row{{"proc1", "PROCEDURE", "Grant"}},
   943  			},
   944  			{
   945  				User:     "tester1",
   946  				Host:     "localhost",
   947  				Query:    "GRANT Execute ON PROCEDURE mydb.proc1 TO tester2@localhost",
   948  				Expected: []sql.Row{{types.NewOkResult(0)}},
   949  			},
   950  			{
   951  				User:           "tester2",
   952  				Host:           "localhost",
   953  				Query:          "GRANT Execute ON PROCEDURE mydb.proc2 TO tester1@localhost",
   954  				ExpectedErrStr: "command denied to user 'tester2'@'localhost'",
   955  			},
   956  		},
   957  	},
   958  	{
   959  		Name: "GRANT Procedure and function privileges reflect in mysql.procs_priv",
   960  		SetUpScript: []string{
   961  			"CREATE USER tester1@localhost;",
   962  			"CREATE USER tester2@localhost;",
   963  			"GRANT EXECUTE ON PROCEDURE mydb.proc1 TO tester1@localhost;",
   964  			"GRANT GRANT OPTION ON PROCEDURE mydb.proc1 TO tester1@localhost;",
   965  			"GRANT ALTER ROUTINE ON PROCEDURE mydb.proc2 TO tester1@localhost;",
   966  			"GRANT GRANT OPTION ON PROCEDURE mydb.proc2 TO tester2@localhost;",
   967  			"GRANT EXECUTE ON PROCEDURE mydb.proc2 TO tester2@localhost;",
   968  			"REVOKE EXECUTE ON PROCEDURE mydb.proc1 FROM tester1@localhost;",
   969  			"REVOKE ALTER ROUTINE ON PROCEDURE mydb.proc2 FROM tester1@localhost;",
   970  			"REVOKE ALTER ROUTINE ON PROCEDURE mydb.proc2 FROM tester2@localhost;", // Should be no-op.
   971  		},
   972  		Assertions: []UserPrivilegeTestAssertion{
   973  			{
   974  				User:     "root",
   975  				Host:     "localhost",
   976  				Query:    "SELECT Routine_name,Routine_type,proc_priv from mysql.procs_priv WHERE User = 'tester1'",
   977  				Expected: []sql.Row{{"proc1", "PROCEDURE", "Grant"}},
   978  			},
   979  			{
   980  				User:     "root",
   981  				Host:     "localhost",
   982  				Query:    "SELECT Routine_name,Routine_type,proc_priv from mysql.procs_priv WHERE User = 'tester2'",
   983  				Expected: []sql.Row{sql.Row{"proc2", "PROCEDURE", "Grant,Execute"}},
   984  			},
   985  		},
   986  	},
   987  	{
   988  		Name: "GRANT function privileges errors",
   989  		SetUpScript: []string{
   990  			"CREATE USER tester1@localhost;",
   991  		},
   992  		Assertions: []UserPrivilegeTestAssertion{
   993  			{
   994  				User:           "root",
   995  				Host:           "localhost",
   996  				Query:          "GRANT GRANT OPTION ON FUNCTION mydb.func1 TO tester1@localhost;",
   997  				ExpectedErrStr: "fine grain function permissions currently unsupported",
   998  			},
   999  			{
  1000  				User:           "root",
  1001  				Host:           "localhost",
  1002  				Query:          "GRANT EXECUTE ON FUNCTION mydb.func1 TO tester1@localhost;",
  1003  				ExpectedErrStr: "fine grain function permissions currently unsupported",
  1004  			},
  1005  			{
  1006  				User:           "root",
  1007  				Host:           "localhost",
  1008  				Query:          "GRANT ALTER ROUTINE ON FUNCTION mydb.func1 TO tester1@localhost;",
  1009  				ExpectedErrStr: "fine grain function permissions currently unsupported",
  1010  			},
  1011  		},
  1012  	},
  1013  	{
  1014  		Name: "Basic revoke SELECT privilege",
  1015  		SetUpScript: []string{
  1016  			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
  1017  			"INSERT INTO test VALUES (1), (2), (3);",
  1018  			"CREATE USER tester@localhost;",
  1019  			"GRANT SELECT ON *.* TO tester@localhost;",
  1020  		},
  1021  		Assertions: []UserPrivilegeTestAssertion{
  1022  			{
  1023  				User:     "tester",
  1024  				Host:     "localhost",
  1025  				Query:    "SELECT * FROM test;",
  1026  				Expected: []sql.Row{{1}, {2}, {3}},
  1027  			},
  1028  			{
  1029  				User:     "root",
  1030  				Host:     "localhost",
  1031  				Query:    "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';",
  1032  				Expected: []sql.Row{{"tester", "localhost", "Y"}},
  1033  			},
  1034  			{
  1035  				User:     "root",
  1036  				Host:     "localhost",
  1037  				Query:    "REVOKE SELECT ON *.* FROM tester@localhost;",
  1038  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1039  			},
  1040  			{
  1041  				User:        "tester",
  1042  				Host:        "localhost",
  1043  				Query:       "SELECT * FROM test;",
  1044  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
  1045  			},
  1046  			{
  1047  				User:     "root",
  1048  				Host:     "localhost",
  1049  				Query:    "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';",
  1050  				Expected: []sql.Row{{"tester", "localhost", "N"}},
  1051  			},
  1052  		},
  1053  	},
  1054  	{
  1055  		Name: "Basic revoke all global static privileges",
  1056  		SetUpScript: []string{
  1057  			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
  1058  			"INSERT INTO test VALUES (1), (2), (3);",
  1059  			"CREATE USER tester@localhost;",
  1060  			"GRANT ALL ON *.* TO tester@localhost;",
  1061  		},
  1062  		Assertions: []UserPrivilegeTestAssertion{
  1063  			{
  1064  				User:     "tester",
  1065  				Host:     "localhost",
  1066  				Query:    "INSERT INTO test VALUES (4);",
  1067  				Expected: []sql.Row{{types.NewOkResult(1)}},
  1068  			},
  1069  			{
  1070  				User:     "tester",
  1071  				Host:     "localhost",
  1072  				Query:    "SELECT * FROM test;",
  1073  				Expected: []sql.Row{{1}, {2}, {3}, {4}},
  1074  			},
  1075  			{
  1076  				User:     "root",
  1077  				Host:     "localhost",
  1078  				Query:    "SELECT User, Host, Select_priv, Insert_priv FROM mysql.user WHERE User = 'tester';",
  1079  				Expected: []sql.Row{{"tester", "localhost", "Y", "Y"}},
  1080  			},
  1081  			{
  1082  				User:     "root",
  1083  				Host:     "localhost",
  1084  				Query:    "REVOKE ALL ON *.* FROM tester@localhost;",
  1085  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1086  			},
  1087  			{
  1088  				User:        "tester",
  1089  				Host:        "localhost",
  1090  				Query:       "SELECT * FROM test;",
  1091  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
  1092  			},
  1093  			{
  1094  				User:        "tester",
  1095  				Host:        "localhost",
  1096  				Query:       "INSERT INTO test VALUES (5);",
  1097  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
  1098  			},
  1099  			{
  1100  				User:     "root",
  1101  				Host:     "localhost",
  1102  				Query:    "SELECT User, Host, Select_priv, Insert_priv FROM mysql.user WHERE User = 'tester';",
  1103  				Expected: []sql.Row{{"tester", "localhost", "N", "N"}},
  1104  			},
  1105  		},
  1106  	},
  1107  	{
  1108  		Name: "Basic role creation",
  1109  		SetUpScript: []string{
  1110  			"CREATE ROLE test_role;",
  1111  		},
  1112  		Assertions: []UserPrivilegeTestAssertion{
  1113  			{
  1114  				User:     "root",
  1115  				Host:     "localhost",
  1116  				Query:    "SELECT User, Host, account_locked FROM mysql.user WHERE User = 'test_role';",
  1117  				Expected: []sql.Row{{"test_role", "%", "Y"}},
  1118  			},
  1119  		},
  1120  	},
  1121  	{
  1122  		Name: "Grant Role with SELECT Privilege",
  1123  		SetUpScript: []string{
  1124  			"SET @@GLOBAL.activate_all_roles_on_login = true;",
  1125  			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
  1126  			"INSERT INTO test VALUES (1), (2), (3);",
  1127  			"CREATE USER tester@localhost;",
  1128  			"CREATE ROLE test_role;",
  1129  			"GRANT SELECT ON *.* TO test_role;",
  1130  		},
  1131  		Assertions: []UserPrivilegeTestAssertion{
  1132  			{
  1133  				User:        "tester",
  1134  				Host:        "localhost",
  1135  				Query:       "SELECT * FROM test;",
  1136  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
  1137  			},
  1138  			{
  1139  				User:     "root",
  1140  				Host:     "localhost",
  1141  				Query:    "SELECT COUNT(*) FROM mysql.role_edges;",
  1142  				Expected: []sql.Row{{0}},
  1143  			},
  1144  			{
  1145  				User:     "root",
  1146  				Host:     "localhost",
  1147  				Query:    "GRANT test_role TO tester@localhost;",
  1148  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1149  			},
  1150  			{
  1151  				User:     "root",
  1152  				Host:     "localhost",
  1153  				Query:    "SELECT * FROM mysql.role_edges;",
  1154  				Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}},
  1155  			},
  1156  			{
  1157  				User:     "tester",
  1158  				Host:     "localhost",
  1159  				Query:    "SELECT * FROM test;",
  1160  				Expected: []sql.Row{{1}, {2}, {3}},
  1161  			},
  1162  			{
  1163  				User:     "root",
  1164  				Host:     "localhost",
  1165  				Query:    "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';",
  1166  				Expected: []sql.Row{{"tester", "localhost", "N"}},
  1167  			},
  1168  		},
  1169  	},
  1170  	{
  1171  		Name: "Revoke role currently granted to a user",
  1172  		SetUpScript: []string{
  1173  			"SET @@GLOBAL.activate_all_roles_on_login = true;",
  1174  			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
  1175  			"INSERT INTO test VALUES (1), (2), (3);",
  1176  			"CREATE USER tester@localhost;",
  1177  			"CREATE ROLE test_role;",
  1178  			"GRANT SELECT ON *.* TO test_role;",
  1179  			"GRANT test_role TO tester@localhost;",
  1180  		},
  1181  		Assertions: []UserPrivilegeTestAssertion{
  1182  			{
  1183  				User:     "tester",
  1184  				Host:     "localhost",
  1185  				Query:    "SELECT * FROM test;",
  1186  				Expected: []sql.Row{{1}, {2}, {3}},
  1187  			},
  1188  			{
  1189  				User:     "root",
  1190  				Host:     "localhost",
  1191  				Query:    "SELECT * FROM mysql.role_edges;",
  1192  				Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}},
  1193  			},
  1194  			{
  1195  				User:     "root",
  1196  				Host:     "localhost",
  1197  				Query:    "REVOKE test_role FROM tester@localhost;",
  1198  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1199  			},
  1200  			{
  1201  				User:        "tester",
  1202  				Host:        "localhost",
  1203  				Query:       "SELECT * FROM test;",
  1204  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
  1205  			},
  1206  			{
  1207  				User:     "root",
  1208  				Host:     "localhost",
  1209  				Query:    "SELECT COUNT(*) FROM mysql.role_edges;",
  1210  				Expected: []sql.Row{{0}},
  1211  			},
  1212  			{
  1213  				User:     "root",
  1214  				Host:     "localhost",
  1215  				Query:    "SELECT COUNT(*) FROM mysql.user WHERE User = 'test_role';",
  1216  				Expected: []sql.Row{{1}},
  1217  			},
  1218  			{
  1219  				User:     "root",
  1220  				Host:     "localhost",
  1221  				Query:    "SELECT COUNT(*) FROM mysql.user WHERE User = 'tester';",
  1222  				Expected: []sql.Row{{1}},
  1223  			},
  1224  		},
  1225  	},
  1226  	{
  1227  		Name: "Drop role currently granted to a user",
  1228  		SetUpScript: []string{
  1229  			"SET @@GLOBAL.activate_all_roles_on_login = true;",
  1230  			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
  1231  			"INSERT INTO test VALUES (1), (2), (3);",
  1232  			"CREATE USER tester@localhost;",
  1233  			"CREATE ROLE test_role;",
  1234  			"GRANT SELECT ON *.* TO test_role;",
  1235  			"GRANT test_role TO tester@localhost;",
  1236  		},
  1237  		Assertions: []UserPrivilegeTestAssertion{
  1238  			{
  1239  				User:     "tester",
  1240  				Host:     "localhost",
  1241  				Query:    "SELECT * FROM test;",
  1242  				Expected: []sql.Row{{1}, {2}, {3}},
  1243  			},
  1244  			{
  1245  				User:     "root",
  1246  				Host:     "localhost",
  1247  				Query:    "SELECT * FROM mysql.role_edges;",
  1248  				Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}},
  1249  			},
  1250  			{
  1251  				User:     "root",
  1252  				Host:     "localhost",
  1253  				Query:    "DROP ROLE test_role;",
  1254  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1255  			},
  1256  			{
  1257  				User:        "tester",
  1258  				Host:        "localhost",
  1259  				Query:       "SELECT * FROM test;",
  1260  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
  1261  			},
  1262  			{
  1263  				User:     "root",
  1264  				Host:     "localhost",
  1265  				Query:    "SELECT COUNT(*) FROM mysql.role_edges;",
  1266  				Expected: []sql.Row{{0}},
  1267  			},
  1268  			{
  1269  				User:     "root",
  1270  				Host:     "localhost",
  1271  				Query:    "SELECT COUNT(*) FROM mysql.user WHERE User = 'test_role';",
  1272  				Expected: []sql.Row{{0}},
  1273  			},
  1274  			{ // Ensure nothing wonky happened like the user was deleted as well
  1275  				User:     "root",
  1276  				Host:     "localhost",
  1277  				Query:    "SELECT COUNT(*) FROM mysql.user WHERE User = 'tester';",
  1278  				Expected: []sql.Row{{1}},
  1279  			},
  1280  			{
  1281  				User:        "root",
  1282  				Host:        "localhost",
  1283  				Query:       "DROP ROLE test_role;",
  1284  				ExpectedErr: sql.ErrRoleDeletionFailure,
  1285  			},
  1286  			{
  1287  				User:     "root",
  1288  				Host:     "localhost",
  1289  				Query:    "DROP ROLE IF EXISTS test_role;",
  1290  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1291  			},
  1292  		},
  1293  	},
  1294  	{
  1295  		Name: "Drop user with role currently granted",
  1296  		SetUpScript: []string{
  1297  			"SET @@GLOBAL.activate_all_roles_on_login = true;",
  1298  			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
  1299  			"INSERT INTO test VALUES (1), (2), (3);",
  1300  			"CREATE USER tester@localhost;",
  1301  			"CREATE ROLE test_role;",
  1302  			"GRANT SELECT ON *.* TO test_role;",
  1303  			"GRANT test_role TO tester@localhost;",
  1304  		},
  1305  		Assertions: []UserPrivilegeTestAssertion{
  1306  			{
  1307  				User:     "root",
  1308  				Host:     "localhost",
  1309  				Query:    "SELECT * FROM mysql.role_edges;",
  1310  				Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}},
  1311  			},
  1312  			{
  1313  				User:     "root",
  1314  				Host:     "localhost",
  1315  				Query:    "DROP USER tester@localhost;",
  1316  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1317  			},
  1318  			{
  1319  				User:     "root",
  1320  				Host:     "localhost",
  1321  				Query:    "SELECT COUNT(*) FROM mysql.role_edges;",
  1322  				Expected: []sql.Row{{0}},
  1323  			},
  1324  			{
  1325  				User:     "root",
  1326  				Host:     "localhost",
  1327  				Query:    "SELECT COUNT(*) FROM mysql.user WHERE User = 'tester';",
  1328  				Expected: []sql.Row{{0}},
  1329  			},
  1330  			{ // Ensure nothing wonky happened like the role was deleted as well
  1331  				User:     "root",
  1332  				Host:     "localhost",
  1333  				Query:    "SELECT COUNT(*) FROM mysql.user WHERE User = 'test_role';",
  1334  				Expected: []sql.Row{{1}},
  1335  			},
  1336  			{
  1337  				User:        "root",
  1338  				Host:        "localhost",
  1339  				Query:       "DROP USER tester@localhost;",
  1340  				ExpectedErr: sql.ErrUserDeletionFailure,
  1341  			},
  1342  			{
  1343  				User:     "root",
  1344  				Host:     "localhost",
  1345  				Query:    "DROP USER IF EXISTS tester@localhost;",
  1346  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1347  			},
  1348  		},
  1349  	},
  1350  	{
  1351  		Name: "Show grants on root account",
  1352  		Assertions: []UserPrivilegeTestAssertion{
  1353  			{
  1354  				User:  "root",
  1355  				Host:  "localhost",
  1356  				Query: "SHOW GRANTS;",
  1357  				Expected: []sql.Row{{"GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, " +
  1358  					"FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, " +
  1359  					"EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, " +
  1360  					"ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, CREATE ROLE, DROP ROLE ON *.* TO " +
  1361  					"`root`@`localhost` WITH GRANT OPTION"}},
  1362  			},
  1363  		},
  1364  	},
  1365  	{
  1366  		Name: "Show grants on a user from the root account",
  1367  		SetUpScript: []string{
  1368  			"CREATE USER tester@localhost;",
  1369  			"GRANT SELECT ON *.* TO tester@localhost;",
  1370  			"CREATE ROLE test_role1;",
  1371  			"CREATE ROLE test_role2;",
  1372  			"GRANT INSERT ON *.* TO test_role1;",
  1373  			"GRANT REFERENCES ON *.* TO test_role2;",
  1374  			"GRANT test_role1 TO tester@localhost;",
  1375  			"GRANT test_role2 TO tester@localhost;",
  1376  		},
  1377  		Assertions: []UserPrivilegeTestAssertion{
  1378  			{
  1379  				User:  "root",
  1380  				Host:  "localhost",
  1381  				Query: "SHOW GRANTS FOR tester@localhost;",
  1382  				Expected: []sql.Row{
  1383  					{"GRANT SELECT ON *.* TO `tester`@`localhost`"},
  1384  					{"GRANT `test_role1`@`%`, `test_role2`@`%` TO `tester`@`localhost`"},
  1385  				},
  1386  			},
  1387  			{
  1388  				User:     "root",
  1389  				Host:     "localhost",
  1390  				Query:    "GRANT UPDATE ON *.* TO tester@localhost WITH GRANT OPTION;",
  1391  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1392  			},
  1393  			{
  1394  				User:  "root",
  1395  				Host:  "localhost",
  1396  				Query: "SHOW GRANTS FOR tester@localhost;",
  1397  				Expected: []sql.Row{
  1398  					{"GRANT SELECT, UPDATE ON *.* TO `tester`@`localhost` WITH GRANT OPTION"},
  1399  					{"GRANT `test_role1`@`%`, `test_role2`@`%` TO `tester`@`localhost`"},
  1400  				},
  1401  			},
  1402  			{
  1403  				User:  "tester",
  1404  				Host:  "localhost",
  1405  				Query: "SHOW GRANTS;",
  1406  				Expected: []sql.Row{
  1407  					{"GRANT SELECT, UPDATE ON *.* TO `tester`@`localhost` WITH GRANT OPTION"},
  1408  					{"GRANT `test_role1`@`%`, `test_role2`@`%` TO `tester`@`localhost`"},
  1409  				},
  1410  			},
  1411  		},
  1412  	},
  1413  	{
  1414  		Name: "show user with no grants",
  1415  		SetUpScript: []string{
  1416  			"CREATE USER tester@localhost;",
  1417  		},
  1418  		Assertions: []UserPrivilegeTestAssertion{
  1419  			{
  1420  				User:  "root",
  1421  				Host:  "localhost",
  1422  				Query: "SHOW GRANTS FOR tester@localhost;",
  1423  				Expected: []sql.Row{
  1424  					{"GRANT USAGE ON *.* TO `tester`@`localhost`"},
  1425  				},
  1426  			},
  1427  		},
  1428  	},
  1429  	{
  1430  		Name: "show grants with multiple global grants",
  1431  		SetUpScript: []string{
  1432  			"CREATE USER tester@localhost;",
  1433  			"GRANT SELECT ON *.* to tester@localhost",
  1434  			"GRANT INSERT ON *.* to tester@localhost",
  1435  		},
  1436  		Assertions: []UserPrivilegeTestAssertion{
  1437  			{
  1438  				User:  "root",
  1439  				Host:  "localhost",
  1440  				Query: "SHOW GRANTS FOR tester@localhost;",
  1441  				Expected: []sql.Row{
  1442  					{"GRANT SELECT, INSERT ON *.* TO `tester`@`localhost`"},
  1443  				},
  1444  			},
  1445  		},
  1446  	},
  1447  	{
  1448  		Name: "show grants at various scopes",
  1449  		SetUpScript: []string{
  1450  			"CREATE USER tester@localhost;",
  1451  			"GRANT SELECT ON *.* to tester@localhost",
  1452  			"GRANT SELECT ON db.* to tester@localhost",
  1453  			"GRANT SELECT ON db.tbl to tester@localhost",
  1454  		},
  1455  		Assertions: []UserPrivilegeTestAssertion{
  1456  			{
  1457  				User:  "root",
  1458  				Host:  "localhost",
  1459  				Query: "SHOW GRANTS FOR tester@localhost;",
  1460  				Expected: []sql.Row{
  1461  					{"GRANT SELECT ON *.* TO `tester`@`localhost`"},
  1462  					{"GRANT SELECT ON `db`.* TO `tester`@`localhost`"},
  1463  					{"GRANT SELECT ON `db`.`tbl` TO `tester`@`localhost`"},
  1464  				},
  1465  			},
  1466  		},
  1467  	},
  1468  	{
  1469  		Name: "show grants at only some scopes",
  1470  		SetUpScript: []string{
  1471  			"CREATE USER tester@localhost;",
  1472  			"GRANT SELECT ON *.* to tester@localhost",
  1473  			"GRANT SELECT ON db.tbl to tester@localhost",
  1474  		},
  1475  		Assertions: []UserPrivilegeTestAssertion{
  1476  			{
  1477  				User:  "root",
  1478  				Host:  "localhost",
  1479  				Query: "SHOW GRANTS FOR tester@localhost;",
  1480  				Expected: []sql.Row{
  1481  					{"GRANT SELECT ON *.* TO `tester`@`localhost`"},
  1482  					{"GRANT SELECT ON `db`.`tbl` TO `tester`@`localhost`"},
  1483  				},
  1484  			},
  1485  		},
  1486  	},
  1487  	{
  1488  		Name: "show always shows global USAGE priv regardless of other privs",
  1489  		SetUpScript: []string{
  1490  			"CREATE USER tester@localhost;",
  1491  			"GRANT SELECT ON db.* to tester@localhost",
  1492  			"GRANT INSERT ON db1.* to tester@localhost",
  1493  			"GRANT DELETE ON db2.* to tester@localhost",
  1494  			"GRANT SELECT ON db.tbl to tester@localhost",
  1495  			"GRANT INSERT ON db.tbl to tester@localhost",
  1496  		},
  1497  		Assertions: []UserPrivilegeTestAssertion{
  1498  			{
  1499  				User:  "root",
  1500  				Host:  "localhost",
  1501  				Query: "SHOW GRANTS FOR tester@localhost;",
  1502  				Expected: []sql.Row{
  1503  					{"GRANT USAGE ON *.* TO `tester`@`localhost`"},
  1504  					{"GRANT SELECT ON `db`.* TO `tester`@`localhost`"},
  1505  					{"GRANT INSERT ON `db1`.* TO `tester`@`localhost`"},
  1506  					{"GRANT DELETE ON `db2`.* TO `tester`@`localhost`"},
  1507  					{"GRANT SELECT, INSERT ON `db`.`tbl` TO `tester`@`localhost`"},
  1508  				},
  1509  			},
  1510  		},
  1511  	},
  1512  	{
  1513  		Name: "with grant option works at every scope",
  1514  		SetUpScript: []string{
  1515  			"CREATE USER tester@localhost;",
  1516  			"GRANT SELECT ON *.* to tester@localhost WITH GRANT OPTION",
  1517  			"GRANT SELECT ON db.* to tester@localhost WITH GRANT OPTION",
  1518  			"GRANT SELECT ON db.tbl to tester@localhost WITH GRANT OPTION",
  1519  		},
  1520  		Assertions: []UserPrivilegeTestAssertion{
  1521  			{
  1522  				User:  "root",
  1523  				Host:  "localhost",
  1524  				Query: "SHOW GRANTS FOR tester@localhost;",
  1525  				Expected: []sql.Row{
  1526  					{"GRANT SELECT ON *.* TO `tester`@`localhost` WITH GRANT OPTION"},
  1527  					{"GRANT SELECT ON `db`.* TO `tester`@`localhost` WITH GRANT OPTION"},
  1528  					{"GRANT SELECT ON `db`.`tbl` TO `tester`@`localhost` WITH GRANT OPTION"},
  1529  				},
  1530  			},
  1531  		},
  1532  	},
  1533  	{
  1534  		Name: "adding with grant option applies to existing privileges",
  1535  		SetUpScript: []string{
  1536  			"CREATE USER tester@localhost;",
  1537  			"GRANT SELECT ON *.* to tester@localhost",
  1538  			"GRANT INSERT ON *.* to tester@localhost WITH GRANT OPTION",
  1539  			"GRANT SELECT ON db.* to tester@localhost",
  1540  			"GRANT INSERT ON db.* to tester@localhost WITH GRANT OPTION",
  1541  			"GRANT SELECT ON db.tbl to tester@localhost",
  1542  			"GRANT INSERT ON db.tbl to tester@localhost WITH GRANT OPTION",
  1543  		},
  1544  		Assertions: []UserPrivilegeTestAssertion{
  1545  			{
  1546  				User:  "root",
  1547  				Host:  "localhost",
  1548  				Query: "SHOW GRANTS FOR tester@localhost;",
  1549  				Expected: []sql.Row{
  1550  					{"GRANT SELECT, INSERT ON *.* TO `tester`@`localhost` WITH GRANT OPTION"},
  1551  					{"GRANT SELECT, INSERT ON `db`.* TO `tester`@`localhost` WITH GRANT OPTION"},
  1552  					{"GRANT SELECT, INSERT ON `db`.`tbl` TO `tester`@`localhost` WITH GRANT OPTION"},
  1553  				},
  1554  			},
  1555  		},
  1556  	},
  1557  	{
  1558  		Name: "SHOW DATABASES shows `mysql` database",
  1559  		SetUpScript: []string{
  1560  			"CREATE USER testuser;",
  1561  		},
  1562  		Assertions: []UserPrivilegeTestAssertion{
  1563  			{
  1564  				User:  "root",
  1565  				Host:  "localhost",
  1566  				Query: "SELECT user FROM mysql.user;",
  1567  				Expected: []sql.Row{
  1568  					{"root"},
  1569  					{"testuser"},
  1570  				},
  1571  			},
  1572  			{
  1573  				User:  "root",
  1574  				Host:  "localhost",
  1575  				Query: "SELECT USER();",
  1576  				Expected: []sql.Row{
  1577  					{"root@localhost"},
  1578  				},
  1579  			},
  1580  			{
  1581  				User:  "root",
  1582  				Host:  "localhost",
  1583  				Query: "SHOW DATABASES",
  1584  				Expected: []sql.Row{
  1585  					{"information_schema"},
  1586  					{"mydb"},
  1587  					{"mysql"},
  1588  				},
  1589  			},
  1590  		},
  1591  	},
  1592  	{
  1593  		Name: "Anonymous User",
  1594  		SetUpScript: []string{
  1595  			"CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY, v1 BIGINT);",
  1596  			"CREATE TABLE mydb.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT);",
  1597  			"INSERT INTO mydb.test VALUES (0, 0), (1, 1);",
  1598  			"INSERT INTO mydb.test2 VALUES (0, 1), (1, 2);",
  1599  			"CREATE USER 'rand_user'@'localhost';",
  1600  			"CREATE USER ''@'%';",
  1601  			"GRANT SELECT ON mydb.test TO 'rand_user'@'localhost';",
  1602  			"GRANT SELECT ON mydb.test2 TO ''@'%';",
  1603  		},
  1604  		Assertions: []UserPrivilegeTestAssertion{
  1605  			{
  1606  				User:  "rand_user",
  1607  				Host:  "localhost",
  1608  				Query: "SELECT * FROM mydb.test;",
  1609  				Expected: []sql.Row{
  1610  					{0, 0},
  1611  					{1, 1},
  1612  				},
  1613  			},
  1614  			{
  1615  				User:        "rand_user",
  1616  				Host:        "localhost",
  1617  				Query:       "SELECT * FROM mydb.test2;",
  1618  				ExpectedErr: sql.ErrTableAccessDeniedForUser,
  1619  			},
  1620  			{
  1621  				User:        "rand_user",
  1622  				Host:        "non_existent_host",
  1623  				Query:       "SELECT * FROM mydb.test;",
  1624  				ExpectedErr: sql.ErrTableAccessDeniedForUser,
  1625  			},
  1626  			{
  1627  				User:  "rand_user",
  1628  				Host:  "non_existent_host",
  1629  				Query: "SELECT * FROM mydb.test2;",
  1630  				Expected: []sql.Row{
  1631  					{0, 1},
  1632  					{1, 2},
  1633  				},
  1634  			},
  1635  			{
  1636  				User:        "non_existent_user",
  1637  				Host:        "non_existent_host",
  1638  				Query:       "SELECT * FROM mydb.test;",
  1639  				ExpectedErr: sql.ErrTableAccessDeniedForUser,
  1640  			},
  1641  			{
  1642  				User:  "non_existent_user",
  1643  				Host:  "non_existent_host",
  1644  				Query: "SELECT * FROM mydb.test2;",
  1645  				Expected: []sql.Row{
  1646  					{0, 1},
  1647  					{1, 2},
  1648  				},
  1649  			},
  1650  			{
  1651  				User:        "",
  1652  				Host:        "%",
  1653  				Query:       "SELECT * FROM mydb.test;",
  1654  				ExpectedErr: sql.ErrTableAccessDeniedForUser,
  1655  			},
  1656  			{
  1657  				User:  "",
  1658  				Host:  "%",
  1659  				Query: "SELECT * FROM mydb.test2;",
  1660  				Expected: []sql.Row{
  1661  					{0, 1},
  1662  					{1, 2},
  1663  				},
  1664  			},
  1665  		},
  1666  	},
  1667  	{
  1668  		Name: "IPv4 Loopback == localhost",
  1669  		SetUpScript: []string{
  1670  			"CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY, v1 BIGINT);",
  1671  			"CREATE TABLE mydb.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT);",
  1672  			"INSERT INTO mydb.test VALUES (0, 0), (1, 1);",
  1673  			"INSERT INTO mydb.test2 VALUES (0, 1), (1, 2);",
  1674  			"CREATE USER 'rand_user1'@'localhost';",
  1675  			"CREATE USER 'rand_user2'@'127.0.0.1';",
  1676  			"GRANT SELECT ON mydb.test TO 'rand_user1'@'localhost';",
  1677  			"GRANT SELECT ON mydb.test2 TO 'rand_user2'@'127.0.0.1';",
  1678  		},
  1679  		Assertions: []UserPrivilegeTestAssertion{
  1680  			{
  1681  				User:  "rand_user1",
  1682  				Host:  "localhost",
  1683  				Query: "SELECT * FROM mydb.test;",
  1684  				Expected: []sql.Row{
  1685  					{0, 0},
  1686  					{1, 1},
  1687  				},
  1688  			},
  1689  			{
  1690  				User:  "rand_user1",
  1691  				Host:  "127.0.0.1",
  1692  				Query: "SELECT * FROM mydb.test;",
  1693  				Expected: []sql.Row{
  1694  					{0, 0},
  1695  					{1, 1},
  1696  				},
  1697  			},
  1698  			{
  1699  				User:        "rand_user1",
  1700  				Host:        "54.244.85.252",
  1701  				Query:       "SELECT * FROM mydb.test;",
  1702  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
  1703  			},
  1704  			{
  1705  				User:  "rand_user2",
  1706  				Host:  "localhost",
  1707  				Query: "SELECT * FROM mydb.test2;",
  1708  				Expected: []sql.Row{
  1709  					{0, 1},
  1710  					{1, 2},
  1711  				},
  1712  			},
  1713  			{
  1714  				User:  "rand_user2",
  1715  				Host:  "127.0.0.1",
  1716  				Query: "SELECT * FROM mydb.test2;",
  1717  				Expected: []sql.Row{
  1718  					{0, 1},
  1719  					{1, 2},
  1720  				},
  1721  			},
  1722  			{
  1723  				User:        "rand_user2",
  1724  				Host:        "54.244.85.252",
  1725  				Query:       "SELECT * FROM mydb.test2;",
  1726  				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
  1727  			},
  1728  		},
  1729  	},
  1730  	{
  1731  		Name: "DROP USER without a host designation",
  1732  		SetUpScript: []string{
  1733  			"CREATE USER admin;",
  1734  		},
  1735  		Assertions: []UserPrivilegeTestAssertion{
  1736  			{
  1737  				User:  "root",
  1738  				Host:  "localhost",
  1739  				Query: "SELECT user FROM mysql.user",
  1740  				Expected: []sql.Row{
  1741  					{"root"},
  1742  					{"admin"},
  1743  				},
  1744  			},
  1745  			{
  1746  				User:     "root",
  1747  				Host:     "localhost",
  1748  				Query:    "DROP USER admin;",
  1749  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1750  			},
  1751  			{
  1752  				User:  "root",
  1753  				Host:  "localhost",
  1754  				Query: "SELECT user FROM mysql.user",
  1755  				Expected: []sql.Row{
  1756  					{"root"},
  1757  				},
  1758  			},
  1759  		},
  1760  	},
  1761  	{
  1762  		Name: "information_schema.columns table 'privileges' column gets correct values",
  1763  		SetUpScript: []string{
  1764  			"CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))",
  1765  			"CREATE TABLE test (pk BIGINT PRIMARY KEY, c VARCHAR(20), p POINT default (POINT(1,1)))",
  1766  			"CREATE USER tester@localhost;",
  1767  		},
  1768  		Assertions: []UserPrivilegeTestAssertion{
  1769  			{
  1770  				User:     "tester",
  1771  				Host:     "localhost",
  1772  				Query:    "SELECT count(*) FROM inFORmation_ScHeMa.columns where table_schema = 'mydb' and table_name = 'test';",
  1773  				Expected: []sql.Row{{0}},
  1774  			},
  1775  			{
  1776  				User:     "root",
  1777  				Host:     "localhost",
  1778  				Query:    "GRANT INSERT ON mydb.test TO tester@localhost;",
  1779  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1780  			},
  1781  			{
  1782  				User:     "tester",
  1783  				Host:     "localhost",
  1784  				Query:    "SELECT column_name, privileges FROM information_schema.columns where table_schema = 'mydb' and table_name = 'test'",
  1785  				Expected: []sql.Row{{"pk", "insert"}, {"c", "insert"}, {"p", "insert"}},
  1786  			},
  1787  			{
  1788  				User:     "root",
  1789  				Host:     "localhost",
  1790  				Query:    "GRANT SELECT ON mydb.* TO tester@localhost;",
  1791  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1792  			},
  1793  			{
  1794  				User:     "tester",
  1795  				Host:     "localhost",
  1796  				Query:    "SELECT column_name, privileges FROM information_schema.columns where table_schema = 'mydb' and table_name = 'test'",
  1797  				Expected: []sql.Row{{"pk", "insert,select"}, {"c", "insert,select"}, {"p", "insert,select"}},
  1798  			},
  1799  			{
  1800  				User:     "root",
  1801  				Host:     "localhost",
  1802  				Query:    "GRANT UPDATE ON mydb.checks TO tester@localhost;",
  1803  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1804  			},
  1805  			{
  1806  				User:     "tester",
  1807  				Host:     "localhost",
  1808  				Query:    "select table_name, column_name, privileges from information_schema.columns where table_schema = 'mydb' and table_name = 'checks';",
  1809  				Expected: []sql.Row{{"checks", "a", "select,update"}, {"checks", "b", "select,update"}, {"checks", "c", "select,update"}},
  1810  			},
  1811  			{
  1812  				User:     "tester",
  1813  				Host:     "localhost",
  1814  				Query:    "SELECT count(*) FROM information_schema.columns where table_schema = 'information_schema' and table_name = 'columns'",
  1815  				Expected: []sql.Row{{22}},
  1816  			},
  1817  			{
  1818  				User:     "root",
  1819  				Host:     "localhost",
  1820  				Query:    "select table_name, column_name, privileges from information_schema.columns where table_schema = 'mydb' and table_name = 'checks';",
  1821  				Expected: []sql.Row{{"checks", "a", "insert,references,select,update"}, {"checks", "b", "insert,references,select,update"}, {"checks", "c", "insert,references,select,update"}},
  1822  			},
  1823  		},
  1824  	},
  1825  	{
  1826  		Name: "information_schema.column_statistics shows columns with privileges only",
  1827  		SetUpScript: []string{
  1828  			"CREATE TABLE two (i bigint primary key, j bigint, key(j))",
  1829  			"INSERT INTO two VALUES (1, 4), (2, 5), (3, 6)",
  1830  			"CREATE TABLE one (f double primary key)",
  1831  			"INSERT INTO one VALUES (1.25), (45.25), (7.5), (10.5)",
  1832  			"ANALYZE TABLE one",
  1833  			"ANALYZE TABLE two",
  1834  			"CREATE USER tester@localhost;",
  1835  		},
  1836  		Assertions: []UserPrivilegeTestAssertion{
  1837  			{
  1838  				User:     "root",
  1839  				Host:     "localhost",
  1840  				Query:    "GRANT SELECT ON mydb.one TO tester@localhost;",
  1841  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1842  			},
  1843  			{
  1844  				User:  "tester",
  1845  				Host:  "localhost",
  1846  				Query: "SELECT table_name, column_name FROM information_schema.column_statistics where schema_name = 'mydb';",
  1847  				Expected: []sql.Row{
  1848  					{"one", "f"},
  1849  				},
  1850  			},
  1851  			{
  1852  				User:     "root",
  1853  				Host:     "localhost",
  1854  				Query:    "GRANT SELECT ON mydb.two TO tester@localhost;",
  1855  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1856  			},
  1857  			{
  1858  				User:  "tester",
  1859  				Host:  "localhost",
  1860  				Query: "SELECT table_name, column_name FROM information_schema.column_statistics where schema_name = 'mydb';",
  1861  				Expected: []sql.Row{
  1862  					{"one", "f"},
  1863  					{"two", "i"},
  1864  					{"two", "j"},
  1865  				},
  1866  			},
  1867  		},
  1868  	},
  1869  	{
  1870  		Name: "information_schema.statistics shows tables with privileges only",
  1871  		SetUpScript: []string{
  1872  			"CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))",
  1873  			"CREATE TABLE test (pk BIGINT PRIMARY KEY, c VARCHAR(20), p POINT default (POINT(1,1)))",
  1874  			"CREATE USER tester@localhost;",
  1875  		},
  1876  		Assertions: []UserPrivilegeTestAssertion{
  1877  			{
  1878  				User:     "tester",
  1879  				Host:     "localhost",
  1880  				Query:    "SELECT count(*) FROM information_schema.statistics where table_schema = 'mydb';",
  1881  				Expected: []sql.Row{{0}},
  1882  			},
  1883  			{
  1884  				User:     "root",
  1885  				Host:     "localhost",
  1886  				Query:    "GRANT INSERT ON mydb.checks TO tester@localhost;",
  1887  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1888  			},
  1889  			{
  1890  				User:     "tester",
  1891  				Host:     "localhost",
  1892  				Query:    "select table_name, column_name, index_name from information_schema.statistics where table_schema = 'mydb';",
  1893  				Expected: []sql.Row{{"checks", "a", "PRIMARY"}},
  1894  			},
  1895  		},
  1896  	},
  1897  	{
  1898  		Name: "basic tests on information_schema.SCHEMA_PRIVILEGES table",
  1899  		SetUpScript: []string{
  1900  			"CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))",
  1901  			"CREATE USER tester@localhost;",
  1902  			"CREATE USER admin@localhost;",
  1903  		},
  1904  		Assertions: []UserPrivilegeTestAssertion{
  1905  			{
  1906  				User:     "root",
  1907  				Host:     "localhost",
  1908  				Query:    "select * from information_schema.schema_privileges;",
  1909  				Expected: []sql.Row{},
  1910  			},
  1911  			{
  1912  				User:     "root",
  1913  				Host:     "localhost",
  1914  				Query:    "GRANT INSERT, REFERENCES ON mydb.* TO tester@localhost;",
  1915  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1916  			},
  1917  			{
  1918  				User:     "root",
  1919  				Host:     "localhost",
  1920  				Query:    "GRANT UPDATE, GRANT OPTION ON mydb.* TO admin@localhost;",
  1921  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1922  			},
  1923  			{
  1924  				User:     "root",
  1925  				Host:     "localhost",
  1926  				Query:    "select * from information_schema.schema_privileges order by privilege_type, is_grantable;",
  1927  				Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "REFERENCES", "NO"}, {"'admin'@'localhost'", "def", "mydb", "UPDATE", "YES"}},
  1928  			},
  1929  			{
  1930  				User:     "tester",
  1931  				Host:     "localhost",
  1932  				Query:    "select * from information_schema.schema_privileges order by privilege_type, is_grantable;",
  1933  				Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "REFERENCES", "NO"}},
  1934  			},
  1935  			{
  1936  				User:     "admin",
  1937  				Host:     "localhost",
  1938  				Query:    "select * from information_schema.schema_privileges order by privilege_type, is_grantable;",
  1939  				Expected: []sql.Row{{"'admin'@'localhost'", "def", "mydb", "UPDATE", "YES"}},
  1940  			},
  1941  			{
  1942  				User:     "root",
  1943  				Host:     "localhost",
  1944  				Query:    "GRANT SELECT ON mysql.* TO admin@localhost;",
  1945  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1946  			},
  1947  			{
  1948  				User:     "admin",
  1949  				Host:     "localhost",
  1950  				Query:    "select * from information_schema.schema_privileges order by privilege_type, is_grantable;",
  1951  				Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "REFERENCES", "NO"}, {"'admin'@'localhost'", "def", "mysql", "SELECT", "NO"}, {"'admin'@'localhost'", "def", "mydb", "UPDATE", "YES"}},
  1952  			},
  1953  		},
  1954  	},
  1955  	{
  1956  		Name: "basic tests on information_schema.TABLE_PRIVILEGES table",
  1957  		SetUpScript: []string{
  1958  			"CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))",
  1959  			"CREATE TABLE test (pk BIGINT PRIMARY KEY, c VARCHAR(20), p POINT default (POINT(1,1)))",
  1960  			"CREATE USER tester@localhost;",
  1961  			"CREATE USER admin@localhost;",
  1962  		},
  1963  		Assertions: []UserPrivilegeTestAssertion{
  1964  			{
  1965  				User:     "root",
  1966  				Host:     "localhost",
  1967  				Query:    "select * from information_schema.table_privileges;",
  1968  				Expected: []sql.Row{},
  1969  			},
  1970  			{
  1971  				User:     "root",
  1972  				Host:     "localhost",
  1973  				Query:    "GRANT INSERT ON mydb.checks TO tester@localhost;",
  1974  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1975  			},
  1976  			{
  1977  				User:     "root",
  1978  				Host:     "localhost",
  1979  				Query:    "GRANT UPDATE, GRANT OPTION ON mydb.test TO tester@localhost;",
  1980  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1981  			},
  1982  			{
  1983  				User:     "root",
  1984  				Host:     "localhost",
  1985  				Query:    "select * from information_schema.table_privileges order by privilege_type, is_grantable;/*root*/",
  1986  				Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "checks", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "test", "UPDATE", "YES"}},
  1987  			},
  1988  			{
  1989  				User:     "tester",
  1990  				Host:     "localhost",
  1991  				Query:    "select * from information_schema.table_privileges order by privilege_type, is_grantable;/*tester*/",
  1992  				Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "checks", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "test", "UPDATE", "YES"}},
  1993  			},
  1994  			{
  1995  				User:     "admin",
  1996  				Host:     "localhost",
  1997  				Query:    "select * from information_schema.table_privileges order by privilege_type, is_grantable;/*admin1*/",
  1998  				Expected: []sql.Row{},
  1999  			},
  2000  			{
  2001  				User:     "root",
  2002  				Host:     "localhost",
  2003  				Query:    "GRANT SELECT ON mysql.* TO admin@localhost;",
  2004  				Expected: []sql.Row{{types.NewOkResult(0)}},
  2005  			},
  2006  			{
  2007  				User:     "admin",
  2008  				Host:     "localhost",
  2009  				Query:    "select * from information_schema.table_privileges order by privilege_type, is_grantable;/*admin2*/",
  2010  				Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "checks", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "test", "UPDATE", "YES"}},
  2011  			},
  2012  		},
  2013  	},
  2014  	{
  2015  		Name: "basic tests on information_schema.USER_PRIVILEGES table",
  2016  		SetUpScript: []string{
  2017  			"CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))",
  2018  			"CREATE TABLE test (pk BIGINT PRIMARY KEY, c VARCHAR(20), p POINT default (POINT(1,1)))",
  2019  			"CREATE USER tester@localhost;",
  2020  			"CREATE USER admin@localhost;",
  2021  		},
  2022  		Assertions: []UserPrivilegeTestAssertion{
  2023  			{
  2024  				User:  "root",
  2025  				Host:  "localhost",
  2026  				Query: "select * from information_schema.user_privileges order by privilege_type LIMIT 4;/*root*/",
  2027  				Expected: []sql.Row{{"'root'@'localhost'", "def", "ALTER", "YES"},
  2028  					{"'root'@'localhost'", "def", "ALTER ROUTINE", "YES"},
  2029  					{"'root'@'localhost'", "def", "CREATE", "YES"},
  2030  					{"'root'@'localhost'", "def", "CREATE ROLE", "YES"}},
  2031  			},
  2032  			{
  2033  				User:     "root",
  2034  				Host:     "localhost",
  2035  				Query:    "GRANT INSERT ON *.* TO tester@localhost;",
  2036  				Expected: []sql.Row{{types.NewOkResult(0)}},
  2037  			},
  2038  			{
  2039  				User:     "tester",
  2040  				Host:     "localhost",
  2041  				Query:    "select * from information_schema.user_privileges order by privilege_type, is_grantable;/*tester1*/",
  2042  				Expected: []sql.Row{{"'tester'@'localhost'", "def", "INSERT", "NO"}},
  2043  			},
  2044  			{
  2045  				User:     "root",
  2046  				Host:     "localhost",
  2047  				Query:    "GRANT UPDATE, GRANT OPTION ON *.* TO tester@localhost;",
  2048  				Expected: []sql.Row{{types.NewOkResult(0)}},
  2049  			},
  2050  			{
  2051  				User:     "tester",
  2052  				Host:     "localhost",
  2053  				Query:    "select * from information_schema.user_privileges order by privilege_type, is_grantable;/*tester2*/",
  2054  				Expected: []sql.Row{{"'tester'@'localhost'", "def", "INSERT", "YES"}, {"'tester'@'localhost'", "def", "UPDATE", "YES"}},
  2055  			},
  2056  			{
  2057  				User:     "admin",
  2058  				Host:     "localhost",
  2059  				Query:    "select * from information_schema.user_privileges order by privilege_type, is_grantable;/*admin*/",
  2060  				Expected: []sql.Row{},
  2061  			},
  2062  		},
  2063  	},
  2064  	{
  2065  		Name: "basic tests on information_schema.USER_ATTRIBUTES table",
  2066  		SetUpScript: []string{
  2067  			"CREATE USER tester@localhost;",
  2068  			// TODO: attributes info is ignored in sqlparser
  2069  			`CREATE USER admin@localhost ATTRIBUTE '{"fname": "Josh", "lname": "Scott"}';`,
  2070  			"GRANT UPDATE ON mysql.* TO admin@localhost;",
  2071  		},
  2072  		Assertions: []UserPrivilegeTestAssertion{
  2073  			{
  2074  				User:  "root",
  2075  				Host:  "localhost",
  2076  				Query: "select * from information_schema.user_attributes order by user;/*root*/",
  2077  				Expected: []sql.Row{{"admin", "localhost", nil},
  2078  					{"root", "localhost", nil},
  2079  					{"tester", "localhost", nil}},
  2080  			},
  2081  			{
  2082  				User:  "admin",
  2083  				Host:  "localhost",
  2084  				Query: "select * from information_schema.user_attributes order by user;/*admin*/",
  2085  				Expected: []sql.Row{{"admin", "localhost", nil},
  2086  					{"root", "localhost", nil},
  2087  					{"tester", "localhost", nil}},
  2088  			},
  2089  			{
  2090  				User:     "tester",
  2091  				Host:     "localhost",
  2092  				Query:    "select * from information_schema.user_attributes order by user;/*tester*/",
  2093  				Expected: []sql.Row{{"tester", "localhost", nil}},
  2094  			},
  2095  		},
  2096  	},
  2097  	{
  2098  		Name: "basic privilege tests on information_schema.ROUTINES and PARAMETERS tables",
  2099  		SetUpScript: []string{
  2100  			"CREATE USER tester@localhost;",
  2101  			"CREATE PROCEDURE testabc(IN x DOUBLE, IN y FLOAT, OUT abc DECIMAL(5,1)) SELECT x*y INTO abc",
  2102  		},
  2103  		Assertions: []UserPrivilegeTestAssertion{
  2104  			{
  2105  				User:     "tester",
  2106  				Host:     "localhost",
  2107  				Query:    "select count(*) from information_schema.routines where routine_name = 'testabc'/*tester1*/;",
  2108  				Expected: []sql.Row{{0}},
  2109  			},
  2110  			{
  2111  				User:     "tester",
  2112  				Host:     "localhost",
  2113  				Query:    "select count(*) from information_schema.parameters where specific_name = 'testabc'/*tester1*/;",
  2114  				Expected: []sql.Row{{0}},
  2115  			},
  2116  			{
  2117  				User:     "root",
  2118  				Host:     "localhost",
  2119  				Query:    "GRANT CREATE ROUTINE ON mydb.* TO tester@localhost;",
  2120  				Expected: []sql.Row{{types.NewOkResult(0)}},
  2121  			},
  2122  			{
  2123  				User:     "tester",
  2124  				Host:     "localhost",
  2125  				Query:    "select count(*) from information_schema.routines where routine_name = 'testabc';",
  2126  				Expected: []sql.Row{{1}},
  2127  			},
  2128  			{
  2129  				User:     "tester",
  2130  				Host:     "localhost",
  2131  				Query:    "select count(*) from information_schema.parameters where specific_name = 'testabc';",
  2132  				Expected: []sql.Row{{3}},
  2133  			},
  2134  		},
  2135  	},
  2136  }
  2137  
  2138  // NoopPlaintextPlugin is used to authenticate plaintext user plugins
  2139  type NoopPlaintextPlugin struct{}
  2140  
  2141  var _ mysql_db.PlaintextAuthPlugin = &NoopPlaintextPlugin{}
  2142  
  2143  func (p *NoopPlaintextPlugin) Authenticate(db *mysql_db.MySQLDb, user string, userEntry *mysql_db.User, pass string) (bool, error) {
  2144  	return pass == "right-password", nil
  2145  }
  2146  
  2147  // ServerAuthTests test the server authentication system. These tests always have the root account available, and the
  2148  // root account is used with any queries in the SetUpScript, along as being set to the context passed to SetUpFunc.
  2149  var ServerAuthTests = []ServerAuthenticationTest{
  2150  	{
  2151  		Name: "ALTER USER can change passwords",
  2152  		Assertions: []ServerAuthenticationTestAssertion{
  2153  			// Create test users, privileges, etc
  2154  			{
  2155  				Username:    "root",
  2156  				Password:    "",
  2157  				Query:       "CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY);",
  2158  				ExpectedErr: false,
  2159  			}, {
  2160  				// Create a user with CREATE USER privileges
  2161  				Username:    "root",
  2162  				Password:    "",
  2163  				Query:       "CREATE USER `createUserUser`@`localhost` IDENTIFIED BY '';",
  2164  				ExpectedErr: false,
  2165  			}, {
  2166  				Username:    "root",
  2167  				Password:    "",
  2168  				Query:       "GRANT CREATE USER ON *.* TO `createUserUser`@`localhost`;",
  2169  				ExpectedErr: false,
  2170  			}, {
  2171  				// Create a user with UPDATE privileges on the mysql database
  2172  				Username:    "root",
  2173  				Password:    "",
  2174  				Query:       "CREATE USER `updateUser`@`localhost` IDENTIFIED BY '';",
  2175  				ExpectedErr: false,
  2176  			}, {
  2177  				Username:    "root",
  2178  				Password:    "",
  2179  				Query:       "GRANT UPDATE ON mysql.* TO `updateUser`@`localhost`;",
  2180  				ExpectedErr: false,
  2181  			}, {
  2182  				// Create a regular user named user1 with SELECT privileges
  2183  				Username:    "root",
  2184  				Password:    "",
  2185  				Query:       "CREATE USER `user1`@`localhost` IDENTIFIED BY '';",
  2186  				ExpectedErr: false,
  2187  			}, {
  2188  				Username:    "root",
  2189  				Password:    "",
  2190  				Query:       "GRANT SELECT ON *.* TO `user1`@`localhost`;",
  2191  				ExpectedErr: false,
  2192  			}, {
  2193  				// Create a regular user named user2 with SELECT privileges
  2194  				Username:    "root",
  2195  				Password:    "",
  2196  				Query:       "CREATE USER `user2`@`localhost` IDENTIFIED BY '';",
  2197  				ExpectedErr: false,
  2198  			}, {
  2199  				Username:    "root",
  2200  				Password:    "",
  2201  				Query:       "GRANT SELECT ON *.* TO `user2`@`localhost`;",
  2202  				ExpectedErr: false,
  2203  			},
  2204  
  2205  			// When IF EXISTS is specified, an error isn't returned if the user doesn't exist
  2206  			{
  2207  				Username:    "root",
  2208  				Password:    "",
  2209  				Query:       "ALTER USER IF EXISTS nobody@localhost IDENTIFIED BY 'password';",
  2210  				ExpectedErr: false,
  2211  			}, {
  2212  				Username:       "root",
  2213  				Password:       "",
  2214  				Query:          "ALTER USER nobody@localhost IDENTIFIED BY 'password';",
  2215  				ExpectedErr:    true,
  2216  				ExpectedErrStr: "Error 1105 (HY000): Operation ALTER USER failed for 'nobody'@'localhost'",
  2217  			},
  2218  
  2219  			// RANDOM PASSWORD is not supported yet, so an error should be returned
  2220  			{
  2221  				Username:    "root",
  2222  				Password:    "",
  2223  				Query:       "ALTER USER user2@localhost IDENTIFIED BY RANDOM PASSWORD;",
  2224  				ExpectedErr: true,
  2225  				ExpectedErrStr: "Error 1105 (HY000): random password generation is not currently supported; " +
  2226  					"you can request support at https://github.com/dolthub/dolt/issues/new",
  2227  			},
  2228  
  2229  			// root super user can change other account passwords
  2230  			{
  2231  				Username:    "root",
  2232  				Password:    "",
  2233  				Query:       "ALTER USER `user1`@`localhost` IDENTIFIED BY 'password1';",
  2234  				ExpectedErr: false,
  2235  			}, {
  2236  				Username:    "user1",
  2237  				Password:    "",
  2238  				Query:       "SELECT * FROM mydb.test;",
  2239  				ExpectedErr: true,
  2240  			}, {
  2241  				Username:    "user1",
  2242  				Password:    "password1",
  2243  				Query:       "SELECT * FROM mydb.test;",
  2244  				ExpectedErr: false,
  2245  			},
  2246  
  2247  			// Accounts with the CREATE USER privilege can change other account passwords
  2248  			{
  2249  				Username:    "createUserUser",
  2250  				Password:    "",
  2251  				Query:       "ALTER USER `user1`@`localhost` IDENTIFIED BY 'password2';",
  2252  				ExpectedErr: false,
  2253  			}, {
  2254  				Username:    "user1",
  2255  				Password:    "",
  2256  				Query:       "SELECT * FROM mydb.test;",
  2257  				ExpectedErr: true,
  2258  			}, {
  2259  				Username:    "user1",
  2260  				Password:    "password2",
  2261  				Query:       "SELECT * FROM mydb.test;",
  2262  				ExpectedErr: false,
  2263  			},
  2264  
  2265  			// Accounts with the UPDATE privilege on the mysql db can change other account passwords
  2266  			{
  2267  				Username:    "updateUser",
  2268  				Password:    "",
  2269  				Query:       "ALTER USER `user2`@`localhost` IDENTIFIED BY 'password3';",
  2270  				ExpectedErr: false,
  2271  			}, {
  2272  				Username:    "user2",
  2273  				Password:    "",
  2274  				Query:       "SELECT * FROM mydb.test;",
  2275  				ExpectedErr: true,
  2276  			}, {
  2277  				Username:    "user2",
  2278  				Password:    "password3",
  2279  				Query:       "SELECT * FROM mydb.test;",
  2280  				ExpectedErr: false,
  2281  			},
  2282  
  2283  			// Accounts can change their own password
  2284  			{
  2285  				Username:    "user1",
  2286  				Password:    "password2",
  2287  				Query:       "ALTER USER `user1`@`localhost` IDENTIFIED BY 'password4';",
  2288  				ExpectedErr: false,
  2289  			}, {
  2290  				Username:    "user1",
  2291  				Password:    "",
  2292  				Query:       "SELECT * FROM mydb.test;",
  2293  				ExpectedErr: true,
  2294  			}, {
  2295  				Username:    "user1",
  2296  				Password:    "password4",
  2297  				Query:       "SELECT * FROM mydb.test;",
  2298  				ExpectedErr: false,
  2299  			},
  2300  
  2301  			// Accounts CANNOT change another account's password (without the CREATE USER or UPDATE privilege)
  2302  			{
  2303  				Username:    "user1",
  2304  				Password:    "password2",
  2305  				Query:       "ALTER USER `user2`@`localhost` IDENTIFIED BY 'password5';",
  2306  				ExpectedErr: true,
  2307  			},
  2308  		},
  2309  	},
  2310  	{
  2311  		Name: "DROP USER reports correct string for missing address",
  2312  		Assertions: []ServerAuthenticationTestAssertion{
  2313  			{
  2314  				Username:       "root",
  2315  				Password:       "",
  2316  				Query:          "DROP USER xyz;",
  2317  				ExpectedErrStr: "Error 1105 (HY000): Operation DROP USER failed for 'xyz'@'%'",
  2318  			},
  2319  		},
  2320  	},
  2321  	{
  2322  		Name: "CREATE USER with a random password is not supported",
  2323  		Assertions: []ServerAuthenticationTestAssertion{
  2324  			{
  2325  				Username:    "root",
  2326  				Password:    "",
  2327  				Query:       "CREATE USER foo1@localhost IDENTIFIED BY RANDOM PASSWORD;",
  2328  				ExpectedErr: true,
  2329  				ExpectedErrStr: "Error 1105 (HY000): random password generation is not currently supported; " +
  2330  					"you can request support at https://github.com/dolthub/dolt/issues/new",
  2331  			},
  2332  		},
  2333  	},
  2334  	{
  2335  		Name: "CREATE USER with an empty password",
  2336  		Assertions: []ServerAuthenticationTestAssertion{
  2337  			{
  2338  				Username:    "root",
  2339  				Password:    "",
  2340  				Query:       "CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY);",
  2341  				ExpectedErr: false,
  2342  			},
  2343  			{
  2344  				Username:    "root",
  2345  				Password:    "",
  2346  				Query:       "CREATE USER rand_user@localhost IDENTIFIED BY '';",
  2347  				ExpectedErr: false,
  2348  			},
  2349  			{
  2350  				Username:    "root",
  2351  				Password:    "",
  2352  				Query:       "GRANT ALL ON *.* TO rand_user@localhost;",
  2353  				ExpectedErr: false,
  2354  			},
  2355  			{
  2356  				Username:    "rand_user",
  2357  				Password:    "",
  2358  				Query:       "SELECT * FROM mydb.test;",
  2359  				ExpectedErr: false,
  2360  			},
  2361  		},
  2362  	},
  2363  	{
  2364  		Name: "Basic root authentication",
  2365  		Assertions: []ServerAuthenticationTestAssertion{
  2366  			{
  2367  				Username:    "root",
  2368  				Password:    "",
  2369  				Query:       "SELECT * FROM mysql.user;",
  2370  				ExpectedErr: false,
  2371  			},
  2372  			{
  2373  				Username:    "root",
  2374  				Password:    "pass",
  2375  				Query:       "SELECT * FROM mysql.user;",
  2376  				ExpectedErr: true,
  2377  			},
  2378  		},
  2379  	},
  2380  	{
  2381  		Name: "Create User without plugin specification",
  2382  		SetUpScript: []string{
  2383  			"CREATE USER rand_user@localhost IDENTIFIED BY 'rand_pass';",
  2384  			"GRANT ALL ON *.* TO rand_user@localhost WITH GRANT OPTION;",
  2385  		},
  2386  		Assertions: []ServerAuthenticationTestAssertion{
  2387  			{
  2388  				Username:    "rand_user",
  2389  				Password:    "rand_pass",
  2390  				Query:       "SELECT * FROM mysql.user;",
  2391  				ExpectedErr: false,
  2392  			},
  2393  			{
  2394  				Username:    "rand_user",
  2395  				Password:    "rand_pass1",
  2396  				Query:       "SELECT * FROM mysql.user;",
  2397  				ExpectedErr: true,
  2398  			},
  2399  			{
  2400  				Username:    "rand_user",
  2401  				Password:    "",
  2402  				Query:       "SELECT * FROM mysql.user;",
  2403  				ExpectedErr: true,
  2404  			},
  2405  			{
  2406  				Username:    "rand_use",
  2407  				Password:    "rand_pass",
  2408  				Query:       "SELECT * FROM mysql.user;",
  2409  				ExpectedErr: true,
  2410  			},
  2411  		},
  2412  	},
  2413  	{
  2414  		Name: "Create User with plugin specification",
  2415  		SetUpScript: []string{
  2416  			"CREATE USER ranuse@localhost IDENTIFIED WITH mysql_native_password BY 'ranpas';",
  2417  			"GRANT ALL ON *.* TO ranuse@localhost WITH GRANT OPTION;",
  2418  		},
  2419  		Assertions: []ServerAuthenticationTestAssertion{
  2420  			{
  2421  				Username:    "ranuse",
  2422  				Password:    "ranpas",
  2423  				Query:       "SELECT * FROM mysql.user;",
  2424  				ExpectedErr: false,
  2425  			},
  2426  			{
  2427  				Username:    "ranuse",
  2428  				Password:    "what",
  2429  				Query:       "SELECT * FROM mysql.user;",
  2430  				ExpectedErr: true,
  2431  			},
  2432  			{
  2433  				Username:    "ranuse",
  2434  				Password:    "",
  2435  				Query:       "SELECT * FROM mysql.user;",
  2436  				ExpectedErr: true,
  2437  			},
  2438  		},
  2439  	},
  2440  	{
  2441  		Name: "Create User with jwt plugin specification",
  2442  		SetUpScript: []string{
  2443  			"CREATE USER `test-user`@localhost IDENTIFIED WITH authentication_dolt_jwt AS 'jwks=testing,sub=test-user,iss=dolthub.com,aud=some_id';",
  2444  			"GRANT ALL ON *.* TO `test-user`@localhost WITH GRANT OPTION;",
  2445  		},
  2446  		SetUpFunc: func(ctx *sql.Context, t *testing.T, engine *sqle.Engine) {
  2447  			plugins := map[string]mysql_db.PlaintextAuthPlugin{"authentication_dolt_jwt": &NoopPlaintextPlugin{}}
  2448  			engine.EngineAnalyzer().Catalog.MySQLDb.SetPlugins(plugins)
  2449  		},
  2450  		Assertions: []ServerAuthenticationTestAssertion{
  2451  			{
  2452  				Username:    "test-user",
  2453  				Password:    "what",
  2454  				Query:       "SELECT * FROM mysql.user;",
  2455  				ExpectedErr: true,
  2456  			},
  2457  			{
  2458  				Username:    "test-user",
  2459  				Password:    "",
  2460  				Query:       "SELECT * FROM mysql.user;",
  2461  				ExpectedErr: true,
  2462  			},
  2463  			{
  2464  				Username:    "test-user",
  2465  				Password:    "right-password",
  2466  				Query:       "SELECT * FROM mysql.user;",
  2467  				ExpectedErr: false,
  2468  			},
  2469  		},
  2470  	},
  2471  	{
  2472  		Name: "Adding a Super User directly",
  2473  		SetUpFunc: func(ctx *sql.Context, t *testing.T, engine *sqle.Engine) {
  2474  			ed := engine.EngineAnalyzer().Catalog.MySQLDb.Editor()
  2475  			defer ed.Close()
  2476  			engine.EngineAnalyzer().Catalog.MySQLDb.AddSuperUser(ed, "bestuser", "localhost", "the_pass")
  2477  		},
  2478  		Assertions: []ServerAuthenticationTestAssertion{
  2479  			{
  2480  				Username:    "bestuser",
  2481  				Password:    "the_past",
  2482  				Query:       "SELECT * FROM mysql.user;",
  2483  				ExpectedErr: true,
  2484  			},
  2485  			{
  2486  				Username:    "bestuser",
  2487  				Password:    "the_pass",
  2488  				Query:       "SELECT * FROM mysql.user;",
  2489  				ExpectedErr: false,
  2490  			},
  2491  		},
  2492  	},
  2493  }
  2494  
  2495  // QuickPrivTests are test that specifically attempt to test as many privileges against as many statements as possible,
  2496  // while being as succinct as possible. All tests here could be fully represented as a UserPrivilegeTest, however each
  2497  // equivalent test would comparatively take up many more lines. This is intended to have as many tests as possible that
  2498  // are as quick to write as possible.
  2499  var QuickPrivTests = []QuickPrivilegeTest{
  2500  	{
  2501  		Queries: []string{
  2502  			"GRANT SELECT ON *.* TO tester@localhost",
  2503  			"SELECT * FROM mydb.test",
  2504  		},
  2505  		Expected: []sql.Row{{0, 0}, {1, 1}},
  2506  	},
  2507  	{
  2508  		Queries: []string{
  2509  			"GRANT SELECT ON mydb.* TO tester@localhost",
  2510  			"SELECT * FROM mydb.test",
  2511  		},
  2512  		Expected: []sql.Row{{0, 0}, {1, 1}},
  2513  	},
  2514  	{
  2515  		Queries: []string{
  2516  			"GRANT SELECT ON mydb.* TO tester@localhost",
  2517  			"SELECT * FROM mydb.test2",
  2518  		},
  2519  		Expected: []sql.Row{{0, 1}, {1, 2}},
  2520  	},
  2521  	{
  2522  		Queries: []string{
  2523  			"GRANT SELECT ON mydb.test TO tester@localhost",
  2524  			"SELECT * FROM mydb.test",
  2525  		},
  2526  		Expected: []sql.Row{{0, 0}, {1, 1}},
  2527  	},
  2528  	{
  2529  		Queries: []string{
  2530  			"GRANT SELECT ON mydb.test TO tester@localhost",
  2531  			"SELECT * FROM mydb.test2",
  2532  		},
  2533  		ExpectingErr: true,
  2534  	},
  2535  	{
  2536  		Queries: []string{
  2537  			"GRANT SELECT ON otherdb.* TO tester@localhost",
  2538  			"SELECT * FROM mydb.test",
  2539  		},
  2540  		ExpectingErr: true,
  2541  	},
  2542  	{
  2543  		Queries: []string{
  2544  			"GRANT SELECT ON otherdb.test TO tester@localhost",
  2545  			"SELECT * FROM mydb.test",
  2546  		},
  2547  		ExpectingErr: true,
  2548  	},
  2549  	{
  2550  		Queries: []string{
  2551  			"GRANT SELECT ON otherdb.test TO tester@localhost",
  2552  			"SELECT * FROM mydb.test",
  2553  		},
  2554  		ExpectingErr: true,
  2555  	},
  2556  	{
  2557  		Queries: []string{
  2558  			"GRANT SELECT ON *.* TO tester@localhost",
  2559  			"USE mydb;",
  2560  			"SHOW TABLES;",
  2561  		},
  2562  		Expected: []sql.Row{{"test"}, {"test2"}},
  2563  	},
  2564  	{
  2565  		Queries: []string{
  2566  			"GRANT SELECT ON mydb.* TO tester@localhost",
  2567  			"USE mydb;",
  2568  			"SHOW TABLES;",
  2569  		},
  2570  		Expected: []sql.Row{{"test"}, {"test2"}},
  2571  	},
  2572  	{
  2573  		Queries: []string{
  2574  			"GRANT SELECT ON mydb.test TO tester@localhost",
  2575  			"USE mydb;",
  2576  			"SHOW TABLES;",
  2577  		},
  2578  		Expected: []sql.Row{{"test"}},
  2579  	},
  2580  	{
  2581  		Queries: []string{
  2582  			"GRANT SELECT ON mydb.non_exist TO tester@localhost",
  2583  			"USE mydb;",
  2584  			"SHOW TABLES;",
  2585  		},
  2586  		Expected: []sql.Row{},
  2587  	},
  2588  	{
  2589  		Queries: []string{
  2590  			"ALTER TABLE mydb.test ADD COLUMN new_column BIGINT;",
  2591  		},
  2592  		ExpectingErr: true,
  2593  	},
  2594  	{
  2595  		Queries: []string{
  2596  			"GRANT ALTER ON *.* TO tester@localhost",
  2597  			"ALTER TABLE mydb.test ADD COLUMN new_column BIGINT",
  2598  		},
  2599  	},
  2600  	{
  2601  		Queries: []string{
  2602  			"GRANT ALTER ON mydb.* TO tester@localhost",
  2603  			"ALTER TABLE mydb.test ADD COLUMN new_column BIGINT;",
  2604  		},
  2605  	},
  2606  	{
  2607  		Queries: []string{
  2608  			"GRANT ALTER ON mydb.test TO tester@localhost",
  2609  			"ALTER TABLE mydb.test ADD COLUMN new_column BIGINT;",
  2610  		},
  2611  	},
  2612  	{
  2613  		Queries: []string{
  2614  			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
  2615  		},
  2616  		ExpectingErr: true,
  2617  	},
  2618  	{
  2619  		Queries: []string{
  2620  			"GRANT ALTER ON *.* TO tester@localhost",
  2621  			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
  2622  		},
  2623  		ExpectingErr: true,
  2624  	},
  2625  	{
  2626  		Queries: []string{
  2627  			"GRANT ALTER, CREATE, DROP, INSERT ON *.* TO tester@localhost",
  2628  			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
  2629  		},
  2630  	},
  2631  	{
  2632  		Queries: []string{
  2633  			"GRANT ALTER, CREATE, DROP, INSERT ON mydb.* TO tester@localhost",
  2634  			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
  2635  		},
  2636  	},
  2637  	{
  2638  		Queries: []string{
  2639  			"GRANT ALTER, CREATE, DROP, INSERT ON mydb.test TO tester@localhost",
  2640  			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
  2641  		},
  2642  		ExpectingErr: true,
  2643  	},
  2644  	{
  2645  		Queries: []string{
  2646  			"GRANT ALTER, DROP ON mydb.test TO tester@localhost",
  2647  			"GRANT CREATE, INSERT ON mydb.new_test TO tester@localhost",
  2648  			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
  2649  		},
  2650  	},
  2651  	{
  2652  		Queries: []string{
  2653  			"GRANT ALTER ON mydb.test TO tester@localhost",
  2654  			"GRANT CREATE, INSERT ON mydb.new_test TO tester@localhost",
  2655  			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
  2656  		},
  2657  		ExpectingErr: true,
  2658  	},
  2659  	{
  2660  		Queries: []string{
  2661  			"GRANT DROP ON mydb.test TO tester@localhost",
  2662  			"GRANT CREATE, INSERT ON mydb.new_test TO tester@localhost",
  2663  			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
  2664  		},
  2665  		ExpectingErr: true,
  2666  	},
  2667  	{
  2668  		Queries: []string{
  2669  			"GRANT ALTER, DROP ON mydb.test TO tester@localhost",
  2670  			"GRANT CREATE ON mydb.new_test TO tester@localhost",
  2671  			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
  2672  		},
  2673  		ExpectingErr: true,
  2674  	},
  2675  	{
  2676  		Queries: []string{
  2677  			"GRANT ALTER, DROP ON mydb.test TO tester@localhost",
  2678  			"GRANT INSERT ON mydb.new_test TO tester@localhost",
  2679  			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
  2680  		},
  2681  		ExpectingErr: true,
  2682  	},
  2683  	{
  2684  		Queries: []string{
  2685  			"USE mydb;",
  2686  			"CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;",
  2687  			"DROP PROCEDURE new_proc;",
  2688  		},
  2689  		ExpectingErr: true,
  2690  	},
  2691  	{
  2692  		Queries: []string{
  2693  			"GRANT ALTER ROUTINE ON *.* TO tester@localhost",
  2694  			"USE mydb;",
  2695  			"CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;",
  2696  			"DROP PROCEDURE new_proc;",
  2697  		},
  2698  	},
  2699  	{
  2700  		Queries: []string{
  2701  			"GRANT ALTER ROUTINE ON mydb.* TO tester@localhost",
  2702  			"USE mydb;",
  2703  			"CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;",
  2704  			"DROP PROCEDURE new_proc;",
  2705  		},
  2706  	},
  2707  	{
  2708  		Queries: []string{
  2709  			"CREATE DATABASE new_db;",
  2710  		},
  2711  		ExpectingErr: true,
  2712  	},
  2713  	{
  2714  		Queries: []string{
  2715  			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
  2716  		},
  2717  		ExpectingErr: true,
  2718  	},
  2719  	{
  2720  		Queries: []string{
  2721  			"GRANT CREATE ON *.* TO tester@localhost",
  2722  			"CREATE DATABASE new_db2;",
  2723  			"GRANT DROP ON *.* TO tester@localhost",
  2724  			"drop database new_db2",
  2725  		},
  2726  	},
  2727  	{
  2728  		Queries: []string{
  2729  			"GRANT CREATE ON *.* TO tester@localhost",
  2730  			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
  2731  		},
  2732  	},
  2733  	{
  2734  		Queries: []string{
  2735  			"GRANT CREATE ON mydb.* TO tester@localhost",
  2736  			"CREATE DATABASE new_db3;",
  2737  			"GRANT DROP ON *.* TO tester@localhost",
  2738  			"drop database new_db3",
  2739  		},
  2740  	},
  2741  	{
  2742  		Queries: []string{
  2743  			"GRANT CREATE ON mydb.* TO tester@localhost",
  2744  			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
  2745  		},
  2746  	},
  2747  	{
  2748  		Queries: []string{
  2749  			"CREATE ROLE new_role;",
  2750  		},
  2751  		ExpectingErr: true,
  2752  	},
  2753  	{
  2754  		Queries: []string{
  2755  			"GRANT CREATE ROLE ON *.* TO tester@localhost",
  2756  			"CREATE ROLE new_role;",
  2757  		},
  2758  	},
  2759  	{
  2760  		Queries: []string{
  2761  			"USE mydb;",
  2762  			"CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;",
  2763  		},
  2764  		ExpectingErr: true,
  2765  	},
  2766  	{
  2767  		Queries: []string{
  2768  			"GRANT CREATE ROUTINE ON *.* TO tester@localhost",
  2769  			"USE mydb;",
  2770  			"CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;",
  2771  		},
  2772  	},
  2773  	{
  2774  		Queries: []string{
  2775  			"GRANT CREATE ROUTINE ON mydb.* TO tester@localhost",
  2776  			"USE mydb;",
  2777  			"CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;",
  2778  		},
  2779  	},
  2780  	{
  2781  		Queries: []string{
  2782  			"CREATE USER new_user;",
  2783  		},
  2784  		ExpectingErr: true,
  2785  	},
  2786  	{
  2787  		Queries: []string{
  2788  			"CREATE USER new_user;",
  2789  			"DROP USER new_user;",
  2790  		},
  2791  		ExpectingErr: true,
  2792  	},
  2793  	{
  2794  		Queries: []string{
  2795  			"GRANT CREATE USER ON *.* TO tester@localhost",
  2796  			"CREATE USER new_user;",
  2797  		},
  2798  	},
  2799  	{
  2800  		Queries: []string{
  2801  			"GRANT CREATE USER ON *.* TO tester@localhost",
  2802  			"CREATE USER new_user;",
  2803  			"DROP USER new_user;",
  2804  		},
  2805  	},
  2806  	{
  2807  		Queries: []string{
  2808  			"GRANT CREATE USER ON *.* TO tester@localhost",
  2809  			"CREATE ROLE new_role;",
  2810  		},
  2811  	},
  2812  	{
  2813  		Queries: []string{
  2814  			"GRANT CREATE USER ON *.* TO tester@localhost",
  2815  			"CREATE ROLE new_role;",
  2816  			"DROP ROLE new_role;",
  2817  		},
  2818  	},
  2819  	{
  2820  		Queries: []string{
  2821  			"CREATE VIEW new_view AS SELECT 1;",
  2822  		},
  2823  		ExpectingErr: true,
  2824  	},
  2825  	{
  2826  		Queries: []string{
  2827  			"GRANT CREATE VIEW ON *.* TO tester@localhost",
  2828  			"CREATE VIEW new_view AS SELECT 1;",
  2829  		},
  2830  	},
  2831  	{
  2832  		Queries: []string{
  2833  			"DELETE FROM mydb.test WHERE pk >= 0;",
  2834  		},
  2835  		ExpectingErr: true,
  2836  	},
  2837  	{
  2838  		Queries: []string{
  2839  			"GRANT DELETE ON *.* TO tester@localhost",
  2840  			"DELETE FROM mydb.test WHERE pk >= 0;",
  2841  		},
  2842  	},
  2843  	{
  2844  		Queries: []string{
  2845  			"GRANT DELETE ON mydb.* TO tester@localhost",
  2846  			"DELETE FROM mydb.test WHERE pk >= 0;",
  2847  		},
  2848  	},
  2849  	{
  2850  		Queries: []string{
  2851  			"GRANT DELETE ON mydb.test TO tester@localhost",
  2852  			"DELETE FROM mydb.test WHERE pk >= 0;",
  2853  		},
  2854  	},
  2855  	{
  2856  		Queries: []string{
  2857  			"DELETE test, test2 FROM mydb.test join mydb.test2 where test.pk=test2.pk",
  2858  		},
  2859  		ExpectingErr: true,
  2860  	},
  2861  	{
  2862  		Queries: []string{
  2863  			"GRANT DELETE ON mydb.test TO tester@localhost",
  2864  			"DELETE test, test2 FROM mydb.test join mydb.test2 where test.pk=test2.pk",
  2865  		},
  2866  		ExpectingErr: true,
  2867  	},
  2868  	{
  2869  		Queries: []string{
  2870  			"GRANT DELETE ON mydb.test2 TO tester@localhost",
  2871  			"DELETE test, test2 FROM mydb.test join mydb.test2 where test.pk=test2.pk",
  2872  		},
  2873  		ExpectingErr: true,
  2874  	},
  2875  	{
  2876  		Queries: []string{
  2877  			"GRANT DELETE ON mydb.test TO tester@localhost",
  2878  			"GRANT DELETE ON mydb.test2 TO tester@localhost",
  2879  			"DELETE test, test2 FROM mydb.test join mydb.test2 where test.pk=test2.pk",
  2880  		},
  2881  	},
  2882  	{
  2883  		Queries: []string{
  2884  			"CREATE DATABASE new_db4;",
  2885  		},
  2886  		ExpectingErr: true,
  2887  	},
  2888  	{
  2889  		Queries: []string{
  2890  			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
  2891  			"DROP TABLE mydb.new_table;",
  2892  		},
  2893  		ExpectingErr: true,
  2894  	},
  2895  	{
  2896  		Queries: []string{
  2897  			"CREATE VIEW new_view AS SELECT 1;",
  2898  			"DROP VIEW new_view;",
  2899  		},
  2900  		ExpectingErr: true,
  2901  	},
  2902  	{
  2903  		Queries: []string{
  2904  			"GRANT DROP ON *.* TO tester@localhost",
  2905  			"CREATE DATABASE new_db5;",
  2906  			"GRANT DROP ON *.* TO tester@localhost",
  2907  			"DROP DATABASE new_db5;",
  2908  		},
  2909  	},
  2910  	{
  2911  		Queries: []string{
  2912  			"GRANT DROP ON *.* TO tester@localhost",
  2913  			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
  2914  			"DROP TABLE mydb.new_table;",
  2915  		},
  2916  	},
  2917  	{
  2918  		Queries: []string{
  2919  			"GRANT DROP ON *.* TO tester@localhost",
  2920  			"CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);",
  2921  			"CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);",
  2922  			"DROP TABLE mydb.new_table1, mydb.new_table2;",
  2923  		},
  2924  	},
  2925  	{
  2926  		Queries: []string{
  2927  			"GRANT DROP ON *.* TO tester@localhost",
  2928  			"CREATE VIEW new_view AS SELECT 1;",
  2929  			"DROP VIEW new_view;",
  2930  		},
  2931  	},
  2932  	{
  2933  		Queries: []string{
  2934  			"GRANT DROP ON mydb.* TO tester@localhost",
  2935  			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
  2936  			"DROP TABLE mydb.new_table;",
  2937  		},
  2938  	},
  2939  	{
  2940  		Queries: []string{
  2941  			"GRANT DROP ON mydb.* TO tester@localhost",
  2942  			"CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);",
  2943  			"CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);",
  2944  			"DROP TABLE mydb.new_table1, mydb.new_table2;",
  2945  		},
  2946  	},
  2947  	{
  2948  		Queries: []string{
  2949  			"GRANT DROP ON mydb.new_table TO tester@localhost",
  2950  			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
  2951  			"DROP TABLE mydb.new_table;",
  2952  		},
  2953  	},
  2954  	{
  2955  		Queries: []string{
  2956  			"GRANT DROP ON mydb.new_table1 TO tester@localhost",
  2957  			"CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);",
  2958  			"CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);",
  2959  			"DROP TABLE mydb.new_table1, mydb.new_table2;",
  2960  		},
  2961  		ExpectingErr: true,
  2962  	},
  2963  	{
  2964  		Queries: []string{
  2965  			"GRANT DROP ON mydb.new_table2 TO tester@localhost",
  2966  			"CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);",
  2967  			"CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);",
  2968  			"DROP TABLE mydb.new_table1, mydb.new_table2;",
  2969  		},
  2970  		ExpectingErr: true,
  2971  	},
  2972  	{
  2973  		Queries: []string{
  2974  			"GRANT DROP ON mydb.new_table1 TO tester@localhost",
  2975  			"GRANT DROP ON mydb.new_table2 TO tester@localhost",
  2976  			"CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);",
  2977  			"CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);",
  2978  			"DROP TABLE mydb.new_table1, mydb.new_table2;",
  2979  		},
  2980  	},
  2981  	{
  2982  		Queries: []string{
  2983  			"CREATE ROLE new_role;",
  2984  			"DROP ROLE new_role;",
  2985  		},
  2986  		ExpectingErr: true,
  2987  	},
  2988  	{
  2989  		Queries: []string{
  2990  			"GRANT DROP ROLE ON *.* TO tester@localhost",
  2991  			"CREATE ROLE new_role;",
  2992  			"DROP ROLE new_role;",
  2993  		},
  2994  	},
  2995  	{
  2996  		Queries: []string{
  2997  			"CREATE INDEX new_idx ON mydb.test (v1);",
  2998  		},
  2999  		ExpectingErr: true,
  3000  	},
  3001  	{
  3002  		Queries: []string{
  3003  			"CREATE INDEX new_idx ON mydb.test (v1);",
  3004  			"DROP INDEX new_idx ON mydb.test;",
  3005  		},
  3006  		ExpectingErr: true,
  3007  	},
  3008  	{
  3009  		Queries: []string{
  3010  			"GRANT INDEX ON *.* TO tester@localhost",
  3011  			"CREATE INDEX new_idx ON mydb.test (v1);",
  3012  		},
  3013  	},
  3014  	{
  3015  		Queries: []string{
  3016  			"GRANT INDEX ON *.* TO tester@localhost",
  3017  			"CREATE INDEX new_idx ON mydb.test (v1);",
  3018  			"DROP INDEX new_idx ON mydb.test;",
  3019  		},
  3020  	},
  3021  	{
  3022  		Queries: []string{
  3023  			"GRANT INDEX ON mydb.* TO tester@localhost",
  3024  			"CREATE INDEX new_idx ON mydb.test (v1);",
  3025  		},
  3026  	},
  3027  	{
  3028  		Queries: []string{
  3029  			"GRANT INDEX ON mydb.* TO tester@localhost",
  3030  			"CREATE INDEX new_idx ON mydb.test (v1);",
  3031  			"DROP INDEX new_idx ON mydb.test;",
  3032  		},
  3033  	},
  3034  	{
  3035  		Queries: []string{
  3036  			"GRANT INDEX ON mydb.test TO tester@localhost",
  3037  			"CREATE INDEX new_idx ON mydb.test (v1);",
  3038  		},
  3039  	},
  3040  	{
  3041  		Queries: []string{
  3042  			"GRANT INDEX ON mydb.test TO tester@localhost",
  3043  			"CREATE INDEX new_idx ON mydb.test (v1);",
  3044  			"DROP INDEX new_idx ON mydb.test;",
  3045  		},
  3046  	},
  3047  	{
  3048  		Queries: []string{
  3049  			"INSERT INTO mydb.test VALUES (9, 9);",
  3050  		},
  3051  		ExpectingErr: true,
  3052  	},
  3053  	{
  3054  		Queries: []string{
  3055  			"GRANT INSERT ON *.* TO tester@localhost",
  3056  			"INSERT INTO mydb.test VALUES (9, 9);",
  3057  		},
  3058  	},
  3059  	{
  3060  		Queries: []string{
  3061  			"GRANT INSERT ON mydb.* TO tester@localhost",
  3062  			"INSERT INTO mydb.test VALUES (9, 9);",
  3063  		},
  3064  	},
  3065  	{
  3066  		Queries: []string{
  3067  			"GRANT INSERT ON mydb.test TO tester@localhost",
  3068  			"INSERT INTO mydb.test VALUES (9, 9);",
  3069  		},
  3070  	},
  3071  	{
  3072  		Queries: []string{
  3073  			"CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;",
  3074  		},
  3075  		ExpectingErr: true,
  3076  	},
  3077  	{
  3078  		Queries: []string{
  3079  			"CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;",
  3080  			"DROP TRIGGER new_trig;",
  3081  		},
  3082  		ExpectingErr: true,
  3083  	},
  3084  	{
  3085  		Queries: []string{
  3086  			"GRANT TRIGGER ON *.* TO tester@localhost",
  3087  			"CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;",
  3088  		},
  3089  	},
  3090  	{
  3091  		Queries: []string{
  3092  			"GRANT TRIGGER ON *.* TO tester@localhost",
  3093  			"CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;",
  3094  			"DROP TRIGGER new_trig;",
  3095  		},
  3096  	},
  3097  	{
  3098  		Queries: []string{
  3099  			"GRANT TRIGGER ON mydb.* TO tester@localhost",
  3100  			"CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;",
  3101  		},
  3102  	},
  3103  	{
  3104  		Queries: []string{
  3105  			"GRANT TRIGGER ON mydb.* TO tester@localhost",
  3106  			"CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;",
  3107  			"DROP TRIGGER new_trig;",
  3108  		},
  3109  	},
  3110  	{
  3111  		Queries: []string{
  3112  			"UPDATE mydb.test SET v1 = 0;",
  3113  		},
  3114  		ExpectingErr: true,
  3115  	},
  3116  	{
  3117  		Queries: []string{
  3118  			"GRANT UPDATE ON *.* TO tester@localhost",
  3119  			"UPDATE mydb.test SET v1 = 0;",
  3120  		},
  3121  	},
  3122  	{
  3123  		Queries: []string{
  3124  			"GRANT UPDATE ON mydb.* TO tester@localhost",
  3125  			"UPDATE mydb.test SET v1 = 0;",
  3126  		},
  3127  	},
  3128  	{
  3129  		Queries: []string{
  3130  			"GRANT UPDATE ON mydb.test TO tester@localhost",
  3131  			"UPDATE mydb.test SET v1 = 0;",
  3132  		},
  3133  	},
  3134  	{
  3135  		Queries: []string{
  3136  			"FLUSH PRIVILEGES;",
  3137  		},
  3138  		ExpectingErr: true,
  3139  	},
  3140  	{
  3141  		Queries: []string{
  3142  			"GRANT RELOAD ON *.* TO tester@localhost",
  3143  			"FLUSH PRIVILEGES;",
  3144  		},
  3145  	},
  3146  }