On Tue, Feb 26, 2019 at 1:06 PM Mike Palmiotto <mike.palmio...@crunchydata.com> wrote: > > On Tue, Feb 26, 2019 at 1:55 AM Tsunakawa, Takayuki > <tsunakawa.ta...@jp.fujitsu.com> wrote: > > > > From: Mike Palmiotto [mailto:mike.palmio...@crunchydata.com] > > > Attached is a patch which attempts to solve a few problems:
Updated patch attached. > > > <snip> > > What concrete problems would you expect this patch to solve? What kind of > > extensions do you imagine? I'd like to hear about the examples. For > > example, "PostgreSQL 12 will not be able to filter out enough partitions > > when planning/executing SELECT ... WHERE ... statement. But an extension > > like this can extract just one partition early." > > My only application of the patch thus far has been to apply an RLS > policy driven by the extension's results. For example: > > CREATE TABLE test.partpar > ( > a int, > b text DEFAULT (extension_default_bfield('test.partpar'::regclass::oid)) > ) PARTITION BY LIST (extension_translate_bfield(b)); > > CREATE POLICY filter_select on test.partpar for SELECT > USING (extension_filter_by_bfield(b)); > > CREATE POLICY filter_select on test.partpar for INSERT > WITH CHECK (extension_generate_insert_bfield('test.partpar'::regclass::oid) > = b); > > CREATE POLICY filter_update on test.partpar for UPDATE > USING (extension_filter_by_bfield(b)) > WITH CHECK (extension_filter_by_bfield(b)); > > CREATE POLICY filter_delete on test.partpar for DELETE > USING (extension_filter_by_bfield(b)); > > The function would filter based on some external criteria relating to > the username and the contents of the b column. > > The desired effect would be to have `SELECT * from test.partpar;` > return check only the partitions where username can see any row in the > table based on column b. This is applicable, for instance, when a > partition of test.partpar (say test.partpar_b2) is given a label with > `SECURITY LABEL on TABLE test.partpar_b2 IS 'foo';` which is exactly > the same as the b column for every row in said partition. Using this > hook, we can simply check the table label and kick the entire > partition out early on. This should greatly improve performance for > the case where you can enforce that the partition SECURITY LABEL and > the b column are the same. Is this explanation suitable, or is more information required? Thanks, -- 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..45c5de990f 100644 --- a/src/backend/catalog/pg_inherits.c +++ b/src/backend/catalog/pg_inherits.c @@ -24,7 +24,9 @@ #include "access/table.h" #include "catalog/indexing.h" #include "catalog/pg_inherits.h" +#include "optimizer/cost.h" #include "parser/parse_type.h" +#include "partitioning/partprune.h" #include "storage/lmgr.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -92,11 +94,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,