From 63d4a62043bd1d2af381c632553f85c89de4f36f Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Sat, 1 Jan 2022 16:47:14 -0600
Subject: [PATCH 04/11] f!0003-gtt-v64-implementation.patch

---
 src/backend/catalog/heap.c          |  8 ++++----
 src/backend/catalog/index.c         | 24 +++++++++++-----------
 src/backend/catalog/storage_gtt.c   | 32 ++++++++++++++---------------
 src/backend/commands/analyze.c      |  4 ++--
 src/backend/commands/cluster.c      |  6 +++---
 src/backend/commands/sequence.c     |  6 +++---
 src/backend/commands/tablecmds.c    | 10 ++++-----
 src/backend/commands/vacuum.c       |  2 +-
 src/backend/commands/view.c         |  2 +-
 src/backend/parser/analyze.c        |  2 +-
 src/backend/parser/parse_utilcmd.c  |  2 +-
 src/backend/postmaster/autovacuum.c |  4 ++--
 src/backend/storage/ipc/procarray.c |  5 ++++-
 src/backend/utils/adt/dbsize.c      |  2 +-
 src/bin/pg_dump/pg_dump.c           |  2 +-
 src/include/catalog/pg_class.h      |  2 +-
 16 files changed, 58 insertions(+), 55 deletions(-)

diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 8e5b56f602..d24afa45c1 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -2023,15 +2023,15 @@ heap_drop_with_catalog(Oid relid)
 		update_default_partition_oid(parentOid, InvalidOid);
 
 	/*
-	 * Only when other sessions are not using this Global temporary table,
-	 * is it allowed to DROP it.
+	 * It is not allowed to DROP a Global temporary table when other
+	 * sessions are using it
 	 */
 	if (RELATION_IS_GLOBAL_TEMP(rel))
 	{
 		if (is_other_backend_use_gtt(RelationGetRelid(rel)))
 			ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("cannot drop global temporary table %s when other backend attached it.",
+				 errmsg("cannot drop global temporary table %s being accessed by another backend",
 						RelationGetRelationName(rel))));
 	}
 
@@ -3466,7 +3466,7 @@ heap_truncate_one_rel(Relation rel)
 
 	/*
 	 * After the data is cleaned up on the GTT, the transaction information
-	 * for the data(stored in local hash table) is also need reset.
+	 * for the data(stored in local hash table) also needs to be reset.
 	 */
 	if (RELATION_IS_GLOBAL_TEMP(rel))
 		up_gtt_relstats(RelationGetRelid(rel), 0, 0, 0, RecentXmin, GetOldestMultiXactId());
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index be08ba376a..e2483426d2 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -741,11 +741,11 @@ index_create(Relation heapRelation,
 	/* For global temporary table only */
 	if (RELATION_IS_GLOBAL_TEMP(heapRelation))
 	{
-		/* No support create index on global temporary table with concurrent mode */
+		/* No support for creating index on global temporary table with concurrent mode */
 		Assert(!concurrent);
 
 		/*
-		 * For the case that some backend is applied relcache message to create
+		 * For the case that some backend is applied relcache message to create XXX
 		 * an index on a global temporary table, if this table in the current
 		 * backend are not initialized, the creation of index storage on the
 		 * table are also skipped.
@@ -2201,18 +2201,18 @@ index_drop(Oid indexId, bool concurrent, bool concurrent_lock_mode)
 	CheckTableNotInUse(userIndexRelation, "DROP INDEX");
 
 	/*
-	 * Allow to drop index on global temporary table when only current
-	 * backend use it.
+	 * Disallow dropping index on global temporary table if another
+	 * backend is using it.
 	 */
 	if (RELATION_IS_GLOBAL_TEMP(userHeapRelation) &&
 		is_other_backend_use_gtt(RelationGetRelid(userHeapRelation)))
 	{
-		ereport(ERROR,
+		ereport(ERROR, // XXX
 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 			 errmsg("cannot drop index %s on global temporary table %s",
 					RelationGetRelationName(userIndexRelation), RelationGetRelationName(userHeapRelation)),
-					errdetail("Because the index is created on the global temporary table and other backend attached it."),
-					errhint("Please try detach all sessions using this temporary table and try again.")));
+					errdetail("The index is created on the global temporary table and other backend attached it."),
+					errhint("Detach other sessions using this temporary table and try again.")));
 	}
 
 	/*
@@ -2926,12 +2926,12 @@ index_update_stats(Relation rel,
 		/* For global temporary table */
 		if (is_gtt)
 		{
-			/* Update GTT'statistics into local relcache */
+			/* Update GTT's statistics into local relcache */
 			rel->rd_rel->relpages = (int32) relpages;
 			rel->rd_rel->reltuples = (float4) reltuples;
 			rel->rd_rel->relallvisible = (int32) relallvisible;
 
-			/* Update GTT'statistics into local hashtable */
+			/* Update GTT's statistics into local hashtable */
 			up_gtt_relstats(RelationGetRelid(rel), relpages, reltuples, relallvisible,
 							InvalidTransactionId, InvalidMultiXactId);
 		}
