Global SysCache

Offering: openGaussDev

More detail:
修复闪回功能未适配GSC导致DDL数据无法丢弃问题

# Conflicts:
#	src/gausskernel/storage/tcap/tcap_truncate.cpp

Match-id-e09ce9c267ac9ae227186b0e7cbc9377b1cfb06a
This commit is contained in:
openGaussDev 2022-03-08 20:22:47 +08:00 committed by yanghao
parent 66b05d1215
commit 0c08e764e0
13 changed files with 538 additions and 536 deletions

View File

@ -211,7 +211,7 @@ void LocalPartDefCache::Init()
}
m_global_partdefcache = t_thrd.lsc_cxt.lsc->GetGlobalPartDefCache();
m_db_id = t_thrd.lsc_cxt.lsc->my_database_id;
part_cache_need_eoxact_work = false;
PartCacheNeedEOXActWork = false;
m_is_inited = true;
}
@ -298,7 +298,7 @@ void LocalPartDefCache::AtEOXact_PartitionCache(bool isCommit)
* transaction, even though we could clear it at subtransaction end in
* some cases.
*/
if (!part_cache_need_eoxact_work
if (!GetPartCacheNeedEOXActWork()
#ifdef USE_ASSERT_CHECKING
&& !assert_enabled
#endif
@ -356,7 +356,7 @@ void LocalPartDefCache::AtEOXact_PartitionCache(bool isCommit)
}
/* Once done with the transaction, we can reset need_eoxact_work */
part_cache_need_eoxact_work = false;
SetPartCacheNeedEOXActWork(false);
}
void LocalPartDefCache::AtEOSubXact_PartitionCache(bool isCommit, SubTransactionId mySubid,
@ -366,7 +366,7 @@ void LocalPartDefCache::AtEOSubXact_PartitionCache(bool isCommit, SubTransaction
* Skip the relcache scan if nothing to do --- see notes for
* AtEOXact_PartitionCache.
*/
if (!part_cache_need_eoxact_work)
if (!GetPartCacheNeedEOXActWork())
return;
Dlelem *bucket_elt;

View File

@ -367,7 +367,7 @@ void LocalTabDefCache::Init()
relcacheInvalsReceived = 0;
initFileRelationIds = NIL;
need_eoxact_work = false;
RelCacheNeedEOXActWork = false;
g_bucketmap_cache = NIL;
max_bucket_map_size = BUCKET_MAP_SIZE;
@ -874,7 +874,7 @@ void LocalTabDefCache::AtEOXact_RelationCache(bool isCommit)
* transaction, even though we could clear it at subtransaction end in
* some cases.
*/
if (!LocalRelCacheNeedEOXactWork()
if (!GetRelCacheNeedEOXActWork()
#ifdef USE_ASSERT_CHECKING
&& !assert_enabled
#endif
@ -963,7 +963,7 @@ void LocalTabDefCache::AtEOXact_RelationCache(bool isCommit)
}
}
/* Once done with the transaction, we can reset u_sess->relcache_cxt.need_eoxact_work */
SetLocalRelCacheNeedEOXactWork(false);
SetRelCacheNeedEOXActWork(false);
}
/*
@ -980,7 +980,7 @@ void LocalTabDefCache::AtEOSubXact_RelationCache(bool isCommit, SubTransactionId
* Skip the relcache scan if nothing to do --- see notes for
* AtEOXact_RelationCache.
*/
if (!LocalRelCacheNeedEOXactWork())
if (!GetRelCacheNeedEOXActWork())
return;
Dlelem *bucket_elt;
@ -1118,7 +1118,7 @@ void LocalTabDefCache::ResetInitFlag()
relcacheInvalsReceived = 0;
initFileRelationIds = NIL;
need_eoxact_work = false;
RelCacheNeedEOXActWork = false;
g_bucketmap_cache = NIL;
max_bucket_map_size = 0;

View File

@ -473,7 +473,7 @@ Partition PartitionBuildLocalPartition(const char *relname, Oid partid, Oid part
part->pd_newRelfilenodeSubid = InvalidSubTransactionId;
/* must flag that we have rels created in this transaction */
SetPartCacheNeedEoxactWork(true);
SetPartCacheNeedEOXActWork(true);
/*
* initialize partition tuple form (caller may add/override data later)
@ -986,7 +986,7 @@ void AtEOXact_PartitionCache(bool isCommit)
* transaction, even though we could clear it at subtransaction end in
* some cases.
*/
if (!u_sess->cache_cxt.part_cache_need_eoxact_work
if (!GetPartCacheNeedEOXActWork()
#ifdef USE_ASSERT_CHECKING
&& !assert_enabled
#endif
@ -1040,7 +1040,7 @@ void AtEOXact_PartitionCache(bool isCommit)
}
/* Once done with the transaction, we can reset need_eoxact_work */
u_sess->cache_cxt.part_cache_need_eoxact_work = false;
SetPartCacheNeedEOXActWork(false);
}
/*
@ -1063,7 +1063,7 @@ void AtEOSubXact_PartitionCache(bool isCommit, SubTransactionId mySubid, SubTran
* Skip the relcache scan if nothing to do --- see notes for
* AtEOXact_PartitionCache.
*/
if (!u_sess->cache_cxt.part_cache_need_eoxact_work)
if (!GetPartCacheNeedEOXActWork())
return;
hash_seq_init(&status, u_sess->cache_cxt.PartitionIdCache);
@ -1705,7 +1705,7 @@ void PartitionSetNewRelfilenode(Relation parent, Partition part, TransactionId f
part->pd_newRelfilenodeSubid = GetCurrentSubTransactionId();
/* ... and now we have eoxact cleanup work to do */
SetPartCacheNeedEoxactWork(true);
SetPartCacheNeedEOXActWork(true);
}
static void PartitionParseRelOptions(Partition partition, HeapTuple tuple)

View File

@ -4161,7 +4161,7 @@ void AtEOXact_RelationCache(bool isCommit)
* transaction, even though we could clear it at subtransaction end in
* some cases.
*/
if (!u_sess->relcache_cxt.need_eoxact_work
if (!GetRelCacheNeedEOXActWork()
#ifdef USE_ASSERT_CHECKING
&& !assert_enabled
#endif
@ -4253,7 +4253,7 @@ void AtEOXact_RelationCache(bool isCommit)
}
/* Once done with the transaction, we can reset u_sess->relcache_cxt.need_eoxact_work */
u_sess->relcache_cxt.need_eoxact_work = false;
SetRelCacheNeedEOXActWork(false);
}
/*
@ -4276,7 +4276,7 @@ void AtEOSubXact_RelationCache(bool isCommit, SubTransactionId mySubid, SubTrans
* Skip the relcache scan if nothing to do --- see notes for
* AtEOXact_RelationCache.
*/
if (!u_sess->relcache_cxt.need_eoxact_work)
if (!GetRelCacheNeedEOXActWork())
return;
hash_seq_init(&status, u_sess->relcache_cxt.RelationIdCache);
@ -4416,7 +4416,7 @@ Relation RelationBuildLocalRelation(const char* relname, Oid relnamespace, Tuple
rel->rd_newRelfilenodeSubid = InvalidSubTransactionId;
/* must flag that we have rels created in this transaction */
SetLocalRelCacheNeedEOXactWork(true);
SetRelCacheNeedEOXActWork(true);
/*
* create a new tuple descriptor from the one passed in. We do this
@ -4784,7 +4784,7 @@ void RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid, Multi
*/
relation->rd_newRelfilenodeSubid = GetCurrentSubTransactionId();
/* ... and now we have eoxact cleanup work to do */
SetLocalRelCacheNeedEOXactWork(true);
SetRelCacheNeedEOXActWork(true);
}
RelFileNodeBackend CreateNewRelfilenode(Relation relation, TransactionId freezeXid)
@ -6064,7 +6064,7 @@ void RelationSetIndexList(Relation relation, List* indexIds, Oid oidIndex)
relation->rd_pkindex = InvalidOid;
relation->rd_indexvalid = 2; /* mark list as forced */
/* must flag that we have a forced index list */
SetLocalRelCacheNeedEOXactWork(true);
SetRelCacheNeedEOXActWork(true);
}
/*

View File

@ -936,7 +936,7 @@ void RebuildPartitonMap(PartitionMap* oldMap, PartitionMap* newMap)
}
} else {
oldMap->isDirty = true;
SetLocalRelCacheNeedEOXactWork(true);
SetRelCacheNeedEOXActWork(true);
elog(LOG, "map refcount is not zero when RebuildPartitonMap ");
}
}

View File

@ -985,7 +985,7 @@ static void knl_u_relcache_init(knl_u_relcache_context* relcache_cxt)
relcache_cxt->criticalSharedRelcachesBuilt = false;
relcache_cxt->relcacheInvalsReceived = 0L;
relcache_cxt->initFileRelationIds = NIL;
relcache_cxt->need_eoxact_work = false;
relcache_cxt->RelCacheNeedEOXActWork = false;
relcache_cxt->OpClassCache = NULL;
relcache_cxt->pgclassdesc = NULL;
relcache_cxt->pgindexdesc = NULL;
@ -1174,7 +1174,7 @@ static void knl_u_cache_init(knl_u_cache_context* cache_cxt)
cache_cxt->PartitionIdCache = NULL;
cache_cxt->BucketIdCache = NULL;
cache_cxt->part_cache_need_eoxact_work = false;
cache_cxt->PartCacheNeedEOXActWork = false;
cache_cxt->bucket_cache_need_eoxact_work = false;
cache_cxt->dn_hash_table = NULL;
}

View File

@ -1,491 +1,493 @@
/*
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
*
* openGauss is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* ---------------------------------------------------------------------------------------
*
* tcap_truncate.cpp
* Routines to support Timecapsule `Recyclebin-based query, restore`.
* We use Tr prefix to indicate it in following coding.
*
* IDENTIFICATION
* src/gausskernel/storage/tcap/tcap_truncate.cpp
*
* ---------------------------------------------------------------------------------------
*/
#include "postgres.h"
#include "pgstat.h"
#include "access/reloptions.h"
#include "access/sysattr.h"
#include "access/xlog.h"
#include "catalog/dependency.h"
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_collation_fn.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_conversion_fn.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_extension_data_source.h"
#include "catalog/pg_extension.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_job.h"
#include "catalog/pg_language.h"
#include "catalog/pg_largeobject.h"
#include "catalog/pg_object.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_recyclebin.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_rlspolicy.h"
#include "catalog/pg_synonym.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_ts_parser.h"
#include "catalog/pg_ts_template.h"
#include "catalog/pgxc_class.h"
#include "catalog/storage.h"
#include "catalog/pg_partition_fn.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "commands/directory.h"
#include "commands/extension.h"
#include "commands/matview.h"
#include "commands/proclang.h"
#include "commands/schemacmds.h"
#include "commands/seclabel.h"
#include "commands/sec_rls_cmds.h"
#include "commands/tablecmds.h"
#include "commands/tablespace.h"
#include "commands/trigger.h"
#include "commands/typecmds.h"
#include "executor/node/nodeModifyTable.h"
#include "rewrite/rewriteRemove.h"
#include "storage/lmgr.h"
#include "storage/predicate.h"
#include "storage/smgr/relfilenode.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/relcache.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "storage/tcap.h"
#include "storage/tcap_impl.h"
void TrRelationSetNewRelfilenode(Relation relation, TransactionId freezeXid, void *baseDesc)
{
TrObjDesc desc;
TrObjDesc *trBaseDesc = (TrObjDesc *)baseDesc;
RelFileNodeBackend newrnode;
/* Indexes, sequences must have Invalid frozenxid; other rels must not. */
Assert((((relation->rd_rel->relkind == RELKIND_INDEX) || (relation->rd_rel->relkind == RELKIND_GLOBAL_INDEX) ||
(RELKIND_IS_SEQUENCE(relation->rd_rel->relkind))) ?
(freezeXid == InvalidTransactionId) :
TransactionIdIsNormal(freezeXid)) ||
relation->rd_rel->relkind == RELKIND_RELATION);
/* Record the old relfilenode to recyclebin. */
desc = *trBaseDesc;
if (!TR_IS_BASE_OBJ_EX(trBaseDesc, RelationGetRelid(relation))) {
TrDescInit(relation, &desc, RB_OPER_TRUNCATE,
TrGetObjType(RelationGetNamespace(relation), RelationGetRelkind(relation)), false);
TrDescWrite(&desc);
}
/* Allocate a new relfilenode, create storage for the main fork. */
newrnode = CreateNewRelfilenode(relation, freezeXid);
/*
* NOTE: if the relation was created in this transaction, it will now be
* present in the pending-delete list twice, once with atCommit true and
* once with atCommit false. Hence, it will be physically deleted at end
* of xact in either case (and the other entry will be ignored by
* smgrDoPendingDeletes, so no error will occur). We could instead remove
* the existing list entry and delete the physical file immediately, but
* for now I'll keep the logic simple.
*/
RelationCloseSmgr(relation);
/*
* Update pg_class entry for new relfilenode.
*/
UpdatePgclass(relation, freezeXid, &newrnode);
/*
* Make the pg_class row change visible, as well as the relation map
* change if any. This will cause the relcache entry to get updated, too.
*/
CommandCounterIncrement();
/*
* Mark the rel as having been given a new relfilenode in the current
* (sub) transaction. This is a hint that can be used to optimize later
* operations on the rel in the same transaction.
*/
relation->rd_newRelfilenodeSubid = GetCurrentSubTransactionId();
/* ... and now we have eoxact cleanup work to do */
u_sess->relcache_cxt.need_eoxact_work = true;
}
void TrPartitionSetNewRelfilenode(Relation parent, Partition part, TransactionId freezeXid, void *baseDesc)
{
RelFileNodeBackend newrnode;
TrObjDesc desc;
TrObjDesc *trBaseDesc = (TrObjDesc *)baseDesc;
Assert((parent->rd_rel->relkind == RELKIND_INDEX || RELKIND_IS_SEQUENCE(parent->rd_rel->relkind))
? freezeXid == InvalidTransactionId
: TransactionIdIsNormal(freezeXid));
/* Record the old relfilenode to recyclebin. */
desc = *trBaseDesc;
if (!TR_IS_BASE_OBJ_EX(trBaseDesc, part->pd_id)) {
TrPartDescInit(parent, part, &desc, RB_OPER_TRUNCATE,
TrGetObjType(RelationGetNamespace(parent), RelationGetRelkind(parent)), false);
TrDescWrite(&desc);
}
/* Allocate a new relfilenode */
newrnode = CreateNewRelfilenodePart(parent, part);
UpdatePartition(parent, part, freezeXid, &newrnode);
CommandCounterIncrement();
/*
* Mark the part as having been given a new relfilenode in the current
* (sub) transaction. This is a hint that can be used to optimize later
* operations on the rel in the same transaction.
*/
part->pd_newRelfilenodeSubid = GetCurrentSubTransactionId();
/* ... and now we have eoxact cleanup work to do */
u_sess->cache_cxt.part_cache_need_eoxact_work = true;
}
bool TrCheckRecyclebinTruncate(const TruncateStmt *stmt)
{
RangeVar *rel = NULL;
Oid relid;
if (/*
* Disable Recyclebin-based-Truncate when with purge option, or
*/
/* recyblebin disabled, or */
!u_sess->attr.attr_storage.enable_recyclebin ||
/* with purge option, or */
stmt->purge ||
/* with restart_seqs option, or */
stmt->restart_seqs ||
/* multi objects truncate. */
list_length(stmt->relations) != 1) {
return false;
}
rel = (RangeVar *)linitial(stmt->relations);
relid = RangeVarGetRelid(rel, NoLock, false);
return NeedTrComm(relid);
}
void TrTruncateOnePart(Relation rel, HeapTuple tup, Oid insertBaseid)
{
Oid toastOid = ((Form_pg_partition)GETSTRUCT(tup))->reltoastrelid;
Relation toastRel = NULL;
Oid partOid = HeapTupleGetOid(tup);
Partition p = partitionOpen(rel, partOid, AccessExclusiveLock);
TrObjDesc baseDesc;
TrPartDescInit(rel, p, &baseDesc, RB_OPER_TRUNCATE, RB_OBJ_PARTITION, false);
baseDesc.id = baseDesc.baseid = insertBaseid;
(void)TrDescWrite(&baseDesc);
TrUpdateBaseid(&baseDesc);
TrPartitionSetNewRelfilenode(rel, p, u_sess->utils_cxt.RecentXmin, &baseDesc);
/* process the toast table */
if (OidIsValid(toastOid)) {
Assert(rel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED);
toastRel = heap_open(toastOid, AccessExclusiveLock);
TrRelationSetNewRelfilenode(toastRel, u_sess->utils_cxt.RecentXmin, &baseDesc);
heap_close(toastRel, AccessExclusiveLock);
}
partitionClose(rel, p, AccessExclusiveLock);
/* report truncate partition to PgStatCollector */
pgstat_report_truncate(partOid, rel->rd_id, rel->rd_rel->relisshared);
}
void TrPartitionTableProcess(Relation rel, Oid insertBaseid)
{
/* truncate partitioned table */
List* partTupleList = NIL;
ListCell* partCell = NULL;
Oid heap_relid;
bool is_shared = rel->rd_rel->relisshared;
heap_relid = RelationGetRelid(rel);
/* partitioned table unspport the unlogged table */
Assert(rel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED);
/* process all partition */
partTupleList = searchPgPartitionByParentId(PART_OBJ_TYPE_TABLE_PARTITION, rel->rd_id);
foreach (partCell, partTupleList) {
if (RelationIsSubPartitioned(rel)) {
/* the "tup" just for get partOid, UHeapTup has no HEAP_HASOID flag, so here use HeapTuple */
HeapTuple tup = (HeapTuple)lfirst(partCell);
Oid partOid = HeapTupleGetOid(tup);
Partition p = partitionOpen(rel, partOid, AccessExclusiveLock);
Relation partRel = partitionGetRelation(rel, p);
List* subPartTupleList = searchPgPartitionByParentId(PART_OBJ_TYPE_TABLE_SUB_PARTITION, partOid);
ListCell* subPartCell = NULL;
foreach (subPartCell, subPartTupleList) {
HeapTuple tup = (HeapTuple)lfirst(subPartCell);
TrTruncateOnePart(partRel, tup, insertBaseid);
}
freePartList(subPartTupleList);
releaseDummyRelation(&partRel);
partitionClose(rel, p, AccessExclusiveLock);
} else {
HeapTuple tup = (HeapTuple)lfirst(partCell);
TrTruncateOnePart(rel, tup, insertBaseid);
}
}
freePartList(partTupleList);
/* report truncate partitioned table to PgStatCollector */
pgstat_report_truncate(heap_relid, InvalidOid, is_shared);
}
void TrTruncate(const TruncateStmt *stmt)
{
RangeVar *rv = (RangeVar*)linitial(stmt->relations);
Relation rel;
Oid relid;
Oid toastRelid;
TrObjDesc baseDesc;
/*
* 1. Open relation in AccessExclusiveLock, and check permission, etc.
*/
rel = heap_openrv(rv, AccessExclusiveLock);
relid = RelationGetRelid(rel);
/* find matview exists or not. */
Oid mlogid = find_matview_mlog_table(relid);
if (OidIsValid(mlogid)) {
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Not support truncate table under materialized view.")));
}
TrForbidAccessRbObject(RelationRelationId, relid, rv->relname);
truncate_check_rel(rel);
/*
* This effectively deletes all rows in the table, and may be done
* in a serializable transaction. In that case we must record a
* rw-conflict in to this transaction from each transaction
* holding a predicate lock on the table.
*/
CheckTableForSerializableConflictIn(rel);
/*
* 2. Create a new empty storage file for the relation, and assign it
* as the relfilenode value, and record the old relfilenode to recyclebin.
*/
TrDescInit(rel, &baseDesc, RB_OPER_TRUNCATE, RB_OBJ_TABLE, true, true);
baseDesc.id = baseDesc.baseid = TrDescWrite(&baseDesc);
TrUpdateBaseid(&baseDesc);
/*
* step 2.1. If rel is partition table, find all partitions, and Create some new empty
* storage file for the all partitions of the relation, and assign them as the
* relfilenodes value, and record the old relfilenodes to recyclebin.
*/
if (RELATION_IS_PARTITIONED(rel)) {
TrPartitionTableProcess(rel, baseDesc.baseid);
}
TrRelationSetNewRelfilenode(rel, u_sess->utils_cxt.RecentXmin, &baseDesc);
/*
* 3. The same for the toast table, if any.
*/
toastRelid = rel->rd_rel->reltoastrelid;
if (OidIsValid(toastRelid) && !RELATION_IS_PARTITIONED(rel)) {
Relation relToast = relation_open(toastRelid, AccessExclusiveLock);
TrRelationSetNewRelfilenode(relToast, u_sess->utils_cxt.RecentXmin, &baseDesc);
heap_close(relToast, NoLock);
}
/*
* 4. Reconstruct the indexes to match, and we're done.
*/
(void)ReindexRelation(relid, REINDEX_REL_PROCESS_TOAST, REINDEX_ALL_INDEX, &baseDesc);
/*
* 5. Report stat, and clean.
*/
/* report truncate to PgStatCollector */
pgstat_report_truncate(relid, InvalidOid, false);
/* Record time of truancate relation. */
recordRelationMTime(relid, rel->rd_rel->relkind);
heap_close(rel, NoLock);
}
/*
* RelationDropStorage
* Schedule unlinking of physical storage at transaction commit.
*/
void TrDoPurgeObjectTruncate(TrObjDesc *desc)
{
Relation rbRel;
SysScanDesc sd;
ScanKeyData skey[1];
HeapTuple tup;
Assert (((desc->type == RB_OBJ_TABLE) && desc->canpurge) || ((desc->type == RB_OBJ_PARTITION) && !desc->canpurge));
rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock);
ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcybaseid, BTEqualStrategyNumber,
F_INT8EQ, Int64GetDatum(desc->baseid));
sd = systable_beginscan(rbRel, RecyclebinBaseidIndexId, true, NULL, 1, skey);
while (HeapTupleIsValid(tup = systable_getnext(sd))) {
Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup);
RelFileNode rnode;
rnode.spcNode = ConvertToRelfilenodeTblspcOid(rbForm->rcytablespace);
rnode.dbNode = (rnode.spcNode == GLOBALTABLESPACE_OID) ? InvalidOid :
u_sess->proc_cxt.MyDatabaseId;
rnode.relNode = rbForm->rcyrelfilenode;
rnode.bucketNode = InvalidBktId;
/*
* Schedule unlinking of the old storage at transaction commit.
*/
InsertStorageIntoPendingList(
&rnode, InvalidAttrNumber, InvalidBackendId, rbForm->rcyowner, true, false);
simple_heap_delete(rbRel, &tup->t_self);
ereport(LOG, (errmsg("Delete truncated object %u/%u/%u", rnode.spcNode,
rnode.dbNode, rnode.relNode)));
}
systable_endscan(sd);
heap_close(rbRel, RowExclusiveLock);
/* ... and now we have eoxact cleanup work to do */
u_sess->relcache_cxt.need_eoxact_work = true;
/*
* CommandCounterIncrement here to ensure that preceding changes are all
* visible to the next deletion step.
*/
CommandCounterIncrement();
}
/* flashback table to before truncate */
void TrRestoreTruncate(const TimeCapsuleStmt *stmt)
{
TrObjDesc baseDesc;
Relation rbRel;
SysScanDesc sd;
ScanKeyData skey[1];
HeapTuple tup;
Relation rel;
Oid relid;
bool found = false;
TrObjDesc desc;
/* process restore truncate fail: TIMECAPSULE TABLE "BIN$3C534EBE021$4930808==$0" TO BEFORE TRUNCATE; */
found = TrFetchName(stmt->relation->relname, RB_OBJ_TABLE, &desc, RB_OPER_RESTORE_TRUNCATE);
if (found) {
stmt->relation->relname = desc.originname;
}
rel = heap_openrv(stmt->relation, AccessExclusiveLock);
relid = RelationGetRelid(rel);
if (rel->rd_tam_type == TAM_HEAP) {
heap_close(rel, NoLock);
elog(ERROR, "timecapsule does not support astore yet");
return;
}
if (found) {
stmt->relation->relname = desc.name;
}
/* 1. Fetch the latest available recycle object. */
TrOperFetch(stmt->relation, RB_OBJ_TABLE, &baseDesc, RB_OPER_RESTORE_TRUNCATE);
/* 2. Lock recycle object and base relation. */
baseDesc.authid = GetUserId();
TrOperPrep(&baseDesc, RB_OPER_RESTORE_TRUNCATE);
/* 3. Check base relation whether normal and matched. */
TrBaseRelMatched(&baseDesc);
/* 4. Do restore. */
rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock);
ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcybaseid, BTEqualStrategyNumber,
F_INT8EQ, Int64GetDatum(baseDesc.id));
sd = systable_beginscan(rbRel, RecyclebinBaseidIndexId, true, NULL, 1, skey);
while (HeapTupleIsValid(tup = systable_getnext(sd))) {
if (!RELATION_IS_PARTITIONED(rel)) {
TrSwapRelfilenode(rbRel, tup, false);
} else {
TrSwapRelfilenode(rbRel, tup, true);
}
}
systable_endscan(sd);
heap_close(rbRel, RowExclusiveLock);
heap_close(rel, NoLock);
/*
* CommandCounterIncrement here to ensure that preceding changes are all
* visible to the next deletion step.
*/
CommandCounterIncrement();
return;
}
/*
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
*
* openGauss is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* ---------------------------------------------------------------------------------------
*
* tcap_truncate.cpp
* Routines to support Timecapsule `Recyclebin-based query, restore`.
* We use Tr prefix to indicate it in following coding.
*
* IDENTIFICATION
* src/gausskernel/storage/tcap/tcap_truncate.cpp
*
* ---------------------------------------------------------------------------------------
*/
#include "postgres.h"
#include "pgstat.h"
#include "access/reloptions.h"
#include "access/sysattr.h"
#include "access/xlog.h"
#include "catalog/dependency.h"
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_collation_fn.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_conversion_fn.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_extension_data_source.h"
#include "catalog/pg_extension.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_job.h"
#include "catalog/pg_language.h"
#include "catalog/pg_largeobject.h"
#include "catalog/pg_object.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_recyclebin.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_rlspolicy.h"
#include "catalog/pg_synonym.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_ts_parser.h"
#include "catalog/pg_ts_template.h"
#include "catalog/pgxc_class.h"
#include "catalog/storage.h"
#include "catalog/pg_partition_fn.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "commands/directory.h"
#include "commands/extension.h"
#include "commands/matview.h"
#include "commands/proclang.h"
#include "commands/schemacmds.h"
#include "commands/seclabel.h"
#include "commands/sec_rls_cmds.h"
#include "commands/tablecmds.h"
#include "commands/tablespace.h"
#include "commands/trigger.h"
#include "commands/typecmds.h"
#include "executor/node/nodeModifyTable.h"
#include "rewrite/rewriteRemove.h"
#include "storage/lmgr.h"
#include "storage/predicate.h"
#include "storage/smgr/relfilenode.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/knl_partcache.h"
#include "utils/knl_relcache.h"
#include "utils/lsyscache.h"
#include "utils/relcache.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "storage/tcap.h"
#include "storage/tcap_impl.h"
void TrRelationSetNewRelfilenode(Relation relation, TransactionId freezeXid, void *baseDesc)
{
TrObjDesc desc;
TrObjDesc *trBaseDesc = (TrObjDesc *)baseDesc;
RelFileNodeBackend newrnode;
/* Indexes, sequences must have Invalid frozenxid; other rels must not. */
Assert((((relation->rd_rel->relkind == RELKIND_INDEX) || (relation->rd_rel->relkind == RELKIND_GLOBAL_INDEX) ||
(RELKIND_IS_SEQUENCE(relation->rd_rel->relkind))) ?
(freezeXid == InvalidTransactionId) :
TransactionIdIsNormal(freezeXid)) ||
relation->rd_rel->relkind == RELKIND_RELATION);
/* Record the old relfilenode to recyclebin. */
desc = *trBaseDesc;
if (!TR_IS_BASE_OBJ_EX(trBaseDesc, RelationGetRelid(relation))) {
TrDescInit(relation, &desc, RB_OPER_TRUNCATE,
TrGetObjType(RelationGetNamespace(relation), RelationGetRelkind(relation)), false);
TrDescWrite(&desc);
}
/* Allocate a new relfilenode, create storage for the main fork. */
newrnode = CreateNewRelfilenode(relation, freezeXid);
/*
* NOTE: if the relation was created in this transaction, it will now be
* present in the pending-delete list twice, once with atCommit true and
* once with atCommit false. Hence, it will be physically deleted at end
* of xact in either case (and the other entry will be ignored by
* smgrDoPendingDeletes, so no error will occur). We could instead remove
* the existing list entry and delete the physical file immediately, but
* for now I'll keep the logic simple.
*/
RelationCloseSmgr(relation);
/*
* Update pg_class entry for new relfilenode.
*/
UpdatePgclass(relation, freezeXid, &newrnode);
/*
* Make the pg_class row change visible, as well as the relation map
* change if any. This will cause the relcache entry to get updated, too.
*/
CommandCounterIncrement();
/*
* Mark the rel as having been given a new relfilenode in the current
* (sub) transaction. This is a hint that can be used to optimize later
* operations on the rel in the same transaction.
*/
relation->rd_newRelfilenodeSubid = GetCurrentSubTransactionId();
/* ... and now we have eoxact cleanup work to do */
SetRelCacheNeedEOXActWork(true);
}
void TrPartitionSetNewRelfilenode(Relation parent, Partition part, TransactionId freezeXid, void *baseDesc)
{
RelFileNodeBackend newrnode;
TrObjDesc desc;
TrObjDesc *trBaseDesc = (TrObjDesc *)baseDesc;
Assert((parent->rd_rel->relkind == RELKIND_INDEX || RELKIND_IS_SEQUENCE(parent->rd_rel->relkind))
? freezeXid == InvalidTransactionId
: TransactionIdIsNormal(freezeXid));
/* Record the old relfilenode to recyclebin. */
desc = *trBaseDesc;
if (!TR_IS_BASE_OBJ_EX(trBaseDesc, part->pd_id)) {
TrPartDescInit(parent, part, &desc, RB_OPER_TRUNCATE,
TrGetObjType(RelationGetNamespace(parent), RelationGetRelkind(parent)), false);
TrDescWrite(&desc);
}
/* Allocate a new relfilenode */
newrnode = CreateNewRelfilenodePart(parent, part);
UpdatePartition(parent, part, freezeXid, &newrnode);
CommandCounterIncrement();
/*
* Mark the part as having been given a new relfilenode in the current
* (sub) transaction. This is a hint that can be used to optimize later
* operations on the rel in the same transaction.
*/
part->pd_newRelfilenodeSubid = GetCurrentSubTransactionId();
/* ... and now we have eoxact cleanup work to do */
SetPartCacheNeedEOXActWork(true);
}
bool TrCheckRecyclebinTruncate(const TruncateStmt *stmt)
{
RangeVar *rel = NULL;
Oid relid;
if (/*
* Disable Recyclebin-based-Truncate when with purge option, or
*/
/* recyblebin disabled, or */
!u_sess->attr.attr_storage.enable_recyclebin ||
/* with purge option, or */
stmt->purge ||
/* with restart_seqs option, or */
stmt->restart_seqs ||
/* multi objects truncate. */
list_length(stmt->relations) != 1) {
return false;
}
rel = (RangeVar *)linitial(stmt->relations);
relid = RangeVarGetRelid(rel, NoLock, false);
return NeedTrComm(relid);
}
void TrTruncateOnePart(Relation rel, HeapTuple tup, Oid insertBaseid)
{
Oid toastOid = ((Form_pg_partition)GETSTRUCT(tup))->reltoastrelid;
Relation toastRel = NULL;
Oid partOid = HeapTupleGetOid(tup);
Partition p = partitionOpen(rel, partOid, AccessExclusiveLock);
TrObjDesc baseDesc;
TrPartDescInit(rel, p, &baseDesc, RB_OPER_TRUNCATE, RB_OBJ_PARTITION, false);
baseDesc.id = baseDesc.baseid = insertBaseid;
(void)TrDescWrite(&baseDesc);
TrUpdateBaseid(&baseDesc);
TrPartitionSetNewRelfilenode(rel, p, u_sess->utils_cxt.RecentXmin, &baseDesc);
/* process the toast table */
if (OidIsValid(toastOid)) {
Assert(rel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED);
toastRel = heap_open(toastOid, AccessExclusiveLock);
TrRelationSetNewRelfilenode(toastRel, u_sess->utils_cxt.RecentXmin, &baseDesc);
heap_close(toastRel, AccessExclusiveLock);
}
partitionClose(rel, p, AccessExclusiveLock);
/* report truncate partition to PgStatCollector */
pgstat_report_truncate(partOid, rel->rd_id, rel->rd_rel->relisshared);
}
void TrPartitionTableProcess(Relation rel, Oid insertBaseid)
{
/* truncate partitioned table */
List* partTupleList = NIL;
ListCell* partCell = NULL;
Oid heap_relid;
bool is_shared = rel->rd_rel->relisshared;
heap_relid = RelationGetRelid(rel);
/* partitioned table unspport the unlogged table */
Assert(rel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED);
/* process all partition */
partTupleList = searchPgPartitionByParentId(PART_OBJ_TYPE_TABLE_PARTITION, rel->rd_id);
foreach (partCell, partTupleList) {
if (RelationIsSubPartitioned(rel)) {
/* the "tup" just for get partOid, UHeapTup has no HEAP_HASOID flag, so here use HeapTuple */
HeapTuple tup = (HeapTuple)lfirst(partCell);
Oid partOid = HeapTupleGetOid(tup);
Partition p = partitionOpen(rel, partOid, AccessExclusiveLock);
Relation partRel = partitionGetRelation(rel, p);
List* subPartTupleList = searchPgPartitionByParentId(PART_OBJ_TYPE_TABLE_SUB_PARTITION, partOid);
ListCell* subPartCell = NULL;
foreach (subPartCell, subPartTupleList) {
HeapTuple tup = (HeapTuple)lfirst(subPartCell);
TrTruncateOnePart(partRel, tup, insertBaseid);
}
freePartList(subPartTupleList);
releaseDummyRelation(&partRel);
partitionClose(rel, p, AccessExclusiveLock);
} else {
HeapTuple tup = (HeapTuple)lfirst(partCell);
TrTruncateOnePart(rel, tup, insertBaseid);
}
}
freePartList(partTupleList);
/* report truncate partitioned table to PgStatCollector */
pgstat_report_truncate(heap_relid, InvalidOid, is_shared);
}
void TrTruncate(const TruncateStmt *stmt)
{
RangeVar *rv = (RangeVar*)linitial(stmt->relations);
Relation rel;
Oid relid;
Oid toastRelid;
TrObjDesc baseDesc;
/*
* 1. Open relation in AccessExclusiveLock, and check permission, etc.
*/
rel = heap_openrv(rv, AccessExclusiveLock);
relid = RelationGetRelid(rel);
/* find matview exists or not. */
Oid mlogid = find_matview_mlog_table(relid);
if (OidIsValid(mlogid)) {
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Not support truncate table under materialized view.")));
}
TrForbidAccessRbObject(RelationRelationId, relid, rv->relname);
truncate_check_rel(rel);
/*
* This effectively deletes all rows in the table, and may be done
* in a serializable transaction. In that case we must record a
* rw-conflict in to this transaction from each transaction
* holding a predicate lock on the table.
*/
CheckTableForSerializableConflictIn(rel);
/*
* 2. Create a new empty storage file for the relation, and assign it
* as the relfilenode value, and record the old relfilenode to recyclebin.
*/
TrDescInit(rel, &baseDesc, RB_OPER_TRUNCATE, RB_OBJ_TABLE, true, true);
baseDesc.id = baseDesc.baseid = TrDescWrite(&baseDesc);
TrUpdateBaseid(&baseDesc);
/*
* step 2.1. If rel is partition table, find all partitions, and Create some new empty
* storage file for the all partitions of the relation, and assign them as the
* relfilenodes value, and record the old relfilenodes to recyclebin.
*/
if (RELATION_IS_PARTITIONED(rel)) {
TrPartitionTableProcess(rel, baseDesc.baseid);
}
TrRelationSetNewRelfilenode(rel, u_sess->utils_cxt.RecentXmin, &baseDesc);
/*
* 3. The same for the toast table, if any.
*/
toastRelid = rel->rd_rel->reltoastrelid;
if (OidIsValid(toastRelid) && !RELATION_IS_PARTITIONED(rel)) {
Relation relToast = relation_open(toastRelid, AccessExclusiveLock);
TrRelationSetNewRelfilenode(relToast, u_sess->utils_cxt.RecentXmin, &baseDesc);
heap_close(relToast, NoLock);
}
/*
* 4. Reconstruct the indexes to match, and we're done.
*/
(void)ReindexRelation(relid, REINDEX_REL_PROCESS_TOAST, REINDEX_ALL_INDEX, &baseDesc);
/*
* 5. Report stat, and clean.
*/
/* report truncate to PgStatCollector */
pgstat_report_truncate(relid, InvalidOid, false);
/* Record time of truancate relation. */
recordRelationMTime(relid, rel->rd_rel->relkind);
heap_close(rel, NoLock);
}
/*
* RelationDropStorage
* Schedule unlinking of physical storage at transaction commit.
*/
void TrDoPurgeObjectTruncate(TrObjDesc *desc)
{
Relation rbRel;
SysScanDesc sd;
ScanKeyData skey[1];
HeapTuple tup;
Assert (((desc->type == RB_OBJ_TABLE) && desc->canpurge) || ((desc->type == RB_OBJ_PARTITION) && !desc->canpurge));
rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock);
ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcybaseid, BTEqualStrategyNumber,
F_INT8EQ, Int64GetDatum(desc->baseid));
sd = systable_beginscan(rbRel, RecyclebinBaseidIndexId, true, NULL, 1, skey);
while (HeapTupleIsValid(tup = systable_getnext(sd))) {
Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup);
RelFileNode rnode;
rnode.spcNode = ConvertToRelfilenodeTblspcOid(rbForm->rcytablespace);
rnode.dbNode = (rnode.spcNode == GLOBALTABLESPACE_OID) ? InvalidOid :
u_sess->proc_cxt.MyDatabaseId;
rnode.relNode = rbForm->rcyrelfilenode;
rnode.bucketNode = InvalidBktId;
/*
* Schedule unlinking of the old storage at transaction commit.
*/
InsertStorageIntoPendingList(
&rnode, InvalidAttrNumber, InvalidBackendId, rbForm->rcyowner, true, false);
simple_heap_delete(rbRel, &tup->t_self);
ereport(LOG, (errmsg("Delete truncated object %u/%u/%u", rnode.spcNode,
rnode.dbNode, rnode.relNode)));
}
systable_endscan(sd);
heap_close(rbRel, RowExclusiveLock);
/* ... and now we have eoxact cleanup work to do */
SetRelCacheNeedEOXActWork(true);
/*
* CommandCounterIncrement here to ensure that preceding changes are all
* visible to the next deletion step.
*/
CommandCounterIncrement();
}
/* flashback table to before truncate */
void TrRestoreTruncate(const TimeCapsuleStmt *stmt)
{
TrObjDesc baseDesc;
Relation rbRel;
SysScanDesc sd;
ScanKeyData skey[1];
HeapTuple tup;
Relation rel;
Oid relid;
bool found = false;
TrObjDesc desc;
/* process restore truncate fail: TIMECAPSULE TABLE "BIN$3C534EBE021$4930808==$0" TO BEFORE TRUNCATE; */
found = TrFetchName(stmt->relation->relname, RB_OBJ_TABLE, &desc, RB_OPER_RESTORE_TRUNCATE);
if (found) {
stmt->relation->relname = desc.originname;
}
rel = heap_openrv(stmt->relation, AccessExclusiveLock);
relid = RelationGetRelid(rel);
if (rel->rd_tam_type == TAM_HEAP) {
heap_close(rel, NoLock);
elog(ERROR, "timecapsule does not support astore yet");
return;
}
if (found) {
stmt->relation->relname = desc.name;
}
/* 1. Fetch the latest available recycle object. */
TrOperFetch(stmt->relation, RB_OBJ_TABLE, &baseDesc, RB_OPER_RESTORE_TRUNCATE);
/* 2. Lock recycle object and base relation. */
baseDesc.authid = GetUserId();
TrOperPrep(&baseDesc, RB_OPER_RESTORE_TRUNCATE);
/* 3. Check base relation whether normal and matched. */
TrBaseRelMatched(&baseDesc);
/* 4. Do restore. */
rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock);
ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcybaseid, BTEqualStrategyNumber,
F_INT8EQ, Int64GetDatum(baseDesc.id));
sd = systable_beginscan(rbRel, RecyclebinBaseidIndexId, true, NULL, 1, skey);
while (HeapTupleIsValid(tup = systable_getnext(sd))) {
if (!RELATION_IS_PARTITIONED(rel)) {
TrSwapRelfilenode(rbRel, tup, false);
} else {
TrSwapRelfilenode(rbRel, tup, true);
}
}
systable_endscan(sd);
heap_close(rbRel, RowExclusiveLock);
heap_close(rel, NoLock);
/*
* CommandCounterIncrement here to ensure that preceding changes are all
* visible to the next deletion step.
*/
CommandCounterIncrement();
return;
}

