v20250209-0019-expression-with-session-variables-can-be-inlined.patch
text/x-patch
Filename: v20250209-0019-expression-with-session-variables-can-be-inlined.patch
Type: text/x-patch
Part: 3
Message:
Re: Re: proposal: schema variables
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v20250209-0019
Subject: expression with session variables can be inlined
| File | + | − |
|---|---|---|
| src/backend/optimizer/util/clauses.c | 27 | 10 |
| src/test/regress/expected/session_variables.out | 3 | 4 |
From 3dbd2c1c72b46cef5f7963fdda7e0c37eaf99740 Mon Sep 17 00:00:00 2001
From: "okbob@github.com" <okbob@github.com>
Date: Sat, 20 Jan 2024 20:35:38 +0100
Subject: [PATCH 19/22] expression with session variables can be inlined
There is not an reason why session variables should to block inlining.
(of SQL functions). I can imagine some use cases like wrapping, and
inlining significantly reduces an overhead of SQL functions.
---
src/backend/optimizer/util/clauses.c | 37 ++++++++++++++-----
.../regress/expected/session_variables.out | 7 ++--
2 files changed, 30 insertions(+), 14 deletions(-)
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 175390c6c28..0eb52fa2081 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -4744,8 +4744,7 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid,
querytree->limitOffset ||
querytree->limitCount ||
querytree->setOperations ||
- (list_length(querytree->targetList) != 1) ||
- querytree->hasSessionVariables)
+ (list_length(querytree->targetList) != 1))
goto fail;
/* If the function result is composite, resolve it */
@@ -4949,21 +4948,39 @@ substitute_actual_parameters_mutator(Node *node,
{
if (node == NULL)
return NULL;
+
+
+ /*
+ * SQL functions can contain two different kind of params. The nodes with
+ * paramkind PARAM_EXTERN are related to function's arguments (and should
+ * be replaced in this step), because this is how we apply the function's
+ * arguments for an expression.
+ *
+ * The nodes with paramkind PARAM_VARIABLE are related to usage of session
+ * variables. The values of session variables are not passed to expression
+ * by expression arguments, so it should not be replaced here by
+ * function's arguments.
+ */
if (IsA(node, Param))
{
Param *param = (Param *) node;
- if (param->paramkind != PARAM_EXTERN)
+ if (param->paramkind != PARAM_EXTERN &&
+ param->paramkind != PARAM_VARIABLE)
elog(ERROR, "unexpected paramkind: %d", (int) param->paramkind);
- if (param->paramid <= 0 || param->paramid > context->nargs)
- elog(ERROR, "invalid paramid: %d", param->paramid);
- /* Count usage of parameter */
- context->usecounts[param->paramid - 1]++;
+ if (param->paramkind == PARAM_EXTERN)
+ {
+ if (param->paramid <= 0 || param->paramid > context->nargs)
+ elog(ERROR, "invalid paramid: %d", param->paramid);
- /* Select the appropriate actual arg and replace the Param with it */
- /* We don't need to copy at this time (it'll get done later) */
- return list_nth(context->args, param->paramid - 1);
+ /* Count usage of parameter */
+ context->usecounts[param->paramid - 1]++;
+
+ /* Select the appropriate actual arg and replace the Param with it */
+ /* We don't need to copy at this time (it'll get done later) */
+ return list_nth(context->args, param->paramid - 1);
+ }
}
return expression_tree_mutator(node, substitute_actual_parameters_mutator, context);
}
diff --git a/src/test/regress/expected/session_variables.out b/src/test/regress/expected/session_variables.out
index 708630ae2ae..7638e1a4771 100644
--- a/src/test/regress/expected/session_variables.out
+++ b/src/test/regress/expected/session_variables.out
@@ -480,7 +480,6 @@ SELECT var1;
ERROR: permission denied for session variable var1
SELECT sqlfx(20);
ERROR: permission denied for session variable var1
-CONTEXT: SQL function "sqlfx" statement 1
SELECT plpgsqlfx(20);
ERROR: permission denied for session variable var1
CONTEXT: PL/pgSQL function plpgsqlfx(integer) line 1 at RETURN
@@ -587,10 +586,10 @@ SELECT sqlfx1(sqlfx2('Hello'));
-- inlining is blocked
EXPLAIN (COSTS OFF, VERBOSE) SELECT sqlfx1(sqlfx2('Hello'));
- QUERY PLAN
-------------------------------------------------------
+ QUERY PLAN
+-----------------------------------------------------------------------------
Result
- Output: sqlfx1(sqlfx2('Hello'::character varying))
+ Output: ((var1 || ', '::text) || ((var2 || ', '::text) || 'Hello'::text))
(2 rows)
DROP FUNCTION sqlfx1(varchar);
--
2.48.1