@@ -109,7 +109,8 @@ static void handle_modification_query(Query *parse, transform_query_cxt *context
109
109
static void partition_filter_visitor (Plan * plan , void * context );
110
110
111
111
static Node * eval_extern_params_mutator (Node * node , ParamListInfo params );
112
- static bool adjust_appendrel_varnos (Node * node , adjust_appendrel_varnos_cxt * context );
112
+ static Node * adjust_appendrel_varnos (Node * node , adjust_appendrel_varnos_cxt * context );
113
+ static bool inh_translation_list_is_trivial (List * translated_vars );
113
114
114
115
115
116
/*
@@ -389,7 +390,7 @@ handle_modification_query(Query *parse, transform_query_cxt *context)
389
390
390
391
rte = rt_fetch (result_rti , parse -> rtable );
391
392
392
- /* Exit if it's DELETE FROM ONLY table */
393
+ /* Exit if it's ONLY table */
393
394
if (!rte -> inh ) return ;
394
395
395
396
prel = get_pathman_relation_info (rte -> relid );
@@ -465,33 +466,37 @@ handle_modification_query(Query *parse, transform_query_cxt *context)
465
466
return ; /* nothing to do here */
466
467
}
467
468
469
+ /* Update RTE's relid and relkind (for FDW) */
470
+ rte -> relid = child ;
471
+ rte -> relkind = child_relkind ;
472
+
473
+ /* HACK: unset the 'inh' flag (no children) */
474
+ rte -> inh = false;
475
+
468
476
/* Both tables are already locked */
469
477
child_rel = heap_open (child , NoLock );
470
478
parent_rel = heap_open (parent , NoLock );
471
479
472
480
make_inh_translation_list (parent_rel , child_rel , 0 , & translated_vars );
473
481
474
- /* Translate varnos for this child */
475
- aav_cxt .child_varno = result_rti ;
476
- aav_cxt .parent_relid = parent ;
477
- aav_cxt .translated_vars = translated_vars ;
478
- adjust_appendrel_varnos ((Node * ) parse , & aav_cxt );
479
-
480
- /* Translate column privileges for this child */
481
- rte -> selectedCols = translate_col_privs (rte -> selectedCols , translated_vars );
482
- rte -> insertedCols = translate_col_privs (rte -> insertedCols , translated_vars );
483
- rte -> updatedCols = translate_col_privs (rte -> updatedCols , translated_vars );
482
+ /* Perform some additional adjustments */
483
+ if (!inh_translation_list_is_trivial (translated_vars ))
484
+ {
485
+ /* Translate varnos for this child */
486
+ aav_cxt .child_varno = result_rti ;
487
+ aav_cxt .parent_relid = parent ;
488
+ aav_cxt .translated_vars = translated_vars ;
489
+ adjust_appendrel_varnos ((Node * ) parse , & aav_cxt );
490
+
491
+ /* Translate column privileges for this child */
492
+ rte -> selectedCols = translate_col_privs (rte -> selectedCols , translated_vars );
493
+ rte -> insertedCols = translate_col_privs (rte -> insertedCols , translated_vars );
494
+ rte -> updatedCols = translate_col_privs (rte -> updatedCols , translated_vars );
495
+ }
484
496
485
497
/* Close relations (should remain locked, though) */
486
498
heap_close (child_rel , NoLock );
487
499
heap_close (parent_rel , NoLock );
488
-
489
- /* Update RTE's relid and relkind (for FDW) */
490
- rte -> relid = child ;
491
- rte -> relkind = child_relkind ;
492
-
493
- /* HACK: unset the 'inh' flag (no children) */
494
- rte -> inh = false;
495
500
}
496
501
}
497
502
@@ -562,11 +567,11 @@ eval_extern_params_mutator(Node *node, ParamListInfo params)
562
567
}
563
568
564
569
/* Remap parent's attributes to child ones s*/
565
- static bool
570
+ static Node *
566
571
adjust_appendrel_varnos (Node * node , adjust_appendrel_varnos_cxt * context )
567
572
{
568
573
if (node == NULL )
569
- return false ;
574
+ return NULL ;
570
575
571
576
if (IsA (node , Query ))
572
577
{
@@ -577,7 +582,7 @@ adjust_appendrel_varnos(Node *node, adjust_appendrel_varnos_cxt *context)
577
582
foreach (lc , query -> targetList )
578
583
{
579
584
TargetEntry * te = (TargetEntry * ) lfirst (lc );
580
- Var * child_var ;
585
+ Var * child_var ;
581
586
582
587
if (te -> resjunk )
583
588
continue ;
@@ -595,10 +600,12 @@ adjust_appendrel_varnos(Node *node, adjust_appendrel_varnos_cxt *context)
595
600
te -> resno = child_var -> varattno ;
596
601
}
597
602
598
- return query_tree_walker ((Query * ) node ,
599
- adjust_appendrel_varnos ,
600
- context ,
601
- QTW_IGNORE_RC_SUBQUERIES );
603
+ /* NOTE: we shouldn't copy top-level Query */
604
+ return (Node * ) query_tree_mutator ((Query * ) node ,
605
+ adjust_appendrel_varnos ,
606
+ context ,
607
+ (QTW_IGNORE_RC_SUBQUERIES |
608
+ QTW_DONT_COPY_QUERY ));
602
609
}
603
610
604
611
if (IsA (node , Var ))
@@ -610,6 +617,8 @@ adjust_appendrel_varnos(Node *node, adjust_appendrel_varnos_cxt *context)
610
617
{
611
618
Var * child_var ;
612
619
620
+ var = copyObject (var );
621
+
613
622
if (var -> varattno > list_length (context -> translated_vars ))
614
623
elog (ERROR , "attribute %d of relation \"%s\" does not exist" ,
615
624
var -> varattno , get_rel_name (context -> parent_relid ));
@@ -623,22 +632,44 @@ adjust_appendrel_varnos(Node *node, adjust_appendrel_varnos_cxt *context)
623
632
var -> varattno = child_var -> varattno ;
624
633
}
625
634
626
- return false ;
635
+ return ( Node * ) var ;
627
636
}
628
637
629
638
if (IsA (node , SubLink ))
630
639
{
631
640
SubLink * sl = (SubLink * ) node ;
632
641
633
642
/* Examine its expression */
634
- node = sl -> testexpr ;
643
+ sl -> testexpr = expression_tree_mutator (sl -> testexpr ,
644
+ adjust_appendrel_varnos ,
645
+ context );
646
+ return (Node * ) sl ;
635
647
}
636
648
637
- return expression_tree_walker (node ,
638
- adjust_appendrel_varnos ,
639
- context );
649
+ return expression_tree_mutator (node ,
650
+ adjust_appendrel_varnos ,
651
+ context );
640
652
}
641
653
654
+ /* Check whether Var translation list is trivial (no shuffle) */
655
+ static bool
656
+ inh_translation_list_is_trivial (List * translated_vars )
657
+ {
658
+ ListCell * lc ;
659
+ AttrNumber i = 1 ;
660
+
661
+ foreach (lc , translated_vars )
662
+ {
663
+ Var * var = (Var * ) lfirst (lc );
664
+
665
+ if (var && var -> varattno != i )
666
+ return false;
667
+
668
+ i ++ ;
669
+ }
670
+
671
+ return true;
672
+ }
642
673
643
674
/*
644
675
* -------------------------------
0 commit comments