From dcdaaaa88dfd4bdc9b31cf308a2626fa5e47c7cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Sun, 2 Mar 2025 08:00:02 +0100 Subject: [PATCH] WIP reorder target list All OK for basic UPDATE multi SELECT --- .../distributed/deparser/citus_ruleutils.c | 70 ++++ .../distributed/deparser/ruleutils_16.c | 72 ++--- src/include/distributed/citus_ruleutils.h | 3 + src/test/regress/expected/indirections.out | 301 ++++++++++++------ src/test/regress/sql/indirections.sql | 95 +++--- 5 files changed, 359 insertions(+), 182 deletions(-) diff --git a/src/backend/distributed/deparser/citus_ruleutils.c b/src/backend/distributed/deparser/citus_ruleutils.c index d590495a6..a7f19c869 100644 --- a/src/backend/distributed/deparser/citus_ruleutils.c +++ b/src/backend/distributed/deparser/citus_ruleutils.c @@ -1715,3 +1715,73 @@ RoleSpecString(RoleSpec *spec, bool withQuoteIdentifier) } } } + + +/* + * list_sort comparator to sort target list by paramid (in MULTIEXPR) + * Intended for indirection management: UPDATE SET () = (SELECT ) + */ +int +target_list_cmp(const ListCell *a, const ListCell *b) +{ + TargetEntry *tleA = lfirst(a); + TargetEntry *tleB = lfirst(b); + + if (IsA(tleA->expr, Param) && IsA(tleB->expr, Param)) + { + int la = ((Param *) tleA->expr)->paramid; + int lb = ((Param *) tleB->expr)->paramid; + return (la > lb) - (la < lb); + } + else if ((IsA(tleA->expr, Param) && IsA(tleB->expr, SubLink)) || + (IsA(tleA->expr, SubLink) && IsA(tleB->expr, Param)) || + (IsA(tleA->expr, SubLink) && IsA(tleB->expr, SubLink))) + { + return -1; + } + else + { + elog(ERROR, "unexpected nodes"); + } +} + + +/* + * Recursively search an expression for a Param and return its paramid + * Intended for indirection management: UPDATE SET () = (SELECT ) + * Does not cover all options but those supported by Citus. + */ +int +GetParamId(Node *expr) +{ + int paramid = 0; + + if (expr == NULL) + { + return paramid; + } + + /* If it's a Param, return its attnum */ + if (IsA(expr, Param)) + { + Param *param = (Param *) expr; + paramid = param->paramid; + } + /* If it's a FuncExpr, search in arguments */ + else if (IsA(expr, FuncExpr)) + { + FuncExpr *func = (FuncExpr *) expr; + ListCell *lc; + + foreach(lc, func->args) + { + paramid = GetParamId((Node *) lfirst(lc)); + if (paramid != 0) + { + break; /* Stop at the first valid paramid */ + } + } + } + + return paramid; +} diff --git a/src/backend/distributed/deparser/ruleutils_16.c b/src/backend/distributed/deparser/ruleutils_16.c index 027fe3242..91eeb4b76 100644 --- a/src/backend/distributed/deparser/ruleutils_16.c +++ b/src/backend/distributed/deparser/ruleutils_16.c @@ -3525,9 +3525,6 @@ get_update_query_targetlist_def(Query *query, List *targetList, SubLink *cur_ma_sublink; List *ma_sublinks; - AttrNumber previous_attnum = InvalidAttrNumber; - int paramid_increment = 0; - /* * Prepare to deal with MULTIEXPR assignments: collect the source SubLinks * into a list. We expect them to appear, in ID order, in resjunk tlist @@ -3536,13 +3533,21 @@ get_update_query_targetlist_def(Query *query, List *targetList, ma_sublinks = NIL; if (query->hasSubLinks) /* else there can't be any */ { + bool saw_junk = false; + bool need_to_sort_target_list = false; + int previous_paramid = 0; + foreach(l, targetList) { TargetEntry *tle = (TargetEntry *) lfirst(l); + // elog(WARNING, "TOP node to string: %s", nodeToString(tle->expr)); + // elog(WARNING, "TOP node type: %d", (int) nodeTag(tle->expr)); + if (tle->resjunk && IsA(tle->expr, SubLink)) { SubLink *sl = (SubLink *) tle->expr; + saw_junk = true; if (sl->subLinkType == MULTIEXPR_SUBLINK) { @@ -3550,7 +3555,30 @@ get_update_query_targetlist_def(Query *query, List *targetList, Assert(sl->subLinkId == list_length(ma_sublinks)); } } + else if (!tle->resjunk) + { + int paramid = 0; + if (saw_junk) + elog(ERROR, "out of order target list"); + + paramid = GetParamId((Node *) tle->expr); + if (paramid < previous_paramid) + need_to_sort_target_list = true; + + previous_paramid = paramid; + } } + + /* + * reorder the target list on left side of the update: + * SET () = (SELECT ) + * reordering the SELECT side only does not work, consider a case like: + * SET (col_1, col3) = (SELECT 1, 3), (col_2) = (SELECT 2) + * Then default order will lead to: + * SET (col_1, col2) = (SELECT 1, 3), (col_3) = (SELECT 2) + */ + if (need_to_sort_target_list) + list_sort(targetList, target_list_cmp); } next_ma_cell = list_head(ma_sublinks); cur_ma_sublink = NULL; @@ -3650,54 +3678,18 @@ get_update_query_targetlist_def(Query *query, List *targetList, */ if (cur_ma_sublink != NULL) { - AttrNumber attnum = InvalidAttrNumber; - if (IsA(expr, Param)) - { - Param *param = (Param *) expr; - attnum = param->paramid + paramid_increment; - } - else if (IsA(expr, FuncExpr)) - { - FuncExpr *func = (FuncExpr *) expr; - ListCell *lc; - - /* Iterate through the arguments of the FuncExpr */ - foreach(lc, func->args) - { - Node *arg = (Node *) lfirst(lc); - - /* Check if the argument is a PARAM node */ - if (IsA(arg, Param)) - { - Param *param = (Param *) arg; - attnum = param->paramid + paramid_increment; - - break; /* Exit loop once we find the PARAM node */ - } - } - } - - if (previous_attnum >= attnum) - ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg( - "cannot plan distributed UPDATE SET (..) = (SELECT ...) query when not sorted by physical order"), - errhint("Sort the columns on the left side by physical order."))); - - previous_attnum = attnum; - if (--remaining_ma_columns > 0) continue; /* not the last column of multiassignment */ - appendStringInfoChar(buf, ')'); expr = (Node *) cur_ma_sublink; cur_ma_sublink = NULL; - paramid_increment = previous_attnum; } appendStringInfoString(buf, " = "); get_rule_expr(expr, context, false); } + elog(DEBUG4, "rewriten query: %s", buf->data); } /* ---------- diff --git a/src/include/distributed/citus_ruleutils.h b/src/include/distributed/citus_ruleutils.h index 3a9c36482..9089ca3a7 100644 --- a/src/include/distributed/citus_ruleutils.h +++ b/src/include/distributed/citus_ruleutils.h @@ -60,5 +60,8 @@ extern char * generate_operator_name(Oid operid, Oid arg1, Oid arg2); extern List * getOwnedSequences_internal(Oid relid, AttrNumber attnum, char deptype); extern void AppendOptionListToString(StringInfo stringData, List *options); +extern int GetParamId(Node *expr); +extern int target_list_cmp(const ListCell *a, const ListCell *b); + #endif /* CITUS_RULEUTILS_H */ diff --git a/src/test/regress/expected/indirections.out b/src/test/regress/expected/indirections.out index 20bd73d2b..115f5a7b4 100644 --- a/src/test/regress/expected/indirections.out +++ b/src/test/regress/expected/indirections.out @@ -126,210 +126,303 @@ RETURNING *; (4 rows) UPDATE test_ref_indirection - SET (col_bool, col_date) = (select true, '1970-01-01'::date) - , (col_int, col_text) = (select 1, 'still ok') + SET (col_bool, col_date) = (select false, '1971-01-01'::date) + , (col_int, col_text) = (select 2, '2 ok') RETURNING *; id | col_bool | col_date | col_int | col_text --------------------------------------------------------------------- - 1 | t | 01-01-1970 | 1 | still ok - 2 | t | 01-01-1970 | 1 | still ok - 3 | t | 01-01-1970 | 1 | still ok - 4 | t | 01-01-1970 | 1 | still ok + 1 | f | 01-01-1971 | 2 | 2 ok + 2 | f | 01-01-1971 | 2 | 2 ok + 3 | f | 01-01-1971 | 2 | 2 ok + 4 | f | 01-01-1971 | 2 | 2 ok (4 rows) UPDATE test_dist_indirection - SET (col_bool, col_date) = (select true, '1970-01-01'::date) - , (col_int, col_text) = (select 1, 'still ok') + SET (col_bool, col_date) = (select false, '1971-01-01'::date) + , (col_int, col_text) = (select 2, '2 ok') RETURNING *; id | col_bool | col_date | col_int | col_text --------------------------------------------------------------------- - 1 | t | 01-01-1970 | 1 | still ok - 2 | t | 01-01-1970 | 1 | still ok - 3 | t | 01-01-1970 | 1 | still ok - 4 | t | 01-01-1970 | 1 | still ok + 1 | f | 01-01-1971 | 2 | 2 ok + 2 | f | 01-01-1971 | 2 | 2 ok + 3 | f | 01-01-1971 | 2 | 2 ok + 4 | f | 01-01-1971 | 2 | 2 ok (4 rows) UPDATE test_ref_indirection - SET (col_bool, col_int) = (select true, 1) - , (col_text) = (select 'ok') + SET (col_bool, col_int) = (select true, 3) + , (col_text) = (select '3 ok') RETURNING *; id | col_bool | col_date | col_int | col_text --------------------------------------------------------------------- - 1 | t | 01-01-1970 | 1 | ok - 2 | t | 01-01-1970 | 1 | ok - 3 | t | 01-01-1970 | 1 | ok - 4 | t | 01-01-1970 | 1 | ok + 1 | t | 01-01-1971 | 3 | 3 ok + 2 | t | 01-01-1971 | 3 | 3 ok + 3 | t | 01-01-1971 | 3 | 3 ok + 4 | t | 01-01-1971 | 3 | 3 ok (4 rows) -SELECT * FROM test_ref_indirection ORDER BY id; +UPDATE test_dist_indirection + SET (col_bool, col_int) = (select true, 3) + , (col_text) = (select '3 ok') +RETURNING *; id | col_bool | col_date | col_int | col_text --------------------------------------------------------------------- - 1 | t | 01-01-1970 | 1 | ok - 2 | t | 01-01-1970 | 1 | ok - 3 | t | 01-01-1970 | 1 | ok - 4 | t | 01-01-1970 | 1 | ok + 1 | t | 01-01-1971 | 3 | 3 ok + 2 | t | 01-01-1971 | 3 | 3 ok + 3 | t | 01-01-1971 | 3 | 3 ok + 4 | t | 01-01-1971 | 3 | 3 ok (4 rows) -SELECT * FROM test_dist_indirection ORDER BY id; - id | col_bool | col_date | col_int | col_text ---------------------------------------------------------------------- - 1 | t | 01-01-1970 | 1 | still ok - 2 | t | 01-01-1970 | 1 | still ok - 3 | t | 01-01-1970 | 1 | still ok - 4 | t | 01-01-1970 | 1 | still ok -(4 rows) - --- but those should not: +-- but those should work since 13.X UPDATE test_ref_indirection SET (col_date, col_text, col_int, col_bool) - = (SELECT '1970-06-06'::date, 'not ok', 2, false) + = (SELECT '1972-01-01'::date, '4 ok', 4, false) RETURNING *; -ERROR: cannot plan distributed UPDATE SET (..) = (SELECT ...) query when not sorted by physical order -HINT: Sort the columns on the left side by physical order. + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 1 | f | 01-01-1972 | 4 | 4 ok + 2 | f | 01-01-1972 | 4 | 4 ok + 3 | f | 01-01-1972 | 4 | 4 ok + 4 | f | 01-01-1972 | 4 | 4 ok +(4 rows) + UPDATE test_dist_indirection SET (col_date, col_text, col_int, col_bool) - = (SELECT '1970-06-06'::date, 'not ok', 2, false) + = (SELECT '1972-01-01'::date, '4 ok', 4, false) RETURNING *; -ERROR: cannot plan distributed UPDATE SET (..) = (SELECT ...) query when not sorted by physical order -HINT: Sort the columns on the left side by physical order. + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 1 | f | 01-01-1972 | 4 | 4 ok + 2 | f | 01-01-1972 | 4 | 4 ok + 3 | f | 01-01-1972 | 4 | 4 ok + 4 | f | 01-01-1972 | 4 | 4 ok +(4 rows) + UPDATE test_ref_indirection - SET (col_int, col_text) = (select 2, 'not ok') + SET (col_int, col_text) = (select 5, '5 ok') + , (col_bool) = (select true) +RETURNING *; + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 1 | t | 01-01-1972 | 5 | 5 ok + 2 | t | 01-01-1972 | 5 | 5 ok + 3 | t | 01-01-1972 | 5 | 5 ok + 4 | t | 01-01-1972 | 5 | 5 ok +(4 rows) + +UPDATE test_dist_indirection + SET (col_int, col_text) = (select 5, '5 ok') + , (col_bool) = (select true) +RETURNING *; + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 1 | t | 01-01-1972 | 5 | 5 ok + 2 | t | 01-01-1972 | 5 | 5 ok + 3 | t | 01-01-1972 | 5 | 5 ok + 4 | t | 01-01-1972 | 5 | 5 ok +(4 rows) + +UPDATE test_ref_indirection + SET (col_int, col_date) = (select 6, '1973-01-01'::date) + , (col_text, col_bool) = (select '6 ok', false) +RETURNING *; + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 1 | f | 01-01-1973 | 6 | 6 ok + 2 | f | 01-01-1973 | 6 | 6 ok + 3 | f | 01-01-1973 | 6 | 6 ok + 4 | f | 01-01-1973 | 6 | 6 ok +(4 rows) + +UPDATE test_dist_indirection + SET (col_int, col_date) = (select 6, '1973-01-01'::date) + , (col_text, col_bool) = (select '6 ok', false) +RETURNING *; + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 1 | f | 01-01-1973 | 6 | 6 ok + 2 | f | 01-01-1973 | 6 | 6 ok + 3 | f | 01-01-1973 | 6 | 6 ok + 4 | f | 01-01-1973 | 6 | 6 ok +(4 rows) + +UPDATE test_ref_indirection + SET (col_int, col_date, col_text) = (select 7, '1974-01-01'::date, '7 ok') + , (col_bool) = (select true) +RETURNING *; + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 1 | t | 01-01-1974 | 7 | 7 ok + 2 | t | 01-01-1974 | 7 | 7 ok + 3 | t | 01-01-1974 | 7 | 7 ok + 4 | t | 01-01-1974 | 7 | 7 ok +(4 rows) + +UPDATE test_dist_indirection + SET (col_int, col_date, col_text) = (select 7, '1974-01-01'::date, '7 ok') + , (col_bool) = (select true) +RETURNING *; + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 1 | t | 01-01-1974 | 7 | 7 ok + 2 | t | 01-01-1974 | 7 | 7 ok + 3 | t | 01-01-1974 | 7 | 7 ok + 4 | t | 01-01-1974 | 7 | 7 ok +(4 rows) + +UPDATE test_ref_indirection + SET (col_date, col_text) = (select '1975-01-01'::date, '8 ok') + , (col_int) = (select 8) , (col_bool) = (select false) RETURNING *; -ERROR: cannot plan distributed UPDATE SET (..) = (SELECT ...) query when not sorted by physical order -HINT: Sort the columns on the left side by physical order. -UPDATE test_ref_indirection - SET (col_int, col_date) = (select 2, '1970-06-06'::date) - , (col_text, col_bool) = (select 'not ok', false) -RETURNING *; -ERROR: cannot plan distributed UPDATE SET (..) = (SELECT ...) query when not sorted by physical order -HINT: Sort the columns on the left side by physical order. + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 1 | f | 01-01-1975 | 8 | 8 ok + 2 | f | 01-01-1975 | 8 | 8 ok + 3 | f | 01-01-1975 | 8 | 8 ok + 4 | f | 01-01-1975 | 8 | 8 ok +(4 rows) + UPDATE test_dist_indirection - SET (col_int, col_date) = (select 2, '1970-06-06'::date) - , (col_text, col_bool) = (select 'not ok', false) + SET (col_date, col_text) = (select '1975-01-01'::date, '8 ok') + , (col_int) = (select 8) + , (col_bool) = (select false) RETURNING *; -ERROR: cannot plan distributed UPDATE SET (..) = (SELECT ...) query when not sorted by physical order -HINT: Sort the columns on the left side by physical order. + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 1 | f | 01-01-1975 | 8 | 8 ok + 2 | f | 01-01-1975 | 8 | 8 ok + 3 | f | 01-01-1975 | 8 | 8 ok + 4 | f | 01-01-1975 | 8 | 8 ok +(4 rows) + -- -- more restrictive ones, just in case we miss a wrong value -- -- those should work UPDATE test_ref_indirection - SET (col_bool, col_text) = (SELECT true, 'ok') + SET (col_bool, col_text) = (SELECT true, '9 ok') RETURNING *; id | col_bool | col_date | col_int | col_text --------------------------------------------------------------------- - 1 | t | 01-01-1970 | 1 | ok - 2 | t | 01-01-1970 | 1 | ok - 3 | t | 01-01-1970 | 1 | ok - 4 | t | 01-01-1970 | 1 | ok + 1 | t | 01-01-1975 | 8 | 9 ok + 2 | t | 01-01-1975 | 8 | 9 ok + 3 | t | 01-01-1975 | 8 | 9 ok + 4 | t | 01-01-1975 | 8 | 9 ok (4 rows) UPDATE test_dist_indirection - SET (col_bool, col_text) = (SELECT true, 'ok') + SET (col_bool, col_text) = (SELECT true, '9 ok') RETURNING *; id | col_bool | col_date | col_int | col_text --------------------------------------------------------------------- - 1 | t | 01-01-1970 | 1 | ok - 2 | t | 01-01-1970 | 1 | ok - 3 | t | 01-01-1970 | 1 | ok - 4 | t | 01-01-1970 | 1 | ok + 1 | t | 01-01-1975 | 8 | 9 ok + 2 | t | 01-01-1975 | 8 | 9 ok + 3 | t | 01-01-1975 | 8 | 9 ok + 4 | t | 01-01-1975 | 8 | 9 ok (4 rows) UPDATE test_ref_indirection - SET (col_bool, col_text) = (SELECT true, 'ok') + SET (col_bool, col_text) = (SELECT false, '10 ok') WHERE id = 1 RETURNING *; id | col_bool | col_date | col_int | col_text --------------------------------------------------------------------- - 1 | t | 01-01-1970 | 1 | ok + 1 | f | 01-01-1975 | 8 | 10 ok (1 row) UPDATE test_dist_indirection - SET (col_bool, col_text) = (SELECT true, 'ok') + SET (col_bool, col_text) = (SELECT false, '10 ok') WHERE id = 1 RETURNING *; id | col_bool | col_date | col_int | col_text --------------------------------------------------------------------- - 1 | t | 01-01-1970 | 1 | ok + 1 | f | 01-01-1975 | 8 | 10 ok (1 row) -SELECT * FROM test_ref_indirection ORDER BY id; +UPDATE test_ref_indirection + SET (col_text, col_bool) = (SELECT '11 ok', true) +RETURNING *; id | col_bool | col_date | col_int | col_text --------------------------------------------------------------------- - 1 | t | 01-01-1970 | 1 | ok - 2 | t | 01-01-1970 | 1 | ok - 3 | t | 01-01-1970 | 1 | ok - 4 | t | 01-01-1970 | 1 | ok + 1 | t | 01-01-1975 | 8 | 11 ok + 2 | t | 01-01-1975 | 8 | 11 ok + 3 | t | 01-01-1975 | 8 | 11 ok + 4 | t | 01-01-1975 | 8 | 11 ok (4 rows) -SELECT * FROM test_dist_indirection ORDER BY id; +UPDATE test_dist_indirection + SET (col_text, col_bool) = (SELECT '11 ok', true) +RETURNING *; id | col_bool | col_date | col_int | col_text --------------------------------------------------------------------- - 1 | t | 01-01-1970 | 1 | ok - 2 | t | 01-01-1970 | 1 | ok - 3 | t | 01-01-1970 | 1 | ok - 4 | t | 01-01-1970 | 1 | ok + 1 | t | 01-01-1975 | 8 | 11 ok + 2 | t | 01-01-1975 | 8 | 11 ok + 3 | t | 01-01-1975 | 8 | 11 ok + 4 | t | 01-01-1975 | 8 | 11 ok (4 rows) --- those should not UPDATE test_ref_indirection - SET (col_text, col_bool) = (SELECT 'not ok', false) -RETURNING *; -ERROR: cannot plan distributed UPDATE SET (..) = (SELECT ...) query when not sorted by physical order -HINT: Sort the columns on the left side by physical order. -UPDATE test_dist_indirection - SET (col_text, col_bool) = (SELECT 'not ok', false) -RETURNING *; -ERROR: cannot plan distributed UPDATE SET (..) = (SELECT ...) query when not sorted by physical order -HINT: Sort the columns on the left side by physical order. -UPDATE test_ref_indirection - SET (col_text, col_bool) = (SELECT 'not ok', false) + SET (col_text, col_bool) = (SELECT '12 ok', false) WHERE id = 2 RETURNING *; -ERROR: cannot plan distributed UPDATE SET (..) = (SELECT ...) query when not sorted by physical order -HINT: Sort the columns on the left side by physical order. + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 2 | f | 01-01-1975 | 8 | 12 ok +(1 row) + UPDATE test_dist_indirection - SET (col_text, col_bool) = (SELECT 'not ok', false) + SET (col_text, col_bool) = (SELECT '12 ok', false) WHERE id = 2 RETURNING *; -ERROR: cannot plan distributed UPDATE SET (..) = (SELECT ...) query when not sorted by physical order -HINT: Sort the columns on the left side by physical order. + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 2 | f | 01-01-1975 | 8 | 12 ok +(1 row) + -- several updates in CTE shoult not work with qq3 as ( update test_ref_indirection SET (col_text, col_bool) - = (SELECT 'full', true) + = (SELECT '13', true) where id = 3 returning * ), qq4 as ( update test_ref_indirection SET (col_text, col_bool) - = (SELECT 'fully', true) + = (SELECT '14', false) where id = 4 returning * ) select * from qq3 union all select * from qq4; -ERROR: cannot plan distributed UPDATE SET (..) = (SELECT ...) query when not sorted by physical order -HINT: Sort the columns on the left side by physical order. + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 3 | t | 01-01-1975 | 8 | 13 + 4 | f | 01-01-1975 | 8 | 14 +(2 rows) + with qq3 as ( update test_dist_indirection SET (col_text, col_bool) - = (SELECT 'full', true) + = (SELECT '13', true) where id = 3 returning * ), qq4 as ( update test_dist_indirection SET (col_text, col_bool) - = (SELECT 'fully', true) + = (SELECT '14', false) where id = 4 returning * ) select * from qq3 union all select * from qq4; -ERROR: cannot plan distributed UPDATE SET (..) = (SELECT ...) query when not sorted by physical order -HINT: Sort the columns on the left side by physical order. + id | col_bool | col_date | col_int | col_text +--------------------------------------------------------------------- + 3 | t | 01-01-1975 | 8 | 13 + 4 | f | 01-01-1975 | 8 | 14 +(2 rows) + DROP TABLE test_dist_indirection; DROP TABLE test_dist_indirection_new; DROP TABLE test_ref_indirection; @@ -349,10 +442,6 @@ SELECT create_reference_table('indirections.update_test'); UPDATE update_test SET (b,a) = (select a,b from update_test where b = 41 and c = 'car') WHERE a = 100 AND b = 20; -ERROR: cannot plan distributed UPDATE SET (..) = (SELECT ...) query when not sorted by physical order -HINT: Sort the columns on the left side by physical order. -- https://github.com/citusdata/citus/pull/5692 +set client_min_messages to ERROR; DROP SCHEMA indirections CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to table update_test -drop cascades to table update_test_750006 diff --git a/src/test/regress/sql/indirections.sql b/src/test/regress/sql/indirections.sql index 73ff78b71..598124208 100644 --- a/src/test/regress/sql/indirections.sql +++ b/src/test/regress/sql/indirections.sql @@ -73,43 +73,69 @@ UPDATE test_dist_indirection RETURNING *; UPDATE test_ref_indirection - SET (col_bool, col_date) = (select true, '1970-01-01'::date) - , (col_int, col_text) = (select 1, 'still ok') + SET (col_bool, col_date) = (select false, '1971-01-01'::date) + , (col_int, col_text) = (select 2, '2 ok') RETURNING *; UPDATE test_dist_indirection - SET (col_bool, col_date) = (select true, '1970-01-01'::date) - , (col_int, col_text) = (select 1, 'still ok') + SET (col_bool, col_date) = (select false, '1971-01-01'::date) + , (col_int, col_text) = (select 2, '2 ok') RETURNING *; UPDATE test_ref_indirection - SET (col_bool, col_int) = (select true, 1) - , (col_text) = (select 'ok') + SET (col_bool, col_int) = (select true, 3) + , (col_text) = (select '3 ok') +RETURNING *; +UPDATE test_dist_indirection + SET (col_bool, col_int) = (select true, 3) + , (col_text) = (select '3 ok') RETURNING *; -SELECT * FROM test_ref_indirection ORDER BY id; -SELECT * FROM test_dist_indirection ORDER BY id; - --- but those should not: +-- but those should work since 13.X UPDATE test_ref_indirection SET (col_date, col_text, col_int, col_bool) - = (SELECT '1970-06-06'::date, 'not ok', 2, false) + = (SELECT '1972-01-01'::date, '4 ok', 4, false) RETURNING *; UPDATE test_dist_indirection SET (col_date, col_text, col_int, col_bool) - = (SELECT '1970-06-06'::date, 'not ok', 2, false) + = (SELECT '1972-01-01'::date, '4 ok', 4, false) RETURNING *; UPDATE test_ref_indirection - SET (col_int, col_text) = (select 2, 'not ok') + SET (col_int, col_text) = (select 5, '5 ok') + , (col_bool) = (select true) +RETURNING *; +UPDATE test_dist_indirection + SET (col_int, col_text) = (select 5, '5 ok') + , (col_bool) = (select true) +RETURNING *; + +UPDATE test_ref_indirection + SET (col_int, col_date) = (select 6, '1973-01-01'::date) + , (col_text, col_bool) = (select '6 ok', false) +RETURNING *; +UPDATE test_dist_indirection + SET (col_int, col_date) = (select 6, '1973-01-01'::date) + , (col_text, col_bool) = (select '6 ok', false) +RETURNING *; + +UPDATE test_ref_indirection + SET (col_int, col_date, col_text) = (select 7, '1974-01-01'::date, '7 ok') + , (col_bool) = (select true) +RETURNING *; +UPDATE test_dist_indirection + SET (col_int, col_date, col_text) = (select 7, '1974-01-01'::date, '7 ok') + , (col_bool) = (select true) +RETURNING *; + +UPDATE test_ref_indirection + SET (col_date, col_text) = (select '1975-01-01'::date, '8 ok') + , (col_int) = (select 8) , (col_bool) = (select false) RETURNING *; -UPDATE test_ref_indirection - SET (col_int, col_date) = (select 2, '1970-06-06'::date) - , (col_text, col_bool) = (select 'not ok', false) -RETURNING *; UPDATE test_dist_indirection - SET (col_int, col_date) = (select 2, '1970-06-06'::date) - , (col_text, col_bool) = (select 'not ok', false) + SET (col_date, col_text) = (select '1975-01-01'::date, '8 ok') + , (col_int) = (select 8) + , (col_bool) = (select false) RETURNING *; -- @@ -117,38 +143,34 @@ RETURNING *; -- -- those should work UPDATE test_ref_indirection - SET (col_bool, col_text) = (SELECT true, 'ok') + SET (col_bool, col_text) = (SELECT true, '9 ok') RETURNING *; UPDATE test_dist_indirection - SET (col_bool, col_text) = (SELECT true, 'ok') + SET (col_bool, col_text) = (SELECT true, '9 ok') RETURNING *; UPDATE test_ref_indirection - SET (col_bool, col_text) = (SELECT true, 'ok') + SET (col_bool, col_text) = (SELECT false, '10 ok') WHERE id = 1 RETURNING *; UPDATE test_dist_indirection - SET (col_bool, col_text) = (SELECT true, 'ok') + SET (col_bool, col_text) = (SELECT false, '10 ok') WHERE id = 1 RETURNING *; -SELECT * FROM test_ref_indirection ORDER BY id; -SELECT * FROM test_dist_indirection ORDER BY id; - --- those should not UPDATE test_ref_indirection - SET (col_text, col_bool) = (SELECT 'not ok', false) + SET (col_text, col_bool) = (SELECT '11 ok', true) RETURNING *; UPDATE test_dist_indirection - SET (col_text, col_bool) = (SELECT 'not ok', false) + SET (col_text, col_bool) = (SELECT '11 ok', true) RETURNING *; UPDATE test_ref_indirection - SET (col_text, col_bool) = (SELECT 'not ok', false) + SET (col_text, col_bool) = (SELECT '12 ok', false) WHERE id = 2 RETURNING *; UPDATE test_dist_indirection - SET (col_text, col_bool) = (SELECT 'not ok', false) + SET (col_text, col_bool) = (SELECT '12 ok', false) WHERE id = 2 RETURNING *; @@ -156,14 +178,14 @@ RETURNING *; with qq3 as ( update test_ref_indirection SET (col_text, col_bool) - = (SELECT 'full', true) + = (SELECT '13', true) where id = 3 returning * ), qq4 as ( update test_ref_indirection SET (col_text, col_bool) - = (SELECT 'fully', true) + = (SELECT '14', false) where id = 4 returning * ) @@ -171,14 +193,14 @@ select * from qq3 union all select * from qq4; with qq3 as ( update test_dist_indirection SET (col_text, col_bool) - = (SELECT 'full', true) + = (SELECT '13', true) where id = 3 returning * ), qq4 as ( update test_dist_indirection SET (col_text, col_bool) - = (SELECT 'fully', true) + = (SELECT '14', false) where id = 4 returning * ) @@ -201,5 +223,6 @@ SET (b,a) = (select a,b from update_test where b = 41 and c = 'car') WHERE a = 100 AND b = 20; -- https://github.com/citusdata/citus/pull/5692 - +set client_min_messages to ERROR; DROP SCHEMA indirections CASCADE; +