diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 24099beb0d..40d5de0a32 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -72,8 +72,7 @@ static Node *transformXmlSerialize(ParseState *pstate, XmlSerialize *xs); static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b); static Node *transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr); static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref); -static Node *transformWholeRowRef(ParseState *pstate, bool for_func_call, - ParseNamespaceItem *nsitem, +static Node *transformWholeRowRef(ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, int location); static Node *transformIndirection(ParseState *pstate, A_Indirection *ind); static Node *transformTypeCast(ParseState *pstate, TypeCast *tc); @@ -513,7 +512,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) char *nspname = NULL; char *relname = NULL; char *colname = NULL; - ParseNamespaceItem *nsitem; + ParseNamespaceItem *nsitem = NULL; int levels_up; enum { @@ -709,8 +708,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) cref->location, &levels_up); if (nsitem) - node = transformWholeRowRef(pstate, false, nsitem, - levels_up, cref->location); + node = transformWholeRowRef(pstate, nsitem, levels_up, + cref->location); } break; } @@ -734,8 +733,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) /* Whole-row reference? */ if (IsA(field2, A_Star)) { - node = transformWholeRowRef(pstate, false, nsitem, - levels_up, cref->location); + node = transformWholeRowRef(pstate, nsitem, levels_up, + cref->location); break; } @@ -747,8 +746,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) if (node == NULL) { /* Try it as a function call on the whole row */ - node = transformWholeRowRef(pstate, true, nsitem, - levels_up, cref->location); + node = transformWholeRowRef(pstate, nsitem, levels_up, + cref->location); node = ParseFuncOrColumn(pstate, list_make1(makeString(colname)), list_make1(node), @@ -781,8 +780,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) /* Whole-row reference? */ if (IsA(field3, A_Star)) { - node = transformWholeRowRef(pstate, false, nsitem, - levels_up, cref->location); + node = transformWholeRowRef(pstate, nsitem, levels_up, + cref->location); break; } @@ -794,8 +793,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) if (node == NULL) { /* Try it as a function call on the whole row */ - node = transformWholeRowRef(pstate, true, nsitem, - levels_up, cref->location); + node = transformWholeRowRef(pstate, nsitem, levels_up, + cref->location); node = ParseFuncOrColumn(pstate, list_make1(makeString(colname)), list_make1(node), @@ -840,8 +839,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) /* Whole-row reference? */ if (IsA(field4, A_Star)) { - node = transformWholeRowRef(pstate, false, nsitem, - levels_up, cref->location); + node = transformWholeRowRef(pstate, nsitem, levels_up, + cref->location); break; } @@ -853,8 +852,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) if (node == NULL) { /* Try it as a function call on the whole row */ - node = transformWholeRowRef(pstate, true, nsitem, - levels_up, cref->location); + node = transformWholeRowRef(pstate, nsitem, levels_up, + cref->location); node = ParseFuncOrColumn(pstate, list_make1(makeString(colname)), list_make1(node), @@ -870,6 +869,16 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) break; } + if (pstate->p_expr_kind == EXPR_KIND_RPR_DEFINE && node != NULL) + { + if (IsA(llast(cref->fields), A_Star) || (list_length(cref->fields) == 1 && nsitem != NULL)) + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("whole-row reference is not allowed in DEFINE clause"), + errhint("A DEFINE condition may reference individual columns only."), + parser_errposition(pstate, cref->location)); + } + /* * 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 @@ -2792,29 +2801,11 @@ transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr) /* * Construct a whole-row reference to represent the notation "relation.*". - * - * for_func_call is true when transformColumnRef is building the reference - * speculatively, to retry a name that did not resolve as a column as a - * function call on the composite value. The query does not contain a - * whole-row reference in that case, so restrictions on writing one must not - * fire; whatever the retry resolves to is diagnosed by the caller. */ static Node * -transformWholeRowRef(ParseState *pstate, bool for_func_call, - ParseNamespaceItem *nsitem, int sublevels_up, - int location) +transformWholeRowRef(ParseState *pstate, ParseNamespaceItem *nsitem, + int sublevels_up, int location) { - /* - * A DEFINE clause cannot use a whole-row reference: ISO/IEC 19075-5 6.5 - * limits the range variables in scope to the row pattern variables. - */ - if (pstate->p_expr_kind == EXPR_KIND_RPR_DEFINE && !for_func_call) - ereport(ERROR, - errcode(ERRCODE_SYNTAX_ERROR), - errmsg("whole-row reference is not allowed in DEFINE clause"), - errhint("A DEFINE condition may reference individual columns only."), - parser_errposition(pstate, location)); - /* * Build the appropriate referencing node. Normally this can be a * whole-row Var, but if the nsitem is a JOIN USING alias then it contains