View File

@ -1879,7 +1879,7 @@ typedef struct knl_u_relcache_context {
/*
* This flag lets us optimize away work in AtEO(Sub)Xact_RelationCache().
*/
bool need_eoxact_work;
bool RelCacheNeedEOXActWork;
HTAB* OpClassCache;
@ -2309,7 +2309,7 @@ typedef struct knl_u_cache_context {
struct HTAB* dn_hash_table;
bool part_cache_need_eoxact_work;
bool PartCacheNeedEOXActWork;
bool bucket_cache_need_eoxact_work;

View File

@ -39,7 +39,7 @@ public:
m_bucket_list.ResetContent();
invalid_entries.ResetInitFlag();
m_global_partdefcache = NULL;
part_cache_need_eoxact_work = false;
PartCacheNeedEOXActWork = false;
m_is_inited = false;
m_db_id = InvalidOid;
}
@ -64,7 +64,7 @@ public:
Partition PartitionIdGetPartition(Oid part_oid, StorageType storage_type);
public:
bool part_cache_need_eoxact_work;
bool PartCacheNeedEOXActWork;
private:
void InsertPartitionIntoGlobal(Partition part, uint32 hash_value);

View File

@ -38,7 +38,7 @@ public:
{
m_is_inited = false;
local_systupcaches = NULL;
need_eoxact_work = false;
CatCacheNeedEOXActWork = false;
}
void ResetInitFlag(bool include_shared)
@ -54,13 +54,13 @@ public:
void AtEOXact_CatCache(bool isCommit)
{
if (!need_eoxact_work) {
if (!CatCacheNeedEOXActWork) {
return;
}
for (int cache_id = 0; cache_id < SysCacheSize; cache_id++) {
local_systupcaches[cache_id]->AtEOXact_CatCache(isCommit);
}
need_eoxact_work = false;
CatCacheNeedEOXActWork = false;
}
/* systup may be shared table cache. not cleaned when cleardb */
@ -166,7 +166,7 @@ public:
}
local_systupcaches[cache_id]->PrepareToInvalidateCacheTuple(tuple, newtuple, function);
}
need_eoxact_work = true;
CatCacheNeedEOXActWork = true;
}
void CreateObject();
@ -270,6 +270,6 @@ private:
}
bool m_is_inited;
bool need_eoxact_work;
bool CatCacheNeedEOXActWork;
};
#endif

