]> granicus.if.org Git - postgresql/commitdiff
Eliminate local inefficiencies in updateTargetListEntry, make_var, and
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 1 Nov 1999 05:06:21 +0000 (05:06 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 1 Nov 1999 05:06:21 +0000 (05:06 +0000)
make_const --- don't repeat cache searches that aren't needed.

src/backend/parser/analyze.c
src/backend/parser/parse_node.c
src/backend/parser/parse_target.c
src/include/parser/parse_target.h

index 08c209b2a5dd0a0876ebfa80c78d7ee1a988ea8c..2bd3a00b73e9656a52bc33124aaa4c056a60b670 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- *     $Id: analyze.c,v 1.121 1999/10/07 04:23:11 tgl Exp $
+ *     $Id: analyze.c,v 1.122 1999/11/01 05:06:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -253,6 +253,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
        Query      *qry = makeNode(Query);
        Node       *fromQual;
        List       *icolumns;
+       List       *attrnos;
+       List       *attnos;
+       int                     numuseratts;
        List       *tl;
        TupleDesc       rd_att;
 
@@ -333,9 +336,11 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
                pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
 
        /* Validate stmt->cols list, or build default list if no list given */
-       icolumns = makeTargetNames(pstate, stmt->cols);
+       icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
 
        /* Prepare non-junk columns for assignment to target table */
+       numuseratts = 0;
+       attnos = attrnos;
        foreach(tl, qry->targetList)
        {
                TargetEntry *tle = (TargetEntry *) lfirst(tl);
@@ -352,16 +357,30 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
                        resnode->resno = (AttrNumber) pstate->p_last_resno++;
                        continue;
                }
-               if (icolumns == NIL)
+               if (icolumns == NIL || attnos == NIL)
                        elog(ERROR, "INSERT has more expressions than target columns");
                id = (Ident *) lfirst(icolumns);
-               updateTargetListEntry(pstate, tle, id->name, id->indirection);
+               updateTargetListEntry(pstate, tle, id->name, lfirsti(attnos),
+                                                         id->indirection);
+               numuseratts++;
                icolumns = lnext(icolumns);
+               attnos = lnext(attnos);
        }
 
+       /*
+        * It is possible that the targetlist has fewer entries than were in
+        * the columns list.  We do not consider this an error (perhaps we
+        * should, if the columns list was explictly given?).  We must truncate
+        * the attrnos list to only include the attrs actually provided,
+        * else we will fail to apply defaults for them below.
+        */
+       if (icolumns != NIL)
+               attrnos = ltruncate(numuseratts, attrnos);
+
        /*
         * Add targetlist items to assign DEFAULT values to any columns that
         * have defaults and were not assigned to by the user.
+        *
         * XXX wouldn't it make more sense to do this further downstream,
         * after the rule rewriter?
         */
@@ -372,29 +391,20 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
                AttrDefault *defval = rd_att->constr->defval;
                int                     ndef = rd_att->constr->num_defval;
 
