Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
P
postgres-lambda-diff
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Jakob Huber
postgres-lambda-diff
Commits
5efe3121
Commit
5efe3121
authored
25 years ago
by
Tom Lane
Browse files
Options
Downloads
Patches
Plain Diff
Clean up tlist.c tree-walking routines with
expression_tree_mutator.
parent
14f84cd8
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/backend/optimizer/util/tlist.c
+88
-280
88 additions, 280 deletions
src/backend/optimizer/util/tlist.c
with
88 additions
and
280 deletions
src/backend/optimizer/util/tlist.c
+
88
−
280
View file @
5efe3121
...
@@ -7,21 +7,19 @@
...
@@ -7,21 +7,19 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.3
6
1999/0
7/16 04:59:27 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.3
7
1999/0
8/09 05:34:13 tgl
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
#include
"postgres.h"
#include
"postgres.h"
#include
"nodes/makefuncs.h"
#include
"nodes/makefuncs.h"
#include
"nodes/nodeFuncs.h"
#include
"nodes/nodeFuncs.h"
#include
"optimizer/clauses.h"
#include
"optimizer/clauses.h"
#include
"optimizer/tlist.h"
#include
"optimizer/tlist.h"
#include
"optimizer/var.h"
#include
"optimizer/var.h"
static
Node
*
flatten_tlist
entry
(
Node
*
tlistentry
,
List
*
flat_tlist
);
static
Node
*
flatten_tlist
_vars_mutator
(
Node
*
node
,
List
*
flat_tlist
);
/*****************************************************************************
/*****************************************************************************
* ---------- RELATION node target list routines ----------
* ---------- RELATION node target list routines ----------
...
@@ -29,25 +27,19 @@ static Node *flatten_tlistentry(Node *tlistentry, List *flat_tlist);
...
@@ -29,25 +27,19 @@ static Node *flatten_tlistentry(Node *tlistentry, List *flat_tlist);
/*
/*
* tlistentry_member
* tlistentry_member
*
* Finds the (first) member of the given tlist whose expression is
* RETURNS: the leftmost member of sequence "targetlist" that satisfies
* var_equal() to the given var. Result is NULL if no such member.
* the predicate "var_equal"
* MODIFIES: nothing
* REQUIRES: test = function which can operate on a lispval union
* var = valid var_node
* targetlist = valid sequence
*/
*/
TargetEntry
*
TargetEntry
*
tlistentry_member
(
Var
*
var
,
List
*
targetlist
)
tlistentry_member
(
Var
*
var
,
List
*
targetlist
)
{
{
if
(
var
)
if
(
var
&&
IsA
(
var
,
Var
)
)
{
{
List
*
temp
;
List
*
temp
;
foreach
(
temp
,
targetlist
)
foreach
(
temp
,
targetlist
)
{
{
if
(
var_equal
(
var
,
if
(
var_equal
(
var
,
get_expr
(
lfirst
(
temp
))))
get_expr
(
lfirst
(
temp
))))
return
(
TargetEntry
*
)
lfirst
(
temp
);
return
(
TargetEntry
*
)
lfirst
(
temp
);
}
}
}
}
...
@@ -56,11 +48,8 @@ tlistentry_member(Var *var, List *targetlist)
...
@@ -56,11 +48,8 @@ tlistentry_member(Var *var, List *targetlist)
/*
/*
* matching_tlist_var
* matching_tlist_var
*
* Same as tlistentry_member(), except returns the tlist expression
* RETURNS: var node in a target list which is var_equal to 'var',
* rather than its parent TargetEntry node.
* if one exists.
* REQUIRES: "test" operates on lispval unions,
*
*/
*/
Expr
*
Expr
*
matching_tlist_var
(
Var
*
var
,
List
*
targetlist
)
matching_tlist_var
(
Var
*
var
,
List
*
targetlist
)
...
@@ -74,54 +63,45 @@ matching_tlist_var(Var *var, List *targetlist)
...
@@ -74,54 +63,45 @@ matching_tlist_var(Var *var, List *targetlist)
return
(
Expr
*
)
NULL
;
return
(
Expr
*
)
NULL
;
}
}
/*
* tlist_member
* Same as tlistentry_member(), except returns the Resdom node
* rather than its parent TargetEntry node.
*/
Resdom
*
tlist_member
(
Var
*
var
,
List
*
tlist
)
{
TargetEntry
*
tlentry
;
tlentry
=
tlistentry_member
(
var
,
tlist
);
if
(
tlentry
)
return
tlentry
->
resdom
;
return
(
Resdom
*
)
NULL
;
}
/*
/*
* add_var_to_tlist
* add_var_to_tlist
* Creates a targetlist entry corresponding to the supplied var node
* Creates a targetlist entry corresponding to the supplied var node
*
* 'var' and adds the new targetlist entry to the targetlist field of
* 'var' and adds the new targetlist entry to the targetlist field of
* 'rel'
* 'rel'. No entry is created if 'var' is already in the tlist.
*
* RETURNS: nothing
* MODIFIES: vartype and varid fields of leftmost varnode that matches
* argument "var" (sometimes).
* CREATES: new var_node iff no matching var_node exists in targetlist
*/
*/
void
void
add_var_to_tlist
(
RelOptInfo
*
rel
,
Var
*
var
)
add_var_to_tlist
(
RelOptInfo
*
rel
,
Var
*
var
)
{
{
Expr
*
oldvar
;
if
(
tlistentry_member
(
var
,
rel
->
targetlist
)
==
NULL
)
oldvar
=
matching_tlist_var
(
var
,
rel
->
targetlist
);
/*
* If 'var' is not already in 'rel's target list, add a new node.
*/
if
(
oldvar
==
NULL
)
{
{
List
*
tlist
=
rel
->
targetlist
;
/* XXX is copyObject necessary here? */
Var
*
newvar
=
makeVar
(
var
->
varno
,
rel
->
targetlist
=
lappend
(
rel
->
targetlist
,
var
->
varattno
,
create_tl_element
((
Var
*
)
copyObject
(
var
),
var
->
vartype
,
length
(
rel
->
targetlist
)
+
1
));
var
->
vartypmod
,
var
->
varlevelsup
,
var
->
varno
,
var
->
varoattno
);
rel
->
targetlist
=
lappend
(
tlist
,
create_tl_element
(
newvar
,
length
(
tlist
)
+
1
));
}
}
}
}
/*
/*
* create_tl_element
* create_tl_element
* Creates a target list entry node and its associated (resdom var) pair
* Creates a target list entry node and its associated (resdom var) pair
* with its resdom number equal to 'resdomno' and the joinlist field set
* with its resdom number equal to 'resdomno'.
* to 'joinlist'.
*
* RETURNS: newly created tlist_entry
* CREATES: new targetlist entry (always).
*/
*/
TargetEntry
*
TargetEntry
*
create_tl_element
(
Var
*
var
,
int
resdomno
)
create_tl_element
(
Var
*
var
,
int
resdomno
)
...
@@ -176,35 +156,6 @@ get_actual_tlist(List *tlist)
...
@@ -176,35 +156,6 @@ get_actual_tlist(List *tlist)
* ---------- GENERAL target list routines ----------
* ---------- GENERAL target list routines ----------
*****************************************************************************/
*****************************************************************************/
/*
* tlist_member
* Determines whether a var node is already contained within a
* target list.
*
* 'var' is the var node
* 'tlist' is the target list
*
* Returns the resdom entry of the matching var node, or NULL if no match.
*
*/
Resdom
*
tlist_member
(
Var
*
var
,
List
*
tlist
)
{
if
(
var
)
{
List
*
i
;
foreach
(
i
,
tlist
)
{
TargetEntry
*
tle
=
(
TargetEntry
*
)
lfirst
(
i
);
if
(
var_equal
(
var
,
get_expr
(
tle
)))
return
tle
->
resdom
;
}
}
return
(
Resdom
*
)
NULL
;
}
/*
/*
* Routine to get the resdom out of a targetlist.
* Routine to get the resdom out of a targetlist.
*/
*/
...
@@ -228,52 +179,37 @@ tlist_resdom(List *tlist, Resdom *resnode)
...
@@ -228,52 +179,37 @@ tlist_resdom(List *tlist, Resdom *resnode)
/*
/*
* match_varid
* match_varid
* Searches a target list for an entry with some desired varid.
* Searches a target list for an entry matching a given var.
*
* 'varid' is the desired id
* 'tlist' is the target list that is searched
*
* Returns the target list entry (resdom var) of the matching var.
*
*
* Now checks to make sure array references (in addition to range
* Returns the target list entry (resdom var) of the matching var,
* table indices) are identical - retrieve (a.b[1],a.b[2]) should
* or NULL if no match.
* not be turned into retrieve (a.b[1],a.b[1]).
*
* [what used to be varid is now broken up into two fields varnoold and
* varoattno. Also, nested attnos are long gone. - ay 2/95]
*/
*/
TargetEntry
*
TargetEntry
*
match_varid
(
Var
*
test_var
,
List
*
tlist
)
match_varid
(
Var
*
test_var
,
List
*
tlist
)
{
{
List
*
tl
;
List
*
tl
;
Oid
type_var
;
type_var
=
(
Oid
)
test_var
->
vartype
;
Assert
(
test_var
->
varlevelsup
==
0
);
/* XXX why? */
Assert
(
test_var
->
varlevelsup
==
0
);
foreach
(
tl
,
tlist
)
foreach
(
tl
,
tlist
)
{
{
TargetEntry
*
entry
;
TargetEntry
*
entry
=
lfirst
(
tl
);
Var
*
tlvar
;
Var
*
tlvar
=
get_expr
(
entry
);
entry
=
lfirst
(
tl
);
tlvar
=
get_expr
(
entry
);
if
(
!
IsA
(
tlvar
,
Var
))
if
(
!
IsA
(
tlvar
,
Var
))
continue
;
continue
;
/*
/*
* we test the original varno
(
instead of varno which might be
* we test the original varno
,
instead of varno which might be
* changed to INNER/OUTER.
* changed to INNER/OUTER.
XXX is test on vartype necessary?
*/
*/
Assert
(
tlvar
->
varlevelsup
==
0
);
Assert
(
tlvar
->
varlevelsup
==
0
);
if
(
tlvar
->
varnoold
==
test_var
->
varnoold
&&
if
(
tlvar
->
varnoold
==
test_var
->
varnoold
&&
tlvar
->
varoattno
==
test_var
->
varoattno
)
tlvar
->
varoattno
==
test_var
->
varoattno
&&
{
tlvar
->
vartype
==
test_var
->
vartype
)
if
(
tlvar
->
vartype
==
type_var
)
return
entry
;
return
entry
;
}
}
}
return
NULL
;
return
NULL
;
}
}
...
@@ -321,11 +257,12 @@ List *
...
@@ -321,11 +257,12 @@ List *
copy_vars
(
List
*
target
,
List
*
source
)
copy_vars
(
List
*
target
,
List
*
source
)
{
{
List
*
result
=
NIL
;
List
*
result
=
NIL
;
List
*
src
=
NIL
;
List
*
src
;
List
*
dest
=
NIL
;
List
*
dest
;
for
(
src
=
source
,
dest
=
target
;
src
!=
NIL
&&
for
(
src
=
source
,
dest
=
target
;
dest
!=
NIL
;
src
=
lnext
(
src
),
dest
=
lnext
(
dest
))
src
!=
NIL
&&
dest
!=
NIL
;
src
=
lnext
(
src
),
dest
=
lnext
(
dest
))
{
{
TargetEntry
*
temp
=
makeTargetEntry
(((
TargetEntry
*
)
lfirst
(
dest
))
->
resdom
,
TargetEntry
*
temp
=
makeTargetEntry
(((
TargetEntry
*
)
lfirst
(
dest
))
->
resdom
,
(
Node
*
)
get_expr
(
lfirst
(
src
)));
(
Node
*
)
get_expr
(
lfirst
(
src
)));
...
@@ -350,50 +287,48 @@ flatten_tlist(List *tlist)
...
@@ -350,50 +287,48 @@ flatten_tlist(List *tlist)
{
{
int
last_resdomno
=
1
;
int
last_resdomno
=
1
;
List
*
new_tlist
=
NIL
;
List
*
new_tlist
=
NIL
;
List
*
tlist_vars
=
NIL
;
List
*
tl
;
List
*
temp
;
foreach
(
t
emp
,
tlist
)
foreach
(
t
l
,
tlist
)
{
{
TargetEntry
*
temp_entry
=
(
TargetEntry
*
)
lfirst
(
temp
);
TargetEntry
*
tl_entry
=
(
TargetEntry
*
)
lfirst
(
tl
);
List
*
vlist
=
pull_var_clause
((
Node
*
)
get_expr
(
tl_entry
));
List
*
v
;
tlist_vars
=
nconc
(
tlist_vars
,
foreach
(
v
,
vlist
)
pull_var_clause
((
Node
*
)
get_expr
(
temp_entry
)));
}
foreach
(
temp
,
tlist_vars
)
{
{
Var
*
var
=
lfirst
(
temp
);
Var
*
var
=
lfirst
(
v
);
if
(
!
(
tlist_member
(
var
,
new_tlist
))
)
if
(
!
tlist
entry
_member
(
var
,
new_tlist
))
{
{
Resdom
*
r
;
Resdom
*
r
;
r
=
makeResdom
(
last_resdomno
,
r
=
makeResdom
(
last_resdomno
++
,
var
->
vartype
,
var
->
vartype
,
var
->
vartypmod
,
var
->
vartypmod
,
NULL
,
NULL
,
(
Index
)
0
,
(
Index
)
0
,
(
Oid
)
0
,
(
Oid
)
0
,
false
);
false
);
last_resdomno
++
;
new_tlist
=
lappend
(
new_tlist
,
new_tlist
=
lappend
(
new_tlist
,
makeTargetEntry
(
r
,
(
Node
*
)
var
));
makeTargetEntry
(
r
,
(
Node
*
)
var
));
}
}
}
}
freeList
(
vlist
);
}
return
new_tlist
;
return
new_tlist
;
}
}
/*
/*
* flatten_tlist_vars
* flatten_tlist_vars
* Redoes the target list of a query with no nested attributes by
* Redoes the target list of a query by replacing vars within
* replacing vars within computational expressions with vars from
* target expressions with vars from the 'flattened' target list.
* the 'flattened' target list of the query.
*
*
* 'full_tlist' is the
actu
al target list
* 'full_tlist' is the
origin
al target list
* 'flat_tlist' is the flattened (var-only) target list
* 'flat_tlist' is the flattened (var-only) target list
*
*
* Returns the
modified actual target list
.
* Returns the
rebuilt target list. The original is not modified
.
*
*
*/
*/
List
*
List
*
...
@@ -406,105 +341,25 @@ flatten_tlist_vars(List *full_tlist, List *flat_tlist)
...
@@ -406,105 +341,25 @@ flatten_tlist_vars(List *full_tlist, List *flat_tlist)
{
{
TargetEntry
*
tle
=
lfirst
(
x
);
TargetEntry
*
tle
=
lfirst
(
x
);
result
=
lappend
(
result
,
makeTargetEntry
(
tle
->
resdom
,
result
=
lappend
(
result
,
flatten_tlistentry
((
Node
*
)
get_expr
(
tle
),
makeTargetEntry
(
tle
->
resdom
,
flatten_tlist_vars_mutator
((
Node
*
)
get_expr
(
tle
),
flat_tlist
)));
flat_tlist
)));
}
}
return
result
;
return
result
;
}
}
/*
* flatten_tlistentry
* Replaces vars within a target list entry with vars from a flattened
* target list.
*
* 'tlistentry' is the target list entry to be modified
* 'flat_tlist' is the flattened target list
*
* Returns the (modified) target_list entry from the target list.
*
*/
static
Node
*
static
Node
*
flatten_tlist
entry
(
Node
*
tlistentry
,
List
*
flat_tlist
)
flatten_tlist
_vars_mutator
(
Node
*
node
,
List
*
flat_tlist
)
{
{
List
*
temp
;
if
(
node
==
NULL
)
if
(
tlistentry
==
NULL
)
return
NULL
;
return
NULL
;
else
if
(
IsA
(
tlistentry
,
Var
))
if
(
IsA
(
node
,
Var
))
return
(
Node
*
)
get_expr
(
match_varid
((
Var
*
)
tlistentry
,
return
(
Node
*
)
get_expr
(
match_varid
((
Var
*
)
node
,
flat_tlist
));
flat_tlist
));
else
if
(
single_node
(
tlistentry
))
return
expression_tree_mutator
(
node
,
flatten_tlist_vars_mutator
,
return
tlistentry
;
(
void
*
)
flat_tlist
);
else
if
(
IsA
(
tlistentry
,
Iter
))
{
((
Iter
*
)
tlistentry
)
->
iterexpr
=
flatten_tlistentry
((
Node
*
)
((
Iter
*
)
tlistentry
)
->
iterexpr
,
flat_tlist
);
return
tlistentry
;
}
else
if
(
is_subplan
(
tlistentry
))
{
/* do we need to support this case? */
elog
(
ERROR
,
"flatten_tlistentry: subplan case not implemented"
);
return
tlistentry
;
}
else
if
(
IsA
(
tlistentry
,
Expr
))
{
/*
* Recursively scan the arguments of an expression. NOTE: this
* must come after is_subplan() case since subplan is a kind of
* Expr node.
*/
foreach
(
temp
,
((
Expr
*
)
tlistentry
)
->
args
)
lfirst
(
temp
)
=
flatten_tlistentry
(
lfirst
(
temp
),
flat_tlist
);
return
tlistentry
;
}
else
if
(
IsA
(
tlistentry
,
Aggref
))
{
/*
* XXX shouldn't this be recursing into the agg's target? Seems to
* work though, so will leave it alone ... tgl 5/99
*/
return
tlistentry
;
}
else
if
(
IsA
(
tlistentry
,
ArrayRef
))
{
ArrayRef
*
aref
=
(
ArrayRef
*
)
tlistentry
;
foreach
(
temp
,
aref
->
refupperindexpr
)
lfirst
(
temp
)
=
flatten_tlistentry
(
lfirst
(
temp
),
flat_tlist
);
foreach
(
temp
,
aref
->
reflowerindexpr
)
lfirst
(
temp
)
=
flatten_tlistentry
(
lfirst
(
temp
),
flat_tlist
);
aref
->
refexpr
=
flatten_tlistentry
(
aref
->
refexpr
,
flat_tlist
);
aref
->
refassgnexpr
=
flatten_tlistentry
(
aref
->
refassgnexpr
,
flat_tlist
);
return
tlistentry
;
}
else
if
(
case_clause
(
tlistentry
))
{
CaseExpr
*
cexpr
=
(
CaseExpr
*
)
tlistentry
;
foreach
(
temp
,
cexpr
->
args
)
{
CaseWhen
*
cwhen
=
(
CaseWhen
*
)
lfirst
(
temp
);
cwhen
->
expr
=
flatten_tlistentry
(
cwhen
->
expr
,
flat_tlist
);
cwhen
->
result
=
flatten_tlistentry
(
cwhen
->
result
,
flat_tlist
);
}
cexpr
->
defresult
=
flatten_tlistentry
(
cexpr
->
defresult
,
flat_tlist
);
return
tlistentry
;
}
else
{
elog
(
ERROR
,
"flatten_tlistentry: Cannot handle node type %d"
,
nodeTag
(
tlistentry
));
return
tlistentry
;
}
}
}
...
@@ -522,11 +377,10 @@ Var *
...
@@ -522,11 +377,10 @@ Var *
get_groupclause_expr
(
GroupClause
*
groupClause
,
List
*
targetList
)
get_groupclause_expr
(
GroupClause
*
groupClause
,
List
*
targetList
)
{
{
List
*
l
;
List
*
l
;
TargetEntry
*
tle
;
foreach
(
l
,
targetList
)
foreach
(
l
,
targetList
)
{
{
tle
=
(
TargetEntry
*
)
lfirst
(
l
);
TargetEntry
*
tle
=
(
TargetEntry
*
)
lfirst
(
l
);
if
(
tle
->
resdom
->
resgroupref
==
groupClause
->
tleGroupref
)
if
(
tle
->
resdom
->
resgroupref
==
groupClause
->
tleGroupref
)
return
get_expr
(
tle
);
return
get_expr
(
tle
);
}
}
...
@@ -535,49 +389,3 @@ get_groupclause_expr(GroupClause *groupClause, List *targetList)
...
@@ -535,49 +389,3 @@ get_groupclause_expr(GroupClause *groupClause, List *targetList)
"get_groupclause_expr: GROUP BY expression not found in targetlist"
);
"get_groupclause_expr: GROUP BY expression not found in targetlist"
);
return
NULL
;
return
NULL
;
}
}
/*****************************************************************************
*
*****************************************************************************/
/*
* AddGroupAttrToTlist -
* append the group attribute to the target list if it's not already
* in there.
*/
#ifdef NOT_USED
/*
* WARNING!!! If this ever get's used again, the new reference
* mechanism from group clause to targetlist entry must be implemented
* here too. Jan
*/
void
AddGroupAttrToTlist
(
List
*
tlist
,
List
*
grpCl
)
{
List
*
gl
;
int
last_resdomno
=
length
(
tlist
)
+
1
;
foreach
(
gl
,
grpCl
)
{
GroupClause
*
gc
=
(
GroupClause
*
)
lfirst
(
gl
);
Var
*
var
=
gc
->
grpAttr
;
if
(
!
(
tlist_member
(
var
,
tlist
)))
{
Resdom
*
r
;
r
=
makeResdom
(
last_resdomno
,
var
->
vartype
,
var
->
vartypmod
,
NULL
,
(
Index
)
0
,
(
Oid
)
0
,
false
);
last_resdomno
++
;
tlist
=
lappend
(
tlist
,
makeTargetEntry
(
r
,
(
Node
*
)
var
));
}
}
}
#endif
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment