]> granicus.if.org Git - postgresql/commitdiff
Parser Overhaul
authorBruce Momjian <bruce@momjian.us>
Wed, 30 Oct 1996 02:02:41 +0000 (02:02 +0000)
committerBruce Momjian <bruce@momjian.us>
Wed, 30 Oct 1996 02:02:41 +0000 (02:02 +0000)
src/backend/commands/recipe.c
src/backend/commands/view.c
src/backend/parser/analyze.c
src/backend/parser/gram.y
src/backend/parser/parse_query.c
src/include/nodes/parsenodes.h
src/include/parser/parse_state.h
src/test/regress/expected.input
src/test/regress/queries.source
src/test/regress/regress.sh

index 97ac1582b629ec90e4e72650f38402708f6147d9..0e14edfb78d8411a62482de9842320e1a7d946fc 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.2 1996/08/28 07:16:17 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.3 1996/10/30 02:01:45 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -690,10 +690,12 @@ tg_parseTeeNode(TgRecipe *r,
        same Tee. */
     if (rt_ind == 0) {
        orig->rtable = lappend(orig->rtable,
-                              makeRangeTableEntry(tt,
+                              addRangeTableEntry(NULL,
+                                                  tt,
+                                                  tt,
                                                   FALSE,
-                                                  NULL,
-                                                  tt));
+                                                  FALSE,
+                                                  NULL));
        rt_ind = length(orig->rtable);
     }
                        
index f6023ca08deb5ecea2718a61aef498a6d278f369..26c1db88840e88fd986d9b086265c49c41c3900a 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.1.1.1 1996/07/09 06:21:22 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.2 1996/10/30 02:01:47 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -235,9 +235,11 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
      * CURRENT first, then NEW....
      */
     rt_entry1 =
-       makeRangeTableEntry((char*)viewName, FALSE, NULL, "*CURRENT*");
+       addRangeTableEntry(NULL, (char*)viewName, "*CURRENT*",
+                                               FALSE, FALSE, NULL);
     rt_entry2 =
-       makeRangeTableEntry((char*)viewName, FALSE, NULL, "*NEW*");
+       addRangeTableEntry(NULL, (char*)viewName, "*NEW*",
+                                               FALSE, FALSE, NULL);
     new_rt = lcons(rt_entry2, old_rt);
     new_rt = lcons(rt_entry1, new_rt);
     
index e28ea8037ef3e0270af46d7dc879a9c1c8405892..b1aad238f6111a7b6903a4f97f6123c428996285 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.7 1996/10/14 03:53:53 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.8 1996/10/30 02:01:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -52,14 +52,11 @@ static Node *transformExpr(ParseState *pstate, Node *expr);
 static void makeRangeTable(ParseState *pstate, char *relname, List *frmList);
 static List *expandAllTables(ParseState *pstate);
 static char *figureColname(Node *expr, Node *resval);
-static List *makeTargetList(ParseState *pstate, List *cols, List *exprs);
-static List *transformTargetList(ParseState *pstate, 
-                                List *targetlist, bool isInsert,
-                                bool isUpdate);
+static List *makeTargetNames(ParseState *pstate, List *cols);
+static List *transformTargetList(ParseState *pstate, List *targetlist);
 static TargetEntry *make_targetlist_expr(ParseState *pstate,
-                                        char *name, Node *expr,
-                                        List *arrayRef,
-                                        bool ResdomNoIsAttrNo);
+                                        char *colname, Node *expr,
+                                        List *arrayRef);
 static Node *transformWhereClause(ParseState *pstate, Node *a_expr);
 static List *transformGroupClause(ParseState *pstate, List *grouplist);
 static List *transformSortClause(ParseState *pstate,
@@ -69,10 +66,10 @@ static List *transformSortClause(ParseState *pstate,
 static void parseFromClause(ParseState *pstate, List *frmList);
 static Node *ParseFunc(ParseState *pstate, char *funcname, 
                       List *fargs, int *curr_resno);
-static char *ParseColumnName(ParseState *pstate, char *name, bool *isRelName);
 static List *setup_tlist(char *attname, Oid relid);
 static List *setup_base_tlist(Oid typeid);
-static void make_arguments(int nargs, List *fargs, Oid *input_typeids, Oid *function_typeids);
+static void make_arguments(int nargs, List *fargs, Oid *input_typeids,
+                                                       Oid *function_typeids);
 static void AddAggToParseState(ParseState *pstate, Aggreg *aggreg);
 static void finalizeAggregates(ParseState *pstate, Query *qry);
 static void parseCheckAggregates(ParseState *pstate, Query *qry);
@@ -94,15 +91,19 @@ makeParseState() {
 
     pstate = malloc(sizeof(ParseState));
     pstate->p_last_resno = 1;
-    pstate->p_target_resnos = NIL;
-    pstate->p_current_rel = NULL;
     pstate->p_rtable = NIL;
-    pstate->p_query_is_rule = 0;
     pstate->p_numAgg = 0;
     pstate->p_aggs = NIL;
+    pstate->p_is_insert = false;
+    pstate->p_insert_columns = NIL;
+    pstate->p_is_update = false;
+    pstate->p_is_rule = false;
+    pstate->p_target_relation = NULL;
+    pstate->p_target_rangetblentry = NULL;
 
     return (pstate);
 }
+
 /*
  * parse_analyze -
  *    analyze a list of parse trees and transform them if necessary.
@@ -127,8 +128,8 @@ parse_analyze(List *pl)
        pstate = makeParseState();
        result->qtrees[i++] = transformStmt(pstate, lfirst(pl));
        pl = lnext(pl);
-       if (pstate->p_current_rel != NULL)
-           heap_close(pstate->p_current_rel);
+       if (pstate->p_target_relation != NULL)
+           heap_close(pstate->p_target_relation);
        free(pstate);
     }
 
@@ -247,14 +248,13 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
     /* set up a range table */
     makeRangeTable(pstate, stmt->relname, NULL);
     
-/*    qry->uniqueFlag = FALSE; */
     qry->uniqueFlag = NULL; 
 
     /* fix where clause */
     qry->qual = transformWhereClause(pstate, stmt->whereClause);
 
     qry->rtable = pstate->p_rtable;
-    qry->resultRelation = RangeTablePosn(pstate->p_rtable, stmt->relname);
+    qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
 
     /* make sure we don't have aggregates in the where clause */
     if (pstate->p_numAgg > 0)
@@ -274,26 +274,24 @@ transformInsertStmt(ParseState *pstate, AppendStmt *stmt)
     List *targetlist;
 
     qry->commandType = CMD_INSERT;
+    pstate->p_is_insert = true;
 
     /* set up a range table */
     makeRangeTable(pstate, stmt->relname, stmt->fromClause);
 
-/*    qry->uniqueFlag = FALSE; */
     qry->uniqueFlag = NULL; 
 
     /* fix the target list */
-    targetlist = makeTargetList(pstate, stmt->cols, stmt->exprs);
-    qry->targetList = transformTargetList(pstate, 
-                                         targetlist,
-                                         TRUE /* is insert */,
-                                         FALSE /*not update*/);
+    pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols);
+
+    qry->targetList = transformTargetList(pstate, stmt->targetList);
 
     /* fix where clause */
     qry->qual = transformWhereClause(pstate, stmt->whereClause);
 
     /* now the range table will not change */
     qry->rtable = pstate->p_rtable;
-    qry->resultRelation = RangeTablePosn(pstate->p_rtable, stmt->relname);
+    qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
 
     if (pstate->p_numAgg > 0)
        finalizeAggregates(pstate, qry);
@@ -362,21 +360,17 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
      * transform each statment, like parse_analyze()
      */
     while (actions != NIL) {
-       RangeTblEntry *curEnt, *newEnt;
-
        /*
         * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW' 
         * equal to 2.
         */
-       curEnt = makeRangeTableEntry(stmt->object->relname, FALSE,
-                                    NULL, "*CURRENT*");
-       newEnt = makeRangeTableEntry(stmt->object->relname, FALSE,
-                                    NULL, "*NEW*");
-       pstate->p_rtable = makeList(curEnt, newEnt, -1);
+       addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
+                                       FALSE, FALSE, NULL);
+       addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
+                                       FALSE, FALSE, NULL);
 
        pstate->p_last_resno = 1;
