diff --git a/src/common/backend/catalog/storage_gtt.cpp b/src/common/backend/catalog/storage_gtt.cpp index 4297ca397281bab4a33c279567287f5b048e5a22..83c2047319ba9db87447719be520b4695235f6d7 100644 --- a/src/common/backend/catalog/storage_gtt.cpp +++ b/src/common/backend/catalog/storage_gtt.cpp @@ -1370,3 +1370,27 @@ static gtt_local_hash_entry* gtt_search_by_relid(Oid relid, bool missingOk) return entry; } +void gtt_create_storage_files(Oid relid) +{ + if (gtt_storage_attached(relid)) { + return; + } + + MemoryContext ctxAlterGtt = + AllocSetContextCreate(CurrentMemoryContext, "gtt alter table", ALLOCSET_DEFAULT_SIZES); + MemoryContext oldcontext = MemoryContextSwitchTo(ctxAlterGtt); + ResultRelInfo* resultRelInfo = makeNode(ResultRelInfo); + Relation rel = relation_open(relid, NoLock); + + InitResultRelInfo(resultRelInfo, rel, 1, 0); + if (resultRelInfo->ri_RelationDesc->rd_rel->relhasindex && + resultRelInfo->ri_IndexRelationDescs == NULL) { + ExecOpenIndices(resultRelInfo); + } + init_gtt_storage(CMD_UTILITY, resultRelInfo); + relation_close(rel, NoLock); + ExecCloseIndices(resultRelInfo); + (void)MemoryContextSwitchTo(oldcontext); + MemoryContextDelete(ctxAlterGtt); +} + diff --git a/src/common/backend/utils/cache/lsyscache.cpp b/src/common/backend/utils/cache/lsyscache.cpp index da9bdde0264b5ceef549a1edb532e5b91bb1f2cb..11d2eaaf5b880585cfd65979f75938423e1c22cc 100644 --- a/src/common/backend/utils/cache/lsyscache.cpp +++ b/src/common/backend/utils/cache/lsyscache.cpp @@ -1922,16 +1922,20 @@ char get_rel_persistence(Oid relid) { HeapTuple tp; Form_pg_class reltup; - char result; tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); - if (!HeapTupleIsValid(tp)) - elog(ERROR, "cache lookup failed for relation %u", relid); - reltup = (Form_pg_class) GETSTRUCT(tp); - result = reltup->relpersistence; - ReleaseSysCache(tp); - - return result; + if (HeapTupleIsValid(tp)) { + reltup = (Form_pg_class) GETSTRUCT(tp); + char result = reltup->relpersistence; + ReleaseSysCache(tp); + return result; + } else { + /* + * for partition table. + * global temp table does not support partitioning. + */ + return '\0'; + } } /* diff --git a/src/gausskernel/optimizer/commands/cluster.cpp b/src/gausskernel/optimizer/commands/cluster.cpp index 202d2e740243a1620df48892560e869171e5479d..609e5bd7ddc5a6c3b41f96554750d4cfd0399804 100644 --- a/src/gausskernel/optimizer/commands/cluster.cpp +++ b/src/gausskernel/optimizer/commands/cluster.cpp @@ -142,8 +142,7 @@ static Datum pgxc_parallel_execution(const char* query, ExecNodes* exec_nodes); static int switch_relfilenode_execnode(Oid relOid1, Oid relOid2, bool isbucket, RedisSwitchNode* rsn); #endif static void swapRelationIndicesRelfileNode(Relation rel1, Relation rel2, bool swapBucket); -static void GttSwapRelationFiles(Oid r1, Oid r2, bool targetIsPgClass, bool swapToastByContent, - TransactionId frozenXid, Oid *mappedTables); +static void GttSwapRelationFiles(Oid r1, Oid r2); /* --------------------------------------------------------------------------- * This cluster code allows for clustering multiple tables at once. Because @@ -698,7 +697,6 @@ static void rebuild_relation( Oid tableOid = RelationGetRelid(OldHeap); Oid tableSpace = OldHeap->rd_rel->reltablespace; Oid OIDNewHeap; - char relpersistence; bool is_system_catalog = false; bool swap_toast_by_content = false; TransactionId frozenXid; @@ -710,7 +708,6 @@ static void rebuild_relation( mark_index_clustered(OldHeap, indexOid); /* Remember if it's a system catalog */ - relpersistence = OldHeap->rd_rel->relpersistence; is_system_catalog = IsSystemRelation(OldHeap); /* Close relcache entry, but keep lock until transaction commit */ @@ -744,8 +741,7 @@ static void rebuild_relation( * Swap the physical files of the target and transient tables, then * rebuild the target's indexes and throw away the transient table. */ - finish_heap_swap( - tableOid, OIDNewHeap, is_system_catalog, swap_toast_by_content, false, frozenXid, memUsage, relpersistence); + finish_heap_swap(tableOid, OIDNewHeap, is_system_catalog, swap_toast_by_content, false, frozenXid, memUsage); /* report vacuum full stat to PgStatCollector */ pgstat_report_vacuum(tableOid, InvalidOid, is_shared, deleteTupleNum); @@ -2790,7 +2786,7 @@ static void SwapCStoreTables(Oid relId1, Oid relId2, Oid parentOid, Oid tempTabl * cleaning up (including rebuilding all indexes on the old heap). */ void finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, bool is_system_catalog, bool swap_toast_by_content, - bool checkConstraints, TransactionId frozenXid, AdaptMem* memInfo, char newrelpersistence) + bool checkConstraints, TransactionId frozenXid, AdaptMem* memInfo) { ObjectAddress object; Oid mapped_tables[4]; @@ -2806,10 +2802,9 @@ void finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, bool is_system_catalog, bo * Swap the contents of the heap relations (including any toast tables). * Also set old heap's relfrozenxid to frozenXid. */ - if (newrelpersistence == RELPERSISTENCE_GLOBAL_TEMP) { + if (get_rel_persistence(OIDOldHeap) == RELPERSISTENCE_GLOBAL_TEMP) { Assert(!is_system_catalog); - GttSwapRelationFiles(OIDOldHeap, OIDNewHeap, (OIDOldHeap == RelationRelationId), - swap_toast_by_content, frozenXid, mapped_tables); + GttSwapRelationFiles(OIDOldHeap, OIDNewHeap); } else { swap_relation_files(OIDOldHeap, OIDNewHeap, (OIDOldHeap == RelationRelationId), swap_toast_by_content, frozenXid, mapped_tables); @@ -2997,17 +2992,13 @@ static List* get_tables_to_cluster(MemoryContext cluster_context) return rvs; } -static void GttSwapRelationFiles(Oid r1, Oid r2, bool targetIsPgClass, bool swapToastByContent, - TransactionId frozenXid, Oid *mappedTables) +static void GttSwapRelationFiles(Oid r1, Oid r2) { - Relation relRelation; - Oid relfilenode1, - relfilenode2; + Oid relfilenode1; + Oid relfilenode2; Relation rel1; Relation rel2; - relRelation = relation_open(RelationRelationId, RowExclusiveLock); - rel1 = relation_open(r1, AccessExclusiveLock); rel2 = relation_open(r2, AccessExclusiveLock); @@ -3020,82 +3011,17 @@ static void GttSwapRelationFiles(Oid r1, Oid r2, bool targetIsPgClass, bool swap CacheInvalidateRelcache(rel1); CacheInvalidateRelcache(rel2); - if (rel1->rd_rel->reltoastrelid || rel2->rd_rel->reltoastrelid) { - if (swapToastByContent) { - if (rel1->rd_rel->reltoastrelid && rel2->rd_rel->reltoastrelid) { - GttSwapRelationFiles(rel1->rd_rel->reltoastrelid, - rel2->rd_rel->reltoastrelid, - targetIsPgClass, - swapToastByContent, - frozenXid, - mappedTables); - } else { - elog(ERROR, "cannot swap toast files by content when there's only one"); - } - } else { - ObjectAddress baseobject, - toastobject; - long count; - - if (IsSystemRelation(rel1)) { - elog(ERROR, "cannot swap toast files by links for system catalogs"); - } - - if (rel1->rd_rel->reltoastrelid) { - count = deleteDependencyRecordsFor(RelationRelationId, - rel1->rd_rel->reltoastrelid, - false); - if (count != 1) { - elog(ERROR, "expected one dependency record for TOAST table, found %ld", - count); - } - } - if (rel2->rd_rel->reltoastrelid) { - count = deleteDependencyRecordsFor(RelationRelationId, - rel2->rd_rel->reltoastrelid, - false); - if (count != 1) { - elog(ERROR, "expected one dependency record for TOAST table, found %ld", - count); - } - } - - /* Register new dependencies */ - baseobject.classId = RelationRelationId; - baseobject.objectSubId = 0; - toastobject.classId = RelationRelationId; - toastobject.objectSubId = 0; - - if (rel1->rd_rel->reltoastrelid) { - baseobject.objectId = r1; - toastobject.objectId = rel1->rd_rel->reltoastrelid; - recordDependencyOn(&toastobject, &baseobject, - DEPENDENCY_INTERNAL); - } - - if (rel2->rd_rel->reltoastrelid) { - baseobject.objectId = r2; - toastobject.objectId = rel2->rd_rel->reltoastrelid; - recordDependencyOn(&toastobject, &baseobject, DEPENDENCY_INTERNAL); - } - } + if (rel1->rd_rel->reltoastrelid && rel2->rd_rel->reltoastrelid) { + GttSwapRelationFiles(rel1->rd_rel->reltoastrelid, rel2->rd_rel->reltoastrelid); } - if (swapToastByContent && rel1->rd_rel->relkind == RELKIND_TOASTVALUE && - rel2->rd_rel->relkind == RELKIND_TOASTVALUE) { - GttSwapRelationFiles(rel1->rd_rel->reltoastidxid, - rel2->rd_rel->reltoastidxid, - targetIsPgClass, - swapToastByContent, - InvalidTransactionId, - mappedTables); + if (rel1->rd_rel->relkind == RELKIND_TOASTVALUE && rel2->rd_rel->relkind == RELKIND_TOASTVALUE) { + GttSwapRelationFiles(rel1->rd_rel->reltoastidxid, rel2->rd_rel->reltoastidxid); } relation_close(rel1, NoLock); relation_close(rel2, NoLock); - relation_close(relRelation, RowExclusiveLock); - RelationCloseSmgrByOid(r1); RelationCloseSmgrByOid(r2); diff --git a/src/gausskernel/optimizer/commands/tablecmds.cpp b/src/gausskernel/optimizer/commands/tablecmds.cpp index 14271bcfb45f664bb539ac91da1878f106439196..2a812876941a0225e931da466ba157baf97f8262 100644 --- a/src/gausskernel/optimizer/commands/tablecmds.cpp +++ b/src/gausskernel/optimizer/commands/tablecmds.cpp @@ -6272,7 +6272,9 @@ static void ATRewriteCatalogs(List** wqueue, LOCKMODE lockmode) /* Check to see if a toast table must be added. */ foreach (ltab, *wqueue) { AlteredTableInfo* tab = (AlteredTableInfo*)lfirst(ltab); - + if (get_rel_persistence(tab->relid) == RELPERSISTENCE_GLOBAL_TEMP) { + gtt_create_storage_files(tab->relid); + } if (tab->relkind == RELKIND_RELATION) AlterTableCreateToastTable(tab->relid, (Datum)0); } @@ -6674,28 +6676,6 @@ static void ATRewriteTables(List** wqueue, LOCKMODE lockmode) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot rewrite temporary tables of other sessions"))); - if (RELATION_IS_GLOBAL_TEMP(OldHeap)) { - /* gtt may not attached, create it */ - if (!gtt_storage_attached(tab->relid)) { - ResultRelInfo *resultRelInfo; - MemoryContext oldcontext; - MemoryContext ctx_alter_gtt; - ctx_alter_gtt = - AllocSetContextCreate(CurrentMemoryContext, "gtt alter table", ALLOCSET_DEFAULT_SIZES); - oldcontext = MemoryContextSwitchTo(ctx_alter_gtt); - resultRelInfo = makeNode(ResultRelInfo); - InitResultRelInfo(resultRelInfo, OldHeap, 1, 0); - if (resultRelInfo->ri_RelationDesc->rd_rel->relhasindex && - resultRelInfo->ri_IndexRelationDescs == NULL) - ExecOpenIndices(resultRelInfo); - - init_gtt_storage(CMD_UTILITY, resultRelInfo); - ExecCloseIndices(resultRelInfo); - (void)MemoryContextSwitchTo(oldcontext); - MemoryContextDelete(ctx_alter_gtt); - } - } - /* * Select destination tablespace (same as original unless user * requested a change) @@ -20247,7 +20227,10 @@ static void ExecRewriteRowTable(AlteredTableInfo* tab, Oid NewTableSpace, LOCKMO ATRewriteTable(tab, oldRel, newRel); heap_close(oldRel, NoLock); heap_close(newRel, NoLock); - + bool swapToastByContent = false; + if (RELATION_IS_GLOBAL_TEMP(oldRel)) { + swapToastByContent = true; + } /* * Swap the physical files of the old and new heaps, then rebuild * indexes and discard the old heap. We can use RecentXmin for @@ -20256,7 +20239,7 @@ static void ExecRewriteRowTable(AlteredTableInfo* tab, Oid NewTableSpace, LOCKMO * we never try to swap toast tables by content, since we have no * interest in letting this code work on system catalogs. */ - finish_heap_swap(tab->relid, OIDNewHeap, false, false, true, u_sess->utils_cxt.RecentXmin); + finish_heap_swap(tab->relid, OIDNewHeap, false, swapToastByContent, true, u_sess->utils_cxt.RecentXmin); /* clear all attrinitdefval */ clearAttrInitDefVal(tab->relid); diff --git a/src/include/catalog/storage_gtt.h b/src/include/catalog/storage_gtt.h index d76a2dd5271c430abef379513a54f073b4520d49..3ac692e86216de920de59d9e86cd17172ecc73e1 100644 --- a/src/include/catalog/storage_gtt.h +++ b/src/include/catalog/storage_gtt.h @@ -43,5 +43,5 @@ extern void gtt_fix_index_state(Relation index); extern void init_gtt_storage(CmdType operation, ResultRelInfo *resultRelInfo); extern Oid gtt_fetch_current_relfilenode(Oid relid); extern void gtt_switch_rel_relfilenode(Oid rel1, Oid relfilenode1, Oid rel2, Oid relfilenode2, bool footprint); - +extern void gtt_create_storage_files(Oid relid); #endif /* STORAGE_GTT_H */ diff --git a/src/include/commands/cluster.h b/src/include/commands/cluster.h index 6ca23fe336750f3266f03d10d9cb2ff3651daa9b..fb7edbb381026ca24ec3be97cc4c98bc69c2875a 100755 --- a/src/include/commands/cluster.h +++ b/src/include/commands/cluster.h @@ -36,8 +36,7 @@ extern void finishPartitionHeapSwap(Oid partitionOid, Oid tempTableOid, bool swa TransactionId frozenXid, bool tempTableIsPartition = false); extern void finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, bool is_system_catalog, bool swap_toast_by_content, - bool check_constraints, TransactionId frozenXid, AdaptMem* memInfo = NULL, - char newrelpersistence = RELPERSISTENCE_PERMANENT); + bool check_constraints, TransactionId frozenXid, AdaptMem* memInfo = NULL); extern void vacuumFullPart(Oid partOid, VacuumStmt* vacstmt, int freeze_min_age, int freeze_table_age); extern void updateRelationName(Oid relOid, bool isPartition, const char* relNewName); diff --git a/src/test/regress/expected/gtt_function.out b/src/test/regress/expected/gtt_function.out index e0a87811055f2589fd6d4058ea2f0a6c56265cb6..4908d212d9d8b4a87c81da7057411d8e569c284c 100644 --- a/src/test/regress/expected/gtt_function.out +++ b/src/test/regress/expected/gtt_function.out @@ -73,8 +73,8 @@ PARTITION BY RANGE (cre_time) ( PARTITION P2 VALUES LESS THAN('2019-01-01 00:00:00') ); NOTICE: CREATE TABLE will create implicit sequence "p_table01_id_seq" for serial column "p_table01.id" -ERROR: ON COMMIT option is not supported for partitioned table - +ERROR: ON COMMIT option is not supported for partitioned table + --CREATE global temp TABLE p_table01_2018 --PARTITION OF p_table01 --FOR VALUES FROM ('2018-01-01 00:00:00') TO ('2019-01-01 00:00:00') on commit delete rows; @@ -160,8 +160,21 @@ create global temp table gtt_test_rename(a int primary key, b text); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "gtt_test_rename_pkey" for table "gtt_test_rename" --ok alter table gtt_test_rename rename to gtt_test_new; +--ok +ALTER TABLE gtt_test_new ADD COLUMN address integer; +--ok +insert into gtt_test_new values(1, 'hello postgres', 128); -- ok -ALTER TABLE gtt_test_new ADD COLUMN address varchar(30); +ALTER TABLE gtt_test_new MODIFY (address varchar(1024)); +--ok +select * from gtt_test_new; + a | b | address +---+----------------+--------- + 1 | hello postgres | 128 +(1 row) + +--ok +ALTER TABLE gtt_test_new DROP address; CREATE global temp TABLE products ( product_no integer PRIMARY KEY, name text, diff --git a/src/test/regress/sql/gtt_function.sql b/src/test/regress/sql/gtt_function.sql index 0ae2ffe76ec8f89c33366c3b7e9ca1c2f188c6e8..6523c70baf52f63a81eb8397b036b3ab2ae16581 100644 --- a/src/test/regress/sql/gtt_function.sql +++ b/src/test/regress/sql/gtt_function.sql @@ -141,7 +141,7 @@ create global temp table gtt4(a int primary key, b text) with(on_commit_delete_r create global temp table gtt5(a int primary key, b text) with(on_commit_delete_rows=true); -- ok -create table tb1 (like gtt2 including reloptions); +create table tb1 (like gtt2 including reloptions); -- ERROR create global temp table gtt7 (like gtt2 including reloptions) on commit preserve rows; @@ -160,8 +160,20 @@ create global temp table gtt_test_rename(a int primary key, b text); --ok alter table gtt_test_rename rename to gtt_test_new; +--ok +ALTER TABLE gtt_test_new ADD COLUMN address integer; + +--ok +insert into gtt_test_new values(1, 'hello postgres', 128); + -- ok -ALTER TABLE gtt_test_new ADD COLUMN address varchar(30); +ALTER TABLE gtt_test_new MODIFY (address varchar(1024)); + +--ok +select * from gtt_test_new; + +--ok +ALTER TABLE gtt_test_new DROP address; CREATE global temp TABLE products ( product_no integer PRIMARY KEY,