mirror of https://github.com/citusdata/citus.git
Use get_attnum to find the attribute number of target entry (#5220)
* Use get_attnum to find the attribute number of target entrypull/5176/head
parent
481f8be084
commit
5ae01303d4
|
@ -634,17 +634,6 @@ ModifyPartialQuerySupported(Query *queryTree, bool multiShardQuery,
|
|||
foreach(targetEntryCell, queryTree->targetList)
|
||||
{
|
||||
TargetEntry *targetEntry = (TargetEntry *) lfirst(targetEntryCell);
|
||||
bool targetEntryPartitionColumn = false;
|
||||
|
||||
/* reference tables do not have partition column */
|
||||
if (partitionColumn == NULL)
|
||||
{
|
||||
targetEntryPartitionColumn = false;
|
||||
}
|
||||
else if (targetEntry->resno == partitionColumn->varattno)
|
||||
{
|
||||
targetEntryPartitionColumn = true;
|
||||
}
|
||||
|
||||
/* skip resjunk entries: UPDATE adds some for ctid, etc. */
|
||||
if (targetEntry->resjunk)
|
||||
|
@ -652,6 +641,35 @@ ModifyPartialQuerySupported(Query *queryTree, bool multiShardQuery,
|
|||
continue;
|
||||
}
|
||||
|
||||
bool targetEntryPartitionColumn = false;
|
||||
AttrNumber targetColumnAttrNumber = InvalidAttrNumber;
|
||||
|
||||
/* reference tables do not have partition column */
|
||||
if (partitionColumn == NULL)
|
||||
{
|
||||
targetEntryPartitionColumn = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (commandType == CMD_UPDATE)
|
||||
{
|
||||
/*
|
||||
* Note that it is not possible to give an alias to
|
||||
* UPDATE table SET ...
|
||||
*/
|
||||
if (targetEntry->resname)
|
||||
{
|
||||
targetColumnAttrNumber = get_attnum(resultRelationId,
|
||||
targetEntry->resname);
|
||||
if (targetColumnAttrNumber == partitionColumn->varattno)
|
||||
{
|
||||
targetEntryPartitionColumn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (commandType == CMD_UPDATE &&
|
||||
FindNodeMatchingCheckFunction((Node *) targetEntry->expr,
|
||||
CitusIsVolatileFunction))
|
||||
|
@ -1134,11 +1152,21 @@ ErrorIfOnConflictNotSupported(Query *queryTree)
|
|||
{
|
||||
setTargetEntryPartitionColumn = false;
|
||||
}
|
||||
else if (setTargetEntry->resno == partitionColumn->varattno)
|
||||
else
|
||||
{
|
||||
Oid resultRelationId = ModifyQueryResultRelationId(queryTree);
|
||||
|
||||
AttrNumber targetColumnAttrNumber = InvalidAttrNumber;
|
||||
if (setTargetEntry->resname)
|
||||
{
|
||||
targetColumnAttrNumber = get_attnum(resultRelationId,
|
||||
setTargetEntry->resname);
|
||||
if (targetColumnAttrNumber == partitionColumn->varattno)
|
||||
{
|
||||
setTargetEntryPartitionColumn = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (setTargetEntryPartitionColumn)
|
||||
{
|
||||
Expr *setExpr = setTargetEntry->expr;
|
||||
|
@ -1522,12 +1550,7 @@ TargetEntryChangesValue(TargetEntry *targetEntry, Var *column, FromExpr *joinTre
|
|||
bool isColumnValueChanged = true;
|
||||
Expr *setExpr = targetEntry->expr;
|
||||
|
||||
if (targetEntry->resno != column->varattno)
|
||||
{
|
||||
/* target entry of the form SET some_other_col = <x> */
|
||||
isColumnValueChanged = false;
|
||||
}
|
||||
else if (IsA(setExpr, Var))
|
||||
if (IsA(setExpr, Var))
|
||||
{
|
||||
Var *newValue = (Var *) setExpr;
|
||||
if (newValue->varattno == column->varattno)
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
CREATE SCHEMA modification_correctness;
|
||||
SET search_path to 'modification_correctness';
|
||||
CREATE TABLE test(k int, a int, b int, c int unique, d int, e int);
|
||||
ALTER TABLE test DROP column k;
|
||||
SELECT create_distributed_table('test', 'c');
|
||||
create_distributed_table
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
ALTER TABLE test DROP column b;
|
||||
UPDATE test SET a = 5, c = 5;
|
||||
ERROR: modifying the partition value of rows is not allowed
|
||||
UPDATE test SET a = 5, c = d, d =3;
|
||||
ERROR: modifying the partition value of rows is not allowed
|
||||
UPDATE test SET c = d, d =3;
|
||||
ERROR: modifying the partition value of rows is not allowed
|
||||
UPDATE test SET d=c, c = d;
|
||||
ERROR: modifying the partition value of rows is not allowed
|
||||
UPDATE test SET e = c, d = 3;
|
||||
UPDATE test SET c = c;
|
||||
UPDATE test SET c = c, c = 3;
|
||||
ERROR: multiple assignments to same column "c"
|
||||
UPDATE test SET c = c, d = c;
|
||||
UPDATE test SET c = c, d = 5, e = 3;
|
||||
INSERT INTO test (c,d) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=7;
|
||||
ERROR: modifying the partition value of rows is not allowed
|
||||
INSERT INTO test (c,d) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET d=7;
|
||||
INSERT INTO test (c,d) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET a=7;
|
||||
INSERT INTO test (d,c) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=7;
|
||||
ERROR: modifying the partition value of rows is not allowed
|
||||
INSERT INTO test (d,c) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET d=7;
|
||||
INSERT INTO test (a,c) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET d=7;
|
||||
INSERT INTO test (c) VALUES(3) ON CONFLICT(c) DO UPDATE SET d=7;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET d=7;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c, e = EXCLUDED.c;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c, e = 7;
|
||||
-- make sure that without fast path planner, we don't get any unexpected errors.
|
||||
SET citus.enable_fast_path_router_planner to false;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET d=7;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c, e = EXCLUDED.c;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c, e = 7;
|
||||
UPDATE test SET e = c, d = 3;
|
||||
UPDATE test SET c = c;
|
||||
UPDATE test SET c = c, c = 3;
|
||||
ERROR: multiple assignments to same column "c"
|
||||
UPDATE test SET c = c, d = c;
|
||||
UPDATE test SET c = c, d = 5, e = 3;
|
||||
RESET citus.enable_fast_path_router_planner;
|
||||
PREPARE foo(int,int) AS INSERT INTO test (c,a) VALUES($1,$2) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c, e = $1;
|
||||
EXECUTE foo(1,2);
|
||||
EXECUTE foo(1,2);
|
||||
EXECUTE foo(1,2);
|
||||
EXECUTE foo(1,2);
|
||||
EXECUTE foo(1,2);
|
||||
EXECUTE foo(1,2);
|
||||
EXECUTE foo(1,2);
|
||||
PREPARE foo1(int, int) AS UPDATE test SET c = c, d = $1, e = $2;
|
||||
EXECUTE foo1(1,2);
|
||||
EXECUTE foo1(1,2);
|
||||
EXECUTE foo1(1,2);
|
||||
EXECUTE foo1(1,2);
|
||||
EXECUTE foo1(1,2);
|
||||
EXECUTE foo1(1,2);
|
||||
EXECUTE foo1(1,2);
|
||||
-- we don't get an error because this is something like c = c
|
||||
UPDATE test SET a = 5,d = 2, c = 5 FROM (SELECT * FROM test LIMIT 10) t2 WHERE t2.d = test.c and test.c = 5;
|
||||
-- we should get an error because c gets 6 -> 5
|
||||
UPDATE test SET a = 5,d = 2, c = 5 FROM (SELECT * FROM test LIMIT 10) t2 WHERE t2.d = test.c and test.c = 6;
|
||||
ERROR: modifying the partition value of rows is not allowed
|
||||
DROP SCHEMA modification_correctness CASCADE;
|
||||
NOTICE: drop cascades to table test
|
|
@ -77,6 +77,7 @@ test: multi_agg_type_conversion multi_count_type_conversion recursive_relation_p
|
|||
test: multi_partition_pruning single_hash_repartition_join
|
||||
test: multi_join_pruning multi_hash_pruning intermediate_result_pruning
|
||||
test: multi_null_minmax_value_pruning cursors
|
||||
test: modification_correctness
|
||||
test: multi_query_directory_cleanup
|
||||
test: multi_task_assignment_policy multi_cross_shard
|
||||
test: multi_utility_statements
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
CREATE SCHEMA modification_correctness;
|
||||
SET search_path to 'modification_correctness';
|
||||
|
||||
CREATE TABLE test(k int, a int, b int, c int unique, d int, e int);
|
||||
ALTER TABLE test DROP column k;
|
||||
SELECT create_distributed_table('test', 'c');
|
||||
ALTER TABLE test DROP column b;
|
||||
|
||||
UPDATE test SET a = 5, c = 5;
|
||||
UPDATE test SET a = 5, c = d, d =3;
|
||||
UPDATE test SET c = d, d =3;
|
||||
UPDATE test SET d=c, c = d;
|
||||
UPDATE test SET e = c, d = 3;
|
||||
UPDATE test SET c = c;
|
||||
UPDATE test SET c = c, c = 3;
|
||||
UPDATE test SET c = c, d = c;
|
||||
UPDATE test SET c = c, d = 5, e = 3;
|
||||
|
||||
|
||||
|
||||
INSERT INTO test (c,d) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=7;
|
||||
INSERT INTO test (c,d) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET d=7;
|
||||
INSERT INTO test (c,d) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET a=7;
|
||||
INSERT INTO test (d,c) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=7;
|
||||
INSERT INTO test (d,c) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET d=7;
|
||||
INSERT INTO test (a,c) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET d=7;
|
||||
INSERT INTO test (c) VALUES(3) ON CONFLICT(c) DO UPDATE SET d=7;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET d=7;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c, e = EXCLUDED.c;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c, e = 7;
|
||||
|
||||
-- make sure that without fast path planner, we don't get any unexpected errors.
|
||||
SET citus.enable_fast_path_router_planner to false;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET d=7;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c, e = EXCLUDED.c;
|
||||
INSERT INTO test (c,a) VALUES(3,4) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c, e = 7;
|
||||
UPDATE test SET e = c, d = 3;
|
||||
UPDATE test SET c = c;
|
||||
UPDATE test SET c = c, c = 3;
|
||||
UPDATE test SET c = c, d = c;
|
||||
UPDATE test SET c = c, d = 5, e = 3;
|
||||
RESET citus.enable_fast_path_router_planner;
|
||||
|
||||
|
||||
PREPARE foo(int,int) AS INSERT INTO test (c,a) VALUES($1,$2) ON CONFLICT(c) DO UPDATE SET c=EXCLUDED.c, d = EXCLUDED.c, e = $1;
|
||||
EXECUTE foo(1,2);
|
||||
EXECUTE foo(1,2);
|
||||
EXECUTE foo(1,2);
|
||||
EXECUTE foo(1,2);
|
||||
EXECUTE foo(1,2);
|
||||
EXECUTE foo(1,2);
|
||||
EXECUTE foo(1,2);
|
||||
|
||||
PREPARE foo1(int, int) AS UPDATE test SET c = c, d = $1, e = $2;
|
||||
EXECUTE foo1(1,2);
|
||||
EXECUTE foo1(1,2);
|
||||
EXECUTE foo1(1,2);
|
||||
EXECUTE foo1(1,2);
|
||||
EXECUTE foo1(1,2);
|
||||
EXECUTE foo1(1,2);
|
||||
EXECUTE foo1(1,2);
|
||||
|
||||
-- we don't get an error because this is something like c = c
|
||||
UPDATE test SET a = 5,d = 2, c = 5 FROM (SELECT * FROM test LIMIT 10) t2 WHERE t2.d = test.c and test.c = 5;
|
||||
-- we should get an error because c gets 6 -> 5
|
||||
UPDATE test SET a = 5,d = 2, c = 5 FROM (SELECT * FROM test LIMIT 10) t2 WHERE t2.d = test.c and test.c = 6;
|
||||
|
||||
|
||||
DROP SCHEMA modification_correctness CASCADE;
|
Loading…
Reference in New Issue