Skip to content

Commit 4f357b9

Browse files
author
James Cor
committed
fix prepare statements and user vars in stored procedures
1 parent d3b95b2 commit 4f357b9

File tree

4 files changed

+65
-13
lines changed

4 files changed

+65
-13
lines changed

engine.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -593,14 +593,7 @@ func (e *Engine) analyzeNode(ctx *sql.Context, query string, bound sql.Node, qFl
593593
// todo(max): improve name resolution so we can cache post name-binding.
594594
// this involves expression memoization, which currently screws up aggregation
595595
// and order by aliases
596-
prepStmt, _, err := e.Parser.ParseOneWithOptions(ctx, query, sqlMode.ParserOptions())
597-
if err != nil {
598-
return nil, err
599-
}
600-
prepare, ok := prepStmt.(*sqlparser.Prepare)
601-
if !ok {
602-
return nil, fmt.Errorf("expected *sqlparser.Prepare, found %T", prepStmt)
603-
}
596+
prepare := n.PrepStmt
604597
cacheStmt, _, err := e.Parser.ParseOneWithOptions(ctx, prepare.Expr, sqlMode.ParserOptions())
605598
if err != nil && strings.HasPrefix(prepare.Expr, "@") {
606599
val, err := expression.NewUserVar(strings.TrimPrefix(prepare.Expr, "@")).Eval(ctx, nil)

enginetest/queries/procedure_queries.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,6 +2192,58 @@ END;`,
21922192
},
21932193
},
21942194
},
2195+
{
2196+
Name: "user variables are usable within stored procedures",
2197+
SetUpScript: []string{
2198+
`
2199+
create procedure proc()
2200+
begin
2201+
declare v int default 123;
2202+
set @v = v;
2203+
end;
2204+
`,
2205+
},
2206+
Assertions: []ScriptTestAssertion{
2207+
{
2208+
Query: "call proc();",
2209+
Expected: []sql.Row{{}},
2210+
},
2211+
{
2212+
Query: "select @v;",
2213+
Expected: []sql.Row{
2214+
{123},
2215+
},
2216+
},
2217+
},
2218+
},
2219+
{
2220+
Name: "prepare statement inside of stored procedures",
2221+
SetUpScript: []string{
2222+
`
2223+
create procedure create_proc()
2224+
begin
2225+
set @stmt = 'create table t (i int)';
2226+
prepare stmt from @stmt;
2227+
execute stmt;
2228+
deallocate prepare stmt;
2229+
end;
2230+
`,
2231+
},
2232+
Assertions: []ScriptTestAssertion{
2233+
{
2234+
Query: "call create_proc();",
2235+
Expected: []sql.Row{
2236+
{types.NewOkResult(0)},
2237+
},
2238+
},
2239+
{
2240+
Query: "insert into t values (1), (2), (3);",
2241+
Expected: []sql.Row{
2242+
{types.NewOkResult(3)},
2243+
},
2244+
},
2245+
},
2246+
},
21952247
}
21962248

21972249
var ProcedureCallTests = []ScriptTest{

sql/plan/prepare.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,27 @@ import (
1919

2020
"github.com/dolthub/go-mysql-server/sql"
2121
"github.com/dolthub/go-mysql-server/sql/types"
22+
23+
"github.com/dolthub/vitess/go/vt/sqlparser"
2224
)
2325

2426
// PrepareQuery is a node that prepares the query
2527
type PrepareQuery struct {
26-
Name string
27-
Child sql.Node
28+
Name string
29+
Child sql.Node
30+
PrepStmt *sqlparser.Prepare
2831
}
2932

3033
var _ sql.Node = (*PrepareQuery)(nil)
3134
var _ sql.CollationCoercible = (*PrepareQuery)(nil)
3235

3336
// NewPrepareQuery creates a new PrepareQuery node.
34-
func NewPrepareQuery(name string, child sql.Node) *PrepareQuery {
35-
return &PrepareQuery{Name: name, Child: child}
37+
func NewPrepareQuery(name string, child sql.Node, prepStmt *sqlparser.Prepare) *PrepareQuery {
38+
return &PrepareQuery{
39+
Name: name,
40+
Child: child,
41+
PrepStmt: prepStmt,
42+
}
3643
}
3744

3845
// Schema implements the Node interface.

sql/planbuilder/transactions.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (b *Builder) buildPrepare(inScope *scope, n *ast.Prepare) (outScope *scope)
7070
// test for query structure; bind variables will be discarded
7171
b.bindCtx = &BindvarContext{resolveOnly: true}
7272
childScope := b.build(inScope, childStmt, expr)
73-
outScope.node = plan.NewPrepareQuery(n.Name, childScope.node)
73+
outScope.node = plan.NewPrepareQuery(n.Name, childScope.node, n)
7474
return outScope
7575
}
7676

0 commit comments

Comments
 (0)