v1-0001-Adding-TRIM_SPACE-option-to-COPY.patch
application/octet-stream
Filename: v1-0001-Adding-TRIM_SPACE-option-to-COPY.patch
Type: application/octet-stream
Part: 0
From d2d530680a895235c6edaadf48ae67a08c64dfe5 Mon Sep 17 00:00:00 2001
From: TatsuyaKawata <kawatatatsuya0913@gmail.com>
Date: Tue, 25 Nov 2025 01:00:42 +0900
Subject: [PATCH v1] Adding TRIM_SPACE option to COPY
---
src/backend/commands/copy.c | 13 +++++++
src/backend/commands/copyfromparse.c | 56 ++++++++++++++++++++++++++--
src/include/commands/copy.h | 1 +
3 files changed, 67 insertions(+), 3 deletions(-)
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 28e878c3688..be1b3981ca0 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -557,6 +557,7 @@ ProcessCopyOptions(ParseState *pstate,
bool on_error_specified = false;
bool log_verbosity_specified = false;
bool reject_limit_specified = false;
+ bool trim_space_specified = false;
ListCell *option;
/* Support external use for option sanity checking */
@@ -730,6 +731,13 @@ ProcessCopyOptions(ParseState *pstate,
reject_limit_specified = true;
opts_out->reject_limit = defGetCopyRejectLimitOption(defel);
}
+ else if (strcmp(defel->defname, "trim_space") == 0)
+ {
+ if (trim_space_specified)
+ errorConflictingDefElem(defel, pstate);
+ trim_space_specified = true;
+ opts_out->trim_space = defGetBoolean(defel);
+ }
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
@@ -758,6 +766,11 @@ ProcessCopyOptions(ParseState *pstate,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cannot specify %s in BINARY mode", "DEFAULT")));
+ if (opts_out->binary && opts_out->trim_space)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("cannot specify %s in BINARY mode", "TRIM_SPACE")));
+
/* Set defaults for omitted options */
if (!opts_out->delim)
opts_out->delim = opts_out->csv_mode ? "," : "\t";
diff --git a/src/backend/commands/copyfromparse.c b/src/backend/commands/copyfromparse.c
index a09e7fbace3..9417c1f9e21 100644
--- a/src/backend/commands/copyfromparse.c
+++ b/src/backend/commands/copyfromparse.c
@@ -1798,6 +1798,30 @@ CopyReadAttributesText(CopyFromState cstate)
pg_verifymbstr(fld, output_ptr - fld, false);
}
+
+ /* Apply TRIM_SPACE if requested */
+ if (cstate->opts.trim_space)
+ {
+ char *fld = cstate->raw_fields[fieldno];
+ char *start = fld;
+ char *end = output_ptr;
+
+ /* Trim leading spaces */
+ while (start < end && *start == ' ')
+ start++;
+
+ /* Trim trailing spaces */
+ while (end > start && *(end - 1) == ' ')
+ end--;
+
+ /* Move trimmed string to the beginning if needed */
+ if (start > fld)
+ {
+ memmove(fld, start, end - start);
+ }
+
+ output_ptr = fld + (end - start);
+ }
}
/* Terminate attribute value in output area */
@@ -1965,9 +1989,6 @@ CopyReadAttributesCSV(CopyFromState cstate)
}
endfield:
- /* Terminate attribute value in output area */
- *output_ptr++ = '\0';
-
/* Check whether raw input matched null marker */
input_len = end_ptr - start_ptr;
if (!saw_quote && input_len == cstate->opts.null_print_len &&
@@ -1999,6 +2020,35 @@ endfield:
NameStr(att->attname))));
}
}
+ else
+ {
+ /* Apply TRIM_SPACE if requested */
+ if (cstate->opts.trim_space)
+ {
+ char *fld = cstate->raw_fields[fieldno];
+ char *start = fld;
+ char *end = output_ptr;
+
+ /* Trim leading spaces */
+ while (start < end && *start == ' ')
+ start++;
+
+ /* Trim trailing spaces */
+ while (end > start && *(end - 1) == ' ')
+ end--;
+
+ /* Move trimmed string to the beginning if needed */
+ if (start > fld)
+ {
+ memmove(fld, start, end - start);
+ }
+
+ output_ptr = fld + (end - start);
+ }
+ }
+
+ /* Terminate attribute value in output area */
+ *output_ptr++ = '\0';
fieldno++;
/* Done if we hit EOL instead of a delim */
diff --git a/src/include/commands/copy.h b/src/include/commands/copy.h
index 541176e1980..1769a193789 100644
--- a/src/include/commands/copy.h
+++ b/src/include/commands/copy.h
@@ -85,6 +85,7 @@ typedef struct CopyFormatOptions
CopyLogVerbosityChoice log_verbosity; /* verbosity of logged messages */
int64 reject_limit; /* maximum tolerable number of errors */
List *convert_select; /* list of column names (can be NIL) */
+ bool trim_space; /* trim leading/trailing spaces? */
} CopyFormatOptions;
/* These are private in commands/copy[from|to].c */
--
2.34.1