Add error hint to failing modify query

pull/1031/head
Murat Tuncer 2016-12-09 17:38:13 +03:00
parent 25e28763b2
commit 2f76b4be99
8 changed files with 93 additions and 6 deletions

View File

@ -24,6 +24,7 @@
#include "distributed/citus_nodes.h"
#include "distributed/citus_nodefuncs.h"
#include "distributed/deparse_shard_query.h"
#include "distributed/distribution_column.h"
#include "distributed/master_metadata_utility.h"
#include "distributed/metadata_cache.h"
#include "distributed/multi_join_order.h"
@ -1665,8 +1666,10 @@ TargetShardIntervalForModify(Query *query)
DistTableCacheEntry *cacheEntry = DistributedTableCacheEntry(distributedTableId);
char partitionMethod = cacheEntry->partitionMethod;
bool fastShardPruningPossible = false;
CmdType commandType = query->commandType;
bool updateOrDelete = (commandType == CMD_UPDATE || commandType == CMD_DELETE);
Assert(query->commandType != CMD_SELECT);
Assert(commandType != CMD_SELECT);
/* error out if no shards exist for the table */
shardCount = cacheEntry->shardIntervalArrayLength;
@ -1709,10 +1712,61 @@ TargetShardIntervalForModify(Query *query)
prunedShardCount = list_length(prunedShardList);
if (prunedShardCount != 1)
{
Oid relationId = cacheEntry->relationId;
char *partitionKeyString = cacheEntry->partitionKeyString;
char *partitionColumnName = ColumnNameToColumn(relationId, partitionKeyString);
StringInfo errorHint = makeStringInfo();
char *errorDetail = NULL;
if (prunedShardCount == 0)
{
errorDetail = "This command modifies no shards.";
}
else if (prunedShardCount == shardCount)
{
errorDetail = "This command modifies all shards.";
}
if (updateOrDelete)
{
appendStringInfo(errorHint,
"Consider using an equality filter on partition column "
"\"%s\". You can use master_modify_multiple_shards() to "
"perform multi-shard delete or update operations.",
partitionColumnName);
}
else
{
appendStringInfo(errorHint,
"Make sure the value for partition column \"%s\" falls into "
"a single shard.", partitionColumnName);
}
if (commandType == CMD_DELETE && partitionMethod == DISTRIBUTE_BY_APPEND)
{
appendStringInfo(errorHint,
" You can also use master_apply_delete_command() to drop "
"all shards satisfying delete criteria.");
}
if (errorDetail == NULL)
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("distributed modifications must target exactly one "
"shard")));
"shard"),
errhint("%s", errorHint->data)));
}
else
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("distributed modifications must target exactly one "
"shard"),
errdetail("%s", errorDetail),
errhint("%s", errorHint->data)));
}
}
return (ShardInterval *) linitial(prunedShardList);

View File

