From 98f706706d723d53b0d43bba2ce4f58e9be4e4ad Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 25 Sep 2000 18:14:55 +0000 Subject: [PATCH] Use variable aliases, if supplied, rather than real column names in complaints about ungrouped variables. This is for consistency with behavior elsewhere, notably the fact that the relname is reported as an alias in these same complaints. Also, it'll work with subselect- in-FROM where old code didn't. --- src/backend/nodes/print.c | 10 +++++--- src/backend/optimizer/util/clauses.c | 7 ++---- src/backend/parser/parse_agg.c | 5 +--- src/backend/parser/parse_relation.c | 37 ++++++++++++++++++++++++++++ src/backend/utils/adt/ruleutils.c | 31 ----------------------- src/include/parser/parsetree.h | 18 ++++++++------ 6 files changed, 56 insertions(+), 52 deletions(-) diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c index d2ac348751..f7e7a99963 100644 --- a/src/backend/nodes/print.c +++ b/src/backend/nodes/print.c @@ -172,11 +172,13 @@ print_expr(Node *expr, List *rtable) break; default: { - RangeTblEntry *rt; + RangeTblEntry *rte; - rt = rt_fetch(var->varno, rtable); - relname = rt->eref->relname; - attname = get_attname(rt->relid, var->varattno); + Assert(var->varno > 0 && + (int) var->varno <= length(rtable)); + rte = rt_fetch(var->varno, rtable); + relname = rte->eref->relname; + attname = get_rte_attribute_name(rte, var->varattno); } break; } diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index dd21a6bfbb..88c821b7a6 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -584,12 +584,9 @@ check_subplans_for_ungrouped_vars_walker(Node *node, char *attname; Assert(var->varno > 0 && - var->varno <= length(context->rtable)); + (int) var->varno <= length(context->rtable)); rte = rt_fetch(var->varno, context->rtable); - attname = get_attname(rte->relid, var->varattno); - if (!attname) - elog(ERROR, "cache lookup of attribute %d in relation %u failed", - var->varattno, rte->relid); + attname = get_rte_attribute_name(rte, var->varattno); elog(ERROR, "Sub-SELECT uses un-GROUPed attribute %s.%s from outer query", rte->eref->relname, attname); } diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index 66821bf169..67da122cdc 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -113,10 +113,7 @@ check_ungrouped_columns_walker(Node *node, Assert(var->varno > 0 && (int) var->varno <= length(context->pstate->p_rtable)); rte = rt_fetch(var->varno, context->pstate->p_rtable); - attname = get_attname(rte->relid, var->varattno); - if (!attname) - elog(ERROR, "cache lookup of attribute %d in relation %u failed", - var->varattno, rte->relid); + attname = get_rte_attribute_name(rte, var->varattno); elog(ERROR, "Attribute %s.%s must be GROUPed or used in an aggregate function", rte->eref->relname, attname); } diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 138f854f5b..4038c9064e 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -713,6 +713,43 @@ expandNamesVars(ParseState *pstate, List *names, List *vars) return te_list; } +/* ---------- + * get_rte_attribute_name + * Get an attribute name from a RangeTblEntry + * + * This is unlike get_attname() because we use aliases if available. + * In particular, it will work on an RTE for a subselect, whereas + * get_attname() only works on real relations. + * ---------- + */ +char * +get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum) +{ + char *attname; + + /* + * If there is an alias, use it + */ + if (attnum > 0 && attnum <= length(rte->eref->attrs)) + return strVal(nth(attnum-1, rte->eref->attrs)); + /* + * Can get here for a system attribute (which never has an alias), + * or if alias name list is too short (which probably can't happen + * anymore). Neither of these cases is valid for a subselect RTE. + */ + if (rte->relid == InvalidOid) + elog(ERROR, "Invalid attnum %d for rangetable entry %s", + attnum, rte->eref->relname); + /* + * Use the real name of the table's column + */ + attname = get_attname(rte->relid, attnum); + if (attname == NULL) + elog(ERROR, "cache lookup of attribute %d in relation %u failed", + attnum, rte->relid); + return attname; +} + /* * given relation and att name, return id of variable * diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index a73f0ec890..9a41967d72 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -110,7 +110,6 @@ static bool tleIsArrayAssign(TargetEntry *tle); static char *quote_identifier(char *ident); static char *get_relation_name(Oid relid); static char *get_relid_attribute_name(Oid relid, AttrNumber attnum); -static char *get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum); #define only_marker(rte) ((rte)->inh ? "" : "ONLY ") @@ -2020,33 +2019,3 @@ get_relid_attribute_name(Oid relid, AttrNumber attnum) attnum, relid); return attname; } - -/* ---------- - * get_rte_attribute_name - * Get an attribute name from a RangeTblEntry - * - * This is unlike get_relid_attribute_name() because we use aliases if - * available. - * ---------- - */ -static char * -get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum) -{ - /* - * If there is an alias, use it - */ - if (attnum > 0 && attnum <= length(rte->eref->attrs)) - return strVal(nth(attnum-1, rte->eref->attrs)); - /* - * Can get here for a system attribute (which never has an alias), - * or if alias name list is too short (which probably can't happen - * anymore). Neither of these cases is valid for a subselect RTE. - */ - if (rte->relid == InvalidOid) - elog(ERROR, "Invalid attnum %d for rangetable entry %s", - attnum, rte->eref->relname); - /* - * Use the real name of the table's column - */ - return get_relid_attribute_name(rte->relid, attnum); -} diff --git a/src/include/parser/parsetree.h b/src/include/parser/parsetree.h index aa087ba5ce..10c7f8c9cf 100644 --- a/src/include/parser/parsetree.h +++ b/src/include/parser/parsetree.h @@ -16,12 +16,8 @@ #define PARSETREE_H #include "nodes/parsenodes.h" -#include "nodes/pg_list.h" +#include "nodes/pg_list.h" /* for nth(), etc */ -/* ---------------- - * need pg_list.h for definitions of nth(), etc. - * ---------------- - */ /* ---------------- * range table macros @@ -33,10 +29,9 @@ * rt_store * * Access and (destructively) replace rangetable entries. - * */ #define rt_fetch(rangetable_index, rangetable) \ - ((RangeTblEntry*) nth((rangetable_index)-1, rangetable)) + ((RangeTblEntry *) nth((rangetable_index)-1, rangetable)) #define rt_store(rangetable_index, rangetable, rt) \ set_nth(rangetable, (rangetable_index)-1, rt) @@ -45,9 +40,16 @@ * getrelid * * Given the range index of a relation, return the corresponding - * relation OID. + * relation OID. Note that InvalidOid will be returned if the + * RTE is for a sub-select rather than a relation. */ #define getrelid(rangeindex,rangetable) \ (rt_fetch(rangeindex, rangetable)->relid) +/* + * Given an RTE and an attribute number, return the appropriate + * variable name or alias for that attribute of that RTE. + */ +extern char *get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum); + #endif /* PARSETREE_H */ -- 2.39.5