Hello. Sometimes it's useful to log content of files used in COPY ... TO ... and COPY ... FROM ... queries. Unfortunately PostgreSQL doesn't allow to do it, even if log_statement='all'. Suggested patch fixes this.
Log example: ``` LOG: statement: create table test (k int, v text); LOG: statement: insert into test values (111, 'aaa'), (222, 'bbb'); LOG: statement: copy test to '/tmp/copy.txt'; LOG: statement: 111 aaa LOG: statement: 222 bbb LOG: statement: delete from test; LOG: statement: copy test from '/tmp/copy.txt'; LOG: statement: 111 aaa LOG: statement: 222 bbb ``` -- Best regards, Aleksander Alekseev
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 5947e72..82b3a18 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -331,6 +331,38 @@ static bool CopyGetInt16(CopyState cstate, int16 *val);
/*
+ * Logs file content during COPY ... FROM / COPY ... TO execution if
+ * log_statement = 'all'.
+ */
+static void
+CopyLogStatement(const char* str, bool flush)
+{
+ static StringInfo logString = NULL;
+
+ if(log_statement != LOGSTMT_ALL)
+ return;
+
+ if(logString == NULL)
+ {
+ MemoryContext oldctx = MemoryContextSwitchTo(TopMemoryContext);
+ logString = makeStringInfo();
+ MemoryContextSwitchTo(oldctx);
+ }
+
+ appendStringInfoString(logString, str);
+
+ if(flush)
+ {
+ ereport(LOG,
+ (errmsg("statement: %s", logString->data),
+ errhidestmt(true),
+ errhidecontext(true)));
+
+ resetStringInfo(logString);
+ }
+}
+
+/*
* Send copy start/stop messages for frontend copies. These have changed
* in past protocol redesigns.
*/
@@ -2045,14 +2077,20 @@ CopyOneRowTo(CopyState cstate, Oid tupleOid, Datum *values, bool *nulls)
if (!cstate->binary)
{
if (need_delim)
+ {
CopySendChar(cstate, cstate->delim[0]);
+ CopyLogStatement(cstate->delim, false);
+ }
need_delim = true;
}
if (isnull)
{
if (!cstate->binary)
+ {
CopySendString(cstate, cstate->null_print_client);
+ CopyLogStatement(cstate->null_print_client, false);
+ }
else
CopySendInt32(cstate, -1);
}
@@ -2062,6 +2100,9 @@ CopyOneRowTo(CopyState cstate, Oid tupleOid, Datum *values, bool *nulls)
{
string = OutputFunctionCall(&out_functions[attnum - 1],
value);
+
+ CopyLogStatement(string, false);
+
if (cstate->csv_mode)
CopyAttributeOutCSV(cstate, string,
cstate->force_quote_flags[attnum - 1],
@@ -2083,6 +2124,7 @@ CopyOneRowTo(CopyState cstate, Oid tupleOid, Datum *values, bool *nulls)
}
CopySendEndOfRow(cstate);
+ CopyLogStatement("", true);
MemoryContextSwitchTo(oldcontext);
}
@@ -2914,6 +2956,8 @@ NextCopyFromRawFields(CopyState cstate, char ***fields, int *nfields)
if (done && cstate->line_buf.len == 0)
return false;
+ CopyLogStatement(cstate->line_buf.data, true);
+
/* Parse the line into de-escaped field values */
if (cstate->csv_mode)
fldct = CopyReadAttributesCSV(cstate);
signature.asc
Description: PGP signature
