Allow references to columns in UPDATE statements (#472)

Allow references to columns in UPDATE statements

Queries like "UPDATE tbl SET column = column + 1" are now allowed, so long as you don't use any IMMUTABLE functions.
pull/1938/head
Brian Cloutier 2016-04-28 05:45:16 -07:00
parent d7c984d957
commit 38fdb01b91
4 changed files with 47 additions and 10 deletions

View File

@ -272,7 +272,7 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
continue; continue;
} }
if (!IsA(targetEntry->expr, Const)) if (contain_mutable_functions((Node *) targetEntry->expr))
{ {
hasNonConstTargetEntryExprs = true; hasNonConstTargetEntryExprs = true;
} }
@ -354,8 +354,8 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
if (hasNonConstTargetEntryExprs || hasNonConstQualExprs) if (hasNonConstTargetEntryExprs || hasNonConstQualExprs)
{ {
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot plan sharded modification containing values " errmsg("functions used in modification queries on distributed "
"which are not constants or constant expressions"))); "tables must be marked IMMUTABLE")));
} }
if (specifiesPartitionValue) if (specifiesPartitionValue)

View File

@ -155,16 +155,16 @@ SET client_min_messages TO DEFAULT;
-- commands with non-constant partition values are unsupported -- commands with non-constant partition values are unsupported
INSERT INTO limit_orders VALUES (random() * 100, 'ORCL', 152, '2011-08-25 11:50:45', INSERT INTO limit_orders VALUES (random() * 100, 'ORCL', 152, '2011-08-25 11:50:45',
'sell', 0.58); 'sell', 0.58);
ERROR: cannot plan sharded modification containing values which are not constants or constant expressions ERROR: functions used in modification queries on distributed tables must be marked IMMUTABLE
-- commands with expressions that cannot be collapsed are unsupported -- commands with expressions that cannot be collapsed are unsupported
INSERT INTO limit_orders VALUES (2036, 'GOOG', 5634, now(), 'buy', random()); INSERT INTO limit_orders VALUES (2036, 'GOOG', 5634, now(), 'buy', random());
ERROR: cannot plan sharded modification containing values which are not constants or constant expressions ERROR: functions used in modification queries on distributed tables must be marked IMMUTABLE
-- commands with mutable functions in their quals -- commands with mutable functions in their quals
DELETE FROM limit_orders WHERE id = 246 AND bidder_id = (random() * 1000); DELETE FROM limit_orders WHERE id = 246 AND bidder_id = (random() * 1000);
ERROR: cannot plan sharded modification containing values which are not constants or constant expressions ERROR: functions used in modification queries on distributed tables must be marked IMMUTABLE
-- commands with mutable but non-volatilte functions(ie: stable func.) in their quals -- commands with mutable but non-volatilte functions(ie: stable func.) in their quals
DELETE FROM limit_orders WHERE id = 246 AND placed_at = current_timestamp; DELETE FROM limit_orders WHERE id = 246 AND placed_at = current_timestamp;
ERROR: cannot plan sharded modification containing values which are not constants or constant expressions ERROR: functions used in modification queries on distributed tables must be marked IMMUTABLE
-- commands with multiple rows are unsupported -- commands with multiple rows are unsupported
INSERT INTO limit_orders VALUES (DEFAULT), (DEFAULT); INSERT INTO limit_orders VALUES (DEFAULT), (DEFAULT);
ERROR: cannot perform distributed planning for the given modification ERROR: cannot perform distributed planning for the given modification
@ -317,6 +317,27 @@ WITH deleted_orders AS (INSERT INTO limit_orders DEFAULT VALUES RETURNING *)
UPDATE limit_orders SET symbol = 'GM'; UPDATE limit_orders SET symbol = 'GM';
ERROR: cannot perform distributed planning for the given modification ERROR: cannot perform distributed planning for the given modification
DETAIL: Common table expressions are not supported in distributed modifications. DETAIL: Common table expressions are not supported in distributed modifications.
SELECT symbol, bidder_id FROM limit_orders WHERE id = 246;
symbol | bidder_id
--------+-----------
GM | 18
(1 row)
-- updates referencing just a var are supported
UPDATE limit_orders SET bidder_id = id WHERE id = 246;
-- updates referencing a column are supported
UPDATE limit_orders SET bidder_id = bidder_id + 1 WHERE id = 246;
-- IMMUTABLE functions are allowed
UPDATE limit_orders SET symbol = LOWER(symbol) WHERE id = 246;
SELECT symbol, bidder_id FROM limit_orders WHERE id = 246;
symbol | bidder_id
--------+-----------
gm | 247
(1 row)
-- updates referencing non-IMMUTABLE functions are unsupported
UPDATE limit_orders SET placed_at = now() WHERE id = 246;
ERROR: functions used in modification queries on distributed tables must be marked IMMUTABLE
-- cursors are not supported -- cursors are not supported
UPDATE limit_orders SET symbol = 'GM' WHERE CURRENT OF cursor_name; UPDATE limit_orders SET symbol = 'GM' WHERE CURRENT OF cursor_name;
ERROR: distributed modifications must target exactly one shard ERROR: distributed modifications must target exactly one shard

