@@ -109,7 +109,8 @@ static void handle_modification_query(Query *parse, transform_query_cxt *context
109109static void partition_filter_visitor (Plan * plan , void * context );
110110
111111static 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 );
113114
114115
115116/*
@@ -389,7 +390,7 @@ handle_modification_query(Query *parse, transform_query_cxt *context)
389390
390391 rte = rt_fetch (result_rti , parse -> rtable );
391392
392- /* Exit if it's DELETE FROM ONLY table */
393+ /* Exit if it's ONLY table */
393394 if (!rte -> inh ) return ;
394395
395396 prel = get_pathman_relation_info (rte -> relid );
@@ -465,33 +466,37 @@ handle_modification_query(Query *parse, transform_query_cxt *context)
465466 return ; /* nothing to do here */
466467 }
467468
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+
468476 /* Both tables are already locked */
469477 child_rel = heap_open (child , NoLock );
470478 parent_rel = heap_open (parent , NoLock );
471479
472480 make_inh_translation_list (parent_rel , child_rel , 0 , & translated_vars );
473481
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+ }
484496
485497 /* Close relations (should remain locked, though) */
486498 heap_close (child_rel , NoLock );
487499 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;
495500 }
496501 }
497502
@@ -562,11 +567,11 @@ eval_extern_params_mutator(Node *node, ParamListInfo params)
562567}
563568
564569/* Remap parent's attributes to child ones s*/
565- static bool
570+ static Node *
566571adjust_appendrel_varnos (Node * node , adjust_appendrel_varnos_cxt * context )
567572{
568573 if (node == NULL )
569- return false ;
574+ return NULL ;
570575
571576 if (IsA (node , Query ))
572577 {
@@ -577,7 +582,7 @@ adjust_appendrel_varnos(Node *node, adjust_appendrel_varnos_cxt *context)
577582 foreach (lc , query -> targetList )
578583 {
579584 TargetEntry * te = (TargetEntry * ) lfirst (lc );
580- Var * child_var ;
585+ Var * child_var ;
581586
582587 if (te -> resjunk )
583588 continue ;
@@ -595,10 +600,12 @@ adjust_appendrel_varnos(Node *node, adjust_appendrel_varnos_cxt *context)
595600 te -> resno = child_var -> varattno ;
596601 }
597602
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 ));
602609 }
603610
604611 if (IsA (node , Var ))
@@ -610,6 +617,8 @@ adjust_appendrel_varnos(Node *node, adjust_appendrel_varnos_cxt *context)
610617 {
611618 Var * child_var ;
612619
620+ var = copyObject (var );
621+
613622 if (var -> varattno > list_length (context -> translated_vars ))
614623 elog (ERROR , "attribute %d of relation \"%s\" does not exist" ,
615624 var -> varattno , get_rel_name (context -> parent_relid ));
@@ -623,22 +632,44 @@ adjust_appendrel_varnos(Node *node, adjust_appendrel_varnos_cxt *context)
623632 var -> varattno = child_var -> varattno ;
624633 }
625634
626- return false ;
635+ return ( Node * ) var ;
627636 }
628637
629638 if (IsA (node , SubLink ))
630639 {
631640 SubLink * sl = (SubLink * ) node ;
632641
633642 /* 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 ;
635647 }
636648
637- return expression_tree_walker (node ,
638- adjust_appendrel_varnos ,
639- context );
649+ return expression_tree_mutator (node ,
650+ adjust_appendrel_varnos ,
651+ context );
640652}
641653
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+ }
642673
643674/*
644675 * -------------------------------
0 commit comments