forked from huawei/openGauss-server
!73 fix GTT alter table issue
Merge pull request !73 from wangzhijun/master
This commit is contained in:
commit
d487655241
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue