From 84b4eeca10fbcf9f87e3e61284ecc1894743923d Mon Sep 17 00:00:00 2001 From: yuzupy Date: Tue, 27 Mar 2018 08:53:38 +0000 Subject: [PATCH 1/5] Fix rel->pages of hypothetical partition --- hypopg_table.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hypopg_table.c b/hypopg_table.c index 1e6c652..53ccc57 100644 --- a/hypopg_table.c +++ b/hypopg_table.c @@ -1864,7 +1864,8 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, List *constraints; PlannerInfo *root_dummy; Selectivity selectivity; - + double pages; + /* get its partition constraints */ constraints = hypo_get_partition_constraints(root, rel, parent); @@ -1882,9 +1883,9 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, JOIN_INNER, NULL); - rel->pages = rint(rel->pages * selectivity); + pages = ceil(rel->pages * selectivity); + rel->pages = (BlockNumber)pages; rel->tuples = clamp_row_est(rel->tuples * selectivity); - } } From de920f9db0b09eba7774c839aa8ed48ce8e77b12 Mon Sep 17 00:00:00 2001 From: yuzupy Date: Mon, 2 Apr 2018 09:50:30 +0000 Subject: [PATCH 2/5] Add the partition estimation feature --- hypopg.c | 3 +- hypopg_import.c | 58 ++++++++++++++- hypopg_table.c | 159 ++++++++++++++++++++++++++++++++++------ include/hypopg_import.h | 4 +- include/hypopg_table.h | 2 + 5 files changed, 200 insertions(+), 26 deletions(-) diff --git a/hypopg.c b/hypopg.c index 3ca82e7..d6b7d10 100644 --- a/hypopg.c +++ b/hypopg.c @@ -361,7 +361,8 @@ hypo_set_rel_pathlist_hook(PlannerInfo *root, RangeTblEntry *rte) { if(HYPO_ENABLED() && hypo_table_oid_is_hypothetical(rte->relid) && rte->relkind == 'r') - hypo_markDummyIfExcluded(root,rel,rti,rte); + // hypo_markDummyIfExcluded(root,rel,rti,rte); + hypo_setPartitionPathlist(root,rel,rti,rte); if (prev_set_rel_pathlist_hook) prev_set_rel_pathlist_hook(root, rel, rti, rte); diff --git a/hypopg_import.c b/hypopg_import.c index 3dabeae..d0ce3f0 100644 --- a/hypopg_import.c +++ b/hypopg_import.c @@ -51,7 +51,7 @@ #include "include/hypopg_import.h" - +int max_parallel_workers_per_gather = 2; @@ -1565,4 +1565,60 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation, *translated_vars = vars; } + +/* + * Copied from src/backend/optimizer/path/allpaths.c, not exported + * + * set_plain_rel_pathlist + * Build access paths for a plain relation (no subquery, no inheritance) + */ +void +set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) +{ + Relids required_outer; + + /* + * We don't support pushing join clauses into the quals of a seqscan, but + * it could still have required parameterization due to LATERAL refs in + * its tlist. + */ + required_outer = rel->lateral_relids; + + /* Consider sequential scan */ + add_path(rel, create_seqscan_path(root, rel, required_outer, 0)); + + /* If appropriate, consider parallel sequential scan */ + if (rel->consider_parallel && required_outer == NULL) + create_plain_partial_paths(root, rel); + + /* Consider index scans */ + create_index_paths(root, rel); + + /* Consider TID scans */ + create_tidscan_paths(root, rel); +} + +/* + * Copied from src/backend/optimizer/path/allpaths.c, not exported + * + * create_plain_partial_paths + * Build partial access paths for parallel scan of a plain relation + */ +void +create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel) +{ + int parallel_workers; + + parallel_workers = compute_parallel_worker(rel, rel->pages, -1, + max_parallel_workers_per_gather); + + /* If any limit was set to zero, the user doesn't want a parallel scan. */ + if (parallel_workers <= 0) + return; + + /* Add an unordered partial path based on a parallel sequential scan. */ + add_partial_path(rel, create_seqscan_path(root, rel, NULL, parallel_workers)); +} + + #endif diff --git a/hypopg_table.c b/hypopg_table.c index 53ccc57..2c36340 100644 --- a/hypopg_table.c +++ b/hypopg_table.c @@ -35,8 +35,11 @@ #include "nodes/nodes.h" #include "optimizer/clauses.h" #include "optimizer/cost.h" +#include "optimizer/pathnode.h" #include "optimizer/predtest.h" #include "optimizer/prep.h" +#include "optimizer/restrictinfo.h" +#include "optimizer/var.h" #include "parser/parsetree.h" #include "parser/parse_utilcmd.h" #include "rewrite/rewriteManip.h" @@ -1855,37 +1858,32 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, /* - * if this rel is partition, rewrite tuples and pages using selectivity - * which is computed according to its partition constraints + * If this rel is partition, we add the partition constraints to the + * rte->securityQuals so that the relation which is need not be scanned + * is marked as Dummy at the set_append_rel_size() and the rel->rows is + * computed correctly at the set_baserel_size_estimates(). We shouldn't + * rewrite the rel->pages and the rel->tuples here, because they will be + * rewritten at the later hook. + * + * TODO: should comfirm that the tuples will not referred till the + * set_baserel_size_esimates() and think about rel->reltarget->width + * */ if (rel->reloptkind != RELOPT_BASEREL &&HYPO_RTI_IS_TAGGED(rel->relid,root)) { List *constraints; - PlannerInfo *root_dummy; - Selectivity selectivity; - double pages; /* get its partition constraints */ constraints = hypo_get_partition_constraints(root, rel, parent); - /* - * to compute selectivity, make dummy PlannerInfo and then rewrite - * tuples and pages using this selectivity + /* + * to compute rel->rows at set_baserel_size_estimates using parent's + * statistics, parent's tuples and baserestrictinfo, we add the partition + * constraints to its rte->securityQuals */ - root_dummy = makeNode(PlannerInfo); - root_dummy = root; - root_dummy->simple_rel_array[rel->relid] = rel; - - selectivity = clauselist_selectivity(root_dummy, - constraints, - 0, - JOIN_INNER, - NULL); - - pages = ceil(rel->pages * selectivity); - rel->pages = (BlockNumber)pages; - rel->tuples = clamp_row_est(rel->tuples * selectivity); + planner_rt_fetch(rel->relid, root)->securityQuals = list_make1(constraints); + } } @@ -1937,11 +1935,126 @@ void hypo_markDummyIfExcluded(PlannerInfo *root, RelOptInfo *rel, /* TODO: re-estimate parent size just like set_append_rel_size() */ - - + } + +/* + * If this rel is partition, we remove the partition constraints from the + * its rel->baserestrictinfo and rewrite some items of its RelOptInfo: + * the rel->pages, the rel->tuples rel->baserestrictcost. After that + * we call the set_plain_rel_pathlist() to re-create its pathlist using + * the new RelOptInfo. + * + */ + +void hypo_setPartitionPathlist(PlannerInfo *root, RelOptInfo *rel, + Index rti, RangeTblEntry *rte) +{ + ListCell *l; + Index parentRTindex; + RelOptInfo *parentrel; + hypoTable *parent = hypo_find_table(rte->relid); + List *constraints = hypo_get_partition_constraints(root, rel, parent); + PlannerInfo *root_dummy; + Selectivity selectivity; + double pages; + + /* + * get the parent's rel and copy its rel->baserestrictinfo to + * the own rel->baserestrictinfo. + * this part is inspired on set_append_rel_size(). + */ + foreach(l, root->append_rel_list) + { + AppendRelInfo *appinfo = (AppendRelInfo *)lfirst(l); + List *childquals = NIL; + Index cq_min_security = UINT_MAX; + ListCell *lc; + + if(appinfo->child_relid == rti) + { + parentRTindex = appinfo->parent_relid; + parentrel = root->simple_rel_array[parentRTindex]; + + foreach(lc, parentrel->baserestrictinfo) + { + RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); + Node *childqual; + ListCell *lc2; + + Assert(IsA(rinfo, RestrictInfo)); + childqual = adjust_appendrel_attrs(root, + (Node *) rinfo->clause, + 1, &appinfo); + childqual = eval_const_expressions(root, childqual); + + /* might have gotten an AND clause, if so flatten it */ + foreach(lc2, make_ands_implicit((Expr *) childqual)) + { + Node *onecq = (Node *) lfirst(lc2); + bool pseudoconstant; + + /* check for pseudoconstant (no Vars or volatile functions) */ + pseudoconstant = + !contain_vars_of_level(onecq, 0) && + !contain_volatile_functions(onecq); + if (pseudoconstant) + { + /* tell createplan.c to check for gating quals */ + root->hasPseudoConstantQuals = true; + } + /* reconstitute RestrictInfo with appropriate properties */ + childquals = lappend(childquals, + make_restrictinfo((Expr *) onecq, + rinfo->is_pushed_down, + rinfo->outerjoin_delayed, + pseudoconstant, + rinfo->security_level, + NULL, NULL, NULL)); + /* track minimum security level among child quals */ + cq_min_security = Min(cq_min_security, rinfo->security_level); + } + } + rel->baserestrictinfo = childquals; + rel->baserestrict_min_security = cq_min_security; + break; + } + } + + /* + * make dummy PlannerInfo to compute the selectivity, and then rewrite + * tuples and pages using this selectivity + */ + root_dummy = makeNode(PlannerInfo); + root_dummy = root; + root_dummy->simple_rel_array[rti] = rel; + + selectivity = clauselist_selectivity(root_dummy, + constraints, + 0, + JOIN_INNER, + NULL); + + pages = ceil(rel->pages * selectivity); + rel->pages = (BlockNumber)pages; + rel->tuples = clamp_row_est(rel->tuples * selectivity); + + /* recompute the rel->baserestrictcost*/ + cost_qual_eval(&rel->baserestrictcost, rel->baserestrictinfo, root); + + /* + * call the set_plain_rel_pathlist() to re-create its pathlist using + * the new RelOptInfo + */ + set_plain_rel_pathlist(root, rel, rte); + +} + + + + /* * If this is the table we want to hypothetically partition, modifies its * metadata to add partitioning information diff --git a/include/hypopg_import.h b/include/hypopg_import.h index d2a5ba4..7f88688 100644 --- a/include/hypopg_import.h +++ b/include/hypopg_import.h @@ -14,6 +14,7 @@ #include "nodes/pg_list.h" #include "optimizer/planner.h" +#include "optimizer/pathnode.h" #include "utils/rel.h" @@ -132,7 +133,8 @@ List *get_range_nulltest(PartitionKey key); void make_inh_translation_list(Relation oldrelation, Relation newrelation, Index newvarno, List **translated_vars); - +void set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte); +void create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel); /* Copied from src/backend/catalog/partition.c, not exported */ #define partition_bound_accepts_nulls(bi) ((bi)->null_index != -1) diff --git a/include/hypopg_table.h b/include/hypopg_table.h index bc3a30c..6da8f93 100644 --- a/include/hypopg_table.h +++ b/include/hypopg_table.h @@ -73,5 +73,7 @@ void hypo_injectHypotheticalPartitioning(PlannerInfo *root, RelOptInfo *rel); void hypo_markDummyIfExcluded(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte); +void hypo_setPartitionPathlist(PlannerInfo *root, RelOptInfo *rel, + Index rti, RangeTblEntry *rte); #endif From c6922fd4eb027b3deb39bacf39b837a734c486df Mon Sep 17 00:00:00 2001 From: yuzupy Date: Tue, 27 Mar 2018 08:53:38 +0000 Subject: [PATCH 3/5] Fix rel->pages of hypothetical partition --- hypopg_table.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/hypopg_table.c b/hypopg_table.c index 1dd6fe3..7fa463e 100644 --- a/hypopg_table.c +++ b/hypopg_table.c @@ -1848,44 +1848,44 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, pcinfo->parent_relid = oldsize; pcinfo->child_rels = partitioned_child_rels; root->pcinfo_list = lappend(root->pcinfo_list, pcinfo); - + /* add partition info to this rel */ hypo_partition_table(root, rel, parent); } - - - /* + + /* * if this rel is partition, rewrite tuples and pages using selectivity * which is computed according to its partition constraints */ if (rel->reloptkind != RELOPT_BASEREL - &&HYPO_RTI_IS_TAGGED(rel->relid,root)) - { + &&HYPO_RTI_IS_TAGGED(rel->relid,root)) + { List *constraints; PlannerInfo *root_dummy; Selectivity selectivity; + double pages; /* get its partition constraints */ constraints = hypo_get_partition_constraints(root, rel, parent); - - /* + + /* * to compute selectivity, make dummy PlannerInfo and then rewrite * tuples and pages using this selectivity */ root_dummy = makeNode(PlannerInfo); root_dummy = root; root_dummy->simple_rel_array[rel->relid] = rel; - - selectivity = clauselist_selectivity(root_dummy, - constraints, - 0, - JOIN_INNER, - NULL); - - rel->pages = rint(rel->pages * selectivity); + + selectivity = clauselist_selectivity(root_dummy, + constraints, + 0, + JOIN_INNER, + NULL); + + pages = ceil(rel->pages * selectivity); + rel->pages = (BlockNumber)pages; rel->tuples = clamp_row_est(rel->tuples * selectivity); - - } + } } From 5ff3f80a8a79688f010f3dab22ee7ae12807465a Mon Sep 17 00:00:00 2001 From: yuzupy Date: Mon, 2 Apr 2018 09:50:30 +0000 Subject: [PATCH 4/5] Add the partition estimation feature --- hypopg.c | 16 ++-- hypopg_import.c | 58 +++++++++++++- hypopg_table.c | 166 +++++++++++++++++++++++++++++++++------- include/hypopg_import.h | 4 +- include/hypopg_table.h | 2 + 5 files changed, 209 insertions(+), 37 deletions(-) diff --git a/hypopg.c b/hypopg.c index b6beb54..85c4ea7 100644 --- a/hypopg.c +++ b/hypopg.c @@ -356,16 +356,16 @@ hypo_get_relation_info_hook(PlannerInfo *root, */ static void hypo_set_rel_pathlist_hook(PlannerInfo *root, - RelOptInfo *rel, - Index rti, - RangeTblEntry *rte) + 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(HYPO_ENABLED() && hypo_table_oid_is_hypothetical(rte->relid) && rte->relkind == 'r') + // hypo_markDummyIfExcluded(root,rel,rti,rte); + hypo_setPartitionPathlist(root,rel,rti,rte); + if (prev_set_rel_pathlist_hook) - prev_set_rel_pathlist_hook(root, rel, rti, rte); + prev_set_rel_pathlist_hook(root, rel, rti, rte); } diff --git a/hypopg_import.c b/hypopg_import.c index b2ceb94..cbf6cd9 100644 --- a/hypopg_import.c +++ b/hypopg_import.c @@ -51,7 +51,7 @@ #include "include/hypopg_import.h" - +int max_parallel_workers_per_gather = 2; @@ -1565,4 +1565,60 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation, *translated_vars = vars; } + +/* + * Copied from src/backend/optimizer/path/allpaths.c, not exported + * + * set_plain_rel_pathlist + * Build access paths for a plain relation (no subquery, no inheritance) + */ +void +set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) +{ + Relids required_outer; + + /* + * We don't support pushing join clauses into the quals of a seqscan, but + * it could still have required parameterization due to LATERAL refs in + * its tlist. + */ + required_outer = rel->lateral_relids; + + /* Consider sequential scan */ + add_path(rel, create_seqscan_path(root, rel, required_outer, 0)); + + /* If appropriate, consider parallel sequential scan */ + if (rel->consider_parallel && required_outer == NULL) + create_plain_partial_paths(root, rel); + + /* Consider index scans */ + create_index_paths(root, rel); + + /* Consider TID scans */ + create_tidscan_paths(root, rel); +} + +/* + * Copied from src/backend/optimizer/path/allpaths.c, not exported + * + * create_plain_partial_paths + * Build partial access paths for parallel scan of a plain relation + */ +void +create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel) +{ + int parallel_workers; + + parallel_workers = compute_parallel_worker(rel, rel->pages, -1, + max_parallel_workers_per_gather); + + /* If any limit was set to zero, the user doesn't want a parallel scan. */ + if (parallel_workers <= 0) + return; + + /* Add an unordered partial path based on a parallel sequential scan. */ + add_partial_path(rel, create_seqscan_path(root, rel, NULL, parallel_workers)); +} + + #endif diff --git a/hypopg_table.c b/hypopg_table.c index 7fa463e..b5097f9 100644 --- a/hypopg_table.c +++ b/hypopg_table.c @@ -35,8 +35,11 @@ #include "nodes/nodes.h" #include "optimizer/clauses.h" #include "optimizer/cost.h" +#include "optimizer/pathnode.h" #include "optimizer/predtest.h" #include "optimizer/prep.h" +#include "optimizer/restrictinfo.h" +#include "optimizer/var.h" #include "parser/parsetree.h" #include "parser/parse_utilcmd.h" #include "rewrite/rewriteManip.h" @@ -1852,39 +1855,34 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, /* add partition info to this rel */ hypo_partition_table(root, rel, parent); } - + /* - * if this rel is partition, rewrite tuples and pages using selectivity - * which is computed according to its partition constraints + * If this rel is partition, we add the partition constraints to the + * rte->securityQuals so that the relation which is need not be scanned + * is marked as Dummy at the set_append_rel_size() and the rel->rows is + * computed correctly at the set_baserel_size_estimates(). We shouldn't + * rewrite the rel->pages and the rel->tuples here, because they will be + * rewritten at the later hook. + * + * TODO: should comfirm that the tuples will not referred till the + * set_baserel_size_esimates() and think about rel->reltarget->width + * */ if (rel->reloptkind != RELOPT_BASEREL &&HYPO_RTI_IS_TAGGED(rel->relid,root)) { List *constraints; - PlannerInfo *root_dummy; - Selectivity selectivity; - double pages; - + /* get its partition constraints */ constraints = hypo_get_partition_constraints(root, rel, parent); - /* - * to compute selectivity, make dummy PlannerInfo and then rewrite - * tuples and pages using this selectivity + /* + * to compute rel->rows at set_baserel_size_estimates using parent's + * statistics, parent's tuples and baserestrictinfo, we add the partition + * constraints to its rte->securityQuals */ - root_dummy = makeNode(PlannerInfo); - root_dummy = root; - root_dummy->simple_rel_array[rel->relid] = rel; - - selectivity = clauselist_selectivity(root_dummy, - constraints, - 0, - JOIN_INNER, - NULL); - - pages = ceil(rel->pages * selectivity); - rel->pages = (BlockNumber)pages; - rel->tuples = clamp_row_est(rel->tuples * selectivity); + planner_rt_fetch(rel->relid, root)->securityQuals = list_make1(constraints); + } } @@ -1934,13 +1932,127 @@ void hypo_markDummyIfExcluded(PlannerInfo *root, RelOptInfo *rel, /* -TODO: re-estimate parent size just like set_append_rel_size() -*/ - - + TODO: re-estimate parent size just like set_append_rel_size() + */ + } + +/* + * If this rel is partition, we remove the partition constraints from the + * its rel->baserestrictinfo and rewrite some items of its RelOptInfo: + * the rel->pages, the rel->tuples rel->baserestrictcost. After that + * we call the set_plain_rel_pathlist() to re-create its pathlist using + * the new RelOptInfo. + * + */ + +void hypo_setPartitionPathlist(PlannerInfo *root, RelOptInfo *rel, + Index rti, RangeTblEntry *rte) +{ + ListCell *l; + Index parentRTindex; + RelOptInfo *parentrel; + hypoTable *parent = hypo_find_table(rte->relid); + List *constraints = hypo_get_partition_constraints(root, rel, parent); + PlannerInfo *root_dummy; + Selectivity selectivity; + double pages; + + /* + * get the parent's rel and copy its rel->baserestrictinfo to + * the own rel->baserestrictinfo. + * this part is inspired on set_append_rel_size(). + */ + foreach(l, root->append_rel_list) + { + AppendRelInfo *appinfo = (AppendRelInfo *)lfirst(l); + List *childquals = NIL; + Index cq_min_security = UINT_MAX; + ListCell *lc; + + if(appinfo->child_relid == rti) + { + parentRTindex = appinfo->parent_relid; + parentrel = root->simple_rel_array[parentRTindex]; + + foreach(lc, parentrel->baserestrictinfo) + { + RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); + Node *childqual; + ListCell *lc2; + + Assert(IsA(rinfo, RestrictInfo)); + childqual = adjust_appendrel_attrs(root, + (Node *) rinfo->clause, + 1, &appinfo); + childqual = eval_const_expressions(root, childqual); + + /* might have gotten an AND clause, if so flatten it */ + foreach(lc2, make_ands_implicit((Expr *) childqual)) + { + Node *onecq = (Node *) lfirst(lc2); + bool pseudoconstant; + + /* check for pseudoconstant (no Vars or volatile functions) */ + pseudoconstant = + !contain_vars_of_level(onecq, 0) && + !contain_volatile_functions(onecq); + if (pseudoconstant) + { + /* tell createplan.c to check for gating quals */ + root->hasPseudoConstantQuals = true; + } + /* reconstitute RestrictInfo with appropriate properties */ + childquals = lappend(childquals, + make_restrictinfo((Expr *) onecq, + rinfo->is_pushed_down, + rinfo->outerjoin_delayed, + pseudoconstant, + rinfo->security_level, + NULL, NULL, NULL)); + /* track minimum security level among child quals */ + cq_min_security = Min(cq_min_security, rinfo->security_level); + } + } + rel->baserestrictinfo = childquals; + rel->baserestrict_min_security = cq_min_security; + break; + } + } + + /* + * make dummy PlannerInfo to compute the selectivity, and then rewrite + * tuples and pages using this selectivity + */ + root_dummy = makeNode(PlannerInfo); + root_dummy = root; + root_dummy->simple_rel_array[rti] = rel; + + selectivity = clauselist_selectivity(root_dummy, + constraints, + 0, + JOIN_INNER, + NULL); + + pages = ceil(rel->pages * selectivity); + rel->pages = (BlockNumber)pages; + rel->tuples = clamp_row_est(rel->tuples * selectivity); + + /* recompute the rel->baserestrictcost*/ + cost_qual_eval(&rel->baserestrictcost, rel->baserestrictinfo, root); + + /* + * call the set_plain_rel_pathlist() to re-create its pathlist using + * the new RelOptInfo + */ + set_plain_rel_pathlist(root, rel, rte); +} + + + + /* * If this is the table we want to hypothetically partition, modifies its * metadata to add partitioning information diff --git a/include/hypopg_import.h b/include/hypopg_import.h index d2a5ba4..7f88688 100644 --- a/include/hypopg_import.h +++ b/include/hypopg_import.h @@ -14,6 +14,7 @@ #include "nodes/pg_list.h" #include "optimizer/planner.h" +#include "optimizer/pathnode.h" #include "utils/rel.h" @@ -132,7 +133,8 @@ List *get_range_nulltest(PartitionKey key); void make_inh_translation_list(Relation oldrelation, Relation newrelation, Index newvarno, List **translated_vars); - +void set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte); +void create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel); /* Copied from src/backend/catalog/partition.c, not exported */ #define partition_bound_accepts_nulls(bi) ((bi)->null_index != -1) diff --git a/include/hypopg_table.h b/include/hypopg_table.h index bc3a30c..6da8f93 100644 --- a/include/hypopg_table.h +++ b/include/hypopg_table.h @@ -73,5 +73,7 @@ void hypo_injectHypotheticalPartitioning(PlannerInfo *root, RelOptInfo *rel); void hypo_markDummyIfExcluded(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte); +void hypo_setPartitionPathlist(PlannerInfo *root, RelOptInfo *rel, + Index rti, RangeTblEntry *rte); #endif From 2892181880b12e31e7ced79c70d137eef68a74c1 Mon Sep 17 00:00:00 2001 From: yuzupy Date: Thu, 19 Apr 2018 02:25:18 +0000 Subject: [PATCH 5/5] Remove a function, hypo_markDummyIfExcluded --- hypopg.c | 4 ++-- hypopg_table.c | 63 ++++---------------------------------------------- 2 files changed, 7 insertions(+), 60 deletions(-) diff --git a/hypopg.c b/hypopg.c index 85c4ea7..e939255 100644 --- a/hypopg.c +++ b/hypopg.c @@ -360,8 +360,8 @@ hypo_set_rel_pathlist_hook(PlannerInfo *root, Index rti, RangeTblEntry *rte) { - if(HYPO_ENABLED() && hypo_table_oid_is_hypothetical(rte->relid) && rte->relkind == 'r') - // hypo_markDummyIfExcluded(root,rel,rti,rte); + if(HYPO_ENABLED() && hypo_table_oid_is_hypothetical(rte->relid) + && rte->relkind == 'r') hypo_setPartitionPathlist(root,rel,rti,rte); if (prev_set_rel_pathlist_hook) diff --git a/hypopg_table.c b/hypopg_table.c index 0ea244a..a737703 100644 --- a/hypopg_table.c +++ b/hypopg_table.c @@ -1886,58 +1886,6 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, } -/* - * 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) -{ - hypoTable *parent; - List *constraints; - List *safe_constraints = NIL; - ListCell *lc; - - Assert(HYPO_ENABLED()); - Assert(hypo_table_oid_is_hypothetical(rte->relid)); - Assert(rte->relkind == 'r'); - - parent = hypo_find_table(rte->relid); - - /* 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() - */ - -} - - - /* * If this rel is partition, we remove the partition constraints from the * its rel->baserestrictinfo and rewrite some items of its RelOptInfo: @@ -1946,7 +1894,6 @@ void hypo_markDummyIfExcluded(PlannerInfo *root, RelOptInfo *rel, * the new RelOptInfo. * */ - void hypo_setPartitionPathlist(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte) { @@ -1981,7 +1928,7 @@ void hypo_setPartitionPathlist(PlannerInfo *root, RelOptInfo *rel, RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); Node *childqual; ListCell *lc2; - + Assert(IsA(rinfo, RestrictInfo)); childqual = adjust_appendrel_attrs(root, (Node *) rinfo->clause, @@ -1993,7 +1940,7 @@ void hypo_setPartitionPathlist(PlannerInfo *root, RelOptInfo *rel, { Node *onecq = (Node *) lfirst(lc2); bool pseudoconstant; - + /* check for pseudoconstant (no Vars or volatile functions) */ pseudoconstant = !contain_vars_of_level(onecq, 0) && @@ -2038,17 +1985,17 @@ void hypo_setPartitionPathlist(PlannerInfo *root, RelOptInfo *rel, pages = ceil(rel->pages * selectivity); rel->pages = (BlockNumber)pages; rel->tuples = clamp_row_est(rel->tuples * selectivity); - + /* recompute the rel->baserestrictcost*/ cost_qual_eval(&rel->baserestrictcost, rel->baserestrictinfo, root); - + /* * call the set_plain_rel_pathlist() to re-create its pathlist using * the new RelOptInfo */ set_plain_rel_pathlist(root, rel, rte); } - + /*