Skip to content

Commit d9efee5

Browse files
author
James Cor
committed
compiling?
1 parent 24f2c2a commit d9efee5

File tree

2 files changed

+106
-59
lines changed

2 files changed

+106
-59
lines changed

sql/procedures/interpreter_logic.go

Lines changed: 42 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ package procedures
1616

1717
import (
1818
"fmt"
19-
"github.com/dolthub/doltgresql/core"
20-
"github.com/dolthub/doltgresql/core/id"
21-
"github.com/dolthub/go-mysql-server/sql"
19+
"io"
20+
21+
"github.com/dolthub/go-mysql-server/sql"
22+
"github.com/dolthub/go-mysql-server/sql/types"
2223
)
2324

2425
// InterpreterNode is an interface that implements an interpreter. These are typically used for functions (which may be
@@ -32,21 +33,21 @@ type InterpreterNode interface {
3233
}
3334

3435
// Call runs the contained operations on the given runner.
35-
func Call(ctx *sql.Context, call sql.InterpreterNode, runner sql.StatementRunner) (any, error) {
36+
func Call(ctx *sql.Context, iNode sql.InterpreterNode, runner sql.StatementRunner, vals []any) (any, error) {
3637
// Set up the initial state of the function
3738
counter := -1 // We increment before accessing, so start at -1
3839
stack := NewInterpreterStack()
3940
// Add the parameters
40-
parameterTypes := call.GetParameters()
41-
parameterNames := call.GetParameterNames()
41+
parameterTypes := iNode.GetParameters()
42+
parameterNames := iNode.GetParameterNames()
4243
if len(vals) != len(parameterTypes) {
4344
return nil, fmt.Errorf("parameter count mismatch: expected %d got %d", len(parameterTypes), len(vals))
4445
}
4546
for i := range vals {
4647
stack.NewVariableWithValue(parameterNames[i], parameterTypes[i], vals[i])
4748
}
4849
// Run the statements
49-
statements := call.Ops
50+
statements := iNode.GetStatements()
5051
for {
5152
counter++
5253
if counter >= len(statements) {
@@ -58,43 +59,28 @@ func Call(ctx *sql.Context, call sql.InterpreterNode, runner sql.StatementRunner
5859
operation := statements[counter]
5960
switch operation.OpCode {
6061
case OpCode_Select:
61-
62+
// TODO
6263
case OpCode_Declare:
63-
typeCollection, err := core.GetTypesCollectionFromContext(ctx)
64-
if err != nil {
65-
return nil, err
66-
}
67-
resolvedType, exists := typeCollection.GetType(id.NewType("pg_catalog", operation.PrimaryData))
68-
if !exists {
69-
return nil, pgtypes.ErrTypeDoesNotExist.New(operation.PrimaryData)
70-
}
64+
resolvedType := types.Uint32 // TODO: figure out actual type from operation
7165
stack.NewVariable(operation.Target, resolvedType)
7266
case OpCode_Exception:
7367
// TODO: implement
7468
case OpCode_Execute:
75-
if len(operation.Target) > 0 {
76-
target := stack.GetVariable(operation.Target)
77-
if target == nil {
78-
return nil, fmt.Errorf("variable `%s` could not be found", operation.Target)
79-
}
80-
retVal, err := iFunc.QuerySingleReturn(ctx, stack, operation.PrimaryData, target.Type, operation.SecondaryData)
81-
if err != nil {
82-
return nil, err
83-
}
84-
err = stack.SetVariable(ctx, operation.Target, retVal)
85-
if err != nil {
86-
return nil, err
87-
}
88-
} else {
89-
rowIter, err := iFunc.QueryMultiReturn(ctx, stack, operation.PrimaryData, operation.SecondaryData)
90-
if err != nil {
91-
return nil, err
92-
}
93-
if _, err = sql.RowIterToRows(ctx, rowIter); err != nil {
69+
_, rowIter, _, err := runner.QueryWithBindings(ctx, "", operation.PrimaryData, nil, nil)
70+
if err != nil {
71+
return nil, err
72+
}
73+
for {
74+
if _, rErr := rowIter.Next(ctx); rErr != nil {
75+
if rErr == io.EOF {
76+
break
77+
}
9478
return nil, err
9579
}
9680
}
97-
81+
if err = rowIter.Close(ctx); err != nil {
82+
return nil, err
83+
}
9884
case OpCode_Goto:
9985
// We must compare to the index - 1, so that the increment hits our target
10086
if counter <= operation.Index {
@@ -104,6 +90,8 @@ func Call(ctx *sql.Context, call sql.InterpreterNode, runner sql.StatementRunner
10490
stack.PushScope()
10591
case OpCode_ScopeEnd:
10692
stack.PopScope()
93+
default:
94+
// No-op
10795
}
10896
}
10997
} else {
@@ -113,24 +101,33 @@ func Call(ctx *sql.Context, call sql.InterpreterNode, runner sql.StatementRunner
113101
stack.PopScope()
114102
case OpCode_ScopeEnd:
115103
stack.PushScope()
104+
default:
105+
// No-op
116106
}
117107
}
118108
}
119109
case OpCode_If:
120-
sch, rowIter, _, err := runner.QueryWithBindings(ctx, "", operation.PrimaryData, nil, nil)
110+
_, rowIter, _, err := runner.QueryWithBindings(ctx, "", operation.PrimaryData, nil, nil)
121111
if err != nil {
122112
return nil, err
123113
}
124-
row, err := rowIter.Next(ctx)
125-
if err != nil {
126-
return nil, err
114+
for {
115+
if _, rErr := rowIter.Next(ctx); rErr != nil {
116+
if rErr == io.EOF {
117+
break
118+
}
119+
return nil, err
120+
}
127121
}
128-
rowIter.Close(ctx)
129-
if retVal.(bool) {
130-
// We're never changing the scope, so we can just assign it directly.
131-
// Also, we must assign to index-1, so that the increment hits our target.
132-
counter = operation.Index - 1
122+
if err = rowIter.Close(ctx); err != nil {
123+
return nil, err
133124
}
125+
// TODO: ensure there is exactly one result that is a bool
126+
//if retVal.(bool) {
127+
// // We're never changing the scope, so we can just assign it directly.
128+
// // Also, we must assign to index-1, so that the increment hits our target.
129+
// counter = operation.Index - 1
130+
//}
134131

135132
case OpCode_ScopeBegin:
136133
stack.PushScope()

sql/procedures/interpreter_stack.go

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,70 @@ import (
1818
"fmt"
1919

2020
"github.com/dolthub/go-mysql-server/sql"
21-
"github.com/dolthub/go-mysql-server/sql/analyzer"
22-
23-
pgtypes "github.com/dolthub/doltgresql/server/types"
24-
"github.com/dolthub/doltgresql/utils"
2521
)
2622

23+
// Stack is a generic stack.
24+
type Stack[T any] struct {
25+
values []T
26+
}
27+
28+
// NewStack creates a new, empty stack.
29+
func NewStack[T any]() *Stack[T] {
30+
return &Stack[T]{}
31+
}
32+
33+
// Len returns the size of the stack.
34+
func (s *Stack[T]) Len() int {
35+
return len(s.values)
36+
}
37+
38+
// Peek returns the top value on the stack without removing it.
39+
func (s *Stack[T]) Peek() (value T) {
40+
if len(s.values) == 0 {
41+
return
42+
}
43+
return s.values[len(s.values)-1]
44+
}
45+
46+
// PeekDepth returns the n-th value from the top. PeekDepth(0) is equivalent to the standard Peek().
47+
func (s *Stack[T]) PeekDepth(depth int) (value T) {
48+
if len(s.values) <= depth {
49+
return
50+
}
51+
return s.values[len(s.values)-(1+depth)]
52+
}
53+
54+
// PeekReference returns a reference to the top value on the stack without removing it.
55+
func (s *Stack[T]) PeekReference() *T {
56+
if len(s.values) == 0 {
57+
return nil
58+
}
59+
return &s.values[len(s.values)-1]
60+
}
61+
62+
// Pop returns the top value on the stack while also removing it from the stack.
63+
func (s *Stack[T]) Pop() (value T) {
64+
if len(s.values) == 0 {
65+
return
66+
}
67+
value = s.values[len(s.values)-1]
68+
s.values = s.values[:len(s.values)-1]
69+
return
70+
}
71+
72+
// Push adds the given value to the stack.
73+
func (s *Stack[T]) Push(value T) {
74+
s.values = append(s.values, value)
75+
}
76+
77+
// Empty returns whether the stack is empty.
78+
func (s *Stack[T]) Empty() bool {
79+
return len(s.values) == 0
80+
}
81+
2782
// InterpreterVariable is a variable that lives on the stack.
2883
type InterpreterVariable struct {
29-
Type *pgtypes.DoltgresType
84+
Type sql.Type
3085
Value any
3186
}
3287

@@ -39,12 +94,12 @@ type InterpreterScopeDetails struct {
3994
// the same as a stack in the traditional programming sense, but rather is a loose abstraction that serves the same
4095
// general purpose.
4196
type InterpreterStack struct {
42-
stack *utils.Stack[*InterpreterScopeDetails]
97+
stack *Stack[*InterpreterScopeDetails]
4398
}
4499

45100
// NewInterpreterStack creates a new InterpreterStack.
46101
func NewInterpreterStack() InterpreterStack {
47-
stack := utils.NewStack[*InterpreterScopeDetails]()
102+
stack := NewStack[*InterpreterScopeDetails]()
48103
// This first push represents the function base, including parameters
49104
stack.Push(&InterpreterScopeDetails{
50105
variables: make(map[string]*InterpreterVariable),
@@ -59,11 +114,6 @@ func (is *InterpreterStack) Details() *InterpreterScopeDetails {
59114
return is.stack.Peek()
60115
}
61116

62-
// Runner returns the runner that is being used for the function's execution.
63-
func (is *InterpreterStack) Runner() sql.StatementRunner {
64-
return is.runner
65-
}
66-
67117
// GetVariable traverses the stack (starting from the top) to find a variable with a matching name. Returns nil if no
68118
// variable was found.
69119
func (is *InterpreterStack) GetVariable(name string) *InterpreterVariable {
@@ -88,12 +138,12 @@ func (is *InterpreterStack) ListVariables() map[string]struct{} {
88138

89139
// NewVariable creates a new variable in the current scope. If a variable with the same name exists in a previous scope,
90140
// then that variable will be shadowed until the current scope exits.
91-
func (is *InterpreterStack) NewVariable(name string, typ *pgtypes.DoltgresType) {
141+
func (is *InterpreterStack) NewVariable(name string, typ sql.Type) {
92142
is.NewVariableWithValue(name, typ, typ.Zero())
93143
}
94144

95145
// NewVariableWithValue creates a new variable in the current scope, setting its initial value to the one given.
96-
func (is *InterpreterStack) NewVariableWithValue(name string, typ *pgtypes.DoltgresType, val any) {
146+
func (is *InterpreterStack) NewVariableWithValue(name string, typ sql.Type, val any) {
97147
is.stack.Peek().variables[name] = &InterpreterVariable{
98148
Type: typ,
99149
Value: val,

0 commit comments

Comments
 (0)