From defb10a4503a83a5c48577e5aa7880d028f17211 Mon Sep 17 00:00:00 2001 From: "Vadim B. Mikheev" Date: Sun, 12 Oct 1997 07:09:20 +0000 Subject: [PATCH] DEFAULT is handled by analyze.c now. --- src/backend/executor/execMain.c | 6 ++- src/backend/parser/analyze.c | 89 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 8 deletions(-) diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 2048e632ca..07935eced7 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.26 1997/09/18 20:20:29 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.27 1997/10/12 07:09:02 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -1245,6 +1245,7 @@ ExecReplace(TupleTableSlot *slot, ExecARUpdateTriggers(resultRelationDesc, tupleid, tuple); } +#if 0 static HeapTuple ExecAttrDefault(Relation rel, HeapTuple tuple) { @@ -1309,6 +1310,7 @@ ExecAttrDefault(Relation rel, HeapTuple tuple) return (newtuple); } +#endif static char * ExecRelCheck(Relation rel, HeapTuple tuple) @@ -1375,8 +1377,10 @@ ExecConstraints(char *caller, Relation rel, HeapTuple tuple) Assert(rel->rd_att->constr); +#if 0 if (rel->rd_att->constr->num_defval > 0) newtuple = tuple = ExecAttrDefault(rel, tuple); +#endif if (rel->rd_att->constr->has_not_null) { diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 2008ab4d7d..dd3aeada2e 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.44 1997/09/18 20:20:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.45 1997/10/12 07:09:20 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -303,6 +303,7 @@ static Query * transformInsertStmt(ParseState *pstate, AppendStmt *stmt) { Query *qry = makeNode(Query); /* make a new query tree */ + List *icolumns; qry->commandType = CMD_INSERT; pstate->p_is_insert = true; @@ -313,10 +314,74 @@ transformInsertStmt(ParseState *pstate, AppendStmt *stmt) qry->uniqueFlag = NULL; /* fix the target list */ - pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols); - + icolumns = pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols); + qry->targetList = transformTargetList(pstate, stmt->targetList); - + + /* DEFAULT handling */ + if (length(qry->targetList) < pstate->p_target_relation->rd_att->natts && + pstate->p_target_relation->rd_att->constr && + pstate->p_target_relation->rd_att->constr->num_defval > 0) + { + AttributeTupleForm *att = pstate->p_target_relation->rd_att->attrs; + AttrDefault *defval = pstate->p_target_relation->rd_att->constr->defval; + int ndef = pstate->p_target_relation->rd_att->constr->num_defval; + + /* + * if stmt->cols == NIL then makeTargetNames returns list of all + * attrs: have to shorter icolumns list... + */ + if (stmt->cols == NIL) + { + List *extrl; + int i = length(qry->targetList); + + foreach (extrl, icolumns) + { + if (--i <= 0) + break; + } + freeList (lnext(extrl)); + lnext(extrl) = NIL; + } + + while (ndef-- > 0) + { + List *tl; + Ident *id; + TargetEntry *te; + + foreach (tl, icolumns) + { + id = (Ident *) lfirst(tl); + if (!namestrcmp(&(att[defval[ndef].adnum - 1]->attname), id->name)) + break; + } + if (tl != NIL) /* something given for this attr */ + continue; + /* + * Nothing given for this attr with DEFAULT expr, so + * add new TargetEntry to qry->targetList. + * Note, that we set resno to defval[ndef].adnum: + * it's what transformTargetList()->make_targetlist_expr() + * does for INSERT ... SELECT. But for INSERT ... VALUES + * pstate->p_last_resno is used. It doesn't matter for + * "normal" using (planner creates proper target list + * in preptlist.c), but may break RULEs in some way. + * It seems better to create proper target list here... + */ + te = makeNode(TargetEntry); + te->resdom = makeResdom(defval[ndef].adnum, + att[defval[ndef].adnum - 1]->atttypid, + att[defval[ndef].adnum - 1]->attlen, + pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))), + 0, 0, 0); + te->fjoin = NULL; + te->expr = (Node *) stringToNode(defval[ndef].adbin); + qry->targetList = lappend (qry->targetList, te); + } + } + /* fix where clause */ qry->qual = transformWhereClause(pstate, stmt->whereClause); @@ -1098,10 +1163,20 @@ makeTargetNames(ParseState *pstate, List *cols) } } else + { foreach(tl, cols) - /* elog on failure */ - varattno(pstate->p_target_relation, ((Ident *) lfirst(tl))->name); - + { + List *nxt; + char *name = ((Ident *) lfirst(tl))->name; + + /* elog on failure */ + varattno(pstate->p_target_relation, name); + foreach(nxt, lnext(tl)) + if (!strcmp(name, ((Ident *) lfirst(nxt))->name)) + elog (WARN, "Attribute %s should be specified only once", name); + } + } + return cols; } -- 2.11.0