@@ -156,7 +156,8 @@ import (
156156// not follow here, although they may be good routes for optimization in the
157157// future.
158158type 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.
201257type routineParam struct {
202258 name ast.Variable
@@ -206,24 +262,21 @@ type routineParam struct {
206262
207263func 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.
22152268func (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.
22522305func (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 }
0 commit comments