diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/common/tupdesc.c | 16 | ||||
-rw-r--r-- | src/backend/catalog/dependency.c | 6 | ||||
-rw-r--r-- | src/backend/nodes/print.c | 5 | ||||
-rw-r--r-- | src/backend/optimizer/prep/preptlist.c | 4 | ||||
-rw-r--r-- | src/backend/optimizer/prep/prepunion.c | 21 | ||||
-rw-r--r-- | src/backend/parser/analyze.c | 13 | ||||
-rw-r--r-- | src/backend/parser/parse_relation.c | 12 | ||||
-rw-r--r-- | src/backend/parser/parse_target.c | 17 | ||||
-rw-r--r-- | src/backend/rewrite/rewriteHandler.c | 22 | ||||
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 68 | ||||
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 25 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 6 | ||||
-rw-r--r-- | src/include/access/tupdesc.h | 4 | ||||
-rw-r--r-- | src/include/nodes/primnodes.h | 39 | ||||
-rw-r--r-- | src/include/utils/lsyscache.h | 3 |
15 files changed, 145 insertions, 116 deletions
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index b76e03ed43f..9a40c08ca92 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.98 2003/08/04 02:39:56 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.99 2003/08/11 23:04:49 tgl Exp $ * * NOTES * some of the executor utility code such as "ExecTypeFromTL" should be @@ -357,7 +357,7 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, - char *attributeName, + const char *attributeName, Oid oidtypeid, int32 typmod, int attdim, @@ -373,13 +373,6 @@ TupleDescInitEntry(TupleDesc desc, AssertArg(PointerIsValid(desc)); AssertArg(attributeNumber >= 1); AssertArg(attributeNumber <= desc->natts); - - /* - * attributeName's are sometimes NULL, from resdom's. I don't know - * why that is, though -- Jolly - */ -/* AssertArg(NameIsValid(attributeName));*/ - AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1])); /* @@ -394,6 +387,11 @@ TupleDescInitEntry(TupleDesc desc, */ att->attrelid = 0; /* dummy value */ + /* + * Note: attributeName can be NULL, because the planner doesn't always + * fill in valid resname values in targetlists, particularly for resjunk + * attributes. + */ if (attributeName != NULL) namestrcpy(&(att->attname), attributeName); else diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index 870a2320c2f..8155f4fff3f 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.30 2003/08/04 02:39:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.31 2003/08/11 23:04:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1439,8 +1439,8 @@ getObjectDescription(const ObjectAddress *object) getRelationDescription(&buffer, object->objectId); if (object->objectSubId != 0) appendStringInfo(&buffer, " column %s", - get_attname(object->objectId, - object->objectSubId)); + get_relid_attribute_name(object->objectId, + object->objectSubId)); break; case OCLASS_PROC: diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c index c3d702316d2..c3417d8efa2 100644 --- a/src/backend/nodes/print.c +++ b/src/backend/nodes/print.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.63 2003/08/04 02:39:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.64 2003/08/11 23:04:49 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -448,7 +448,8 @@ print_tl(List *tlist, List *rtable) { TargetEntry *tle = lfirst(tl); - printf("\t%d %s\t", tle->resdom->resno, tle->resdom->resname); + printf("\t%d %s\t", tle->resdom->resno, + tle->resdom->resname ? tle->resdom->resname : "<null>"); if (tle->resdom->ressortgroupref != 0) printf("(%u):\t", tle->resdom->ressortgroupref); else diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index 5796870e767..f2368d06779 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.64 2003/08/04 02:40:01 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.65 2003/08/11 23:04:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -150,8 +150,6 @@ expand_targetlist(List *tlist, int command_type, if (!resdom->resjunk && resdom->resno == attrno) { - Assert(strcmp(resdom->resname, - NameStr(att_tup->attname)) == 0); new_tle = old_tle; tlist = lnext(tlist); } diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index d023fd97a8f..281b15571d5 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.103 2003/08/04 02:40:01 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.104 2003/08/11 23:04:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -64,7 +64,7 @@ static bool tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK); static Node *adjust_inherited_attrs_mutator(Node *node, adjust_inherited_attrs_context *context); static Relids adjust_relid_set(Relids relids, Index oldrelid, Index newrelid); -static List *adjust_inherited_tlist(List *tlist, Oid new_relid); +static List *adjust_inherited_tlist(List *tlist, Oid old_relid, Oid new_relid); /* @@ -787,6 +787,7 @@ adjust_inherited_attrs(Node *node, if (newnode->commandType == CMD_UPDATE) newnode->targetList = adjust_inherited_tlist(newnode->targetList, + old_relid, new_relid); } return (Node *) newnode; @@ -812,9 +813,10 @@ adjust_inherited_attrs_mutator(Node *node, var->varnoold = context->new_rt_index; if (var->varattno > 0) { - char *attname = get_attname(context->old_relid, - var->varattno); + char *attname; + attname = get_relid_attribute_name(context->old_relid, + var->varattno); var->varattno = get_attnum(context->new_relid, attname); if (var->varattno == InvalidAttrNumber) elog(ERROR, "attribute \"%s\" of relation \"%s\" does not exist", @@ -976,7 +978,7 @@ adjust_relid_set(Relids relids, Index oldrelid, Index newrelid) * Note that this is not needed for INSERT because INSERT isn't inheritable. */ static List * -adjust_inherited_tlist(List *tlist, Oid new_relid) +adjust_inherited_tlist(List *tlist, Oid old_relid, Oid new_relid) { bool changed_it = false; List *tl; @@ -989,21 +991,26 @@ adjust_inherited_tlist(List *tlist, Oid new_relid) { TargetEntry *tle = (TargetEntry *) lfirst(tl); Resdom *resdom = tle->resdom; + char *attname; if (resdom->resjunk) continue; /* ignore junk items */ - attrno = get_attnum(new_relid, resdom->resname); + attname = get_relid_attribute_name(old_relid, resdom->resno); + attrno = get_attnum(new_relid, attname); if (attrno == InvalidAttrNumber) elog(ERROR, "attribute \"%s\" of relation \"%s\" does not exist", - resdom->resname, get_rel_name(new_relid)); + attname, get_rel_name(new_relid)); if (resdom->resno != attrno) { resdom = (Resdom *) copyObject((Node *) resdom); resdom->resno = attrno; + resdom->resname = attname; tle->resdom = resdom; changed_it = true; } + else + pfree(attname); } /* diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index ea9a1d80a8e..832c98a1c1c 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.286 2003/08/08 21:41:55 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.287 2003/08/11 23:04:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2124,10 +2124,12 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) { Oid colType = lfirsto(dtlist); Resdom *leftResdom = ((TargetEntry *) lfirst(lefttl))->resdom; - char *colName = pstrdup(leftResdom->resname); + char *colName; Resdom *resdom; Expr *expr; + Assert(!leftResdom->resjunk); + colName = pstrdup(leftResdom->resname); resdom = makeResdom((AttrNumber) pstate->p_next_resno++, colType, -1, @@ -2501,11 +2503,12 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt) { /* * Resjunk nodes need no additional processing, but be sure - * they have names and resnos that do not match any target - * columns; else rewriter or planner might get confused. + * they have resnos that do not match any target columns; + * else rewriter or planner might get confused. They don't + * need a resname either. */ - resnode->resname = "?resjunk?"; resnode->resno = (AttrNumber) pstate->p_next_resno++; + resnode->resname = NULL; continue; } if (origTargetList == NIL) diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index b8c2d8c8e36..ba1eea0475b 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.88 2003/08/11 20:46:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.89 2003/08/11 23:04:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1516,8 +1516,6 @@ expandRelAttrs(ParseState *pstate, RangeTblEntry *rte) char * get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum) { - char *attname; - if (attnum == InvalidAttrNumber) return "*"; @@ -1535,13 +1533,7 @@ get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum) * built (which can easily happen for rules). */ if (rte->rtekind == RTE_RELATION) - { - attname = get_attname(rte->relid, attnum); - if (attname == NULL) - elog(ERROR, "cache lookup failed for attribute %d of relation %u", - attnum, rte->relid); - return attname; - } + return get_relid_attribute_name(rte->relid, attnum); /* * Otherwise use the column name from eref. There should always be diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index a525e8795f0..5d5ee56eb14 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.111 2003/08/11 20:46:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.112 2003/08/11 23:04:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -71,7 +71,7 @@ transformTargetEntry(ParseState *pstate, type_id = exprType(expr); type_mod = exprTypmod(expr); - if (colname == NULL) + if (colname == NULL && !resjunk) { /* * Generate a suitable column name for a column without any @@ -428,14 +428,19 @@ updateTargetListEntry(ParseState *pstate, /* * The result of the target expression should now match the - * destination column's type. Also, reset the resname and resno to - * identify the destination column --- rewriter and planner depend on - * that! + * destination column's type. */ resnode->restype = attrtype; resnode->restypmod = attrtypmod; - resnode->resname = colname; + /* + * Set the resno to identify the target column --- the rewriter and + * planner depend on this. We also set the resname to identify the + * target column, but this is only for debugging purposes; it should + * not be relied on. (In particular, it might be out of date in a + * stored rule.) + */ resnode->resno = (AttrNumber) attrno; + resnode->resname = colname; } diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index e8f3c185d16..d0ca89ee6ab 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.128 2003/08/08 21:41:56 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.129 2003/08/11 23:04:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -48,7 +48,8 @@ static Query *rewriteRuleAction(Query *parsetree, static List *adjustJoinTreeList(Query *parsetree, bool removert, int rt_index); static void rewriteTargetList(Query *parsetree, Relation target_relation); static TargetEntry *process_matched_tle(TargetEntry *src_tle, - TargetEntry *prior_tle); + TargetEntry *prior_tle, + const char *attrName); static void markQueryForUpdate(Query *qry, bool skipOldNew); static List *matchLocks(CmdType event, RuleLock *rulelocks, int varno, Query *parsetree); @@ -312,8 +313,7 @@ rewriteTargetList(Query *parsetree, Relation target_relation) continue; /* - * Look for targetlist entries matching this attr. We match by - * resno, but the resname should match too. + * Look for targetlist entries matching this attr. * * Junk attributes are not candidates to be matched. */ @@ -324,9 +324,8 @@ rewriteTargetList(Query *parsetree, Relation target_relation) if (!resdom->resjunk && resdom->resno == attrno) { - Assert(strcmp(resdom->resname, - NameStr(att_tup->attname)) == 0); - new_tle = process_matched_tle(old_tle, new_tle); + new_tle = process_matched_tle(old_tle, new_tle, + NameStr(att_tup->attname)); /* keep scanning to detect multiple assignments to attr */ } } @@ -424,11 +423,12 @@ rewriteTargetList(Query *parsetree, Relation target_relation) * Convert a matched TLE from the original tlist into a correct new TLE. * * This routine detects and handles multiple assignments to the same target - * attribute. + * attribute. (The attribute name is needed only for error messages.) */ static TargetEntry * process_matched_tle(TargetEntry *src_tle, - TargetEntry *prior_tle) + TargetEntry *prior_tle, + const char *attrName) { Resdom *resdom = src_tle->resdom; Node *priorbottom; @@ -456,7 +456,7 @@ process_matched_tle(TargetEntry *src_tle, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple assignments to same attribute \"%s\"", - resdom->resname))); + attrName))); /* * Prior TLE could be a nest of ArrayRefs if we do this more than @@ -470,7 +470,7 @@ process_matched_tle(TargetEntry *src_tle, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple assignments to same attribute \"%s\"", - resdom->resname))); + attrName))); /* * Looks OK to nest 'em. diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 49cc73f24e4..83989292d6a 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.150 2003/08/08 21:42:09 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.151 2003/08/11 23:04:49 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -207,7 +207,6 @@ static char *generate_relation_name(Oid relid); static char *generate_function_name(Oid funcid, int nargs, Oid *argtypes); static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2); static void print_operator_name(StringInfo buf, List *opname); -static char *get_relid_attribute_name(Oid relid, AttrNumber attnum); #define only_marker(rte) ((rte)->inh ? "" : "ONLY ") @@ -1140,7 +1139,7 @@ decompile_column_index_array(Datum column_index_array, Oid relId, { char *colName; - colName = get_attname(relId, DatumGetInt16(keys[j])); + colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j])); if (j == 0) appendStringInfo(buf, "%s", @@ -1901,7 +1900,6 @@ get_basic_select_query(Query *query, deparse_context *context, foreach(l, query->targetList) { TargetEntry *tle = (TargetEntry *) lfirst(l); - bool tell_as = false; char *colname; if (tle->resdom->resjunk) @@ -1924,24 +1922,30 @@ get_basic_select_query(Query *query, deparse_context *context, else colname = tle->resdom->resname; - /* Check if we must say AS ... */ - if (!IsA(tle->expr, Var)) - tell_as = (strcmp(colname, "?column?") != 0); - else + if (colname) /* resname could be NULL */ { - Var *var = (Var *) (tle->expr); - char *schemaname; - char *refname; - char *attname; + /* Check if we must say AS ... */ + bool tell_as; - get_names_for_var(var, context, &schemaname, &refname, &attname); - tell_as = (attname == NULL || - strcmp(attname, colname) != 0); - } + if (!IsA(tle->expr, Var)) + tell_as = (strcmp(colname, "?column?") != 0); + else + { + Var *var = (Var *) (tle->expr); + char *schemaname; + char *refname; + char *attname; - /* and do if so */ - if (tell_as) - appendStringInfo(buf, " AS %s", quote_identifier(colname)); + get_names_for_var(var, context, + &schemaname, &refname, &attname); + tell_as = (attname == NULL || + strcmp(attname, colname) != 0); + } + + /* and do if so */ + if (tell_as) + appendStringInfo(buf, " AS %s", quote_identifier(colname)); + } } /* Add the FROM clause if needed */ @@ -2151,7 +2155,9 @@ get_insert_query_def(Query *query, deparse_context *context) appendStringInfo(buf, sep); sep = ", "; - appendStringInfo(buf, "%s", quote_identifier(tle->resdom->resname)); + appendStringInfo(buf, "%s", + quote_identifier(get_relid_attribute_name(rte->relid, + tle->resdom->resno))); } appendStringInfo(buf, ") "); @@ -2225,7 +2231,8 @@ get_update_query_def(Query *query, deparse_context *context) */ if (!tleIsArrayAssign(tle)) appendStringInfo(buf, "%s = ", - quote_identifier(tle->resdom->resname)); + quote_identifier(get_relid_attribute_name(rte->relid, + tle->resdom->resno))); get_rule_expr((Node *) tle->expr, context, false); } @@ -4351,22 +4358,3 @@ print_operator_name(StringInfo buf, List *opname) appendStringInfo(buf, "%s)", strVal(lfirst(opname))); } } - -/* - * 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_relid_attribute_name(Oid relid, AttrNumber attnum) -{ - char *attname; - - attname = get_attname(relid, attnum); - if (attname == NULL) - elog(ERROR, "cache lookup failed for attribute %d of relation %u", - attnum, relid); - return attname; -} diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 0dfa0eb7c79..0faa097f349 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.105 2003/08/04 02:40:06 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.106 2003/08/11 23:04:49 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -180,11 +180,10 @@ get_op_hash_function(Oid opno) /* * get_attname - * * Given the relation id and the attribute number, * return the "attname" field from the attribute relation. * - * Note: returns a palloc'd copy of the string, or NULL if no such operator. + * Note: returns a palloc'd copy of the string, or NULL if no such attribute. */ char * get_attname(Oid relid, AttrNumber attnum) @@ -209,6 +208,24 @@ get_attname(Oid relid, AttrNumber attnum) } /* + * get_relid_attribute_name + * + * Same as above routine get_attname(), except that error + * is handled by elog() instead of returning NULL. + */ +char * +get_relid_attribute_name(Oid relid, AttrNumber attnum) +{ + char *attname; + + attname = get_attname(relid, attnum); + if (attname == NULL) + elog(ERROR, "cache lookup failed for attribute %d of relation %u", + attnum, relid); + return attname; +} + +/* * get_attnum * * Given the relation id and the attribute name, @@ -1443,7 +1460,7 @@ get_typtype(Oid typid) * get_typname * Returns the name of a given type. * - * Returns a palloc'd copy of the string, or NULL if no such relation. + * Returns a palloc'd copy of the string, or NULL if no such type. * * NOTE: since type name is not unique, be wary of code that uses this * for anything except preparing error messages. diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index ddaee15de57..2ff904510ca 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut <peter_e@gmx.net>. * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.148 2003/08/04 23:59:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.149 2003/08/11 23:04:49 tgl Exp $ * *-------------------------------------------------------------------- */ @@ -3293,7 +3293,7 @@ GetPGVariableResultDesc(const char *name) /* need a tuple descriptor representing a single TEXT column */ tupdesc = CreateTemplateTupleDesc(1, false); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, (char *) varname, + TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname, TEXTOID, -1, 0, false); } return tupdesc; @@ -3333,7 +3333,7 @@ ShowGUCConfigOption(const char *name, DestReceiver *dest) /* need a tuple descriptor representing a single TEXT column */ tupdesc = CreateTemplateTupleDesc(1, false); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, (char *) varname, + TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname, TEXTOID, -1, 0, false); /* prepare for projection of tuples */ diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h index c955689663b..4ecb951a902 100644 --- a/src/include/access/tupdesc.h +++ b/src/include/access/tupdesc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: tupdesc.h,v 1.40 2003/08/04 02:40:10 momjian Exp $ + * $Id: tupdesc.h,v 1.41 2003/08/11 23:04:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -70,7 +70,7 @@ extern bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2); extern void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, - char *attributeName, + const char *attributeName, Oid oidtypeid, int32 typmod, int attdim, diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 49d5f494676..f6e4436d950 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: primnodes.h,v 1.90 2003/08/08 21:42:48 momjian Exp $ + * $Id: primnodes.h,v 1.91 2003/08/11 23:04:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,13 +31,29 @@ * * Notes: * - * resno will normally be equal to the item's position in a targetlist, - * but the code generally tries to avoid relying on that (eg, we avoid - * using "nth()" rather than a search to find an item by resno). - * - * resname will be null if no name can easily be assigned to the column. - * But it should never be null for user-visible columns (i.e., non-junk - * columns in a toplevel targetlist). + * In a SELECT's targetlist, resno should always be equal to the item's + * ordinal position (counting from 1). However, in an INSERT or UPDATE + * targetlist, resno represents the attribute number of the destination + * column for the item; so there may be missing or out-of-order resnos. + * In an UPDATE, it is even legal to have duplicated resnos; consider + * UPDATE table SET arraycol[1] = ..., arraycol[2] = ..., ... + * The two meanings come together in the executor, because the planner + * transforms INSERT/UPDATE tlists into a normalized form with exactly + * one entry for each column of the destination table. Before that's + * happened, however, it is risky to assume that resno == position. + * Generally get_tle_by_resno() should be used rather than nth() to fetch + * tlist entries by resno. + * + * resname is required to represent the correct column name in non-resjunk + * entries of top-level SELECT targetlists, since it will be used as the + * column title sent to the frontend. In most other contexts it is only + * a debugging aid, and may be wrong or even NULL. (In particular, it may + * be wrong in a tlist from a stored rule, if the referenced column has been + * renamed by ALTER TABLE since the rule was made. Also, the planner tends + * to store NULL rather than look up a valid name for tlist entries in + * non-toplevel plan nodes.) In resjunk entries, resname should be either + * a specific system-generated name (such as "ctid") or NULL; anything else + * risks confusing ExecGetJunkAttribute! * * ressortgroupref is used in the representation of ORDER BY and * GROUP BY items. Targetlist entries with ressortgroupref=0 are not @@ -53,13 +69,16 @@ * a simple reference, these fields are zeroes. * * If resjunk is true then the column is a working column (such as a sort key) - * that should be removed from the final output of the query. + * that should be removed from the final output of the query. Resjunk columns + * must have resnos that cannot duplicate any regular column's resno. Also + * note that there are places that assume resjunk columns come after non-junk + * columns. *-------------------- */ typedef struct Resdom { NodeTag type; - AttrNumber resno; /* attribute number (1..N) */ + AttrNumber resno; /* attribute number (see notes above) */ Oid restype; /* type of the value */ int32 restypmod; /* type-specific modifier of the value */ char *resname; /* name of the column (could be NULL) */ diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index c94e78eb491..4c9c073adea 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: lsyscache.h,v 1.79 2003/08/08 21:42:55 momjian Exp $ + * $Id: lsyscache.h,v 1.80 2003/08/11 23:04:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,6 +29,7 @@ extern bool op_requires_recheck(Oid opno, Oid opclass); extern Oid get_opclass_member(Oid opclass, int16 strategy); extern Oid get_op_hash_function(Oid opno); extern char *get_attname(Oid relid, AttrNumber attnum); +extern char *get_relid_attribute_name(Oid relid, AttrNumber attnum); extern AttrNumber get_attnum(Oid relid, const char *attname); extern Oid get_atttype(Oid relid, AttrNumber attnum); extern int32 get_atttypmod(Oid relid, AttrNumber attnum); |