Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Fix issue #7674 about UPDATE SET(..), with indirection #7675

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
40 changes: 40 additions & 0 deletions src/backend/distributed/deparser/ruleutils_14.c
Original file line number Diff line number Diff line change
Expand Up @@ -3440,6 +3440,9 @@ 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
Expand Down Expand Up @@ -3562,11 +3565,48 @@ 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, " = ");
Expand Down
40 changes: 40 additions & 0 deletions src/backend/distributed/deparser/ruleutils_15.c
Original file line number Diff line number Diff line change
Expand Up @@ -3505,6 +3505,9 @@ 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
Expand Down Expand Up @@ -3627,11 +3630,48 @@ 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, " = ");
Expand Down
40 changes: 40 additions & 0 deletions src/backend/distributed/deparser/ruleutils_16.c
Original file line number Diff line number Diff line change
Expand Up @@ -3521,6 +3521,9 @@ 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
Expand Down Expand Up @@ -3643,11 +3646,48 @@ 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, " = ");
Expand Down
9 changes: 7 additions & 2 deletions src/backend/distributed/planner/insert_select_planner.c
Original file line number Diff line number Diff line change
Expand Up @@ -1071,10 +1071,15 @@ ReorderInsertSelectTargetLists(Query *originalQuery, RangeTblEntry *insertRte,
TargetEntry *newSubqueryTargetEntry = NULL;
AttrNumber originalAttrNo = get_attnum(insertRelationId,
oldInsertTargetEntry->resname);
Node *expr;

/* we need to explore the underlying expression */
expr = (Node *) oldInsertTargetEntry->expr;
expr = strip_implicit_coercions(expr);

/* see transformInsertRow() for the details */
if (IsA(oldInsertTargetEntry->expr, SubscriptingRef) ||
IsA(oldInsertTargetEntry->expr, FieldStore))
if (IsA(expr, SubscriptingRef) ||
IsA(expr, FieldStore))
{
ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg(
Expand Down
29 changes: 28 additions & 1 deletion src/test/regress/expected/distributed_types.out
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,12 @@ HINT: Use the column name to insert or update the composite type as a single va
INSERT INTO field_indirection_test_1 (int_col, ct1_col.int_1) VALUES (0, 1);
ERROR: inserting or modifying composite type fields is not supported
HINT: Use the column name to insert or update the composite type as a single value
INSERT INTO field_indirection_test_1 (int_col, ct1_col.int_1, ct1_col.int_2) SELECT 0, 1, 2;
ERROR: cannot plan distributed INSERT INTO ... SELECT query
HINT: Do not use array references and field stores on the INSERT target list.
INSERT INTO field_indirection_test_1 (int_col, ct1_col.int_1) SELECT 0, 1;
ERROR: cannot plan distributed INSERT INTO ... SELECT query
HINT: Do not use array references and field stores on the INSERT target list.
CREATE TYPE ct2 as (int_2 int, text_1 text, int_1 int);
CREATE TABLE field_indirection_test_2 (int_col int, ct2_col ct2, ct1_col ct1);
SELECT create_distributed_table('field_indirection_test_2', 'int_col');
Expand All @@ -399,10 +405,17 @@ INSERT INTO field_indirection_test_2 (ct2_col.int_1, int_col, ct2_col.text_1, ct
VALUES (0, 1, 'text1', 2), (3, 4, 'text1', 5);
ERROR: inserting or modifying composite type fields is not supported
HINT: Use the column name to insert or update the composite type as a single value
INSERT INTO field_indirection_test_2 (ct2_col.int_1, int_col, ct2_col.text_1, ct1_col.int_2)
SELECT * FROM (VALUES (0, 1, 'text1', 2), (3, 4, 'text1', 5));
ERROR: cannot plan distributed INSERT INTO ... SELECT query
HINT: Do not use array references and field stores on the INSERT target list.
-- not supported (field indirection in update)
UPDATE field_indirection_test_2 SET (ct2_col.text_1, ct1_col.int_2) = ('text2', 10) WHERE int_col=4;
ERROR: inserting or modifying composite type fields is not supported
HINT: Use the column name to insert or update the composite type as a single value
UPDATE field_indirection_test_2 SET (ct2_col.text_1, ct1_col.int_2) = (SELECT 'text2', 10) WHERE int_col=4;
ERROR: inserting or modifying composite type fields is not supported
HINT: Use the column name to insert or update the composite type as a single value
CREATE TYPE two_ints as (if1 int, if2 int);
CREATE DOMAIN domain AS two_ints CHECK ((VALUE).if1 > 0);
CREATE TABLE domain_indirection_test (f1 int, f3 domain, domain_array domain[]);
Expand All @@ -416,22 +429,36 @@ SELECT create_distributed_table('domain_indirection_test', 'f1');
INSERT INTO domain_indirection_test (f1,f3.if1, f3.if2) VALUES (0, 1, 2);
ERROR: inserting or modifying composite type fields is not supported
HINT: Use the column name to insert or update the composite type as a single value
INSERT INTO domain_indirection_test (f1,f3.if1, f3.if2) SELECT 0, 1, 2;
ERROR: cannot plan distributed INSERT INTO ... SELECT query
HINT: Do not use array references and field stores on the INSERT target list.
INSERT INTO domain_indirection_test (f1,f3.if1) VALUES (0, 1);
ERROR: inserting or modifying composite type fields is not supported
HINT: Use the column name to insert or update the composite type as a single value
INSERT INTO domain_indirection_test (f1,f3.if1) SELECT 0, 1;
ERROR: cannot plan distributed INSERT INTO ... SELECT query
HINT: Do not use array references and field stores on the INSERT target list.
UPDATE domain_indirection_test SET domain_array[0].if2 = 5;
ERROR: inserting or modifying composite type fields is not supported
HINT: Use the column name to insert or update the composite type as a single value
UPDATE domain_indirection_test SET domain_array[0].if2 = (SELECT 5);
ERROR: inserting or modifying composite type fields is not supported
HINT: Use the column name to insert or update the composite type as a single value
-- below are supported as we don't do any field indirection
INSERT INTO field_indirection_test_2 (ct2_col, int_col, ct1_col)
VALUES ('(1, "text1", 2)', 3, '(4, 5)'), ('(6, "text2", 7)', 8, '(9, 10)');
INSERT INTO field_indirection_test_2 (ct2_col, int_col, ct1_col)
SELECT * FROM (VALUES ('(1, "text1", 2)'::ct2, 3, '(4, 5)'::ct1), ('(6, "text2", 7)'::ct2, 8, '(9, 10)'::ct1));
UPDATE field_indirection_test_2 SET (ct2_col, ct1_col) = ('(10, "text10", 20)', '(40, 50)') WHERE int_col=8;
UPDATE field_indirection_test_2 SET (ct2_col, ct1_col) = (SELECT '(10, "text10", 20)'::ct2, '(40, 50)'::ct1) WHERE int_col=8;
SELECT * FROM field_indirection_test_2 ORDER BY 1,2,3;
int_col | ct2_col | ct1_col
---------------------------------------------------------------------
3 | (1," text1",2) | (4,5)
3 | (1," text1",2) | (4,5)
8 | (10," text10",20) | (40,50)
(2 rows)
8 | (10," text10",20) | (40,50)
(4 rows)

-- test different ddl propagation modes
SET citus.create_object_propagation TO deferred;
Expand Down
Loading
Loading