Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 07a3af0

Browse files
committed
Fix parsetree representation of XMLTABLE(XMLNAMESPACES(DEFAULT ...)).
The original coding for XMLTABLE thought it could represent a default namespace by a T_String Value node with a null string pointer. That's not okay, though; in particular outfuncs.c/readfuncs.c are not on board with such a representation, meaning you'll get a null pointer crash if you try to store a view or rule containing this construct. To fix, change the parsetree representation so that we have a NULL list element, instead of a bogus Value node. This isn't really a functional limitation since default XML namespaces aren't yet implemented in the executor; you'd just get "DEFAULT namespace is not supported" anyway. But crashes are not nice, so back-patch to v10 where this syntax was added. Ordinarily we'd consider a parsetree representation change to be un-backpatchable; but since existing releases would crash on the way to storing such constructs, there can't be any existing views/rules to be incompatible with. Per report from Andrey Lepikhov. Discussion: https://postgr.es/m/[email protected]
1 parent 789ba50 commit 07a3af0

File tree

5 files changed

+23
-15
lines changed

5 files changed

+23
-15
lines changed

src/backend/executor/nodeTableFuncscan.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,9 @@ tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc)
364364
forboth(lc1, tstate->ns_uris, lc2, tstate->ns_names)
365365
{
366366
ExprState *expr = (ExprState *) lfirst(lc1);
367-
char *ns_name = strVal(lfirst(lc2));
367+
Value *ns_node = (Value *) lfirst(lc2);
368368
char *ns_uri;
369+
char *ns_name;
369370

370371
value = ExecEvalExpr((ExprState *) expr, econtext, &isnull);
371372
if (isnull)
@@ -374,6 +375,9 @@ tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc)
374375
errmsg("namespace URI must not be null")));
375376
ns_uri = TextDatumGetCString(value);
376377

378+
/* DEFAULT is passed down to SetNamespace as NULL */
379+
ns_name = ns_node ? strVal(ns_node) : NULL;
380+
377381
routine->SetNamespace(tstate, ns_name, ns_uri);
378382
}
379383

src/backend/parser/parse_clause.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -779,7 +779,7 @@ transformRangeTableFunc(ParseState *pstate, RangeTableFunc *rtf)
779779
/* undef ordinality column number */
780780
tf->ordinalitycol = -1;
781781

782-
782+
/* Process column specs */
783783
names = palloc(sizeof(char *) * list_length(rtf->columns));
784784

785785
colno = 0;
@@ -900,15 +900,15 @@ transformRangeTableFunc(ParseState *pstate, RangeTableFunc *rtf)
900900
{
901901
foreach(lc2, ns_names)
902902
{
903-
char *name = strVal(lfirst(lc2));
903+
Value *ns_node = (Value *) lfirst(lc2);
904904

905-
if (name == NULL)
905+
if (ns_node == NULL)
906906
continue;
907-
if (strcmp(name, r->name) == 0)
907+
if (strcmp(strVal(ns_node), r->name) == 0)
908908
ereport(ERROR,
909909
(errcode(ERRCODE_SYNTAX_ERROR),
910910
errmsg("namespace name \"%s\" is not unique",
911-
name),
911+
r->name),
912912
parser_errposition(pstate, r->location)));
913913
}
914914
}
@@ -922,8 +922,9 @@ transformRangeTableFunc(ParseState *pstate, RangeTableFunc *rtf)
922922
default_ns_seen = true;
923923
}
924924

925-
/* Note the string may be NULL */
926-
ns_names = lappend(ns_names, makeString(r->name));
925+
/* We represent DEFAULT by a null pointer */
926+
ns_names = lappend(ns_names,
927+
r->name ? makeString(r->name) : NULL);
927928
}
928929

929930
tf->ns_uris = ns_uris;

src/backend/utils/adt/ruleutils.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9739,17 +9739,17 @@ get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
97399739
forboth(lc1, tf->ns_uris, lc2, tf->ns_names)
97409740
{
97419741
Node *expr = (Node *) lfirst(lc1);
9742-
char *name = strVal(lfirst(lc2));
9742+
Value *ns_node = (Value *) lfirst(lc2);
97439743

97449744
if (!first)
97459745
appendStringInfoString(buf, ", ");
97469746
else
97479747
first = false;
97489748

9749-
if (name != NULL)
9749+
if (ns_node != NULL)
97509750
{
97519751
get_rule_expr(expr, context, showimplicit);
9752-
appendStringInfo(buf, " AS %s", name);
9752+
appendStringInfo(buf, " AS %s", strVal(ns_node));
97539753
}
97549754
else
97559755
{

src/include/nodes/execnodes.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,8 +1573,8 @@ typedef struct TableFuncScanState
15731573
ExprState *rowexpr; /* state for row-generating expression */
15741574
List *colexprs; /* state for column-generating expression */
15751575
List *coldefexprs; /* state for column default expressions */
1576-
List *ns_names; /* list of str nodes with namespace names */
1577-
List *ns_uris; /* list of states of namespace uri exprs */
1576+
List *ns_names; /* same as TableFunc.ns_names */
1577+
List *ns_uris; /* list of states of namespace URI exprs */
15781578
Bitmapset *notnulls; /* nullability flag for each output column */
15791579
void *opaque; /* table builder private space */
15801580
const struct TableFuncRoutine *routine; /* table builder methods */

src/include/nodes/primnodes.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,15 @@ typedef struct RangeVar
7575

7676
/*
7777
* TableFunc - node for a table function, such as XMLTABLE.
78+
*
79+
* Entries in the ns_names list are either string Value nodes containing
80+
* literal namespace names, or NULL pointers to represent DEFAULT.
7881
*/
7982
typedef struct TableFunc
8083
{
8184
NodeTag type;
82-
List *ns_uris; /* list of namespace uri */
83-
List *ns_names; /* list of namespace names */
85+
List *ns_uris; /* list of namespace URI expressions */
86+
List *ns_names; /* list of namespace names or NULL */
8487
Node *docexpr; /* input document expression */
8588
Node *rowexpr; /* row filter expression */
8689
List *colnames; /* column names (list of String) */

0 commit comments

Comments
 (0)