Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
cc9bcbc8
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,发现更多精彩内容 >>
提交
cc9bcbc8
编写于
7月 03, 2005
作者:
T
Tom Lane
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Improve outer-join-deduction logic to be able to propagate equalities
through multiple join clauses.
上级
76eca0ec
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
202 addition
and
157 deletion
+202
-157
src/backend/optimizer/path/pathkeys.c
src/backend/optimizer/path/pathkeys.c
+202
-157
未找到文件。
src/backend/optimizer/path/pathkeys.c
浏览文件 @
cc9bcbc8
...
...
@@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.
69 2005/07/02 23:00:40
tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.
70 2005/07/03 18:26:32
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -35,6 +35,10 @@ static PathKeyItem *makePathKeyItem(Node *key, Oid sortop, bool checkType);
static
void
generate_outer_join_implications
(
PlannerInfo
*
root
,
List
*
equi_key_set
,
Relids
*
relids
);
static
void
sub_generate_join_implications
(
PlannerInfo
*
root
,
List
*
equi_key_set
,
Relids
*
relids
,
Node
*
item1
,
Oid
sortop1
,
Relids
item1_relids
);
static
void
process_implied_const_eq
(
PlannerInfo
*
root
,
List
*
equi_key_set
,
Relids
*
relids
,
Node
*
item1
,
Oid
sortop1
,
...
...
@@ -250,65 +254,65 @@ generate_implied_equalities(PlannerInfo *root)
i1
++
;
}
/*
* If we have constant(s) and outer joins, try to propagate the
* constants through outer-join quals.
*/
if
(
have_consts
&&
root
->
hasOuterJoins
)
generate_outer_join_implications
(
root
,
curset
,
relids
);
/*
* A set containing only two items cannot imply any equalities
* beyond the one that created the set, so we can skip it.
*/
if
(
nitems
<
3
)
continue
;
/*
* Match each item in the set with all that appear after it (it's
* sufficient to generate A=B, need not process B=A too).
*
* A set containing only two items cannot imply any equalities
* beyond the one that created the set, so we can skip this
* processing in that case.
*/
i1
=
0
;
foreach
(
ptr1
,
curset
)
if
(
nitems
>=
3
)
{
PathKeyItem
*
item1
=
(
PathKeyItem
*
)
lfirst
(
ptr1
);
bool
i1_is_variable
=
!
bms_is_empty
(
relids
[
i1
]);
ListCell
*
ptr2
;
int
i2
=
i1
+
1
;
for_each_cell
(
ptr2
,
lnext
(
ptr1
))
i1
=
0
;
foreach
(
ptr1
,
curset
)
{
PathKeyItem
*
item2
=
(
PathKeyItem
*
)
lfirst
(
ptr2
);
bool
i2_is_variable
=
!
bms_is_empty
(
relids
[
i2
]);
PathKeyItem
*
item1
=
(
PathKeyItem
*
)
lfirst
(
ptr1
);
bool
i1_is_variable
=
!
bms_is_empty
(
relids
[
i1
]);
ListCell
*
ptr2
;
int
i2
=
i1
+
1
;
/*
* If it's "const = const" then just ignore it altogether.
* There is no place in the restrictinfo structure to
* store it. (If the two consts are in fact unequal, then
* propagating the comparison to Vars will cause us to
* produce zero rows out, as expected.)
*/
if
(
i1_is_variable
||
i2_is_variable
)
for_each_cell
(
ptr2
,
lnext
(
ptr1
))
{
PathKeyItem
*
item2
=
(
PathKeyItem
*
)
lfirst
(
ptr2
);
bool
i2_is_variable
=
!
bms_is_empty
(
relids
[
i2
]);
/*
* Tell process_implied_equality to delete the clause,
* not add it, if it's "var = var" and we have
* constants present in the list.
* If it's "const = const" then just ignore it altogether.
* There is no place in the restrictinfo structure to
* store it. (If the two consts are in fact unequal, then
* propagating the comparison to Vars will cause us to
* produce zero rows out, as expected.)
*/
bool
delete_it
=
(
have_consts
&&
i1_is_variable
&&
i2_is_variable
);
process_implied_equality
(
root
,
item1
->
key
,
item2
->
key
,
item1
->
sortop
,
item2
->
sortop
,
relids
[
i1
],
relids
[
i2
],
delete_it
);
if
(
i1_is_variable
||
i2_is_variable
)
{
/*
* Tell process_implied_equality to delete the clause,
* not add it, if it's "var = var" and we have
* constants present in the list.
*/
bool
delete_it
=
(
have_consts
&&
i1_is_variable
&&
i2_is_variable
);
process_implied_equality
(
root
,
item1
->
key
,
item2
->
key
,
item1
->
sortop
,
item2
->
sortop
,
relids
[
i1
],
relids
[
i2
],
delete_it
);
}
i2
++
;
}
i
2
++
;
i
1
++
;
}
i1
++
;
}
/*
* If we have constant(s) and outer joins, try to propagate the
* constants through outer-join quals.
*/
if
(
have_consts
&&
root
->
hasOuterJoins
)
generate_outer_join_implications
(
root
,
curset
,
relids
);
}
}
...
...
@@ -362,118 +366,154 @@ generate_outer_join_implications(PlannerInfo *root,
List
*
equi_key_set
,
Relids
*
relids
)
{
ListCell
*
l1
;
ListCell
*
l
;
int
i
=
0
;
/*
Examine each mergejoinable outer-join clause with OUTERVAR on lef
t */
foreach
(
l
1
,
root
->
left_join_clauses
)
/*
Process each non-constant element of equi_key_se
t */
foreach
(
l
,
equi_key_set
)
{
RestrictInfo
*
rinfo
=
(
RestrictInfo
*
)
lfirst
(
l1
);
Node
*
leftop
=
get_leftop
(
rinfo
->
clause
);
Node
*
rightop
=
get_rightop
(
rinfo
->
clause
);
ListCell
*
l2
;
PathKeyItem
*
item1
=
(
PathKeyItem
*
)
lfirst
(
l
);
/* Scan to see if it matches any element of equi_key_set */
foreach
(
l2
,
equi_key_set
)
if
(
!
bms_is_empty
(
relids
[
i
]))
{
PathKeyItem
*
item1
=
(
PathKeyItem
*
)
lfirst
(
l2
);
sub_generate_join_implications
(
root
,
equi_key_set
,
relids
,
item1
->
key
,
item1
->
sortop
,
relids
[
i
]);
}
i
++
;
}
}
if
(
equal
(
leftop
,
item1
->
key
)
&&
rinfo
->
left_sortop
==
item1
->
sortop
)
{
/*
* Yes, so find constant member(s) of set and generate
* implied INNERVAR = CONSTANT
*/
process_implied_const_eq
(
root
,
equi_key_set
,
relids
,
rightop
,
rinfo
->
right_sortop
,
rinfo
->
right_relids
,
false
);
/*
* We can remove the explicit outer join qual, too,
* since we now have tests forcing each of its sides
* to the same value.
*/
process_implied_equality
(
root
,
leftop
,
rightop
,
rinfo
->
left_sortop
,
rinfo
->
right_sortop
,
rinfo
->
left_relids
,
rinfo
->
right_relids
,
true
);
/*
* sub_generate_join_implications
* Propagate a constant equality through outer join clauses.
*
* The item described by item1/sortop1/item1_relids has been determined
* to be equal to the constant(s) listed in equi_key_set. Recursively
* trace out the implications of this.
*
* equi_key_set and relids are as for generate_outer_join_implications.
*/
static
void
sub_generate_join_implications
(
PlannerInfo
*
root
,
List
*
equi_key_set
,
Relids
*
relids
,
Node
*
item1
,
Oid
sortop1
,
Relids
item1_relids
)
/* No need to match against remaining set members */
break
;
}
{
ListCell
*
l
;
/*
* Examine each mergejoinable outer-join clause with OUTERVAR on left,
* looking for an OUTERVAR identical to item1
*/
foreach
(
l
,
root
->
left_join_clauses
)
{
RestrictInfo
*
rinfo
=
(
RestrictInfo
*
)
lfirst
(
l
);
Node
*
leftop
=
get_leftop
(
rinfo
->
clause
);
if
(
equal
(
leftop
,
item1
)
&&
rinfo
->
left_sortop
==
sortop1
)
{
/*
* Match, so find constant member(s) of set and generate
* implied INNERVAR = CONSTANT
*/
Node
*
rightop
=
get_rightop
(
rinfo
->
clause
);
process_implied_const_eq
(
root
,
equi_key_set
,
relids
,
rightop
,
rinfo
->
right_sortop
,
rinfo
->
right_relids
,
false
);
/*
* We can remove explicit tests of this outer-join qual, too,
* since we now have tests forcing each of its sides
* to the same value.
*/
process_implied_equality
(
root
,
leftop
,
rightop
,
rinfo
->
left_sortop
,
rinfo
->
right_sortop
,
rinfo
->
left_relids
,
rinfo
->
right_relids
,
true
);
/*
* And recurse to see if we can deduce anything from
* INNERVAR = CONSTANT
*/
sub_generate_join_implications
(
root
,
equi_key_set
,
relids
,
rightop
,
rinfo
->
right_sortop
,
rinfo
->
right_relids
);
}
}
/*
Examine each mergejoinable outer-join clause
with OUTERVAR on right */
foreach
(
l
1
,
root
->
right_join_clauses
)
/*
The same, looking at clauses
with OUTERVAR on right */
foreach
(
l
,
root
->
right_join_clauses
)
{
RestrictInfo
*
rinfo
=
(
RestrictInfo
*
)
lfirst
(
l1
);
Node
*
leftop
=
get_leftop
(
rinfo
->
clause
);
RestrictInfo
*
rinfo
=
(
RestrictInfo
*
)
lfirst
(
l
);
Node
*
rightop
=
get_rightop
(
rinfo
->
clause
);
ListCell
*
l2
;
/* Scan to see if it matches any element of equi_key_set */
foreach
(
l2
,
equi_key_set
)
if
(
equal
(
rightop
,
item1
)
&&
rinfo
->
right_sortop
==
sortop1
)
{
PathKeyItem
*
item1
=
(
PathKeyItem
*
)
lfirst
(
l2
);
if
(
equal
(
rightop
,
item1
->
key
)
&&
rinfo
->
right_sortop
==
item1
->
sortop
)
{
/*
* Yes, so find constant member(s) of set and generate
* implied INNERVAR = CONSTANT
*/
process_implied_const_eq
(
root
,
equi_key_set
,
relids
,
leftop
,
rinfo
->
left_sortop
,
rinfo
->
left_relids
,
false
);
/*
* We can remove the explicit outer join qual, too,
* since we now have tests forcing each of its sides
* to the same value.
*/
process_implied_equality
(
root
,
leftop
,
rightop
,
rinfo
->
left_sortop
,
rinfo
->
right_sortop
,
rinfo
->
left_relids
,
rinfo
->
right_relids
,
true
);
/*
* Match, so find constant member(s) of set and generate
* implied INNERVAR = CONSTANT
*/
Node
*
leftop
=
get_leftop
(
rinfo
->
clause
);
/* No need to match against remaining set members */
break
;
}
process_implied_const_eq
(
root
,
equi_key_set
,
relids
,
leftop
,
rinfo
->
left_sortop
,
rinfo
->
left_relids
,
false
);
/*
* We can remove explicit tests of this outer-join qual, too,
* since we now have tests forcing each of its sides
* to the same value.
*/
process_implied_equality
(
root
,
leftop
,
rightop
,
rinfo
->
left_sortop
,
rinfo
->
right_sortop
,
rinfo
->
left_relids
,
rinfo
->
right_relids
,
true
);
/*
* And recurse to see if we can deduce anything from
* INNERVAR = CONSTANT
*/
sub_generate_join_implications
(
root
,
equi_key_set
,
relids
,
leftop
,
rinfo
->
left_sortop
,
rinfo
->
left_relids
);
}
}
/* Examine each mergejoinable full-join clause */
foreach
(
l1
,
root
->
full_join_clauses
)
/*
* Only COALESCE(x,y) items can possibly match full joins
*/
if
(
IsA
(
item1
,
CoalesceExpr
))
{
RestrictInfo
*
rinfo
=
(
RestrictInfo
*
)
lfirst
(
l1
);
Node
*
leftop
=
get_leftop
(
rinfo
->
clause
);
Node
*
rightop
=
get_rightop
(
rinfo
->
clause
);
int
i1
=
0
;
ListCell
*
l2
;
CoalesceExpr
*
cexpr
=
(
CoalesceExpr
*
)
item1
;
Node
*
cfirst
;
Node
*
csecond
;
/* Scan to see if it matches any element of equi_key_set */
foreach
(
l2
,
equi_key_set
)
if
(
list_length
(
cexpr
->
args
)
!=
2
)
return
;
cfirst
=
(
Node
*
)
linitial
(
cexpr
->
args
);
csecond
=
(
Node
*
)
lsecond
(
cexpr
->
args
);
/*
* Examine each mergejoinable full-join clause, looking for a
* clause of the form "x = y" matching the COALESCE(x,y) expression
*/
foreach
(
l
,
root
->
full_join_clauses
)
{
PathKeyItem
*
item1
=
(
PathKeyItem
*
)
lfirst
(
l2
);
CoalesceExpr
*
cexpr
=
(
CoalesceExpr
*
)
item1
->
key
;
RestrictInfo
*
rinfo
=
(
RestrictInfo
*
)
lfirst
(
l
);
Node
*
leftop
=
get_leftop
(
rinfo
->
clause
);
Node
*
rightop
=
get_rightop
(
rinfo
->
clause
);
/*
* Try to match a pathkey containing a COALESCE() expression
* to the join clause. We can assume the COALESCE() inputs
* are in the same order as the join clause, since both were
* automatically generated in the cases we care about.
* We can assume the COALESCE() inputs are in the same order
* as the join clause, since both were automatically generated
* in the cases we care about.
*
* XXX currently this may fail to match in cross-type cases
* because the COALESCE will contain typecast operations while
...
...
@@ -482,15 +522,13 @@ generate_outer_join_implications(PlannerInfo *root,
* Is it OK to strip implicit coercions from the COALESCE
* arguments? What of the sortops in such cases?
*/
if
(
IsA
(
cexpr
,
CoalesceExpr
)
&&
list_length
(
cexpr
->
args
)
==
2
&&
equal
(
leftop
,
(
Node
*
)
linitial
(
cexpr
->
args
))
&&
equal
(
rightop
,
(
Node
*
)
lsecond
(
cexpr
->
args
))
&&
rinfo
->
left_sortop
==
item1
->
sortop
&&
rinfo
->
right_sortop
==
item1
->
sortop
)
if
(
equal
(
leftop
,
cfirst
)
&&
equal
(
rightop
,
csecond
)
&&
rinfo
->
left_sortop
==
sortop1
&&
rinfo
->
right_sortop
==
sortop1
)
{
/*
*
Yes
, so find constant member(s) of set and generate
*
Match
, so find constant member(s) of set and generate
* implied LEFTVAR = CONSTANT
*/
process_implied_const_eq
(
root
,
equi_key_set
,
relids
,
...
...
@@ -506,28 +544,37 @@ generate_outer_join_implications(PlannerInfo *root,
false
);
/* ... and remove COALESCE() = CONSTANT */
process_implied_const_eq
(
root
,
equi_key_set
,
relids
,
item1
->
key
,
item1
->
sortop
,
relids
[
i1
]
,
item1
,
sortop1
,
item1_relids
,
true
);
/*
* We can remove
the explicit outer
join qual, too,
* We can remove
explicit tests of this outer-
join qual, too,
* since we now have tests forcing each of its sides
* to the same value.
*/
process_implied_equality
(
root
,
leftop
,
rightop
,
leftop
,
rightop
,
rinfo
->
left_sortop
,
rinfo
->
right_sortop
,
rinfo
->
left_relids
,
rinfo
->
right_relids
,
true
);
/*
* And recurse to see if we can deduce anything from
* LEFTVAR = CONSTANT
*/
sub_generate_join_implications
(
root
,
equi_key_set
,
relids
,
leftop
,
rinfo
->
left_sortop
,
rinfo
->
left_relids
);
/* ... and RIGHTVAR = CONSTANT */
sub_generate_join_implications
(
root
,
equi_key_set
,
relids
,
rightop
,
rinfo
->
right_sortop
,
rinfo
->
right_relids
);
/* No need to match against remaining set members */
break
;
}
i1
++
;
}
}
}
...
...
@@ -537,10 +584,8 @@ generate_outer_join_implications(PlannerInfo *root,
* Apply process_implied_equality with the given item and each
* pseudoconstant member of equi_key_set.
*
* This is just a subroutine to save some cruft in
* generate_outer_join_implications. equi_key_set and relids are as in
* generate_outer_join_implications, the other parameters as for
* process_implied_equality.
* equi_key_set and relids are as for generate_outer_join_implications,
* the other parameters as for process_implied_equality.
*/
static
void
process_implied_const_eq
(
PlannerInfo
*
root
,
List
*
equi_key_set
,
Relids
*
relids
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录