summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Paquier2012-04-24 10:48:41 +0000
committerMichael Paquier2012-04-24 10:48:41 +0000
commitba13c73845855573c28d16fc4a4d5919b3e0946c (patch)
tree99a1f1f4506861bf79609f5e737207729dd8a0a2 /src
parentf12afa86e544f581c7c6d7a0fdf02502c4a0aed9 (diff)
Fix standard remote DML plans using inherited tables
Simple test cases like this one were not possible for 4 reasons: create table p1 (f1 int); create table c1 (f2 text, f3 int) inherits (p1); alter table p1 add column a1 int check (a1 > 0); alter table p1 add column f2 text; insert into p1 values (1,2,'abc'); insert into c1 values(11,'xyz',33,22); update p1 set a1 = a1 + 1, f2 = upper(f2); 1) When generating a remote DDL query, the parent relation name was used instead of the child name. 2) UPDATE and DELETE did not use ONLY when generating query, causing subtables to be deleted or updated twice. Well deletion is not so much a problem but UPDATE leaded to inconsistencies for stuff updated like "column = column + expression()" 3) Remote DDL executor was always using the parent plan, leading to inconsistencies in parameters pushed down 4) In query generated for remote UPDATE, the attribute number used was the one from target list. In case of parent it is correct, but not always for child tables. This commit fixes some issues in tests alter_table and plpgsql.
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/nodeModifyTable.c15
-rw-r--r--src/backend/optimizer/plan/createplan.c37
-rw-r--r--src/test/regress/expected/xc_FQS_join.out8
3 files changed, 35 insertions, 25 deletions
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 002e1d2991..0259cbf1b7 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -813,9 +813,10 @@ ExecModifyTable(ModifyTableState *node)
/* Preload local variables */
resultRelInfo = node->resultRelInfo + node->mt_whichplan;
subplanstate = node->mt_plans[node->mt_whichplan];
-#ifdef PGXC
+#ifdef PGXC
+ /* Initialize remote plan state */
remoterelstate = node->mt_remoterels[node->mt_whichplan];
-#endif
+#endif
junkfilter = resultRelInfo->ri_junkFilter;
/*
@@ -826,12 +827,12 @@ ExecModifyTable(ModifyTableState *node)
* CTE). So we have to save and restore the caller's value.
*/
saved_resultRelInfo = estate->es_result_relation_info;
-#ifdef PGXC
+#ifdef PGXC
saved_resultRemoteRel = estate->es_result_remoterel;
#endif
estate->es_result_relation_info = resultRelInfo;
-#ifdef PGXC
+#ifdef PGXC
estate->es_result_remoterel = remoterelstate;
#endif
@@ -859,9 +860,11 @@ ExecModifyTable(ModifyTableState *node)
{
resultRelInfo++;
subplanstate = node->mt_plans[node->mt_whichplan];
-#ifdef PGXC
+#ifdef PGXC
+ /* Move to next remote plan */
+ estate->es_result_remoterel = node->mt_remoterels[node->mt_whichplan];
remoterelstate = node->mt_plans[node->mt_whichplan];
-#endif
+#endif
junkfilter = resultRelInfo->ri_junkFilter;
estate->es_result_relation_info = resultRelInfo;
EvalPlanQualSetPlan(&node->mt_epqstate, subplanstate->plan,
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index fd7d8e7198..834e8e80e3 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -5503,6 +5503,7 @@ create_remoteinsert_plan(PlannerInfo *root, Plan *topplan)
char *nspname;
int natts, att;
Oid *att_types;
+ char *relname;
ttab = rt_fetch(resultRelationIndex, root->parse->rtable);
@@ -5520,6 +5521,7 @@ create_remoteinsert_plan(PlannerInfo *root, Plan *topplan)
/* Compose INSERT FROM target_table */
nspid = get_rel_namespace(ttab->relid);
nspname = get_namespace_name(nspid);
+ relname = get_rel_name(ttab->relid);
/*
* Do not qualify with namespace for TEMP tables. The schema name may
@@ -5527,10 +5529,10 @@ create_remoteinsert_plan(PlannerInfo *root, Plan *topplan)
*/
if (IsTempTable(ttab->relid))
appendStringInfo(buf, "INSERT INTO %s (",
- quote_identifier(ttab->relname));
+ quote_identifier(relname));
else
appendStringInfo(buf, "INSERT INTO %s.%s (", quote_identifier(nspname),
- quote_identifier(ttab->relname));
+ quote_identifier(relname));
fstep = make_remotequery(NIL, NIL, resultRelationIndex);
fstep->is_temp = IsTempTable(ttab->relid);
@@ -5651,6 +5653,7 @@ create_remoteupdate_plan(PlannerInfo *root, Plan *topplan)
ListCell *elt;
int count = 1, where_count = 1;
int natts, count_prepparams, tot_prepparams;
+ char *relname;
ttab = rt_fetch(resultRelationIndex, parse->rtable);
@@ -5658,6 +5661,8 @@ create_remoteupdate_plan(PlannerInfo *root, Plan *topplan)
if (ttab == NULL || ttab->rtekind != RTE_RELATION)
continue;
+ relname = get_rel_name(ttab->relid);
+
/* Get location info of the target table */
rel_loc_info = GetRelationLocInfo(ttab->relid);
if (rel_loc_info == NULL)
@@ -5677,11 +5682,11 @@ create_remoteupdate_plan(PlannerInfo *root, Plan *topplan)
* vary on each node
*/
if (IsTempTable(ttab->relid))
- appendStringInfo(buf, "UPDATE %s SET ",
- quote_identifier(ttab->relname));
+ appendStringInfo(buf, "UPDATE ONLY %s SET ",
+ quote_identifier(relname));
else
- appendStringInfo(buf, "UPDATE %s.%s SET ", quote_identifier(nspname),
- quote_identifier(ttab->relname));
+ appendStringInfo(buf, "UPDATE ONLY %s.%s SET ", quote_identifier(nspname),
+ quote_identifier(relname));
/*
* Count the number of junk entries before setting the parameter type list.
@@ -5743,11 +5748,6 @@ create_remoteupdate_plan(PlannerInfo *root, Plan *topplan)
else
appendStringInfoString(buf, ", ");
- /* Complete string */
- appendStringInfo(buf, "%s = $%d",
- tle->resname,
- tle->resno);
-
/* We need first to find the position of this element in attribute list */
for (i = 0; i < natts; i++)
{
@@ -5759,6 +5759,11 @@ create_remoteupdate_plan(PlannerInfo *root, Plan *topplan)
}
}
+ /* Complete string */
+ appendStringInfo(buf, "%s = $%d",
+ tle->resname,
+ attno);
+
/* Set parameter type correctly */
param_types[attno - 1] = exprType((Node *) tle->expr);
}
@@ -5951,6 +5956,7 @@ create_remotedelete_plan(PlannerInfo *root, Plan *topplan)
bool is_where_created = false;
ListCell *elt;
int count = 1;
+ char *relname;
ttab = rt_fetch(resultRelationIndex, parse->rtable);
@@ -5969,6 +5975,7 @@ create_remotedelete_plan(PlannerInfo *root, Plan *topplan)
/* Compose DELETE target_table */
nspid = get_rel_namespace(ttab->relid);
nspname = get_namespace_name(nspid);
+ relname = get_rel_name(ttab->relid);
/* Parameters are defined by target list */
nparams = list_length(parse->targetList);
@@ -5979,11 +5986,11 @@ create_remotedelete_plan(PlannerInfo *root, Plan *topplan)
* vary on each node.
*/
if (IsTempTable(ttab->relid))
- appendStringInfo(buf, "DELETE FROM %s ",
- quote_identifier(ttab->relname));
+ appendStringInfo(buf, "DELETE FROM ONLY %s ",
+ quote_identifier(relname));
else
- appendStringInfo(buf, "DELETE FROM %s.%s ", quote_identifier(nspname),
- quote_identifier(ttab->relname));
+ appendStringInfo(buf, "DELETE FROM ONLY %s.%s ", quote_identifier(nspname),
+ quote_identifier(relname));
/* Generate WHERE clause for each target list item */
foreach(elt, parse->targetList)
diff --git a/src/test/regress/expected/xc_FQS_join.out b/src/test/regress/expected/xc_FQS_join.out
index aa496cc9a0..c4af46e7ae 100644
--- a/src/test/regress/expected/xc_FQS_join.out
+++ b/src/test/regress/expected/xc_FQS_join.out
@@ -484,7 +484,7 @@ explain (costs off, verbose on, nodes off) update tab1_mod set val2 = 1000 from
--------------------------------------------------------------------------------------------------------------------
Update on public.tab1_mod
Node expr: tab1_mod.val
- Remote query: UPDATE public.tab1_mod SET val2 = $2 WHERE ctid = $5 AND xc_node_id = $6
+ Remote query: UPDATE ONLY public.tab1_mod SET val2 = $2 WHERE ctid = $5 AND xc_node_id = $6
-> Nested Loop
Output: tab1_mod.val, 1000, tab1_mod.val, tab1_mod.val2, tab1_mod.ctid, tab1_mod.xc_node_id, tab2_mod.ctid
Join Filter: ((tab1_mod.val = tab2_mod.val) AND (tab1_mod.val2 = tab2_mod.val2))
@@ -501,7 +501,7 @@ explain (costs off, verbose on, nodes off) delete from tab1_mod using tab2_mod
QUERY PLAN
------------------------------------------------------------------------------------------------
Delete on public.tab1_mod
- Remote query: DELETE FROM public.tab1_mod WHERE ctid = $3 AND xc_node_id = $4
+ Remote query: DELETE FROM ONLY public.tab1_mod WHERE ctid = $3 AND xc_node_id = $4
-> Nested Loop
Output: tab1_mod.val, tab1_mod.val2, tab1_mod.ctid, tab1_mod.xc_node_id, tab2_mod.ctid
Join Filter: ((tab1_mod.val = tab2_mod.val) AND (tab1_mod.val2 = tab2_mod.val2))
@@ -518,7 +518,7 @@ explain (costs off, verbose on, nodes off) update tab1_rep set val2 = 1000 from
QUERY PLAN
-----------------------------------------------------------------------------------------------
Update on public.tab1_rep
- Remote query: UPDATE public.tab1_rep SET val2 = $2 WHERE ctid = $5
+ Remote query: UPDATE ONLY public.tab1_rep SET val2 = $2 WHERE ctid = $5
-> Nested Loop
Output: tab1_rep.val, 1000, tab1_rep.val, tab1_rep.val2, tab1_rep.ctid, tab2_rep.ctid
Join Filter: ((tab1_rep.val = tab2_rep.val) AND (tab1_rep.val2 = tab2_rep.val2))
@@ -535,7 +535,7 @@ explain (costs off, verbose on, nodes off) delete from tab1_rep using tab2_rep
QUERY PLAN
------------------------------------------------------------------------------------------
Delete on public.tab1_rep
- Remote query: DELETE FROM public.tab1_rep WHERE ctid = $3
+ Remote query: DELETE FROM ONLY public.tab1_rep WHERE ctid = $3
-> Nested Loop
Output: tab1_rep.val, tab1_rep.val2, tab1_rep.ctid, tab2_rep.ctid
Join Filter: ((tab1_rep.val = tab2_rep.val) AND (tab1_rep.val2 = tab2_rep.val2))