file_fdw_notnull_v1.patch
text/plain
Filename: file_fdw_notnull_v1.patch
Type: text/plain
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
Series: patch v1
| File | + | − |
|---|---|---|
| contrib/file_fdw/file_fdw.c | 22 | 0 |
| src/backend/executor/execMain.c | 1 | 0 |
| src/include/executor/executor.h | 2 | 0 |
*** a/contrib/file_fdw/file_fdw.c
--- b/contrib/file_fdw/file_fdw.c
***************
*** 502,507 **** fileIterateForeignScan(ForeignScanState *node)
--- 502,510 ----
{
FileFdwExecutionState *festate = (FileFdwExecutionState *) node->fdw_state;
TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
+ Relation rel = node->ss.ss_currentRelation;
+ TupleConstr *constr = rel->rd_att->constr;
+ bool has_not_null = (constr != NULL) ? constr->has_not_null : false;
bool found;
ErrorContextCallback errcontext;
***************
*** 528,534 **** fileIterateForeignScan(ForeignScanState *node)
--- 531,556 ----
slot->tts_values, slot->tts_isnull,
NULL);
if (found)
+ {
ExecStoreVirtualTuple(slot);
+ if (has_not_null)
+ {
+ int natts = rel->rd_att->natts;
+ int attrChk;
+
+ for (attrChk = 1; attrChk <= natts; attrChk++)
+ {
+ if (rel->rd_att->attrs[attrChk - 1]->attnotnull &&
+ slot_attisnull(slot, attrChk))
+ ereport(ERROR,
+ (errcode(ERRCODE_NOT_NULL_VIOLATION),
+ errmsg("null value in column \"%s\" violates not-null constraint",
+ NameStr(rel->rd_att->attrs[attrChk - 1]->attname)),
+ errdetail("Failing row contains %s.",
+ ExecBuildSlotValueDescription(slot, 64))));
+ }
+ }
+ }
/* Remove error callback. */
error_context_stack = errcontext.previous;
*** a/src/backend/executor/execMain.c
--- b/src/backend/executor/execMain.c
***************
*** 86,93 **** static void ExecutePlan(EState *estate, PlanState *planstate,
DestReceiver *dest);
static bool ExecCheckRTEPerms(RangeTblEntry *rte);
static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt);
- static char *ExecBuildSlotValueDescription(TupleTableSlot *slot,
- int maxfieldlen);
static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate,
Plan *planTree);
static void OpenIntoRel(QueryDesc *queryDesc);
--- 86,91 ----
***************
*** 1604,1610 **** ExecConstraints(ResultRelInfo *resultRelInfo,
* here since heap field values could be very long, whereas index entries
* typically aren't so wide.
*/
! static char *
ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
{
StringInfoData buf;
--- 1602,1608 ----
* here since heap field values could be very long, whereas index entries
* typically aren't so wide.
*/
! char *
ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
{
StringInfoData buf;
*** a/src/include/executor/executor.h
--- b/src/include/executor/executor.h
***************
*** 184,189 **** extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid);
--- 184,191 ----
extern bool ExecContextForcesOids(PlanState *planstate, bool *hasoids);
extern void ExecConstraints(ResultRelInfo *resultRelInfo,
TupleTableSlot *slot, EState *estate);
+ extern char *ExecBuildSlotValueDescription(TupleTableSlot *slot,
+ int maxfieldlen);
extern ExecRowMark *ExecFindRowMark(EState *estate, Index rti);
extern ExecAuxRowMark *ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist);
extern TupleTableSlot *EvalPlanQual(EState *estate, EPQState *epqstate,