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
5efe3121
Commit
5efe3121
authored
Aug 09, 1999
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Clean up tlist.c tree-walking routines with
expression_tree_mutator.
parent
14f84cd8
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
88 additions
and
280 deletions
+88
-280
src/backend/optimizer/util/tlist.c
src/backend/optimizer/util/tlist.c
+88
-280
No files found.
src/backend/optimizer/util/tlist.c
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/07/16 04:59:27 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.3
7 1999/08/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'. No entry is created if 'var' is already in the tlist.
* 'rel'
*
* 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,51 +179,36 @@ tlist_resdom(List *tlist, Resdom *resnode)
...
@@ -228,51 +179,36 @@ 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,35 +287,34 @@ flatten_tlist(List *tlist)
...
@@ -350,35 +287,34 @@ 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
(
temp
,
tlist
)
{
TargetEntry
*
temp_entry
=
(
TargetEntry
*
)
lfirst
(
temp
);
tlist_vars
=
nconc
(
tlist_vars
,
pull_var_clause
((
Node
*
)
get_expr
(
temp_entry
)));
}
foreach
(
t
emp
,
tlist_vars
)
foreach
(
t
l
,
tlist
)
{
{
Var
*
var
=
lfirst
(
temp
);
TargetEntry
*
tl_entry
=
(
TargetEntry
*
)
lfirst
(
tl
);
List
*
vlist
=
pull_var_clause
((
Node
*
)
get_expr
(
tl_entry
));
List
*
v
;
if
(
!
(
tlist_member
(
var
,
new_tlist
))
)
foreach
(
v
,
vlist
)
{
{
Resdom
*
r
;
Var
*
var
=
lfirst
(
v
);
r
=
makeResdom
(
last_resdomno
,
if
(
!
tlistentry_member
(
var
,
new_tlist
))
var
->
vartype
,
{
var
->
vartypmod
,
Resdom
*
r
;
NULL
,
(
Index
)
0
,
r
=
makeResdom
(
last_resdomno
++
,
(
Oid
)
0
,
var
->
vartype
,
false
);
var
->
vartypmod
,
last_resdomno
++
;
NULL
,
new_tlist
=
lappend
(
new_tlist
,
makeTargetEntry
(
r
,
(
Node
*
)
var
));
(
Index
)
0
,
(
Oid
)
0
,
false
);
new_tlist
=
lappend
(
new_tlist
,
makeTargetEntry
(
r
,
(
Node
*
)
var
));
}
}
}
freeList
(
vlist
);
}
}
return
new_tlist
;
return
new_tlist
;
...
@@ -386,14 +322,13 @@ flatten_tlist(List *tlist)
...
@@ -386,14 +322,13 @@ flatten_tlist(List *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
,
flat_tlist
)));
flatten_tlist_vars_mutator
((
Node
*
)
get_expr
(
tle
),
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
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