// Compile compiles an ast.StmtNode to a stmt.Statement. // If it is supported to use new plan and executer, it optimizes the node to // a plan, and we wrap the plan in an adapter as stmt.Statement. // If it is not supported, the node will be converted to old statement. func (c *Compiler) Compile(ctx context.Context, node ast.StmtNode) (stmt.Statement, error) { if optimizer.IsSupported(node) { ast.SetFlag(node) if err := optimizer.Validate(node, false); err != nil { return nil, errors.Trace(err) } is := sessionctx.GetDomain(ctx).InfoSchema() if err := optimizer.ResolveName(node, is, ctx); err != nil { return nil, errors.Trace(err) } p, err := optimizer.Optimize(ctx, node) if err != nil { return nil, errors.Trace(err) } sa := &statementAdapter{ is: is, plan: p, } return sa, nil } c.converter = &converter.Converter{} s, err := c.converter.Convert(node) if err != nil { return nil, errors.Trace(err) } return s, nil }
// Compile compiles an ast.StmtNode to a stmt.Statement. // If it is supported to use new plan and executer, it optimizes the node to // a plan, and we wrap the plan in an adapter as stmt.Statement. // If it is not supported, the node will be converted to old statement. func (c *Compiler) Compile(ctx context.Context, node ast.StmtNode) (stmt.Statement, error) { if optimizer.IsSupported(node) { ast.SetFlag(node) is := sessionctx.GetDomain(ctx).InfoSchema() if err := optimizer.Preprocess(node, is, ctx); err != nil { return nil, errors.Trace(err) } // Validate should be after NameResolve. if err := optimizer.Validate(node, false); err != nil { return nil, errors.Trace(err) } sb := NewSubQueryBuilder(is) p, err := optimizer.Optimize(ctx, node, sb) if err != nil { return nil, errors.Trace(err) } sa := &statementAdapter{ is: is, plan: p, } return sa, nil } c.converter = &converter.Converter{} s, err := c.converter.Convert(node) if err != nil { return nil, errors.Trace(err) } return s, nil }
func (s *testValidatorSuite) TestValidator(c *C) { cases := []struct { sql string inPrepare bool err error }{ {"select ?", false, parser.ErrSyntax}, {"select ?", true, nil}, {"create table t(id int not null auto_increment default 2, key (id))", true, errors.New("Invalid default value for 'id'")}, {"create table t(id int not null default 2 auto_increment, key (id))", true, errors.New("Invalid default value for 'id'")}, {"create table t(id int not null auto_increment)", true, errors.New("Incorrect table definition; there can be only one auto column and it must be defined as a key")}, {"create table t(id int not null auto_increment, c int auto_increment, key (id, c))", true, errors.New("Incorrect table definition; there can be only one auto column and it must be defined as a key")}, {"create table t(id int not null auto_increment, c int, key (c, id))", true, errors.New("Incorrect table definition; there can be only one auto column and it must be defined as a key")}, {"create table t(id decimal auto_increment, key (id))", true, errors.New("Incorrect column specifier for column 'id'")}, {"create table t(id float auto_increment, key (id))", true, nil}, } store, err := tidb.NewStore(tidb.EngineGoLevelDBMemory) c.Assert(err, IsNil) se, err := tidb.CreateSession(store) c.Assert(err, IsNil) for _, ca := range cases { stmts, err1 := tidb.Parse(se.(context.Context), ca.sql) c.Assert(err1, IsNil) c.Assert(stmts, HasLen, 1) stmt := stmts[0] err = optimizer.Validate(stmt, ca.inPrepare) c.Assert(terror.ErrorEqual(err, ca.err), IsTrue) } }
func (s *testValidatorSuite) TestValidator(c *C) { cases := []struct { sql string inPrepare bool err error }{ {"select ?", false, parser.ErrSyntax}, {"select ?", true, nil}, } store, err := tidb.NewStore(tidb.EngineGoLevelDBMemory) c.Assert(err, IsNil) se, err := tidb.CreateSession(store) c.Assert(err, IsNil) for _, ca := range cases { stmts, err1 := tidb.Parse(se.(context.Context), ca.sql) c.Assert(err1, IsNil) c.Assert(stmts, HasLen, 1) stmt := stmts[0] err = optimizer.Validate(stmt, ca.inPrepare) c.Assert(terror.ErrorEqual(err, ca.err), IsTrue) } }