From d164305929675c2d684d4e9ebdc65da5adeb8ca4 Mon Sep 17 00:00:00 2001 From: Jason Petersen Date: Wed, 10 Feb 2016 14:58:46 -0700 Subject: [PATCH] Handle hash-partitioned aliased data types When two data types have the same binary representation, PostgreSQL may add an implicit coercion between them by wrapping a node in a relabel type. This wrapper signals that the wrapped value is completely binary compatible with the designated "final type" of the relabel node. As an example, the varchar type is often relabeled to text, since functions provided for use with text (comparisons, hashes, etc.) are completely compatible with varchar as well. The hash-partitioned codepath contains functions that verify queries actually contain an equality constraint on the partition column, but those functions expect such constraints to be comparison operations between a Var and Const. The RelabelType wrapper node causes these functions to always return false, which bypasses shard pruning. --- .../distributed/planner/multi_physical_planner.c | 8 ++++++++ src/test/regress/expected/multi_data_types.out | 12 ++++++------ src/test/regress/sql/multi_data_types.sql | 8 ++++---- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/backend/distributed/planner/multi_physical_planner.c b/src/backend/distributed/planner/multi_physical_planner.c index 1b4172d3a..5e497970e 100644 --- a/src/backend/distributed/planner/multi_physical_planner.c +++ b/src/backend/distributed/planner/multi_physical_planner.c @@ -2808,6 +2808,10 @@ SimpleOpExpression(Expr *clause) return false; /* not a binary opclause */ } + /* strip coercions before doing check */ + leftOperand = strip_implicit_coercions(leftOperand); + rightOperand = strip_implicit_coercions(rightOperand); + if (IsA(rightOperand, Const) && IsA(leftOperand, Var)) { constantClause = (Const *) rightOperand; @@ -2919,6 +2923,10 @@ OpExpressionContainsColumn(OpExpr *operatorExpression, Var *partitionColumn) Node *rightOperand = get_rightop((Expr *) operatorExpression); Var *column = NULL; + /* strip coercions before doing check */ + leftOperand = strip_implicit_coercions(leftOperand); + rightOperand = strip_implicit_coercions(rightOperand); + if (IsA(leftOperand, Var)) { column = (Var *) leftOperand; diff --git a/src/test/regress/expected/multi_data_types.out b/src/test/regress/expected/multi_data_types.out index 8dc78f841..18b7a54dc 100644 --- a/src/test/regress/expected/multi_data_types.out +++ b/src/test/regress/expected/multi_data_types.out @@ -121,7 +121,7 @@ CREATE TABLE varchar_hash_partitioned_table id int, name varchar ); -SELECT master_create_distributed_table('varchar_hash_partitioned_table', 'id', 'hash'); +SELECT master_create_distributed_table('varchar_hash_partitioned_table', 'name', 'hash'); master_create_distributed_table --------------------------------- @@ -139,16 +139,16 @@ INSERT INTO varchar_hash_partitioned_table VALUES (2, 'Ozgun'); INSERT INTO varchar_hash_partitioned_table VALUES (3, 'Onder'); INSERT INTO varchar_hash_partitioned_table VALUES (4, 'Sumedh'); INSERT INTO varchar_hash_partitioned_table VALUES (5, 'Marco'); -SELECT * FROM varchar_hash_partitioned_table WHERE name = 'Onder'; +SELECT * FROM varchar_hash_partitioned_table WHERE id = 1; id | name ----+------- - 3 | Onder + 1 | Jason (1 row) -UPDATE varchar_hash_partitioned_table SET name = 'Samay' WHERE id = 5; -SELECT * FROM varchar_hash_partitioned_table WHERE name = 'Samay'; +UPDATE varchar_hash_partitioned_table SET id = 6 WHERE name = 'Jason'; +SELECT * FROM varchar_hash_partitioned_table WHERE id = 6; id | name ----+------- - 5 | Samay + 6 | Jason (1 row) diff --git a/src/test/regress/sql/multi_data_types.sql b/src/test/regress/sql/multi_data_types.sql index 99c603e63..68b84044f 100644 --- a/src/test/regress/sql/multi_data_types.sql +++ b/src/test/regress/sql/multi_data_types.sql @@ -104,7 +104,7 @@ CREATE TABLE varchar_hash_partitioned_table name varchar ); -SELECT master_create_distributed_table('varchar_hash_partitioned_table', 'id', 'hash'); +SELECT master_create_distributed_table('varchar_hash_partitioned_table', 'name', 'hash'); SELECT master_create_worker_shards('varchar_hash_partitioned_table', 4, 1); -- execute INSERT, SELECT and UPDATE queries on composite_type_partitioned_table @@ -114,8 +114,8 @@ INSERT INTO varchar_hash_partitioned_table VALUES (3, 'Onder'); INSERT INTO varchar_hash_partitioned_table VALUES (4, 'Sumedh'); INSERT INTO varchar_hash_partitioned_table VALUES (5, 'Marco'); -SELECT * FROM varchar_hash_partitioned_table WHERE name = 'Onder'; +SELECT * FROM varchar_hash_partitioned_table WHERE id = 1; -UPDATE varchar_hash_partitioned_table SET name = 'Samay' WHERE id = 5; +UPDATE varchar_hash_partitioned_table SET id = 6 WHERE name = 'Jason'; -SELECT * FROM varchar_hash_partitioned_table WHERE name = 'Samay'; +SELECT * FROM varchar_hash_partitioned_table WHERE id = 6;