diff --git a/src/backend/distributed/planner/multi_router_planner.c b/src/backend/distributed/planner/multi_router_planner.c index 0f46befaf..c90ad28e1 100644 --- a/src/backend/distributed/planner/multi_router_planner.c +++ b/src/backend/distributed/planner/multi_router_planner.c @@ -130,6 +130,7 @@ static bool IsTidColumn(Node *node); static DeferredErrorMessage * ModifyPartialQuerySupported(Query *queryTree, bool multiShardQuery, Oid *distributedTableId); +static bool NodeIsFieldStore(Node *node); static DeferredErrorMessage * DeferErrorIfUnsupportedModifyQueryWithLocalTable( Query *query); static DeferredErrorMessage * DeferErrorIfUnsupportedModifyQueryWithCitusLocalTable( @@ -674,6 +675,18 @@ ModifyPartialQuerySupported(Query *queryTree, bool multiShardQuery, { Assert(hasVarArgument || hasBadCoalesce); } + + if (FindNodeMatchingCheckFunction((Node *) targetEntry->expr, + NodeIsFieldStore)) + { + /* DELETE cannot do field indirection already */ + Assert(commandType == CMD_UPDATE || commandType == CMD_INSERT); + return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED, + "inserting or modifying composite type fields is not " + "supported", NULL, + "Use the column name to insert or update the composite " + "type as a single value"); + } } if (joinTree != NULL) @@ -740,6 +753,16 @@ ModifyPartialQuerySupported(Query *queryTree, bool multiShardQuery, } +/* + * NodeIsFieldStore returns true if given Node is a FieldStore object. + */ +static bool +NodeIsFieldStore(Node *node) +{ + return node && IsA(node, FieldStore); +} + + /* * DeferErrorIfUnsupportedModifyQueryWithLocalTable returns DeferredErrorMessage * for unsupported modify queries that cannot be planned by router planner due to diff --git a/src/test/regress/expected/distributed_types.out b/src/test/regress/expected/distributed_types.out index 242ebfa34..6d22ee2a2 100644 --- a/src/test/regress/expected/distributed_types.out +++ b/src/test/regress/expected/distributed_types.out @@ -380,6 +380,79 @@ SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname IN (' (2 rows) RESET citus.enable_create_type_propagation; +CREATE TYPE ct1 as (int_1 int, int_2 int); +CREATE TABLE field_indirection_test_1 (int_col int, ct1_col ct1); +SELECT create_distributed_table('field_indirection_test_1', 'int_col'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +-- not supported (field indirection in single row insert) +INSERT INTO field_indirection_test_1 (int_col, ct1_col.int_1, ct1_col.int_2) 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 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 +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'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +-- not supported (field indirection in multi row insert) +INSERT INTO field_indirection_test_2 (ct2_col.int_1, int_col, ct2_col.text_1, ct1_col.int_2) +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 +-- 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 +CREATE TYPE two_ints as (if1 int, if2 int); +CREATE DOMAIN domain AS two_ints CHECK ((VALUE).if1 > 0); +-- citus does not propagate domain objects +SELECT run_command_on_workers( +$$ + CREATE DOMAIN type_tests.domain AS type_tests.two_ints CHECK ((VALUE).if1 > 0); +$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,"CREATE DOMAIN") + (localhost,57638,t,"CREATE DOMAIN") +(2 rows) + +CREATE TABLE domain_indirection_test (f1 int, f3 domain, domain_array domain[]); +SELECT create_distributed_table('domain_indirection_test', 'f1'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +-- not supported (field indirection to underlying composite type) +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) 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 +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 +-- 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)'); +UPDATE field_indirection_test_2 SET (ct2_col, ct1_col) = ('(10, "text10", 20)', '(40, 50)') 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) + 8 | (10," text10",20) | (40,50) +(2 rows) + -- clear objects SET client_min_messages TO error; -- suppress cascading objects dropping DROP SCHEMA type_tests CASCADE; diff --git a/src/test/regress/sql/distributed_types.sql b/src/test/regress/sql/distributed_types.sql index 582b35e57..5448fb181 100644 --- a/src/test/regress/sql/distributed_types.sql +++ b/src/test/regress/sql/distributed_types.sql @@ -240,6 +240,47 @@ SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname IN (' RESET citus.enable_create_type_propagation; +CREATE TYPE ct1 as (int_1 int, int_2 int); +CREATE TABLE field_indirection_test_1 (int_col int, ct1_col ct1); +SELECT create_distributed_table('field_indirection_test_1', 'int_col'); + +-- not supported (field indirection in single row insert) +INSERT INTO field_indirection_test_1 (int_col, ct1_col.int_1, ct1_col.int_2) VALUES (0, 1, 2); +INSERT INTO field_indirection_test_1 (int_col, ct1_col.int_1) VALUES (0, 1); + +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'); + +-- not supported (field indirection in multi row insert) +INSERT INTO field_indirection_test_2 (ct2_col.int_1, int_col, ct2_col.text_1, ct1_col.int_2) +VALUES (0, 1, 'text1', 2), (3, 4, 'text1', 5); + +-- 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; + +CREATE TYPE two_ints as (if1 int, if2 int); +CREATE DOMAIN domain AS two_ints CHECK ((VALUE).if1 > 0); +-- citus does not propagate domain objects +SELECT run_command_on_workers( +$$ + CREATE DOMAIN type_tests.domain AS type_tests.two_ints CHECK ((VALUE).if1 > 0); +$$); +CREATE TABLE domain_indirection_test (f1 int, f3 domain, domain_array domain[]); +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) VALUES (0, 1); +UPDATE domain_indirection_test SET domain_array[0].if2 = 5; + +-- 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)'); +UPDATE field_indirection_test_2 SET (ct2_col, ct1_col) = ('(10, "text10", 20)', '(40, 50)') WHERE int_col=8; + +SELECT * FROM field_indirection_test_2 ORDER BY 1,2,3; + -- clear objects SET client_min_messages TO error; -- suppress cascading objects dropping DROP SCHEMA type_tests CASCADE;