Skip to content

Commit

Permalink
plan: refactor errors (#6377)
Browse files Browse the repository at this point in the history
  • Loading branch information
zz-jason authored May 9, 2018
1 parent 5f2b161 commit 6248a74
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 145 deletions.
19 changes: 19 additions & 0 deletions executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2700,6 +2700,25 @@ func (s *testSuite) TestCoprocessorStreamingFlag(c *C) {
}
}

func (s *testSuite) TestIncorrectLimitArg(c *C) {
tk := testkit.NewTestKit(c, s.store)

tk.MustExec(`use test;`)
tk.MustExec(`drop table if exists t;`)
tk.MustExec(`create table t(a bigint);`)
tk.MustExec(`prepare stmt1 from 'select * from t limit ?';`)
tk.MustExec(`prepare stmt2 from 'select * from t limit ?, ?';`)
tk.MustExec(`set @a = -1;`)
tk.MustExec(`set @b = 1;`)

var err error
_, err = tk.Se.Execute(context.TODO(), `execute stmt1 using @a;`)
c.Assert(err.Error(), Equals, `[planner:1210]Incorrect arguments to LIMIT`)

_, err = tk.Se.Execute(context.TODO(), `execute stmt2 using @b, @a;`)
c.Assert(err.Error(), Equals, `[planner:1210]Incorrect arguments to LIMIT`)
}

