v16_fix_masahiko.patch.txt

text/plain

Filename: v16_fix_masahiko.patch.txt
Type: text/plain
Part: 0
Message: Re: speedup COPY TO for partitioned table.
diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index aba76eb0173..7d5067d90b5 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -119,8 +119,8 @@ static void CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot);
 static void CopyAttributeOutText(CopyToState cstate, const char *string);
 static void CopyAttributeOutCSV(CopyToState cstate, const char *string,
 								bool use_quote);
-static void CopyRelTo(CopyToState cstate, Relation rel, Relation root_rel,
-					  uint64 *processed);
+static void CopyRelationTo(CopyToState cstate, Relation rel, Relation root_rel,
+						   uint64 *processed);
 
 /* built-in format-specific routines */
 static void CopyToTextLikeStart(CopyToState cstate, TupleDesc tupDesc);
@@ -681,32 +681,30 @@ BeginCopyTo(ParseState *pstate,
 		else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
 		{
 			/*
-			 * Collect a list of partitions containing data, so that later
+			 * Collect OIDs of relation containing data, so that later
 			 * DoCopyTo can copy the data from them.
-			*/
-			children = find_all_inheritors(RelationGetRelid(rel),
-										   AccessShareLock,
-										   NULL);
+			 */
+			children = find_all_inheritors(RelationGetRelid(rel), AccessShareLock, NULL);
 
-			foreach_oid(childreloid, children)
+			foreach_oid(child, children)
 			{
-				char		 relkind = get_rel_relkind(childreloid);
+				char		relkind = get_rel_relkind(child);
 
 				if (relkind == RELKIND_FOREIGN_TABLE)
 				{
-					char	   *relation_name;
+					char	   *relation_name = get_rel_name(child);
 
-					relation_name = get_rel_name(childreloid);
 					ereport(ERROR,
-							errcode(ERRCODE_WRONG_OBJECT_TYPE),
-							errmsg("cannot copy from foreign table \"%s\"", relation_name),
-							errdetail("Partition \"%s\" is a foreign table in the partitioned table \"%s\"",
-									  relation_name, RelationGetRelationName(rel)),
-							errhint("Try the COPY (SELECT ...) TO variant."));
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							 errmsg("cannot copy from foreign table \"%s\"", relation_name),
+							 errdetail("Partition \"%s\" is a foreign table in partitioned table \"%s\"",
+									   relation_name, RelationGetRelationName(rel)),
+							 errhint("Try the COPY (SELECT ...) TO variant.")));
 				}
 
+				/* Exclude tables with no data */
 				if (RELKIND_HAS_PARTITIONS(relkind))
-					children = foreach_delete_current(children, childreloid);
+					children = foreach_delete_current(children, child);
 			}
 		}
 		else
@@ -1106,21 +1104,21 @@ DoCopyTo(CopyToState cstate)
 		/*
 		 * If COPY TO source table is a partitioned table, then open each
 		 * partition and process each individual partition.
-		*/
+		 */
 		if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
 		{
-			foreach_oid(scan_oid, cstate->partitions)
+			foreach_oid(child, cstate->partitions)
 			{
-				Relation		scan_rel;
+				Relation	scan_rel;
 
-				/* We already got the needed lock in BeginCopyTo */
-				scan_rel = table_open(scan_oid, NoLock);
-				CopyRelTo(cstate, scan_rel, cstate->rel, &processed);
+				/* We already got the lock in BeginCopyTo */
+				scan_rel = table_open(child, NoLock);
+				CopyRelationTo(cstate, scan_rel, cstate->rel, &processed);
 				table_close(scan_rel, NoLock);
 			}
 		}
 		else
-			CopyRelTo(cstate, cstate->rel, NULL, &processed);
+			CopyRelationTo(cstate, cstate->rel, NULL, &processed);
 	}
 	else
 	{
@@ -1140,22 +1138,19 @@ DoCopyTo(CopyToState cstate)
 }
 
 /*
- * Scan a single table (which may be a partition) and export its rows to the
- * COPY destination.
+ * Scans a single table and exports its rows to the COPY destination.
  *
- * rel: the table from which the actual data will be copied.
- * root_rel: if not NULL, it indicates that COPY TO command copy partitioned
- * table data to the destination, and "rel" is the partition of "root_rel".
- * processed: number of tuples processed.
+ * root_rel can be set to the root table of rel if rel is a partition
+ * table so that we can send tuples in root_rel's rowtype, which might
+ * differ from individual partitions.
 */
 static void
-CopyRelTo(CopyToState cstate, Relation rel, Relation root_rel,
-		  uint64 *processed)
+CopyRelationTo(CopyToState cstate, Relation rel, Relation root_rel, uint64 *processed)
 {
 	TupleTableSlot *slot;
 	TableScanDesc scandesc;
-	AttrMap    		*map	= NULL;
-	TupleTableSlot  *root_slot = NULL;
+	AttrMap    *map = NULL;
+	TupleTableSlot *root_slot = NULL;
 
 	scandesc = table_beginscan(rel, GetActiveSnapshot(), 0, NULL);
 	slot = table_slot_create(rel, NULL);
@@ -1164,7 +1159,7 @@ CopyRelTo(CopyToState cstate, Relation rel, Relation root_rel,
 	 * A partition's rowtype might differ from the root table's. If we are
 	 * exporting partition data here, we must convert it back to the root
 	 * table's rowtype.
-	*/
+	 */
 	if (root_rel != NULL)
 	{
 		root_slot = table_slot_create(root_rel, NULL);
@@ -1192,8 +1187,7 @@ CopyRelTo(CopyToState cstate, Relation rel, Relation root_rel,
 		CopyOneRowTo(cstate, copyslot);
 
 		/*
-		 * Increment the number of processed tuples, and report the
-		 * progress.
+		 * Increment the number of processed tuples, and report the progress.
 		 */
 		pgstat_progress_update_param(PROGRESS_COPY_TUPLES_PROCESSED,
 									 ++(*processed));