Exemple #1
0
// 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
}
Exemple #2
0
// 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
}
Exemple #3
0
// Build builds a prepared statement into an executor.
func (e *ExecuteExec) Build() error {
	vars := variable.GetSessionVars(e.Ctx)
	if e.Name != "" {
		e.ID = vars.PreparedStmtNameToID[e.Name]
	}
	v := vars.PreparedStmts[e.ID]
	if v == nil {
		return ErrStmtNotFound
	}
	prepared := v.(*Prepared)

	if len(prepared.Params) != len(e.UsingVars) {
		return ErrWrongParamCount
	}

	for i, usingVar := range e.UsingVars {
		val, err := evaluator.Eval(e.Ctx, usingVar)
		if err != nil {
			return errors.Trace(err)
		}
		prepared.Params[i].SetValue(val)
	}

	if optimizer.IsSupported(prepared.Stmt) {
		if prepared.SchemaVersion != e.IS.SchemaMetaVersion() {
			// If the schema version has changed we need to prepare it again,
			// if this time it failed, the real reason for the error is schema changed.
			err := optimizer.Prepare(e.IS, e.Ctx, prepared.Stmt)
			if err != nil {
				return ErrSchemaChanged.Gen("Schema change casued error: %s", err.Error())
			}
			prepared.SchemaVersion = e.IS.SchemaMetaVersion()
		}
		sb := &subqueryBuilder{is: e.IS}
		plan, err := optimizer.Optimize(e.Ctx, prepared.Stmt, sb)
		if err != nil {
			return errors.Trace(err)
		}
		b := newExecutorBuilder(e.Ctx, e.IS)
		stmtExec := b.build(plan)
		if b.err != nil {
			return errors.Trace(b.err)
		}
		e.StmtExec = stmtExec
	} else {
		conv := converter.Converter{}
		oStmt, err := conv.Convert(prepared.Stmt)
		if err != nil {
			return errors.Trace(err)
		}
		e.OldStmt = oStmt
	}
	return nil
}
Exemple #4
0
func checkPlan(c *C, se Session, sql, explain string) {
	ctx := se.(context.Context)
	stmts, err := Parse(ctx, sql)
	c.Assert(err, IsNil)
	stmt := stmts[0]
	c.Assert(optimizer.IsSupported(stmt), IsTrue)
	is := sessionctx.GetDomain(ctx).InfoSchema()
	err = optimizer.Prepare(is, ctx, stmt)
	c.Assert(err, IsNil)
	p, err := optimizer.Optimize(ctx, stmt)
	c.Assert(err, IsNil)
	planStr, err := plan.Explain(p)
	c.Assert(err, IsNil)
	c.Assert(planStr, Equals, explain)
}