From 7d2a5be3127d121033ae9dcfb8f278d69affcb03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Mon, 19 Aug 2024 19:20:00 +0200 Subject: [PATCH] Add more test for target list indirections Adding similar indirection test to existing ones but using a sublink. i.e. INSERT INTO .... SELECT and UPDATE ... SELECT are added. Queries of the form: ``` ... SET (a, b) = (SELECT '1', '2') ... SET (b, a) = (SELECT '2', '1') ``` Should do the same thing, but currently the order of the attributes in `SET (...)` as rewriten for pushdown is only based on the physical ordering of the attributes in the relation. This leads to several subtle problems including situation where a DROPped then reADDed attributes will change its placement in the attribute list. There are maybe more tests to add in other situation where a SET (MULTIEXPR) is possible, though some alternatives are not supported yet by citus, for example: `(INSERT .. ON CONFLICT SET (a,b).....` --- .../regress/expected/distributed_types.out | 1 + .../regress/expected/multi_modifications.out | 30 +++++++++++++++++++ .../expected/multi_mx_modifications.out | 21 +++++++++++++ src/test/regress/sql/distributed_types.sql | 4 +++ src/test/regress/sql/multi_modifications.sql | 18 +++++++++++ .../regress/sql/multi_mx_modifications.sql | 15 ++++++++++ 6 files changed, 89 insertions(+) diff --git a/src/test/regress/expected/distributed_types.out b/src/test/regress/expected/distributed_types.out index 703614d61..68b952aae 100644 --- a/src/test/regress/expected/distributed_types.out +++ b/src/test/regress/expected/distributed_types.out @@ -444,6 +444,7 @@ HINT: Use the column name to insert or update the composite type as a single va 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 +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)'); diff --git a/src/test/regress/expected/multi_modifications.out b/src/test/regress/expected/multi_modifications.out index 93f6c8c45..1a2c01a4d 100644 --- a/src/test/regress/expected/multi_modifications.out +++ b/src/test/regress/expected/multi_modifications.out @@ -330,6 +330,12 @@ UPDATE limit_orders SET (kind, limit_price) = ('buy', 999) WHERE id = 246 RETURN 246 | GM | 30 | Mon Jul 02 16:32:15 2007 | buy | 999 (1 row) +UPDATE limit_orders SET (kind, limit_price) = (SELECT 'buy'::order_side, 999) WHERE id = 246 RETURNING *; + id | symbol | bidder_id | placed_at | kind | limit_price +--------------------------------------------------------------------- + 246 | GM | 30 | Mon Jul 02 16:32:15 2007 | buy | 999 +(1 row) + -- Test that on unique contraint violations, we fail fast \set VERBOSITY terse INSERT INTO limit_orders VALUES (275, 'ADR', 140, '2007-07-02 16:32:15', 'sell', 43.67); @@ -435,6 +441,8 @@ UPDATE limit_orders SET limit_price = 0.00 FROM bidders -- should succeed with a CTE WITH deleted_orders AS (INSERT INTO limit_orders VALUES (399, 'PDR', 14, '2017-07-02 16:32:15', 'sell', 43)) UPDATE limit_orders SET symbol = 'GM'; +WITH deleted_orders AS (INSERT INTO limit_orders SELECT 400, 'PDR', 14, '2017-07-02 16:32:15', 'sell', 43) +UPDATE limit_orders SET symbol = 'GM'; SELECT symbol, bidder_id FROM limit_orders WHERE id = 246; symbol | bidder_id --------------------------------------------------------------------- @@ -927,6 +935,17 @@ SELECT * FROM summary_table ORDER BY id; 2 | 400 | 450.0000000000000000 | | (2 rows) +--- TODO this one is a silent corruption: +-- UPDATE summary_table SET (average_value, min_value) = +-- (SELECT avg(value), min(value) FROM raw_table WHERE id = 2) +-- WHERE id = 2; +SELECT * FROM summary_table ORDER BY id; + id | min_value | average_value | count | uniques +--------------------------------------------------------------------- + 1 | | 200.0000000000000000 | | + 2 | 400 | 450.0000000000000000 | | +(2 rows) + UPDATE summary_table SET min_value = 100 WHERE id IN (SELECT id FROM raw_table WHERE id = 1 and value > 100) AND id = 1; SELECT * FROM summary_table ORDER BY id; @@ -1103,6 +1122,17 @@ SELECT * FROM reference_summary_table ORDER BY id; 2 | 400 | 450.0000000000000000 | | (2 rows) +--- TODO this one is a silent corruption: +-- UPDATE reference_summary_table SET (average_value, min_value) = +-- (SELECT avg(value), min(value) FROM reference_raw_table WHERE id = 2) +-- WHERE id = 2; +SELECT * FROM reference_summary_table ORDER BY id; + id | min_value | average_value | count | uniques +--------------------------------------------------------------------- + 1 | | 200.0000000000000000 | | + 2 | 400 | 450.0000000000000000 | | +(2 rows) + -- no need partition colum equalities on reference tables UPDATE reference_summary_table SET (count) = (SELECT id AS inner_id FROM reference_raw_table WHERE value = 500) diff --git a/src/test/regress/expected/multi_mx_modifications.out b/src/test/regress/expected/multi_mx_modifications.out index 9e053d3f2..b401a67e3 100644 --- a/src/test/regress/expected/multi_mx_modifications.out +++ b/src/test/regress/expected/multi_mx_modifications.out @@ -91,6 +91,8 @@ SET client_min_messages TO DEFAULT; -- commands with non-constant partition values are unsupported INSERT INTO limit_orders_mx VALUES (random() * 100, 'ORCL', 152, '2011-08-25 11:50:45', 'sell', 0.58); +INSERT INTO limit_orders_mx SELECT random() * 100, 'ORCL', 152, '2011-08-25 11:50:45', + 'sell', 0.58; -- values for other columns are totally fine INSERT INTO limit_orders_mx VALUES (2036, 'GOOG', 5634, now(), 'buy', random()); -- commands with mutable functions in their quals @@ -103,6 +105,22 @@ DELETE FROM limit_orders_mx WHERE id = 246 AND placed_at = current_timestamp::ti INSERT INTO limit_orders_mx VALUES (2037, 'GOOG', 5634, now(), 'buy', random()), (2038, 'GOOG', 5634, now(), 'buy', random()), (2039, 'GOOG', 5634, now(), 'buy', random()); +SELECT count(distinct placed_at) FROM limit_orders_mx WHERE id BETWEEN 2037 AND 2039; + count +--------------------------------------------------------------------- + 1 +(1 row) + +INSERT INTO limit_orders_mx SELECT * FROM (VALUES + (2040, 'GOOG', 5634, now(), 'buy'::citus_mx_test_schema.order_side_mx, random()), + (2041, 'GOOG', 5634, now(), 'buy'::citus_mx_test_schema.order_side_mx, random()), + (2042, 'GOOG', 5634, now(), 'buy'::citus_mx_test_schema.order_side_mx, random())); +SELECT count(distinct placed_at) FROM limit_orders_mx WHERE id BETWEEN 2040 AND 2042; + count +--------------------------------------------------------------------- + 1 +(1 row) + -- connect back to the other node \c - - - :worker_1_port -- commands containing a CTE are supported @@ -216,9 +234,12 @@ INSERT INTO limit_orders_mx VALUES (275, 'ADR', 140, '2007-07-02 16:32:15', 'sel ERROR: duplicate key value violates unique constraint "limit_orders_mx_pkey_1220093" -- multi shard update is supported UPDATE limit_orders_mx SET limit_price = 0.00; +UPDATE limit_orders_mx SET limit_price = (SELECT 0.00); -- attempting to change the partition key is unsupported UPDATE limit_orders_mx SET id = 0 WHERE id = 246; ERROR: modifying the partition value of rows is not allowed +UPDATE limit_orders_mx SET id = (SELECT 0) WHERE id = 246; +ERROR: modifying the partition value of rows is not allowed -- UPDATEs with a FROM clause are unsupported UPDATE limit_orders_mx SET limit_price = 0.00 FROM bidders WHERE limit_orders_mx.id = 246 AND diff --git a/src/test/regress/sql/distributed_types.sql b/src/test/regress/sql/distributed_types.sql index 205faf9c7..ac44457da 100644 --- a/src/test/regress/sql/distributed_types.sql +++ b/src/test/regress/sql/distributed_types.sql @@ -270,10 +270,14 @@ SELECT create_distributed_table('domain_indirection_test', 'f1'); -- not supported (field indirection to underlying composite type) INSERT INTO domain_indirection_test (f1,f3.if1, f3.if2) VALUES (0, 1, 2); INSERT INTO domain_indirection_test (f1,f3.if1, f3.if2) SELECT 0, 1, 2; +-- INSERT INTO domain_indirection_test (f1,f3.if1, f3.if2) SELECT 0, 1, 2; INSERT INTO domain_indirection_test (f1,f3.if1) VALUES (0, 1); INSERT INTO domain_indirection_test (f1,f3.if1) SELECT 0, 1; +-- INSERT INTO domain_indirection_test (f1,f3.if1) SELECT 0, 1; +-- ERROR: could not find a conversion path from type 23 to 17619 UPDATE domain_indirection_test SET domain_array[0].if2 = 5; UPDATE domain_indirection_test SET domain_array[0].if2 = (SELECT 5); +UPDATE domain_indirection_test SET domain_array[0].if2 = (SELECT 5); -- below are supported as we don't do any field indirection INSERT INTO field_indirection_test_2 (ct2_col, int_col, ct1_col) diff --git a/src/test/regress/sql/multi_modifications.sql b/src/test/regress/sql/multi_modifications.sql index 2a00e7992..eeab5536f 100644 --- a/src/test/regress/sql/multi_modifications.sql +++ b/src/test/regress/sql/multi_modifications.sql @@ -234,6 +234,7 @@ SELECT kind, limit_price FROM limit_orders WHERE id = 246; -- multi-column UPDATE with RETURNING UPDATE limit_orders SET (kind, limit_price) = ('buy', 999) WHERE id = 246 RETURNING *; +UPDATE limit_orders SET (kind, limit_price) = (SELECT 'buy'::order_side, 999) WHERE id = 246 RETURNING *; -- Test that on unique contraint violations, we fail fast \set VERBOSITY terse @@ -337,6 +338,9 @@ UPDATE limit_orders SET limit_price = 0.00 FROM bidders WITH deleted_orders AS (INSERT INTO limit_orders VALUES (399, 'PDR', 14, '2017-07-02 16:32:15', 'sell', 43)) UPDATE limit_orders SET symbol = 'GM'; +WITH deleted_orders AS (INSERT INTO limit_orders SELECT 400, 'PDR', 14, '2017-07-02 16:32:15', 'sell', 43) +UPDATE limit_orders SET symbol = 'GM'; + SELECT symbol, bidder_id FROM limit_orders WHERE id = 246; -- updates referencing just a var are supported @@ -584,6 +588,13 @@ WHERE id = 2; SELECT * FROM summary_table ORDER BY id; +--- TODO this one is a silent corruption: +-- UPDATE summary_table SET (average_value, min_value) = +-- (SELECT avg(value), min(value) FROM raw_table WHERE id = 2) +-- WHERE id = 2; + +SELECT * FROM summary_table ORDER BY id; + UPDATE summary_table SET min_value = 100 WHERE id IN (SELECT id FROM raw_table WHERE id = 1 and value > 100) AND id = 1; @@ -712,6 +723,13 @@ WHERE id = 2; SELECT * FROM reference_summary_table ORDER BY id; +--- TODO this one is a silent corruption: +-- UPDATE reference_summary_table SET (average_value, min_value) = +-- (SELECT avg(value), min(value) FROM reference_raw_table WHERE id = 2) +-- WHERE id = 2; + +SELECT * FROM reference_summary_table ORDER BY id; + -- no need partition colum equalities on reference tables UPDATE reference_summary_table SET (count) = (SELECT id AS inner_id FROM reference_raw_table WHERE value = 500) diff --git a/src/test/regress/sql/multi_mx_modifications.sql b/src/test/regress/sql/multi_mx_modifications.sql index 852bf3a42..185fef451 100644 --- a/src/test/regress/sql/multi_mx_modifications.sql +++ b/src/test/regress/sql/multi_mx_modifications.sql @@ -67,6 +67,8 @@ SET client_min_messages TO DEFAULT; -- commands with non-constant partition values are unsupported INSERT INTO limit_orders_mx VALUES (random() * 100, 'ORCL', 152, '2011-08-25 11:50:45', 'sell', 0.58); +INSERT INTO limit_orders_mx SELECT random() * 100, 'ORCL', 152, '2011-08-25 11:50:45', + 'sell', 0.58; -- values for other columns are totally fine INSERT INTO limit_orders_mx VALUES (2036, 'GOOG', 5634, now(), 'buy', random()); @@ -83,6 +85,17 @@ INSERT INTO limit_orders_mx VALUES (2037, 'GOOG', 5634, now(), 'buy', random()), (2038, 'GOOG', 5634, now(), 'buy', random()), (2039, 'GOOG', 5634, now(), 'buy', random()); +SELECT count(distinct placed_at) FROM limit_orders_mx WHERE id BETWEEN 2037 AND 2039; + +INSERT INTO limit_orders_mx SELECT * FROM (VALUES + (2040, 'GOOG', 5634, now(), 'buy'::citus_mx_test_schema.order_side_mx, random()), + (2041, 'GOOG', 5634, now(), 'buy'::citus_mx_test_schema.order_side_mx, random()), + (2042, 'GOOG', 5634, now(), 'buy'::citus_mx_test_schema.order_side_mx, random())); + +SELECT count(distinct placed_at) FROM limit_orders_mx WHERE id BETWEEN 2040 AND 2042; + + + -- connect back to the other node \c - - - :worker_1_port @@ -153,9 +166,11 @@ INSERT INTO limit_orders_mx VALUES (275, 'ADR', 140, '2007-07-02 16:32:15', 'sel -- multi shard update is supported UPDATE limit_orders_mx SET limit_price = 0.00; +UPDATE limit_orders_mx SET limit_price = (SELECT 0.00); -- attempting to change the partition key is unsupported UPDATE limit_orders_mx SET id = 0 WHERE id = 246; +UPDATE limit_orders_mx SET id = (SELECT 0) WHERE id = 246; -- UPDATEs with a FROM clause are unsupported UPDATE limit_orders_mx SET limit_price = 0.00 FROM bidders