@@ -3066,7 +3066,7 @@ index_build(Relation heapRelation,
 		pgstat_progress_update_multi_param(6, progress_index, progress_vals);
 	}
 
-	/* For build index on global temporary table */
+	/* If building index on global temporary table */
 	if (RELATION_IS_GLOBAL_TEMP(indexRelation))
 	{
 		/*
@@ -3075,7 +3075,7 @@ index_build(Relation heapRelation,
 		 */
 		if (!gtt_storage_attached(RelationGetRelid(indexRelation)))
 		{
-			/* Before create init storage, fix the local Relcache first */
+			/* Before creating init storage, fix the local Relcache first */
 			force_enable_gtt_index(indexRelation);
 
 			Assert(gtt_storage_attached(RelationGetRelid(heapRelation)));
@@ -3651,7 +3651,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
 		if (OidIsValid(params->tablespaceOid))
 			ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("The tablespace of global temporary table can not be changed")));
+				 errmsg("The tablespace of global temporary table cannot be changed")));
 
 		if (!gtt_storage_attached(indexId))
 		{
diff --git a/src/backend/catalog/storage_gtt.c b/src/backend/catalog/storage_gtt.c
index d50e1fa9af..1660163e99 100644
--- a/src/backend/catalog/storage_gtt.c
+++ b/src/backend/catalog/storage_gtt.c
@@ -1,12 +1,12 @@
 /*-------------------------------------------------------------------------
  *
  * storage_gtt.c
- *	  The body implementation of Global Temparary table.
+ *	  The body implementation of Global Temporary table.
  *
  * IDENTIFICATION
  *	  src/backend/catalog/storage_gtt.c
  *
- *	  See src/backend/catalog/GTT_README for Global temparary table's
+ *	  See src/backend/catalog/GTT_README for Global temporary table's
  *	  requirements and design.
  *
  *-------------------------------------------------------------------------
@@ -197,7 +197,7 @@ active_gtt_shared_hash_size(void)
 }
 
 /*
- * Initialization shared hash table for GTT.
+ * Initialization of shared hash table for GTT.
  */
 void
 active_gtt_shared_hash_init(void)
@@ -277,7 +277,7 @@ gtt_storage_checkin(Oid relid)
 
 /*
  * Remove the GTT relid record from the shared hash table which means that current backend is
- * not use this GTT.
+ * not using this GTT.
  */
 static void
 gtt_storage_checkout(Oid relid, bool isCommit)
@@ -298,7 +298,7 @@ gtt_storage_checkout(Oid relid, bool isCommit)
 	{
 		LWLockRelease(&gtt_shared_ctl->lock);
 		if (isCommit)
-			elog(WARNING, "relid %u not exist in gtt shared hash when drop local storage", relid);
+			elog(WARNING, "relid %u doesn't exist in gtt shared hash when dropping local storage", relid);
 
 		return;
 	}
@@ -319,9 +319,9 @@ gtt_storage_checkout(Oid relid, bool isCommit)
 
 /*
  * Gets usage information for a GTT from shared hash table.
- * The information is in the form of bitmap.
- * Quickly copy the entire bitmap from shared memory and return it.
- * that to avoid holding locks for a long time.
+ * The information is in the form of a bitmap.
+ * Quickly copy the entire bitmap from shared memory and return it,
+ * to avoid holding locks for a long time.
  */
 static Bitmapset *
 copy_active_gtt_bitmap(Oid relid)
@@ -417,18 +417,18 @@ remember_gtt_storage_info(RelFileNode rnode, Relation rel)
 	if (max_active_gtt <= 0)
 		ereport(ERROR,
 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-			 errmsg("Global temporary table feature is disable"),
+			 errmsg("Global temporary table feature is disabled"),
 			 errhint("You might need to increase max_active_global_temporary_table to enable this feature.")));
 
 	if (RecoveryInProgress())
-		elog(ERROR, "readonly mode not support access global temporary table");
+		elog(ERROR, "recovery mode does not support accessing global temporary table");
 
 	if (rel->rd_rel->relkind == RELKIND_INDEX &&
 		rel->rd_index &&
 		(!rel->rd_index->indisvalid ||
 		 !rel->rd_index->indisready ||
 		 !rel->rd_index->indislive))
-		 elog(ERROR, "invalid gtt index %s not allow to create storage", RelationGetRelationName(rel));
+		 elog(ERROR, "invalid gtt index %s not allowed to create storage", RelationGetRelationName(rel));
 
 	/* First time through: initialize the hash table */
 	if (gtt_storage_local_hash == NULL)
@@ -757,7 +757,7 @@ up_gtt_relstats(Oid relid,
 
 /*
  * Search GTT relstats(relpage/reltuple/relallvisible)
- * from local has.
+ * from local hash.
  */
 bool
 get_gtt_relstats(Oid relid, BlockNumber *relpages, double *reltuples,
@@ -852,7 +852,7 @@ up_gtt_att_statistic(Oid reloid, int attnum, bool inh, int natts,
 	}
 	MemoryContextSwitchTo(oldcontext);
 
-	if (!found)
+	if (!found) // XXX: should be an ereport with a hint ?
 		elog(WARNING, "analyze can not update relid %u column %d statistics after add or drop column, try truncate table first", reloid, attnum);
 
 	return;
@@ -960,7 +960,7 @@ remove_gtt_relfrozenxid_from_ordered_list(Oid relfrozenxid)
 
 /*
  * Update of backend Level oldest relfrozenxid to MyProc.
- * This makes each backend's oldest RelFrozenxID globally visible.
+ * This makes each backend's oldest RelFrozenXID globally visible.
  */
 static void
 set_gtt_session_relfrozenxid(void)
@@ -1282,7 +1282,7 @@ pg_list_gtt_relfrozenxids(PG_FUNCTION_ARGS)
 }
 
 /*
- * In order to build the GTT index, force enable GTT'index.
+ * In order to build the GTT index, force enable GTT index.
  */
 void
 force_enable_gtt_index(Relation index)
@@ -1331,7 +1331,7 @@ gtt_fix_index_backend_state(Relation index)
 
 /*
  * During the SQL initialization of the executor (InitPlan)
- * Initialize storage of GTT GTT'indexes and build empty index.
+ * Initialize storage of GTT's indexes and build empty index.
  */
 void
 init_gtt_storage(CmdType operation, Relation relation)
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 72218b2c66..6dee51784f 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -188,8 +188,8 @@ analyze_rel(Oid relid, RangeVar *relation,
 	}
 
 	/*
-	 * Skip the global temporary table that did not initialize the storage
-	 * in this backend.
+	 * Skip global temporary tables for which storage was not initialized by
+	 * this backend.
 	 */
 	if (RELATION_IS_GLOBAL_TEMP(onerel) &&
 		!gtt_storage_attached(RelationGetRelid(onerel)))
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 535f537aae..ff6ae583f5 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -392,15 +392,15 @@ cluster_rel(Oid tableOid, Oid indexOid, ClusterParams *params)
 	}
 
 	/*
-	 * Skip the global temporary table that did not initialize the storage
-	 * in this backend.
+	 * Skip global temporary tables for which storage was not initialized by
+	 * this backend.
 	 */
 	if (RELATION_IS_GLOBAL_TEMP(OldHeap))
 	{
 		if (gtt_storage_attached(RelationGetRelid(OldHeap)))
 			ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("not support cluster global temporary table")));
