mirror of
https://github.com/HypoPG/hypopg
synced 2026-05-24 09:38:21 +00:00
Fix for pg10 partition pruning
This commit is contained in:
parent
1a9d1876bf
commit
7033609dfe
3 changed files with 107 additions and 1 deletions
32
hypopg.c
32
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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue