@@ -285,16 +285,8 @@ typedef struct
285
285
*/
286
286
typedef struct ConversionLocation
287
287
{
288
- Relation rel ; /* foreign table's relcache entry. */
289
288
AttrNumber cur_attno ; /* attribute number being processed, or 0 */
290
-
291
- /*
292
- * In case of foreign join push down, fdw_scan_tlist is used to identify
293
- * the Var node corresponding to the error location and
294
- * fsstate->ss.ps.state gives access to the RTEs of corresponding relation
295
- * to get the relation name and attribute name.
296
- */
297
- ForeignScanState * fsstate ;
289
+ ForeignScanState * fsstate ; /* plan node being processed */
298
290
} ConversionLocation ;
299
291
300
292
/* Callback argument for ec_member_matches_foreign */
@@ -6369,7 +6361,6 @@ make_tuple_from_result_row(PGresult *res,
6369
6361
/*
6370
6362
* Set up and install callback to report where conversion error occurs.
6371
6363
*/
6372
- errpos .rel = rel ;
6373
6364
errpos .cur_attno = 0 ;
6374
6365
errpos .fsstate = fsstate ;
6375
6366
errcallback .callback = conversion_error_callback ;
@@ -6472,70 +6463,73 @@ make_tuple_from_result_row(PGresult *res,
6472
6463
/*
6473
6464
* Callback function which is called when error occurs during column value
6474
6465
* conversion. Print names of column and relation.
6466
+ *
6467
+ * Note that this function mustn't do any catalog lookups, since we are in
6468
+ * an already-failed transaction. Fortunately, we can get the needed info
6469
+ * from the query's rangetable instead.
6475
6470
*/
6476
6471
static void
6477
6472
conversion_error_callback (void * arg )
6478
6473
{
6474
+ ConversionLocation * errpos = (ConversionLocation * ) arg ;
6475
+ ForeignScanState * fsstate = errpos -> fsstate ;
6476
+ ForeignScan * fsplan = castNode (ForeignScan , fsstate -> ss .ps .plan );
6477
+ int varno = 0 ;
6478
+ AttrNumber colno = 0 ;
6479
6479
const char * attname = NULL ;
6480
6480
const char * relname = NULL ;
6481
6481
bool is_wholerow = false;
6482
- ConversionLocation * errpos = (ConversionLocation * ) arg ;
6483
6482
6484
- if (errpos -> rel )
6483
+ if (fsplan -> scan . scanrelid > 0 )
6485
6484
{
6486
6485
/* error occurred in a scan against a foreign table */
6487
- TupleDesc tupdesc = RelationGetDescr (errpos -> rel );
6488
- Form_pg_attribute attr = TupleDescAttr (tupdesc , errpos -> cur_attno - 1 );
6489
-
6490
- if (errpos -> cur_attno > 0 && errpos -> cur_attno <= tupdesc -> natts )
6491
- attname = NameStr (attr -> attname );
6492
- else if (errpos -> cur_attno == SelfItemPointerAttributeNumber )
6493
- attname = "ctid" ;
6494
-
6495
- relname = RelationGetRelationName (errpos -> rel );
6486
+ varno = fsplan -> scan .scanrelid ;
6487
+ colno = errpos -> cur_attno ;
6496
6488
}
6497
6489
else
6498
6490
{
6499
6491
/* error occurred in a scan against a foreign join */
6500
- ForeignScanState * fsstate = errpos -> fsstate ;
6501
- ForeignScan * fsplan = castNode (ForeignScan , fsstate -> ss .ps .plan );
6502
- EState * estate = fsstate -> ss .ps .state ;
6503
6492
TargetEntry * tle ;
6504
6493
6505
6494
tle = list_nth_node (TargetEntry , fsplan -> fdw_scan_tlist ,
6506
6495
errpos -> cur_attno - 1 );
6507
6496
6508
6497
/*
6509
6498
* Target list can have Vars and expressions. For Vars, we can get
6510
- * its relation , however for expressions we can't. Thus for
6499
+ * some information , however for expressions we can't. Thus for
6511
6500
* expressions, just show generic context message.
6512
6501
*/
6513
6502
if (IsA (tle -> expr , Var ))
6514
6503
{
6515
- RangeTblEntry * rte ;
6516
6504
Var * var = (Var * ) tle -> expr ;
6517
6505
6518
- rte = exec_rt_fetch (var -> varno , estate );
6519
-
6520
- if (var -> varattno == 0 )
6521
- is_wholerow = true;
6522
- else
6523
- attname = get_attname (rte -> relid , var -> varattno , false);
6524
-
6525
- relname = get_rel_name (rte -> relid );
6506
+ varno = var -> varno ;
6507
+ colno = var -> varattno ;
6526
6508
}
6527
- else
6528
- errcontext ("processing expression at position %d in select list" ,
6529
- errpos -> cur_attno );
6530
6509
}
6531
6510
6532
- if (relname )
6511
+ if (varno > 0 )
6533
6512
{
6534
- if (is_wholerow )
6535
- errcontext ("whole-row reference to foreign table \"%s\"" , relname );
6536
- else if (attname )
6537
- errcontext ("column \"%s\" of foreign table \"%s\"" , attname , relname );
6513
+ EState * estate = fsstate -> ss .ps .state ;
6514
+ RangeTblEntry * rte = exec_rt_fetch (varno , estate );
6515
+
6516
+ relname = rte -> eref -> aliasname ;
6517
+
6518
+ if (colno == 0 )
6519
+ is_wholerow = true;
6520
+ else if (colno > 0 && colno <= list_length (rte -> eref -> colnames ))
6521
+ attname = strVal (list_nth (rte -> eref -> colnames , colno - 1 ));
6522
+ else if (colno == SelfItemPointerAttributeNumber )
6523
+ attname = "ctid" ;
6538
6524
}
6525
+
6526
+ if (relname && is_wholerow )
6527
+ errcontext ("whole-row reference to foreign table \"%s\"" , relname );
6528
+ else if (relname && attname )
6529
+ errcontext ("column \"%s\" of foreign table \"%s\"" , attname , relname );
6530
+ else
6531
+ errcontext ("processing expression at position %d in select list" ,
6532
+ errpos -> cur_attno );
6539
6533
}
6540
6534
6541
6535
/*
0 commit comments