1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

Add a DEFAULT option to COPY FROM

This allows for a string which if an input field matches causes the
column's default value to be inserted. The advantage of this is that
the default can be inserted in some rows and not others, for which
non-default data is available.

The file_fdw extension is also modified to take allow use of this
option.

Israel Barth Rubio

Discussion: https://postgr.es/m/CAO_rXXAcqesk6DsvioOZ5zmeEmpUN5ktZf-9=9yu+DTr0Xr8Uw@mail.gmail.com
This commit is contained in:
Andrew Dunstan
2023-03-13 10:01:56 -04:00
parent 7b14e20b12
commit 9f8377f7a2
15 changed files with 447 additions and 24 deletions

View File

@ -72,6 +72,7 @@ static const struct FileFdwOption valid_options[] = {
{"quote", ForeignTableRelationId},
{"escape", ForeignTableRelationId},
{"null", ForeignTableRelationId},
{"default", ForeignTableRelationId},
{"encoding", ForeignTableRelationId},
{"force_not_null", AttributeRelationId},
{"force_null", AttributeRelationId},
@ -712,6 +713,9 @@ static TupleTableSlot *
fileIterateForeignScan(ForeignScanState *node)
{
FileFdwExecutionState *festate = (FileFdwExecutionState *) node->fdw_state;
EState *estate = CreateExecutorState();
ExprContext *econtext;
MemoryContext oldcontext;
TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
bool found;
ErrorContextCallback errcallback;
@ -728,15 +732,25 @@ fileIterateForeignScan(ForeignScanState *node)
* ExecStoreVirtualTuple. If we don't find another row in the file, we
* just skip the last step, leaving the slot empty as required.
*
* We can pass ExprContext = NULL because we read all columns from the
* file, so no need to evaluate default expressions.
* We pass ExprContext because there might be a use of the DEFAULT option
* in COPY FROM, so we may need to evaluate default expressions.
*/
ExecClearTuple(slot);
found = NextCopyFrom(festate->cstate, NULL,
econtext = GetPerTupleExprContext(estate);
/*
* DEFAULT expressions need to be evaluated in a per-tuple context, so
* switch in case we are doing that.
*/
oldcontext = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
found = NextCopyFrom(festate->cstate, econtext,
slot->tts_values, slot->tts_isnull);
if (found)
ExecStoreVirtualTuple(slot);
/* Switch back to original memory context */
MemoryContextSwitchTo(oldcontext);
/* Remove error callback. */
error_context_stack = errcallback.previous;