From cf8319b992aa4e60cf2acab4d9485a6349505dea Mon Sep 17 00:00:00 2001 From: Markus Sintonen Date: Sun, 16 Feb 2020 01:21:10 +0200 Subject: [PATCH] Add comment, add subquery NOT tests --- .../distributed/planner/shard_pruning.c | 6 +- .../regress/expected/multi_hash_pruning.out | 59 +++++++++++++++++++ src/test/regress/expected/null_parameters.out | 3 - src/test/regress/sql/multi_hash_pruning.sql | 8 +++ 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/backend/distributed/planner/shard_pruning.c b/src/backend/distributed/planner/shard_pruning.c index 25200e39d..38ac32e88 100644 --- a/src/backend/distributed/planner/shard_pruning.c +++ b/src/backend/distributed/planner/shard_pruning.c @@ -560,9 +560,11 @@ BuildPruningTree(Node *node, PruningTreeBuildContext *context) if (boolExpr->boolop == NOT_EXPR) { /* - * We should not encounter NOT_EXPR nodes. + * With Var-Const conditions we should not encounter NOT_EXPR nodes. * Postgres standard planner applies De Morgan's laws to remove them. - * But if we encounter one, we treat it as invalid constraint for pruning. + * We still encounter them with subqueries inside NOT, for example with: + * WHERE id NOT IN (SELECT id FROM something). + * We treat these as invalid constraints for pruning when we encounter them. */ context->current->hasInvalidConstraints = true; diff --git a/src/test/regress/expected/multi_hash_pruning.out b/src/test/regress/expected/multi_hash_pruning.out index a6676a70e..0fc97ad84 100644 --- a/src/test/regress/expected/multi_hash_pruning.out +++ b/src/test/regress/expected/multi_hash_pruning.out @@ -1056,4 +1056,63 @@ DEBUG: assigned task to node localhost:xxxxx 4 (1 row) +-- Check that subquery NOT is pruned when ANDed to a valid constraint +SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey IN (1,2) AND o_custkey NOT IN (SELECT o_custkey FROM orders_hash_partitioned WHERE o_orderkey = 1); +DEBUG: constraint value: 1 +DEBUG: shard count: 1 +DEBUG: constraint value: 1 +DEBUG: constraint value: 2 +DEBUG: shard count: 2 +DEBUG: Router planner cannot handle multi-shard select queries +DEBUG: constraint value: 1 +DEBUG: shard count: 1 +DEBUG: Creating router plan +DEBUG: Plan is router executable +DETAIL: distribution column value: 1 +DEBUG: generating subplan XXX_1 for subquery SELECT o_custkey FROM public.orders_hash_partitioned WHERE (o_orderkey OPERATOR(pg_catalog.=) 1) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM public.orders_hash_partitioned WHERE ((o_orderkey OPERATOR(pg_catalog.=) ANY (ARRAY[1, 2])) AND (NOT (o_custkey OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.o_custkey FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(o_custkey integer))))) +DEBUG: constraint value: 1 +DEBUG: constraint value: 2 +DEBUG: shard count: 2 +DEBUG: Router planner cannot handle multi-shard select queries +DEBUG: constraint value: 1 +DEBUG: constraint value: 2 +DEBUG: shard count: 2 +DEBUG: assigned task to node localhost:xxxxx +DEBUG: assigned task to node localhost:xxxxx + count +--------------------------------------------------------------------- + 1 +(1 row) + +-- Check that subquery NOT is unpruned when ORed to a valid constraint +SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey IN (1,2) OR o_custkey NOT IN (SELECT o_custkey FROM orders_hash_partitioned WHERE o_orderkey = 3); +DEBUG: constraint value: 3 +DEBUG: shard count: 1 +DEBUG: no valid constraints found +DEBUG: shard count: 4 +DEBUG: Router planner cannot handle multi-shard select queries +DEBUG: constraint value: 3 +DEBUG: shard count: 1 +DEBUG: Creating router plan +DEBUG: Plan is router executable +DETAIL: distribution column value: 3 +DEBUG: generating subplan XXX_1 for subquery SELECT o_custkey FROM public.orders_hash_partitioned WHERE (o_orderkey OPERATOR(pg_catalog.=) 3) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM public.orders_hash_partitioned WHERE ((o_orderkey OPERATOR(pg_catalog.=) ANY (ARRAY[1, 2])) OR (NOT (o_custkey OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.o_custkey FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(o_custkey integer))))) +DEBUG: no valid constraints found +DEBUG: shard count: 4 +DEBUG: Router planner cannot handle multi-shard select queries +DEBUG: no valid constraints found +DEBUG: shard count: 4 +DEBUG: assigned task to node localhost:xxxxx +DEBUG: assigned task to node localhost:xxxxx +DEBUG: assigned task to node localhost:xxxxx +DEBUG: assigned task to node localhost:xxxxx + count +--------------------------------------------------------------------- + 3 +(1 row) + SET client_min_messages TO DEFAULT; diff --git a/src/test/regress/expected/null_parameters.out b/src/test/regress/expected/null_parameters.out index 6661ae8ec..8f6c17922 100644 --- a/src/test/regress/expected/null_parameters.out +++ b/src/test/regress/expected/null_parameters.out @@ -1429,9 +1429,6 @@ DEBUG: Deferred pruning for a fast-path router query DEBUG: Creating router plan DEBUG: Plan is router executable EXECUTE null_update_on_text_param_and_in(NULL); -DEBUG: Deferred pruning for a fast-path router query -DEBUG: Creating router plan -DEBUG: Plan is router executable PREPARE null_update_on_text_param_and_in_2(text) AS UPDATE text_dist_column SET value = '' WHERE key IN ($1, 'test'); EXECUTE null_update_on_text_param_and_in_2(NULL); DEBUG: Creating router plan diff --git a/src/test/regress/sql/multi_hash_pruning.sql b/src/test/regress/sql/multi_hash_pruning.sql index 91a63a8e9..beb55b8f0 100644 --- a/src/test/regress/sql/multi_hash_pruning.sql +++ b/src/test/regress/sql/multi_hash_pruning.sql @@ -274,4 +274,12 @@ SELECT count(*) FROM orders_hash_partitioned SELECT count(*) FROM orders_hash_partitioned WHERE NOT (o_orderkey = 2 AND o_orderkey = 3); +-- Check that subquery NOT is pruned when ANDed to a valid constraint +SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey IN (1,2) AND o_custkey NOT IN (SELECT o_custkey FROM orders_hash_partitioned WHERE o_orderkey = 1); + +-- Check that subquery NOT is unpruned when ORed to a valid constraint +SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey IN (1,2) OR o_custkey NOT IN (SELECT o_custkey FROM orders_hash_partitioned WHERE o_orderkey = 3); + SET client_min_messages TO DEFAULT;