-       pstate->p_target_resnos = NIL;
-       pstate->p_query_is_rule = 1;    /* for expand all */
+       pstate->p_is_rule = true;       /* for expand all */
        pstate->p_numAgg = 0;
        pstate->p_aggs = NULL;
        
@@ -413,10 +407,7 @@ transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt)
     qry->isPortal = FALSE;
 
     /* fix the target list */
-    qry->targetList = transformTargetList(pstate, 
-                                         stmt->targetList,
-                                         FALSE, /*is insert */
-                                         FALSE /*not update*/);
+    qry->targetList = transformTargetList(pstate, stmt->targetList);
 
     /* fix where clause */
     qry->qual = transformWhereClause(pstate,stmt->whereClause);
@@ -449,7 +440,7 @@ transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt)
     Query *qry = makeNode(Query);
 
     qry->commandType = CMD_UPDATE;
-
+    pstate->p_is_update = true;
     /*
      * the FROM clause is non-standard SQL syntax. We used to be able to
      * do this with REPLACE in POSTQUEL so we keep the feature.
@@ -457,16 +448,13 @@ transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt)
     makeRangeTable(pstate, stmt->relname, stmt->fromClause); 
 
     /* fix the target list */
-    qry->targetList = transformTargetList(pstate, 
-                                         stmt->targetList,
-                                         FALSE, /* not insert */
-                                         TRUE   /* is update */);
+    qry->targetList = transformTargetList(pstate, stmt->targetList);
 
     /* fix where clause */
     qry->qual = transformWhereClause(pstate,stmt->whereClause);
 
     qry->rtable = pstate->p_rtable;
-    qry->resultRelation = RangeTablePosn(pstate->p_rtable, stmt->relname);
+    qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
 
     /* make sure we don't have aggregates in the where clause */
     if (pstate->p_numAgg > 0)
@@ -502,10 +490,7 @@ transformCursorStmt(ParseState *pstate, CursorStmt *stmt)
     qry->isBinary = stmt->binary;      /* internal portal */
 
     /* fix the target list */
-    qry->targetList = transformTargetList(pstate,
-                                         stmt->targetList,
-                                         FALSE, /*is insert */
-                                         FALSE /*not update*/);
+    qry->targetList = transformTargetList(pstate, stmt->targetList);
 
     /* fix where clause */
     qry->qual = transformWhereClause(pstate,stmt->whereClause);
