Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2ce250c

Browse files
committed
copy expression trees for safety
1 parent 00309ba commit 2ce250c

File tree

1 file changed

+62
-31
lines changed

1 file changed

+62
-31
lines changed

src/planner_tree_modification.c

+62-31
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ static void handle_modification_query(Query *parse, transform_query_cxt *context
109109
static void partition_filter_visitor(Plan *plan, void *context);
110110

111111
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);
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 *
566571
adjust_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

Comments
 (0)