github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/executor/grant.go (about)

     1  // Copyright 2016 PingCAP, 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  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package executor
    15  
    16  import (
    17  	"fmt"
    18  	"strings"
    19  
    20  	"github.com/insionng/yougam/libraries/juju/errors"
    21  	"github.com/insionng/yougam/libraries/pingcap/tidb/ast"
    22  	"github.com/insionng/yougam/libraries/pingcap/tidb/column"
    23  	"github.com/insionng/yougam/libraries/pingcap/tidb/context"
    24  	"github.com/insionng/yougam/libraries/pingcap/tidb/model"
    25  	"github.com/insionng/yougam/libraries/pingcap/tidb/mysql"
    26  	"github.com/insionng/yougam/libraries/pingcap/tidb/sessionctx"
    27  	"github.com/insionng/yougam/libraries/pingcap/tidb/sessionctx/db"
    28  	"github.com/insionng/yougam/libraries/pingcap/tidb/sessionctx/variable"
    29  	"github.com/insionng/yougam/libraries/pingcap/tidb/table"
    30  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/sqlexec"
    31  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/types"
    32  )
    33  
    34  /***
    35   * Grant Statement
    36   * See: https://dev.mysql.com/doc/refman/5.7/en/grant.html
    37   ************************************************************************************/
    38  var (
    39  	_ Executor = (*GrantExec)(nil)
    40  )
    41  
    42  // GrantExec executes GrantStmt.
    43  type GrantExec struct {
    44  	Privs      []*ast.PrivElem
    45  	ObjectType ast.ObjectTypeType
    46  	Level      *ast.GrantLevel
    47  	Users      []*ast.UserSpec
    48  
    49  	ctx  context.Context
    50  	done bool
    51  }
    52  
    53  // Fields implements Executor Fields interface.
    54  func (e *GrantExec) Fields() []*ast.ResultField {
    55  	return nil
    56  }
    57  
    58  // Next implements Execution Next interface.
    59  func (e *GrantExec) Next() (*Row, error) {
    60  	if e.done {
    61  		return nil, nil
    62  	}
    63  	// Grant for each user
    64  	for _, user := range e.Users {
    65  		// Check if user exists.
    66  		userName, host := parseUser(user.User)
    67  		exists, err := userExists(e.ctx, userName, host)
    68  		if err != nil {
    69  			return nil, errors.Trace(err)
    70  		}
    71  		if !exists {
    72  			return nil, errors.Errorf("Unknown user: %s", user.User)
    73  		}
    74  
    75  		// If there is no privilege entry in corresponding table, insert a new one.
    76  		// DB scope:		mysql.DB
    77  		// Table scope:		mysql.Tables_priv
    78  		// Column scope:	mysql.Columns_priv
    79  		switch e.Level.Level {
    80  		case ast.GrantLevelDB:
    81  			err := e.checkAndInitDBPriv(userName, host)
    82  			if err != nil {
    83  				return nil, errors.Trace(err)
    84  			}
    85  		case ast.GrantLevelTable:
    86  			err := e.checkAndInitTablePriv(userName, host)
    87  			if err != nil {
    88  				return nil, errors.Trace(err)
    89  			}
    90  		}
    91  		// Grant each priv to the user.
    92  		for _, priv := range e.Privs {
    93  			if len(priv.Cols) > 0 {
    94  				// Check column scope privilege entry.
    95  				// TODO: Check validity before insert new entry.
    96  				err1 := e.checkAndInitColumnPriv(userName, host, priv.Cols)
    97  				if err1 != nil {
    98  					return nil, errors.Trace(err1)
    99  				}
   100  			}
   101  			err2 := e.grantPriv(priv, user)
   102  			if err2 != nil {
   103  				return nil, errors.Trace(err2)
   104  			}
   105  		}
   106  	}
   107  	e.done = true
   108  	return nil, nil
   109  }
   110  
   111  // Close implements Executor Close interface.
   112  func (e *GrantExec) Close() error {
   113  	return nil
   114  }
   115  
   116  // Check if DB scope privilege entry exists in mysql.DB.
   117  // If unexists, insert a new one.
   118  func (e *GrantExec) checkAndInitDBPriv(user string, host string) error {
   119  	db, err := e.getTargetSchema()
   120  	if err != nil {
   121  		return errors.Trace(err)
   122  	}
   123  	ok, err := dbUserExists(e.ctx, user, host, db.Name.O)
   124  	if err != nil {
   125  		return errors.Trace(err)
   126  	}
   127  	if ok {
   128  		return nil
   129  	}
   130  	// Entry does not exist for user-host-db. Insert a new entry.
   131  	return initDBPrivEntry(e.ctx, user, host, db.Name.O)
   132  }
   133  
   134  // Check if table scope privilege entry exists in mysql.Tables_priv.
   135  // If unexists, insert a new one.
   136  func (e *GrantExec) checkAndInitTablePriv(user string, host string) error {
   137  	db, tbl, err := e.getTargetSchemaAndTable()
   138  	if err != nil {
   139  		return errors.Trace(err)
   140  	}
   141  	ok, err := tableUserExists(e.ctx, user, host, db.Name.O, tbl.Meta().Name.O)
   142  	if err != nil {
   143  		return errors.Trace(err)
   144  	}
   145  	if ok {
   146  		return nil
   147  	}
   148  	// Entry does not exist for user-host-db-tbl. Insert a new entry.
   149  	return initTablePrivEntry(e.ctx, user, host, db.Name.O, tbl.Meta().Name.O)
   150  }
   151  
   152  // Check if column scope privilege entry exists in mysql.Columns_priv.
   153  // If unexists, insert a new one.
   154  func (e *GrantExec) checkAndInitColumnPriv(user string, host string, cols []*ast.ColumnName) error {
   155  	db, tbl, err := e.getTargetSchemaAndTable()
   156  	if err != nil {
   157  		return errors.Trace(err)
   158  	}
   159  	for _, c := range cols {
   160  		col := column.FindCol(tbl.Cols(), c.Name.L)
   161  		if col == nil {
   162  			return errors.Errorf("Unknown column: %s", c.Name.O)
   163  		}
   164  		ok, err := columnPrivEntryExists(e.ctx, user, host, db.Name.O, tbl.Meta().Name.O, col.Name.O)
   165  		if err != nil {
   166  			return errors.Trace(err)
   167  		}
   168  		if ok {
   169  			continue
   170  		}
   171  		// Entry does not exist for user-host-db-tbl-col. Insert a new entry.
   172  		err = initColumnPrivEntry(e.ctx, user, host, db.Name.O, tbl.Meta().Name.O, col.Name.O)
   173  		if err != nil {
   174  			return errors.Trace(err)
   175  		}
   176  	}
   177  	return nil
   178  }
   179  
   180  // Insert a new row into mysql.DB with empty privilege.
   181  func initDBPrivEntry(ctx context.Context, user string, host string, db string) error {
   182  	sql := fmt.Sprintf(`INSERT INTO %s.%s (Host, User, DB) VALUES ("%s", "%s", "%s")`, mysql.SystemDB, mysql.DBTable, host, user, db)
   183  	_, err := ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(ctx, sql)
   184  	return errors.Trace(err)
   185  }
   186  
   187  // Insert a new row into mysql.Tables_priv with empty privilege.
   188  func initTablePrivEntry(ctx context.Context, user string, host string, db string, tbl string) error {
   189  	sql := fmt.Sprintf(`INSERT INTO %s.%s (Host, User, DB, Table_name, Table_priv, Column_priv) VALUES ("%s", "%s", "%s", "%s", "", "")`, mysql.SystemDB, mysql.TablePrivTable, host, user, db, tbl)
   190  	_, err := ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(ctx, sql)
   191  	return errors.Trace(err)
   192  }
   193  
   194  // Insert a new row into mysql.Columns_priv with empty privilege.
   195  func initColumnPrivEntry(ctx context.Context, user string, host string, db string, tbl string, col string) error {
   196  	sql := fmt.Sprintf(`INSERT INTO %s.%s (Host, User, DB, Table_name, Column_name, Column_priv) VALUES ("%s", "%s", "%s", "%s", "%s", "")`, mysql.SystemDB, mysql.ColumnPrivTable, host, user, db, tbl, col)
   197  	_, err := ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(ctx, sql)
   198  	return errors.Trace(err)
   199  }
   200  
   201  // Grant priv to user in s.Level scope.
   202  func (e *GrantExec) grantPriv(priv *ast.PrivElem, user *ast.UserSpec) error {
   203  	switch e.Level.Level {
   204  	case ast.GrantLevelGlobal:
   205  		return e.grantGlobalPriv(priv, user)
   206  	case ast.GrantLevelDB:
   207  		return e.grantDBPriv(priv, user)
   208  	case ast.GrantLevelTable:
   209  		if len(priv.Cols) == 0 {
   210  			return e.grantTablePriv(priv, user)
   211  		}
   212  		return e.grantColumnPriv(priv, user)
   213  	default:
   214  		return errors.Errorf("Unknown grant level: %#v", e.Level)
   215  	}
   216  }
   217  
   218  // Manipulate mysql.user table.
   219  func (e *GrantExec) grantGlobalPriv(priv *ast.PrivElem, user *ast.UserSpec) error {
   220  	asgns, err := composeGlobalPrivUpdate(priv.Priv)
   221  	if err != nil {
   222  		return errors.Trace(err)
   223  	}
   224  	userName, host := parseUser(user.User)
   225  	sql := fmt.Sprintf(`UPDATE %s.%s SET %s WHERE User="%s" AND Host="%s"`, mysql.SystemDB, mysql.UserTable, asgns, userName, host)
   226  	_, err = e.ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(e.ctx, sql)
   227  	return errors.Trace(err)
   228  }
   229  
   230  // Manipulate mysql.db table.
   231  func (e *GrantExec) grantDBPriv(priv *ast.PrivElem, user *ast.UserSpec) error {
   232  	db, err := e.getTargetSchema()
   233  	if err != nil {
   234  		return errors.Trace(err)
   235  	}
   236  	asgns, err := composeDBPrivUpdate(priv.Priv)
   237  	if err != nil {
   238  		return errors.Trace(err)
   239  	}
   240  	userName, host := parseUser(user.User)
   241  	sql := fmt.Sprintf(`UPDATE %s.%s SET %s WHERE User="%s" AND Host="%s" AND DB="%s";`, mysql.SystemDB, mysql.DBTable, asgns, userName, host, db.Name.O)
   242  	_, err = e.ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(e.ctx, sql)
   243  	return errors.Trace(err)
   244  }
   245  
   246  // Manipulate mysql.tables_priv table.
   247  func (e *GrantExec) grantTablePriv(priv *ast.PrivElem, user *ast.UserSpec) error {
   248  	db, tbl, err := e.getTargetSchemaAndTable()
   249  	if err != nil {
   250  		return errors.Trace(err)
   251  	}
   252  	userName, host := parseUser(user.User)
   253  	asgns, err := composeTablePrivUpdate(e.ctx, priv.Priv, userName, host, db.Name.O, tbl.Meta().Name.O)
   254  	if err != nil {
   255  		return errors.Trace(err)
   256  	}
   257  	sql := fmt.Sprintf(`UPDATE %s.%s SET %s WHERE User="%s" AND Host="%s" AND DB="%s" AND Table_name="%s";`, mysql.SystemDB, mysql.TablePrivTable, asgns, userName, host, db.Name.O, tbl.Meta().Name.O)
   258  	_, err = e.ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(e.ctx, sql)
   259  	return errors.Trace(err)
   260  }
   261  
   262  // Manipulate mysql.tables_priv table.
   263  func (e *GrantExec) grantColumnPriv(priv *ast.PrivElem, user *ast.UserSpec) error {
   264  	db, tbl, err := e.getTargetSchemaAndTable()
   265  	if err != nil {
   266  		return errors.Trace(err)
   267  	}
   268  	userName, host := parseUser(user.User)
   269  	for _, c := range priv.Cols {
   270  		col := column.FindCol(tbl.Cols(), c.Name.L)
   271  		if col == nil {
   272  			return errors.Errorf("Unknown column: %s", c)
   273  		}
   274  		asgns, err := composeColumnPrivUpdate(e.ctx, priv.Priv, userName, host, db.Name.O, tbl.Meta().Name.O, col.Name.O)
   275  		if err != nil {
   276  			return errors.Trace(err)
   277  		}
   278  		sql := fmt.Sprintf(`UPDATE %s.%s SET %s WHERE User="%s" AND Host="%s" AND DB="%s" AND Table_name="%s" AND Column_name="%s";`, mysql.SystemDB, mysql.ColumnPrivTable, asgns, userName, host, db.Name.O, tbl.Meta().Name.O, col.Name.O)
   279  		_, err = e.ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(e.ctx, sql)
   280  		if err != nil {
   281  			return errors.Trace(err)
   282  		}
   283  	}
   284  	return nil
   285  }
   286  
   287  // Compose update stmt assignment list string for global scope privilege update.
   288  func composeGlobalPrivUpdate(priv mysql.PrivilegeType) (string, error) {
   289  	if priv == mysql.AllPriv {
   290  		strs := make([]string, 0, len(mysql.Priv2UserCol))
   291  		for _, v := range mysql.Priv2UserCol {
   292  			strs = append(strs, fmt.Sprintf(`%s="Y"`, v))
   293  		}
   294  		return strings.Join(strs, ", "), nil
   295  	}
   296  	col, ok := mysql.Priv2UserCol[priv]
   297  	if !ok {
   298  		return "", errors.Errorf("Unknown priv: %v", priv)
   299  	}
   300  	return fmt.Sprintf(`%s="Y"`, col), nil
   301  }
   302  
   303  // Compose update stmt assignment list for db scope privilege update.
   304  func composeDBPrivUpdate(priv mysql.PrivilegeType) (string, error) {
   305  	if priv == mysql.AllPriv {
   306  		strs := make([]string, 0, len(mysql.AllDBPrivs))
   307  		for _, p := range mysql.AllDBPrivs {
   308  			v, ok := mysql.Priv2UserCol[p]
   309  			if !ok {
   310  				return "", errors.Errorf("Unknown db privilege %v", priv)
   311  			}
   312  			strs = append(strs, fmt.Sprintf(`%s="Y"`, v))
   313  		}
   314  		return strings.Join(strs, ", "), nil
   315  	}
   316  	col, ok := mysql.Priv2UserCol[priv]
   317  	if !ok {
   318  		return "", errors.Errorf("Unknown priv: %v", priv)
   319  	}
   320  	return fmt.Sprintf(`%s="Y"`, col), nil
   321  }
   322  
   323  // Compose update stmt assignment list for table scope privilege update.
   324  func composeTablePrivUpdate(ctx context.Context, priv mysql.PrivilegeType, name string, host string, db string, tbl string) (string, error) {
   325  	var newTablePriv, newColumnPriv string
   326  	if priv == mysql.AllPriv {
   327  		for _, p := range mysql.AllTablePrivs {
   328  			v, ok := mysql.Priv2SetStr[p]
   329  			if !ok {
   330  				return "", errors.Errorf("Unknown table privilege %v", p)
   331  			}
   332  			if len(newTablePriv) == 0 {
   333  				newTablePriv = v
   334  			} else {
   335  				newTablePriv = fmt.Sprintf("%s,%s", newTablePriv, v)
   336  			}
   337  		}
   338  		for _, p := range mysql.AllColumnPrivs {
   339  			v, ok := mysql.Priv2SetStr[p]
   340  			if !ok {
   341  				return "", errors.Errorf("Unknown column privilege %v", p)
   342  			}
   343  			if len(newColumnPriv) == 0 {
   344  				newColumnPriv = v
   345  			} else {
   346  				newColumnPriv = fmt.Sprintf("%s,%s", newColumnPriv, v)
   347  			}
   348  		}
   349  	} else {
   350  		currTablePriv, currColumnPriv, err := getTablePriv(ctx, name, host, db, tbl)
   351  		if err != nil {
   352  			return "", errors.Trace(err)
   353  		}
   354  		p, ok := mysql.Priv2SetStr[priv]
   355  		if !ok {
   356  			return "", errors.Errorf("Unknown priv: %v", priv)
   357  		}
   358  		if len(currTablePriv) == 0 {
   359  			newTablePriv = p
   360  		} else {
   361  			newTablePriv = fmt.Sprintf("%s,%s", currTablePriv, p)
   362  		}
   363  		for _, cp := range mysql.AllColumnPrivs {
   364  			if priv == cp {
   365  				if len(currColumnPriv) == 0 {
   366  					newColumnPriv = p
   367  				} else {
   368  					newColumnPriv = fmt.Sprintf("%s,%s", currColumnPriv, p)
   369  				}
   370  				break
   371  			}
   372  		}
   373  	}
   374  	return fmt.Sprintf(`Table_priv="%s", Column_priv="%s", Grantor="%s"`, newTablePriv, newColumnPriv, variable.GetSessionVars(ctx).User), nil
   375  }
   376  
   377  // Compose update stmt assignment list for column scope privilege update.
   378  func composeColumnPrivUpdate(ctx context.Context, priv mysql.PrivilegeType, name string, host string, db string, tbl string, col string) (string, error) {
   379  	newColumnPriv := ""
   380  	if priv == mysql.AllPriv {
   381  		for _, p := range mysql.AllColumnPrivs {
   382  			v, ok := mysql.Priv2SetStr[p]
   383  			if !ok {
   384  				return "", errors.Errorf("Unknown column privilege %v", p)
   385  			}
   386  			if len(newColumnPriv) == 0 {
   387  				newColumnPriv = v
   388  			} else {
   389  				newColumnPriv = fmt.Sprintf("%s,%s", newColumnPriv, v)
   390  			}
   391  		}
   392  	} else {
   393  		currColumnPriv, err := getColumnPriv(ctx, name, host, db, tbl, col)
   394  		if err != nil {
   395  			return "", errors.Trace(err)
   396  		}
   397  		p, ok := mysql.Priv2SetStr[priv]
   398  		if !ok {
   399  			return "", errors.Errorf("Unknown priv: %v", priv)
   400  		}
   401  		if len(currColumnPriv) == 0 {
   402  			newColumnPriv = p
   403  		} else {
   404  			newColumnPriv = fmt.Sprintf("%s,%s", currColumnPriv, p)
   405  		}
   406  	}
   407  	return fmt.Sprintf(`Column_priv="%s"`, newColumnPriv), nil
   408  }
   409  
   410  // Helper function to check if the sql returns any row.
   411  func recordExists(ctx context.Context, sql string) (bool, error) {
   412  	rs, err := ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(ctx, sql)
   413  	if err != nil {
   414  		return false, errors.Trace(err)
   415  	}
   416  	defer rs.Close()
   417  	row, err := rs.Next()
   418  	if err != nil {
   419  		return false, errors.Trace(err)
   420  	}
   421  	return row != nil, nil
   422  }
   423  
   424  // Check if there is an entry with key user-host-db in mysql.DB.
   425  func dbUserExists(ctx context.Context, name string, host string, db string) (bool, error) {
   426  	sql := fmt.Sprintf(`SELECT * FROM %s.%s WHERE User="%s" AND Host="%s" AND DB="%s";`, mysql.SystemDB, mysql.DBTable, name, host, db)
   427  	return recordExists(ctx, sql)
   428  }
   429  
   430  // Check if there is an entry with key user-host-db-tbl in mysql.Tables_priv.
   431  func tableUserExists(ctx context.Context, name string, host string, db string, tbl string) (bool, error) {
   432  	sql := fmt.Sprintf(`SELECT * FROM %s.%s WHERE User="%s" AND Host="%s" AND DB="%s" AND Table_name="%s";`, mysql.SystemDB, mysql.TablePrivTable, name, host, db, tbl)
   433  	return recordExists(ctx, sql)
   434  }
   435  
   436  // Check if there is an entry with key user-host-db-tbl-col in mysql.Columns_priv.
   437  func columnPrivEntryExists(ctx context.Context, name string, host string, db string, tbl string, col string) (bool, error) {
   438  	sql := fmt.Sprintf(`SELECT * FROM %s.%s WHERE User="%s" AND Host="%s" AND DB="%s" AND Table_name="%s" AND Column_name="%s";`, mysql.SystemDB, mysql.ColumnPrivTable, name, host, db, tbl, col)
   439  	return recordExists(ctx, sql)
   440  }
   441  
   442  // Get current table scope privilege set from mysql.Tables_priv.
   443  // Return Table_priv and Column_priv.
   444  func getTablePriv(ctx context.Context, name string, host string, db string, tbl string) (string, string, error) {
   445  	sql := fmt.Sprintf(`SELECT Table_priv, Column_priv FROM %s.%s WHERE User="%s" AND Host="%s" AND DB="%s" AND Table_name="%s";`, mysql.SystemDB, mysql.TablePrivTable, name, host, db, tbl)
   446  	rs, err := ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(ctx, sql)
   447  	if err != nil {
   448  		return "", "", errors.Trace(err)
   449  	}
   450  	defer rs.Close()
   451  	row, err := rs.Next()
   452  	if err != nil {
   453  		return "", "", errors.Trace(err)
   454  	}
   455  	var tPriv, cPriv string
   456  	if row.Data[0].Kind() == types.KindMysqlSet {
   457  		tablePriv := row.Data[0].GetMysqlSet()
   458  		tPriv = tablePriv.Name
   459  	}
   460  	if row.Data[1].Kind() == types.KindMysqlSet {
   461  		columnPriv := row.Data[1].GetMysqlSet()
   462  		cPriv = columnPriv.Name
   463  	}
   464  	return tPriv, cPriv, nil
   465  }
   466  
   467  // Get current column scope privilege set from mysql.Columns_priv.
   468  // Return Column_priv.
   469  func getColumnPriv(ctx context.Context, name string, host string, db string, tbl string, col string) (string, error) {
   470  	sql := fmt.Sprintf(`SELECT Column_priv FROM %s.%s WHERE User="%s" AND Host="%s" AND DB="%s" AND Table_name="%s" AND Column_name="%s";`, mysql.SystemDB, mysql.ColumnPrivTable, name, host, db, tbl, col)
   471  	rs, err := ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(ctx, sql)
   472  	if err != nil {
   473  		return "", errors.Trace(err)
   474  	}
   475  	defer rs.Close()
   476  	row, err := rs.Next()
   477  	if err != nil {
   478  		return "", errors.Trace(err)
   479  	}
   480  	cPriv := ""
   481  	if row.Data[0].Kind() == types.KindMysqlSet {
   482  		cPriv = row.Data[0].GetMysqlSet().Name
   483  	}
   484  	return cPriv, nil
   485  }
   486  
   487  // Find the schema by dbName.
   488  func (e *GrantExec) getTargetSchema() (*model.DBInfo, error) {
   489  	dbName := e.Level.DBName
   490  	if len(dbName) == 0 {
   491  		// Grant *, use current schema
   492  		dbName = db.GetCurrentSchema(e.ctx)
   493  		if len(dbName) == 0 {
   494  			return nil, errors.New("Miss DB name for grant privilege.")
   495  		}
   496  	}
   497  	//check if db exists
   498  	schema := model.NewCIStr(dbName)
   499  	is := sessionctx.GetDomain(e.ctx).InfoSchema()
   500  	db, ok := is.SchemaByName(schema)
   501  	if !ok {
   502  		return nil, errors.Errorf("Unknown schema name: %s", dbName)
   503  	}
   504  	return db, nil
   505  }
   506  
   507  // Find the schema and table by dbName and tableName.
   508  func (e *GrantExec) getTargetSchemaAndTable() (*model.DBInfo, table.Table, error) {
   509  	db, err := e.getTargetSchema()
   510  	if err != nil {
   511  		return nil, nil, errors.Trace(err)
   512  	}
   513  	name := model.NewCIStr(e.Level.TableName)
   514  	is := sessionctx.GetDomain(e.ctx).InfoSchema()
   515  	tbl, err := is.TableByName(db.Name, name)
   516  	if err != nil {
   517  		return nil, nil, errors.Trace(err)
   518  	}
   519  	return db, tbl, nil
   520  }