From 819a96d8cac5d41eae1dd2b32cdfd817199dd5ad Mon Sep 17 00:00:00 2001 From: Masahiko Sawada Date: Mon, 10 Nov 2025 15:05:05 -0800 Subject: [PATCH 5/6] Add Copy{To,From}ProcessOneOption callback. --- src/backend/commands/copyfrom.c | 15 +++++++++++---- src/backend/commands/copyto.c | 17 ++++++++++++----- src/include/commands/copyapi.h | 18 +++++++++++++++++- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c index 6ca5466f244..c23c4b1188a 100644 --- a/src/backend/commands/copyfrom.c +++ b/src/backend/commands/copyfrom.c @@ -132,6 +132,7 @@ static void CopyFromBinaryEnd(CopyFromState cstate); /* text format */ static const CopyFromRoutine CopyFromRoutineText = { .CopyFromEstimateStateSpace = CopyFromBuiltinsEstimateSpace, + .CopyFromProcessOneOption = NULL, .CopyFromInFunc = CopyFromTextLikeInFunc, .CopyFromStart = CopyFromTextLikeStart, .CopyFromOneRow = CopyFromTextOneRow, @@ -141,6 +142,7 @@ static const CopyFromRoutine CopyFromRoutineText = { /* CSV format */ static const CopyFromRoutine CopyFromRoutineCSV = { .CopyFromEstimateStateSpace = CopyFromBuiltinsEstimateSpace, + .CopyFromProcessOneOption = NULL, .CopyFromInFunc = CopyFromTextLikeInFunc, .CopyFromStart = CopyFromTextLikeStart, .CopyFromOneRow = CopyFromCSVOneRow, @@ -150,6 +152,7 @@ static const CopyFromRoutine CopyFromRoutineCSV = { /* binary format */ static const CopyFromRoutine CopyFromRoutineBinary = { .CopyFromEstimateStateSpace = CopyFromBuiltinsEstimateSpace, + .CopyFromProcessOneOption = NULL, .CopyFromInFunc = CopyFromBinaryInFunc, .CopyFromStart = CopyFromBinaryStart, .CopyFromOneRow = CopyFromBinaryOneRow, @@ -2048,10 +2051,14 @@ ProcessCopyFromOptions(CopyFromState cstate, List *options, ParseState *pstate) foreach_node(DefElem, option, other_options) { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("COPY format \"%s\" not recognized", option->defname), - parser_errposition(pstate, option->location))); + if (cstate->routine->CopyFromProcessOneOption && + cstate->routine->CopyFromProcessOneOption(cstate, option)) + /* custom option is processed */ ; + else + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("COPY format \"%s\" not recognized", option->defname), + parser_errposition(pstate, option->location))); } if (temp_state) diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c index ea31fa911f9..9136098a0ed 100644 --- a/src/backend/commands/copyto.c +++ b/src/backend/commands/copyto.c @@ -122,6 +122,7 @@ static void CopySendInt16(CopyToState cstate, int16 val); /* text format */ static const CopyToRoutine CopyToRoutineText = { .CopyToEstimateStateSpace = CopyToEstimateStateTextLike, + .CopyToProcessOneOption = NULL, .CopyToStart = CopyToTextLikeStart, .CopyToOutFunc = CopyToTextLikeOutFunc, .CopyToOneRow = CopyToTextOneRow, @@ -131,6 +132,7 @@ static const CopyToRoutine CopyToRoutineText = { /* CSV format */ static const CopyToRoutine CopyToRoutineCSV = { .CopyToEstimateStateSpace = CopyToEstimateStateTextLike, + .CopyToProcessOneOption = NULL, .CopyToStart = CopyToTextLikeStart, .CopyToOutFunc = CopyToTextLikeOutFunc, .CopyToOneRow = CopyToCSVOneRow, @@ -140,6 +142,7 @@ static const CopyToRoutine CopyToRoutineCSV = { /* binary format */ static const CopyToRoutine CopyToRoutineBinary = { .CopyToEstimateStateSpace = CopyToEstimateStateBinary, + .CopyToProcessOneOption = NULL, .CopyToStart = CopyToBinaryStart, .CopyToOutFunc = CopyToBinaryOutFunc, .CopyToOneRow = CopyToBinaryOneRow, @@ -1589,12 +1592,16 @@ ProcessCopyToOptions(CopyToState cstate, List *options, ParseState *pstate) ProcessCopyBuiltinOptions(options, opts, false, &other_options, pstate); - foreach_node(DefElem, option, options) + foreach_node(DefElem, option, other_options) { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("COPY format \"%s\" not recognized", option->defname), - parser_errposition(pstate, option->location))); + if (cstate->routine->CopyToProcessOneOption && + cstate->routine->CopyToProcessOneOption(cstate, option)) + /* custom option is processed */ ; + else + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("COPY format \"%s\" not recognized", option->defname), + parser_errposition(pstate, option->location))); } if (temp_state) diff --git a/src/include/commands/copyapi.h b/src/include/commands/copyapi.h index 2090a4e1c61..e19279d0c3d 100644 --- a/src/include/commands/copyapi.h +++ b/src/include/commands/copyapi.h @@ -27,6 +27,14 @@ typedef struct CopyToRoutine */ Size (*CopyToEstimateStateSpace) (void); + /* + * Process one COPY TO option. Return true if the option is processed, + * otherwise return false. + * + * This is an optional callback. + */ + bool (*CopyToProcessOneOption) (CopyToState cstate, DefElem *option); + /* * Set output function information. This callback is called once at the * beginning of COPY TO. @@ -70,6 +78,14 @@ typedef struct CopyFromRoutine */ Size (*CopyFromEstimateStateSpace) (void); + /* + * Process one COPY FROM option. Return true if the option is processed, + * otherwise return false. + * + * This is an optional callback. + */ + bool (*CopyFromProcessOneOption) (CopyFromState cstate, DefElem *option); + /* * Set input function information. This callback is called once at the * beginning of COPY FROM. @@ -112,7 +128,7 @@ typedef struct CopyFromRoutine void (*CopyFromEnd) (CopyFromState cstate); } CopyFromRoutine; -extern int CopyFromGetData(CopyFromState cstate, void *databuf, int minread, int maxread); +extern int CopyFromGetData(CopyFromState cstate, void *databuf, int minread, int maxread); extern void CopyToFlushData(CopyToState cstate); extern void RegisterCopyCustomFormat(const char *fmt_name, const CopyFromRoutine *from_routine, -- 2.47.3