Fix for pg10 partition pruning

This commit is contained in:
yuzupy 2018-11-19 16:04:26 +09:00 committed by Julien Rouhaud
parent 1a9d1876bf
commit 7033609dfe
3 changed files with 107 additions and 1 deletions

View file

@ -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.

View file

@ -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
/*

View file

@ -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