Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
c9fe1283
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,发现更多精彩内容 >>
提交
c9fe1283
编写于
1月 22, 2001
作者:
T
Tom Lane
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Clean up per-tuple memory leaks in trigger firing and plpgsql
expression evaluation.
上级
59a3a401
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
160 addition
and
147 deletion
+160
-147
src/backend/commands/copy.c
src/backend/commands/copy.c
+6
-3
src/backend/commands/trigger.c
src/backend/commands/trigger.c
+57
-30
src/backend/executor/execMain.c
src/backend/executor/execMain.c
+33
-29
src/backend/executor/execUtils.c
src/backend/executor/execUtils.c
+23
-15
src/backend/executor/nodeIndexscan.c
src/backend/executor/nodeIndexscan.c
+1
-10
src/include/commands/trigger.h
src/include/commands/trigger.h
+9
-6
src/include/executor/executor.h
src/include/executor/executor.h
+19
-1
src/include/nodes/execnodes.h
src/include/nodes/execnodes.h
+2
-2
src/pl/plpgsql/src/pl_exec.c
src/pl/plpgsql/src/pl_exec.c
+10
-51
未找到文件。
src/backend/commands/copy.c
浏览文件 @
c9fe1283
...
...
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.13
0 2001/01/19 06:54:57
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.13
1 2001/01/22 00:50:06
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -705,6 +705,9 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
lineno
++
;
/* Reset the per-output-tuple exprcontext */
ResetPerTupleExprContext
(
estate
);
/* Initialize all values for row to NULL */
MemSet
(
values
,
0
,
attr_count
*
sizeof
(
Datum
));
MemSet
(
nulls
,
'n'
,
attr_count
*
sizeof
(
char
));
...
...
@@ -861,7 +864,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
{
HeapTuple
newtuple
;
newtuple
=
ExecBRInsertTriggers
(
rel
,
tuple
);
newtuple
=
ExecBRInsertTriggers
(
estate
,
rel
,
tuple
);
if
(
newtuple
==
NULL
)
/* "do nothing" */
skip_tuple
=
true
;
...
...
@@ -895,7 +898,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
/* AFTER ROW INSERT Triggers */
if
(
rel
->
trigdesc
&&
rel
->
trigdesc
->
n_after_row
[
TRIGGER_EVENT_INSERT
]
>
0
)
ExecARInsertTriggers
(
rel
,
tuple
);
ExecARInsertTriggers
(
estate
,
rel
,
tuple
);
}
for
(
i
=
0
;
i
<
attr_count
;
i
++
)
...
...
src/backend/commands/trigger.c
浏览文件 @
c9fe1283
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.8
2 2000/12/18 00:44:46
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.8
3 2001/01/22 00:50:07
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -36,7 +36,8 @@ static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
static
HeapTuple
GetTupleForTrigger
(
EState
*
estate
,
ItemPointer
tid
,
TupleTableSlot
**
newSlot
);
static
HeapTuple
ExecCallTriggerFunc
(
Trigger
*
trigger
,
TriggerData
*
trigdata
);
TriggerData
*
trigdata
,
MemoryContext
per_tuple_context
);
static
void
DeferredTriggerSaveEvent
(
Relation
rel
,
int
event
,
HeapTuple
oldtup
,
HeapTuple
newtup
);
...
...
@@ -831,10 +832,13 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
}
static
HeapTuple
ExecCallTriggerFunc
(
Trigger
*
trigger
,
TriggerData
*
trigdata
)
ExecCallTriggerFunc
(
Trigger
*
trigger
,
TriggerData
*
trigdata
,
MemoryContext
per_tuple_context
)
{
FunctionCallInfoData
fcinfo
;
Datum
result
;
MemoryContext
oldContext
;
/*
* Fmgr lookup info is cached in the Trigger structure,
...
...
@@ -843,6 +847,14 @@ ExecCallTriggerFunc(Trigger *trigger, TriggerData *trigdata)
if
(
trigger
->
tgfunc
.
fn_oid
==
InvalidOid
)
fmgr_info
(
trigger
->
tgfoid
,
&
trigger
->
tgfunc
);
/*
* Do the function evaluation in the per-tuple memory context,
* so that leaked memory will be reclaimed once per tuple.
* Note in particular that any new tuple created by the trigger function
* will live till the end of the tuple cycle.
*/
oldContext
=
MemoryContextSwitchTo
(
per_tuple_context
);
/*
* Call the function, passing no arguments but setting a context.
*/
...
...
@@ -853,6 +865,8 @@ ExecCallTriggerFunc(Trigger *trigger, TriggerData *trigdata)
result
=
FunctionCallInvoke
(
&
fcinfo
);
MemoryContextSwitchTo
(
oldContext
);
/*
* Trigger protocol allows function to return a null pointer,
* but NOT to set the isnull result flag.
...
...
@@ -865,7 +879,7 @@ ExecCallTriggerFunc(Trigger *trigger, TriggerData *trigdata)
}
HeapTuple
ExecBRInsertTriggers
(
Relation
rel
,
HeapTuple
trigtuple
)
ExecBRInsertTriggers
(
EState
*
estate
,
Relation
rel
,
HeapTuple
trigtuple
)
{
int
ntrigs
=
rel
->
trigdesc
->
n_before_row
[
TRIGGER_EVENT_INSERT
];
Trigger
**
trigger
=
rel
->
trigdesc
->
tg_before_row
[
TRIGGER_EVENT_INSERT
];
...
...
@@ -884,20 +898,20 @@ ExecBRInsertTriggers(Relation rel, HeapTuple trigtuple)
continue
;
LocTriggerData
.
tg_trigtuple
=
oldtuple
=
newtuple
;
LocTriggerData
.
tg_trigger
=
trigger
[
i
];
newtuple
=
ExecCallTriggerFunc
(
trigger
[
i
],
&
LocTriggerData
);
newtuple
=
ExecCallTriggerFunc
(
trigger
[
i
],
&
LocTriggerData
,
GetPerTupleMemoryContext
(
estate
));
if
(
oldtuple
!=
newtuple
&&
oldtuple
!=
trigtuple
)
heap_freetuple
(
oldtuple
);
if
(
newtuple
==
NULL
)
break
;
else
if
(
oldtuple
!=
newtuple
&&
oldtuple
!=
trigtuple
)
heap_freetuple
(
oldtuple
);
}
return
newtuple
;
}
void
ExecARInsertTriggers
(
Relation
rel
,
HeapTuple
trigtuple
)
ExecARInsertTriggers
(
EState
*
estate
,
Relation
rel
,
HeapTuple
trigtuple
)
{
DeferredTriggerSaveEvent
(
rel
,
TRIGGER_EVENT_INSERT
,
NULL
,
trigtuple
);
return
;
}
bool
...
...
@@ -926,7 +940,8 @@ ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid)
continue
;
LocTriggerData
.
tg_trigtuple
=
trigtuple
;
LocTriggerData
.
tg_trigger
=
trigger
[
i
];
newtuple
=
ExecCallTriggerFunc
(
trigger
[
i
],
&
LocTriggerData
);
newtuple
=
ExecCallTriggerFunc
(
trigger
[
i
],
&
LocTriggerData
,
GetPerTupleMemoryContext
(
estate
));
if
(
newtuple
==
NULL
)
break
;
if
(
newtuple
!=
trigtuple
)
...
...
@@ -944,7 +959,7 @@ ExecARDeleteTriggers(EState *estate, ItemPointer tupleid)
HeapTuple
trigtuple
=
GetTupleForTrigger
(
estate
,
tupleid
,
NULL
);
DeferredTriggerSaveEvent
(
rel
,
TRIGGER_EVENT_DELETE
,
trigtuple
,
NULL
);
return
;
heap_freetuple
(
trigtuple
)
;
}
HeapTuple
...
...
@@ -981,11 +996,12 @@ ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
LocTriggerData
.
tg_trigtuple
=
trigtuple
;
LocTriggerData
.
tg_newtuple
=
oldtuple
=
newtuple
;
LocTriggerData
.
tg_trigger
=
trigger
[
i
];
newtuple
=
ExecCallTriggerFunc
(
trigger
[
i
],
&
LocTriggerData
);
newtuple
=
ExecCallTriggerFunc
(
trigger
[
i
],
&
LocTriggerData
,
GetPerTupleMemoryContext
(
estate
));
if
(
oldtuple
!=
newtuple
&&
oldtuple
!=
intuple
)
heap_freetuple
(
oldtuple
);
if
(
newtuple
==
NULL
)
break
;
else
if
(
oldtuple
!=
newtuple
&&
oldtuple
!=
intuple
)
heap_freetuple
(
oldtuple
);
}
heap_freetuple
(
trigtuple
);
return
newtuple
;
...
...
@@ -998,7 +1014,7 @@ ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
HeapTuple
trigtuple
=
GetTupleForTrigger
(
estate
,
tupleid
,
NULL
);
DeferredTriggerSaveEvent
(
rel
,
TRIGGER_EVENT_UPDATE
,
trigtuple
,
newtuple
);
return
;
heap_freetuple
(
trigtuple
)
;
}
...
...
@@ -1236,7 +1252,7 @@ deferredTriggerGetPreviousEvent(Oid relid, ItemPointer ctid)
}
elog
(
ERROR
,
"deferredTriggerGetPreviousEvent
()
: event for tuple %s not found"
,
"deferredTriggerGetPreviousEvent: event for tuple %s not found"
,
DatumGetCString
(
DirectFunctionCall1
(
tidout
,
PointerGetDatum
(
ctid
))));
return
NULL
;
}
...
...
@@ -1250,7 +1266,8 @@ deferredTriggerGetPreviousEvent(Oid relid, ItemPointer ctid)
* ----------
*/
static
void
deferredTriggerExecute
(
DeferredTriggerEvent
event
,
int
itemno
)
deferredTriggerExecute
(
DeferredTriggerEvent
event
,
int
itemno
,
MemoryContext
per_tuple_context
)
{
Relation
rel
;
TriggerData
LocTriggerData
;
...
...
@@ -1271,7 +1288,7 @@ deferredTriggerExecute(DeferredTriggerEvent event, int itemno)
ItemPointerCopy
(
&
(
event
->
dte_oldctid
),
&
(
oldtuple
.
t_self
));
heap_fetch
(
rel
,
SnapshotAny
,
&
oldtuple
,
&
oldbuffer
);
if
(
!
oldtuple
.
t_data
)
elog
(
ERROR
,
"deferredTriggerExecute
()
: failed to fetch old tuple"
);
elog
(
ERROR
,
"deferredTriggerExecute: failed to fetch old tuple"
);
}
if
(
ItemPointerIsValid
(
&
(
event
->
dte_newctid
)))
...
...
@@ -1279,7 +1296,7 @@ deferredTriggerExecute(DeferredTriggerEvent event, int itemno)
ItemPointerCopy
(
&
(
event
->
dte_newctid
),
&
(
newtuple
.
t_self
));
heap_fetch
(
rel
,
SnapshotAny
,
&
newtuple
,
&
newbuffer
);
if
(
!
newtuple
.
t_data
)
elog
(
ERROR
,
"deferredTriggerExecute
()
: failed to fetch new tuple"
);
elog
(
ERROR
,
"deferredTriggerExecute: failed to fetch new tuple"
);
}
/* ----------
...
...
@@ -1320,7 +1337,9 @@ deferredTriggerExecute(DeferredTriggerEvent event, int itemno)
* updated tuple.
* ----------
*/
rettuple
=
ExecCallTriggerFunc
(
LocTriggerData
.
tg_trigger
,
&
LocTriggerData
);
rettuple
=
ExecCallTriggerFunc
(
LocTriggerData
.
tg_trigger
,
&
LocTriggerData
,
per_tuple_context
);
if
(
rettuple
!=
NULL
&&
rettuple
!=
&
oldtuple
&&
rettuple
!=
&
newtuple
)
heap_freetuple
(
rettuple
);
...
...
@@ -1359,6 +1378,7 @@ deferredTriggerInvokeEvents(bool immediate_only)
int
still_deferred_ones
;
int
eventno
=
-
1
;
int
i
;
MemoryContext
per_tuple_context
;
/* ----------
* For now we process all events - to speedup transaction blocks
...
...
@@ -1369,10 +1389,21 @@ deferredTriggerInvokeEvents(bool immediate_only)
* SET CONSTRAINTS ... command finishes and calls EndQuery.
* ----------
*/
/* Make a per-tuple memory context for trigger function calls */
per_tuple_context
=
AllocSetContextCreate
(
CurrentMemoryContext
,
"DeferredTriggerTupleContext"
,
0
,
ALLOCSET_DEFAULT_INITSIZE
,
ALLOCSET_DEFAULT_MAXSIZE
);
foreach
(
el
,
deftrig_events
)
{
eventno
++
;
MemoryContextReset
(
per_tuple_context
);
/* ----------
* Get the event and check if it is completely done.
* ----------
...
...
@@ -1409,7 +1440,7 @@ deferredTriggerInvokeEvents(bool immediate_only)
* So let's fire it...
* ----------
*/
deferredTriggerExecute
(
event
,
i
);
deferredTriggerExecute
(
event
,
i
,
per_tuple_context
);
event
->
dte_item
[
i
].
dti_state
|=
TRIGGER_DEFERRED_DONE
;
}
...
...
@@ -1421,6 +1452,8 @@ deferredTriggerInvokeEvents(bool immediate_only)
if
(
!
still_deferred_ones
)
event
->
dte_event
|=
TRIGGER_DEFERRED_DONE
;
}
MemoryContextDelete
(
per_tuple_context
);
}
...
...
@@ -1866,13 +1899,10 @@ DeferredTriggerSaveEvent(Relation rel, int event,
* Check if we're interested in this row at all
* ----------
*/
if
(
rel
->
trigdesc
->
n_after_row
[
TRIGGER_EVENT_INSERT
]
==
0
&&
rel
->
trigdesc
->
n_after_row
[
TRIGGER_EVENT_UPDATE
]
==
0
&&
rel
->
trigdesc
->
n_after_row
[
TRIGGER_EVENT_DELETE
]
==
0
&&
rel
->
trigdesc
->
n_before_row
[
TRIGGER_EVENT_INSERT
]
==
0
&&
rel
->
trigdesc
->
n_before_row
[
TRIGGER_EVENT_UPDATE
]
==
0
&&
rel
->
trigdesc
->
n_before_row
[
TRIGGER_EVENT_DELETE
]
==
0
)
ntriggers
=
rel
->
trigdesc
->
n_after_row
[
event
];
if
(
ntriggers
<=
0
)
return
;
triggers
=
rel
->
trigdesc
->
tg_after_row
[
event
];
/* ----------
* Get the CTID's of OLD and NEW
...
...
@@ -1893,9 +1923,6 @@ DeferredTriggerSaveEvent(Relation rel, int event,
*/
oldcxt
=
MemoryContextSwitchTo
(
deftrig_cxt
);
ntriggers
=
rel
->
trigdesc
->
n_after_row
[
event
];
triggers
=
rel
->
trigdesc
->
tg_after_row
[
event
];
new_size
=
sizeof
(
DeferredTriggerEventData
)
+
ntriggers
*
sizeof
(
DeferredTriggerEventItem
);
...
...
src/backend/executor/execMain.c
浏览文件 @
c9fe1283
...
...
@@ -27,7 +27,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.13
4 2001/01/01 21:22:54
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.13
5 2001/01/22 00:50:07
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -941,11 +941,13 @@ ExecutePlan(EState *estate,
/*
* Loop until we've processed the proper number of tuples from the
* plan.
.
* plan.
*/
for
(;;)
{
/* Reset the per-output-tuple exprcontext */
ResetPerTupleExprContext
(
estate
);
/*
* Execute the plan and obtain a tuple
...
...
@@ -1213,20 +1215,25 @@ ExecAppend(TupleTableSlot *slot,
/* BEFORE ROW INSERT Triggers */
if
(
resultRelationDesc
->
trigdesc
&&
resultRelationDesc
->
trigdesc
->
n_before_row
[
TRIGGER_EVENT_INSERT
]
>
0
)
resultRelationDesc
->
trigdesc
->
n_before_row
[
TRIGGER_EVENT_INSERT
]
>
0
)
{
HeapTuple
newtuple
;
newtuple
=
ExecBRInsertTriggers
(
resultRelationDesc
,
tuple
);
newtuple
=
ExecBRInsertTriggers
(
estate
,
resultRelationDesc
,
tuple
);
if
(
newtuple
==
NULL
)
/* "do nothing" */
return
;
if
(
newtuple
!=
tuple
)
/* modified by Trigger(s) */
{
Assert
(
slot
->
ttc_shouldFree
);
heap_freetuple
(
tuple
);
slot
->
val
=
tuple
=
newtuple
;
/*
* Insert modified tuple into tuple table slot, replacing the
* original. We assume that it was allocated in per-tuple
* memory context, and therefore will go away by itself.
* The tuple table slot should not try to clear it.
*/
ExecStoreTuple
(
newtuple
,
slot
,
InvalidBuffer
,
false
);
tuple
=
newtuple
;
}
}
...
...
@@ -1257,8 +1264,9 @@ ExecAppend(TupleTableSlot *slot,
ExecInsertIndexTuples
(
slot
,
&
(
tuple
->
t_self
),
estate
,
false
);
/* AFTER ROW INSERT Triggers */
if
(
resultRelationDesc
->
trigdesc
)
ExecARInsertTriggers
(
resultRelationDesc
,
tuple
);
if
(
resultRelationDesc
->
trigdesc
&&
resultRelationDesc
->
trigdesc
->
n_after_row
[
TRIGGER_EVENT_INSERT
]
>
0
)
ExecARInsertTriggers
(
estate
,
resultRelationDesc
,
tuple
);
}
/* ----------------------------------------------------------------
...
...
@@ -1286,7 +1294,7 @@ ExecDelete(TupleTableSlot *slot,
/* BEFORE ROW DELETE Triggers */
if
(
resultRelationDesc
->
trigdesc
&&
resultRelationDesc
->
trigdesc
->
n_before_row
[
TRIGGER_EVENT_DELETE
]
>
0
)
resultRelationDesc
->
trigdesc
->
n_before_row
[
TRIGGER_EVENT_DELETE
]
>
0
)
{
bool
dodelete
;
...
...
@@ -1343,9 +1351,9 @@ ldelete:;
*/
/* AFTER ROW DELETE Triggers */
if
(
resultRelationDesc
->
trigdesc
)
if
(
resultRelationDesc
->
trigdesc
&&
resultRelationDesc
->
trigdesc
->
n_after_row
[
TRIGGER_EVENT_DELETE
]
>
0
)
ExecARDeleteTriggers
(
estate
,
tupleid
);
}
/* ----------------------------------------------------------------
...
...
@@ -1393,7 +1401,7 @@ ExecReplace(TupleTableSlot *slot,
/* BEFORE ROW UPDATE Triggers */
if
(
resultRelationDesc
->
trigdesc
&&
resultRelationDesc
->
trigdesc
->
n_before_row
[
TRIGGER_EVENT_UPDATE
]
>
0
)
resultRelationDesc
->
trigdesc
->
n_before_row
[
TRIGGER_EVENT_UPDATE
]
>
0
)
{
HeapTuple
newtuple
;
...
...
@@ -1404,9 +1412,14 @@ ExecReplace(TupleTableSlot *slot,
if
(
newtuple
!=
tuple
)
/* modified by Trigger(s) */
{
Assert
(
slot
->
ttc_shouldFree
);
heap_freetuple
(
tuple
);
slot
->
val
=
tuple
=
newtuple
;
/*
* Insert modified tuple into tuple table slot, replacing the
* original. We assume that it was allocated in per-tuple
* memory context, and therefore will go away by itself.
* The tuple table slot should not try to clear it.
*/
ExecStoreTuple
(
newtuple
,
slot
,
InvalidBuffer
,
false
);
tuple
=
newtuple
;
}
}
...
...
@@ -1478,7 +1491,8 @@ lreplace:;
ExecInsertIndexTuples
(
slot
,
&
(
tuple
->
t_self
),
estate
,
true
);
/* AFTER ROW UPDATE Triggers */
if
(
resultRelationDesc
->
trigdesc
)
if
(
resultRelationDesc
->
trigdesc
&&
resultRelationDesc
->
trigdesc
->
n_after_row
[
TRIGGER_EVENT_UPDATE
]
>
0
)
ExecARUpdateTriggers
(
estate
,
tupleid
,
tuple
);
}
...
...
@@ -1514,19 +1528,9 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
/*
* We will use the EState's per-tuple context for evaluating constraint
* expressions. Create it if it's not already there; if it is, reset it
* to free previously-used storage.
* expressions (creating it if it's not already there).
*/
econtext
=
estate
->
es_per_tuple_exprcontext
;
if
(
econtext
==
NULL
)
{
oldContext
=
MemoryContextSwitchTo
(
estate
->
es_query_cxt
);
estate
->
es_per_tuple_exprcontext
=
econtext
=
MakeExprContext
(
NULL
,
estate
->
es_query_cxt
);
MemoryContextSwitchTo
(
oldContext
);
}
else
ResetExprContext
(
econtext
);
econtext
=
GetPerTupleExprContext
(
estate
);
/* Arrange for econtext's scan tuple to be the tuple under test */
econtext
->
ecxt_scantuple
=
slot
;
...
...
src/backend/executor/execUtils.c
浏览文件 @
c9fe1283
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.7
0 2000/12/27 23:59:11
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.7
1 2001/01/22 00:50:07
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -230,6 +230,26 @@ FreeExprContext(ExprContext *econtext)
pfree
(
econtext
);
}
/*
* Build a per-output-tuple ExprContext for an EState.
*
* This is normally invoked via GetPerTupleExprContext() macro.
*/
ExprContext
*
MakePerTupleExprContext
(
EState
*
estate
)
{
if
(
estate
->
es_per_tuple_exprcontext
==
NULL
)
{
MemoryContext
oldContext
;
oldContext
=
MemoryContextSwitchTo
(
estate
->
es_query_cxt
);
estate
->
es_per_tuple_exprcontext
=
MakeExprContext
(
NULL
,
estate
->
es_query_cxt
);
MemoryContextSwitchTo
(
oldContext
);
}
return
estate
->
es_per_tuple_exprcontext
;
}
/* ----------------------------------------------------------------
* Result slot tuple type and ProjectionInfo support
* ----------------------------------------------------------------
...
...
@@ -836,21 +856,9 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
/*
* We will use the EState's per-tuple context for evaluating predicates
* and functional-index functions. Create it if it's not already there;
* if it is, reset it to free previously-used storage.
* and functional-index functions (creating it if it's not already there).
*/
econtext
=
estate
->
es_per_tuple_exprcontext
;
if
(
econtext
==
NULL
)
{
MemoryContext
oldContext
;
oldContext
=
MemoryContextSwitchTo
(
estate
->
es_query_cxt
);
estate
->
es_per_tuple_exprcontext
=
econtext
=
MakeExprContext
(
NULL
,
estate
->
es_query_cxt
);
MemoryContextSwitchTo
(
oldContext
);
}
else
ResetExprContext
(
econtext
);
econtext
=
GetPerTupleExprContext
(
estate
);
/* Arrange for econtext's scan tuple to be the tuple under test */
econtext
->
ecxt_scantuple
=
slot
;
...
...
src/backend/executor/nodeIndexscan.c
浏览文件 @
c9fe1283
...
...
@@ -8,14 +8,12 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.5
4 2000/08/24 03:29:03
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.5
5 2001/01/22 00:50:07
tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* INTERFACE ROUTINES
* ExecInsertIndexTuples inserts tuples into indices on result relation
*
* ExecIndexScan scans a relation using indices
* ExecIndexNext using index to retrieve next tuple
* ExecInitIndexScan creates and initializes state info.
...
...
@@ -23,16 +21,9 @@
* ExecEndIndexScan releases all storage.
* ExecIndexMarkPos marks scan position.
* ExecIndexRestrPos restores scan position.
*
* NOTES
* the code supporting ExecInsertIndexTuples should be
* collected and merged with the genam stuff.
*
*/
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "executor/execdebug.h"
...
...
src/include/commands/trigger.h
浏览文件 @
c9fe1283
...
...
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: trigger.h,v 1.2
2 2000/12/18 00:44:48
tgl Exp $
* $Id: trigger.h,v 1.2
3 2001/01/22 00:50:07
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -89,13 +89,16 @@ extern void FreeTriggerDesc(TriggerDesc *trigdesc);
extern
bool
equalTriggerDescs
(
TriggerDesc
*
trigdesc1
,
TriggerDesc
*
trigdesc2
);
extern
HeapTuple
ExecBRInsertTriggers
(
Relation
rel
,
HeapTuple
tuple
);
extern
void
ExecARInsertTriggers
(
Relation
rel
,
HeapTuple
tuple
);
extern
HeapTuple
ExecBRInsertTriggers
(
EState
*
estate
,
Relation
rel
,
HeapTuple
tuple
);
extern
void
ExecARInsertTriggers
(
EState
*
estate
,
Relation
rel
,
HeapTuple
tuple
);
extern
bool
ExecBRDeleteTriggers
(
EState
*
estate
,
ItemPointer
tupleid
);
extern
void
ExecARDeleteTriggers
(
EState
*
estate
,
ItemPointer
tupleid
);
extern
HeapTuple
ExecBRUpdateTriggers
(
EState
*
estate
,
ItemPointer
tupleid
,
HeapTuple
tuple
);
extern
void
ExecARUpdateTriggers
(
EState
*
estate
,
ItemPointer
tupleid
,
HeapTuple
tuple
);
extern
HeapTuple
ExecBRUpdateTriggers
(
EState
*
estate
,
ItemPointer
tupleid
,
HeapTuple
tuple
);
extern
void
ExecARUpdateTriggers
(
EState
*
estate
,
ItemPointer
tupleid
,
HeapTuple
tuple
);
/* ----------
...
...
src/include/executor/executor.h
浏览文件 @
c9fe1283
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: executor.h,v 1.5
3 2000/11/12 00:37:01
tgl Exp $
* $Id: executor.h,v 1.5
4 2001/01/22 00:50:07
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -153,6 +153,24 @@ extern void FreeExprContext(ExprContext *econtext);
#define ResetExprContext(econtext) \
MemoryContextReset((econtext)->ecxt_per_tuple_memory)
extern
ExprContext
*
MakePerTupleExprContext
(
EState
*
estate
);
/* Get an EState's per-output-tuple exprcontext, making it if first use */
#define GetPerTupleExprContext(estate) \
((estate)->es_per_tuple_exprcontext ? \
(estate)->es_per_tuple_exprcontext : \
MakePerTupleExprContext(estate))
#define GetPerTupleMemoryContext(estate) \
(GetPerTupleExprContext(estate)->ecxt_per_tuple_memory)
/* Reset an EState's per-output-tuple exprcontext, if one's been created */
#define ResetPerTupleExprContext(estate) \
do { \
if ((estate)->es_per_tuple_exprcontext) \
ResetExprContext((estate)->es_per_tuple_exprcontext); \
} while (0)
extern
void
ExecOpenIndices
(
ResultRelInfo
*
resultRelInfo
);
extern
void
ExecCloseIndices
(
ResultRelInfo
*
resultRelInfo
);
extern
void
ExecInsertIndexTuples
(
TupleTableSlot
*
slot
,
ItemPointer
tupleid
,
...
...
src/include/nodes/execnodes.h
浏览文件 @
c9fe1283
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: execnodes.h,v 1.5
3 2000/11/12 00:37:01
tgl Exp $
* $Id: execnodes.h,v 1.5
4 2001/01/22 00:50:07
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -251,7 +251,7 @@ typedef struct EState
MemoryContext
es_query_cxt
;
/* per-query context in which EState lives */
/*
* this ExprContext is for per-output-tuple operations, such as
* constraint checks and index-value computations. It
can
be reset
* constraint checks and index-value computations. It
will
be reset
* for each output tuple. Note that it will be created only if needed.
*/
ExprContext
*
es_per_tuple_exprcontext
;
...
...
src/pl/plpgsql/src/pl_exec.c
浏览文件 @
c9fe1283
...
...
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.3
5 2001/01/06 01:43:01
tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.3
6 2001/01/22 00:50:07
tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
...
...
@@ -112,8 +112,6 @@ static void exec_prepare_plan(PLpgSQL_execstate * estate,
PLpgSQL_expr
*
expr
);
static
bool
exec_simple_check_node
(
Node
*
node
);
static
void
exec_simple_check_plan
(
PLpgSQL_expr
*
expr
);
static
void
exec_eval_clear_fcache
(
Node
*
node
);
static
bool
exec_eval_clear_fcache_walker
(
Node
*
node
,
void
*
context
);
static
Datum
exec_eval_simple_expr
(
PLpgSQL_execstate
*
estate
,
PLpgSQL_expr
*
expr
,
bool
*
isNull
,
...
...
@@ -2530,10 +2528,17 @@ exec_eval_simple_expr(PLpgSQL_execstate * estate,
ParamListInfo
paramLI
;
/* ----------
* Create a simple expression context to hold the arguments
* Create a simple expression context to hold the arguments.
*
* NOTE: we pass TopMemoryContext as the query-lifetime context for
* function cache nodes and suchlike allocations. This is necessary
* because that's where the expression tree itself is (it'll never be
* freed in this backend, and the function cache nodes must live as
* long as it does). The memory allocation for plpgsql's plan trees
* really needs to be redesigned...
* ----------
*/
econtext
=
MakeExprContext
(
NULL
,
T
ransactionCommand
Context
);
econtext
=
MakeExprContext
(
NULL
,
T
opMemory
Context
);
paramLI
=
(
ParamListInfo
)
palloc
((
expr
->
nparams
+
1
)
*
sizeof
(
ParamListInfoData
));
econtext
->
ecxt_param_list_info
=
paramLI
;
...
...
@@ -2601,12 +2606,6 @@ exec_eval_simple_expr(PLpgSQL_execstate * estate,
*/
*
rettype
=
expr
->
plan_simple_type
;
/* ----------
* Clear any function cache entries in the expression tree
* ----------
*/
exec_eval_clear_fcache
(
expr
->
plan_simple_expr
);
/* ----------
* Now call the executor to evaluate the expression
* ----------
...
...
@@ -2902,46 +2901,6 @@ exec_simple_check_plan(PLpgSQL_expr * expr)
expr
->
plan_simple_type
=
exprType
(
tle
->
expr
);
}
/* ----------
* exec_eval_clear_fcache - The function cache is palloc()'d by
* the executor, and contains call specific
* data based on the arguments. This has
* to be recalculated.
* ----------
*/
static
void
exec_eval_clear_fcache
(
Node
*
node
)
{
/* This tree walk requires no special setup, so away we go... */
exec_eval_clear_fcache_walker
(
node
,
NULL
);
}
static
bool
exec_eval_clear_fcache_walker
(
Node
*
node
,
void
*
context
)
{
if
(
node
==
NULL
)
return
false
;
if
(
IsA
(
node
,
Expr
))
{
Expr
*
expr
=
(
Expr
*
)
node
;
switch
(
expr
->
opType
)
{
case
OP_EXPR
:
((
Oper
*
)
(
expr
->
oper
))
->
op_fcache
=
NULL
;
break
;
case
FUNC_EXPR
:
((
Func
*
)
(
expr
->
oper
))
->
func_fcache
=
NULL
;
break
;
default:
break
;
}
}
return
expression_tree_walker
(
node
,
exec_eval_clear_fcache_walker
,
context
);
}
/* ----------
* exec_set_found Set the global found variable
* to true/false
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录