Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
35026079
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,发现更多精彩内容 >>
提交
35026079
编写于
12月 18, 2002
作者:
T
Tom Lane
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update EvalPlanQual() to work with new executor memory management method.
It doesn't leak memory anymore ...
上级
68965976
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
186 addition
and
139 deletion
+186
-139
src/backend/executor/execMain.c
src/backend/executor/execMain.c
+178
-131
src/backend/executor/execUtils.c
src/backend/executor/execUtils.c
+2
-2
src/include/nodes/execnodes.h
src/include/nodes/execnodes.h
+6
-6
未找到文件。
src/backend/executor/execMain.c
浏览文件 @
35026079
...
...
@@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.19
4 2002/12/15 21:01:34
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.19
5 2002/12/18 00:14:47
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -46,6 +46,22 @@
#include "utils/lsyscache.h"
typedef
struct
execRowMark
{
Relation
relation
;
Index
rti
;
char
resname
[
32
];
}
execRowMark
;
typedef
struct
evalPlanQual
{
Index
rti
;
EState
*
estate
;
PlanState
*
planstate
;
struct
evalPlanQual
*
next
;
/* stack of active PlanQual plans */
struct
evalPlanQual
*
free
;
/* list of free PlanQual plans */
}
evalPlanQual
;
/* decls for local routines only used within this module */
static
void
InitPlan
(
QueryDesc
*
queryDesc
);
static
void
initResultRelInfo
(
ResultRelInfo
*
resultRelInfo
,
...
...
@@ -69,6 +85,9 @@ static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
static
TupleTableSlot
*
EvalPlanQualNext
(
EState
*
estate
);
static
void
EndEvalPlanQual
(
EState
*
estate
);
static
void
ExecCheckRTEPerms
(
RangeTblEntry
*
rte
,
CmdType
operation
);
static
void
EvalPlanQualStart
(
evalPlanQual
*
epq
,
EState
*
estate
,
evalPlanQual
*
priorepq
);
static
void
EvalPlanQualStop
(
evalPlanQual
*
epq
);
/* end of local decls */
...
...
@@ -365,21 +384,6 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
* ===============================================================
*/
typedef
struct
execRowMark
{
Relation
relation
;
Index
rti
;
char
resname
[
32
];
}
execRowMark
;
typedef
struct
evalPlanQual
{
Plan
*
plan
;
/* XXX temporary */
PlanState
*
planstate
;
Index
rti
;
EState
estate
;
struct
evalPlanQual
*
free
;
}
evalPlanQual
;
/* ----------------------------------------------------------------
* InitPlan
...
...
@@ -518,10 +522,10 @@ InitPlan(QueryDesc *queryDesc)
}
/* mark EvalPlanQual not active */
estate
->
es_
orig
Plan
=
plan
;
estate
->
es_
top
Plan
=
plan
;
estate
->
es_evalPlanQual
=
NULL
;
estate
->
es_evTuple
=
NULL
;
estate
->
es_evTupleNull
=
NULL
;
estate
->
es_evTuple
=
NULL
;
estate
->
es_useEvalPlan
=
false
;
/*
...
...
@@ -1594,7 +1598,6 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
Relation
relation
;
HeapTupleData
tuple
;
HeapTuple
copyTuple
=
NULL
;
int
rtsize
;
bool
endNode
;
Assert
(
rti
!=
0
);
...
...
@@ -1686,15 +1689,13 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
/*
* Need to run a recheck subquery. Find or create a PQ stack entry.
*/
epq
=
(
evalPlanQual
*
)
estate
->
es_evalPlanQual
;
rtsize
=
length
(
estate
->
es_range_table
);
epq
=
estate
->
es_evalPlanQual
;
endNode
=
true
;
if
(
epq
!=
NULL
&&
epq
->
rti
==
0
)
{
/* Top PQ stack entry is idle, so re-use it */
Assert
(
!
(
estate
->
es_useEvalPlan
)
&&
epq
->
estate
.
es_evalPlanQual
==
NULL
);
Assert
(
!
(
estate
->
es_useEvalPlan
)
&&
epq
->
next
==
NULL
);
epq
->
rti
=
rti
;
endNode
=
false
;
}
...
...
@@ -1706,26 +1707,21 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
* forget all what we done after Ra was suspended. Cool? -:))
*/
if
(
epq
!=
NULL
&&
epq
->
rti
!=
rti
&&
epq
->
estate
.
es_evTuple
[
rti
-
1
]
!=
NULL
)
epq
->
estate
->
es_evTuple
[
rti
-
1
]
!=
NULL
)
{
do
{
evalPlanQual
*
oldepq
;
/* pop previous PlanQual from the stack */
epqstate
=
&
(
epq
->
estate
);
oldepq
=
(
evalPlanQual
*
)
epqstate
->
es_evalPlanQual
;
Assert
(
oldepq
->
rti
!=
0
);
/* stop execution */
ExecEndNode
(
epq
->
planstate
);
ExecDropTupleTable
(
epqstate
->
es_tupleTable
,
true
);
epqstate
->
es_tupleTable
=
NULL
;
heap_freetuple
(
epqstate
->
es_evTuple
[
epq
->
rti
-
1
]);
epqstate
->
es_evTuple
[
epq
->
rti
-
1
]
=
NULL
;
EvalPlanQualStop
(
epq
);
/* pop previous PlanQual from the stack */
oldepq
=
epq
->
next
;
Assert
(
oldepq
&&
oldepq
->
rti
!=
0
);
/* push current PQ to freePQ stack */
oldepq
->
free
=
epq
;
epq
=
oldepq
;
estate
->
es_evalPlanQual
=
(
Pointer
)
epq
;
estate
->
es_evalPlanQual
=
epq
;
}
while
(
epq
->
rti
!=
rti
);
}
...
...
@@ -1740,62 +1736,26 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
if
(
newepq
==
NULL
)
/* first call or freePQ stack is empty */
{
newepq
=
(
evalPlanQual
*
)
palloc
(
sizeof
(
evalPlanQual
));
newepq
=
(
evalPlanQual
*
)
palloc
0
(
sizeof
(
evalPlanQual
));
newepq
->
free
=
NULL
;
/*
* Each stack level has its own copy of the plan tree. This
* is wasteful, but necessary until plan trees are fully
* read-only.
*/
newepq
->
plan
=
copyObject
(
estate
->
es_origPlan
);
/*
* Init stack level's EState. We share top level's copy of
* es_result_relations array and other non-changing status. We
* need our own tupletable, es_param_exec_vals, and other
* changeable state.
*/
epqstate
=
&
(
newepq
->
estate
);
memcpy
(
epqstate
,
estate
,
sizeof
(
EState
));
epqstate
->
es_direction
=
ForwardScanDirection
;
if
(
estate
->
es_origPlan
->
nParamExec
>
0
)
epqstate
->
es_param_exec_vals
=
(
ParamExecData
*
)
palloc
(
estate
->
es_origPlan
->
nParamExec
*
sizeof
(
ParamExecData
));
epqstate
->
es_tupleTable
=
NULL
;
epqstate
->
es_per_tuple_exprcontext
=
NULL
;
/*
* Each epqstate must have its own es_evTupleNull state, but
* all the stack entries share es_evTuple state. This allows
* sub-rechecks to inherit the value being examined by an
* outer recheck.
*/
epqstate
->
es_evTupleNull
=
(
bool
*
)
palloc
(
rtsize
*
sizeof
(
bool
));
if
(
epq
==
NULL
)
/* first PQ stack entry */
epqstate
->
es_evTuple
=
(
HeapTuple
*
)
palloc0
(
rtsize
*
sizeof
(
HeapTuple
));
else
/* later stack entries share the same storage */
epqstate
->
es_evTuple
=
epq
->
estate
.
es_evTuple
;
newepq
->
estate
=
NULL
;
newepq
->
planstate
=
NULL
;
}
else
{
/* recycle previously used EState */
epqstate
=
&
(
newepq
->
estate
);
/* recycle previously used PlanQual */
Assert
(
newepq
->
estate
==
NULL
);
epq
->
free
=
NULL
;
}
/* push current PQ to the stack */
epqstate
->
es_evalPlanQual
=
(
Pointer
)
epq
;
newepq
->
next
=
epq
;
epq
=
newepq
;
estate
->
es_evalPlanQual
=
(
Pointer
)
epq
;
estate
->
es_evalPlanQual
=
epq
;
epq
->
rti
=
rti
;
endNode
=
false
;
}
Assert
(
epq
->
rti
==
rti
);
epqstate
=
&
(
epq
->
estate
);
/*
* Ok - we're requested for the same RTE. Unfortunately we still have
...
...
@@ -1804,81 +1764,78 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
* could make that work if insertion of the target tuple were
* integrated with the Param mechanism somehow, so that the upper plan
* nodes know that their children's outputs have changed.
*
* Note that the stack of free evalPlanQual nodes is quite useless at
* the moment, since it only saves us from pallocing/releasing the
* evalPlanQual nodes themselves. But it will be useful once we
* implement ReScan instead of end/restart for re-using PlanQual nodes.
*/
if
(
endNode
)
{
/* stop execution */
ExecEndNode
(
epq
->
planstate
);
ExecDropTupleTable
(
epqstate
->
es_tupleTable
,
true
);
epqstate
->
es_tupleTable
=
NULL
;
EvalPlanQualStop
(
epq
);
}
/*
* Initialize new recheck query.
*
* Note: if we were re-using PlanQual plans via ExecReScan, we'd need
* to instead copy down changeable state from the top plan (including
* es_result_relation_info, es_junkFilter) and reset locally changeable
* state in the epq (including es_param_exec_vals, es_evTupleNull).
*/
EvalPlanQualStart
(
epq
,
estate
,
epq
->
next
);
/*
* free old RTE' tuple, if any, and store target tuple where
* relation's scan node will see it
*/
epqstate
=
epq
->
estate
;
if
(
epqstate
->
es_evTuple
[
rti
-
1
]
!=
NULL
)
heap_freetuple
(
epqstate
->
es_evTuple
[
rti
-
1
]);
epqstate
->
es_evTuple
[
rti
-
1
]
=
copyTuple
;
/*
* Initialize for new recheck query; be careful to copy down state
* that might have changed in top EState.
*/
epqstate
->
es_result_relation_info
=
estate
->
es_result_relation_info
;
epqstate
->
es_junkFilter
=
estate
->
es_junkFilter
;
if
(
estate
->
es_origPlan
->
nParamExec
>
0
)
memset
(
epqstate
->
es_param_exec_vals
,
0
,
estate
->
es_origPlan
->
nParamExec
*
sizeof
(
ParamExecData
));
memset
(
epqstate
->
es_evTupleNull
,
false
,
rtsize
*
sizeof
(
bool
));
epqstate
->
es_useEvalPlan
=
false
;
Assert
(
epqstate
->
es_tupleTable
==
NULL
);
epqstate
->
es_tupleTable
=
ExecCreateTupleTable
(
estate
->
es_tupleTable
->
size
);
epq
->
planstate
=
ExecInitNode
(
epq
->
plan
,
epqstate
);
return
EvalPlanQualNext
(
estate
);
}
static
TupleTableSlot
*
EvalPlanQualNext
(
EState
*
estate
)
{
evalPlanQual
*
epq
=
(
evalPlanQual
*
)
estate
->
es_evalPlanQual
;
EState
*
epqstate
=
&
(
epq
->
estate
);
evalPlanQual
*
oldepq
;
evalPlanQual
*
epq
=
estate
->
es_evalPlanQual
;
MemoryContext
oldcontext
;
TupleTableSlot
*
slot
;
Assert
(
epq
->
rti
!=
0
);
lpqnext:
;
oldcontext
=
MemoryContextSwitchTo
(
epq
->
estate
->
es_query_cxt
);
slot
=
ExecProcNode
(
epq
->
planstate
);
MemoryContextSwitchTo
(
oldcontext
);
/*
* No more tuples for this PQ. Continue previous one.
*/
if
(
TupIsNull
(
slot
))
{
evalPlanQual
*
oldepq
;
/* stop execution */
ExecEndNode
(
epq
->
planstate
);
ExecDropTupleTable
(
epqstate
->
es_tupleTable
,
true
);
epqstate
->
es_tupleTable
=
NULL
;
heap_freetuple
(
epqstate
->
es_evTuple
[
epq
->
rti
-
1
]);
epqstate
->
es_evTuple
[
epq
->
rti
-
1
]
=
NULL
;
EvalPlanQualStop
(
epq
);
/* pop old PQ from the stack */
oldepq
=
(
evalPlanQual
*
)
epqstate
->
es_evalPlanQual
;
if
(
oldepq
==
(
evalPlanQual
*
)
NULL
)
oldepq
=
epq
->
next
;
if
(
oldepq
==
NULL
)
{
epq
->
rti
=
0
;
/* this is the first (oldest) */
estate
->
es_useEvalPlan
=
false
;
/* PQ - mark as free and */
return
(
NULL
);
/* continue Query execution */
/* this is the first (oldest) PQ - mark as free */
epq
->
rti
=
0
;
estate
->
es_useEvalPlan
=
false
;
/* and continue Query execution */
return
(
NULL
);
}
Assert
(
oldepq
->
rti
!=
0
);
/* push current PQ to freePQ stack */
oldepq
->
free
=
epq
;
epq
=
oldepq
;
epqstate
=
&
(
epq
->
estate
);
estate
->
es_evalPlanQual
=
(
Pointer
)
epq
;
estate
->
es_evalPlanQual
=
epq
;
goto
lpqnext
;
}
...
...
@@ -1888,40 +1845,130 @@ lpqnext:;
static
void
EndEvalPlanQual
(
EState
*
estate
)
{
evalPlanQual
*
epq
=
(
evalPlanQual
*
)
estate
->
es_evalPlanQual
;
EState
*
epqstate
=
&
(
epq
->
estate
);
evalPlanQual
*
oldepq
;
evalPlanQual
*
epq
=
estate
->
es_evalPlanQual
;
if
(
epq
->
rti
==
0
)
/* plans already shutdowned */
{
Assert
(
epq
->
estate
.
es_evalPlanQual
==
NULL
);
Assert
(
epq
->
next
==
NULL
);
return
;
}
for
(;;)
{
evalPlanQual
*
oldepq
;
/* stop execution */
ExecEndNode
(
epq
->
planstate
);
ExecDropTupleTable
(
epqstate
->
es_tupleTable
,
true
);
epqstate
->
es_tupleTable
=
NULL
;
if
(
epqstate
->
es_evTuple
[
epq
->
rti
-
1
]
!=
NULL
)
{
heap_freetuple
(
epqstate
->
es_evTuple
[
epq
->
rti
-
1
]);
epqstate
->
es_evTuple
[
epq
->
rti
-
1
]
=
NULL
;
}
EvalPlanQualStop
(
epq
);
/* pop old PQ from the stack */
oldepq
=
(
evalPlanQual
*
)
epqstate
->
es_evalPlanQual
;
if
(
oldepq
==
(
evalPlanQual
*
)
NULL
)
oldepq
=
epq
->
next
;
if
(
oldepq
==
NULL
)
{
epq
->
rti
=
0
;
/* this is the first (oldest) */
estate
->
es_useEvalPlan
=
false
;
/* PQ - mark as free */
/* this is the first (oldest) PQ - mark as free */
epq
->
rti
=
0
;
estate
->
es_useEvalPlan
=
false
;
break
;
}
Assert
(
oldepq
->
rti
!=
0
);
/* push current PQ to freePQ stack */
oldepq
->
free
=
epq
;
epq
=
oldepq
;
epqstate
=
&
(
epq
->
estate
);
estate
->
es_evalPlanQual
=
(
Pointer
)
epq
;
estate
->
es_evalPlanQual
=
epq
;
}
}
/*
* Start execution of one level of PlanQual.
*
* This is a cut-down version of ExecutorStart(): we copy some state from
* the top-level estate rather than initializing it fresh.
*/
static
void
EvalPlanQualStart
(
evalPlanQual
*
epq
,
EState
*
estate
,
evalPlanQual
*
priorepq
)
{
EState
*
epqstate
;
int
rtsize
;
MemoryContext
oldcontext
;
rtsize
=
length
(
estate
->
es_range_table
);
epq
->
estate
=
epqstate
=
CreateExecutorState
();
oldcontext
=
MemoryContextSwitchTo
(
epqstate
->
es_query_cxt
);
/*
* The epqstates share the top query's copy of unchanging state such
* as the snapshot, rangetable, result-rel info, and external Param info.
* They need their own copies of local state, including a tuple table,
* es_param_exec_vals, etc.
*/
epqstate
->
es_direction
=
ForwardScanDirection
;
epqstate
->
es_snapshot
=
estate
->
es_snapshot
;
epqstate
->
es_range_table
=
estate
->
es_range_table
;
epqstate
->
es_result_relations
=
estate
->
es_result_relations
;
epqstate
->
es_num_result_relations
=
estate
->
es_num_result_relations
;
epqstate
->
es_result_relation_info
=
estate
->
es_result_relation_info
;
epqstate
->
es_junkFilter
=
estate
->
es_junkFilter
;
epqstate
->
es_into_relation_descriptor
=
estate
->
es_into_relation_descriptor
;
epqstate
->
es_param_list_info
=
estate
->
es_param_list_info
;
if
(
estate
->
es_topPlan
->
nParamExec
>
0
)
epqstate
->
es_param_exec_vals
=
(
ParamExecData
*
)
palloc0
(
estate
->
es_topPlan
->
nParamExec
*
sizeof
(
ParamExecData
));
epqstate
->
es_rowMark
=
estate
->
es_rowMark
;
epqstate
->
es_instrument
=
estate
->
es_instrument
;
epqstate
->
es_topPlan
=
estate
->
es_topPlan
;
/*
* Each epqstate must have its own es_evTupleNull state, but
* all the stack entries share es_evTuple state. This allows
* sub-rechecks to inherit the value being examined by an
* outer recheck.
*/
epqstate
->
es_evTupleNull
=
(
bool
*
)
palloc0
(
rtsize
*
sizeof
(
bool
));
if
(
priorepq
==
NULL
)
/* first PQ stack entry */
epqstate
->
es_evTuple
=
(
HeapTuple
*
)
palloc0
(
rtsize
*
sizeof
(
HeapTuple
));
else
/* later stack entries share the same storage */
epqstate
->
es_evTuple
=
priorepq
->
estate
->
es_evTuple
;
epqstate
->
es_tupleTable
=
ExecCreateTupleTable
(
estate
->
es_tupleTable
->
size
);
epq
->
planstate
=
ExecInitNode
(
estate
->
es_topPlan
,
epqstate
);
MemoryContextSwitchTo
(
oldcontext
);
}
/*
* End execution of one level of PlanQual.
*
* This is a cut-down version of ExecutorEnd(); basically we want to do most
* of the normal cleanup, but *not* close result relations (which we are
* just sharing from the outer query).
*/
static
void
EvalPlanQualStop
(
evalPlanQual
*
epq
)
{
EState
*
epqstate
=
epq
->
estate
;
MemoryContext
oldcontext
;
oldcontext
=
MemoryContextSwitchTo
(
epqstate
->
es_query_cxt
);
ExecEndNode
(
epq
->
planstate
);
ExecDropTupleTable
(
epqstate
->
es_tupleTable
,
true
);
epqstate
->
es_tupleTable
=
NULL
;
if
(
epqstate
->
es_evTuple
[
epq
->
rti
-
1
]
!=
NULL
)
{
heap_freetuple
(
epqstate
->
es_evTuple
[
epq
->
rti
-
1
]);
epqstate
->
es_evTuple
[
epq
->
rti
-
1
]
=
NULL
;
}
MemoryContextSwitchTo
(
oldcontext
);
FreeExecutorState
(
epqstate
);
epq
->
estate
=
NULL
;
epq
->
planstate
=
NULL
;
}
src/backend/executor/execUtils.c
浏览文件 @
35026079
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.9
3 2002/12/15 16:17:46
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.9
4 2002/12/18 00:14:47
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -204,7 +204,7 @@ CreateExecutorState(void)
estate
->
es_per_tuple_exprcontext
=
NULL
;
estate
->
es_
orig
Plan
=
NULL
;
estate
->
es_
top
Plan
=
NULL
;
estate
->
es_evalPlanQual
=
NULL
;
estate
->
es_evTupleNull
=
NULL
;
estate
->
es_evTuple
=
NULL
;
...
...
src/include/nodes/execnodes.h
浏览文件 @
35026079
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: execnodes.h,v 1.8
7 2002/12/15 21:01:34
tgl Exp $
* $Id: execnodes.h,v 1.8
8 2002/12/18 00:14:47
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -316,11 +316,11 @@ typedef struct EState
ExprContext
*
es_per_tuple_exprcontext
;
/* Below is to re-evaluate plan qual in READ COMMITTED mode */
struct
Plan
*
es_origPlan
;
Pointer
es_evalPlanQual
;
bool
*
es_evTupleNull
;
HeapTuple
*
es_evTuple
;
bool
es_useEvalPlan
;
Plan
*
es_topPlan
;
/* link to top of plan tree */
struct
evalPlanQual
*
es_evalPlanQual
;
/* chain of PlanQual states */
bool
*
es_evTupleNull
;
/* local array of EPQ status */
HeapTuple
*
es_evTuple
;
/* shared array of EPQ substitute tuples */
bool
es_useEvalPlan
;
/* evaluating EPQ tuples? */
}
EState
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录