aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/analyze.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/analyze.c')
-rw-r--r--src/backend/parser/analyze.c59
1 files changed, 36 insertions, 23 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 08c209b2a5d..2bd3a00b73e 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: analyze.c,v 1.121 1999/10/07 04:23:11 tgl Exp $
+ * $Id: analyze.c,v 1.122 1999/11/01 05:06:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -253,6 +253,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
Query *qry = makeNode(Query);
Node *fromQual;
List *icolumns;
+ List *attrnos;
+ List *attnos;
+ int numuseratts;
List *tl;
TupleDesc rd_att;
@@ -333,9 +336,11 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
/* Validate stmt->cols list, or build default list if no list given */
- icolumns = makeTargetNames(pstate, stmt->cols);
+ icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
/* Prepare non-junk columns for assignment to target table */
+ numuseratts = 0;
+ attnos = attrnos;
foreach(tl, qry->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
@@ -352,16 +357,30 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
resnode->resno = (AttrNumber) pstate->p_last_resno++;
continue;
}
- if (icolumns == NIL)
+ if (icolumns == NIL || attnos == NIL)
elog(ERROR, "INSERT has more expressions than target columns");
id = (Ident *) lfirst(icolumns);
- updateTargetListEntry(pstate, tle, id->name, id->indirection);
+ updateTargetListEntry(pstate, tle, id->name, lfirsti(attnos),
+ id->indirection);
+ numuseratts++;
icolumns = lnext(icolumns);
+ attnos = lnext(attnos);
}
/*
+ * It is possible that the targetlist has fewer entries than were in
+ * the columns list. We do not consider this an error (perhaps we
+ * should, if the columns list was explictly given?). We must truncate
+ * the attrnos list to only include the attrs actually provided,
+ * else we will fail to apply defaults for them below.
+ */
+ if (icolumns != NIL)
+ attrnos = ltruncate(numuseratts, attrnos);
+
+ /*
* Add targetlist items to assign DEFAULT values to any columns that
* have defaults and were not assigned to by the user.
+ *
* XXX wouldn't it make more sense to do this further downstream,
* after the rule rewriter?
*/
@@ -372,29 +391,20 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
AttrDefault *defval = rd_att->constr->defval;
int ndef = rd_att->constr->num_defval;
- while (ndef-- > 0)
+ while (--ndef >= 0)
{
- Form_pg_attribute thisatt = att[defval[ndef].adnum - 1];
- TargetEntry *te;
+ AttrNumber attrno = defval[ndef].adnum;
+ Form_pg_attribute thisatt = att[attrno - 1];
+ TargetEntry *te;
- foreach(tl, qry->targetList)
- {
- TargetEntry *tle = (TargetEntry *) lfirst(tl);
- Resdom *resnode = tle->resdom;
-
- if (resnode->resjunk)
- continue; /* ignore resjunk nodes */
- if (namestrcmp(&(thisatt->attname), resnode->resname) == 0)
- break;
- }
- if (tl != NIL) /* found TLE for this attr */
- continue;
+ if (intMember((int) attrno, attrnos))
+ continue; /* there was a user-specified value */
/*
* No user-supplied value, so add a targetentry with DEFAULT expr
* and correct data for the target column.
*/
te = makeTargetEntry(
- makeResdom(defval[ndef].adnum,
+ makeResdom(attrno,
thisatt->atttypid,
thisatt->atttypmod,
pstrdup(nameout(&(thisatt->attname))),
@@ -405,7 +415,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
* Make sure the value is coerced to the target column type
* (might not be right type if it's not a constant!)
*/
- updateTargetListEntry(pstate, te, te->resdom->resname, NIL);
+ updateTargetListEntry(pstate, te, te->resdom->resname, attrno,
+ NIL);
}
}
@@ -1128,8 +1139,10 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
if (origTargetList == NIL)
elog(ERROR, "UPDATE target count mismatch --- internal error");
origTarget = (ResTarget *) lfirst(origTargetList);
- updateTargetListEntry(pstate, tle,
- origTarget->name, origTarget->indirection);
+ updateTargetListEntry(pstate, tle, origTarget->name,
+ attnameAttNum(pstate->p_target_relation,
+ origTarget->name),
+ origTarget->indirection);
origTargetList = lnext(origTargetList);
}
if (origTargetList != NIL)