diff --git a/bootstrap.go b/bootstrap.go index 450fa11316..ae1da48d1e 100644 --- a/bootstrap.go +++ b/bootstrap.go @@ -24,9 +24,9 @@ import ( "github.com/juju/errors" "github.com/ngaut/log" + "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/mysql" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/terror" ) const ( @@ -122,7 +122,7 @@ const ( func checkBootstrapped(s Session) (bool, error) { // Check if system db exists. _, err := s.Execute(fmt.Sprintf("USE %s;", mysql.SystemDB)) - if err != nil && terror.DatabaseNotExists.NotEqual(err) { + if err != nil && infoschema.DatabaseNotExists.NotEqual(err) { log.Fatal(err) } // Check bootstrapped variable value in TiDB table. @@ -138,7 +138,7 @@ func checkBootstrappedVar(s Session) (bool, error) { mysql.SystemDB, mysql.TiDBTable, bootstrappedVar) rs, err := s.Execute(sql) if err != nil { - if terror.TableNotExists.Equal(err) { + if infoschema.TableNotExists.Equal(err) { return false, nil } return false, errors.Trace(err) diff --git a/ddl/ddl.go b/ddl/ddl.go index e97733ead7..9c5a2dc6e2 100644 --- a/ddl/ddl.go +++ b/ddl/ddl.go @@ -35,7 +35,6 @@ import ( "github.com/pingcap/tidb/parser/coldef" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/table" - "github.com/pingcap/tidb/terror" "github.com/pingcap/tidb/util/charset" "github.com/twinj/uuid" ) @@ -473,7 +472,7 @@ func (d *ddl) CreateTable(ctx context.Context, ident table.Ident, colDefs []*col is := d.GetInformationSchema() schema, ok := is.SchemaByName(ident.Schema) if !ok { - return terror.DatabaseNotExists.Gen("database %s not exists", ident.Schema) + return infoschema.DatabaseNotExists.Gen("database %s not exists", ident.Schema) } if is.TableExists(ident.Schema, ident.Name) { return errors.Trace(ErrExists) @@ -567,7 +566,7 @@ func (d *ddl) AddColumn(ctx context.Context, ti table.Ident, spec *AlterSpecific is := d.infoHandle.Get() schema, ok := is.SchemaByName(ti.Schema) if !ok { - return errors.Trace(terror.DatabaseNotExists) + return errors.Trace(infoschema.DatabaseNotExists) } t, err := is.TableByName(ti.Schema, ti.Name) @@ -607,7 +606,7 @@ func (d *ddl) DropColumn(ctx context.Context, ti table.Ident, colName model.CISt is := d.infoHandle.Get() schema, ok := is.SchemaByName(ti.Schema) if !ok { - return errors.Trace(terror.DatabaseNotExists) + return errors.Trace(infoschema.DatabaseNotExists) } t, err := is.TableByName(ti.Schema, ti.Name) @@ -638,7 +637,7 @@ func (d *ddl) DropTable(ctx context.Context, ti table.Ident) (err error) { is := d.GetInformationSchema() schema, ok := is.SchemaByName(ti.Schema) if !ok { - return terror.DatabaseNotExists.Gen("database %s not exists", ti.Schema) + return infoschema.DatabaseNotExists.Gen("database %s not exists", ti.Schema) } tb, err := is.TableByName(ti.Schema, ti.Name) @@ -661,7 +660,7 @@ func (d *ddl) CreateIndex(ctx context.Context, ti table.Ident, unique bool, inde is := d.infoHandle.Get() schema, ok := is.SchemaByName(ti.Schema) if !ok { - return terror.DatabaseNotExists.Gen("database %s not exists", ti.Schema) + return infoschema.DatabaseNotExists.Gen("database %s not exists", ti.Schema) } t, err := is.TableByName(ti.Schema, ti.Name) @@ -689,7 +688,7 @@ func (d *ddl) DropIndex(ctx context.Context, ti table.Ident, indexName model.CIS is := d.infoHandle.Get() schema, ok := is.SchemaByName(ti.Schema) if !ok { - return errors.Trace(terror.DatabaseNotExists) + return errors.Trace(infoschema.DatabaseNotExists) } t, err := is.TableByName(ti.Schema, ti.Name) diff --git a/ddl/ddl_test.go b/ddl/ddl_test.go index 85b785731a..abc2c075b8 100644 --- a/ddl/ddl_test.go +++ b/ddl/ddl_test.go @@ -22,6 +22,7 @@ import ( "github.com/pingcap/tidb/context" "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/executor" + "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/model" "github.com/pingcap/tidb/mysql" @@ -74,7 +75,7 @@ func (ts *testSuite) TestDDL(c *C) { tbStmt := statement(ctx, "create table t (a int primary key not null, b varchar(255), key idx_b (b), c int, d int unique)").(*stmts.CreateTableStmt) err = sessionctx.GetDomain(ctx).DDL().CreateTable(ctx, table.Ident{Schema: noExist, Name: tbIdent.Name}, tbStmt.Cols, tbStmt.Constraints) - c.Assert(terror.DatabaseNotExists.Equal(err), IsTrue) + c.Assert(infoschema.DatabaseNotExists.Equal(err), IsTrue) err = sessionctx.GetDomain(ctx).DDL().CreateTable(ctx, tbIdent, tbStmt.Cols, tbStmt.Constraints) c.Assert(err, IsNil) diff --git a/ddl/table.go b/ddl/table.go index 4ea12822df..440e72f74d 100644 --- a/ddl/table.go +++ b/ddl/table.go @@ -15,6 +15,7 @@ package ddl import ( "github.com/juju/errors" + "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/meta/autoid" "github.com/pingcap/tidb/model" @@ -36,7 +37,7 @@ func (d *ddl) onCreateTable(t *meta.Meta, job *model.Job) error { tables, err := t.ListTables(schemaID) if terror.ErrorEqual(err, meta.ErrDBNotExists) { job.State = model.JobCancelled - return errors.Trace(terror.DatabaseNotExists) + return errors.Trace(infoschema.DatabaseNotExists) } else if err != nil { return errors.Trace(err) } @@ -82,7 +83,7 @@ func (d *ddl) onDropTable(t *meta.Meta, job *model.Job) error { tblInfo, err := t.GetTable(schemaID, tableID) if terror.ErrorEqual(err, meta.ErrDBNotExists) { job.State = model.JobCancelled - return errors.Trace(terror.DatabaseNotExists) + return errors.Trace(infoschema.DatabaseNotExists) } else if err != nil { return errors.Trace(err) } diff --git a/infoschema/infoschema.go b/infoschema/infoschema.go index 80fe8d72ea..570edcf8f2 100644 --- a/infoschema/infoschema.go +++ b/infoschema/infoschema.go @@ -20,6 +20,7 @@ import ( "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta/autoid" "github.com/pingcap/tidb/model" + "github.com/pingcap/tidb/mysql" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/terror" // import table implementation to init table.TableFromMeta @@ -106,7 +107,7 @@ func (is *infoSchema) SchemaExists(schema model.CIStr) bool { func (is *infoSchema) TableByName(schema, table model.CIStr) (t table.Table, err error) { id, ok := is.tableNameToID[tableName{schema: schema.L, table: table.L}] if !ok { - return nil, terror.TableNotExists.Gen("table %s.%s does not exist", schema, table) + return nil, TableNotExists.Gen("table %s.%s does not exist", schema, table) } t = is.tables[id] return @@ -250,3 +251,28 @@ func (h *Handle) Get() InfoSchema { schema, _ := v.(InfoSchema) return schema } + +// Schema error codes. +const ( + CodeDatabaseNotExists terror.ErrCode = 1049 + CodeTableNotExists = 1146 + CodeColumnNotExists = 1054 +) + +var ( + // DatabaseNotExists returns for database not exists. + DatabaseNotExists = terror.ClassSchema.New(CodeDatabaseNotExists, "database not exists") + // TableNotExists returns for table not exists. + TableNotExists = terror.ClassSchema.New(CodeTableNotExists, "table not exists") + // ColumnNotExists returns for column not exists. + ColumnNotExists = terror.ClassSchema.New(CodeColumnNotExists, "field not exists") +) + +func init() { + schemaMySQLErrCodes := map[terror.ErrCode]uint16{ + CodeDatabaseNotExists: mysql.ErrBadDb, + CodeTableNotExists: mysql.ErrNoSuchTable, + CodeColumnNotExists: mysql.ErrBadField, + } + terror.ErrClassToMySQLCodes[terror.ClassSchema] = schemaMySQLErrCodes +} diff --git a/stmt/stmts/drop.go b/stmt/stmts/drop.go index 65d73d3afe..eac675265a 100644 --- a/stmt/stmts/drop.go +++ b/stmt/stmts/drop.go @@ -23,6 +23,7 @@ import ( "github.com/juju/errors" "github.com/pingcap/tidb/context" "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/model" "github.com/pingcap/tidb/mysql" "github.com/pingcap/tidb/privilege" @@ -138,7 +139,7 @@ func (s *DropTableStmt) Exec(ctx context.Context) (rset.Recordset, error) { } err = sessionctx.GetDomain(ctx).DDL().DropTable(ctx, fullti) - if terror.ErrorEqual(err, ddl.ErrNotExists) || terror.DatabaseNotExists.Equal(err) { + if terror.ErrorEqual(err, ddl.ErrNotExists) || infoschema.DatabaseNotExists.Equal(err) { notExistTables = append(notExistTables, ti.String()) } else if err != nil { return nil, errors.Trace(err) @@ -182,7 +183,7 @@ func (s *DropIndexStmt) SetText(text string) { // Exec implements the stmt.Statement Exec interface. func (s *DropIndexStmt) Exec(ctx context.Context) (rset.Recordset, error) { err := sessionctx.GetDomain(ctx).DDL().DropIndex(ctx, s.TableIdent.Full(ctx), model.NewCIStr(s.IndexName)) - if (terror.ErrorEqual(err, ddl.ErrNotExists) || terror.DatabaseNotExists.Equal(err)) && s.IfExists { + if (terror.ErrorEqual(err, ddl.ErrNotExists) || infoschema.DatabaseNotExists.Equal(err)) && s.IfExists { err = nil } diff --git a/stmt/stmts/use.go b/stmt/stmts/use.go index 2533ccfed8..ac0273c7ed 100644 --- a/stmt/stmts/use.go +++ b/stmt/stmts/use.go @@ -19,13 +19,13 @@ package stmts import ( "github.com/pingcap/tidb/context" + "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/model" "github.com/pingcap/tidb/rset" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/db" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/stmt" - "github.com/pingcap/tidb/terror" "github.com/pingcap/tidb/util/format" ) @@ -64,7 +64,7 @@ func (s *UseStmt) Exec(ctx context.Context) (_ rset.Recordset, err error) { dbname := model.NewCIStr(s.DBName) dbinfo, exists := sessionctx.GetDomain(ctx).InfoSchema().SchemaByName(dbname) if !exists { - return nil, terror.DatabaseNotExists.Gen("database %s not exists", dbname) + return nil, infoschema.DatabaseNotExists.Gen("database %s not exists", dbname) } db.BindCurrentSchema(ctx, dbname.O) s.updateSysVars(ctx, dbinfo) diff --git a/terror/terror.go b/terror/terror.go index 0208aea6d6..2c9c96143e 100644 --- a/terror/terror.go +++ b/terror/terror.go @@ -25,9 +25,6 @@ import ( // Common base error instances. var ( - DatabaseNotExists = ClassSchema.New(CodeDatabaseNotExists, "database not exists") - TableNotExists = ClassSchema.New(CodeTableNotExists, "table not exists") - CommitNotInTransaction = ClassExecutor.New(CodeCommitNotInTransaction, "commit not in transaction") RollbackNotInTransaction = ClassExecutor.New(CodeRollbackNotInTransaction, "rollback not in transaction") ExecResultIsEmpty = ClassExecutor.New(CodeExecResultIsEmpty, "exec result is empty") @@ -44,24 +41,18 @@ var ( // Same error code can be used in different error classes. type ErrCode int -// Schema error codes. -const ( - CodeDatabaseNotExists ErrCode = iota + 1 - CodeTableNotExists -) - // Executor error codes. const ( - CodeCommitNotInTransaction ErrCode = iota + 1 - CodeRollbackNotInTransaction - CodeExecResultIsEmpty + CodeCommitNotInTransaction ErrCode = 1 + CodeRollbackNotInTransaction = 2 + CodeExecResultIsEmpty = 3 ) // KV error codes. const ( - CodeIncompatibleDBFormat ErrCode = iota + 1 - CodeNoDataForHandle - CodeKeyExists + CodeIncompatibleDBFormat ErrCode = 1 + CodeNoDataForHandle = 2 + CodeKeyExists = 3 ) // Variable error codes. @@ -204,7 +195,7 @@ func (e *Error) ToSQLError() *mysql.SQLError { var defaultMySQLErrorCode uint16 func (e *Error) getMySQLErrorCode() uint16 { - codeMap, ok := errClassToMySQLCodes[e.class] + codeMap, ok := ErrClassToMySQLCodes[e.class] if !ok { log.Warnf("Unknown error class: %v", e.class) return defaultMySQLErrorCode @@ -220,7 +211,6 @@ func (e *Error) getMySQLErrorCode() uint16 { var ( // ErrCode to mysql error code map. parserMySQLErrCodes = map[ErrCode]uint16{} - schemaMySQLErrCodes = map[ErrCode]uint16{} optimizerMySQLErrCodes = map[ErrCode]uint16{} executorMySQLErrCodes = map[ErrCode]uint16{} kvMySQLErrCodes = map[ErrCode]uint16{ @@ -229,19 +219,18 @@ var ( serverMySQLErrCodes = map[ErrCode]uint16{} expressionMySQLErrCodes = map[ErrCode]uint16{} - // ErrClass to code-map map. - errClassToMySQLCodes map[ErrClass](map[ErrCode]uint16) + // ErrClassToMySQLCodes is the map of ErrClass to code-map. + ErrClassToMySQLCodes map[ErrClass](map[ErrCode]uint16) ) func init() { - errClassToMySQLCodes = make(map[ErrClass](map[ErrCode]uint16)) - errClassToMySQLCodes[ClassParser] = parserMySQLErrCodes - errClassToMySQLCodes[ClassSchema] = schemaMySQLErrCodes - errClassToMySQLCodes[ClassOptimizer] = optimizerMySQLErrCodes - errClassToMySQLCodes[ClassExecutor] = executorMySQLErrCodes - errClassToMySQLCodes[ClassKV] = kvMySQLErrCodes - errClassToMySQLCodes[ClassServer] = serverMySQLErrCodes - errClassToMySQLCodes[ClassExpression] = expressionMySQLErrCodes + ErrClassToMySQLCodes = make(map[ErrClass](map[ErrCode]uint16)) + ErrClassToMySQLCodes[ClassParser] = parserMySQLErrCodes + ErrClassToMySQLCodes[ClassOptimizer] = optimizerMySQLErrCodes + ErrClassToMySQLCodes[ClassExecutor] = executorMySQLErrCodes + ErrClassToMySQLCodes[ClassKV] = kvMySQLErrCodes + ErrClassToMySQLCodes[ClassServer] = serverMySQLErrCodes + ErrClassToMySQLCodes[ClassExpression] = expressionMySQLErrCodes defaultMySQLErrorCode = mysql.ErrUnknown } diff --git a/tidb-server/server/server_test.go b/tidb-server/server/server_test.go index ab2a95a4eb..d8fd1deb32 100644 --- a/tidb-server/server/server_test.go +++ b/tidb-server/server/server_test.go @@ -231,6 +231,13 @@ func runTestErrorCode(c *C) { c.Assert(err, IsNil) err = txn1.Commit() checkErrorCode(c, err, tmysql.ErrDupEntry) + + txn2, err := dbt.db.Begin() + c.Assert(err, IsNil) + _, err = txn2.Exec("use db_not_exists;") + checkErrorCode(c, err, tmysql.ErrBadDb) + _, err = txn2.Exec("select * from tbl_not_exists;") + checkErrorCode(c, err, tmysql.ErrNoSuchTable) }) }