func (s *testSuite) TestLimit(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec(`use test;`)
Expand Down
2 changes: 1 addition & 1 deletion executor/prepared_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,5 +260,5 @@ func (s *testSuite) TestPreparedNameResolver(c *C) {
tk.MustExec("create table t (id int, KEY id (id))")
tk.MustExec("prepare stmt from 'select * from t limit ? offset ?'")
_, err := tk.Exec("prepare stmt from 'select b from t'")
c.Assert(err.Error(), Equals, "[plan:1054]Unknown column 'b' in 'field list'")
c.Assert(err.Error(), Equals, "[planner:1054]Unknown column 'b' in 'field list'")
}
81 changes: 73 additions & 8 deletions plan/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,83 @@ import (
"github.com/pingcap/tidb/terror"
)

var (
// ErrWrongUsage is returned when SQL operators are not properly used.
ErrWrongUsage = terror.ClassParser.New(codeWrongUsage, mysql.MySQLErrName[mysql.ErrWrongUsage])
const (
codeUnsupportedType terror.ErrCode = 1
codeAnalyzeMissIndex = 2
codeUnsupported = 3
codeStmtNotFound = 4
codeWrongParamCount = 5
codeSchemaChanged = 6

codeWrongUsage = mysql.ErrWrongUsage
codeAmbiguous = mysql.ErrNonUniq
codeUnknownColumn = mysql.ErrBadField
codeUnknownTable = mysql.ErrUnknownTable
codeWrongArguments = mysql.ErrWrongArguments
codeBadGeneratedColumn = mysql.ErrBadGeneratedColumn
codeFieldNotInGroupBy = mysql.ErrFieldNotInGroupBy
codeBadTable = mysql.ErrBadTable
codeKeyDoesNotExist = mysql.ErrKeyDoesNotExist
codeOperandColumns = mysql.ErrOperandColumns
codeInvalidWildCard = mysql.ErrParse
codeInvalidGroupFuncUse = mysql.ErrInvalidGroupFuncUse
codeIllegalReference = mysql.ErrIllegalReference
codeNoDB = mysql.ErrNoDB
codeUnknownExplainFormat = mysql.ErrUnknownExplainFormat
codeWrongGroupField = mysql.ErrWrongGroupField
codeDupFieldName = mysql.ErrDupFieldName
codeNonUpdatableTable = mysql.ErrNonUpdatableTable
)

const (
codeWrongUsage = terror.ErrCode(mysql.ErrWrongUsage)
// error definitions.
var (
ErrUnsupportedType = terror.ClassOptimizer.New(codeUnsupportedType, "Unsupported type %T")
ErrAnalyzeMissIndex = terror.ClassOptimizer.New(codeAnalyzeMissIndex, "Index '%s' in field list does not exist in table '%s'")
ErrCartesianProductUnsupported = terror.ClassOptimizer.New(codeUnsupported, "Cartesian product is unsupported")
ErrStmtNotFound = terror.ClassOptimizer.New(codeStmtNotFound, "Prepared statement not found")
ErrWrongParamCount = terror.ClassOptimizer.New(codeWrongParamCount, "Wrong parameter count")
ErrSchemaChanged = terror.ClassOptimizer.New(codeSchemaChanged, "Schema has changed")

ErrWrongUsage = terror.ClassOptimizer.New(codeWrongUsage, mysql.MySQLErrName[mysql.ErrWrongUsage])
ErrAmbiguous = terror.ClassOptimizer.New(codeAmbiguous, mysql.MySQLErrName[mysql.ErrNonUniq])
ErrUnknownColumn = terror.ClassOptimizer.New(codeUnknownColumn, mysql.MySQLErrName[mysql.ErrBadField])
ErrUnknownTable = terror.ClassOptimizer.New(codeUnknownTable, mysql.MySQLErrName[mysql.ErrUnknownTable])
ErrWrongArguments = terror.ClassOptimizer.New(codeWrongArguments, mysql.MySQLErrName[mysql.ErrWrongArguments])
ErrBadGeneratedColumn = terror.ClassOptimizer.New(codeBadGeneratedColumn, mysql.MySQLErrName[mysql.ErrBadGeneratedColumn])
ErrFieldNotInGroupBy = terror.ClassOptimizer.New(codeFieldNotInGroupBy, mysql.MySQLErrName[mysql.ErrFieldNotInGroupBy])
ErrBadTable = terror.ClassOptimizer.New(codeBadTable, mysql.MySQLErrName[mysql.ErrBadTable])
ErrKeyDoesNotExist = terror.ClassOptimizer.New(codeKeyDoesNotExist, mysql.MySQLErrName[mysql.ErrKeyDoesNotExist])
ErrOperandColumns = terror.ClassOptimizer.New(codeOperandColumns, mysql.MySQLErrName[mysql.ErrOperandColumns])
ErrInvalidWildCard = terror.ClassOptimizer.New(codeInvalidWildCard, "Wildcard fields without any table name appears in wrong place")
ErrInvalidGroupFuncUse = terror.ClassOptimizer.New(codeInvalidGroupFuncUse, mysql.MySQLErrName[mysql.ErrInvalidGroupFuncUse])
ErrIllegalReference = terror.ClassOptimizer.New(codeIllegalReference, mysql.MySQLErrName[mysql.ErrIllegalReference])
ErrNoDB = terror.ClassOptimizer.New(codeNoDB, mysql.MySQLErrName[mysql.ErrNoDB])
ErrUnknownExplainFormat = terror.ClassOptimizer.New(codeUnknownExplainFormat, mysql.MySQLErrName[mysql.ErrUnknownExplainFormat])
ErrWrongGroupField = terror.ClassOptimizer.New(codeWrongGroupField, mysql.MySQLErrName[mysql.ErrWrongGroupField])
ErrDupFieldName = terror.ClassOptimizer.New(codeDupFieldName, mysql.MySQLErrName[mysql.ErrDupFieldName])
ErrNonUpdatableTable = terror.ClassOptimizer.New(codeNonUpdatableTable, mysql.MySQLErrName[mysql.ErrNonUpdatableTable])
)

func init() {
typesMySQLErrCodes := map[terror.ErrCode]uint16{
codeWrongUsage: mysql.ErrWrongUsage,
mysqlErrCodeMap := map[terror.ErrCode]uint16{
codeWrongUsage: mysql.ErrWrongUsage,
codeAmbiguous: mysql.ErrNonUniq,
codeUnknownColumn: mysql.ErrBadField,
codeUnknownTable: mysql.ErrBadTable,
codeWrongArguments: mysql.ErrWrongArguments,
codeBadGeneratedColumn: mysql.ErrBadGeneratedColumn,
codeFieldNotInGroupBy: mysql.ErrFieldNotInGroupBy,
codeBadTable: mysql.ErrBadTable,
codeKeyDoesNotExist: mysql.ErrKeyDoesNotExist,
codeOperandColumns: mysql.ErrOperandColumns,
codeInvalidWildCard: mysql.ErrParse,
codeInvalidGroupFuncUse: mysql.ErrInvalidGroupFuncUse,
codeIllegalReference: mysql.ErrIllegalReference,
codeNoDB: mysql.ErrNoDB,
codeUnknownExplainFormat: mysql.ErrUnknownExplainFormat,
codeWrongGroupField: mysql.ErrWrongGroupField,
codeDupFieldName: mysql.ErrDupFieldName,
codeNonUpdatableTable: mysql.ErrUnknownTable,
}
terror.ErrClassToMySQLCodes[terror.ClassParser] = typesMySQLErrCodes
terror.ErrClassToMySQLCodes[terror.ClassOptimizer] = mysqlErrCodeMap
}
4 changes: 2 additions & 2 deletions plan/expression_rewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -1141,7 +1141,7 @@ func (er *expressionRewriter) funcCallToExpression(v *ast.FuncCallExpr) {
func (er *expressionRewriter) toColumn(v *ast.ColumnName) {
column, err := er.schema.FindColumn(v)
if err != nil {
er.err = ErrAmbiguous.GenByArgs(v.Name)
er.err = ErrAmbiguous.GenByArgs(v.Name, clauseMsg[fieldList])
return
}
if column != nil {
Expand All @@ -1156,7 +1156,7 @@ func (er *expressionRewriter) toColumn(v *ast.ColumnName) {
return
}
if err != nil {
er.err = ErrAmbiguous.GenByArgs(v.Name)
er.err = ErrAmbiguous.GenByArgs(v.Name, clauseMsg[fieldList])
return
}
}
Expand Down
6 changes: 3 additions & 3 deletions plan/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -762,14 +762,14 @@ func (b *planBuilder) buildLimit(src LogicalPlan, limit *ast.Limit) LogicalPlan
if limit.Offset != nil {
offset, err = getUintForLimitOffset(sc, limit.Offset.GetValue())
if err != nil {
b.err = ErrWrongArguments
b.err = ErrWrongArguments.GenByArgs("LIMIT")
return nil
}
}
if limit.Count != nil {
count, err = getUintForLimitOffset(sc, limit.Count.GetValue())
if err != nil {
b.err = ErrWrongArguments
b.err = ErrWrongArguments.GenByArgs("LIMIT")
return nil
}
}
Expand Down Expand Up @@ -832,7 +832,7 @@ func resolveFromSelectFields(v *ast.ColumnNameExpr, fields []*ast.SelectField, i
index = i
} else if !colMatch(matchedExpr.(*ast.ColumnNameExpr).Name, curCol.Name) &&
!colMatch(curCol.Name, matchedExpr.(*ast.ColumnNameExpr).Name) {
return -1, ErrAmbiguous.GenByArgs(curCol.Name.Name.L)
return -1, ErrAmbiguous.GenByArgs(curCol.Name.Name.L, clauseMsg[fieldList])
}
}
}
Expand Down
22 changes: 11 additions & 11 deletions plan/logical_plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1552,27 +1552,27 @@ func (s *testPlanSuite) TestNameResolver(c *C) {
err string
}{
{"select a from t", ""},
{"select c3 from t", "[plan:1054]Unknown column 'c3' in 'field list'"},
{"select c3 from t", "[planner:1054]Unknown column 'c3' in 'field list'"},
{"select c1 from t4", "[schema:1146]Table 'test.t4' doesn't exist"},
{"select * from t", ""},
{"select t.* from t", ""},
{"select t2.* from t", "[plan:1051]Unknown table 't2'"},
{"select b as a, c as a from t group by a", "[plan:1052]Column 'c' in field list is ambiguous"},
{"select t2.* from t", "[planner:1051]Unknown table 't2'"},
{"select b as a, c as a from t group by a", "[planner:1052]Column 'c' in field list is ambiguous"},
{"select 1 as a, b as a, c as a from t group by a", ""},
{"select a, b as a from t group by a+1", ""},
{"select c, a as c from t order by c+1", ""},
{"select * from t as t1, t as t2 join t as t3 on t2.a = t3.a", ""},
{"select * from t as t1, t as t2 join t as t3 on t1.c1 = t2.a", "[plan:1054]Unknown column 't1.c1' in 'on clause'"},
{"select * from t as t1, t as t2 join t as t3 on t1.c1 = t2.a", "[planner:1054]Unknown column 't1.c1' in 'on clause'"},
{"select a from t group by a having a = 3", ""},
{"select a from t group by a having c2 = 3", "[plan:1054]Unknown column 'c2' in 'having clause'"},
{"select a from t group by a having c2 = 3", "[planner:1054]Unknown column 'c2' in 'having clause'"},
{"select a from t where exists (select b)", ""},
{"select cnt from (select count(a) as cnt from t group by b) as t2 group by cnt", ""},
{"select a from t where t11.a < t.a", "[plan:1054]Unknown column 't11.a' in 'where clause'"},
{"select a from t having t11.c1 < t.a", "[plan:1054]Unknown column 't11.c1' in 'having clause'"},
{"select a from t where t.a < t.a order by t11.c1", "[plan:1054]Unknown column 't11.c1' in 'order clause'"},
{"select a from t group by t11.c1", "[plan:1054]Unknown column 't11.c1' in 'group statement'"},
{"delete a from (select * from t ) as a, t", "[optimizer:1288]The target table a of the DELETE is not updatable"},
{"delete b from (select * from t ) as a, t", "[plan:1109]Unknown table 'b' in MULTI DELETE"},
{"select a from t where t11.a < t.a", "[planner:1054]Unknown column 't11.a' in 'where clause'"},
{"select a from t having t11.c1 < t.a", "[planner:1054]Unknown column 't11.c1' in 'having clause'"},
{"select a from t where t.a < t.a order by t11.c1", "[planner:1054]Unknown column 't11.c1' in 'order clause'"},
{"select a from t group by t11.c1", "[planner:1054]Unknown column 't11.c1' in 'group statement'"},
{"delete a from (select * from t ) as a, t", "[planner:1288]The target table a of the DELETE is not updatable"},
{"delete b from (select * from t ) as a, t", "[planner:1109]Unknown table 'b' in MULTI DELETE"},
}

for _, t := range tests {
Expand Down
47 changes: 0 additions & 47 deletions plan/optimizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ import (
"github.com/pingcap/tidb/ast"
"github.com/pingcap/tidb/expression"
"github.com/pingcap/tidb/infoschema"
"github.com/pingcap/tidb/mysql"
"github.com/pingcap/tidb/privilege"
"github.com/pingcap/tidb/sessionctx"
"github.com/pingcap/tidb/terror"
)

// AllowCartesianProduct means whether tidb allows cartesian join without equal conditions.
Expand Down Expand Up @@ -172,51 +170,6 @@ func existsCartesianProduct(p LogicalPlan) bool {
return false
}

// Optimizer error codes.
const (
CodeInvalidWildCard terror.ErrCode = 3
CodeUnsupported = 4
CodeStmtNotFound = 7
CodeWrongParamCount = 8
CodeSchemaChanged = 9

// MySQL error code.
CodeInvalidGroupFuncUse = mysql.ErrInvalidGroupFuncUse
CodeIllegalReference = mysql.ErrIllegalReference
CodeNoDB = mysql.ErrNoDB
CodeUnknownExplainFormat = mysql.ErrUnknownExplainFormat
CodeWrongGroupField = mysql.ErrWrongGroupField
CodeDupFieldName = mysql.ErrDupFieldName
CodeNonUpdatableTable = mysql.ErrNonUpdatableTable
)

// Optimizer base errors.
var (
ErrInvalidWildCard = terror.ClassOptimizer.New(CodeInvalidWildCard, "Wildcard fields without any table name appears in wrong place")
ErrCartesianProductUnsupported = terror.ClassOptimizer.New(CodeUnsupported, "Cartesian product is unsupported")
ErrInvalidGroupFuncUse = terror.ClassOptimizer.New(CodeInvalidGroupFuncUse, "Invalid use of group function")
ErrIllegalReference = terror.ClassOptimizer.New(CodeIllegalReference, mysql.MySQLErrName[mysql.ErrIllegalReference])
ErrNoDB = terror.ClassOptimizer.New(CodeNoDB, "No database selected")
ErrUnknownExplainFormat = terror.ClassOptimizer.New(CodeUnknownExplainFormat, mysql.MySQLErrName[mysql.ErrUnknownExplainFormat])
ErrStmtNotFound = terror.ClassOptimizer.New(CodeStmtNotFound, "Prepared statement not found")
ErrWrongParamCount = terror.ClassOptimizer.New(CodeWrongParamCount, "Wrong parameter count")
ErrSchemaChanged = terror.ClassOptimizer.New(CodeSchemaChanged, "Schema has changed")
ErrWrongGroupField = terror.ClassOptimizer.New(CodeWrongGroupField, mysql.MySQLErrName[mysql.ErrWrongGroupField])
ErrDupFieldName = terror.ClassOptimizer.New(CodeDupFieldName, mysql.MySQLErrName[mysql.ErrDupFieldName])
ErrNonUpdatableTable = terror.ClassOptimizer.New(CodeNonUpdatableTable, mysql.MySQLErrName[mysql.ErrNonUpdatableTable])
)

func init() {
mySQLErrCodes := map[terror.ErrCode]uint16{
CodeInvalidWildCard: mysql.ErrParse,
CodeInvalidGroupFuncUse: mysql.ErrInvalidGroupFuncUse,
CodeIllegalReference: mysql.ErrIllegalReference,
CodeNoDB: mysql.ErrNoDB,
CodeUnknownExplainFormat: mysql.ErrUnknownExplainFormat,
CodeWrongGroupField: mysql.ErrWrongGroupField,
CodeDupFieldName: mysql.ErrDupFieldName,
CodeNonUpdatableTable: mysql.ErrUnknownTable,
}
terror.ErrClassToMySQLCodes[terror.ClassOptimizer] = mySQLErrCodes
expression.EvalAstExpr = evalAstExpr
}
47 changes: 0 additions & 47 deletions plan/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,57 +26,10 @@ import (
"github.com/pingcap/tidb/parser/opcode"
"github.com/pingcap/tidb/sessionctx"
"github.com/pingcap/tidb/table"
"github.com/pingcap/tidb/terror"
"github.com/pingcap/tidb/types"
"github.com/pingcap/tidb/util/ranger"
)

// Error instances.
var (
ErrUnsupportedType = terror.ClassOptimizerPlan.New(CodeUnsupportedType, "Unsupported type %T")
SystemInternalErrorType = terror.ClassOptimizerPlan.New(SystemInternalError, "System internal error")
ErrUnknownColumn = terror.ClassOptimizerPlan.New(CodeUnknownColumn, mysql.MySQLErrName[mysql.ErrBadField])
ErrUnknownTable = terror.ClassOptimizerPlan.New(CodeUnknownTable, mysql.MySQLErrName[mysql.ErrUnknownTable])
ErrWrongArguments = terror.ClassOptimizerPlan.New(CodeWrongArguments, "Incorrect arguments to EXECUTE")
ErrAmbiguous = terror.ClassOptimizerPlan.New(CodeAmbiguous, "Column '%s' in field list is ambiguous")
ErrAnalyzeMissIndex = terror.ClassOptimizerPlan.New(CodeAnalyzeMissIndex, "Index '%s' in field list does not exist in table '%s'")
ErrAlterAutoID = terror.ClassAutoid.New(CodeAlterAutoID, "No support for setting auto_increment using alter_table")
ErrBadGeneratedColumn = terror.ClassOptimizerPlan.New(CodeBadGeneratedColumn, mysql.MySQLErrName[mysql.ErrBadGeneratedColumn])
ErrFieldNotInGroupBy = terror.ClassOptimizerPlan.New(CodeFieldNotInGroupBy, mysql.MySQLErrName[mysql.ErrFieldNotInGroupBy])
ErrBadTable = terror.ClassOptimizerPlan.New(CodeBadTable, mysql.MySQLErrName[mysql.ErrBadTable])
ErrKeyDoesNotExist = terror.ClassOptimizerPlan.New(CodeKeyDoesNotExist, mysql.MySQLErrName[mysql.ErrKeyDoesNotExist])
)

// Error codes.
const (
CodeUnsupportedType terror.ErrCode = 1
SystemInternalError = 2
CodeAlterAutoID = 3
CodeAnalyzeMissIndex = 4
CodeAmbiguous = 1052
CodeUnknownColumn = mysql.ErrBadField
CodeUnknownTable = mysql.ErrUnknownTable
CodeWrongArguments = 1210
CodeBadGeneratedColumn = mysql.ErrBadGeneratedColumn
CodeFieldNotInGroupBy = mysql.ErrFieldNotInGroupBy
CodeBadTable = mysql.ErrBadTable
CodeKeyDoesNotExist = mysql.ErrKeyDoesNotExist
)

func init() {
tableMySQLErrCodes := map[terror.ErrCode]uint16{
CodeUnknownColumn: mysql.ErrBadField,
CodeUnknownTable: mysql.ErrBadTable,
CodeAmbiguous: mysql.ErrNonUniq,
CodeWrongArguments: mysql.ErrWrongArguments,
CodeBadGeneratedColumn: mysql.ErrBadGeneratedColumn,
CodeFieldNotInGroupBy: mysql.ErrFieldNotInGroupBy,
CodeBadTable: mysql.ErrBadTable,
CodeKeyDoesNotExist: mysql.ErrKeyDoesNotExist,
}
terror.ErrClassToMySQLCodes[terror.ClassOptimizerPlan] = tableMySQLErrCodes
}

type visitInfo struct {
privilege mysql.PrivilegeType
db string
Expand Down
48 changes: 23 additions & 25 deletions terror/terror.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ const (
ClassKV
ClassMeta
ClassOptimizer
ClassOptimizerPlan
ClassParser
ClassPerfSchema
ClassPrivilege
Expand All @@ -88,30 +87,29 @@ const (
)

var errClz2Str = map[ErrClass]string{
ClassAutoid: "autoid",
ClassDDL: "ddl",
ClassDomain: "domain",
ClassExecutor: "executor",
ClassExpression: "expression",
ClassAdmin: "admin",
ClassMeta: "meta",
ClassKV: "kv",
ClassOptimizer: "optimizer",
ClassOptimizerPlan: "plan",
ClassParser: "parser",
ClassPerfSchema: "perfschema",
ClassPrivilege: "privilege",
ClassSchema: "schema",
ClassServer: "server",
ClassStructure: "structure",
ClassVariable: "variable",
ClassTable: "table",
ClassTypes: "types",
ClassGlobal: "global",
ClassMockTikv: "mocktikv",
ClassJSON: "json",
ClassTiKV: "tikv",
ClassSession: "session",
ClassAutoid: "autoid",
ClassDDL: "ddl",
ClassDomain: "domain",
ClassExecutor: "executor",
ClassExpression: "expression",
ClassAdmin: "admin",
ClassMeta: "meta",
ClassKV: "kv",
ClassOptimizer: "planner",
ClassParser: "parser",
ClassPerfSchema: "perfschema",
ClassPrivilege: "privilege",
ClassSchema: "schema",
ClassServer: "server",
ClassStructure: "structure",
ClassVariable: "variable",
ClassTable: "table",
ClassTypes: "types",
ClassGlobal: "global",
ClassMockTikv: "mocktikv",
ClassJSON: "json",
ClassTiKV: "tikv",
ClassSession: "session",
}

// String implements fmt.Stringer interface.
Expand Down
2 changes: 1 addition & 1 deletion util/ranger/points.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (

// Error instances.
var (
ErrUnsupportedType = terror.ClassOptimizerPlan.New(CodeUnsupportedType, "Unsupported type")
ErrUnsupportedType = terror.ClassOptimizer.New(CodeUnsupportedType, "Unsupported type")
)

// Error codes.
Expand Down

0 comments on commit 6248a74

Please sign in to comment.