View File

@ -223,15 +223,15 @@ DETAIL: Subqueries are not supported in distributed modifications.
-- non mutable function call in the SET -- non mutable function call in the SET
INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO
UPDATE SET other_col = random()::int; UPDATE SET other_col = random()::int;
ERROR: cannot plan sharded modification containing values which are not constants or constant expressions ERROR: functions used in modification queries on distributed tables must be marked IMMUTABLE
-- non mutable function call in the WHERE -- non mutable function call in the WHERE
INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO
UPDATE SET other_col = 5 WHERE upsert_test.other_col = random()::int; UPDATE SET other_col = 5 WHERE upsert_test.other_col = random()::int;
ERROR: cannot plan sharded modification containing values which are not constants or constant expressions ERROR: functions used in modification queries on distributed tables must be marked IMMUTABLE
-- non mutable function call in the arbiter WHERE -- non mutable function call in the arbiter WHERE
INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) WHERE part_key = random()::int INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) WHERE part_key = random()::int
DO UPDATE SET other_col = 5; DO UPDATE SET other_col = 5;
ERROR: cannot plan sharded modification containing values which are not constants or constant expressions ERROR: functions used in modification queries on distributed tables must be marked IMMUTABLE
-- error out on attempt to update the partition key -- error out on attempt to update the partition key
INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO
UPDATE SET part_key = 15; UPDATE SET part_key = 15;

View File

@ -235,5 +235,21 @@ UPDATE limit_orders SET symbol = 'GM' WHERE id = 246 RETURNING *;
WITH deleted_orders AS (INSERT INTO limit_orders DEFAULT VALUES RETURNING *) WITH deleted_orders AS (INSERT INTO limit_orders DEFAULT VALUES RETURNING *)
UPDATE limit_orders SET symbol = 'GM'; UPDATE limit_orders SET symbol = 'GM';
SELECT symbol, bidder_id FROM limit_orders WHERE id = 246;
-- updates referencing just a var are supported
UPDATE limit_orders SET bidder_id = id WHERE id = 246;
-- updates referencing a column are supported
UPDATE limit_orders SET bidder_id = bidder_id + 1 WHERE id = 246;
-- IMMUTABLE functions are allowed
UPDATE limit_orders SET symbol = LOWER(symbol) WHERE id = 246;
SELECT symbol, bidder_id FROM limit_orders WHERE id = 246;
-- updates referencing non-IMMUTABLE functions are unsupported
UPDATE limit_orders SET placed_at = now() WHERE id = 246;
-- cursors are not supported -- cursors are not supported
UPDATE limit_orders SET symbol = 'GM' WHERE CURRENT OF cursor_name; UPDATE limit_orders SET symbol = 'GM' WHERE CURRENT OF cursor_name;