Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9e52381

Browse files
committed
Rewrite rewriteTargetList() to avoid O(N^2) behavior on wide target lists.
1 parent4377648 commit9e52381

File tree

1 file changed

+64
-56
lines changed

1 file changed

+64
-56
lines changed

‎src/backend/rewrite/rewriteHandler.c

Lines changed: 64 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.148 2005/03/10 23:21:24 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.149 2005/03/26 05:53:01 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -287,52 +287,91 @@ static void
287287
rewriteTargetList(Query*parsetree,Relationtarget_relation)
288288
{
289289
CmdTypecommandType=parsetree->commandType;
290-
List*tlist=parsetree->targetList;
290+
TargetEntry**new_tles;
291291
List*new_tlist=NIL;
292+
List*junk_tlist=NIL;
293+
Form_pg_attributeatt_tup;
292294
intattrno,
295+
next_junk_attrno,
293296
numattrs;
294297
ListCell*temp;
295298

296299
/*
297-
* Scan the tuple description in the relation's relcache entry to make
298-
* sure we have all the user attributes in the right order.
300+
* We process the normal (non-junk) attributes by scanning the input
301+
* tlist once and transferring TLEs into an array, then scanning the
302+
* array to build an output tlist. This avoids O(N^2) behavior for
303+
* large numbers of attributes.
304+
*
305+
* Junk attributes are tossed into a separate list during the same
306+
* tlist scan, then appended to the reconstructed tlist.
299307
*/
300308
numattrs=RelationGetNumberOfAttributes(target_relation);
309+
new_tles= (TargetEntry**)palloc0(numattrs*sizeof(TargetEntry*));
310+
next_junk_attrno=numattrs+1;
301311

302-
for (attrno=1;attrno <=numattrs;attrno++)
312+
foreach(temp,parsetree->targetList)
303313
{
304-
Form_pg_attributeatt_tup=target_relation->rd_att->attrs[attrno-1];
305-
TargetEntry*new_tle=NULL;
314+
TargetEntry*old_tle=(TargetEntry*)lfirst(temp);
315+
Resdom*resdom=old_tle->resdom;
306316

307-
/* We can ignore deleted attributes */
308-
if (att_tup->attisdropped)
309-
continue;
317+
if (!resdom->resjunk)
318+
{
319+
/* Normal attr: stash it into new_tles[] */
320+
attrno=resdom->resno;
321+
if (attrno<1||attrno>numattrs)
322+
elog(ERROR,"bogus resno %d in targetlist",attrno);
323+
att_tup=target_relation->rd_att->attrs[attrno-1];
324+
325+
/* We can (and must) ignore deleted attributes */
326+
if (att_tup->attisdropped)
327+
continue;
310328

311-
/*
312-
* Look for targetlist entries matching this attr.
313-
*
314-
* Junk attributes are not candidates to be matched.
315-
*/
316-
foreach(temp,tlist)
329+
/* Merge with any prior assignment to same attribute */
330+
new_tles[attrno-1]=
331+
process_matched_tle(old_tle,
332+
new_tles[attrno-1],
333+
NameStr(att_tup->attname));
334+
}
335+
else
317336
{
318-
TargetEntry*old_tle= (TargetEntry*)lfirst(temp);
319-
Resdom*resdom=old_tle->resdom;
337+
/*
338+
* Copy all resjunk tlist entries to junk_tlist, and
339+
* assign them resnos above the last real resno.
340+
*
341+
* Typical junk entries include ORDER BY or GROUP BY expressions
342+
* (are these actually possible in an INSERT or UPDATE?), system
343+
* attribute references, etc.
344+
*/
320345

321-
if (!resdom->resjunk&&resdom->resno==attrno)
346+
/* Get the resno right, but don't copy unnecessarily */
347+
if (resdom->resno!=next_junk_attrno)
322348
{
323-
new_tle=process_matched_tle(old_tle,new_tle,
324-
NameStr(att_tup->attname));
325-
/* keep scanning to detect multiple assignments to attr */
349+
resdom=(Resdom*)copyObject((Node*)resdom);
350+
resdom->resno=next_junk_attrno;
351+
old_tle=makeTargetEntry(resdom,old_tle->expr);
326352
}
353+
junk_tlist=lappend(junk_tlist,old_tle);
354+
next_junk_attrno++;
327355
}
356+
}
357+
358+
for (attrno=1;attrno <=numattrs;attrno++)
359+
{
360+
TargetEntry*new_tle=new_tles[attrno-1];
361+
362+
att_tup=target_relation->rd_att->attrs[attrno-1];
363+
364+
/* We can (and must) ignore deleted attributes */
365+
if (att_tup->attisdropped)
366+
continue;
328367

329368
/*
330369
* Handle the two cases where we need to insert a default
331370
* expression: it's an INSERT and there's no tlist entry for the
332371
* column, or the tlist entry is a DEFAULT placeholder node.
333372
*/
334373
if ((new_tle==NULL&&commandType==CMD_INSERT)||
335-
(new_tle&&new_tle->expr&&IsA(new_tle->expr,SetToDefault)))
374+
(new_tle&&new_tle->expr&&IsA(new_tle->expr,SetToDefault)))
336375
{
337376
Node*new_expr;
338377

@@ -380,40 +419,9 @@ rewriteTargetList(Query *parsetree, Relation target_relation)
380419
new_tlist=lappend(new_tlist,new_tle);
381420
}
382421

383-
/*
384-
* Copy all resjunk tlist entries to the end of the new tlist, and
385-
* assign them resnos above the last real resno.
386-
*
387-
* Typical junk entries include ORDER BY or GROUP BY expressions (are
388-
* these actually possible in an INSERT or UPDATE?), system attribute
389-
* references, etc.
390-
*/
391-
foreach(temp,tlist)
392-
{
393-
TargetEntry*old_tle= (TargetEntry*)lfirst(temp);
394-
Resdom*resdom=old_tle->resdom;
395-
396-
if (resdom->resjunk)
397-
{
398-
/* Get the resno right, but don't copy unnecessarily */
399-
if (resdom->resno!=attrno)
400-
{
401-
resdom= (Resdom*)copyObject((Node*)resdom);
402-
resdom->resno=attrno;
403-
old_tle=makeTargetEntry(resdom,old_tle->expr);
404-
}
405-
new_tlist=lappend(new_tlist,old_tle);
406-
attrno++;
407-
}
408-
else
409-
{
410-
/* Let's just make sure we processed all the non-junk items */
411-
if (resdom->resno<1||resdom->resno>numattrs)
412-
elog(ERROR,"bogus resno %d in targetlist",resdom->resno);
413-
}
414-
}
422+
pfree(new_tles);
415423

416-
parsetree->targetList=new_tlist;
424+
parsetree->targetList=list_concat(new_tlist,junk_tlist);
417425
}
418426

419427

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp