From 257a284447e64753277f7bc08b387e901bcab8bb Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <sawada.mshk@gmail.com>
Date: Tue, 19 Nov 2024 11:52:33 -0800
Subject: [PATCH v24 2/4] fixup: fixup: minor updates for COPY TO refactoring.

includes:

- reroder function definitions.
- clenaup comments.
---
 src/backend/commands/copyto.c  | 242 +++++++++++++++------------------
 src/include/commands/copyapi.h |  23 ++--
 2 files changed, 121 insertions(+), 144 deletions(-)

diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index 46f3507a8b..73b9ca4457 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -65,7 +65,7 @@ typedef enum CopyDest
  */
 typedef struct CopyToStateData
 {
-	/* format routine */
+	/* format-specific routines */
 	const CopyToRoutine *routine;
 
 	/* low-level state data */
@@ -118,6 +118,19 @@ static void CopyAttributeOutText(CopyToState cstate, const char *string);
 static void CopyAttributeOutCSV(CopyToState cstate, const char *string,
 								bool use_quote);
 
+/* built-in format-specific routines */
+static void CopyToTextLikeStart(CopyToState cstate, TupleDesc tupDesc);
+static void CopyToTextLikeOutFunc(CopyToState cstate, Oid atttypid, FmgrInfo *finfo);
+static void CopyToTextOneRow(CopyToState cstate, TupleTableSlot *slot);
+static void CopyToCSVOneRow(CopyToState cstate, TupleTableSlot *slot);
+static void CopyToTextLikeOneRow(CopyToState cstate, TupleTableSlot *slot,
+								 bool is_csv);
+static void CopyToTextLikeEnd(CopyToState cstate);
+static void CopyToBinaryStart(CopyToState cstate, TupleDesc tupDesc);
+static void CopyToBinaryOutFunc(CopyToState cstate, Oid atttypid, FmgrInfo *finfo);
+static void CopyToBinaryOneRow(CopyToState cstate, TupleTableSlot *slot);
+static void CopyToBinaryEnd(CopyToState cstate);
+
 /* Low-level communications functions */
 static void SendCopyBegin(CopyToState cstate);
 static void SendCopyEnd(CopyToState cstate);
@@ -125,49 +138,55 @@ static void CopySendData(CopyToState cstate, const void *databuf, int datasize);
 static void CopySendString(CopyToState cstate, const char *str);
 static void CopySendChar(CopyToState cstate, char c);
 static void CopySendEndOfRow(CopyToState cstate);
+static void CopySendTextLikeEndOfRow(CopyToState cstate);
 static void CopySendInt32(CopyToState cstate, int32 val);
 static void CopySendInt16(CopyToState cstate, int16 val);
 
 /*
- * CopyToRoutine implementations.
- */
-
-/*
- * CopyToTextLikeSendEndOfRow
+ * COPY TO routines for built-in formats.
  *
- * Apply line terminations for a line sent in text or CSV format depending
- * on the destination, then send the end of a row.
+ * CSV and text formats share the same TextLike routines except for the
+ * one-row callback.
  */
-static pg_attribute_always_inline void
-CopyToTextLikeSendEndOfRow(CopyToState cstate)
+
+/* TEXT format */
+static const CopyToRoutine CopyToRoutineText = {
+	.CopyToStart = CopyToTextLikeStart,
+	.CopyToOutFunc = CopyToTextLikeOutFunc,
+	.CopyToOneRow = CopyToTextOneRow,
+	.CopyToEnd = CopyToTextLikeEnd,
+};
+
+/* CSV format */
+static const CopyToRoutine CopyToRoutineCSV = {
+	.CopyToStart = CopyToTextLikeStart,
+	.CopyToOutFunc = CopyToTextLikeOutFunc,
+	.CopyToOneRow = CopyToCSVOneRow,
+	.CopyToEnd = CopyToTextLikeEnd,
+};
+
+/* BINARY format */
+static const CopyToRoutine CopyToRoutineBinary = {
+	.CopyToStart = CopyToBinaryStart,
+	.CopyToOutFunc = CopyToBinaryOutFunc,
+	.CopyToOneRow = CopyToBinaryOneRow,
+	.CopyToEnd = CopyToBinaryEnd,
+};
+
+/* Return COPY TO routines for the given option */
+static const CopyToRoutine *
+CopyToGetRoutine(CopyFormatOptions opts)
 {
-	switch (cstate->copy_dest)
-	{
-		case COPY_FILE:
-			/* Default line termination depends on platform */
-#ifndef WIN32
-			CopySendChar(cstate, '\n');
-#else
-			CopySendString(cstate, "\r\n");
-#endif
-			break;
-		case COPY_FRONTEND:
-			/* The FE/BE protocol uses \n as newline for all platforms */
-			CopySendChar(cstate, '\n');
-			break;
-		default:
-			break;
-	}
+	if (opts.csv_mode)
+		return &CopyToRoutineCSV;
+	else if (opts.binary)
+		return &CopyToRoutineBinary;
 
-	/* Now take the actions related to the end of a row */
-	CopySendEndOfRow(cstate);
+	/* default is text */
+	return &CopyToRoutineText;
 }
 
-/*
- * CopyToTextLikeStart
- *
- * Start of COPY TO for text and CSV format.
- */
+/* Implementation of the start callback for text and CSV formats */
 static void
 CopyToTextLikeStart(CopyToState cstate, TupleDesc tupDesc)
 {
@@ -203,14 +222,13 @@ CopyToTextLikeStart(CopyToState cstate, TupleDesc tupDesc)
 				CopyAttributeOutText(cstate, colname);
 		}
 
-		CopyToTextLikeSendEndOfRow(cstate);
+		CopySendTextLikeEndOfRow(cstate);
 	}
 }
 
 /*
- * CopyToTextLikeOutFunc
- *
- * Assign output function data for a relation's attribute in text/CSV format.
+ * Implementation of the outfunc callback for text and CSV formats. Assign
+ * the output function data to the given *finfo.
  */
 static void
 CopyToTextLikeOutFunc(CopyToState cstate, Oid atttypid, FmgrInfo *finfo)
