Skip to content

Commit 9edc4b9

Browse files
committed
More dump-related fixes
1 parent 9cf989f commit 9edc4b9

File tree

13 files changed

+198
-87
lines changed

13 files changed

+198
-87
lines changed

server/ast/alter_database.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ func nodeAlterDatabase(ctx *Context, node *tree.AlterDatabase) (vitess.Statement
2626
return nil, nil
2727
}
2828

29-
// We can handle the common ALTER DATABASE .. TO OWNER case since it's a no-op
30-
if node.Owner != "" {
31-
return NewNoOp("owners are unsupported"), nil
29+
// We intentionally don't support OWNER TO since we don't support owning objects
30+
if node.Owner != "" && len(node.Options) == 0 {
31+
return NewNoOp("OWNER TO is unsupported and ignored"), nil
3232
}
3333

3434
return NotYetSupportedError("ALTER DATABASE is not yet supported")

server/ast/alter_function.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ func nodeAlterFunction(ctx *Context, node *tree.AlterFunction) (vitess.Statement
2727
return nil, err
2828
}
2929

30-
// We can handle the common ALTER FUNCTION .. TO OWNER case since it's a no-op
31-
if node.Owner != "" {
32-
return NewNoOp("owners are unsupported"), nil
30+
// We intentionally don't support OWNER TO since we don't support owning objects
31+
if node.Owner != "" && len(node.Options) == 0 {
32+
return NewNoOp("OWNER TO is unsupported and ignored"), nil
3333
}
3434

3535
return NotYetSupportedError("ALTER FUNCTION statement is not yet supported")

server/ast/alter_schema.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ func nodeAlterSchema(ctx *Context, node *tree.AlterSchema) (vitess.Statement, er
2626
return nil, nil
2727
}
2828

29-
// We can handle the common ALTER SCHEMA .. TO OWNER case since it's a no-op
29+
// We intentionally don't support OWNER TO since we don't support owning objects
3030
if _, ok := node.Cmd.(*tree.AlterSchemaOwner); ok {
31-
return NewNoOp("owners are unsupported"), nil
31+
return NewNoOp("OWNER TO is unsupported and ignored"), nil
3232
}
3333

3434
return NotYetSupportedError("ALTER SCHEMA is not yet supported")

server/ast/alter_sequence.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ func nodeAlterSequence(ctx *Context, node *tree.AlterSequence) (vitess.Statement
3232

3333
var warnings []string
3434
if len(node.Owner) > 0 {
35+
// We intentionally don't support OWNER TO since we don't support owning objects
3536
if len(node.Options) == 0 {
3637
return NewNoOp("OWNER TO is unsupported and ignored"), nil
3738
} else {

server/ast/alter_type.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ func nodeAlterType(ctx *Context, node *tree.AlterType) (vitess.Statement, error)
2626
return nil, nil
2727
}
2828

29-
// We can handle the common ALTER TYPE .. TO OWNER case since it's a no-op
29+
// We intentionally don't support OWNER TO since we don't support owning objects
3030
if _, ok := node.Cmd.(*tree.AlterTypeOwner); ok {
31-
return NewNoOp("owners are unsupported"), nil
31+
return NewNoOp("OWNER TO is unsupported and ignored"), nil
3232
}
3333

3434
return NotYetSupportedError("ALTER TYPE is not yet supported")

server/ast/alter_view.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ func nodeAlterView(ctx *Context, stmt *tree.AlterView) (sqlparser.Statement, err
2626
return nil, nil
2727
}
2828

29-
// We can handle the common ALTER VIEW .. TO OWNER case since it's a no-op
29+
// We intentionally don't support OWNER TO since we don't support owning objects
3030
if _, ok := stmt.Cmd.(*tree.AlterViewOwnerTo); ok {
31-
return NewNoOp("owners are unsupported"), nil
31+
return NewNoOp("OWNER TO is unsupported and ignored"), nil
3232
}
3333

3434
return NotYetSupportedError("ALTER VIEW is not yet supported")

server/cast/timestamp.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ func timestampAssignment() {
3737
FromType: pgtypes.Timestamp,
3838
ToType: pgtypes.Date,
3939
Function: func(ctx *sql.Context, val any, targetType *pgtypes.DoltgresType) (any, error) {
40-
return pgdate.MakeDateFromTime(val.(time.Time))
40+
d, err := pgdate.MakeDateFromTime(val.(time.Time))
41+
if err != nil {
42+
return nil, err
43+
}
44+
return d.ToTime()
4145
},
4246
})
4347
framework.MustAddAssignmentTypeCast(framework.TypeCast{

server/cast/timestamptz.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ func timestampTZAssignment() {
3737
FromType: pgtypes.TimestampTZ,
3838
ToType: pgtypes.Date,
3939
Function: func(ctx *sql.Context, val any, targetType *pgtypes.DoltgresType) (any, error) {
40-
return pgdate.MakeDateFromTime(val.(time.Time))
40+
d, err := pgdate.MakeDateFromTime(val.(time.Time))
41+
if err != nil {
42+
return nil, err
43+
}
44+
return d.ToTime()
4145
},
4246
})
4347
framework.MustAddAssignmentTypeCast(framework.TypeCast{

server/functions/framework/interpreted_function.go

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -102,23 +102,10 @@ func (iFunc InterpretedFunction) VariadicIndex() int {
102102
}
103103

104104
// QuerySingleReturn handles queries that are supposed to return a single value.
105-
func (InterpretedFunction) QuerySingleReturn(ctx *sql.Context, stack plpgsql.InterpreterStack, stmt string, targetType *pgtypes.DoltgresType, bindings []string) (val any, err error) {
106-
if len(bindings) > 0 {
107-
for i, bindingName := range bindings {
108-
variable := stack.GetVariable(bindingName)
109-
if variable.Type == nil {
110-
return nil, fmt.Errorf("variable `%s` could not be found", bindingName)
111-
}
112-
formattedVar, err := variable.Type.FormatValue(*variable.Value)
113-
if err != nil {
114-
return nil, err
115-
}
116-
switch variable.Type.TypCategory {
117-
case pgtypes.TypeCategory_ArrayTypes, pgtypes.TypeCategory_StringTypes:
118-
formattedVar = pq.QuoteLiteral(formattedVar)
119-
}
120-
stmt = strings.Replace(stmt, "$"+strconv.Itoa(i+1), formattedVar, 1)
121-
}
105+
func (iFunc InterpretedFunction) QuerySingleReturn(ctx *sql.Context, stack plpgsql.InterpreterStack, stmt string, targetType *pgtypes.DoltgresType, bindings []string) (val any, err error) {
106+
stmt, _, err = iFunc.ApplyBindings(ctx, stack, stmt, bindings, true)
107+
if err != nil {
108+
return nil, err
122109
}
123110
return sql.RunInterpreted(ctx, func(subCtx *sql.Context) (any, error) {
124111
sch, rowIter, _, err := stack.Runner().QueryWithBindings(subCtx, stmt, nil, nil, nil)
@@ -177,23 +164,10 @@ func (InterpretedFunction) QuerySingleReturn(ctx *sql.Context, stack plpgsql.Int
177164
}
178165

179166
// QueryMultiReturn handles queries that may return multiple values over multiple rows.
180-
func (InterpretedFunction) QueryMultiReturn(ctx *sql.Context, stack plpgsql.InterpreterStack, stmt string, bindings []string) (rows []sql.Row, err error) {
181-
if len(bindings) > 0 {
182-
for i, bindingName := range bindings {
183-
variable := stack.GetVariable(bindingName)
184-
if variable.Type == nil {
185-
return nil, fmt.Errorf("variable `%s` could not be found", bindingName)
186-
}
187-
formattedVar, err := variable.Type.FormatValue(*variable.Value)
188-
if err != nil {
189-
return nil, err
190-
}
191-
switch variable.Type.TypCategory {
192-
case pgtypes.TypeCategory_ArrayTypes, pgtypes.TypeCategory_StringTypes:
193-
formattedVar = pq.QuoteLiteral(formattedVar)
194-
}
195-
stmt = strings.Replace(stmt, "$"+strconv.Itoa(i+1), formattedVar, 1)
196-
}
167+
func (iFunc InterpretedFunction) QueryMultiReturn(ctx *sql.Context, stack plpgsql.InterpreterStack, stmt string, bindings []string) (rows []sql.Row, err error) {
168+
stmt, _, err = iFunc.ApplyBindings(ctx, stack, stmt, bindings, true)
169+
if err != nil {
170+
return nil, err
197171
}
198172
return sql.RunInterpreted(ctx, func(subCtx *sql.Context) ([]sql.Row, error) {
199173
_, rowIter, _, err := stack.Runner().QueryWithBindings(subCtx, stmt, nil, nil, nil)
@@ -207,5 +181,43 @@ func (InterpretedFunction) QueryMultiReturn(ctx *sql.Context, stack plpgsql.Inte
207181
})
208182
}
209183

184+
// ApplyBindings applies the given bindings to the statement. If `varFound` is false, then the error will be state that
185+
// the variable was not found (which means the error may be ignored if you're only concerned with finding a variable).
186+
// If `varFound` is true, then the error is related to formatting the variable. `enforceType` adds casting and quotes to
187+
// ensure that the value is correctly represented in the string.
188+
func (InterpretedFunction) ApplyBindings(ctx *sql.Context, stack plpgsql.InterpreterStack, stmt string, bindings []string, enforceType bool) (newStmt string, varFound bool, err error) {
189+
if len(bindings) == 0 {
190+
return stmt, false, nil
191+
}
192+
newStmt = stmt
193+
for i, bindingName := range bindings {
194+
variable := stack.GetVariable(bindingName)
195+
if variable.Type == nil {
196+
return newStmt, false, fmt.Errorf("variable `%s` could not be found", bindingName)
197+
}
198+
var formattedVar string
199+
if *variable.Value != nil {
200+
formattedVar, err = variable.Type.FormatValue(*variable.Value)
201+
if err != nil {
202+
return newStmt, true, err
203+
}
204+
if enforceType {
205+
switch variable.Type.TypCategory {
206+
case pgtypes.TypeCategory_ArrayTypes, pgtypes.TypeCategory_DateTimeTypes, pgtypes.TypeCategory_StringTypes:
207+
formattedVar = pq.QuoteLiteral(formattedVar)
208+
}
209+
}
210+
} else {
211+
formattedVar = "NULL"
212+
}
213+
if enforceType {
214+
newStmt = strings.Replace(newStmt, "$"+strconv.Itoa(i+1), fmt.Sprintf(`(%s)::%s`, formattedVar, variable.Type.String()), 1)
215+
} else {
216+
newStmt = strings.Replace(newStmt, "$"+strconv.Itoa(i+1), formattedVar, 1)
217+
}
218+
}
219+
return newStmt, true, nil
220+
}
221+
210222
// enforceInterfaceInheritance implements the interface FunctionInterface.
211223
func (iFunc InterpretedFunction) enforceInterfaceInheritance(error) {}

server/plpgsql/interpreter_logic.go

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"strconv"
2020
"strings"
2121

22+
"github.com/cockroachdb/errors"
2223
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
2324
"github.com/dolthub/go-mysql-server/sql"
2425
"github.com/jackc/pgx/v5/pgproto3"
@@ -32,6 +33,7 @@ import (
3233
// InterpretedFunction is an interface that essentially mirrors the implementation of InterpretedFunction in the
3334
// framework package.
3435
type InterpretedFunction interface {
36+
ApplyBindings(ctx *sql.Context, stack InterpreterStack, stmt string, bindings []string, enforceType bool) (newStmt string, varFound bool, err error)
3537
GetParameters() []*pgtypes.DoltgresType
3638
GetParameterNames() []string
3739
GetReturn() *pgtypes.DoltgresType
@@ -207,23 +209,25 @@ func call(ctx *sql.Context, iFunc InterpretedFunction, stack InterpreterStack) (
207209
// notice levels to send to the client.
208210
// https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-CLIENT-MIN-MESSAGES
209211

210-
// TODO: Notices at the EXCEPTION level should also abort the current tx.
211-
212212
message, err := evaluteNoticeMessage(ctx, iFunc, operation, stack)
213213
if err != nil {
214214
return nil, err
215215
}
216216

217-
noticeResponse := &pgproto3.NoticeResponse{
218-
Severity: operation.PrimaryData,
219-
Message: message,
220-
}
221-
222-
if err = applyNoticeOptions(ctx, noticeResponse, operation.Options); err != nil {
223-
return nil, err
217+
if operation.PrimaryData == "EXCEPTION" {
218+
// TODO: Notices at the EXCEPTION level should also abort the current tx.
219+
return nil, errors.New(message)
220+
} else {
221+
noticeResponse := &pgproto3.NoticeResponse{
222+
Severity: operation.PrimaryData,
223+
Message: message,
224+
}
225+
if err = applyNoticeOptions(ctx, noticeResponse, operation.Options); err != nil {
226+
return nil, err
227+
}
228+
sess := dsess.DSessFromSess(ctx.Session)
229+
sess.Notice(noticeResponse)
224230
}
225-
sess := dsess.DSessFromSess(ctx.Session)
226-
sess.Notice(noticeResponse)
227231
case OpCode_Return:
228232
if len(operation.PrimaryData) == 0 {
229233
return nil, nil
@@ -295,22 +299,36 @@ func evaluteNoticeMessage(ctx *sql.Context, iFunc InterpretedFunction,
295299
message := operation.SecondaryData[0]
296300
if len(operation.SecondaryData) > 1 {
297301
params := operation.SecondaryData[1:]
298-
currentParam := 0
302+
currentParamIdx := 0
299303

300304
parts := strings.Split(message, "%%")
301305
for i, part := range parts {
302306
for strings.Contains(part, "%") {
303-
retVal, err := iFunc.QuerySingleReturn(ctx, stack, "SELECT "+params[currentParam], nil, nil)
304-
if err != nil {
305-
return "", err
307+
if currentParamIdx >= len(params) {
308+
return "", errors.New("too few parameters specified for RAISE")
309+
}
310+
currentParam := params[currentParamIdx]
311+
currentParamIdx += 1
312+
formattedVar, varFound, err := iFunc.ApplyBindings(ctx, stack, "$1", []string{currentParam}, false)
313+
if varFound {
314+
if err != nil {
315+
return "", err
316+
}
317+
part = strings.Replace(part, "%", formattedVar, 1)
318+
} else {
319+
retVal, err := iFunc.QuerySingleReturn(ctx, stack, fmt.Sprintf("SELECT (%s)::text", currentParam), nil, nil)
320+
if err != nil {
321+
return "", err
322+
}
323+
stringVal := fmt.Sprintf("%v", retVal) // We should always return a string, but this is just a safety net
324+
part = strings.Replace(part, "%", stringVal, 1)
306325
}
307-
currentParam += 1
308-
309-
s := fmt.Sprintf("%v", retVal)
310-
part = strings.Replace(part, "%", s, 1)
311326
}
312327
parts[i] = part
313328
}
329+
if currentParamIdx < len(params) {
330+
return "", errors.New("too many parameters specified for RAISE")
331+
}
314332
message = strings.Join(parts, "%")
315333
}
316334
return message, nil

0 commit comments

Comments
 (0)