Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
9e523813
Commit
9e523813
authored
Mar 26, 2005
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rewrite rewriteTargetList() to avoid O(N^2) behavior on wide target lists.
parent
4377648b
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
64 additions
and
56 deletions
+64
-56
src/backend/rewrite/rewriteHandler.c
src/backend/rewrite/rewriteHandler.c
+64
-56
No files found.
src/backend/rewrite/rewriteHandler.c
View file @
9e523813
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.14
8 2005/03/10 23:21:24
tgl Exp $
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.14
9 2005/03/26 05:53:01
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -287,44 +287,83 @@ static void
rewriteTargetList
(
Query
*
parsetree
,
Relation
target_relation
)
{
CmdType
commandType
=
parsetree
->
commandType
;
List
*
tlist
=
parsetree
->
targetList
;
TargetEntry
**
new_tles
;
List
*
new_tlist
=
NIL
;
List
*
junk_tlist
=
NIL
;
Form_pg_attribute
att_tup
;
int
attrno
,
next_junk_attrno
,
numattrs
;
ListCell
*
temp
;
/*
* Scan the tuple description in the relation's relcache entry to make
* sure we have all the user attributes in the right order.
* We process the normal (non-junk) attributes by scanning the input
* tlist once and transferring TLEs into an array, then scanning the
* array to build an output tlist. This avoids O(N^2) behavior for
* large numbers of attributes.
*
* Junk attributes are tossed into a separate list during the same
* tlist scan, then appended to the reconstructed tlist.
*/
numattrs
=
RelationGetNumberOfAttributes
(
target_relation
);
new_tles
=
(
TargetEntry
**
)
palloc0
(
numattrs
*
sizeof
(
TargetEntry
*
));
next_junk_attrno
=
numattrs
+
1
;
for
(
attrno
=
1
;
attrno
<=
numattrs
;
attrno
++
)
for
each
(
temp
,
parsetree
->
targetList
)
{
Form_pg_attribute
att_tup
=
target_relation
->
rd_att
->
attrs
[
attrno
-
1
]
;
TargetEntry
*
new_tle
=
NULL
;
TargetEntry
*
old_tle
=
(
TargetEntry
*
)
lfirst
(
temp
)
;
Resdom
*
resdom
=
old_tle
->
resdom
;
/* We can ignore deleted attributes */
if
(
att_tup
->
attisdropped
)
continue
;
if
(
!
resdom
->
resjunk
)
{
/* Normal attr: stash it into new_tles[] */
attrno
=
resdom
->
resno
;
if
(
attrno
<
1
||
attrno
>
numattrs
)
elog
(
ERROR
,
"bogus resno %d in targetlist"
,
attrno
);
att_tup
=
target_relation
->
rd_att
->
attrs
[
attrno
-
1
];
/* We can (and must) ignore deleted attributes */
if
(
att_tup
->
attisdropped
)
continue
;
/*
* Look for targetlist entries matching this attr.
*
* Junk attributes are not candidates to be matched.
*/
foreach
(
temp
,
tlist
)
/* Merge with any prior assignment to same attribute */
new_tles
[
attrno
-
1
]
=
process_matched_tle
(
old_tle
,
new_tles
[
attrno
-
1
],
NameStr
(
att_tup
->
attname
));
}
else
{
TargetEntry
*
old_tle
=
(
TargetEntry
*
)
lfirst
(
temp
);
Resdom
*
resdom
=
old_tle
->
resdom
;
/*
* Copy all resjunk tlist entries to junk_tlist, and
* assign them resnos above the last real resno.
*
* Typical junk entries include ORDER BY or GROUP BY expressions
* (are these actually possible in an INSERT or UPDATE?), system
* attribute references, etc.
*/
if
(
!
resdom
->
resjunk
&&
resdom
->
resno
==
attrno
)
/* Get the resno right, but don't copy unnecessarily */
if
(
resdom
->
resno
!=
next_junk_attrno
)
{
new_tle
=
process_matched_tle
(
old_tle
,
new_tle
,
NameStr
(
att_tup
->
attname
))
;
/* keep scanning to detect multiple assignments to attr */
resdom
=
(
Resdom
*
)
copyObject
((
Node
*
)
resdom
);
resdom
->
resno
=
next_junk_attrno
;
old_tle
=
makeTargetEntry
(
resdom
,
old_tle
->
expr
);
}
junk_tlist
=
lappend
(
junk_tlist
,
old_tle
);
next_junk_attrno
++
;
}
}
for
(
attrno
=
1
;
attrno
<=
numattrs
;
attrno
++
)
{
TargetEntry
*
new_tle
=
new_tles
[
attrno
-
1
];
att_tup
=
target_relation
->
rd_att
->
attrs
[
attrno
-
1
];
/* We can (and must) ignore deleted attributes */
if
(
att_tup
->
attisdropped
)
continue
;
/*
* Handle the two cases where we need to insert a default
...
...
@@ -332,7 +371,7 @@ rewriteTargetList(Query *parsetree, Relation target_relation)
* column, or the tlist entry is a DEFAULT placeholder node.
*/
if
((
new_tle
==
NULL
&&
commandType
==
CMD_INSERT
)
||
(
new_tle
&&
new_tle
->
expr
&&
IsA
(
new_tle
->
expr
,
SetToDefault
)))
(
new_tle
&&
new_tle
->
expr
&&
IsA
(
new_tle
->
expr
,
SetToDefault
)))
{
Node
*
new_expr
;
...
...
@@ -380,40 +419,9 @@ rewriteTargetList(Query *parsetree, Relation target_relation)
new_tlist
=
lappend
(
new_tlist
,
new_tle
);
}
/*
* Copy all resjunk tlist entries to the end of the new tlist, and
* assign them resnos above the last real resno.
*
* Typical junk entries include ORDER BY or GROUP BY expressions (are
* these actually possible in an INSERT or UPDATE?), system attribute
* references, etc.
*/
foreach
(
temp
,
tlist
)
{
TargetEntry
*
old_tle
=
(
TargetEntry
*
)
lfirst
(
temp
);
Resdom
*
resdom
=
old_tle
->
resdom
;
if
(
resdom
->
resjunk
)
{
/* Get the resno right, but don't copy unnecessarily */
if
(
resdom
->
resno
!=
attrno
)
{
resdom
=
(
Resdom
*
)
copyObject
((
Node
*
)
resdom
);
resdom
->
resno
=
attrno
;
old_tle
=
makeTargetEntry
(
resdom
,
old_tle
->
expr
);
}
new_tlist
=
lappend
(
new_tlist
,
old_tle
);
attrno
++
;
}
else
{
/* Let's just make sure we processed all the non-junk items */
if
(
resdom
->
resno
<
1
||
resdom
->
resno
>
numattrs
)
elog
(
ERROR
,
"bogus resno %d in targetlist"
,
resdom
->
resno
);
}
}
pfree
(
new_tles
);
parsetree
->
targetList
=
new_tlist
;
parsetree
->
targetList
=
list_concat
(
new_tlist
,
junk_tlist
)
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment