Disallow field indirection in INSERT/UPDATE queries (#4241)

pull/3597/head
Onur Tirtir 2020-10-14 14:11:59 +03:00 committed by GitHub
parent 8efca3b60a
commit 1a28858c47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 137 additions and 0 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;