v6-0008-Extract-transformColumnRefInternal.patch
text/x-patch
Filename: v6-0008-Extract-transformColumnRefInternal.patch
Type: text/x-patch
Part: 7
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 v6-0008
Subject: Extract transformColumnRefInternal()
| File | + | − |
|---|---|---|
| src/backend/parser/parse_expr.c | 132 | 106 |
From face4d14fb335204d024456e63b6dca7bdc1f97d Mon Sep 17 00:00:00 2001
From: Nikita Glukhov <n.gluhov@postgrespro.ru>
Date: Sun, 2 Apr 2023 00:13:38 +0300
Subject: [PATCH v6 08/11] Extract transformColumnRefInternal()
---
src/backend/parser/parse_expr.c | 238 ++++++++++++++++++--------------
1 file changed, 132 insertions(+), 106 deletions(-)
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 3ed01864f66..b82d25c40a4 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -567,116 +567,31 @@ transformIndirection(ParseState *pstate, A_Indirection *ind,
return result;
}
-/*
- * Transform a ColumnRef.
- *
- * If you find yourself changing this code, see also ExpandColumnRefStar.
- */
-static Node *
-transformColumnRef(ParseState *pstate, ColumnRef *cref)
+typedef struct ColRefError
{
- Node *node = NULL;
- char *nspname = NULL;
- char *relname = NULL;
- char *colname = NULL;
- ParseNamespaceItem *nsitem;
- int levels_up;
enum
{
CRERR_NO_COLUMN,
CRERR_NO_RTE,
CRERR_WRONG_DB,
CRERR_TOO_MANY
- } crerr = CRERR_NO_COLUMN;
- const char *err;
+ } code;
+ char *nspname;
+ char *relname;
+ char *colname;
+} ColRefError;
- /*
- * Check to see if the column reference is in an invalid place within the
- * query. We allow column references in most places, except in default
- * expressions and partition bound expressions.
- */
- err = NULL;
- switch (pstate->p_expr_kind)
- {
- case EXPR_KIND_NONE:
- Assert(false); /* can't happen */
- break;
- case EXPR_KIND_OTHER:
- case EXPR_KIND_JOIN_ON:
- case EXPR_KIND_JOIN_USING:
- case EXPR_KIND_FROM_SUBSELECT:
- case EXPR_KIND_FROM_FUNCTION:
- case EXPR_KIND_WHERE:
- case EXPR_KIND_POLICY:
- case EXPR_KIND_HAVING:
- case EXPR_KIND_FILTER:
- case EXPR_KIND_WINDOW_PARTITION:
- case EXPR_KIND_WINDOW_ORDER:
- case EXPR_KIND_WINDOW_FRAME_RANGE:
- case EXPR_KIND_WINDOW_FRAME_ROWS:
- case EXPR_KIND_WINDOW_FRAME_GROUPS:
- case EXPR_KIND_SELECT_TARGET:
- case EXPR_KIND_INSERT_TARGET:
- case EXPR_KIND_UPDATE_SOURCE:
- case EXPR_KIND_UPDATE_TARGET:
- case EXPR_KIND_MERGE_WHEN:
- case EXPR_KIND_GROUP_BY:
- case EXPR_KIND_ORDER_BY:
- case EXPR_KIND_DISTINCT_ON:
- case EXPR_KIND_LIMIT:
- case EXPR_KIND_OFFSET:
- case EXPR_KIND_RETURNING:
- case EXPR_KIND_MERGE_RETURNING:
- case EXPR_KIND_VALUES:
- case EXPR_KIND_VALUES_SINGLE:
- case EXPR_KIND_CHECK_CONSTRAINT:
- case EXPR_KIND_DOMAIN_CHECK:
- case EXPR_KIND_FUNCTION_DEFAULT:
- case EXPR_KIND_INDEX_EXPRESSION:
- case EXPR_KIND_INDEX_PREDICATE:
- case EXPR_KIND_STATS_EXPRESSION:
- case EXPR_KIND_ALTER_COL_TRANSFORM:
- case EXPR_KIND_EXECUTE_PARAMETER:
- case EXPR_KIND_TRIGGER_WHEN:
- case EXPR_KIND_PARTITION_EXPRESSION:
- case EXPR_KIND_CALL_ARGUMENT:
- case EXPR_KIND_COPY_WHERE:
- case EXPR_KIND_GENERATED_COLUMN:
- case EXPR_KIND_CYCLE_MARK:
- /* okay */
- break;
-
- case EXPR_KIND_COLUMN_DEFAULT:
- err = _("cannot use column reference in DEFAULT expression");
- break;
- case EXPR_KIND_PARTITION_BOUND:
- err = _("cannot use column reference in partition bound expression");
- break;
-
- /*
- * There is intentionally no default: case here, so that the
- * compiler will warn if we add a new ParseExprKind without
- * extending this switch. If we do see an unrecognized value at
- * runtime, the behavior will be the same as for EXPR_KIND_OTHER,
- * which is sane anyway.
- */
- }
- if (err)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg_internal("%s", err),
- parser_errposition(pstate, cref->location)));
-
- /*
- * Give the PreParseColumnRefHook, if any, first shot. If it returns
- * non-null then that's all, folks.
- */
- if (pstate->p_pre_columnref_hook != NULL)
- {
- node = pstate->p_pre_columnref_hook(pstate, cref);
- if (node != NULL)
- return node;
- }
+static Node *
+transformColumnRefInternal(ParseState *pstate, ColumnRef *cref, int nfields,
+ ColRefError *err)
+{
+ ParseNamespaceItem *nsitem;
+ Node *node = NULL;
+ char *nspname = NULL;
+ char *relname = NULL;
+ char *colname = NULL;
+ int crerr = CRERR_NO_COLUMN;
+ int levels_up;
/*----------
* The allowed syntaxes are:
@@ -701,7 +616,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
* database name; we check it here and then discard it.
*----------
*/
- switch (list_length(cref->fields))
+ switch (nfields)
{
case 1:
{
@@ -890,6 +805,117 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
break;
}
+ err->code = crerr;
+ err->nspname = nspname;
+ err->relname = relname;
+ err->colname = colname;
+
+ return node;
+}
+
+/*
+ * Transform a ColumnRef.
+ *
+ * If you find yourself changing this code, see also ExpandColumnRefStar.
+ */
+static Node *
+transformColumnRef(ParseState *pstate, ColumnRef *cref)
+{
+ Node *node = NULL;
+ ColRefError crerr;
+ const char *err;
+
+ /*
+ * Check to see if the column reference is in an invalid place within the
+ * query. We allow column references in most places, except in default
+ * expressions and partition bound expressions.
+ */
+ err = NULL;
+ switch (pstate->p_expr_kind)
+ {
+ case EXPR_KIND_NONE:
+ Assert(false); /* can't happen */
+ break;
+ case EXPR_KIND_OTHER:
+ case EXPR_KIND_JOIN_ON:
+ case EXPR_KIND_JOIN_USING:
+ case EXPR_KIND_FROM_SUBSELECT:
+ case EXPR_KIND_FROM_FUNCTION:
+ case EXPR_KIND_WHERE:
+ case EXPR_KIND_POLICY:
+ case EXPR_KIND_HAVING:
+ case EXPR_KIND_FILTER:
+ case EXPR_KIND_WINDOW_PARTITION:
+ case EXPR_KIND_WINDOW_ORDER:
+ case EXPR_KIND_WINDOW_FRAME_RANGE:
+ case EXPR_KIND_WINDOW_FRAME_ROWS:
+ case EXPR_KIND_WINDOW_FRAME_GROUPS:
+ case EXPR_KIND_SELECT_TARGET:
+ case EXPR_KIND_INSERT_TARGET:
+ case EXPR_KIND_UPDATE_SOURCE:
+ case EXPR_KIND_UPDATE_TARGET:
+ case EXPR_KIND_MERGE_WHEN:
+ case EXPR_KIND_GROUP_BY:
+ case EXPR_KIND_ORDER_BY:
+ case EXPR_KIND_DISTINCT_ON:
+ case EXPR_KIND_LIMIT:
+ case EXPR_KIND_OFFSET:
+ case EXPR_KIND_RETURNING:
+ case EXPR_KIND_MERGE_RETURNING:
+ case EXPR_KIND_VALUES:
+ case EXPR_KIND_VALUES_SINGLE:
+ case EXPR_KIND_CHECK_CONSTRAINT:
+ case EXPR_KIND_DOMAIN_CHECK:
+ case EXPR_KIND_FUNCTION_DEFAULT:
+ case EXPR_KIND_INDEX_EXPRESSION:
+ case EXPR_KIND_INDEX_PREDICATE:
+ case EXPR_KIND_STATS_EXPRESSION:
+ case EXPR_KIND_ALTER_COL_TRANSFORM:
+ case EXPR_KIND_EXECUTE_PARAMETER:
+ case EXPR_KIND_TRIGGER_WHEN:
+ case EXPR_KIND_PARTITION_EXPRESSION:
+ case EXPR_KIND_CALL_ARGUMENT:
+ case EXPR_KIND_COPY_WHERE:
+ case EXPR_KIND_GENERATED_COLUMN:
+ case EXPR_KIND_CYCLE_MARK:
+ /* okay */
+ break;
+
+ case EXPR_KIND_COLUMN_DEFAULT:
+ err = _("cannot use column reference in DEFAULT expression");
+ break;
+ case EXPR_KIND_PARTITION_BOUND:
+ err = _("cannot use column reference in partition bound expression");
+ break;
+
+ /*
+ * There is intentionally no default: case here, so that the
+ * compiler will warn if we add a new ParseExprKind without
+ * extending this switch. If we do see an unrecognized value at
+ * runtime, the behavior will be the same as for EXPR_KIND_OTHER,
+ * which is sane anyway.
+ */
+ }
+ if (err)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg_internal("%s", err),
+ parser_errposition(pstate, cref->location)));
+
+ /*
+ * Give the PreParseColumnRefHook, if any, first shot. If it returns
+ * non-null then that's all, folks.
+ */
+ if (pstate->p_pre_columnref_hook != NULL)
+ {
+ node = pstate->p_pre_columnref_hook(pstate, cref);
+ if (node != NULL)
+ return node;
+ }
+
+ node = transformColumnRefInternal(pstate, cref, list_length(cref->fields),
+ &crerr);
+
/*
* Now give the PostParseColumnRefHook, if any, a chance. We pass the
* translation-so-far so that it can throw an error if it wishes in the
@@ -919,13 +945,13 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
*/
if (node == NULL)
{
- switch (crerr)
+ switch (crerr.code)
{
case CRERR_NO_COLUMN:
- errorMissingColumn(pstate, relname, colname, cref->location);
+ errorMissingColumn(pstate, crerr.relname, crerr.colname, cref->location);
break;
case CRERR_NO_RTE:
- errorMissingRTE(pstate, makeRangeVar(nspname, relname,
+ errorMissingRTE(pstate, makeRangeVar(crerr.nspname, crerr.relname,
cref->location));
break;
case CRERR_WRONG_DB:
--
2.25.1