@@ -243,16 +243,8 @@ typedef struct PgFdwAnalyzeState
243
243
*/
244
244
typedef struct ConversionLocation
245
245
{
246
- Relation rel ; /* foreign table's relcache entry. */
247
246
AttrNumber cur_attno ; /* attribute number being processed, or 0 */
248
-
249
- /*
250
- * In case of foreign join push down, fdw_scan_tlist is used to identify
251
- * the Var node corresponding to the error location and
252
- * fsstate->ss.ps.state gives access to the RTEs of corresponding relation
253
- * to get the relation name and attribute name.
254
- */
255
- ForeignScanState * fsstate ;
247
+ ForeignScanState * fsstate ; /* plan node being processed */
256
248
} ConversionLocation ;
257
249
258
250
/* Callback argument for ec_member_matches_foreign */
@@ -4454,7 +4446,6 @@ make_tuple_from_result_row(PGresult *res,
4454
4446
/*
4455
4447
* Set up and install callback to report where conversion error occurs.
4456
4448
*/
4457
- errpos .rel = rel ;
4458
4449
errpos .cur_attno = 0 ;
4459
4450
errpos .fsstate = fsstate ;
4460
4451
errcallback .callback = conversion_error_callback ;
@@ -4553,61 +4544,77 @@ make_tuple_from_result_row(PGresult *res,
4553
4544
/*
4554
4545
* Callback function which is called when error occurs during column value
4555
4546
* conversion. Print names of column and relation.
4547
+ *
4548
+ * Note that this function mustn't do any catalog lookups, since we are in
4549
+ * an already-failed transaction. Fortunately, we can get the needed info
4550
+ * from the query's rangetable instead.
4556
4551
*/
4557
4552
static void
4558
4553
conversion_error_callback (void * arg )
4559
4554
{
4555
+ ConversionLocation * errpos = (ConversionLocation * ) arg ;
4556
+ ForeignScanState * fsstate = errpos -> fsstate ;
4557
+ ForeignScan * fsplan = (ForeignScan * ) fsstate -> ss .ps .plan ;
4558
+ int varno = 0 ;
4559
+ AttrNumber colno = 0 ;
4560
4560
const char * attname = NULL ;
4561
4561
const char * relname = NULL ;
4562
4562
bool is_wholerow = false;
4563
- ConversionLocation * errpos = (ConversionLocation * ) arg ;
4564
4563
4565
- if (errpos -> rel )
4564
+ if (fsplan -> scan . scanrelid > 0 )
4566
4565
{
4567
4566
/* error occurred in a scan against a foreign table */
4568
- TupleDesc tupdesc = RelationGetDescr (errpos -> rel );
4569
-
4570
- if (errpos -> cur_attno > 0 && errpos -> cur_attno <= tupdesc -> natts )
4571
- attname = NameStr (tupdesc -> attrs [errpos -> cur_attno - 1 ]-> attname );
4572
- else if (errpos -> cur_attno == SelfItemPointerAttributeNumber )
4573
- attname = "ctid" ;
4574
-
4575
- relname = RelationGetRelationName (errpos -> rel );
4567
+ varno = fsplan -> scan .scanrelid ;
4568
+ colno = errpos -> cur_attno ;
4576
4569
}
4577
4570
else
4578
4571
{
4579
4572
/* error occurred in a scan against a foreign join */
4580
- ForeignScanState * fsstate = errpos -> fsstate ;
4581
- ForeignScan * fsplan = (ForeignScan * ) fsstate -> ss .ps .plan ;
4582
- EState * estate = fsstate -> ss .ps .state ;
4583
4573
TargetEntry * tle ;
4584
- Var * var ;
4585
- RangeTblEntry * rte ;
4586
4574
4587
4575
Assert (IsA (fsplan , ForeignScan ));
4588
4576
tle = (TargetEntry * ) list_nth (fsplan -> fdw_scan_tlist ,
4589
4577
errpos -> cur_attno - 1 );
4590
4578
Assert (IsA (tle , TargetEntry ));
4591
- var = (Var * ) tle -> expr ;
4592
- Assert (IsA (var , Var ));
4593
-
4594
- rte = rt_fetch (var -> varno , estate -> es_range_table );
4595
4579
4596
- if (var -> varattno == 0 )
4597
- is_wholerow = true;
4598
- else
4599
- attname = get_relid_attribute_name (rte -> relid , var -> varattno );
4580
+ /*
4581
+ * Target list can have Vars and expressions. For Vars, we can get
4582
+ * some information, however for expressions we can't. Thus for
4583
+ * expressions, just show generic context message.
4584
+ */
4585
+ if (IsA (tle -> expr , Var ))
4586
+ {
4587
+ Var * var = (Var * ) tle -> expr ;
4600
4588
4601
- relname = get_rel_name (rte -> relid );
4589
+ varno = var -> varno ;
4590
+ colno = var -> varattno ;
4591
+ }
4602
4592
}
4603
4593
4604
- if (relname )
4594
+ if (varno > 0 )
4605
4595
{
4606
- if (is_wholerow )
4607
- errcontext ("whole-row reference to foreign table \"%s\"" , relname );
4608
- else if (attname )
4609
- errcontext ("column \"%s\" of foreign table \"%s\"" , attname , relname );
4596
+ EState * estate = fsstate -> ss .ps .state ;
4597
+ RangeTblEntry * rte = rt_fetch (varno , estate -> es_range_table );
4598
+
4599
+ relname = rte -> eref -> aliasname ;
4600
+
4601
+ if (colno == 0 )
4602
+ is_wholerow = true;
4603
+ else if (colno > 0 && colno <= list_length (rte -> eref -> colnames ))
4604
+ attname = strVal (list_nth (rte -> eref -> colnames , colno - 1 ));
4605
+ else if (colno == SelfItemPointerAttributeNumber )
4606
+ attname = "ctid" ;
4607
+ else if (colno == ObjectIdAttributeNumber )
4608
+ attname = "oid" ;
4610
4609
}
4610
+
4611
+ if (relname && is_wholerow )
4612
+ errcontext ("whole-row reference to foreign table \"%s\"" , relname );
4613
+ else if (relname && attname )
4614
+ errcontext ("column \"%s\" of foreign table \"%s\"" , attname , relname );
4615
+ else
4616
+ errcontext ("processing expression at position %d in select list" ,
4617
+ errpos -> cur_attno );
4611
4618
}
4612
4619
4613
4620
/*
0 commit comments