Make sure resdomno for update/insert match attribute number for
authorBruce Momjian
Tue, 25 Aug 1998 03:17:29 +0000 (03:17 +0000)
committerBruce Momjian
Tue, 25 Aug 1998 03:17:29 +0000 (03:17 +0000)
rewrite system.  Restructure parse_target to make it easier to
understand.

src/backend/parser/parse_clause.c
src/backend/parser/parse_target.c
src/include/parser/parse_target.h

index 98eecb319a01f66b8fcc930b4b5e8d347416cc07..47384994d792f7dc8307591c5fbfdfdc2f76a316 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.23 1998/08/05 04:49:09 scrappy Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.24 1998/08/25 03:17:26 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -272,14 +272,14 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
        switch(nodeTag(node))
        {
            case T_Attr: 
-               target_result = transformTargetIdent(pstate, node, makeNode(TargetEntry),
+               target_result = MakeTargetEntryIdent(pstate, node,
                                        &((Attr*)node)->relname, NULL,
                                        ((Attr*)node)->relname, TRUE);
                lappend(tlist, target_result);
                break;
 
            case T_Ident:
-               target_result = transformTargetIdent(pstate, node, makeNode(TargetEntry),
+               target_result = MakeTargetEntryIdent(pstate, node,
                                        &((Ident*)node)->name, NULL,
                                        ((Ident*)node)->name, TRUE);
                lappend(tlist, target_result);
@@ -294,7 +294,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
 
            case T_FuncCall:
            case T_A_Expr:
-               target_result = MakeTargetlistExpr(pstate, "resjunk", expr, FALSE, TRUE);
+               target_result = MakeTargetEntryExpr(pstate, "resjunk", expr, FALSE, TRUE);
                lappend(tlist, target_result);
                break;
 
index b54e1b6786dfb615d13fb61c0d305fbf55242eb7..ec9a578f1b286824f6284d8576d24cd2fbaec33b 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.22 1998/08/23 14:43:46 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.23 1998/08/25 03:17:28 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,7 +40,7 @@ SizeTargetExpr(ParseState *pstate,
               int32 attrtypmod);
 
 
-/* transformTargetIdent()
+/* MakeTargetEntryIdent()
  * Transforms an Ident Node to a Target Entry
  * Created this function to allow the ORDER/GROUP BY clause to be able 
  *  to construct a TargetEntry from an Ident.
@@ -52,13 +52,12 @@ SizeTargetExpr(ParseState *pstate,
  * - thomas 1998-06-02
  */
 TargetEntry *
-transformTargetIdent(ParseState *pstate,
+MakeTargetEntryIdent(ParseState *pstate,
 #if FALSE
                     Ident *ident,
 #else
                     Node *node,
 #endif
-                    TargetEntry *tent,
                     char **resname,
                     char *refname,
                     char *colname,
@@ -66,7 +65,7 @@ transformTargetIdent(ParseState *pstate,
 {
    Node   *expr = NULL;
    Oid     attrtype_target;
-
+   TargetEntry *tent = makeNode(TargetEntry);
 
    if (pstate->p_is_insert)
    {
@@ -93,6 +92,7 @@ transformTargetIdent(ParseState *pstate,
 
        target_colname = *resname;
 
+       /* this looks strange to me, returning an empty TargetEntry bjm 1998/08/24 */
        if (target_colname == NULL || colname == NULL)
            return (tent);
 
@@ -115,7 +115,7 @@ transformTargetIdent(ParseState *pstate,
        attrtypmod_target = get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target);
 
 #ifdef PARSEDEBUG
-printf("transformTargetIdent- transform type %d to %d\n",
+printf("MakeTargetEntryIdent- transform type %d to %d\n",
  attrtype_id, attrtype_target);
 #endif
        if ((attrtype_id != attrtype_target)
@@ -125,7 +125,7 @@ printf("transformTargetIdent- transform type %d to %d\n",
            {
                expr = coerce_type(pstate, node, attrtype_id, attrtype_target);
                expr = transformExpr(pstate, expr, EXPR_COLUMN_FIRST);
-               tent = MakeTargetlistExpr(pstate, *resname, expr, FALSE, FALSE);
+               tent = MakeTargetEntryExpr(pstate, *resname, expr, FALSE, FALSE);
                expr = tent->expr;
            }
            else
@@ -155,7 +155,7 @@ printf("transformTargetIdent- transform type %d to %d\n",
        name = ((*resname != NULL)? *resname: colname);
 
 #ifdef PARSEDEBUG
-printf("transformTargetIdent- call transformIdent()\n");
+printf("MakeTargetEntryIdent- call transformIdent()\n");
 #endif
 #if FALSE
        expr = transformIdent(pstate, (Node *) ident, EXPR_COLUMN_FIRST);
@@ -170,7 +170,7 @@ printf("transformTargetIdent- call transformIdent()\n");
            type_mod = -1;
 
 #ifdef PARSEDEBUG
-printf("transformTargetIdent- attrtype_target = %d; type_mod = %d\n", attrtype_target, type_mod);
+printf("MakeTargetEntryIdent- attrtype_target = %d; type_mod = %d\n", attrtype_target, type_mod);
 #endif
 
        tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
@@ -184,10 +184,10 @@ printf("transformTargetIdent- attrtype_target = %d; type_mod = %d\n", attrtype_t
    }
 
    return (tent);
-} /* transformTargetIdent() */
+} /* MakeTargetEntryIdent() */
 
 
-/* MakeTargetlistExpr()
+/* MakeTargetEntryExpr()
  * Make a TargetEntry from an expression.
  * arrayRef is a list of transformed A_Indices.
  *
@@ -200,7 +200,7 @@ printf("transformTargetIdent- attrtype_target = %d; type_mod = %d\n", attrtype_t
  * -  [email protected] 1998-07-31 
  */
 TargetEntry *
-MakeTargetlistExpr(ParseState *pstate,
+MakeTargetEntryExpr(ParseState *pstate,
                     char *colname,
                     Node *expr,
                     List *arrayRef,
@@ -213,11 +213,10 @@ MakeTargetlistExpr(ParseState *pstate,
    int         resdomno;
    Relation    rd;
    bool        attrisset;
-   TargetEntry *tent;
    Resdom     *resnode;
 
    if (expr == NULL)
-       elog(ERROR, "MakeTargetlistExpr: invalid use of NULL expression");
+       elog(ERROR, "MakeTargetEntryExpr: invalid use of NULL expression");
 
    type_id = exprType(expr);
    if (nodeTag(expr) == T_Var)
@@ -225,7 +224,7 @@ MakeTargetlistExpr(ParseState *pstate,
    else
        type_mod = -1;
 
-   /* Processes target columns that will be receiving results */
+   /* Process target columns that will be receiving results */
    if (pstate->p_is_insert || pstate->p_is_update)
    {
        /*
@@ -266,7 +265,7 @@ MakeTargetlistExpr(ParseState *pstate,
            }
 
 #ifdef PARSEDEBUG
-printf("MakeTargetlistExpr: attrtypmod is %d\n", (int4) attrtypmod);
+printf("MakeTargetEntryExpr: attrtypmod is %d\n", (int4) attrtypmod);
 #endif
 
            /* Apparently going to a fixed-length string?
@@ -329,12 +328,199 @@ printf("MakeTargetlistExpr: attrtypmod is %d\n", (int4) attrtypmod);
                         (Oid) 0,
                         resjunk);
 
-   tent = makeTargetEntry(resnode, expr);
+   return makeTargetEntry(resnode, expr);
+} /* MakeTargetEntryExpr() */
 
-   return tent;
-} /* MakeTargetlistExpr() */
+/*
+ * MakeTargetlistComplex()
+ * pMake a TargetEntry from an complex node.
+ */
+static TargetEntry *
+MakeTargetEntryComplex(ParseState *pstate,
+                     ResTarget *res)
+{
+   Node    *expr = transformExpr(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
+
+#ifdef PARSEDEBUG
+printf("transformTargetList: decode T_Expr\n");
+#endif
+
+   handleTargetColname(pstate, &res->name, NULL, NULL);
+   /* note indirection has not been transformed */
+   if (pstate->p_is_insert && res->indirection != NIL)
+   {
+       /* this is an array assignment */
+       char       *val;
+       char       *str,
+                  *save_str;
+       List       *elt;
+       int         i = 0,
+                   ndims;
+       int         lindx[MAXDIM],
+                   uindx[MAXDIM];
+       int         resdomno;
+       Relation    rd;
+       Value      *constval;
+
+       if (exprType(expr) != UNKNOWNOID || !IsA(expr, Const))
+           elog(ERROR, "yyparse: string constant expected");
+
+       val = (char *) textout((struct varlena *)
+                          ((Const *) expr)->constvalue);
+       str = save_str = (char *) palloc(strlen(val) + MAXDIM * 25 + 2);
+       foreach(elt, res->indirection)
+       {
+           A_Indices  *aind = (A_Indices *) lfirst(elt);
+
+           aind->uidx = transformExpr(pstate, aind->uidx, EXPR_COLUMN_FIRST);
+           if (!IsA(aind->uidx, Const))
+               elog(ERROR, "Array Index for Append should be a constant");
+
+           uindx[i] = ((Const *) aind->uidx)->constvalue;
+           if (aind->lidx != NULL)
+           {
+               aind->lidx = transformExpr(pstate, aind->lidx, EXPR_COLUMN_FIRST);
+               if (!IsA(aind->lidx, Const))
+                   elog(ERROR, "Array Index for Append should be a constant");
+
+               lindx[i] = ((Const *) aind->lidx)->constvalue;
+           }
+           else
+               lindx[i] = 1;
+           if (lindx[i] > uindx[i])
+               elog(ERROR, "yyparse: lower index cannot be greater than upper index");
 
+           sprintf(str, "[%d:%d]", lindx[i], uindx[i]);
+           str += strlen(str);
+           i++;
+       }
+       sprintf(str, "=%s", val);
+       rd = pstate->p_target_relation;
+       Assert(rd != NULL);
+       resdomno = attnameAttNum(rd, res->name);
+       ndims = attnumAttNelems(rd, resdomno);
+       if (i != ndims)
+           elog(ERROR, "yyparse: array dimensions do not match");
+
+       constval = makeNode(Value);
+       constval->type = T_String;
+       constval->val.str = save_str;
+       return MakeTargetEntryExpr(pstate, res->name,
+                                 (Node *) make_const(constval),
+                                 NULL, FALSE);
+       pfree(save_str);
+   }
+   else
+   {
+       char       *colname = res->name;
 
+       /* this is not an array assignment */
+       if (colname == NULL)
+       {
+           /*
+            * if you're wondering why this is here, look
+            * at the yacc grammar for why a name can be
+            * missing. -ay
+            */
+           colname = FigureColname(expr, res->val);
+       }
+       if (res->indirection)
+       {
+           List       *ilist = res->indirection;
+
+           while (ilist != NIL)
+           {
+               A_Indices  *ind = lfirst(ilist);
+
+               ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
+               ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
+               ilist = lnext(ilist);
+           }
+       }
+       res->name = colname;
+       return MakeTargetEntryExpr(pstate, res->name, expr,
+                                 res->indirection, FALSE);
+   }
+}
+
+/*
+ * MakeTargetlistComplex()
+ * pMake a TargetEntry from an complex node.
+ */
+static TargetEntry *
+MakeTargetEntryAttr(ParseState *pstate,
+                  ResTarget    *res)
+{
+   Oid         type_id;
+   int32       type_mod;
+   Attr       *att = (Attr *) res->val;
+   Node       *result;
+   char       *attrname;
+   char       *resname;
+   Resdom     *resnode;
+   int         resdomno;
+   List       *attrs = att->attrs;
+   TargetEntry *tent;
+   Oid         relid;
+
+   attrname = strVal(lfirst(att->attrs));
+   /*
+    * Target item is fully specified: ie.
+    * relation.attribute
+    */
+#ifdef PARSEDEBUG
+printf("transformTargetList: decode T_Attr\n");
+#endif
+   result = ParseNestedFuncOrColumn(pstate, att, &pstate->p_last_resno, EXPR_COLUMN_FIRST);
+   handleTargetColname(pstate, &res->name, att->relname, attrname);
+   if (att->indirection != NIL)
+   {
+       List       *ilist = att->indirection;
+
+       while (ilist != NIL)
+       {
+           A_Indices  *ind = lfirst(ilist);
+
+           ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
+           ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
+           ilist = lnext(ilist);
+       }
+       result = (Node *) make_array_ref(result, att->indirection);
+   }
+   type_id = exprType(result);
+   if (nodeTag(result) == T_Var)
+       type_mod = ((Var *) result)->vartypmod;
+   else
+       type_mod = -1;
+   /* move to last entry */
+   while (lnext(attrs) != NIL)
+       attrs = lnext(attrs);
+   resname = (res->name) ? res->name : strVal(lfirst(attrs));
+   if (pstate->p_is_insert || pstate->p_is_update)
+   {
+       /*
+        * insert or update query -- insert, update work only on one
+        * relation, so multiple occurence of same resdomno is bogus
+        */
+       relid = refnameRangeTableEntry(pstate, att->relname)->relid;
+       resdomno = get_attnum(relid, attrname);
+   }
+   else
+       resdomno  = pstate->p_last_resno++;
+   resnode = makeResdom((AttrNumber) resdomno,
+                        (Oid) type_id,
+                        type_mod,
+                        resname,
+                        (Index) 0,
+                        (Oid) 0,
+                        0);
+   tent = makeNode(TargetEntry);
+   tent->resdom = resnode;
+   tent->expr = result;
+   return tent;
+}
+
+                     
 /* transformTargetList()
  * Turns a list of ResTarget's into a list of TargetEntry's.
  */
@@ -347,22 +533,19 @@ transformTargetList(ParseState *pstate, List *targetlist)
    while (targetlist != NIL)
    {
        ResTarget   *res = (ResTarget *) lfirst(targetlist);
-       TargetEntry *tent = makeNode(TargetEntry);
+       TargetEntry *tent = NULL;
 
        switch (nodeTag(res->val))
        {
            case T_Ident:
                {
                    char       *identname;
-#if FALSE
-                   char       *resname;
-#endif
 
 #ifdef PARSEDEBUG
 printf("transformTargetList: decode T_Ident\n");
 #endif
                    identname = ((Ident *) res->val)->name;
-                   tent = transformTargetIdent(pstate, (Node *)res->val, tent, &res->name, NULL, identname, FALSE);
+                   tent = MakeTargetEntryIdent(pstate, (Node *)res->val, &res->name, NULL, identname, FALSE);
                    break;
                }
            case T_ParamNo:
@@ -370,120 +553,14 @@ printf("transformTargetList: decode T_Ident\n");
            case T_A_Const:
            case T_A_Expr:
                {
-                   Node    *expr = transformExpr(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
-
-#ifdef PARSEDEBUG
-printf("transformTargetList: decode T_Expr\n");
-#endif
-                   handleTargetColname(pstate, &res->name, NULL, NULL);
-                   /* note indirection has not been transformed */
-                   if (pstate->p_is_insert && res->indirection != NIL)
-                   {
-                       /* this is an array assignment */
-                       char       *val;
-                       char       *str,
-                                  *save_str;
-                       List       *elt;
-                       int         i = 0,
-                                   ndims;
-                       int         lindx[MAXDIM],
-                                   uindx[MAXDIM];
-                       int         resdomno;
-                       Relation    rd;
-                       Value      *constval;
-
-                       if (exprType(expr) != UNKNOWNOID || !IsA(expr, Const))
-                           elog(ERROR, "yyparse: string constant expected");
-
-                       val = (char *) textout((struct varlena *)
-                                          ((Const *) expr)->constvalue);
-                       str = save_str = (char *) palloc(strlen(val) + MAXDIM * 25 + 2);
-                       foreach(elt, res->indirection)
-                       {
-                           A_Indices  *aind = (A_Indices *) lfirst(elt);
-
-                           aind->uidx = transformExpr(pstate, aind->uidx, EXPR_COLUMN_FIRST);
-                           if (!IsA(aind->uidx, Const))
-                               elog(ERROR, "Array Index for Append should be a constant");
-
-                           uindx[i] = ((Const *) aind->uidx)->constvalue;
-                           if (aind->lidx != NULL)
-                           {
-                               aind->lidx = transformExpr(pstate, aind->lidx, EXPR_COLUMN_FIRST);
-                               if (!IsA(aind->lidx, Const))
-                                   elog(ERROR, "Array Index for Append should be a constant");
-
-                               lindx[i] = ((Const *) aind->lidx)->constvalue;
-                           }
-                           else
-                               lindx[i] = 1;
-                           if (lindx[i] > uindx[i])
-                               elog(ERROR, "yyparse: lower index cannot be greater than upper index");
-
-                           sprintf(str, "[%d:%d]", lindx[i], uindx[i]);
-                           str += strlen(str);
-                           i++;
-                       }
-                       sprintf(str, "=%s", val);
-                       rd = pstate->p_target_relation;
-                       Assert(rd != NULL);
-                       resdomno = attnameAttNum(rd, res->name);
-                       ndims = attnumAttNelems(rd, resdomno);
-                       if (i != ndims)
-                           elog(ERROR, "yyparse: array dimensions do not match");
-
-                       constval = makeNode(Value);
-                       constval->type = T_String;
-                       constval->val.str = save_str;
-                       tent = MakeTargetlistExpr(pstate, res->name,
-                                                 (Node *) make_const(constval),
-                                                 NULL, FALSE);
-                       pfree(save_str);
-                   }
-                   else
-                   {
-                       char       *colname = res->name;
-
-                       /* this is not an array assignment */
-                       if (colname == NULL)
-                       {
-                           /*
-                            * if you're wondering why this is here, look
-                            * at the yacc grammar for why a name can be
-                            * missing. -ay
-                            */
-                           colname = FigureColname(expr, res->val);
-                       }
-                       if (res->indirection)
-                       {
-                           List       *ilist = res->indirection;
-
-                           while (ilist != NIL)
-                           {
-                               A_Indices  *ind = lfirst(ilist);
-
-                               ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
-                               ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
-                               ilist = lnext(ilist);
-                           }
-                       }
-                       res->name = colname;
-                       tent = MakeTargetlistExpr(pstate, res->name, expr,
-                                                 res->indirection, FALSE);
-                   }
+                   tent = MakeTargetEntryComplex(pstate, res);
                    break;
                }
            case T_Attr:
                {
-                   Oid         type_id;
-                   int32       type_mod;
-                   Attr       *att = (Attr *) res->val;
-                   Node       *result;
+                   bool expand_star = false;
                    char       *attrname;
-                   char       *resname;
-                   Resdom     *resnode;
-                   List       *attrs = att->attrs;
-
+                   Attr       *att = (Attr *) res->val;
                    /*
                     * Target item is a single '*', expand all tables (eg.
                     * SELECT * FROM emp)
@@ -494,16 +571,7 @@ printf("transformTargetList: decode T_Expr\n");
                            p_target = tail_p_target = ExpandAllTables(pstate);
                        else
                            lnext(tail_p_target) = ExpandAllTables(pstate);
-
-                       while (lnext(tail_p_target) != NIL)
-                           /* make sure we point to the last target entry */
-                           tail_p_target = lnext(tail_p_target);
-
-                       /*
-                        * skip rest of while loop
-                        */
-                       targetlist = lnext(targetlist);
-                       continue;
+                       expand_star = true;
                    }
 
                    /*
@@ -526,60 +594,24 @@ printf("transformTargetList: decode T_Expr\n");
                            lnext(tail_p_target) =
                                expandAll(pstate, att->relname, att->relname,
                                          &pstate->p_last_resno);
+                       expand_star = true;
+                   }
+                   if (expand_star)
+                   {
                        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
+                        * skip rest of while loop
                         */
                        targetlist = lnext(targetlist);
                        continue;
                    }
-
-
-                   /*
-                    * Target item is fully specified: ie.
-                    * relation.attribute
-                    */
-#ifdef PARSEDEBUG
-printf("transformTargetList: decode T_Attr\n");
-#endif
-                   result = ParseNestedFuncOrColumn(pstate, att, &pstate->p_last_resno, EXPR_COLUMN_FIRST);
-                   handleTargetColname(pstate, &res->name, att->relname, attrname);
-                   if (att->indirection != NIL)
+                   else
                    {
-                       List       *ilist = att->indirection;
-
-                       while (ilist != NIL)
-                       {
-                           A_Indices  *ind = lfirst(ilist);
-
-                           ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
-                           ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
-                           ilist = lnext(ilist);
-                       }
-                       result = (Node *) make_array_ref(result, att->indirection);
+                       tent = MakeTargetEntryAttr(pstate, res);
+                       break;
                    }
-                   type_id = exprType(result);
-                   if (nodeTag(result) == T_Var)
-                       type_mod = ((Var *) result)->vartypmod;
-                   else
-                       type_mod = -1;
-                   /* move to last entry */
-                   while (lnext(attrs) != NIL)
-                       attrs = lnext(attrs);
-                   resname = (res->name) ? res->name : strVal(lfirst(attrs));
-                   resnode = makeResdom((AttrNumber) pstate->p_last_resno++,
-                                        (Oid) type_id,
-                                        type_mod,
-                                        resname,
-                                        (Index) 0,
-                                        (Oid) 0,
-                                        0);
-                   tent->resdom = resnode;
-                   tent->expr = result;
-                   break;
                }
            default:
                /* internal error */
index b3fc020fde3fff39a720c2eb0881631718ab34ba..884fb299c477759f0c631e3e4d4ae912a1161f8d 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_target.h,v 1.9 1998/08/05 04:49:15 scrappy Exp $
+ * $Id: parse_target.h,v 1.10 1998/08/25 03:17:29 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,9 +25,8 @@
 extern List *transformTargetList(ParseState *pstate, List *targetlist);
 extern List *makeTargetNames(ParseState *pstate, List *cols);
 extern TargetEntry *
-transformTargetIdent(ParseState *pstate,
+MakeTargetEntryIdent(ParseState *pstate,
                     Node *node,
-                    TargetEntry *tent,
                     char **resname,
                     char *refname,
                     char *colname,
@@ -35,7 +34,7 @@ transformTargetIdent(ParseState *pstate,
 extern Node *
 CoerceTargetExpr(ParseState *pstate, Node *expr,
                 Oid type_id, Oid attrtype);
-TargetEntry * MakeTargetlistExpr(ParseState *pstate,
+TargetEntry * MakeTargetEntryExpr(ParseState *pstate,
                   char *colname,
                   Node *expr,
                   List *arrayRef,