View File

@ -124,7 +124,7 @@ public:
*/
List *initFileRelationIds;
bool need_eoxact_work;
bool RelCacheNeedEOXActWork;
struct tupleDesc *m_pgclassdesc;
struct tupleDesc *m_pgindexdesc;

View File

@ -105,21 +105,21 @@ extern Partition PartitionBuildDesc(Oid targetPartId, StorageType storage_type,
} \
} while (0)
inline bool PartCacheNeedEoxactWork()
inline bool GetPartCacheNeedEOXActWork()
{
if (EnableLocalSysCache()) {
return t_thrd.lsc_cxt.lsc->partdefcache.part_cache_need_eoxact_work;
return t_thrd.lsc_cxt.lsc->partdefcache.PartCacheNeedEOXActWork;
} else {
return u_sess->cache_cxt.part_cache_need_eoxact_work;
return u_sess->cache_cxt.PartCacheNeedEOXActWork;
}
}
inline void SetPartCacheNeedEoxactWork(bool value)
inline void SetPartCacheNeedEOXActWork(bool value)
{
if (EnableLocalSysCache()) {
t_thrd.lsc_cxt.lsc->partdefcache.part_cache_need_eoxact_work = value;
t_thrd.lsc_cxt.lsc->partdefcache.PartCacheNeedEOXActWork = value;
} else {
u_sess->cache_cxt.part_cache_need_eoxact_work = value;
u_sess->cache_cxt.PartCacheNeedEOXActWork = value;
}
}
#endif

View File

@ -194,21 +194,21 @@ inline void AddLocalRelCacheInvalsReceived(int value)
}
}
inline bool LocalRelCacheNeedEOXactWork()
inline bool GetRelCacheNeedEOXActWork()
{
if (EnableLocalSysCache()) {
return t_thrd.lsc_cxt.lsc->tabdefcache.need_eoxact_work;
return t_thrd.lsc_cxt.lsc->tabdefcache.RelCacheNeedEOXActWork;
} else {
return u_sess->relcache_cxt.need_eoxact_work;
return u_sess->relcache_cxt.RelCacheNeedEOXActWork;
}
}
inline void SetLocalRelCacheNeedEOXactWork(bool value)
inline void SetRelCacheNeedEOXActWork(bool value)
{
if (EnableLocalSysCache()) {
t_thrd.lsc_cxt.lsc->tabdefcache.need_eoxact_work = value;
t_thrd.lsc_cxt.lsc->tabdefcache.RelCacheNeedEOXActWork = value;
} else {
u_sess->relcache_cxt.need_eoxact_work = value;
u_sess->relcache_cxt.RelCacheNeedEOXActWork = value;
}
}