mirror of https://github.com/citusdata/citus.git
Disallow field indirection in INSERT/UPDATE queries (#4241)
parent
8efca3b60a
commit
1a28858c47
|
@ -130,6 +130,7 @@ static bool IsTidColumn(Node *node);
|
||||||
static DeferredErrorMessage * ModifyPartialQuerySupported(Query *queryTree, bool
|
static DeferredErrorMessage * ModifyPartialQuerySupported(Query *queryTree, bool
|
||||||
multiShardQuery,
|
multiShardQuery,
|
||||||
Oid *distributedTableId);
|
Oid *distributedTableId);
|
||||||
|
static bool NodeIsFieldStore(Node *node);
|
||||||
static DeferredErrorMessage * DeferErrorIfUnsupportedModifyQueryWithLocalTable(
|
static DeferredErrorMessage * DeferErrorIfUnsupportedModifyQueryWithLocalTable(
|
||||||
Query *query);
|
Query *query);
|
||||||
static DeferredErrorMessage * DeferErrorIfUnsupportedModifyQueryWithCitusLocalTable(
|
static DeferredErrorMessage * DeferErrorIfUnsupportedModifyQueryWithCitusLocalTable(
|
||||||
|
@ -674,6 +675,18 @@ ModifyPartialQuerySupported(Query *queryTree, bool multiShardQuery,
|
||||||
{
|
{
|
||||||
Assert(hasVarArgument || hasBadCoalesce);
|
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)
|
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
|
* DeferErrorIfUnsupportedModifyQueryWithLocalTable returns DeferredErrorMessage
|
||||||
* for unsupported modify queries that cannot be planned by router planner due to
|
* for unsupported modify queries that cannot be planned by router planner due to
|
||||||
|
|
|
@ -380,6 +380,79 @@ SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname IN ('
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
RESET citus.enable_create_type_propagation;
|
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
|
-- clear objects
|
||||||
SET client_min_messages TO error; -- suppress cascading objects dropping
|
SET client_min_messages TO error; -- suppress cascading objects dropping
|
||||||
DROP SCHEMA type_tests CASCADE;
|
DROP SCHEMA type_tests CASCADE;
|
||||||
|
|
|
@ -240,6 +240,47 @@ SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname IN ('
|
||||||
|
|
||||||
RESET citus.enable_create_type_propagation;
|
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
|
-- clear objects
|
||||||
SET client_min_messages TO error; -- suppress cascading objects dropping
|
SET client_min_messages TO error; -- suppress cascading objects dropping
|
||||||
DROP SCHEMA type_tests CASCADE;
|
DROP SCHEMA type_tests CASCADE;
|
||||||
|
|
Loading…
Reference in New Issue