aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/gram.y1
-rw-r--r--src/backend/parser/parse_expr.c19
-rw-r--r--src/include/nodes/primnodes.h3
3 files changed, 20 insertions, 3 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index ad98b364f13..456887665a0 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -13341,6 +13341,7 @@ makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args,
x->args = args;
/* xmloption, if relevant, must be filled in by caller */
/* type and typmod will be filled in during parse analysis */
+ x->type = InvalidOid; /* marks the node as not analyzed */
x->location = location;
return (Node *) x;
}
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index e9267c56fc5..3b1b6d0139c 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -92,6 +92,8 @@ static Expr *make_distinct_op(ParseState *pstate, List *opname,
* function argument to the required type (via coerce_type())
* can apply transformExpr to an already-transformed subexpression.
* An example here is "SELECT count(*) + 1.0 FROM table".
+ * 3. CREATE TABLE t1 (LIKE t2 INCLUDING INDEXES) can pass in
+ * already-transformed index expressions.
* While it might be possible to eliminate these cases, the path of
* least resistance so far has been to ensure that transformExpr() does
* no damage if applied to an already-transformed tree. This is pretty
@@ -1775,11 +1777,17 @@ transformArrayExpr(ParseState *pstate, A_ArrayExpr *a,
static Node *
transformRowExpr(ParseState *pstate, RowExpr *r)
{
- RowExpr *newr = makeNode(RowExpr);
+ RowExpr *newr;
char fname[16];
int fnum;
ListCell *lc;
+ /* If we already transformed this node, do nothing */
+ if (OidIsValid(r->row_typeid))
+ return (Node *) r;
+
+ newr = makeNode(RowExpr);
+
/* Transform the field expressions */
newr->args = transformExpressionList(pstate, r->args, pstate->p_expr_kind);
@@ -1880,16 +1888,23 @@ transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m)
static Node *
transformXmlExpr(ParseState *pstate, XmlExpr *x)
{
- XmlExpr *newx = makeNode(XmlExpr);
+ XmlExpr *newx;
ListCell *lc;
int i;
+ /* If we already transformed this node, do nothing */
+ if (OidIsValid(x->type))
+ return (Node *) x;
+
+ newx = makeNode(XmlExpr);
newx->op = x->op;
if (x->name)
newx->name = map_sql_identifier_to_xml_name(x->name, false, false);
else
newx->name = NULL;
newx->xmloption = x->xmloption;
+ newx->type = XMLOID; /* this just marks the node as transformed */
+ newx->typmod = -1;
newx->location = x->location;
/*
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index a233fce003e..5eb5f8b4cd7 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -958,7 +958,8 @@ typedef struct MinMaxExpr
*
* Note: result type/typmod/collation are not stored, but can be deduced
* from the XmlExprOp. The type/typmod fields are just used for display
- * purposes, and are NOT the true result type of the node.
+ * purposes, and are NOT necessarily the true result type of the node.
+ * (We also use type == InvalidOid to mark a not-yet-parse-analyzed XmlExpr.)
*/
typedef enum XmlExprOp
{