@@ -223,13 +241,24 @@ CopyToTextLikeOutFunc(CopyToState cstate, Oid atttypid, FmgrInfo *finfo)
 	fmgr_info(func_oid, finfo);
 }
 
+/* Implementation of the per-row callback for text format */
+static void
+CopyToTextOneRow(CopyToState cstate, TupleTableSlot *slot)
+{
+	CopyToTextLikeOneRow(cstate, slot, false);
+}
+
+/* Implementation of the per-row callback for CSV format */
+static void
+CopyToCSVOneRow(CopyToState cstate, TupleTableSlot *slot)
+{
+	CopyToTextLikeOneRow(cstate, slot, true);
+}
 
 /*
- * CopyToTextLikeOneRow
- *
- * Process one row for text/CSV format.
- *
  * Workhorse for CopyToTextOneRow() and CopyToCSVOneRow().
+ *
+ * We use pg_attribute_always_inline to reduce function call overheads.
  */
 static pg_attribute_always_inline void
 CopyToTextLikeOneRow(CopyToState cstate,
@@ -271,36 +300,10 @@ CopyToTextLikeOneRow(CopyToState cstate,
 		}
 	}
 
-	CopyToTextLikeSendEndOfRow(cstate);
+	CopySendTextLikeEndOfRow(cstate);
 }
 
-/*
- * CopyToTextOneRow
- *
- * Per-row callback for COPY TO with text format.
- */
-static void
-CopyToTextOneRow(CopyToState cstate, TupleTableSlot *slot)
-{
-	CopyToTextLikeOneRow(cstate, slot, false);
-}
-
-/*
- * CopyToTextOneRow
- *
- * Per-row callback for COPY TO with CSV format.
- */
-static void
-CopyToCSVOneRow(CopyToState cstate, TupleTableSlot *slot)
-{
-	CopyToTextLikeOneRow(cstate, slot, true);
-}
-
-/*
- * CopyToTextLikeEnd
- *
- * End of COPY TO for text/CSV format.
- */
+/* Implementation of the end callback for text and CSV formats */
 static void
 CopyToTextLikeEnd(CopyToState cstate)
 {
@@ -308,18 +311,12 @@ CopyToTextLikeEnd(CopyToState cstate)
 }
 
 /*
- * CopyToRoutine implementation for "binary".
- */
-
-/*
- * CopyToBinaryStart
- *
- * Start of COPY TO for binary format.
+ * Implementation of the start callback for binary format. Send a header
+ * for a binary copy.
  */
 static void
 CopyToBinaryStart(CopyToState cstate, TupleDesc tupDesc)
 {
-	/* Generate header for a binary copy */
 	int32		tmp;
 
 	/* Signature */
@@ -333,9 +330,8 @@ CopyToBinaryStart(CopyToState cstate, TupleDesc tupDesc)
 }
 
 /*
- * CopyToBinaryOutFunc
- *
- * Assign output function data for a relation's attribute in binary format.
+ * Implementation of the outfunc callback for binary format. Assign
+ * the binary output function to the given *finfo.
  */
 static void
 CopyToBinaryOutFunc(CopyToState cstate, Oid atttypid, FmgrInfo *finfo)
@@ -348,11 +344,7 @@ CopyToBinaryOutFunc(CopyToState cstate, Oid atttypid, FmgrInfo *finfo)
 	fmgr_info(func_oid, finfo);
 }
 
-/*
- * CopyToBinaryOneRow
- *
- * Process one row for binary format.
- */
+/* Implementation of the per-row callback for binary format */
 static void
 CopyToBinaryOneRow(CopyToState cstate, TupleTableSlot *slot)
 {
@@ -385,11 +377,7 @@ CopyToBinaryOneRow(CopyToState cstate, TupleTableSlot *slot)
 	CopySendEndOfRow(cstate);
 }
 
-/*
- * CopyToBinaryEnd
- *
- * End of COPY TO for binary format.
- */
+/* Implementation of the end callback for binary format */
 static void
 CopyToBinaryEnd(CopyToState cstate)
 {
@@ -399,47 +387,6 @@ CopyToBinaryEnd(CopyToState cstate)
 	CopySendEndOfRow(cstate);
 }
 
