DEFAULT is handled by analyze.c now.
authorVadim B. Mikheev
Sun, 12 Oct 1997 07:09:20 +0000 (07:09 +0000)
committerVadim B. Mikheev
Sun, 12 Oct 1997 07:09:20 +0000 (07:09 +0000)
src/backend/executor/execMain.c
src/backend/parser/analyze.c

index 2048e632ca0388e2c9d638a607fb0b53766aacc7..07935eced7297403b042838a4a7f86afd063b94b 100644 (file)
@@ -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)
    {
index 2008ab4d7dbbca0c80740d017231c57a5914323e..dd3aeada2eb0fbcc73351746bfdabe6e6bb11582 100644 (file)
@@ -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;
 }