Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
5efe3121
G
Gpdb
项目概览
Greenplum
/
Gpdb
通知
7
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Gpdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
5efe3121
编写于
8月 09, 1999
作者:
T
Tom Lane
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Clean up tlist.c tree-walking routines with
expression_tree_mutator.
上级
14f84cd8
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
88 addition
and
280 deletion
+88
-280
src/backend/optimizer/util/tlist.c
src/backend/optimizer/util/tlist.c
+88
-280
未找到文件。
src/backend/optimizer/util/tlist.c
浏览文件 @
5efe3121
...
...
@@ -7,21 +7,19 @@
*
*
* 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 "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/tlist.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 ----------
...
...
@@ -29,25 +27,19 @@ static Node *flatten_tlistentry(Node *tlistentry, List *flat_tlist);
/*
* tlistentry_member
*
* RETURNS: the leftmost member of sequence "targetlist" that satisfies
* the predicate "var_equal"
* MODIFIES: nothing
* REQUIRES: test = function which can operate on a lispval union
* var = valid var_node
* targetlist = valid sequence
* Finds the (first) member of the given tlist whose expression is
* var_equal() to the given var. Result is NULL if no such member.
*/
TargetEntry
*
tlistentry_member
(
Var
*
var
,
List
*
targetlist
)
{
if
(
var
)
if
(
var
&&
IsA
(
var
,
Var
)
)
{
List
*
temp
;
foreach
(
temp
,
targetlist
)
{
if
(
var_equal
(
var
,
get_expr
(
lfirst
(
temp
))))
if
(
var_equal
(
var
,
get_expr
(
lfirst
(
temp
))))
return
(
TargetEntry
*
)
lfirst
(
temp
);
}
}
...
...
@@ -56,11 +48,8 @@ tlistentry_member(Var *var, List *targetlist)
/*
* matching_tlist_var
*
* RETURNS: var node in a target list which is var_equal to 'var',
* if one exists.
* REQUIRES: "test" operates on lispval unions,
*
* Same as tlistentry_member(), except returns the tlist expression
* rather than its parent TargetEntry node.
*/
Expr
*
matching_tlist_var
(
Var
*
var
,
List
*
targetlist
)
...
...
@@ -74,54 +63,45 @@ matching_tlist_var(Var *var, List *targetlist)
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
* Creates a targetlist entry corresponding to the supplied var node
*
* 'var' and adds the new targetlist entry to the targetlist field of
* '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
* 'rel'. No entry is created if 'var' is already in the tlist.
*/
void
add_var_to_tlist
(
RelOptInfo
*
rel
,
Var
*
var
)
{
Expr
*
oldvar
;
oldvar
=
matching_tlist_var
(
var
,
rel
->
targetlist
);
/*
* If 'var' is not already in 'rel's target list, add a new node.
*/
if
(
oldvar
==
NULL
)
if
(
tlistentry_member
(
var
,
rel
->
targetlist
)
==
NULL
)
{
List
*
tlist
=
rel
->
targetlist
;
Var
*
newvar
=
makeVar
(
var
->
varno
,
var
->
varattno
,
var
->
vartype
,
var
->
vartypmod
,
var
->
varlevelsup
,
var
->
varno
,
var
->
varoattno
);
rel
->
targetlist
=
lappend
(
tlist
,
create_tl_element
(
newvar
,
length
(
tlist
)
+
1
));
/* XXX is copyObject necessary here? */
rel
->
targetlist
=
lappend
(
rel
->
targetlist
,
create_tl_element
((
Var
*
)
copyObject
(
var
),
length
(
rel
->
targetlist
)
+
1
));
}
}
/*
* create_tl_element
* Creates a target list entry node and its associated (resdom var) pair
* with its resdom number equal to 'resdomno' and the joinlist field set
* to 'joinlist'.
*
* RETURNS: newly created tlist_entry
* CREATES: new targetlist entry (always).
* with its resdom number equal to 'resdomno'.
*/
TargetEntry
*
create_tl_element
(
Var
*
var
,
int
resdomno
)
...
...
@@ -176,35 +156,6 @@ get_actual_tlist(List *tlist)
* ---------- 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.
*/
...
...
@@ -228,52 +179,37 @@ tlist_resdom(List *tlist, Resdom *resnode)
/*
* match_varid
* Searches a target list for an entry with some desired varid.
*
* 'varid' is the desired id
* 'tlist' is the target list that is searched
*
* Returns the target list entry (resdom var) of the matching var.
* Searches a target list for an entry matching a given var.
*
* Now checks to make sure array references (in addition to range
* table indices) are identical - retrieve (a.b[1],a.b[2]) should
* 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]
* Returns the target list entry (resdom var) of the matching var,
* or NULL if no match.
*/
TargetEntry
*
match_varid
(
Var
*
test_var
,
List
*
tlist
)
{
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
)
{
TargetEntry
*
entry
;
Var
*
tlvar
;
entry
=
lfirst
(
tl
);
tlvar
=
get_expr
(
entry
);
TargetEntry
*
entry
=
lfirst
(
tl
);
Var
*
tlvar
=
get_expr
(
entry
);
if
(
!
IsA
(
tlvar
,
Var
))
continue
;
/*
* we test the original varno
(
instead of varno which might be
* changed to INNER/OUTER.
* we test the original varno
,
instead of varno which might be
* changed to INNER/OUTER.
XXX is test on vartype necessary?
*/
Assert
(
tlvar
->
varlevelsup
==
0
);
if
(
tlvar
->
varnoold
==
test_var
->
varnoold
&&
tlvar
->
varoattno
==
test_var
->
varoattno
)
{
if
(
tlvar
->
vartype
==
type_var
)
tlvar
->
varoattno
==
test_var
->
varoattno
&&
tlvar
->
vartype
==
test_var
->
vartype
)
return
entry
;
}
}
return
NULL
;
}
...
...
@@ -321,11 +257,12 @@ List *
copy_vars
(
List
*
target
,
List
*
source
)
{
List
*
result
=
NIL
;
List
*
src
=
NIL
;
List
*
dest
=
NIL
;
List
*
src
;
List
*
dest
;
for
(
src
=
source
,
dest
=
target
;
src
!=
NIL
&&
dest
!=
NIL
;
src
=
lnext
(
src
),
dest
=
lnext
(
dest
))
for
(
src
=
source
,
dest
=
target
;
src
!=
NIL
&&
dest
!=
NIL
;
src
=
lnext
(
src
),
dest
=
lnext
(
dest
))
{
TargetEntry
*
temp
=
makeTargetEntry
(((
TargetEntry
*
)
lfirst
(
dest
))
->
resdom
,
(
Node
*
)
get_expr
(
lfirst
(
src
)));
...
...
@@ -350,50 +287,48 @@ flatten_tlist(List *tlist)
{
int
last_resdomno
=
1
;
List
*
new_tlist
=
NIL
;
List
*
tlist_vars
=
NIL
;
List
*
temp
;
List
*
tl
;
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
,
pull_var_clause
((
Node
*
)
get_expr
(
temp_entry
)));
}
foreach
(
temp
,
tlist_vars
)
foreach
(
v
,
vlist
)
{
Var
*
var
=
lfirst
(
temp
);
Var
*
var
=
lfirst
(
v
);
if
(
!
(
tlist_member
(
var
,
new_tlist
)
))
if
(
!
tlistentry_member
(
var
,
new_tlist
))
{
Resdom
*
r
;
r
=
makeResdom
(
last_resdomno
,
r
=
makeResdom
(
last_resdomno
++
,
var
->
vartype
,
var
->
vartypmod
,
NULL
,
(
Index
)
0
,
(
Oid
)
0
,
false
);
last_resdomno
++
;
new_tlist
=
lappend
(
new_tlist
,
makeTargetEntry
(
r
,
(
Node
*
)
var
));
new_tlist
=
lappend
(
new_tlist
,
makeTargetEntry
(
r
,
(
Node
*
)
var
));
}
}
freeList
(
vlist
);
}
return
new_tlist
;
}
/*
* flatten_tlist_vars
* Redoes the target list of a query with no nested attributes by
* replacing vars within computational expressions with vars from
* the 'flattened' target list of the query.
* Redoes the target list of a query by replacing vars within
* target expressions with vars from the 'flattened' target list.
*
* '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
*
* Returns the
modified actual target list
.
* Returns the
rebuilt target list. The original is not modified
.
*
*/
List
*
...
...
@@ -406,105 +341,25 @@ flatten_tlist_vars(List *full_tlist, List *flat_tlist)
{
TargetEntry
*
tle
=
lfirst
(
x
);
result
=
lappend
(
result
,
makeTargetEntry
(
tle
->
resdom
,
flatten_tlistentry
((
Node
*
)
get_expr
(
tle
),
result
=
lappend
(
result
,
makeTargetEntry
(
tle
->
resdom
,
flatten_tlist_vars_mutator
((
Node
*
)
get_expr
(
tle
),
flat_tlist
)));
}
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
*
flatten_tlist
entry
(
Node
*
tlistentry
,
List
*
flat_tlist
)
flatten_tlist
_vars_mutator
(
Node
*
node
,
List
*
flat_tlist
)
{
List
*
temp
;
if
(
tlistentry
==
NULL
)
if
(
node
==
NULL
)
return
NULL
;
else
if
(
IsA
(
tlistentry
,
Var
))
return
(
Node
*
)
get_expr
(
match_varid
((
Var
*
)
tlistentry
,
if
(
IsA
(
node
,
Var
))
return
(
Node
*
)
get_expr
(
match_varid
((
Var
*
)
node
,
flat_tlist
));
else
if
(
single_node
(
tlistentry
))
return
tlistentry
;
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
;
}
return
expression_tree_mutator
(
node
,
flatten_tlist_vars_mutator
,
(
void
*
)
flat_tlist
);
}
...
...
@@ -522,11 +377,10 @@ Var *
get_groupclause_expr
(
GroupClause
*
groupClause
,
List
*
targetList
)
{
List
*
l
;
TargetEntry
*
tle
;
foreach
(
l
,
targetList
)
{
tle
=
(
TargetEntry
*
)
lfirst
(
l
);
TargetEntry
*
tle
=
(
TargetEntry
*
)
lfirst
(
l
);
if
(
tle
->
resdom
->
resgroupref
==
groupClause
->
tleGroupref
)
return
get_expr
(
tle
);
}
...
...
@@ -535,49 +389,3 @@ get_groupclause_expr(GroupClause *groupClause, List *targetList)
"get_groupclause_expr: GROUP BY expression not found in targetlist"
);
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
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录