From 7033609dfec94da8b8f60d266a208106a826d8be Mon Sep 17 00:00:00 2001 From: yuzupy Date: Mon, 19 Nov 2018 16:04:26 +0900 Subject: [PATCH] Fix for pg10 partition pruning --- hypopg.c | 32 ++++++++++++++++++- hypopg_table.c | 72 ++++++++++++++++++++++++++++++++++++++++++ include/hypopg_table.h | 4 +++ 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/hypopg.c b/hypopg.c index 926b965..5f3edf3 100644 --- a/hypopg.c +++ b/hypopg.c @@ -104,6 +104,13 @@ static bool hypo_get_relation_stats_hook(PlannerInfo *root, AttrNumber attnum, VariableStatData *vardata); static get_relation_stats_hook_type prev_get_relation_stats_hook = NULL; +#if PG_VERSION_NUM < 110000 +static void hypo_set_rel_pathlist_hook(PlannerInfo *root, + RelOptInfo *rel, + Index rti, + RangeTblEntry *rte); +static set_rel_pathlist_hook_type prev_set_rel_pathlist_hook = NULL; +#endif static bool hypo_query_walker(Node *node, hypoWalkerContext *context); static void hypo_CacheRelCallback(Datum arg, Oid relid); @@ -126,7 +133,10 @@ _PG_init(void) prev_get_relation_stats_hook = get_relation_stats_hook; get_relation_stats_hook = hypo_get_relation_stats_hook; - +#if PG_VERSION_NUM < 110000 + prev_set_rel_pathlist_hook = set_rel_pathlist_hook; + set_rel_pathlist_hook = hypo_set_rel_pathlist_hook; +#endif isExplain = false; hypoIndexes = NIL; #if PG_VERSION_NUM >= 100000 @@ -167,6 +177,9 @@ _PG_fini(void) get_relation_info_hook = prev_get_relation_info_hook; explain_get_index_name_hook = prev_explain_get_index_name_hook; get_relation_stats_hook = prev_get_relation_stats_hook; +#if PG_VERSION_NUM < 110000 + set_rel_pathlist_hook = prev_set_rel_pathlist_hook; +#endif } /*--------------------------------- @@ -685,6 +698,23 @@ hypo_get_relation_stats_hook(PlannerInfo *root, #endif } +#if PG_VERSION_NUM < 110000 +/* + * if this child relation is excluded by constraints, call set_dummy_rel_pathlist + */ +static void +hypo_set_rel_pathlist_hook(PlannerInfo *root, + RelOptInfo *rel, + Index rti, + RangeTblEntry *rte) +{ + if(HYPO_ENABLED() && hypo_table_oid_is_hypothetical(rte->relid) && rte->relkind == 'r') + hypo_markDummyIfExcluded(root,rel,rti,rte); + + if (prev_set_rel_pathlist_hook) + prev_set_rel_pathlist_hook(root, rel, rti, rte); +} +#endif /* * Reset all stored entries. diff --git a/hypopg_table.c b/hypopg_table.c index c24db97..725b3ae 100644 --- a/hypopg_table.c +++ b/hypopg_table.c @@ -159,6 +159,10 @@ hypo_expand_partitioned_entry(PlannerInfo *root, Oid relationObjectId, int i, j; PartitionDesc partdesc; Oid *partoids; +#if PG_VERSION_NUM < 110000 + List *partitioned_child_rels = NIL; + PartitionedChildRelInfo *pcinfo; +#endif Assert(hypo_table_oid_is_hypothetical(relationObjectId)); @@ -219,6 +223,10 @@ hypo_expand_partitioned_entry(PlannerInfo *root, Oid relationObjectId, hypo_expand_single_inheritance_child(root, relationObjectId, rel, parentrel, branch, rte, branch, firstpos, parent_rti, true); +#if PG_VERSION_NUM < 110000 + partitioned_child_rels = lappend_int(partitioned_child_rels, + firstpos); +#endif firstpos++; } @@ -276,6 +284,17 @@ hypo_expand_partitioned_entry(PlannerInfo *root, Oid relationObjectId, newrelid++; } +#if PG_VERSION_NUM < 110000 + /* create pcinfo for this relation */ + if (partitioned_child_rels != NIL) + { + pcinfo = makeNode(PartitionedChildRelInfo); + pcinfo->parent_relid = oldsize; + pcinfo->child_rels = partitioned_child_rels; + root->pcinfo_list = lappend(root->pcinfo_list, pcinfo); + } +#endif + #if PG_VERSION_NUM >= 110000 /* add partition info for root partition */ if (!branch) @@ -2235,6 +2254,59 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, #endif } +#if PGVERSION_NUM < 110000 +/* + * If this rel is need not be scanned, we have to mark it as dummy to omit it + * from the appendrel + * + * It is inspired on relation_excluded_by_constraints + */ +void +hypo_markDummyIfExcluded(PlannerInfo *root, RelOptInfo *rel, + Index rti, RangeTblEntry *rte) +{ + List *constraints; + List *safe_constraints = NIL; + ListCell *lc; + Oid partoid = HYPO_TABLE_RTE_GET_HYPOOID(rte); + hypoTable *part = hypo_find_table(partoid, false); + hypoTable *parent = hypo_find_table(part->parentid, false); + + Assert(hypo_table_oid_is_hypothetical(rte->relid)); + Assert(rte->relkind == 'r'); + + /* get its partition constraints */ + constraints = hypo_get_partition_constraints(root, rel, parent); + + /* + * We do not currently enforce that CHECK constraints contain only + * immutable functions, so it's necessary to check here. We daren't draw + * conclusions from plan-time evaluation of non-immutable functions. Since + * they're ANDed, we can just ignore any mutable constraints in the list, + * and reason about the rest. + */ + foreach(lc, constraints) + { + Node *pred = (Node *) lfirst(lc); + + if (!contain_mutable_functions(pred)) + safe_constraints = lappend(safe_constraints, pred); + } + + /* + * if this partition need not be scanned, we call the set_dummy_rel_pathlist() + * to mark it as dummy + */ + if (predicate_refuted_by(safe_constraints, rel->baserestrictinfo, false)) + set_dummy_rel_pathlist(rel); + + /* + TODO: re-estimate parent size just like set_append_rel_size() + */ + + +} +#endif #if PG_VERSION_NUM >= 110000 /* diff --git a/include/hypopg_table.h b/include/hypopg_table.h index 680e8f7..6900ee9 100644 --- a/include/hypopg_table.h +++ b/include/hypopg_table.h @@ -92,6 +92,10 @@ bool hypo_table_remove(Oid tableid, hypoTable *parent, bool deep); void hypo_injectHypotheticalPartitioning(PlannerInfo *root, Oid relationObjectId, RelOptInfo *rel); +#if PG_VERSION_NUM < 110000 +void hypo_markDummyIfExcluded(PlannerInfo *root, RelOptInfo *rel, + Index rti, RangeTblEntry *rte); +#endif #endif #endif