From 5bbb6f0941123d43c3adf82834acc936093b10dc Mon Sep 17 00:00:00 2001 From: wangzhijun2018 Date: Wed, 12 Aug 2020 15:08:21 +0800 Subject: [PATCH] GTT alter table enhancement --- src/common/backend/catalog/heap.cpp | 10 ++- src/common/backend/catalog/storage_gtt.cpp | 48 ++++++++++++- .../optimizer/commands/tablecmds.cpp | 6 +- src/include/catalog/storage_gtt.h | 1 + src/test/regress/expected/gtt_function.out | 68 ++++++++++++++++++- src/test/regress/sql/gtt_function.sql | 24 +++++++ 6 files changed, 150 insertions(+), 7 deletions(-) diff --git a/src/common/backend/catalog/heap.cpp b/src/common/backend/catalog/heap.cpp index e7bec0ec01..dedda7885c 100755 --- a/src/common/backend/catalog/heap.cpp +++ b/src/common/backend/catalog/heap.cpp @@ -2460,8 +2460,14 @@ void RemoveAttributeById(Oid relid, AttrNumber attnum) heap_close(attr_rel, RowExclusiveLock); - if (attnum > 0) - RemoveStatistics<'c'>(relid, attnum); + if (attnum > 0) { + if (RELATION_IS_GLOBAL_TEMP(rel)) { + remove_gtt_att_statistic(relid, attnum); + } else { + RemoveStatistics<'c'>(relid, attnum); + } + } + /* decrease the relation's relnatts in pg_class */ if (isRedisDropColumn) { pgclass = heap_open(RelationRelationId, RowExclusiveLock); diff --git a/src/common/backend/catalog/storage_gtt.cpp b/src/common/backend/catalog/storage_gtt.cpp index 83c2047319..9fab21762e 100644 --- a/src/common/backend/catalog/storage_gtt.cpp +++ b/src/common/backend/catalog/storage_gtt.cpp @@ -709,6 +709,50 @@ bool get_gtt_relstats(Oid relid, BlockNumber* relpages, double* reltuples, Block return true; } +void remove_gtt_att_statistic(Oid reloid, int attnum) +{ + gtt_local_hash_entry* entry = gtt_search_by_relid(reloid, true); + if (entry == NULL) { + return; + } + for (int i = 0; i < entry->natts; i++) { + if (entry->attnum[i] != attnum) { + continue; + } + Assert(entry->att_stat_tups[i]); + entry->attnum[i] = 0; + heap_freetuple(entry->att_stat_tups[i]); + entry->att_stat_tups[i] = NULL; + break; + } + return; +} + +void extend_gtt_att_statistic(gtt_local_hash_entry* entry, int natts) +{ + Assert(entry != NULL); + Assert(entry->natts < natts); + + MemoryContext oldContext = MemoryContextSwitchTo(u_sess->gtt_ctx.gtt_relstats_context); + int* attNum = (int*)palloc0(sizeof(int) * natts); + HeapTuple* attStatTups = (HeapTuple*)palloc0(sizeof(HeapTuple) * natts); + for (int i = 0; i < entry->natts; i++) { + if (entry->attnum[i] == 0) { + continue; + } + attNum[i] = entry->attnum[i]; + attStatTups[i] = entry->att_stat_tups[i]; + } + pfree(entry->attnum); + pfree(entry->att_stat_tups); + + entry->natts = natts; + entry->attnum = attNum; + entry->att_stat_tups = attStatTups; + (void)MemoryContextSwitchTo(oldContext); + return; +} + /* * Update global temp table statistic info(definition is same as pg_statistic) * to local hashtable where ananyze global temp table @@ -725,10 +769,8 @@ void up_gtt_att_statistic(Oid reloid, int attnum, int natts, TupleDesc tupleDesc entry = gtt_search_by_relid(reloid, true); if (entry == NULL) return; - if (entry->natts < natts) { - elog(WARNING, "reloid %u not support update attstat after add colunm", reloid); - return; + extend_gtt_att_statistic(entry, natts); } oldcontext = MemoryContextSwitchTo(u_sess->gtt_ctx.gtt_relstats_context); diff --git a/src/gausskernel/optimizer/commands/tablecmds.cpp b/src/gausskernel/optimizer/commands/tablecmds.cpp index e545dfcb92..01e5060f76 100644 --- a/src/gausskernel/optimizer/commands/tablecmds.cpp +++ b/src/gausskernel/optimizer/commands/tablecmds.cpp @@ -11115,7 +11115,11 @@ static void ATExecAlterColumnType(AlteredTableInfo* tab, Relation rel, AlterTabl /* * Drop any pg_statistic entry for the column, since it's now wrong type */ - RemoveStatistics<'c'>(RelationGetRelid(rel), attnum); + if (RELATION_IS_GLOBAL_TEMP(rel)) { + remove_gtt_att_statistic(RelationGetRelid(rel), attnum); + } else { + RemoveStatistics<'c'>(RelationGetRelid(rel), attnum); + } /* * Update the default, if present, by brute force --- remove and re-add diff --git a/src/include/catalog/storage_gtt.h b/src/include/catalog/storage_gtt.h index 3ac692e862..74079bdd87 100644 --- a/src/include/catalog/storage_gtt.h +++ b/src/include/catalog/storage_gtt.h @@ -44,4 +44,5 @@ 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); +extern void remove_gtt_att_statistic(Oid reloid, int attnum); #endif /* STORAGE_GTT_H */ diff --git a/src/test/regress/expected/gtt_function.out b/src/test/regress/expected/gtt_function.out index 2af1b5a3eb..a53fd63e4a 100644 --- a/src/test/regress/expected/gtt_function.out +++ b/src/test/regress/expected/gtt_function.out @@ -176,6 +176,71 @@ select * from gtt_test_new; --ok ALTER TABLE gtt_test_new DROP address; +--gtt statistic test +create global temp table gtt_statistic_test(id int); +insert into gtt_statistic_test values (generate_series(1,1000)); +analyze gtt_statistic_test; +select attname,avg_width from pg_gtt_stats where tablename='gtt_statistic_test'; + attname | avg_width +---------+----------- + id | 4 +(1 row) + +--add column +alter table gtt_statistic_test add column text varchar(128); +\d gtt_statistic_test + Table "gtt_function.gtt_statistic_test" + Column | Type | Modifiers +--------+------------------------+----------- + id | integer | + text | character varying(128) | + +select attname,avg_width from pg_gtt_stats where tablename='gtt_statistic_test'; + attname | avg_width +---------+----------- + id | 4 + text | +(2 rows) + +insert into gtt_statistic_test values (generate_series(1,1000),'hello gtt'); +analyze gtt_statistic_test; +select attname,avg_width from pg_gtt_stats where tablename='gtt_statistic_test'; + attname | avg_width +---------+----------- + id | 4 + text | 10 +(2 rows) + +--modify column +alter table gtt_statistic_test modify id varchar(128); +\d gtt_statistic_test + Table "gtt_function.gtt_statistic_test" + Column | Type | Modifiers +--------+------------------------+----------- + id | character varying(128) | + text | character varying(128) | + +select attname,avg_width from pg_gtt_stats where tablename='gtt_statistic_test'; + attname | avg_width +---------+----------- + id | + text | 10 +(2 rows) + +--drop column +alter table gtt_statistic_test drop text; +\d gtt_statistic_test + Table "gtt_function.gtt_statistic_test" + Column | Type | Modifiers +--------+------------------------+----------- + id | character varying(128) | + +select attname,avg_width from pg_gtt_stats where tablename='gtt_statistic_test'; + attname | avg_width +---------+----------- + id | +(1 row) + CREATE global temp TABLE products ( product_no integer PRIMARY KEY, name text, @@ -382,7 +447,7 @@ create global temp table gtt_test11(c1 int) with(on_commit_delete_rows=''); ERROR: parameter "on_commit_delete_rows" requires a Boolean value reset search_path; drop schema gtt_function cascade; -NOTICE: drop cascades to 34 other objects +NOTICE: drop cascades to 35 other objects DETAIL: drop cascades to table gtt_function.gtt1 drop cascades to table gtt_function.gtt2 drop cascades to table gtt_function.gtt3 @@ -398,6 +463,7 @@ drop cascades to table gtt_function.gtt7 drop cascades to table gtt_function.gtt8 drop cascades to table gtt_function.gtt9 drop cascades to table gtt_function.gtt_test_new +drop cascades to table gtt_function.gtt_statistic_test drop cascades to table gtt_function.products drop cascades to table gtt_function.orders drop cascades to table gtt_function.mytable diff --git a/src/test/regress/sql/gtt_function.sql b/src/test/regress/sql/gtt_function.sql index abe6052dac..339143003f 100644 --- a/src/test/regress/sql/gtt_function.sql +++ b/src/test/regress/sql/gtt_function.sql @@ -178,6 +178,30 @@ select * from gtt_test_new; --ok ALTER TABLE gtt_test_new DROP address; +--gtt statistic test +create global temp table gtt_statistic_test(id int); +insert into gtt_statistic_test values (generate_series(1,1000)); +analyze gtt_statistic_test; +select attname,avg_width from pg_gtt_stats where tablename='gtt_statistic_test'; + +--add column +alter table gtt_statistic_test add column text varchar(128); +\d gtt_statistic_test +select attname,avg_width from pg_gtt_stats where tablename='gtt_statistic_test'; +insert into gtt_statistic_test values (generate_series(1,1000),'hello gtt'); +analyze gtt_statistic_test; +select attname,avg_width from pg_gtt_stats where tablename='gtt_statistic_test'; + +--modify column +alter table gtt_statistic_test modify id varchar(128); +\d gtt_statistic_test +select attname,avg_width from pg_gtt_stats where tablename='gtt_statistic_test'; + +--drop column +alter table gtt_statistic_test drop text; +\d gtt_statistic_test +select attname,avg_width from pg_gtt_stats where tablename='gtt_statistic_test'; + CREATE global temp TABLE products ( product_no integer PRIMARY KEY, name text, -- Gitee