Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plan: refactor errors #6377

Merged
merged 11 commits into from
May 9, 2018
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, "[optimizer:1054]Unknown column 'b' in 'field list'")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

planner?

}
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)
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 is returned when SQL operators are not properly used.
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 @@ -1177,7 +1177,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, "field list")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/ "field list"/ clauseMsg[fieldList]
so as the others.

return
}
if column != nil {
Expand All @@ -1192,7 +1192,7 @@ func (er *expressionRewriter) toColumn(v *ast.ColumnName) {
return
}
if err != nil {
er.err = ErrAmbiguous.GenByArgs(v.Name)
er.err = ErrAmbiguous.GenByArgs(v.Name, "field list")
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 @@ -774,14 +774,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")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add test case for this in TestNameResolver?

Copy link
Member Author

@zz-jason zz-jason May 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the Offset and Count of ast.Limit is guaranteed to be a value of uint64 by parser, maybe we should delete this check.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But if offset and count are paramMarker, they are not guaranteed to be uint64.

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 @@ -844,7 +844,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, "field list")
}
}
}
Expand Down
20 changes: 10 additions & 10 deletions plan/logical_plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1545,27 +1545,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", "[optimizer: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", "[optimizer:1051]Unknown table 't2'"},
{"select b as a, c as a from t group by a", "[optimizer: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", "[optimizer: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", "[optimizer: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'"},
{"select a from t where t11.a < t.a", "[optimizer:1054]Unknown column 't11.a' in 'where clause'"},
{"select a from t having t11.c1 < t.a", "[optimizer:1054]Unknown column 't11.c1' in 'having clause'"},
{"select a from t where t.a < t.a order by t11.c1", "[optimizer:1054]Unknown column 't11.c1' in 'order clause'"},
{"select a from t group by t11.c1", "[optimizer: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"},
{"delete b from (select * from t ) as a, t", "[optimizer:1109]Unknown table 'b' in MULTI DELETE"},
}

for _, t := range tests {
Expand Down
50 changes: 0 additions & 50 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 @@ -169,54 +167,6 @@ func existsCartesianProduct(p LogicalPlan) bool {
return false
}

// Optimizer error codes.
const (
CodeOperandColumns terror.ErrCode = 1
CodeInvalidWildCard = 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 (
ErrOperandColumns = terror.ClassOptimizer.New(CodeOperandColumns, "Operand should contain %d column(s)")
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{
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.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
46 changes: 22 additions & 24 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 @@ -87,29 +86,28 @@ 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",
ClassAutoid: "autoid",
ClassDDL: "ddl",
ClassDomain: "domain",
ClassExecutor: "executor",
ClassExpression: "expression",
ClassAdmin: "admin",
ClassMeta: "meta",
ClassKV: "kv",
ClassOptimizer: "optimizer",
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",
}

// 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