From bf31258d590bbac6bf243a2eafcd71272f79ccf7 Mon Sep 17 00:00:00 2001
From: Matthias van de Meent <boekewurm+postgres@gmail.com>
Date: Sat, 21 Jan 2023 01:46:52 +0100
Subject: [PATCH v1] Only report progress if we're actually in a (parsed) COPY
 command

We assume that only exclusive COPY commands (including table sync
worker) provide a pstate to BeginCopyFrom.

This solves bogus progress reporting stats in file_fdw, which uses
the copy infrastructure for implementing a foreign data wrapper, and
may thus have more than one copy in progress at the same time.
---
 src/backend/commands/copyfrom.c          | 35 ++++++++++++++++--------
 src/include/commands/copyfrom_internal.h |  1 +
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c
index af52faca6d..c785ac49bc 100644
--- a/src/backend/commands/copyfrom.c
+++ b/src/backend/commands/copyfrom.c
@@ -382,8 +382,9 @@ CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo,
 
 			/* Update the row counter and progress of the COPY command */
 			*processed += inserted;
-			pgstat_progress_update_param(PROGRESS_COPY_TUPLES_PROCESSED,
-										 *processed);
+			if (cstate->report_progress)
+				pgstat_progress_update_param(PROGRESS_COPY_TUPLES_PROCESSED,
+											 *processed);
 		}
 
 		for (i = 0; i < nused; i++)
@@ -461,8 +462,9 @@ CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo,
 
 		/* Update the row counter and progress of the COPY command */
 		*processed += nused;
-		pgstat_progress_update_param(PROGRESS_COPY_TUPLES_PROCESSED,
-									 *processed);
+		if (cstate->report_progress)
+			pgstat_progress_update_param(PROGRESS_COPY_TUPLES_PROCESSED,
+										 *processed);
 
 		/* reset cur_lineno and line_buf_valid to what they were */
 		cstate->line_buf_valid = line_buf_valid;
@@ -1016,8 +1018,10 @@ CopyFrom(CopyFromState cstate)
 				 * Report that this tuple was filtered out by the WHERE
 				 * clause.
 				 */
-				pgstat_progress_update_param(PROGRESS_COPY_TUPLES_EXCLUDED,
-											 ++excluded);
+				++excluded;
+				if (cstate->report_progress)
+					pgstat_progress_update_param(PROGRESS_COPY_TUPLES_EXCLUDED,
+												 excluded);
 				continue;
 			}
 		}
@@ -1271,8 +1275,10 @@ CopyFrom(CopyFromState cstate)
 			 * for counting tuples inserted by an INSERT command.  Update
 			 * progress of the COPY command as well.
 			 */
-			pgstat_progress_update_param(PROGRESS_COPY_TUPLES_PROCESSED,
-										 ++processed);
+			++processed;
+			if (cstate->report_progress)
+				pgstat_progress_update_param(PROGRESS_COPY_TUPLES_PROCESSED,
+											 processed);
 		}
 	}
 
@@ -1384,6 +1390,8 @@ BeginCopyFrom(ParseState *pstate,
 	/* Extract options from the statement node tree */
 	ProcessCopyOptions(pstate, &cstate->opts, true /* is_from */ , options);
 
+	cstate->report_progress = pstate != NULL;
+
 	/* Process the target relation */
 	cstate->rel = rel;
 
@@ -1610,8 +1618,9 @@ BeginCopyFrom(ParseState *pstate,
 
 
 	/* initialize progress */
-	pgstat_progress_start_command(PROGRESS_COMMAND_COPY,
-								  cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
+	if (cstate->report_progress)
+		pgstat_progress_start_command(PROGRESS_COMMAND_COPY,
+									  cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid);
 	cstate->bytes_processed = 0;
 
 	/* We keep those variables in cstate. */
@@ -1687,7 +1696,8 @@ BeginCopyFrom(ParseState *pstate,
 		}
 	}
 
-	pgstat_progress_update_multi_param(3, progress_cols, progress_vals);
+	if (cstate->report_progress)
+		pgstat_progress_update_multi_param(3, progress_cols, progress_vals);
 
 	if (cstate->opts.binary)
 	{
@@ -1729,7 +1739,8 @@ EndCopyFrom(CopyFromState cstate)
 							cstate->filename)));
 	}
 
-	pgstat_progress_end_command();
+	if (cstate->report_progress)
+		pgstat_progress_end_command();
 
 	MemoryContextDelete(cstate->copycontext);
 	pfree(cstate);
diff --git a/src/include/commands/copyfrom_internal.h b/src/include/commands/copyfrom_internal.h
index 7b1c4327bd..4b8782d481 100644
--- a/src/include/commands/copyfrom_internal.h
+++ b/src/include/commands/copyfrom_internal.h
@@ -66,6 +66,7 @@ typedef struct CopyFromStateData
 	EolType		eol_type;		/* EOL type of input */
 	int			file_encoding;	/* file or remote side's character encoding */
 	bool		need_transcoding;	/* file encoding diff from server? */
+	bool		report_progress;	/* do we need to report progress? */
 	Oid			conversion_proc;	/* encoding conversion function */
 
 	/* parameters from the COPY command */
-- 
2.39.0

