Skip to content

Commit bf0922c

Browse files
committed
plpgsql: pass options struct to plpgsqlBuilder
This commit moves the bool arguments used when constructing a `plpgsqlBuilder` instance to an options struct. This will simplify adding new options in the future. Informs #105240 Release note: None
1 parent bdd627e commit bf0922c

File tree

5 files changed

+89
-35
lines changed

5 files changed

+89
-35
lines changed

pkg/sql/opt/optbuilder/create_function.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -427,8 +427,7 @@ func (b *Builder) buildCreateFunction(cf *tree.CreateRoutine, inScope *scope) (o
427427
}
428428

429429
// Special handling for trigger functions.
430-
buildSQL := true
431-
isTriggerFn := false
430+
var skipSQL, isTriggerFn bool
432431
if funcReturnType.Identical(types.Trigger) {
433432
// Trigger functions cannot have user-defined parameters. However, they do
434433
// have a set of implicitly defined parameters.
@@ -449,17 +448,21 @@ func (b *Builder) buildCreateFunction(cf *tree.CreateRoutine, inScope *scope) (o
449448

450449
// Analysis of SQL expressions for trigger functions must be deferred
451450
// until the function is bound to a trigger.
452-
buildSQL = false
453451
isTriggerFn = true
452+
skipSQL = true
454453
}
455454

456455
// We need to disable stable function folding because we want to catch the
457456
// volatility of stable functions. If folded, we only get a scalar and lose
458457
// the volatility.
458+
options := basePLOptions().
459+
SetIsProcedure(cf.IsProcedure).
460+
SetIsTriggerFn(isTriggerFn).
461+
SetSkipSQL(skipSQL)
459462
b.factory.FoldingControl().TemporarilyDisallowStableFolds(func() {
460463
plBuilder := newPLpgSQLBuilder(
461-
b, cf.Name.Object(), stmt.AST.Label, nil /* colRefs */, routineParams, funcReturnType,
462-
cf.IsProcedure, false /* isDoBlock */, isTriggerFn, buildSQL, nil, /* outScope */
464+
b, options, cf.Name.Object(), stmt.AST.Label, nil /* colRefs */, routineParams,
465+
funcReturnType, nil, /* outScope */
463466
)
464467
stmtScope = plBuilder.buildRootBlock(stmt.AST, bodyScope, routineParams)
465468
})

pkg/sql/opt/optbuilder/create_trigger.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,8 @@ func (b *Builder) buildFunctionForTrigger(
244244
}
245245
b.factory.FoldingControl().TemporarilyDisallowStableFolds(func() {
246246
plBuilder := newPLpgSQLBuilder(
247-
b, ct.FuncName.String(), stmt.AST.Label, nil /* colRefs */, triggerFuncParams, tableTyp,
248-
false /* isProcedure */, false, /* isDoBlock */
249-
true /* isTriggerFn */, true /* buildSQL */, nil, /* outScope */
247+
b, basePLOptions().WithIsTriggerFn(), ct.FuncName.String(), stmt.AST.Label,
248+
nil /* colRefs */, triggerFuncParams, tableTyp, nil, /* outScope */
250249
)
251250
funcScope = plBuilder.buildRootBlock(stmt.AST, funcScope, triggerFuncParams)
252251
})

pkg/sql/opt/optbuilder/plpgsql.go

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ import (
156156
// not follow here, although they may be good routes for optimization in the
157157
// future.
158158
type plpgsqlBuilder struct {
159-
ob *Builder
159+
ob *Builder
160+
options plOptions
160161

161162
// colRefs, if non-nil, tracks the set of columns referenced by scalar
162163
// expressions.
@@ -190,13 +191,68 @@ type plpgsqlBuilder struct {
190191
outScope *scope
191192

192193
routineName string
193-
isProcedure bool
194-
isDoBlock bool
195-
isTriggerFn bool
196-
buildSQL bool
197194
identCounter int
198195
}
199196

197+
// plOptions is a set of options that can be used to modify the behavior of the
198+
// PLpgSQL builder.
199+
type plOptions struct {
200+
isProcedure bool
201+
isDoBlock bool
202+
isTriggerFn bool
203+
204+
// skipSQL is true if SQL statements and expressions should not be built.
205+
// This is used during trigger function creation.
206+
skipSQL bool
207+
}
208+
209+
// basePLOptions returns a new plOptions struct with default values.
210+
func basePLOptions() plOptions {
211+
return plOptions{}
212+
}
213+
214+
// WithIsProcedure returns a new plOptions struct with the isProcedure flag set
215+
// to true.
216+
func (opts plOptions) WithIsProcedure() plOptions {
217+
opts.isProcedure = true
218+
return opts
219+
}
220+
221+
// SetIsProcedure returns a new plOptions struct with the isProcedure flag set
222+
// to the given value.
223+
func (opts plOptions) SetIsProcedure(isProcedure bool) plOptions {
224+
opts.isProcedure = isProcedure
225+
return opts
226+
}
227+
228+
// WithIsDoBlock returns a new plOptions struct with the isDoBlock flag set to
229+
// true.
230+
func (opts plOptions) WithIsDoBlock() plOptions {
231+
opts.isDoBlock = true
232+
return opts
233+
}
234+
235+
// WithIsTriggerFn returns a new plOptions struct with the isTriggerFn flag
236+
// set to true.
237+
func (opts plOptions) WithIsTriggerFn() plOptions {
238+
opts.isTriggerFn = true
239+
return opts
240+
}
241+
242+
// SetIsTriggerFn returns a new plOptions struct with the isTriggerFn flag set
243+
// to the given value.
244+
func (opts plOptions) SetIsTriggerFn(isTriggerFn bool) plOptions {
245+
opts.isTriggerFn = isTriggerFn
246+
return opts
247+
}
248+
249+
// SetSkipSQL returns a new plOptions struct with the skipSQL flag set to the
250+
// given value.
251+
func (opts plOptions) SetSkipSQL(skipSQL bool) plOptions {
252+
opts.skipSQL = skipSQL
253+
return opts
254+
}
255+
200256
// routineParam is similar to tree.RoutineParam but stores the resolved type.
201257
type routineParam struct {
202258
name ast.Variable
@@ -206,24 +262,21 @@ type routineParam struct {
206262

207263
func newPLpgSQLBuilder(
208264
ob *Builder,
265+
options plOptions,
209266
routineName, rootBlockLabel string,
210267
colRefs *opt.ColSet,
211268
routineParams []routineParam,
212269
returnType *types.T,
213-
isProcedure, isDoBlock, isTriggerFn, buildSQL bool,
214270
outScope *scope,
215271
) *plpgsqlBuilder {
216272
const initialBlocksCap = 2
217273
b := &plpgsqlBuilder{
218274
ob: ob,
275+
options: options,
219276
colRefs: colRefs,
220277
returnType: returnType,
221278
blocks: make([]plBlock, 0, initialBlocksCap),
222279
routineName: routineName,
223-
isProcedure: isProcedure,
224-
isDoBlock: isDoBlock,
225-
isTriggerFn: isTriggerFn,
226-
buildSQL: buildSQL,
227280
outScope: outScope,
228281
}
229282
// Build the initial block for the routine parameters, which are considered
@@ -320,7 +373,7 @@ func (b *plpgsqlBuilder) buildRootBlock(
320373
s, param.name, &tree.CastExpr{Expr: tree.DNull, Type: param.typ}, noIndirection,
321374
)
322375
}
323-
if b.isProcedure {
376+
if b.options.isProcedure {
324377
var tc transactionControlVisitor
325378
ast.Walk(&tc, astBlock)
326379
if tc.foundTxnControlStatement {
@@ -333,7 +386,7 @@ func (b *plpgsqlBuilder) buildRootBlock(
333386
"transaction control statements in nested routines",
334387
))
335388
}
336-
if b.isDoBlock {
389+
if b.options.isDoBlock {
337390
// Disallow transaction control statements in DO blocks for now.
338391
panic(unimplemented.NewWithIssue(138704,
339392
"transaction control statements in DO blocks",
@@ -521,7 +574,7 @@ func (b *plpgsqlBuilder) buildPLpgSQLStatements(stmts []ast.Statement, s *scope)
521574
expr = b.makeReturnForOutParams()
522575
} else if b.returnType.Family() == types.VoidFamily {
523576
if expr != nil {
524-
if b.isProcedure {
577+
if b.options.isProcedure {
525578
panic(returnWithVoidParameterProcedureErr)
526579
} else {
527580
panic(returnWithVoidParameterErr)
@@ -1006,7 +1059,7 @@ func (b *plpgsqlBuilder) buildPLpgSQLStatements(stmts []ast.Statement, s *scope)
10061059
if b.hasExceptionHandler() {
10071060
panic(txnControlWithExceptionErr)
10081061
}
1009-
if !b.isProcedure {
1062+
if !b.options.isProcedure {
10101063
panic(txnInUDFErr)
10111064
}
10121065
name := "_stmt_commit"
@@ -1425,7 +1478,7 @@ func (b *plpgsqlBuilder) handleIndirectionForAssign(
14251478

14261479
// We do not yet support qualifying a variable with a block label.
14271480
b.checkBlockLabelReference(elemName)
1428-
if !b.buildSQL {
1481+
if b.options.skipSQL {
14291482
// For lazy SQL evaluation, replace all expressions with NULL.
14301483
return memo.NullSingleton
14311484
}
@@ -2021,7 +2074,7 @@ func (b *plpgsqlBuilder) makeContinuation(conName string) continuation {
20212074
// continuation UDFs.
20222075
paramOrd := len(params)
20232076
col.setParamOrd(len(params))
2024-
if b.ob.insideFuncDef && b.isTriggerFn && paramOrd == triggerArgvColIdx {
2077+
if b.ob.insideFuncDef && b.options.isTriggerFn && paramOrd == triggerArgvColIdx {
20252078
// Due to #135311, we disallow references to the TG_ARGV param for now.
20262079
if !b.ob.evalCtx.SessionData().AllowCreateTriggerFunctionWithArgvReferences {
20272080
col.resolveErr = unimplementedArgvErr
@@ -2213,7 +2266,7 @@ func (b *plpgsqlBuilder) addBarrierIfVolatile(s *scope, expr opt.ScalarExpr) {
22132266
// buildSQLExpr type-checks and builds the given SQL expression into a
22142267
// ScalarExpr within the given scope.
22152268
func (b *plpgsqlBuilder) buildSQLExpr(expr ast.Expr, typ *types.T, s *scope) opt.ScalarExpr {
2216-
if !b.buildSQL {
2269+
if b.options.skipSQL {
22172270
// For lazy SQL evaluation, replace all expressions with NULL.
22182271
return memo.NullSingleton
22192272
}
@@ -2250,7 +2303,7 @@ func (b *plpgsqlBuilder) buildSQLExpr(expr ast.Expr, typ *types.T, s *scope) opt
22502303
// buildSQLStatement type-checks and builds the given SQL statement into a
22512304
// RelExpr within the given scope.
22522305
func (b *plpgsqlBuilder) buildSQLStatement(stmt tree.Statement, inScope *scope) (outScope *scope) {
2253-
if !b.buildSQL {
2306+
if b.options.skipSQL {
22542307
// For lazy SQL evaluation, replace all statements with a single row without
22552308
// any columns.
22562309
outScope = inScope.push()
@@ -2424,7 +2477,7 @@ func (b *plpgsqlBuilder) makeReturnForOutParams() tree.Expr {
24242477
exprs[i] = tree.DNull
24252478
}
24262479
}
2427-
if len(exprs) == 1 && !b.isProcedure {
2480+
if len(exprs) == 1 && !b.options.isProcedure {
24282481
// For procedures, even a single column is wrapped in a tuple.
24292482
return exprs[0]
24302483
}

pkg/sql/opt/optbuilder/routine.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -445,9 +445,9 @@ func (b *Builder) buildRoutine(
445445
}
446446
var expr memo.RelExpr
447447
var physProps *physical.Required
448+
options := basePLOptions().SetIsProcedure(isProc)
448449
plBuilder := newPLpgSQLBuilder(
449-
b, def.Name, stmt.AST.Label, colRefs, routineParams, f.ResolvedType(),
450-
isProc, false /* isDoBlock */, false /* isTriggerFn */, true /* buildSQL */, outScope,
450+
b, options, def.Name, stmt.AST.Label, colRefs, routineParams, f.ResolvedType(), outScope,
451451
)
452452
stmtScope := plBuilder.buildRootBlock(stmt.AST, bodyScope, routineParams)
453453
rTyp := b.finalizeRoutineReturnType(f, stmtScope, inScope, oldInsideDataSource)
@@ -857,10 +857,10 @@ func (b *Builder) buildPLpgSQLDoBody(
857857
do *plpgsqltree.DoBlock,
858858
) (body memo.RelExpr, bodyProps *physical.Required) {
859859
// Build an expression for each statement in the function body.
860+
options := basePLOptions().WithIsProcedure().WithIsDoBlock()
860861
plBuilder := newPLpgSQLBuilder(
861-
b, doBlockRoutineName, do.Block.Label, nil /* colRefs */, nil /* routineParams */, types.Void,
862-
true /* isProc */, true, /* isDoBlock */
863-
false /* isTriggerFn */, true /* buildSQL */, nil, /* outScope */
862+
b, options, doBlockRoutineName, do.Block.Label, nil, /* colRefs */
863+
nil /* routineParams */, types.Void, nil, /* outScope */
864864
)
865865
// Allocate a fresh scope, since DO blocks do not take parameters or reference
866866
// variables or columns from the calling context.

pkg/sql/opt/optbuilder/trigger.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -838,9 +838,8 @@ func (b *Builder) buildTriggerFunction(
838838
panic(err)
839839
}
840840
plBuilder := newPLpgSQLBuilder(
841-
b, resolvedDef.Name, stmt.AST.Label, nil /* colRefs */, params, tableTyp,
842-
false /* isProc */, false, /* isDoBlock */
843-
true /* isTriggerFn */, true /* buildSQL */, nil, /* outScope */
841+
b, basePLOptions().WithIsTriggerFn(), resolvedDef.Name, stmt.AST.Label, nil, /* colRefs */
842+
params, tableTyp, nil, /* outScope */
844843
)
845844
stmtScope := plBuilder.buildRootBlock(stmt.AST, triggerFuncScope, params)
846845
udfDef.Body = []memo.RelExpr{stmtScope.expr}

0 commit comments

Comments
 (0)