@@ -700,33 +685,23 @@ transformExpr(ParseState *pstate, Node *expr)
     }
     case T_Ident: {
        Ident *ident = (Ident*)expr;
-       bool isrel;
-       char *reln= ParseColumnName(pstate,ident->name, &isrel);
+       RangeTblEntry *rte;
 
-       /* could be a column name or a relation_name */
-       if (reln==NULL) {
-           /*
-            * may be a relation_name
-            *
-            * ??? in fact, every ident left after transfromExpr() is called
-            *     will be assumed to be a relation.
-            */
-           if (isrel) {
+               /* could be a column name or a relation_name */
+       if (refnameRangeTableEntry(pstate->p_rtable, ident->name) != NULL) {
                ident->isRel = TRUE;
                result = (Node*)ident;
-           } else {
-               elog(WARN, "attribute \"%s\" not found", ident->name);
-           }
-       }else {
+       }
+       else if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL)
+       {
            Attr *att = makeNode(Attr);
-           att->relname = reln;
+
+           att->relname = rte->refname;
            att->attrs = lcons(makeString(ident->name), NIL);
-           /*
-            * a column name
-            */
            result =
                (Node*)handleNestedDots(pstate, att, &pstate->p_last_resno);
-       }
+       } else
+           elog(WARN, "attribute \"%s\" not found", ident->name);
        break;
     }
     case T_FuncCall: {
@@ -734,9 +709,8 @@ transformExpr(ParseState *pstate, Node *expr)
        List *args;
 
        /* transform the list of arguments */
-       foreach(args, fn->args) {
+       foreach(args, fn->args)
            lfirst(args) = transformExpr(pstate, (Node*)lfirst(args));
-       }
        result = ParseFunc(pstate,
                           fn->funcname, fn->args, &pstate->p_last_resno);
        break;
@@ -769,30 +743,21 @@ transformExpr(ParseState *pstate, Node *expr)
 static void
 parseFromClause(ParseState *pstate, List *frmList)
 {
-    List *fl= frmList;
+    List *fl;
 
-    while(fl!=NIL) {
+    foreach(fl, frmList)
+    {
        RangeVar *r = lfirst(fl);
        RelExpr *baserel = r->relExpr;
-       RangeTblEntry *ent;
        char *relname = baserel->relname;
        char *refname = r->name;
-
-       if (refname==NULL) {
+       RangeTblEntry *rte;
+       
+       if (refname==NULL)
            refname = relname;
-       } else {
-           /*
-            * check whether refname exists already
-            */
-           if (RangeTablePosn(pstate->p_rtable, refname) != 0)
-               elog(WARN, "parser: range variable \"%s\" duplicated",
-                    refname);
-       }
 
-       ent = makeRangeTableEntry(relname, baserel->inh,
-                                 baserel->timeRange, refname);
        /*
-        * marks this entry to indicate it comes from the from clause. In
+        * marks this entry to indicate it comes from the FROM clause. In
         * SQL, the target list can only refer to range variables specified
         * in the from clause but we follow the more powerful POSTQUEL
         * semantics and automatically generate the range variable if not
@@ -802,10 +767,8 @@ parseFromClause(ParseState *pstate, List *frmList)
         * eg. select * from foo f where f.x = 1; will generate wrong answer
         *     if we expand * to foo.x.
         */
-       ent->inFromCl = true;
-
-       pstate->p_rtable = lappend(pstate->p_rtable, ent);      
-       fl= lnext(fl);
+       rte = addRangeTableEntry(pstate, relname, refname, baserel->inh, TRUE,
+                                 baserel->timeRange);
     }
 }
 
@@ -817,25 +780,23 @@ parseFromClause(ParseState *pstate, List *frmList)
 static void
 makeRangeTable(ParseState *pstate, char *relname, List *frmList)
 {
-    int x;
+    RangeTblEntry *rte;
 
     parseFromClause(pstate, frmList);
 
     if (relname == NULL)
        return;
     
-    if (RangeTablePosn(pstate->p_rtable, relname) < 1) {
-       RangeTblEntry *ent;
-
-       ent = makeRangeTableEntry(relname, FALSE, NULL, relname);
-       pstate->p_rtable = lappend(pstate->p_rtable, ent);
-    }
-    x = RangeTablePosn(pstate->p_rtable, relname);
-    if (pstate->p_current_rel != NULL)
-        heap_close(pstate->p_current_rel);
-    pstate->p_current_rel = heap_openr(VarnoGetRelname(pstate,x));
-    if (pstate->p_current_rel == NULL)
-       elog(WARN,"invalid relation name");
+    if (refnameRangeTablePosn(pstate->p_rtable, relname) < 1)
+       rte = addRangeTableEntry(pstate, relname, relname, FALSE, FALSE, NULL);
+    else
+       rte = refnameRangeTableEntry(pstate->p_rtable, relname);
+
+    pstate->p_target_rangetblentry = rte;
+    Assert(pstate->p_target_relation == NULL);
+    pstate->p_target_relation = heap_open(rte->relid);
+    Assert(pstate->p_target_relation != NULL);
+       /* will close relation later */
 }
 
 /*
@@ -897,7 +858,7 @@ expandAllTables(ParseState *pstate)
     List *rt, *rtable;
 
     rtable = pstate->p_rtable;
-    if (pstate->p_query_is_rule) {
+    if (pstate->p_is_rule) {
        /*
         * skip first two entries, "*new*" and "*current*"
         */
@@ -927,16 +888,16 @@ expandAllTables(ParseState *pstate)
 
     foreach(rt, legit_rtable) {
        RangeTblEntry *rte = lfirst(rt);
-       char *rt_name= rte->refname;    /* use refname here so that we
-                                          refer to the right entry */
        List *temp = target;
        
        if(temp == NIL )
-           target = expandAll(pstate, rt_name, &pstate->p_last_resno);
+           target = expandAll(pstate, rte->relname, rte->refname,
+                                                       &pstate->p_last_resno);
        else {
            while (temp != NIL && lnext(temp) != NIL)
                temp = lnext(temp);
-           lnext(temp) = expandAll(pstate, rt_name, &pstate->p_last_resno);
+           lnext(temp) = expandAll(pstate, rte->relname, rte->refname,
+                                                       &pstate->p_last_resno);
        }
     }
     return target;
@@ -976,96 +937,46 @@ figureColname(Node *expr, Node *resval)
  *****************************************************************************/
 
 /*
- * makeTargetList -
- *    turn a list of column names and expressions (in the same order) into
- *    a target list (used exclusively for inserts)
+ * makeTargetNames -
+ *    generate a list of column names if not supplied or
+ *    test supplied column names to make sure they are in target table
+ *    (used exclusively for inserts)
  */
 static List *
-makeTargetList(ParseState *pstate, List *cols, List *exprs)
+makeTargetNames(ParseState *pstate, List *cols)
 {
-    List *tlist, *tl=NULL;
-    if (cols != NIL) {
-       /* has to transform colElem too (opt_indirection can be exprs) */
-       while(cols!=NIL) {
-           ResTarget *res = makeNode(ResTarget);
-           Ident *id = lfirst(cols);
-           /* Id opt_indirection */
-           res->name = id->name;
-           res->indirection = id->indirection;
-           if (exprs == NIL) {
-               elog(WARN, "insert: number of expressions less than columns");
-           }else {
-               res->val = (Node *)lfirst(exprs);
-           }
-           if (tl==NIL) {
-               tlist = tl = lcons(res, NIL);
-           }else {
-               lnext(tl) = lcons(res,NIL);
-               tl = lnext(tl);
-           }
-           cols = lnext(cols);
-           exprs = lnext(exprs);
-       }
-       if (cols != NIL) {
-           elog(WARN, "insert: number of columns more than expressions");
-       }
-    }else {
-       bool has_star = false;
+    List *tl=NULL;
+
+       /* Generate ResTarget if not supplied */
+       
+    if (cols == NIL) {
+       int numcol;
+       int i;
+       AttributeTupleForm *attr = pstate->p_target_relation->rd_att->attrs;
        
-       if (exprs==NIL)
-           return NIL;
-       if (IsA(lfirst(exprs),Attr)) {
-           Attr *att = lfirst(exprs);
-
-           if ((att->relname!=NULL && !strcmp(att->relname,"*")) ||
-               (att->attrs!=NIL && !strcmp(strVal(lfirst(att->attrs)),"*")))
-               has_star = true;
-       }
-       if (has_star) {
-           /*
-            * right now, these better be 'relname.*' or '*' (this can happen
-            * in eg. insert into tenk2 values (tenk1.*); or
-            *        insert into tenk2 select * from tenk1;
-            */
-           while(exprs!=NIL) {
-               ResTarget *res = makeNode(ResTarget);
-               res->name = NULL;
-               res->indirection = NULL;
-               res->val = (Node *)lfirst(exprs);
-               if (tl==NIL) {
-                   tlist = tl = lcons(res, NIL);
-               }else {
-                   lnext(tl) = lcons(res,NIL);
-                   tl = lnext(tl);
-               }
-               exprs = lnext(exprs);
-           }
-       } else {
-           Relation insertRel = pstate->p_current_rel;
-           int numcol;
-           int i;
-           AttributeTupleForm *attr = insertRel->rd_att->attrs;
-           
-           numcol = Min(length(exprs), insertRel->rd_rel->relnatts);
-           for(i=0; i < numcol; i++) {
-               ResTarget *res = makeNode(ResTarget);
-
-               res->name = palloc(NAMEDATALEN+1);
-               strncpy(res->name, attr[i]->attname.data, NAMEDATALEN);
-               res->name[NAMEDATALEN]='\0';
-               res->indirection = NULL;
-               res->val = (Node *)lfirst(exprs);
-               if (tl==NIL) {
-                   tlist = tl = lcons(res, NIL);
-               }else {
-                   lnext(tl) = lcons(res,NIL);
-                   tl = lnext(tl);
-               }
-               exprs = lnext(exprs);
+       numcol = pstate->p_target_relation->rd_rel->relnatts;
+       for(i=0; i < numcol; i++) {
+           Ident *id = makeNode(Ident);
+
+           id->name = palloc(NAMEDATALEN+1);
+           strncpy(id->name, attr[i]->attname.data, NAMEDATALEN);
+           id->name[NAMEDATALEN]='\0';
+           id->indirection = NIL;
+           id->isRel = false;
+           if (tl == NIL)
+               cols = tl = lcons(id, NIL);
+           else {
+               lnext(tl) = lcons(id,NIL);
+               tl = lnext(tl);
            }
        }
     }
-    return tlist;
+    else
+        foreach(tl, cols)
+                       /* elog on failure */
+        (void)varattno(pstate->p_target_relation,((Ident *)lfirst(tl))->name);
+
+    return cols;
 }
 
 /*
@@ -1073,13 +984,10 @@ makeTargetList(ParseState *pstate, List *cols, List *exprs)
  *    turns a list of ResTarget's into a list of TargetEntry's
  */
 static List *
-transformTargetList(ParseState *pstate, 
-                   List *targetlist,
-                   bool isInsert,
-                   bool isUpdate)
+transformTargetList(ParseState *pstate, List *targetlist)
 {
     List *p_target= NIL;
-    List *temp = NIL;
+    List *tail_p_target = NIL;
 
     while(targetlist != NIL) {
        ResTarget *res= (ResTarget *)lfirst(targetlist);
@@ -1092,8 +1000,9 @@ transformTargetList(ParseState *pstate,
            int type_len;
            char *identname;
            char *resname;
-
+           
            identname = ((Ident*)res->val)->name;
+           handleTargetColname(pstate, &res->name, NULL, res->name);
            expr = transformExpr(pstate, (Node*)res->val);
            type_id = exprType(expr);
            type_len = tlen(get_id_type(type_id));
@@ -1115,11 +1024,9 @@ transformTargetList(ParseState *pstate,
        case T_A_Expr: {
            Node *expr = transformExpr(pstate, (Node *)res->val);
 
-           if (isInsert && res->name==NULL)
-               elog(WARN, "Sorry, have to specify the column list");
-
+           handleTargetColname(pstate, &res->name, NULL, NULL);
            /* note indirection has not been transformed */
-           if (isInsert && res->indirection!=NIL) {
+           if (pstate->p_is_insert && res->indirection!=NIL) {
                /* this is an array assignment */
                char *val;
                char *str, *save_str;
@@ -1160,7 +1067,7 @@ transformTargetList(ParseState *pstate,
                    i++;
                }
                sprintf(str, "=%s", val);
-               rd = pstate->p_current_rel;
+               rd = pstate->p_target_relation;
                Assert(rd != NULL);
                resdomno = varattno(rd, res->name);
                ndims = att_attnelems(rd, resdomno);
@@ -1171,8 +1078,7 @@ transformTargetList(ParseState *pstate,
                constval->val.str = save_str;
                tent = make_targetlist_expr(pstate, res->name,
                                            (Node*)make_const(constval),
-                                           NULL,
-                                           (isInsert||isUpdate));
+                                           NULL);
                pfree(save_str);
            } else {
                char *colname= res->name;
@@ -1192,9 +1098,9 @@ transformTargetList(ParseState *pstate,
                        ilist = lnext(ilist);
                    }
                }
-               tent = make_targetlist_expr(pstate, colname, expr, 
-                                           res->indirection,
-                                           (isInsert||isUpdate));
+               res->name = colname;
+               tent = make_targetlist_expr(pstate, res->name, expr, 
+                                           res->indirection);
            }
            break;
        }
@@ -1207,7 +1113,6 @@ transformTargetList(ParseState *pstate,
            char *resname;
            Resdom *resnode;
            List *attrs = att->attrs;
-               
 
            /*
             * Target item is a single '*', expand all tables
@@ -1231,19 +1136,20 @@ transformTargetList(ParseState *pstate,
             */
            attrname = strVal(lfirst(att->attrs));
            if (att->attrs!=NIL && !strcmp(attrname,"*")) {
-               /* temp is the target list we're building in the while
+               /* tail_p_target is the target list we're building in the while
                 * loop. Make sure we fix it after appending more nodes.
                 */
-               if (temp == NIL) {
-                   p_target = temp =
-                       expandAll(pstate, att->relname, &pstate->p_last_resno);
+               if (tail_p_target == NIL) {
+                   p_target = tail_p_target = expandAll(pstate, att->relname,
+                                       att->relname, &pstate->p_last_resno);
                } else {
-                   lnext(temp) =
-                       expandAll(pstate, att->relname, &pstate->p_last_resno);
+                   lnext(tail_p_target) =
+                       expandAll(pstate, att->relname, att->relname,
+                                                       &pstate->p_last_resno);
                }
-               while(lnext(temp)!=NIL)
-                   temp = lnext(temp); /* make sure we point to the last
-                                          target entry */
+               while(lnext(tail_p_target)!=NIL)
+                       /* make sure we point to the last target entry */
+                   tail_p_target = lnext(tail_p_target);
                /*
                 * skip the rest of the while loop
                 */
@@ -1256,6 +1162,7 @@ transformTargetList(ParseState *pstate,
             * Target item is fully specified: ie. relation.attribute
             */
            result = handleNestedDots(pstate, att, &pstate->p_last_resno);
+           handleTargetColname(pstate, &res->name, att->relname, attrname);
            if (att->indirection != NIL) {
                List *ilist = att->indirection;
                while (ilist!=NIL) {
@@ -1268,6 +1175,7 @@ transformTargetList(ParseState *pstate,
            }
            type_id = exprType(result);
            type_len = tlen(get_id_type(type_id));
+               /* move to last entry */
            while(lnext(attrs)!=NIL)
                attrs=lnext(attrs);
            resname = (res->name) ? res->name : strVal(lfirst(attrs));
@@ -1289,30 +1197,30 @@ transformTargetList(ParseState *pstate,
            break;
        }
 
-       if (p_target==NIL) {
-           p_target = temp = lcons(tent, NIL);
+       if (p_target == NIL) {
+           p_target = tail_p_target = lcons(tent, NIL);
        }else {
-           lnext(temp) = lcons(tent, NIL);
-           temp = lnext(temp);
+           lnext(tail_p_target) = lcons(tent, NIL);
+           tail_p_target = lnext(tail_p_target);
        }
        targetlist = lnext(targetlist);
     }
+
     return p_target;
 }
 
 
 /*
  * make_targetlist_expr -
- *    make a TargetEntry
+ *    make a TargetEntry from an expression
  *
  * arrayRef is a list of transformed A_Indices
  */
 static TargetEntry *
 make_targetlist_expr(ParseState *pstate,
-                    char *name,
+                    char *colname,
                     Node *expr,
-                    List *arrayRef,
-                    bool ResdomNoIsAttrNo)
+                    List *arrayRef)
 {
      int type_id, type_len, attrtype, attrlen;
      int resdomno;
@@ -1333,16 +1241,17 @@ make_targetlist_expr(ParseState *pstate,
      type_len = tlen(get_id_type(type_id));
 
      /* I have no idea what the following does! */
-     if (ResdomNoIsAttrNo) {
+     /* It appears to process target columns that will be receiving results */
+     if (pstate->p_is_insert||pstate->p_is_update) {
          /*
           * append or replace query -- 
           * append, replace work only on one relation,
           * so multiple occurence of same resdomno is bogus
           */
-         rd = pstate->p_current_rel;
+         rd = pstate->p_target_relation;
          Assert(rd != NULL);
-         resdomno = varattno(rd,name);
-         attrisset = varisset(rd,name);
+         resdomno = varattno(rd,colname);
+         attrisset = varisset(rd,colname);
          attrtype = att_typeid(rd,resdomno);
          if ((arrayRef != NIL) && (lfirst(arrayRef) == NIL))
               attrtype = GetArrayElementType(attrtype);
@@ -1388,13 +1297,14 @@ make_targetlist_expr(ParseState *pstate,
                         lfirst(expr) = lispInteger (FLOAT4OID);
                     else
                         elog(WARN, "unequal type in tlist : %s \n",
-                             name));
+                             colname));
               }
          
          Input_is_string = false;
          Input_is_integer = false;
          Typecast_ok = true;
 #endif
+
          if (attrtype != type_id) {
              if (IsA(expr,Const)) {
                  /* try to cast the constant */
@@ -1415,18 +1325,12 @@ make_targetlist_expr(ParseState *pstate,
              } else {
                  /* currently, we can't handle casting of expressions */
                  elog(WARN, "parser: attribute '%s' is of type '%.*s' but expression is of type '%.*s'",
-                      name,
+                      colname,
                       NAMEDATALEN, get_id_typname(attrtype),
                       NAMEDATALEN, get_id_typname(type_id));
              }
          }
 
-         if (intMember(resdomno, pstate->p_target_resnos)) {
-              elog(WARN,"two or more occurrences of same attr");
-         } else {
-              pstate->p_target_resnos = lconsi(resdomno,
-                                                pstate->p_target_resnos);
-         }
          if (arrayRef != NIL) {
               Expr *target_expr;
               Attr *att = makeNode(Attr);
@@ -1435,7 +1339,7 @@ make_targetlist_expr(ParseState *pstate,
               List *lowerIndexpr = NIL;
 
               att->relname = pstrdup(RelationGetRelationName(rd)->data);
-              att->attrs = lcons(makeString(name), NIL);
+              att->attrs = lcons(makeString(colname), NIL);
               target_expr = (Expr*)handleNestedDots(pstate, att,
                                                     &pstate->p_last_resno);
               while(ar!=NIL) {
@@ -1471,7 +1375,7 @@ make_targetlist_expr(ParseState *pstate,
      resnode = makeResdom((AttrNumber)resdomno,
                          (Oid) attrtype,
                          (Size) attrlen,
-                         name, 
+                         colname, 
                          (Index)0,
                          (Oid)0,
                          0);
@@ -1524,14 +1428,13 @@ transformWhereClause(ParseState *pstate, Node *a_expr)
  *
  */
 static Resdom *
-find_tl_elt(ParseState *pstate, char *range, char *varname, List *tlist)
+find_tl_elt(ParseState *pstate, char *refname, char *colname, List *tlist)
 {
     List *i;
     int real_rtable_pos;
 
-    if(range) {
-       real_rtable_pos = RangeTablePosn(pstate->p_rtable, range);
-    }
+    if(refname)
+       real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable, refname);
 
     foreach(i, tlist) {
        TargetEntry *target = (TargetEntry *)lfirst(i);
@@ -1540,8 +1443,8 @@ find_tl_elt(ParseState *pstate, char *range, char *varname, List *tlist)
        char *resname = resnode->resname;
        int test_rtable_pos = var->varno;
 
-       if (!strcmp(resname, varname)) {
-           if(range) {
+       if (!strcmp(resname, colname)) {
+           if(refname) {
                if(real_rtable_pos == test_rtable_pos) {
                    return (resnode);
                }
@@ -1979,7 +1882,8 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
     Oid funcid = (Oid)0;
     List *i = NIL;
     Node *first_arg= NULL;
-    char *relname, *oldname;
+    char *relname;
+    char *refname;
     Relation rd;
     Oid relid;
     int nargs;
@@ -2005,28 +1909,23 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
      ** type, then the function could be a projection.
      */
     if (length(fargs) == 1) {
+       
        if (nodeTag(first_arg)==T_Ident && ((Ident*)first_arg)->isRel) {
+           RangeTblEntry *rte;
            Ident *ident = (Ident*)first_arg;
 
            /*
             * first arg is a relation. This could be a projection.
             */
-           relname = ident->name;
-           if (RangeTablePosn(pstate->p_rtable, relname)== 0) {
-               RangeTblEntry *ent;
-
-               ent =
-                   makeRangeTableEntry(relname,
-                                       FALSE, NULL, relname);
-               pstate->p_rtable = lappend(pstate->p_rtable, ent);
-           }
-           oldname = relname;
-           relname = VarnoGetRelname(pstate, 
-                                     RangeTablePosn(pstate->p_rtable,
-                                                    oldname));
-           rd = heap_openr(relname);
-           relid = RelationGetRelationId(rd);
-           heap_close(rd);
+           refname = ident->name;
+
+           rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+           if (rte == NULL)
+               rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE,NULL);
+
+           relname = rte->relname;
+           relid = rte->relid;
+
            /* If the attr isn't a set, just make a var for it.  If
             * it is a set, treat it like a function and drop through.
             */
@@ -2035,7 +1934,7 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
 
                return
                    ((Node*)make_var(pstate,
-                                    oldname,
+                                    refname,
                                     funcname,
                                     &dummyTypeId));
            } else {
@@ -2064,10 +1963,10 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
                         tname(get_id_type(toid)));
                argrelid = typeid_get_relid(toid);
                /* A projection contains either an attribute name or the
-                * word "all".
+                * "*".
                 */
                if ((get_attnum(argrelid, funcname) == InvalidAttrNumber) 
-                   && strcmp(funcname, "all")) {
+                   && strcmp(funcname, "*")) {
                    elog(WARN, "Functions on sets are not yet supported");
                }
            }
@@ -2109,35 +2008,23 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
     nargs=0;
     foreach ( i , fargs ) {
        int vnum;
+       RangeTblEntry *rte;
        Node *pair = lfirst(i);
-           
+
        if (nodeTag(pair)==T_Ident && ((Ident*)pair)->isRel) {
            /*
             * a relation
             */
-           relname = ((Ident*)pair)->name;
-                   
-           /* get the range table entry for the var node */
-           vnum = RangeTablePosn(pstate->p_rtable, relname);
-           if (vnum == 0) {
-               pstate->p_rtable =
-                   lappend(pstate->p_rtable ,
-                            makeRangeTableEntry(relname, FALSE,
-                                                NULL, relname));
-               vnum = RangeTablePosn (pstate->p_rtable, relname);
-           }
+           refname = ((Ident*)pair)->name;
                    
-           /*
-            *  We have to do this because the relname in the pair
-            *  may have been a range table variable name, rather
-            *  than a real relation name.
-            */
-           relname = VarnoGetRelname(pstate, vnum);
-                   
-           rd = heap_openr(relname);
-           relid = RelationGetRelationId(rd);
-           heap_close(rd);
-           
+           rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+           if (rte == NULL)
+               rte = addRangeTableEntry(pstate, refname, refname,
+                                               FALSE, FALSE, NULL);
+           relname = rte->relname;
+
+            vnum = refnameRangeTablePosn (pstate->p_rtable, rte->refname);
+          
            /*
             *  for func(relname), the param to the function
             *  is the tuple under consideration.  we build a special
@@ -2225,9 +2112,9 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
      * attribute of the set tuples.
      */
     if (attisset) {
-       if (!strcmp(funcname, "all")) {
+       if (!strcmp(funcname, "*")) {
            funcnode->func_tlist =
-               expandAll(pstate, (char*)relname, curr_resno);
+               expandAll(pstate, relname, refname, curr_resno);
        } else {
            funcnode->func_tlist = setup_tlist(funcname,argrelid);
            rettype = find_atttype(argrelid, funcname);
@@ -2258,55 +2145,6 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
     return(retval);
 }
 
-/*
- * returns (relname) if found, NIL if not a column
- */
-static char*
-ParseColumnName(ParseState *pstate, char *name, bool *isRelName)
-{
-    List *et;
-    Relation rd;
-    List *rtable;
-
-    /*
-     * see if it is a relation name. If so, leave it as it is
-     */
-    if (RangeTablePosn(pstate->p_rtable, name)!=0) {
-       *isRelName = TRUE;
-       return NULL;
-    }
-
-    if (pstate->p_query_is_rule) {
-       rtable = lnext(lnext(pstate->p_rtable));
-    } else {
-       rtable = pstate->p_rtable;
-    }
-    /*
-     * search each relation in the FROM list and see if we have a match
-     */
-    foreach(et, rtable) {
-       RangeTblEntry *rte = lfirst(et);
-       char *relname= rte->relname;
-        char *refname= rte->refname;
-       Oid relid;
-
-       rd= heap_openr(relname);
-       relid = RelationGetRelationId(rd);
-       heap_close(rd);
-       if (get_attnum(relid, name) != InvalidAttrNumber) {
-           /* found */
-           *isRelName = FALSE;
-           return refname;
-       }
-
-    }
-
-    /* attribute not found */
-    *isRelName = FALSE;
-    return NULL;
-}
-
-
 /*****************************************************************************
  *
  *****************************************************************************/
@@ -2365,9 +2203,8 @@ finalizeAggregates(ParseState *pstate, Query *qry)
     qry->qry_aggs =
        (Aggreg **)palloc(sizeof(Aggreg *) * qry->qry_numAgg);
     i = 0;
-    foreach(l, pstate->p_aggs) {
+    foreach(l, pstate->p_aggs)
        qry->qry_aggs[i++] = (Aggreg*)lfirst(l);
-    }
 }
 
 /*    
@@ -2390,30 +2227,26 @@ contain_agg_clause(Node *clause)
     else if (or_clause(clause)) {
        List *temp;
 
-       foreach (temp, ((Expr*)clause)->args) {
+       foreach (temp, ((Expr*)clause)->args)
            if (contain_agg_clause(lfirst(temp)))
                return TRUE;
-       }
        return FALSE;
     } else if (is_funcclause (clause)) {
        List *temp;
 
-       foreach(temp, ((Expr *)clause)->args) {
+       foreach(temp, ((Expr *)clause)->args)
            if (contain_agg_clause(lfirst(temp)))
                return TRUE;
-       }
        return FALSE;
     } else if (IsA(clause,ArrayRef)) {
        List *temp;
 
-       foreach(temp, ((ArrayRef*)clause)->refupperindexpr)  {
+       foreach(temp, ((ArrayRef*)clause)->refupperindexpr)
            if (contain_agg_clause(lfirst(temp)))
                return TRUE;
-       }
-       foreach(temp, ((ArrayRef*)clause)->reflowerindexpr) {
+       foreach(temp, ((ArrayRef*)clause)->reflowerindexpr)
            if (contain_agg_clause(lfirst(temp)))
                return TRUE;
-       }
        if (contain_agg_clause(((ArrayRef*)clause)->refexpr))
            return TRUE;
        if (contain_agg_clause(((ArrayRef*)clause)->refassgnexpr))
@@ -2459,10 +2292,9 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause)
     else if (IsA(expr,Expr)) {
        List *temp;
 
-       foreach (temp, ((Expr*)expr)->args) {
+       foreach (temp, ((Expr*)expr)->args)
            if (!exprIsAggOrGroupCol(lfirst(temp),groupClause))
                return FALSE;
-       }
        return TRUE;
     }
 
@@ -2510,5 +2342,3 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
     
     return;
 }
-
-
index a9b69e9fff8fcbcd56f5beb785fd943191936b89..0fd80f6ce1b664b0520c05623e656c34e43429e1 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.12 1996/09/20 08:34:14 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.13 1996/10/30 02:01:54 momjian Exp $
  *
  * HISTORY
  *    AUTHOR           DATE            MAJOR EVENT
@@ -124,7 +124,7 @@ static Node *makeA_Expr(int op, char *opname, Node *lexpr, Node *rexpr);
        tableElementList, OptInherit, definition,
        opt_with_func, def_args, def_name_list, func_argtypes, 
        oper_argtypes, OptStmtList, OptStmtBlock, opt_column_list, columnList,
-       exprList, sort_clause, sortby_list, index_params, 
+       sort_clause, sortby_list, index_params, 
        name_list, from_clause, from_list, opt_array_bounds, nest_array_bounds,
        expr_list, attrs, res_target_list, res_target_list2, def_list,
        opt_indirection, group_clause, groupby_list, explain_options
@@ -143,7 +143,7 @@ static Node *makeA_Expr(int op, char *opname, Node *lexpr, Node *rexpr);
 %type <typnam> Typename, typname, opt_type
 %type <coldef> columnDef
 %type <defelt> def_elem
-%type <node>   def_arg, columnElem, exprElem, where_clause, 
+%type <node>   def_arg, columnElem, where_clause, 
                a_expr, AexprConst, having_clause, groupby
 %type <value>  NumConst
 %type <attr>   event_object, attr
@@ -1244,17 +1244,17 @@ AppendStmt:  INSERT INTO relation_name opt_column_list insert_rest
                 }
        ;
 
-insert_rest: VALUES '(' exprList ')'
+insert_rest: VALUES '(' res_target_list2 ')'
                {
                    $$ = makeNode(AppendStmt);
-                   $$->exprs = $3;
+                   $$->targetList = $3;
                    $$->fromClause = NIL;
                    $$->whereClause = NULL;
                }
-       | SELECT exprList from_clause where_clause
+       | SELECT res_target_list2 from_clause where_clause
                {
                    $$ = makeNode(AppendStmt);
-                   $$->exprs = $2;
+                   $$->targetList = $2;
                    $$->fromClause = $3;
                    $$->whereClause = $4;
                }
@@ -1280,36 +1280,6 @@ columnElem: Id opt_indirection
                }
        ;
 
-exprList:  exprList ',' exprElem
-               { $$ = lappend($1, $3); }
-       | exprElem
-               { $$ = lcons($1, NIL); }
-
-       ;
-
-exprElem: a_expr 
-               {   $$ = (Node *)$1;  }
-       |  relation_name '.' '*'
-               {
-                   Attr *n = makeNode(Attr);
-                   n->relname = $1;
-                   n->paramNo = NULL;
-                   n->attrs = lcons(makeString("*"), NIL);
-                   n->indirection = NIL;
-                   $$ = (Node *)n;
-               }
-       |  '*'
-               {
-                   Attr *n = makeNode(Attr);
-                   n->relname = "*";
-                   n->paramNo = NULL;
-                   n->attrs = NIL;
-                   n->indirection = NIL;
-                   $$ = (Node *)n;
-               }
-       ;
-
-
 /*****************************************************************************
  *
  *     QUERY:
index 81480b1d1f0562868b3c1bf4c6e6d14fc6ebc42d..179186d5d70d56342b39f889fc7a3dacdec7abb4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.4 1996/08/28 22:50:24 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.5 1996/10/30 02:01:59 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 Oid *param_type_info;
 int pfunc_num_args;
 
-extern int Quiet;
+/* given refname, return a pointer to the range table entry */
+RangeTblEntry *
+refnameRangeTableEntry(List *rtable, char *refname)
+{
+    List *temp;
+    
+    foreach(temp, rtable) {
+       RangeTblEntry *rte = lfirst(temp);
 
+       if (!strcmp(rte->refname, refname))
+           return rte;
+    }
+    return NULL;
+}
 
-/* given range variable, return id of variable; position starts with 1 */
+/* given refname, return id of variable; position starts with 1 */
 int
-RangeTablePosn(List *rtable, char *rangevar)
+refnameRangeTablePosn(List *rtable, char *refname)
 {
     int index;
     List *temp;
     
     index = 1;
-/*    temp = pstate->p_rtable; */
-    temp = rtable;
-    while (temp != NIL) {
-       RangeTblEntry *rt_entry = lfirst(temp);
+    foreach(temp, rtable) {
+       RangeTblEntry *rte = lfirst(temp);
 
-       if (!strcmp(rt_entry->refname, rangevar))
+       if (!strcmp(rte->refname, refname))
            return index;
-
-       temp = lnext(temp);
        index++;
     }
     return(0);
 }
 
-char*
-VarnoGetRelname(ParseState *pstate, int vnum)
+/*
+ * returns range entry if found, else NULL
+ */
+RangeTblEntry *
+colnameRangeTableEntry(ParseState *pstate, char *colname)
 {
-    int i;
-    List *temp = pstate->p_rtable;
-    for( i = 1; i < vnum ; i++) 
-       temp = lnext(temp);
-    return(((RangeTblEntry*)lfirst(temp))->relname);
+    List *et;
+    List *rtable;
+    RangeTblEntry *rte_result;
+
+    if (pstate->p_is_rule)
+       rtable = lnext(lnext(pstate->p_rtable));
+    else
+       rtable = pstate->p_rtable;
+
+    rte_result = NULL;
+    foreach(et, rtable) {
+       RangeTblEntry *rte = lfirst(et);
+
+               /* only entries on outer(non-function?) scope */
+       if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
+           continue;
+
+       if (get_attnum(rte->relid, colname) != InvalidAttrNumber) {
+           if (rte_result != NULL) {
+               if (!pstate->p_is_insert ||
+                   rte != pstate->p_target_rangetblentry)
+               elog(WARN, "Column %s is ambiguous", colname);
+           }
+           else rte_result = rte;
+       }
+    }
+    return rte_result;
 }
 
-
+/*
+ * put new entry in pstate p_rtable structure, or return pointer
+ * if pstate null
+*/
 RangeTblEntry *
-makeRangeTableEntry(char *relname,
-                   bool inh,
-                   TimeRange *timeRange,
-                   char *refname)
+addRangeTableEntry(ParseState *pstate,
+                   char *relname,
+                   char *refname,
+                   bool inh, bool inFromCl,
+                   TimeRange *timeRange)
 {
     Relation relation;
-    RangeTblEntry *ent = makeNode(RangeTblEntry);
+    RangeTblEntry *rte = makeNode(RangeTblEntry);
 
-    ent->relname = pstrdup(relname);
-    ent->refname = refname;
+    if (pstate != NULL &&
+       refnameRangeTableEntry(pstate->p_rtable, refname) != NULL)
+       elog(WARN,"Table name %s specified more than once",refname);
+       
+    rte->relname = pstrdup(relname);
+    rte->refname = pstrdup(refname);
 
-    relation = heap_openr(ent->relname);
+    relation = heap_openr(relname);
     if (relation == NULL) {
        elog(WARN,"%s: %s",
             relname, ACL_NO_PRIV_WARNING);
@@ -99,18 +140,26 @@ makeRangeTableEntry(char *relname,
      *  or recursive (transitive closure)
      * [we don't support them all -- ay 9/94 ]
      */
-    ent->inh = inh;
+    rte->inh = inh;
 
-    ent->timeRange = timeRange;
+    rte->timeRange = timeRange;
     
     /* RelOID */
-    ent->relid = RelationGetRelationId(relation);
+    rte->relid = RelationGetRelationId(relation);
+
+    rte->archive = false;
+
+    rte->inFromCl = inFromCl;
 
     /*
      * close the relation we're done with it for now.
      */
+    if (pstate != NULL)
+       pstate->p_rtable = lappend(pstate->p_rtable, rte);
+
     heap_close(relation);
-    return ent;
+
+    return rte;
 }
 
 /*
@@ -119,65 +168,59 @@ makeRangeTableEntry(char *relname,
  *    assumes reldesc caching works
  */
 List *
-expandAll(ParseState* pstate, char *relname, int *this_resno)
+expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
 {
     Relation rdesc;
-    List *tall = NIL;
+    List *te_tail = NIL, *te_head = NIL;
     Var *varnode;
-    int i, maxattrs, first_resno;
-    int type_id, type_len, vnum;
-    char *physical_relname;
-    
-    first_resno = *this_resno;
-    
-    /* printf("\nExpanding %.*s.all\n", NAMEDATALEN, relname); */
-    vnum = RangeTablePosn(pstate->p_rtable, relname);
-    if ( vnum == 0 ) {
-       pstate->p_rtable = lappend(pstate->p_rtable,
-                                  makeRangeTableEntry(relname, FALSE, NULL,
-                                                      relname));
-       vnum = RangeTablePosn(pstate->p_rtable, relname);
-    }
-    
-    physical_relname = VarnoGetRelname(pstate, vnum);
+    int varattno, maxattrs;
+    int type_id, type_len;
+    RangeTblEntry *rte;
+   
+    rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+    if (rte == NULL)
+       rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE, NULL);
     
-    rdesc = heap_openr(physical_relname);
+    rdesc = heap_open(rte->relid);
     
     if (rdesc == NULL ) {
-       elog(WARN,"Unable to expand all -- heap_openr failed on %s",
-            physical_relname);
+       elog(WARN,"Unable to expand all -- heap_open failed on %s",
+            rte->refname);
        return NIL;
     }
     maxattrs = RelationGetNumberOfAttributes(rdesc);
     
-    for ( i = maxattrs-1 ; i > -1 ; --i ) {
+    for ( varattno = 0; varattno <= maxattrs-1 ; varattno++ ) {
        char *attrname;
-       TargetEntry *rte = makeNode(TargetEntry);
+       char *resname = NULL;
+       TargetEntry *te = makeNode(TargetEntry);
        
-       attrname = pstrdup ((rdesc->rd_att->attrs[i]->attname).data);
-       varnode = (Var*)make_var(pstate, relname, attrname, &type_id);
+       attrname = pstrdup ((rdesc->rd_att->attrs[varattno]->attname).data);
+       varnode = (Var*)make_var(pstate, refname, attrname, &type_id);
        type_len = (int)tlen(get_id_type(type_id));
 
+       handleTargetColname(pstate, &resname, refname, attrname);
+       if (resname != NULL)
+               attrname = resname;
+       
        /* Even if the elements making up a set are complex, the
         * set itself is not. */
        
-       rte->resdom = makeResdom((AttrNumber) i + first_resno, 
+       te->resdom = makeResdom((AttrNumber) (*this_resno)++,
                                 (Oid)type_id,
                                 (Size)type_len,
                                 attrname,
                                 (Index)0,
                                 (Oid)0,
                                 0);
-       rte->expr = (Node *)varnode;
-       tall = lcons(rte, tall);
+       te->expr = (Node *)varnode;
+       if (te_head == NIL)
+               te_head = te_tail = lcons(te, NIL);
+       else    te_tail = lappend(te_tail, te);
     }
     
-    /*
-     * Close the reldesc - we're done with it now
-     */
     heap_close(rdesc);
-    *this_resno = first_resno + maxattrs;
-    return(tall);
+    return(te_head);
 }
 
 TimeQual
@@ -385,27 +428,21 @@ find_atttype(Oid relid, char *attrname)
 
 
 Var *
-make_var(ParseState *pstate, char *relname, char *attrname, int *type_id)
+make_var(ParseState *pstate, char *refname, char *attrname, int *type_id)
 {
     Var *varnode;
     int vnum, attid, vartypeid;
     Relation rd;
-    
-    vnum = RangeTablePosn(pstate->p_rtable, relname);
-    
-    if (vnum == 0) {
-       pstate->p_rtable =
-           lappend(pstate->p_rtable,
-                    makeRangeTableEntry(relname, FALSE,
-                                        NULL, relname));
-       vnum = RangeTablePosn (pstate->p_rtable, relname);
-       relname = VarnoGetRelname(pstate, vnum);
-    } else {
-       relname = VarnoGetRelname(pstate, vnum);
-    }
-    
-    rd = heap_openr(relname);
-/*    relid = RelationGetRelationId(rd); */
+    RangeTblEntry *rte;
+
+    rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+    if (rte == NULL)
+       rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE, NULL);
+
+    vnum = refnameRangeTablePosn(pstate->p_rtable, refname);
+
+    rd = heap_open(rte->relid);
+
     attid =  nf_varattno(rd, (char *) attrname);
     if (attid == InvalidAttrNumber) 
        elog(WARN, "Invalid attribute %s\n", attrname);
@@ -413,9 +450,6 @@ make_var(ParseState *pstate, char *relname, char *attrname, int *type_id)
 
     varnode = makeVar(vnum, attid, vartypeid, vnum, attid);
 
-    /*
-     * close relation we're done with it now
-     */
     heap_close(rd);
 
     *type_id = vartypeid;
@@ -655,3 +689,76 @@ param_type(int t)
     return param_type_info[t-1];
 }
 
+/*
+ * handleTargetColname -
+ *    use column names from insert
+ */
+void
+handleTargetColname(ParseState *pstate, char **resname,
+                                       char *refname, char *colname)
+{
+    if (pstate->p_is_insert) {
+        if (pstate->p_insert_columns != NIL ) {
+            Ident *id = lfirst(pstate->p_insert_columns);
+            Assert(lfirst(pstate->p_insert_columns) != NIL);
+           *resname = id->name;
+            pstate->p_insert_columns = lnext(pstate->p_insert_columns);
+        }
+       else
+           elog(WARN, "insert: more expressions than target columns");
+    }
+    if (pstate->p_is_insert||pstate->p_is_update)
+        checkTargetTypes(pstate, *resname, refname, colname);
+}
+
+/*
+ * checkTargetTypes -
+ *    checks value and target column types
+ */
+void
+checkTargetTypes(ParseState *pstate, char *target_colname,
+                                       char *refname, char *colname)
+{
+    int attrtype_id, attrtype_target, resdomno_id, resdomno_target;
+    Relation rd;
+    RangeTblEntry *rte;
+    
+    if (target_colname == NULL || colname == NULL)
+       return;
+       
+    if (refname != NULL)
+       rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+    else {
+       rte = colnameRangeTableEntry(pstate, colname);
+       refname = rte->refname;
+    }
+
+    Assert(refname != NULL && rte != NULL);
+
+    Assert(rte != NULL);
+/*
+    if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry)
+       elog(WARN, "%s not available in this context", colname);
+*/
+    rd = heap_open(rte->relid);
+    Assert(RelationIsValid(rd));
+
+    resdomno_id = varattno(rd,colname);
+    attrtype_id = att_typeid(rd,resdomno_id);
+
+    resdomno_target = varattno(pstate->p_target_relation,target_colname);
+    attrtype_target = att_typeid(pstate->p_target_relation, resdomno_target);
+
+    if (attrtype_id != attrtype_target)
+       elog(WARN, "Type of %s does not match target column %s",
+           colname, target_colname);
+
+    if ((attrtype_id == BPCHAROID || attrtype_id == VARCHAROID) &&
+         rd->rd_att->attrs[resdomno_id-1]->attlen !=
+        pstate->p_target_relation->rd_att->attrs[resdomno_target-1]->attlen)
+       elog(WARN, "Length of %s does not match length of target column %s",
+           colname, target_colname);
+
+    heap_close(rd);
+}
+
index 6755644660652914fc1e28c190a6400e99233096..61e20dc2be99cba3094a8ed232ba66f3ef6ae72e 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.3 1996/10/19 04:49:29 scrappy Exp $
+ * $Id: parsenodes.h,v 1.4 1996/10/30 02:02:08 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -422,8 +422,7 @@ typedef struct AppendStmt {
     NodeTag            type;
     char               *relname;       /* relation to insert into */
     List               *cols;          /* names of the columns */
-    List               *exprs;         /* the expressions (same order as
-                                          the columns) */
+    List               *targetList;    /* the target list (of ResTarget) */
     List               *fromClause;    /* the from clause */
     Node               *whereClause;   /* qualifications */
 } AppendStmt;
index a897784c18df8b392ea99d360520902376b9cfc2..4854cecca3f62cbd3757b5bbd5223ee7c60c8b1a 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_state.h,v 1.3 1996/10/13 17:13:58 momjian Exp $
+ * $Id: parse_state.h,v 1.4 1996/10/30 02:02:13 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 /* state information used during parse analysis */
 typedef struct ParseState {
-    int        p_last_resno; 
-    List       *p_target_resnos;
-    Relation   p_current_rel;
+    int        p_last_resno;
     List       *p_rtable;
-    int        p_query_is_rule;
     int                p_numAgg;
     List       *p_aggs;
+    bool       p_is_insert;
+    List       *p_insert_columns;
+    bool       p_is_update;
+    bool       p_is_rule;
+    Relation   p_target_relation;
+    RangeTblEntry *p_target_rangetblentry;
 } ParseState;
 
 
index de69a44fbcfe03ef59899e318e3b2658ec798008..0d4ad38f4e46bd62df47d874e5963c0421cf39d6 100644 (file)
@@ -4761,7 +4761,7 @@ QUERY: CLOSE foo23;
 QUERY: CLOSE foo24;
 QUERY: CLOSE foo25;
 QUERY: END;
-QUERY: PURGE hash_f8_heap BEFORE 'now';                -- absolute time
+QUERY: PURGE hash_f8_heap BEFORE 'now';
 SELECT count(*) AS has_10002 FROM hash_f8_heap[,] h;
 QUERY: VACUUM hash_f8_heap;
 QUERY: SELECT count(*) AS has_10000 FROM hash_f8_heap[,] h;
@@ -4770,7 +4770,7 @@ has_10000
     10002
 (1 row)
 
-QUERY: PURGE hash_i4_heap AFTER '@ 1 second ago';      -- relative time
+QUERY: PURGE hash_i4_heap AFTER '@ 1 second ago';
 SELECT count(*) AS has_10002 FROM hash_i4_heap[,] h;
 QUERY: VACUUM hash_i4_heap;
 QUERY: SELECT count(*) AS has_10000 FROM hash_i4_heap[,] h;
index 046e49d474db3fa3d3a9e7593ff65f22e8d6a23f..68385b8e1f3df69964888db043b0ff11ca4abb05 100644 (file)
@@ -1,7 +1,7 @@
 --
 -- queries.source
 --
--- $Header: /cvsroot/pgsql/src/test/regress/Attic/queries.source,v 1.2 1996/10/07 02:33:25 momjian Exp $
+-- $Header: /cvsroot/pgsql/src/test/regress/Attic/queries.source,v 1.3 1996/10/30 02:02:39 momjian Exp $
 --
 -- The comments that contain sequences of UNIX commands generate the 
 -- desired output for the POSTQUEL statement(s).
@@ -721,7 +721,7 @@ SELECT '' AS three, f.f1, f.f1 * '-10' AS x FROM FLOAT4_TBL f
    WHERE f.f1 > '0.0';
 
 SELECT '' AS three, f.f1, f.f1 + '-10' AS x FROM FLOAT4_TBL f
-   WHERE f.f1 > '0.0'
+   WHERE f.f1 > '0.0';
 
 SELECT '' AS three, f.f1, f.f1 / '-10' AS x FROM FLOAT4_TBL f
    WHERE f.f1 > '0.0';
@@ -2195,7 +2195,8 @@ END;
 -- miss deleting a bunch of index tuples, which caused big problems when
 -- you dereferenced the tids and found garbage..
 --
-PURGE hash_f8_heap BEFORE 'now';               -- absolute time
+-- absolute time
+PURGE hash_f8_heap BEFORE 'now';
 
 SELECT count(*) AS has_10002 FROM hash_f8_heap[,] h;
 
@@ -2203,7 +2204,8 @@ VACUUM hash_f8_heap;
 
 SELECT count(*) AS has_10000 FROM hash_f8_heap[,] h;
 
-PURGE hash_i4_heap AFTER '@ 1 second ago';     -- relative time
+-- relative time
+PURGE hash_i4_heap AFTER '@ 1 second ago';
 
 SELECT count(*) AS has_10002 FROM hash_i4_heap[,] h;
 
index fb17ab7a721748bce8cf67d50739969bb9e24804..ccc52ff1c731997c0abf72483f2c45651de9729c 100755 (executable)
@@ -1,10 +1,12 @@
 #!/bin/sh
-# $Header: /cvsroot/pgsql/src/test/regress/Attic/regress.sh,v 1.1.1.1 1996/07/09 06:22:24 scrappy Exp $
+# $Header: /cvsroot/pgsql/src/test/regress/Attic/regress.sh,v 1.2 1996/10/30 02:02:41 momjian Exp $
 #
 if [ -d ./obj ]; then
        cd ./obj
 fi
 
+TZ="PST8PDT"; export TZ
+
 #FRONTEND=monitor
 FRONTEND="psql -n -e -q"