@ -108,6 +108,8 @@ INSERT INTO limit_orders VALUES (32744, 'AAPL', 9580, '2004-10-19 10:23:54', 'bu
INSERT INTO insufficient_shards VALUES (32743, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy',
20.69);
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies no shards.
HINT: Make sure the value for partition column "id" falls into a single shard.
-- try an insert to a range-partitioned table
INSERT INTO range_partitioned VALUES (32743, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy',
20.69);
@ -139,10 +141,14 @@ SET citus.task_executor_type TO DEFAULT;
INSERT INTO range_partitioned VALUES (999999, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy',
20.69);
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies no shards.
HINT: Make sure the value for partition column "id" falls into a single shard.
-- and insert into an append-partitioned table with a value that spans shards:
INSERT INTO append_partitioned VALUES (500000, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy',
20.69);
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies all shards.
HINT: Make sure the value for partition column "id" falls into a single shard.
-- INSERT with DEFAULT in the target list
INSERT INTO limit_orders VALUES (12756, 'MSFT', 10959, '2013-05-08 07:29:23', 'sell',
DEFAULT);
@ -259,6 +265,8 @@ SELECT COUNT(*) FROM limit_orders WHERE id = 246;
-- commands with no constraints on the partition key are not supported
DELETE FROM limit_orders WHERE bidder_id = 162;
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies all shards.
HINT: Consider using an equality filter on partition column "id". You can use master_modify_multiple_shards() to perform multi-shard delete or update operations.
-- commands with a USING clause are unsupported
CREATE TABLE bidders ( name text, id bigint );
DELETE FROM limit_orders USING bidders WHERE limit_orders.id = 246 AND
@ -273,6 +281,8 @@ DETAIL: Common table expressions are not supported in distributed modifications
-- cursors are not supported
DELETE FROM limit_orders WHERE CURRENT OF cursor_name;
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies all shards.
HINT: Consider using an equality filter on partition column "id". You can use master_modify_multiple_shards() to perform multi-shard delete or update operations.
INSERT INTO limit_orders VALUES (246, 'TSLA', 162, '2007-07-02 16:32:15', 'sell', 20.69);
-- simple UPDATE
UPDATE limit_orders SET symbol = 'GM' WHERE id = 246;
@ -392,6 +402,8 @@ ALTER TABLE renamed_orders RENAME TO limit_orders_750000;
-- commands with no constraints on the partition key are not supported
UPDATE limit_orders SET limit_price = 0.00;
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies all shards.
HINT: Consider using an equality filter on partition column "id". You can use master_modify_multiple_shards() to perform multi-shard delete or update operations.
-- attempting to change the partition key is unsupported
UPDATE limit_orders SET id = 0 WHERE id = 246;
ERROR: modifying the partition value of rows is not allowed
@ -491,6 +503,8 @@ ERROR: non-IMMUTABLE functions are not allowed in the RETURNING clause
-- cursors are not supported
UPDATE limit_orders SET symbol = 'GM' WHERE CURRENT OF cursor_name;
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies all shards.
HINT: Consider using an equality filter on partition column "id". You can use master_modify_multiple_shards() to perform multi-shard delete or update operations.
-- check that multi-row UPDATE/DELETEs with RETURNING work
INSERT INTO multiple_hash VALUES ('0', '1');
INSERT INTO multiple_hash VALUES ('0', '2');

View File

@ -602,6 +602,8 @@ BEGIN;
INSERT INTO append_researchers VALUES (1, 1, 'John McCarthy');
INSERT INTO append_researchers VALUES (500000, 500000, 'Tony Hoare');
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies all shards.
HINT: Make sure the value for partition column "id" falls into a single shard.
ROLLBACK;
SELECT * FROM append_researchers;
id | lab_id | name

View File

@ -874,6 +874,8 @@ SELECT partition_parameter_update(5, 51);
-- This fails with an unexpected error message
SELECT partition_parameter_update(5, 52);
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies all shards.
HINT: Consider using an equality filter on partition column "key". You can use master_modify_multiple_shards() to perform multi-shard delete or update operations.
CONTEXT: SQL statement "UPDATE plpgsql_table SET value = $2 WHERE key = $1"
PL/pgSQL function partition_parameter_update(integer,integer) line 3 at SQL statement
CREATE FUNCTION non_partition_parameter_update(int, int) RETURNS void as $$
@ -985,6 +987,8 @@ SELECT partition_parameter_delete(5, 51);
-- This fails with an unexpected error message
SELECT partition_parameter_delete(0, 10);
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies all shards.
HINT: Consider using an equality filter on partition column "key". You can use master_modify_multiple_shards() to perform multi-shard delete or update operations.
CONTEXT: SQL statement "DELETE FROM plpgsql_table WHERE key = $1 AND value = $2"
PL/pgSQL function partition_parameter_delete(integer,integer) line 3 at SQL statement
CREATE FUNCTION non_partition_parameter_delete(int) RETURNS void as $$

View File

@ -751,6 +751,8 @@ EXECUTE prepared_partition_parameter_update(5, 51);
-- This fails with an unexpected error message
EXECUTE prepared_partition_parameter_update(5, 52);
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies all shards.
HINT: Consider using an equality filter on partition column "key". You can use master_modify_multiple_shards() to perform multi-shard delete or update operations.
PREPARE prepared_non_partition_parameter_update(int, int) AS
UPDATE prepare_table SET value = $2 WHERE key = 0 AND value = $1;
-- execute 6 times to trigger prepared statement usage
@ -799,6 +801,8 @@ EXECUTE prepared_partition_parameter_delete(5, 51);
-- This fails with an unexpected error message
EXECUTE prepared_partition_parameter_delete(0, 10);
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies all shards.
HINT: Consider using an equality filter on partition column "key". You can use master_modify_multiple_shards() to perform multi-shard delete or update operations.
PREPARE prepared_non_partition_parameter_delete(int) AS
DELETE FROM prepare_table WHERE key = 0 AND value = $1;
-- execute 6 times to trigger prepared statement usage

View File

@ -93,8 +93,12 @@ INSERT INTO articles_single_shard VALUES (50, 10, 'anjanette', 19519);
-- zero-shard modifications should fail
UPDATE articles SET title = '' WHERE author_id = 1 AND author_id = 2;
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies no shards.
HINT: Consider using an equality filter on partition column "author_id". You can use master_modify_multiple_shards() to perform multi-shard delete or update operations.
DELETE FROM articles WHERE author_id = 1 AND author_id = 2;
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies no shards.
HINT: Consider using an equality filter on partition column "author_id". You can use master_modify_multiple_shards() to perform multi-shard delete or update operations.
-- single-shard tests
-- test simple select for a single row
SELECT * FROM articles WHERE author_id = 10 AND id = 50;

View File

@ -28,9 +28,9 @@ SELECT master_create_distributed_table('customer_delete_protocol', 'c_custkey',
SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol
WHERE c_acctbal > 0.0');
-- Check that free-form deletes are not supported.
DELETE FROM customer_delete_protocol WHERE c_custkey > 100;
-- Check that we delete a shard if and only if all rows in the shard satisfy the condition.
SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol
WHERE c_custkey > 6500');
SELECT count(*) from customer_delete_protocol;

View File

@ -28,6 +28,11 @@ SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol
WHERE c_acctbal > 0.0');
ERROR: cannot delete from distributed table
DETAIL: Where clause includes a column other than partition column
-- Check that free-form deletes are not supported.
DELETE FROM customer_delete_protocol WHERE c_custkey > 100;
ERROR: distributed modifications must target exactly one shard
DETAIL: This command modifies all shards.
HINT: Consider using an equality filter on partition column "c_custkey". You can use master_modify_multiple_shards() to perform multi-shard delete or update operations. You can also use master_apply_delete_command() to drop all shards satisfying delete criteria.
-- Check that we delete a shard if and only if all rows in the shard satisfy the condition.
SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol
WHERE c_custkey > 6500');