@@ -284,16 +284,8 @@ typedef struct
284
284
*/
285
285
typedef struct ConversionLocation
286
286
{
287
- Relation rel ; /* foreign table's relcache entry. */
288
287
AttrNumber cur_attno ; /* attribute number being processed, or 0 */
289
-
290
- /*
291
- * In case of foreign join push down, fdw_scan_tlist is used to identify
292
- * the Var node corresponding to the error location and
293
- * fsstate->ss.ps.state gives access to the RTEs of corresponding relation
294
- * to get the relation name and attribute name.
295
- */
296
- ForeignScanState * fsstate ;
288
+ ForeignScanState * fsstate ; /* plan node being processed */
297
289
} ConversionLocation ;
298
290
299
291
/* Callback argument for ec_member_matches_foreign */
@@ -6317,7 +6309,6 @@ make_tuple_from_result_row(PGresult *res,
6317
6309
/*
6318
6310
* Set up and install callback to report where conversion error occurs.
6319
6311
*/
6320
- errpos .rel = rel ;
6321
6312
errpos .cur_attno = 0 ;
6322
6313
errpos .fsstate = fsstate ;
6323
6314
errcallback .callback = conversion_error_callback ;
@@ -6420,70 +6411,73 @@ make_tuple_from_result_row(PGresult *res,
6420
6411
/*
6421
6412
* Callback function which is called when error occurs during column value
6422
6413
* conversion. Print names of column and relation.
6414
+ *
6415
+ * Note that this function mustn't do any catalog lookups, since we are in
6416
+ * an already-failed transaction. Fortunately, we can get the needed info
6417
+ * from the query's rangetable instead.
6423
6418
*/
6424
6419
static void
6425
6420
conversion_error_callback (void * arg )
6426
6421
{
6422
+ ConversionLocation * errpos = (ConversionLocation * ) arg ;
6423
+ ForeignScanState * fsstate = errpos -> fsstate ;
6424
+ ForeignScan * fsplan = castNode (ForeignScan , fsstate -> ss .ps .plan );
6425
+ int varno = 0 ;
6426
+ AttrNumber colno = 0 ;
6427
6427
const char * attname = NULL ;
6428
6428
const char * relname = NULL ;
6429
6429
bool is_wholerow = false;
6430
- ConversionLocation * errpos = (ConversionLocation * ) arg ;
6431
6430
6432
- if (errpos -> rel )
6431
+ if (fsplan -> scan . scanrelid > 0 )
6433
6432
{
6434
6433
/* error occurred in a scan against a foreign table */
6435
- TupleDesc tupdesc = RelationGetDescr (errpos -> rel );
6436
- Form_pg_attribute attr = TupleDescAttr (tupdesc , errpos -> cur_attno - 1 );
6437
-
6438
- if (errpos -> cur_attno > 0 && errpos -> cur_attno <= tupdesc -> natts )
6439
- attname = NameStr (attr -> attname );
6440
- else if (errpos -> cur_attno == SelfItemPointerAttributeNumber )
6441
- attname = "ctid" ;
6442
-
6443
- relname = RelationGetRelationName (errpos -> rel );
6434
+ varno = fsplan -> scan .scanrelid ;
6435
+ colno = errpos -> cur_attno ;
6444
6436
}
6445
6437
else
6446
6438
{
6447
6439
/* error occurred in a scan against a foreign join */
6448
- ForeignScanState * fsstate = errpos -> fsstate ;
6449
- ForeignScan * fsplan = castNode (ForeignScan , fsstate -> ss .ps .plan );
6450
- EState * estate = fsstate -> ss .ps .state ;
6451
6440
TargetEntry * tle ;
6452
6441
6453
6442
tle = list_nth_node (TargetEntry , fsplan -> fdw_scan_tlist ,
6454
6443
errpos -> cur_attno - 1 );
6455
6444
6456
6445
/*
6457
6446
* Target list can have Vars and expressions. For Vars, we can get
6458
- * its relation , however for expressions we can't. Thus for
6447
+ * some information , however for expressions we can't. Thus for
6459
6448
* expressions, just show generic context message.
6460
6449
*/
6461
6450
if (IsA (tle -> expr , Var ))
6462
6451
{
6463
- RangeTblEntry * rte ;
6464
6452
Var * var = (Var * ) tle -> expr ;
6465
6453
6466
- rte = exec_rt_fetch (var -> varno , estate );
6467
-
6468
- if (var -> varattno == 0 )
6469
- is_wholerow = true;
6470
- else
6471
- attname = get_attname (rte -> relid , var -> varattno , false);
6472
-
6473
- relname = get_rel_name (rte -> relid );
6454
+ varno = var -> varno ;
6455
+ colno = var -> varattno ;
6474
6456
}
6475
- else
6476
- errcontext ("processing expression at position %d in select list" ,
6477
- errpos -> cur_attno );
6478
6457
}
6479
6458
6480
- if (relname )
6459
+ if (varno > 0 )
6481
6460
{
6482
- if (is_wholerow )
6483
- errcontext ("whole-row reference to foreign table \"%s\"" , relname );
6484
- else if (attname )
6485
- errcontext ("column \"%s\" of foreign table \"%s\"" , attname , relname );
6461
+ EState * estate = fsstate -> ss .ps .state ;
6462
+ RangeTblEntry * rte = exec_rt_fetch (varno , estate );
6463
+
6464
+ relname = rte -> eref -> aliasname ;
6465
+
6466
+ if (colno == 0 )
6467
+ is_wholerow = true;
6468
+ else if (colno > 0 && colno <= list_length (rte -> eref -> colnames ))
6469
+ attname = strVal (list_nth (rte -> eref -> colnames , colno - 1 ));
6470
+ else if (colno == SelfItemPointerAttributeNumber )
6471
+ attname = "ctid" ;
6486
6472
}
6473
+
6474
+ if (relname && is_wholerow )
6475
+ errcontext ("whole-row reference to foreign table \"%s\"" , relname );
6476
+ else if (relname && attname )
6477
+ errcontext ("column \"%s\" of foreign table \"%s\"" , attname , relname );
6478
+ else
6479
+ errcontext ("processing expression at position %d in select list" ,
6480
+ errpos -> cur_attno );
6487
6481
}
6488
6482
6489
6483
/*
0 commit comments