Skip to content

Commit d40dbb7

Browse files
committed
Eliminate local inefficiencies in updateTargetListEntry, make_var, and
make_const --- don't repeat cache searches that aren't needed.
1 parent 249f6b4 commit d40dbb7

File tree

4 files changed

+106
-76
lines changed

4 files changed

+106
-76
lines changed

src/backend/parser/analyze.c

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Copyright (c) 1994, Regents of the University of California
77
*
8-
* $Id: analyze.c,v 1.121 1999/10/07 04:23:11 tgl Exp $
8+
* $Id: analyze.c,v 1.122 1999/11/01 05:06:21 tgl Exp $
99
*
1010
*-------------------------------------------------------------------------
1111
*/
@@ -253,6 +253,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
253253
Query *qry = makeNode(Query);
254254
Node *fromQual;
255255
List *icolumns;
256+
List *attrnos;
257+
List *attnos;
258+
int numuseratts;
256259
List *tl;
257260
TupleDesc rd_att;
258261

@@ -333,9 +336,11 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
333336
pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
334337

335338
/* Validate stmt->cols list, or build default list if no list given */
336-
icolumns = makeTargetNames(pstate, stmt->cols);
339+
icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
337340

338341
/* Prepare non-junk columns for assignment to target table */
342+
numuseratts = 0;
343+
attnos = attrnos;
339344
foreach(tl, qry->targetList)
340345
{
341346
TargetEntry *tle = (TargetEntry *) lfirst(tl);
@@ -352,16 +357,30 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
352357
resnode->resno = (AttrNumber) pstate->p_last_resno++;
353358
continue;
354359
}
355-
if (icolumns == NIL)
360+
if (icolumns == NIL || attnos == NIL)
356361
elog(ERROR, "INSERT has more expressions than target columns");
357362
id = (Ident *) lfirst(icolumns);
358-
updateTargetListEntry(pstate, tle, id->name, id->indirection);
363+
updateTargetListEntry(pstate, tle, id->name, lfirsti(attnos),
364+
id->indirection);
365+
numuseratts++;
359366
icolumns = lnext(icolumns);
367+
attnos = lnext(attnos);
360368
}
361369

370+
/*
371+
* It is possible that the targetlist has fewer entries than were in
372+
* the columns list. We do not consider this an error (perhaps we
373+
* should, if the columns list was explictly given?). We must truncate
374+
* the attrnos list to only include the attrs actually provided,
375+
* else we will fail to apply defaults for them below.
376+
*/
377+
if (icolumns != NIL)
378+
attrnos = ltruncate(numuseratts, attrnos);
379+
362380
/*
363381
* Add targetlist items to assign DEFAULT values to any columns that
364382
* have defaults and were not assigned to by the user.
383+
*
365384
* XXX wouldn't it make more sense to do this further downstream,
366385
* after the rule rewriter?
367386
*/
@@ -372,29 +391,20 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
372391
AttrDefault *defval = rd_att->constr->defval;
373392
int ndef = rd_att->constr->num_defval;
374393

