v3-0003-Add-an-hook-for-custom-COPY-format-option-validat.patch
text/x-patch
Filename: v3-0003-Add-an-hook-for-custom-COPY-format-option-validat.patch
Type: text/x-patch
Part: 0
Patch
Format: format-patch
Series: patch v3-0003
Subject: Add an hook for custom COPY format option validation.
| File | + | − |
|---|---|---|
| src/backend/commands/copyapi.c | 3 | 1 |
| src/backend/commands/copy.c | 9 | 0 |
| src/include/commands/copyapi.h | 13 | 1 |
From 43c06a26a14c914f6bc3d72d01accd95e3b0f8e8 Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <sawada.mshk@gmail.com>
Date: Mon, 22 Jun 2026 09:23:09 -0700
Subject: [PATCH v3 3/4] Add an hook for custom COPY format option validation.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
---
src/backend/commands/copy.c | 9 +++++++++
src/backend/commands/copyapi.c | 4 +++-
src/include/commands/copyapi.h | 14 +++++++++++++-
3 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 0fda54905cd..dab523c68db 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -1119,6 +1119,15 @@ ProcessCopyOptions(ParseState *pstate,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("COPY format \"%s\" cannot be used with COPY TO",
opts_out->custom_format_ent->name)));
+
+ /*
+ * Let the format validate its fully-parsed options as a whole. This
+ * runs even when no format-specific options were given, so a format
+ * can reject incompatible core options or enforce cross-option
+ * constraints.
+ */
+ if (opts_out->custom_format_ent->validate_fn != NULL)
+ opts_out->custom_format_ent->validate_fn(opts_out, is_from);
}
}
diff --git a/src/backend/commands/copyapi.c b/src/backend/commands/copyapi.c
index f007d73e867..29fb98ff4c2 100644
--- a/src/backend/commands/copyapi.c
+++ b/src/backend/commands/copyapi.c
@@ -48,7 +48,8 @@ is_builtin_copy_format(const char *name)
*/
void
RegisterCopyCustomFormat(const char *name, const CopyToRoutine *to,
- const CopyFromRoutine *from, ProcessOneCopyOptionFn option_fn)
+ const CopyFromRoutine *from, ProcessOneCopyOptionFn option_fn,
+ ValidateCopyOptionsFn validate_fn)
{
Assert(name != NULL && name[0] != '\0');
@@ -94,6 +95,7 @@ RegisterCopyCustomFormat(const char *name, const CopyToRoutine *to,
CopyCustomFormatArray[CopyCustomFormatsAssigned].to_routine = to;
CopyCustomFormatArray[CopyCustomFormatsAssigned].from_routine = from;
CopyCustomFormatArray[CopyCustomFormatsAssigned].option_fn = option_fn;
+ CopyCustomFormatArray[CopyCustomFormatsAssigned].validate_fn = validate_fn;
CopyCustomFormatsAssigned++;
}
diff --git a/src/include/commands/copyapi.h b/src/include/commands/copyapi.h
index 1b323b23bba..f1924424df8 100644
--- a/src/include/commands/copyapi.h
+++ b/src/include/commands/copyapi.h
@@ -117,6 +117,15 @@ typedef struct CopyFromRoutine
typedef bool (*ProcessOneCopyOptionFn) (CopyFormatOptions *opts, bool is_from,
DefElem *option);
+/*
+ * Optional callback to validate a custom format's fully-parsed options as a
+ * whole. Invoked once from ProcessCopyOptions() after all options have been
+ * processed, so it can enforce cross-option constraints and reject
+ * incompatible core options. It runs even when no format-specific options were
+ * supplied. Reports problems with ereport().
+ */
+typedef void (*ValidateCopyOptionsFn) (CopyFormatOptions *opts, bool is_from);
+
/*
* Sturct to store the registered custom format information.
*/
@@ -126,11 +135,14 @@ typedef struct CopyCustomFormatEntry
const CopyToRoutine *to_routine;
const CopyFromRoutine *from_routine;
ProcessOneCopyOptionFn option_fn;
+ ValidateCopyOptionsFn validate_fn;
} CopyCustomFormatEntry;
extern void RegisterCopyCustomFormat(const char *name, const CopyToRoutine *to,
const CopyFromRoutine *from,
- ProcessOneCopyOptionFn option_fn);
+ ProcessOneCopyOptionFn option_fn,
+ ValidateCopyOptionsFn validate_fn);
+
extern const CopyCustomFormatEntry *GetCopyCustomFormatRoutines(const char *name);
#endif /* COPYAPI_H */
--
2.54.0