+				 errmsg("clustering is not supported on a global temporary table")));
 
 		relation_close(OldHeap, AccessExclusiveLock);
 		pgstat_progress_end_command();
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index af12dd2cdc..4d5aedf2c3 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -461,7 +461,7 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
 		if (is_other_backend_use_gtt(RelationGetRelid(seqrel)))
 			ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("cannot alter global temporary sequence %s when other backend attached it.",
+				 errmsg("cannot alter global temporary sequence %s being accessed by another backend",
 						RelationGetRelationName(seqrel))));
 	}
 
@@ -1194,7 +1194,7 @@ init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
 	*p_elm = elm;
 	*p_rel = seqrel;
 
-	/* Initializes the storage for sequence which the global temporary table belongs. */
+	/* Initializes the storage for sequence which belongs to a global temporary table. */
 	if (RELATION_IS_GLOBAL_TEMP(seqrel) &&
 		!gtt_storage_attached(RelationGetRelid(seqrel)))
 	{
@@ -1999,7 +1999,7 @@ get_seqence_start_value(Oid seqid)
 }
 
 /*
- * Initialize sequence which global temporary table belongs.
+ * Initialize sequence which belongs to a global temporary table.
  */
 void
 gtt_init_seq(Relation rel)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 7aa3beba2c..e4b67f8731 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -2018,8 +2018,8 @@ ExecuteTruncateGuts(List *explicit_rels,
 		}
 
 		/*
-		 * Skip the global temporary table that is not initialized for storage
-		 * in current backend.
+		 * Skip global temporary tables for which the current backend has not
+		 * initialized storage.
 		 */
 		if (RELATION_IS_GLOBAL_TEMP(rel))
 		{
@@ -3365,7 +3365,7 @@ CheckRelationTableSpaceMove(Relation rel, Oid newTableSpaceId)
 	if (RELATION_IS_GLOBAL_TEMP(rel))
 		ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("The tablespace of global temporary table can not be changed")));
+				 errmsg("The tablespace of global temporary table cannot be changed")));
 
 	return true;
 }
@@ -4136,13 +4136,13 @@ AlterTable(AlterTableStmt *stmt, LOCKMODE lockmode,
 	/* Caller is required to provide an adequate lock. */
 	rel = relation_open(context->relid, NoLock);
 
-	/* We allow to alter global temporary table only current backend use it */
+	/* We disallow altering a global temporary table if another backend is using it */
 	if (RELATION_IS_GLOBAL_TEMP(rel))
 	{
 		if (is_other_backend_use_gtt(RelationGetRelid(rel)))
 			ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("cannot alter global temporary table %s when other backend attached it.",
+				 errmsg("cannot alter global temporary table %s being accessed by another backend",
 						RelationGetRelationName(rel))));
 	}
 
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 47c734aa1c..3a48892feb 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -2140,7 +2140,7 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
 	}
 
 	/*
-	 * Skip those global temporary table that are not initialized in
+	 * Skip global temporary tables that are not initialized in the
 	 * current backend.
 	 */
 	if (RELATION_IS_GLOBAL_TEMP(rel) &&
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index cd2bd57e38..79e4b0c9c7 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -543,7 +543,7 @@ DefineView(ViewStmt *stmt, const char *queryString,
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("views cannot be unlogged because they do not have storage")));
 
