From a5a290cab923c8203ed01631989daa616003ebf8 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 18 Sep 2000 20:14:23 +0000 Subject: [PATCH] Make rule lister use aliases from FROM clause when a table column has been given an alias. Otherwise, results are incorrect. --- src/backend/utils/adt/ruleutils.c | 70 ++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 26ebe21c4a..45282fd94c 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * back to source text * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.61 2000/09/12 21:07:05 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.62 2000/09/18 20:14:23 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -109,7 +109,8 @@ static void get_from_clause_item(Node *jtnode, Query *query, static bool tleIsArrayAssign(TargetEntry *tle); static char *quote_identifier(char *ident); static char *get_relation_name(Oid relid); -static char *get_attribute_name(Oid relid, int2 attnum); +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 ") @@ -445,7 +446,7 @@ pg_get_indexdef(PG_FUNCTION_ARGS) * ---------- */ appendStringInfo(&keybuf, "%s", - quote_identifier(get_attribute_name(idxrec->indrelid, + quote_identifier(get_relid_attribute_name(idxrec->indrelid, idxrec->indkey[keyno]))); /* ---------- @@ -696,8 +697,8 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc) quote_identifier(get_relation_name(ev_class))); if (ev_attr > 0) appendStringInfo(buf, ".%s", - quote_identifier(get_attribute_name(ev_class, - ev_attr))); + quote_identifier(get_relid_attribute_name(ev_class, + ev_attr))); /* If the rule has an event qualification, add it */ if (ev_qual == NULL) @@ -908,7 +909,7 @@ get_select_query_def(Query *query, deparse_context *context) char *attname; rte = get_rte_for_var(var, context); - attname = get_attribute_name(rte->relid, var->varattno); + attname = get_rte_attribute_name(rte, var->varattno); tell_as = (strcmp(attname, tle->resdom->resname) != 0); } @@ -1164,7 +1165,7 @@ get_rule_expr(Node *node, deparse_context *context) quote_identifier(rte->eref->relname)); } appendStringInfo(buf, "%s", - quote_identifier(get_attribute_name(rte->relid, + quote_identifier(get_rte_attribute_name(rte, var->varattno))); } break; @@ -1340,7 +1341,8 @@ get_rule_expr(Node *node, deparse_context *context) if (!OidIsValid(typrelid)) elog(ERROR, "Argument type %s of FieldSelect is not a tuple type", NameStr(typeStruct->typname)); - fieldname = get_attribute_name(typrelid, fselect->fieldnum); + fieldname = get_relid_attribute_name(typrelid, + fselect->fieldnum); appendStringInfo(buf, ".%s", quote_identifier(fieldname)); } break; @@ -2000,23 +2002,51 @@ get_relation_name(Oid relid) /* ---------- - * get_attribute_name - Get an attribute name by its - * relations Oid and its attnum + * get_relid_attribute_name + * Get an attribute name by its relations Oid and its attnum + * + * Same as underlying syscache routine get_attname(), except that error + * is handled by elog() instead of returning NULL. * ---------- */ static char * -get_attribute_name(Oid relid, int2 attnum) +get_relid_attribute_name(Oid relid, AttrNumber attnum) { - HeapTuple atttup; - Form_pg_attribute attStruct; + char *attname; - atttup = SearchSysCacheTuple(ATTNUM, - ObjectIdGetDatum(relid), (Datum) attnum, - 0, 0); - if (!HeapTupleIsValid(atttup)) + attname = get_attname(relid, attnum); + if (attname == NULL) elog(ERROR, "cache lookup of attribute %d in relation %u failed", attnum, relid); - - attStruct = (Form_pg_attribute) GETSTRUCT(atttup); - return pstrdup(NameStr(attStruct->attname)); + 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); }