-               while (ndef-- > 0)
+               while (--ndef >= 0)
                {
-                       Form_pg_attribute thisatt = att[defval[ndef].adnum - 1];
-                       TargetEntry *te;
+                       AttrNumber              attrno = defval[ndef].adnum;
+                       Form_pg_attribute thisatt = att[attrno - 1];
+                       TargetEntry        *te;
 
-                       foreach(tl, qry->targetList)
-                       {
-                               TargetEntry *tle = (TargetEntry *) lfirst(tl);
-                               Resdom     *resnode = tle->resdom;
-
-                               if (resnode->resjunk)
-                                       continue;       /* ignore resjunk nodes */
-                               if (namestrcmp(&(thisatt->attname), resnode->resname) == 0)
-                                       break;
-                       }
-                       if (tl != NIL)          /* found TLE for this attr */
-                               continue;
+                       if (intMember((int) attrno, attrnos))
+                               continue;               /* there was a user-specified value */
                        /*
                         * No user-supplied value, so add a targetentry with DEFAULT expr
                         * and correct data for the target column.
                         */
                        te = makeTargetEntry(
-                               makeResdom(defval[ndef].adnum,
+                               makeResdom(attrno,
                                                   thisatt->atttypid,
                                                   thisatt->atttypmod,
                                                   pstrdup(nameout(&(thisatt->attname))),
@@ -405,7 +415,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
                         * Make sure the value is coerced to the target column type
                         * (might not be right type if it's not a constant!)
                         */
-                       updateTargetListEntry(pstate, te, te->resdom->resname, NIL);
+                       updateTargetListEntry(pstate, te, te->resdom->resname, attrno,
+                                                                 NIL);
                }
        }
 
@@ -1128,8 +1139,10 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
                if (origTargetList == NIL)
                        elog(ERROR, "UPDATE target count mismatch --- internal error");
                origTarget = (ResTarget *) lfirst(origTargetList);
-               updateTargetListEntry(pstate, tle,
-                                                         origTarget->name, origTarget->indirection);
+               updateTargetListEntry(pstate, tle, origTarget->name,
+                                                         attnameAttNum(pstate->p_target_relation,
+                                                                                       origTarget->name),
+                                                         origTarget->indirection);
                origTargetList = lnext(origTargetList);
        }
        if (origTargetList != NIL)
index 35fa858dc0888931da341c97d3d33af95bac520e..d4593a1357b3c1d30b939d4d393e902e8656ccb1 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.31 1999/08/23 23:48:39 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.32 1999/11/01 05:06:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -176,11 +176,16 @@ make_op(char *opname, Node *ltree, Node *rtree)
 }      /* make_op() */
 
 
+/*
+ * make_var
+ *             Build a Var node for an attribute identified by name
+ */
 Var *
 make_var(ParseState *pstate, Oid relid, char *refname,
                 char *attrname)
 {
-       Var                *varnode;
+       HeapTuple       tp;
+       Form_pg_attribute att_tup;
        int                     vnum,
                                attid;
        Oid                     vartypeid;
@@ -189,16 +194,19 @@ make_var(ParseState *pstate, Oid relid, char *refname,
 
        vnum = refnameRangeTablePosn(pstate, refname, &sublevels_up);
 
-       attid = get_attnum(relid, attrname);
-       if (attid == InvalidAttrNumber)
+       tp = SearchSysCacheTuple(ATTNAME,
+                                                        ObjectIdGetDatum(relid),
+                                                        PointerGetDatum(attrname),
+                                                        0, 0);
+       if (!HeapTupleIsValid(tp))
                elog(ERROR, "Relation %s does not have attribute %s",
                         refname, attrname);
-       vartypeid = get_atttype(relid, attid);
-       type_mod = get_atttypmod(relid, attid);
-
-       varnode = makeVar(vnum, attid, vartypeid, type_mod, sublevels_up);
+       att_tup = (Form_pg_attribute) GETSTRUCT(tp);
+       attid = att_tup->attnum;
+       vartypeid = att_tup->atttypid;
+       type_mod = att_tup->atttypmod;
 
-       return varnode;
+       return makeVar(vnum, attid, vartypeid, type_mod, sublevels_up);
 }
 
 /*
@@ -380,67 +388,73 @@ transformArraySubscripts(ParseState *pstate,
 }
 
 /*
- * make_const -
+ * make_const
  *
- * - takes a lispvalue, (as returned to the yacc routine by the lexer)
- *      extracts the type, and makes the appropriate type constant
- *      by invoking the (c-callable) lisp routine c-make-const
- *      via the lisp_call() mechanism
- *
- * eventually, produces a "const" lisp-struct as per nodedefs.cl
+ *     Convert a Value node (as returned by the grammar) to a Const node
+ *     of the "natural" type for the constant.  For strings we produce
+ *     a constant of type UNKNOWN ---- representation is the same as text,
+ *     but this indicates to later type resolution that we're not sure that
+ *     it should be considered text.
  */
 Const *
 make_const(Value *value)
 {
-       Type            tp;
        Datum           val;
+       Oid                     typeid;
+       int                     typelen;
+       bool            typebyval;
        Const      *con;
 
        switch (nodeTag(value))
        {
                case T_Integer:
-                       tp = typeidType(INT4OID);
                        val = Int32GetDatum(intVal(value));
+
+                       typeid = INT4OID;
+                       typelen = sizeof(int32);
+                       typebyval = true;
                        break;
 
                case T_Float:
                        {
                                float64         dummy;
 
-                               tp = typeidType(FLOAT8OID);
-
                                dummy = (float64) palloc(sizeof(float64data));
                                *dummy = floatVal(value);
 
                                val = Float64GetDatum(dummy);
+
+                               typeid = FLOAT8OID;
+                               typelen = sizeof(float64data);
+                               typebyval = false;
                        }
                        break;
 
                case T_String:
-                       tp = typeidType(UNKNOWNOID);            /* unknown for now, will
-                                                                                                * be type coerced */
                        val = PointerGetDatum(textin(strVal(value)));
+
+                       typeid = UNKNOWNOID; /* will be coerced later */
+                       typelen = -1;           /* variable len */
+                       typebyval = false;
                        break;
 
                case T_Null:
                default:
-                       {
-                               if (nodeTag(value) != T_Null)
-                                       elog(NOTICE, "make_const: unknown type %d\n", nodeTag(value));
+                       if (nodeTag(value) != T_Null)
+                               elog(NOTICE, "make_const: unknown type %d\n", nodeTag(value));
 
-                               /* null const */
-                               con = makeConst(0, 0, (Datum) NULL, true, false, false, false);
-                               return con;
-                       }
+                       /* return a null const */
+                       con = makeConst(0, 0, (Datum) NULL, true, false, false, false);
+                       return con;
        }
 
-       con = makeConst(typeTypeId(tp),
-                                       typeLen(tp),
+       con = makeConst(typeid,
+                                       typelen,
                                        val,
                                        false,
-                                       typeByVal(tp),
+                                       typebyval,
                                        false,          /* not a set */
-                                       false);
+                                       false);         /* not coerced */
 
        return con;
 }
index 48973f67d9b928a7532ab2688d4dd45076e661b4..a009bc5a77cc554ee847de2f78a9f3a9f4c9465e 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.46 1999/07/19 00:26:20 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.47 1999/11/01 05:06:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -162,12 +162,14 @@ transformTargetList(ParseState *pstate, List *targetlist)
  * pstate              parse state
  * tle                 target list entry to be modified
  * colname             target column name (ie, name of attribute to be assigned to)
+ * attrno              target attribute number
  * indirection subscripts for target column, if any
  */
 void
 updateTargetListEntry(ParseState *pstate,
                                          TargetEntry *tle,
                                          char *colname,
+                                         int attrno,
                                          List *indirection)
 {
        Oid                     type_id = exprType(tle->expr); /* type of value provided */
@@ -175,14 +177,12 @@ updateTargetListEntry(ParseState *pstate,
        int32           attrtypmod;
        Resdom     *resnode = tle->resdom;
        Relation        rd = pstate->p_target_relation;
-       int                     resdomno;
 
        Assert(rd != NULL);
-       resdomno = attnameAttNum(rd, colname);
-       if (resdomno <= 0)
+       if (attrno <= 0)
                elog(ERROR, "Cannot assign to system attribute '%s'", colname);
-       attrtype = attnumTypeId(rd, resdomno);
-       attrtypmod = rd->rd_att->attrs[resdomno - 1]->atttypmod;
+       attrtype = attnumTypeId(rd, attrno);
+       attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod;
 
        /*
         * If there are subscripts on the target column, prepare an
@@ -260,7 +260,7 @@ updateTargetListEntry(ParseState *pstate,
        resnode->restype = attrtype;
        resnode->restypmod = attrtypmod;
        resnode->resname = colname;
-       resnode->resno = (AttrNumber) resdomno;
+       resnode->resno = (AttrNumber) attrno;
 }
 
 
@@ -356,14 +356,17 @@ SizeTargetExpr(ParseState *pstate,
 
 
 /*
- * makeTargetNames -
+ * checkInsertTargets -
  *       generate a list of column names if not supplied or
  *       test supplied column names to make sure they are in target table.
+ *       Also return an integer list of the columns' attribute numbers.
  *       (used exclusively for inserts)
  */
 List *
-makeTargetNames(ParseState *pstate, List *cols)
+checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
 {
+       *attrnos = NIL;
+
        if (cols == NIL)
        {
                /*
@@ -382,6 +385,7 @@ makeTargetNames(ParseState *pstate, List *cols)
                        id->indirection = NIL;
                        id->isRel = false;
                        cols = lappend(cols, id);
+                       *attrnos = lappendi(*attrnos, i+1);
                }
        }
        else
@@ -394,17 +398,14 @@ makeTargetNames(ParseState *pstate, List *cols)
                foreach(tl, cols)
                {
                        char       *name = ((Ident *) lfirst(tl))->name;
-                       List       *nxt;
+                       int                     attrno;
 
                        /* Lookup column name, elog on failure */
-                       attnameAttNum(pstate->p_target_relation, name);
+                       attrno = attnameAttNum(pstate->p_target_relation, name);
                        /* Check for duplicates */
-                       foreach(nxt, lnext(tl))
-                       {
-                               if (strcmp(name, ((Ident *) lfirst(nxt))->name) == 0)
-                                       elog(ERROR, "Attribute '%s' specified more than once",
-                                                name);
-                       }
+                       if (intMember(attrno, *attrnos))
+                               elog(ERROR, "Attribute '%s' specified more than once", name);
+                       *attrnos = lappendi(*attrnos, attrno);
                }
        }
 
index c2babecb769d9e1b9b257fbc58420c157132db00..08cf389d72e61671edcb3a2c4a78e8489f22b42d 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_target.h,v 1.15 1999/07/19 00:26:18 tgl Exp $
+ * $Id: parse_target.h,v 1.16 1999/11/01 05:06:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,9 +20,11 @@ extern TargetEntry *transformTargetEntry(ParseState *pstate,
                                                                                 Node *node, Node *expr,
                                                                                 char *colname, bool resjunk);
 extern void updateTargetListEntry(ParseState *pstate, TargetEntry *tle,
-                                                                 char *colname, List *indirection);
+                                                                 char *colname, int attrno,
+                                                                 List *indirection);
 extern Node *CoerceTargetExpr(ParseState *pstate, Node *expr,
                                                          Oid type_id, Oid attrtype);
-extern List *makeTargetNames(ParseState *pstate, List *cols);
+extern List *checkInsertTargets(ParseState *pstate, List *cols,
+                                                               List **attrnos);
 
 #endif  /* PARSE_TARGET_H */