Greetings, Attached is a patch which attempts to solve a few problems:
1) Filtering out partitions flexibly based on the results of an external function call (supplied by an extension). 2) Filtering out partitions from pg_inherits based on the same function call. 3) Filtering out partitions from a partitioned table BEFORE the partition is actually opened on-disk. The name "partitionChildAccess_hook" comes from the fact that the backend may not have access to a particular partition within the partitioned table. The idea would be to silently filter out the partition from queries to the parent table, which means also adjusting the returned contents of find_inheritance_children based on the external function. I am curious how the community feels about these patches and if there is an alternative approach to solve the above issues (perhaps another existing hook). Thanks for your time. -- Mike Palmiotto Software Engineer Crunchy Data Solutions https://crunchydata.com
diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c index 00f7957b3d..c4711490f1 100644 --- a/src/backend/catalog/pg_inherits.c +++ b/src/backend/catalog/pg_inherits.c @@ -25,6 +25,7 @@ #include "catalog/indexing.h" #include "catalog/pg_inherits.h" #include "parser/parse_type.h" +#include "partitioning/partprune.h" #include "storage/lmgr.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -92,11 +93,16 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode) while ((inheritsTuple = systable_getnext(scan)) != NULL) { inhrelid = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhrelid; + + if (enable_partition_pruning && inhrelid && !partitionChildAccess_hook(inhrelid)) + continue; + if (numoids >= maxoids) { maxoids *= 2; oidarr = (Oid *) repalloc(oidarr, maxoids * sizeof(Oid)); } + oidarr[numoids++] = inhrelid; } diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 0debac75c6..185bfc10eb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1067,6 +1067,13 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, continue; } + if (enable_partition_pruning && !partitionChildAccess_hook(childRTE->relid)) + { + /* Implement custom partition pruning filter*/ + set_dummy_rel_pathlist(childrel); + continue; + } + /* * CE failed, so finish copying/modifying targetlist and join quals. * diff --git a/src/include/partitioning/partprune.h b/src/include/partitioning/partprune.h index 2f75717ffb..968b0ccbe0 100644 --- a/src/include/partitioning/partprune.h +++ b/src/include/partitioning/partprune.h @@ -74,6 +74,12 @@ typedef struct PartitionPruneContext #define PruneCxtStateIdx(partnatts, step_id, keyno) \ ((partnatts) * (step_id) + (keyno)) +/* Custom partition child access hook. Provides further partition pruning given + * child OID. + */ +typedef bool (*partitionChildAccess_hook_type) (Oid childOID); +PGDLLIMPORT partitionChildAccess_hook_type partitionChildAccess_hook; + extern PartitionPruneInfo *make_partition_pruneinfo(struct PlannerInfo *root, struct RelOptInfo *parentrel, List *subpaths,