diff --git a/src/backend/access/external/fileam.c b/src/backend/access/external/fileam.c index 8b5d0028b23aa9e6554e1230c7f059de7539cb20..ca303e48e0a261a273e5f6b910b233b99dd521f7 100644 --- a/src/backend/access/external/fileam.c +++ b/src/backend/access/external/fileam.c @@ -279,11 +279,6 @@ external_beginscan(Relation relation, Index scanrelid, uint32 scancounter, scan->fs_formatter->fmt_perrow_ctx = scan->fs_pstate->rowcontext; } - /* Set up callback to identify error line number */ - scan->errcontext.callback = external_scan_error_callback; - scan->errcontext.arg = (void *) scan->fs_pstate; - scan->errcontext.previous = error_context_stack; - /* pgstat_initstats(relation); */ return scan; @@ -405,11 +400,6 @@ external_endscan(FileScanDesc scan) scan->fs_pstate = NULL; } - /* - * clean up error context - */ - error_context_stack = scan->errcontext.previous; - PG_TRY(); { /* @@ -1200,10 +1190,16 @@ externalgettup(FileScanDesc scan, { CopyState pstate = scan->fs_pstate; bool custom = pstate->custom; + HeapTuple tup = NULL; + ErrorContextCallback externalscan_error_context; Assert(ScanDirectionIsForward(dir)); - error_context_stack = &scan->errcontext; + externalscan_error_context.callback = external_scan_error_callback; + externalscan_error_context.arg = (void *) scan->fs_pstate; + externalscan_error_context.previous = error_context_stack; + + error_context_stack = &externalscan_error_context; if (!scan->fs_inited) { @@ -1217,10 +1213,14 @@ externalgettup(FileScanDesc scan, } if (!custom) - return externalgettup_defined(scan); /* text/csv */ + tup = externalgettup_defined(scan); /* text/csv */ else - return externalgettup_custom(scan); /* custom */ + tup = externalgettup_custom(scan); /* custom */ + + /* Restore the previous error callback */ + error_context_stack = externalscan_error_context.previous; + return tup; } /* diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h index c868885ad852b27c03a1fa10934b37888f87d748..fae6fff33a2578f5a7f093c2b110e5a5f17b0710 100644 --- a/src/include/access/relscan.h +++ b/src/include/access/relscan.h @@ -118,7 +118,6 @@ typedef struct FileScanDescData FmgrInfo *in_functions; Oid *typioparams; Oid in_func_oid; - ErrorContextCallback errcontext; /* current file scan state */ bool fs_inited; /* false = scan not init'd yet */ diff --git a/src/test/regress/input/external_table.source b/src/test/regress/input/external_table.source index 93e6ef270ca55b919ce68998018a7736e1471f66..75ed7d024d8755bec1ab8f6157a68a11758642e8 100644 --- a/src/test/regress/input/external_table.source +++ b/src/test/regress/input/external_table.source @@ -1421,3 +1421,32 @@ FORMAT 'csv'; -- drop temp external table DROP EXTERNAL TABLE IF EXISTS serial; + +-- External table query within plpgSQL function get error +CREATE EXTERNAL TABLE exttab_error_context_callback(c1 int, c2 int) +LOCATION ('file://@hostname@@abs_srcdir@/data/exttab.data') FORMAT 'TEXT'; + +CREATE or REPLACE FUNCTION exttab_error_context_callback_func() +RETURNS SETOF INTEGER +AS +$$ +DECLARE + ret INTEGER; +BEGIN + FOR ret IN + SELECT c2 from exttab_error_context_callback + LOOP + RETURN NEXT ret; + END LOOP; +END +$$ +LANGUAGE plpgSQL READS SQL DATA; + +SET gp_log_gang TO DEBUG; + +SELECT * FROM exttab_error_context_callback_func(); + +SET gp_log_gang TO DEFAULT; + +DROP FUNCTION exttab_error_context_callback_func(); +DROP EXTERNAL TABLE exttab_error_context_callback; diff --git a/src/test/regress/output/external_table.source b/src/test/regress/output/external_table.source index b8bbf4539a407d3f78f2897738d91ab254618ccf..8d19586e01ab76658819e92f9541439a54f53fad 100644 --- a/src/test/regress/output/external_table.source +++ b/src/test/regress/output/external_table.source @@ -2886,3 +2886,29 @@ FORMAT 'csv'; NOTICE: CREATE EXTERNAL TABLE will create implicit sequence "serial_a_seq" for serial column "serial.a" -- drop temp external table DROP EXTERNAL TABLE IF EXISTS serial; +-- External table query within plpgSQL function get error +CREATE EXTERNAL TABLE exttab_error_context_callback(c1 int, c2 int) +LOCATION ('file://@hostname@@abs_srcdir@/data/exttab.data') FORMAT 'TEXT'; +CREATE or REPLACE FUNCTION exttab_error_context_callback_func() +RETURNS SETOF INTEGER +AS +$$ +DECLARE + ret INTEGER; +BEGIN + FOR ret IN + SELECT c2 from exttab_error_context_callback + LOOP + RETURN NEXT ret; + END LOOP; +END +$$ +LANGUAGE plpgSQL READS SQL DATA; +SET gp_log_gang TO DEBUG; +SELECT * FROM exttab_error_context_callback_func(); +ERROR: missing data for column "c2" (seg1 slice2 @hostname@:25532 pid=20960) +DETAIL: External table exttab_error_context_callback, line 1 of file://@hostname@@abs_srcdir@/data/exttab.data: "1|1_number" +CONTEXT: PL/pgSQL function "exttab_error_context_callback_func" line 4 at FOR over SELECT rows +SET gp_log_gang TO DEFAULT; +DROP FUNCTION exttab_error_context_callback_func(); +DROP EXTERNAL TABLE exttab_error_context_callback;