-/*
- * CSV and text share the same implementation, at the exception of the
- * output representation and per-row callbacks.
- */
-static const CopyToRoutine CopyToRoutineText = {
-	.CopyToStart = CopyToTextLikeStart,
-	.CopyToOutFunc = CopyToTextLikeOutFunc,
-	.CopyToOneRow = CopyToTextOneRow,
-	.CopyToEnd = CopyToTextLikeEnd,
-};
-
-static const CopyToRoutine CopyToRoutineCSV = {
-	.CopyToStart = CopyToTextLikeStart,
-	.CopyToOutFunc = CopyToTextLikeOutFunc,
-	.CopyToOneRow = CopyToCSVOneRow,
-	.CopyToEnd = CopyToTextLikeEnd,
-};
-
-static const CopyToRoutine CopyToRoutineBinary = {
-	.CopyToStart = CopyToBinaryStart,
-	.CopyToOutFunc = CopyToBinaryOutFunc,
-	.CopyToOneRow = CopyToBinaryOneRow,
-	.CopyToEnd = CopyToBinaryEnd,
-};
-
-/*
- * Define the COPY TO routines to use for a format.  This should be called
- * after options are parsed.
- */
-static const CopyToRoutine *
-CopyToGetRoutine(CopyFormatOptions opts)
-{
-	if (opts.csv_mode)
-		return &CopyToRoutineCSV;
-	else if (opts.binary)
-		return &CopyToRoutineBinary;
-
-	/* default is text */
-	return &CopyToRoutineText;
-}
-
 /*
  * Send copy start/stop messages for frontend copies.  These have changed
  * in past protocol redesigns.
@@ -555,6 +502,35 @@ CopySendEndOfRow(CopyToState cstate)
 	resetStringInfo(fe_msgbuf);
 }
 
+/*
+ * Wrapper function of CopySendEndOfRow for text and CSV formats. Sends the
+ * the line termination and do common appropriate things for the end of row.
+ */
+static inline void
+CopySendTextLikeEndOfRow(CopyToState cstate)
+{
+	switch (cstate->copy_dest)
+	{
+		case COPY_FILE:
+			/* Default line termination depends on platform */
+#ifndef WIN32
+			CopySendChar(cstate, '\n');
+#else
+			CopySendString(cstate, "\r\n");
+#endif
+			break;
+		case COPY_FRONTEND:
+			/* The FE/BE protocol uses \n as newline for all platforms */
+			CopySendChar(cstate, '\n');
+			break;
+		default:
+			break;
+	}
+
+	/* Now take the actions related to the end of a row */
+	CopySendEndOfRow(cstate);
+}
+
 /*
  * These functions do apply some data conversion
  */
@@ -1143,7 +1119,7 @@ DoCopyTo(CopyToState cstate)
 /*
  * Emit one row during DoCopyTo().
  */
-static void
+static inline void
 CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot)
 {
 	MemoryContext oldcontext;
diff --git a/src/include/commands/copyapi.h b/src/include/commands/copyapi.h
index 5ce24f195d..99981b1579 100644
--- a/src/include/commands/copyapi.h
+++ b/src/include/commands/copyapi.h
@@ -27,31 +27,32 @@ typedef struct CopyToStateData *CopyToState;
 typedef struct CopyToRoutine
 {
 	/*
-	 * Called when COPY TO is started to set up the output functions
-	 * associated with the relation's attributes reading from.  `finfo` can be
-	 * optionally filled to provide the catalog information of the output
-	 * function.  `atttypid` is the OID of data type used by the relation's
-	 * attribute.
+	 * Set output function information. This callback is called once at the
+	 * beginning of COPY TO.
+	 *
+	 * 'finfo' can be optionally filled to provide the catalog information of
+	 * the output function.
+	 *
+	 * 'atttypid' is the OID of data type used by the relation's attribute.
 	 */
 	void		(*CopyToOutFunc) (CopyToState cstate, Oid atttypid,
 								  FmgrInfo *finfo);
 
 	/*
-	 * Called when COPY TO is started.
+	 * Start a COPY TO. This callback is called once at the beginning of COPY
+	 * FROM.
 	 *
-	 * `tupDesc` is the tuple descriptor of the relation from where the data
+	 * 'tupDesc' is the tuple descriptor of the relation from where the data
 	 * is read.
 	 */
 	void		(*CopyToStart) (CopyToState cstate, TupleDesc tupDesc);
 
 	/*
-	 * Copy one row for COPY TO.
-	 *
-	 * `slot` is the tuple slot where the data is emitted.
+	 * Write one row to the 'slot'.
 	 */
 	void		(*CopyToOneRow) (CopyToState cstate, TupleTableSlot *slot);
 
-	/* Called when COPY TO has ended */
+	/* End a COPY TO. This callback is called once at the end of COPY FROM */
 	void		(*CopyToEnd) (CopyToState cstate);
 } CopyToRoutine;
 
-- 
2.43.5

