From 0c08e764e03aed8e1f1c57df661b13f12f91a0be Mon Sep 17 00:00:00 2001 From: openGaussDev Date: Tue, 8 Mar 2022 20:22:47 +0800 Subject: [PATCH] Global SysCache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Offering: openGaussDev More detail: 修复闪回功能未适配GSC导致DDL数据无法丢弃问题 # Conflicts: # src/gausskernel/storage/tcap/tcap_truncate.cpp Match-id-e09ce9c267ac9ae227186b0e7cbc9377b1cfb06a --- .../utils/cache/knl_localpartdefcache.cpp | 8 +- .../utils/cache/knl_localtabdefcache.cpp | 10 +- src/common/backend/utils/cache/partcache.cpp | 10 +- src/common/backend/utils/cache/relcache.cpp | 12 +- .../cbb/utils/partition/partitionmap.cpp | 2 +- .../process/threadpool/knl_session.cpp | 4 +- .../storage/tcap/tcap_truncate.cpp | 984 +++++++++--------- src/include/knl/knl_session.h | 4 +- src/include/utils/knl_localpartdefcache.h | 4 +- src/include/utils/knl_localsystabcache.h | 10 +- src/include/utils/knl_localtabdefcache.h | 2 +- src/include/utils/knl_partcache.h | 12 +- src/include/utils/knl_relcache.h | 12 +- 13 files changed, 538 insertions(+), 536 deletions(-) diff --git a/src/common/backend/utils/cache/knl_localpartdefcache.cpp b/src/common/backend/utils/cache/knl_localpartdefcache.cpp index a54bd21a3..a12167b92 100644 --- a/src/common/backend/utils/cache/knl_localpartdefcache.cpp +++ b/src/common/backend/utils/cache/knl_localpartdefcache.cpp @@ -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; diff --git a/src/common/backend/utils/cache/knl_localtabdefcache.cpp b/src/common/backend/utils/cache/knl_localtabdefcache.cpp index 704c44bc0..6b989cde8 100644 --- a/src/common/backend/utils/cache/knl_localtabdefcache.cpp +++ b/src/common/backend/utils/cache/knl_localtabdefcache.cpp @@ -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; diff --git a/src/common/backend/utils/cache/partcache.cpp b/src/common/backend/utils/cache/partcache.cpp index 9b025ff8e..1015826fe 100644 --- a/src/common/backend/utils/cache/partcache.cpp +++ b/src/common/backend/utils/cache/partcache.cpp @@ -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) diff --git a/src/common/backend/utils/cache/relcache.cpp b/src/common/backend/utils/cache/relcache.cpp index be1b965a4..f44b182b0 100644 --- a/src/common/backend/utils/cache/relcache.cpp +++ b/src/common/backend/utils/cache/relcache.cpp @@ -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); } /* diff --git a/src/gausskernel/cbb/utils/partition/partitionmap.cpp b/src/gausskernel/cbb/utils/partition/partitionmap.cpp index 1f2989690..b5242fa97 100644 --- a/src/gausskernel/cbb/utils/partition/partitionmap.cpp +++ b/src/gausskernel/cbb/utils/partition/partitionmap.cpp @@ -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 "); } } diff --git a/src/gausskernel/process/threadpool/knl_session.cpp b/src/gausskernel/process/threadpool/knl_session.cpp index 3b479b240..6c3225a37 100755 --- a/src/gausskernel/process/threadpool/knl_session.cpp +++ b/src/gausskernel/process/threadpool/knl_session.cpp @@ -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; } diff --git a/src/gausskernel/storage/tcap/tcap_truncate.cpp b/src/gausskernel/storage/tcap/tcap_truncate.cpp index ea048f21a..9fb89f4f5 100644 --- a/src/gausskernel/storage/tcap/tcap_truncate.cpp +++ b/src/gausskernel/storage/tcap/tcap_truncate.cpp @@ -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; +} diff --git a/src/include/knl/knl_session.h b/src/include/knl/knl_session.h index 0b664c6d5..766c6179b 100644 --- a/src/include/knl/knl_session.h +++ b/src/include/knl/knl_session.h @@ -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; diff --git a/src/include/utils/knl_localpartdefcache.h b/src/include/utils/knl_localpartdefcache.h index a37b2f94e..990c2dc4a 100644 --- a/src/include/utils/knl_localpartdefcache.h +++ b/src/include/utils/knl_localpartdefcache.h @@ -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); diff --git a/src/include/utils/knl_localsystabcache.h b/src/include/utils/knl_localsystabcache.h index 5acca8a3a..ba5eadd2c 100644 --- a/src/include/utils/knl_localsystabcache.h +++ b/src/include/utils/knl_localsystabcache.h @@ -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 \ No newline at end of file diff --git a/src/include/utils/knl_localtabdefcache.h b/src/include/utils/knl_localtabdefcache.h index ca86d33e1..4d020b851 100644 --- a/src/include/utils/knl_localtabdefcache.h +++ b/src/include/utils/knl_localtabdefcache.h @@ -124,7 +124,7 @@ public: */ List *initFileRelationIds; - bool need_eoxact_work; + bool RelCacheNeedEOXActWork; struct tupleDesc *m_pgclassdesc; struct tupleDesc *m_pgindexdesc; diff --git a/src/include/utils/knl_partcache.h b/src/include/utils/knl_partcache.h index a8324ca77..04fcd4acc 100644 --- a/src/include/utils/knl_partcache.h +++ b/src/include/utils/knl_partcache.h @@ -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 \ No newline at end of file diff --git a/src/include/utils/knl_relcache.h b/src/include/utils/knl_relcache.h index cf269e9ed..1a88f2509 100644 --- a/src/include/utils/knl_relcache.h +++ b/src/include/utils/knl_relcache.h @@ -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; } }