diff --git a/src/backend/distributed/planner/shard_pruning.c b/src/backend/distributed/planner/shard_pruning.c index a0adb7ee0..487685ee5 100644 --- a/src/backend/distributed/planner/shard_pruning.c +++ b/src/backend/distributed/planner/shard_pruning.c @@ -63,6 +63,7 @@ #include "nodes/nodeFuncs.h" #include "nodes/makefuncs.h" #include "optimizer/clauses.h" +#include "parser/parse_coerce.h" #include "utils/arrayaccess.h" #include "utils/catcache.h" #include "utils/lsyscache.h" @@ -715,13 +716,15 @@ AddNewConjuction(ClauseWalkerContext *context, OpExpr *op) */ static void AddPartitionKeyRestrictionToInstance(ClauseWalkerContext *context, OpExpr *opClause, - Var *varClause, Const *constantClause) + Var *partitionColumn, Const *constantClause) { PruningInstance *prune = context->currentPruningInstance; List *btreeInterpretationList = NULL; ListCell *btreeInterpretationCell = NULL; bool matchedOp = false; + Assert(IsBinaryCoercible(constantClause->consttype, partitionColumn->vartype)); + btreeInterpretationList = get_op_btree_interpretation(opClause->opno); foreach(btreeInterpretationCell, btreeInterpretationList) @@ -838,6 +841,9 @@ AddHashRestrictionToInstance(ClauseWalkerContext *context, OpExpr *opClause, List *btreeInterpretationList = NULL; ListCell *btreeInterpretationCell = NULL; + /* be paranoid */ + Assert(IsBinaryCoercible(constantClause->consttype, INT4OID)); + btreeInterpretationList = get_op_btree_interpretation(opClause->opno); foreach(btreeInterpretationCell, btreeInterpretationList) diff --git a/src/test/regress/expected/multi_prune_shard_list.out b/src/test/regress/expected/multi_prune_shard_list.out index f39264127..2bdf12640 100644 --- a/src/test/regress/expected/multi_prune_shard_list.out +++ b/src/test/regress/expected/multi_prune_shard_list.out @@ -203,3 +203,27 @@ SELECT print_sorted_shard_intervals('pruning_range'); {800004,800005,800006,800007} (1 row) +-- =================================================================== +-- test pruning using values whose types are coerced +-- =================================================================== +CREATE TABLE coerce_hash ( + id bigint NOT NULL, + value text NOT NULL +); +SELECT create_distributed_table('coerce_hash', 'id'); + create_distributed_table +-------------------------- + +(1 row) + +-- PostgreSQL will cast id to numeric rather than 1.0 to bigint... +-- We used to blindly pass the RHS' Datum to our comparison func., +-- resulting in inaccurate pruning. An Assert now verifies type- +-- compatibility; the following would crash the server in an Assert- +-- before the underlying issue was addressed. It looks like a boring +-- test now, but if the old behavior is restored, it should crash again. +SELECT * FROM coerce_hash WHERE id = 1.0::numeric; + id | value +----+------- +(0 rows) + diff --git a/src/test/regress/sql/multi_prune_shard_list.sql b/src/test/regress/sql/multi_prune_shard_list.sql index 39f32a502..89c73d0db 100644 --- a/src/test/regress/sql/multi_prune_shard_list.sql +++ b/src/test/regress/sql/multi_prune_shard_list.sql @@ -119,3 +119,21 @@ SELECT print_sorted_shard_intervals('pruning_range'); -- all shard placements are uninitialized UPDATE pg_dist_shard set shardminvalue = NULL, shardmaxvalue = NULL WHERE shardid = 103077; SELECT print_sorted_shard_intervals('pruning_range'); + +-- =================================================================== +-- test pruning using values whose types are coerced +-- =================================================================== + +CREATE TABLE coerce_hash ( + id bigint NOT NULL, + value text NOT NULL +); +SELECT create_distributed_table('coerce_hash', 'id'); + +-- PostgreSQL will cast id to numeric rather than 1.0 to bigint... +-- We used to blindly pass the RHS' Datum to our comparison func., +-- resulting in inaccurate pruning. An Assert now verifies type- +-- compatibility; the following would crash the server in an Assert- +-- before the underlying issue was addressed. It looks like a boring +-- test now, but if the old behavior is restored, it should crash again. +SELECT * FROM coerce_hash WHERE id = 1.0::numeric;