From ea7f9cd050e3869a1c704547e2696fcc4bbc19a0 Mon Sep 17 00:00:00 2001 From: Fujii Masao Date: Wed, 4 Nov 2026 17:42:46 +0900 Subject: [PATCH v1] file_fdw: Fix ANALYZE crashes with DEFAULT markers ANALYZE on a file_fdw foreign table failed an assertion when the input contained a DEFAULT marker, and could crash in builds without assertions. This happened because the sampling code passed a NULL ExprContext to NextCopyFrom(), which requires one to evaluate column defaults. Fix this by providing an expression context for sampling, allowing defaults to be evaluated without assertion failures or crashes. Backpatch to v16, which introduced DEFAULT marker support. Backpatch-through: 16 --- contrib/file_fdw/expected/file_fdw.out | 10 ++++++++++ contrib/file_fdw/file_fdw.c | 24 +++++++++++++----------- contrib/file_fdw/sql/file_fdw.sql | 5 +++++ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/contrib/file_fdw/expected/file_fdw.out b/contrib/file_fdw/expected/file_fdw.out index 640986528ae..bd502c98833 100644 --- a/contrib/file_fdw/expected/file_fdw.out +++ b/contrib/file_fdw/expected/file_fdw.out @@ -536,6 +536,16 @@ SELECT id, text_value, ts_value FROM copy_default; 3 | test | Tue Jul 05 00:00:00 2022 (3 rows) +ANALYZE copy_default; +SELECT most_common_vals +FROM pg_stats +WHERE schemaname = 'public' AND tablename = 'copy_default' + AND attname = 'text_value'; + most_common_vals +------------------ + {test} +(1 row) + DROP FOREIGN TABLE copy_default; -- privilege tests SET ROLE regress_file_fdw_superuser; diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c index 7d9dc3baf74..1b6d47e561a 100644 --- a/contrib/file_fdw/file_fdw.c +++ b/contrib/file_fdw/file_fdw.c @@ -1200,7 +1200,8 @@ file_acquire_sample_rows(Relation onerel, int elevel, CopyFromState cstate; ErrorContextCallback errcallback; MemoryContext oldcontext = CurrentMemoryContext; - MemoryContext tupcontext; + EState *estate; + ExprContext *econtext; Assert(onerel); Assert(targrows > 0); @@ -1219,12 +1220,11 @@ file_acquire_sample_rows(Relation onerel, int elevel, options); /* - * Use per-tuple memory context to prevent leak of memory used to read - * rows from the file with Copy routines. + * Create an expression context to evaluate DEFAULT expressions. Use its + * per-tuple memory context for reading rows with the Copy routines, too. */ - tupcontext = AllocSetContextCreate(CurrentMemoryContext, - "file_fdw temporary context", - ALLOCSET_DEFAULT_SIZES); + estate = CreateExecutorState(); + econtext = GetPerTupleExprContext(estate); /* Prepare for sampling rows */ reservoir_init_selection_state(&rstate, targrows); @@ -1242,11 +1242,13 @@ file_acquire_sample_rows(Relation onerel, int elevel, /* Check for user-requested abort or sleep */ vacuum_delay_point(true); - /* Fetch next row */ - MemoryContextReset(tupcontext); - MemoryContextSwitchTo(tupcontext); + /* Clean up the previous row's expression evaluation state */ + ReScanExprContext(econtext); + + /* Fetch next row in the per-tuple memory context */ + MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); - found = NextCopyFrom(cstate, NULL, values, nulls); + found = NextCopyFrom(cstate, econtext, values, nulls); MemoryContextSwitchTo(oldcontext); @@ -1311,7 +1313,7 @@ file_acquire_sample_rows(Relation onerel, int elevel, error_context_stack = errcallback.previous; /* Clean up. */ - MemoryContextDelete(tupcontext); + FreeExecutorState(estate); if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE && cstate->num_errors > 0 && diff --git a/contrib/file_fdw/sql/file_fdw.sql b/contrib/file_fdw/sql/file_fdw.sql index 56bfc926c00..b5894ed22fe 100644 --- a/contrib/file_fdw/sql/file_fdw.sql +++ b/contrib/file_fdw/sql/file_fdw.sql @@ -293,6 +293,11 @@ CREATE FOREIGN TABLE copy_default ( ) SERVER file_server OPTIONS (format 'csv', filename :'filename', default '\D'); SELECT id, text_value, ts_value FROM copy_default; +ANALYZE copy_default; +SELECT most_common_vals +FROM pg_stats +WHERE schemaname = 'public' AND tablename = 'copy_default' + AND attname = 'text_value'; DROP FOREIGN TABLE copy_default; -- privilege tests -- 2.56.0