-	/* Global temporary table are not sensible. */
+	/* Global temporary views are not sensible. */
 	if (stmt->view->relpersistence == RELPERSISTENCE_GLOBAL_TEMP)
 		ereport(ERROR,
 				(errcode(ERRCODE_SYNTAX_ERROR),
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 75a0940b25..4b96429f30 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -2912,7 +2912,7 @@ transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
 		if (is_query_using_gtt(query))
 			ereport(ERROR,
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("materialized views must not use global temporary tables or views")));
+					 errmsg("materialized views must not use global temporary tables")));
 
 		/*
 		 * A materialized view would either need to save parameters for use in
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 45241b8b0f..c9bef46339 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -449,7 +449,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
 
 	/*
 	 * If a sequence is bound to a global temporary table, then the sequence
-	 * must been "global temporary"
+	 * must be "global temporary"
 	 */
 	if (cxt->relation->relpersistence == RELPERSISTENCE_GLOBAL_TEMP)
 		seqstmt->sequence->relpersistence = cxt->relation->relpersistence;
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 5601f15d18..fa8c391d40 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2119,8 +2119,8 @@ do_autovacuum(void)
 		else if (classForm->relpersistence == RELPERSISTENCE_GLOBAL_TEMP)
 		{
 			/*
-			 * Aotuvacuum cannot vacuum the private data stored in each backend
-			 * that belongs to global temporary table, so skip them.
+			 * Autovacuum cannot vacuum the private data stored in each backend
+			 * that belongs to global temporary tables, so skip them.
 			 */
 			continue;
 		}
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index e9cea9b423..0b207dca16 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -5180,6 +5180,9 @@ KnownAssignedXidsReset(void)
 /*
  * search all active backend to get oldest frozenxid
  * for global temporary table.
+ * Return the oldest frozenxid, or InvalidTransactionId if none.
+ * If pids!=NULL, it's populated with qualifying backend pids.
+ * If xids!=NULL, it's populated with qualifying backend frozenxids.
  */
 int
 list_all_backend_gtt_frozenxids(int max_size, int *pids, uint32 *xids, int *n)
@@ -5216,7 +5219,7 @@ list_all_backend_gtt_frozenxids(int max_size, int *pids, uint32 *xids, int *n)
 	if (max_size > 0 && max_size < arrayP->numProcs)
 	{
 		LWLockRelease(ProcArrayLock);
-		elog(ERROR, "list_all_gtt_frozenxids require more array");
+		elog(ERROR, "list_all_gtt_frozenxids requires a longer array");
 	}
 
 	for (index = 0; index < arrayP->numProcs; index++)
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index 9a6e7cee24..b86bc4fc69 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -984,7 +984,7 @@ pg_relation_filepath(PG_FUNCTION_ARGS)
 			break;
 		case RELPERSISTENCE_GLOBAL_TEMP:
 			/*
-			 * For global temporary table ,each backend has its own storage,
+			 * For global temporary table, each backend has its own storage,
 			 * also only sees its own storage. Use Backendid to identify them.
 			 */
 			backend = BackendIdForTempRelations();
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 3100ddc704..caab5dc36a 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -15431,7 +15431,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
 
 		/*
 		 * Transaction information for the global temporary table is not stored
-		 * in the pg_class.
+		 * in pg_class.
 		 */
 		if (tbinfo->relpersistence == RELPERSISTENCE_GLOBAL_TEMP)
 		{
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index e23cb49c01..658e9be8de 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -169,10 +169,10 @@ DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, ClassTblspcRelfilenodeInd
 #define		  RELKIND_PARTITIONED_TABLE 'p' /* partitioned table */
 #define		  RELKIND_PARTITIONED_INDEX 'I' /* partitioned index */
 
+#define		  RELPERSISTENCE_GLOBAL_TEMP	'g' /* global temporary table */
 #define		  RELPERSISTENCE_PERMANENT	'p' /* regular table */
 #define		  RELPERSISTENCE_UNLOGGED	'u' /* unlogged permanent table */
 #define		  RELPERSISTENCE_TEMP		't' /* temporary table */
-#define		  RELPERSISTENCE_GLOBAL_TEMP	'g' /* global temporary table */
 
 /* default selection for replica identity (primary key or nothing) */
 #define		  REPLICA_IDENTITY_DEFAULT	'd'
-- 
2.17.1