375-
while (ndef-- > 0)
394+
while (--ndef >= 0)
376395
{
377-
Form_pg_attribute thisatt = att[defval[ndef].adnum - 1];
378-
TargetEntry *te;
396+
AttrNumber attrno = defval[ndef].adnum;
397+
Form_pg_attribute thisatt = att[attrno - 1];
398+
TargetEntry *te;
379399

380-
foreach(tl, qry->targetList)
381-
{
382-
TargetEntry *tle = (TargetEntry *) lfirst(tl);
383-
Resdom *resnode = tle->resdom;
384-
385-
if (resnode->resjunk)
386-
continue; /* ignore resjunk nodes */
387-
if (namestrcmp(&(thisatt->attname), resnode->resname) == 0)
388-
break;
389-
}
390-
if (tl != NIL) /* found TLE for this attr */
391-
continue;
400+
if (intMember((int) attrno, attrnos))
401+
continue; /* there was a user-specified value */
392402
/*
393403
* No user-supplied value, so add a targetentry with DEFAULT expr
394404
* and correct data for the target column.
395405
*/
396406
te = makeTargetEntry(
397-
makeResdom(defval[ndef].adnum,
407+
makeResdom(attrno,
398408
thisatt->atttypid,
399409
thisatt->atttypmod,
400410
pstrdup(nameout(&(thisatt->attname))),
@@ -405,7 +415,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
405415
* Make sure the value is coerced to the target column type
406416
* (might not be right type if it's not a constant!)
407417
*/
408-
updateTargetListEntry(pstate, te, te->resdom->resname, NIL);
418+
updateTargetListEntry(pstate, te, te->resdom->resname, attrno,
419+
NIL);
409420
}
410421
}
411422

@@ -1128,8 +1139,10 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
11281139
if (origTargetList == NIL)
11291140
elog(ERROR, "UPDATE target count mismatch --- internal error");
11301141
origTarget = (ResTarget *) lfirst(origTargetList);
1131-
updateTargetListEntry(pstate, tle,
1132-
origTarget->name, origTarget->indirection);
1142+
updateTargetListEntry(pstate, tle, origTarget->name,
1143+
attnameAttNum(pstate->p_target_relation,
1144+
origTarget->name),
1145+
origTarget->indirection);
11331146
origTargetList = lnext(origTargetList);
11341147
}
11351148
if (origTargetList != NIL)

src/backend/parser/parse_node.c

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.31 1999/08/23 23:48:39 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.32 1999/11/01 05:06:21 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -176,11 +176,16 @@ make_op(char *opname, Node *ltree, Node *rtree)
176176
} /* make_op() */
177177

178178

179+
/*
180+
* make_var
181+
* Build a Var node for an attribute identified by name
182+
*/
179183
Var *
180184
make_var(ParseState *pstate, Oid relid, char *refname,
181185
char *attrname)
182186
{
183-
Var *varnode;
187+
HeapTuple tp;
188+
Form_pg_attribute att_tup;
184189
int vnum,
185190
attid;
186191
Oid vartypeid;
@@ -189,16 +194,19 @@ make_var(ParseState *pstate, Oid relid, char *refname,
189194

190195
vnum = refnameRangeTablePosn(pstate, refname, &sublevels_up);
191196

192-
attid = get_attnum(relid, attrname);
193-
if (attid == InvalidAttrNumber)
197+
tp = SearchSysCacheTuple(ATTNAME,
198+
ObjectIdGetDatum(relid),
199+
PointerGetDatum(attrname),
200+
0, 0);
201+
if (!HeapTupleIsValid(tp))
194202
elog(ERROR, "Relation %s does not have attribute %s",
195203
refname, attrname);
196-
vartypeid = get_atttype(relid, attid);
197-
type_mod = get_atttypmod(relid, attid);
198-
199-
varnode = makeVar(vnum, attid, vartypeid, type_mod, sublevels_up);
204+
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
205+
attid = att_tup->attnum;
206+
vartypeid = att_tup->atttypid;
207+
type_mod = att_tup->atttypmod;
200208

201-
return varnode;
209+
return makeVar(vnum, attid, vartypeid, type_mod, sublevels_up);
202210
}
203211

204212
/*
@@ -380,67 +388,73 @@ transformArraySubscripts(ParseState *pstate,
380388
}
381389

382390
/*
383-
* make_const -
391+
* make_const
384392
*
385-
* - takes a lispvalue, (as returned to the yacc routine by the lexer)
386-
* extracts the type, and makes the appropriate type constant
387-
* by invoking the (c-callable) lisp routine c-make-const
388-
* via the lisp_call() mechanism
389-
*
390-
* eventually, produces a "const" lisp-struct as per nodedefs.cl
393+
* Convert a Value node (as returned by the grammar) to a Const node
394+
* of the "natural" type for the constant. For strings we produce
395+
* a constant of type UNKNOWN ---- representation is the same as text,
396+
* but this indicates to later type resolution that we're not sure that
397+
* it should be considered text.
391398
*/
392399
Const *
393400
make_const(Value *value)
394401
{
395-
Type tp;
396402
Datum val;
403+
Oid typeid;
404+
int typelen;
405+
bool typebyval;
397406
Const *con;
398407

399408
switch (nodeTag(value))
400409
{
401410
case T_Integer:
402-
tp = typeidType(INT4OID);
403411
val = Int32GetDatum(intVal(value));
412+
413+
typeid = INT4OID;
414+
typelen = sizeof(int32);
415+
typebyval = true;
404416
break;
405417

406418
case T_Float:
407419
{
408420
float64 dummy;
409421

410-
tp = typeidType(FLOAT8OID);
411-
412422
dummy = (float64) palloc(sizeof(float64data));
413423
*dummy = floatVal(value);
414424

415425
val = Float64GetDatum(dummy);
426+
427+
typeid = FLOAT8OID;
428+
typelen = sizeof(float64data);
429+
typebyval = false;
416430
}
417431
break;
418432

419433
case T_String:
420-
tp = typeidType(UNKNOWNOID); /* unknown for now, will
421-
* be type coerced */
422434
val = PointerGetDatum(textin(strVal(value)));
435+
436+
typeid = UNKNOWNOID; /* will be coerced later */
437+
typelen = -1; /* variable len */
438+
typebyval = false;
423439
break;
424440

425441
case T_Null:
426442
default:
427-
{
428-
if (nodeTag(value) != T_Null)
429-
elog(NOTICE, "make_const: unknown type %d\n", nodeTag(value));
443+
if (nodeTag(value) != T_Null)
444+
elog(NOTICE, "make_const: unknown type %d\n", nodeTag(value));
430445

431-
/* null const */
432-
con = makeConst(0, 0, (Datum) NULL, true, false, false, false);
433-
return con;
434-
}
446+
/* return a null const */
447+
con = makeConst(0, 0, (Datum) NULL, true, false, false, false);
448+
return con;
435449
}
436450

437-
con = makeConst(typeTypeId(tp),
438-
typeLen(tp),
451+
con = makeConst(typeid,
452+
typelen,
439453
val,
440454
false,
441-
typeByVal(tp),
455+
typebyval,
442456
false, /* not a set */
443-
false);
457+
false); /* not coerced */
444458

445459
return con;
446460
}

src/backend/parser/parse_target.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.46 1999/07/19 00:26:20 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.47 1999/11/01 05:06:21 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -162,27 +162,27 @@ transformTargetList(ParseState *pstate, List *targetlist)
162162
* pstate parse state
163163
* tle target list entry to be modified
164164
* colname target column name (ie, name of attribute to be assigned to)
165+
* attrno target attribute number
165166
* indirection subscripts for target column, if any
166167
*/
167168
void
168169
updateTargetListEntry(ParseState *pstate,
169170
TargetEntry *tle,
170171
char *colname,
172+
int attrno,
171173
List *indirection)
172174
{
173175
Oid type_id = exprType(tle->expr); /* type of value provided */
174176
Oid attrtype; /* type of target column */
175177
int32 attrtypmod;
176178
Resdom *resnode = tle->resdom;
177179
Relation rd = pstate->p_target_relation;
178-
int resdomno;
179180

180181
Assert(rd != NULL);
181-
resdomno = attnameAttNum(rd, colname);
182-
if (resdomno <= 0)
182+
if (attrno <= 0)
183183
elog(ERROR, "Cannot assign to system attribute '%s'", colname);
184-
attrtype = attnumTypeId(rd, resdomno);
185-
attrtypmod = rd->rd_att->attrs[resdomno - 1]->atttypmod;
184+
attrtype = attnumTypeId(rd, attrno);
185+
attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod;
186186

187187
/*
188188
* If there are subscripts on the target column, prepare an
@@ -260,7 +260,7 @@ updateTargetListEntry(ParseState *pstate,
260260
resnode->restype = attrtype;
261261
resnode->restypmod = attrtypmod;
262262
resnode->resname = colname;
263-
resnode->resno = (AttrNumber) resdomno;
263+
resnode->resno = (AttrNumber) attrno;
264264
}
265265

266266

@@ -356,14 +356,17 @@ SizeTargetExpr(ParseState *pstate,
356356

357357

358358
/*
359-
* makeTargetNames -
359+
* checkInsertTargets -
360360
* generate a list of column names if not supplied or
361361
* test supplied column names to make sure they are in target table.
362+
* Also return an integer list of the columns' attribute numbers.
362363
* (used exclusively for inserts)
363364
*/
364365
List *
365-
makeTargetNames(ParseState *pstate, List *cols)
366+
checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
366367
{
368+
*attrnos = NIL;
369+
367370
if (cols == NIL)
368371
{
369372
/*
@@ -382,6 +385,7 @@ makeTargetNames(ParseState *pstate, List *cols)
382385
id->indirection = NIL;
383386
id->isRel = false;
384387
cols = lappend(cols, id);
388+
*attrnos = lappendi(*attrnos, i+1);
385389
}
386390
}
387391
else
@@ -394,17 +398,14 @@ makeTargetNames(ParseState *pstate, List *cols)
394398
foreach(tl, cols)
395399
{
396400
char *name = ((Ident *) lfirst(tl))->name;
397-
List *nxt;
401+
int attrno;
398402

399403
/* Lookup column name, elog on failure */
400-
attnameAttNum(pstate->p_target_relation, name);
404+
attrno = attnameAttNum(pstate->p_target_relation, name);
401405
/* Check for duplicates */
402-
foreach(nxt, lnext(tl))
403-
{
404-
if (strcmp(name, ((Ident *) lfirst(nxt))->name) == 0)
405-
elog(ERROR, "Attribute '%s' specified more than once",
406-
name);
407-
}
406+
if (intMember(attrno, *attrnos))
407+
elog(ERROR, "Attribute '%s' specified more than once", name);
408+
*attrnos = lappendi(*attrnos, attrno);
408409
}
409410
}
410411

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy