src/backend/commands/explain.c | 10 ++++-- src/backend/nodes/bitmapset.c | 57 +++++++++++++++++++++++++++++++++ src/backend/nodes/copyfuncs.c | 2 ++ src/backend/nodes/outfuncs.c | 2 ++ src/backend/optimizer/plan/createplan.c | 4 +++ src/backend/optimizer/plan/setrefs.c | 8 +++++ src/include/nodes/bitmapset.h | 1 + src/include/nodes/plannodes.h | 4 +++ 8 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 9281874..8892dca 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -730,11 +730,17 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used) case T_ValuesScan: case T_CteScan: case T_WorkTableScan: - case T_ForeignScan: - case T_CustomScan: *rels_used = bms_add_member(*rels_used, ((Scan *) plan)->scanrelid); break; + case T_ForeignScan: + *rels_used = bms_add_members(*rels_used, + ((ForeignScan *) plan)->fdw_relids); + break; + case T_CustomScan: + *rels_used = bms_add_members(*rels_used, + ((CustomScan *) plan)->custom_relids); + break; case T_ModifyTable: *rels_used = bms_add_member(*rels_used, ((ModifyTable *) plan)->nominalRelation); diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c index a9c3b4b..4dc3286 100644 --- a/src/backend/nodes/bitmapset.c +++ b/src/backend/nodes/bitmapset.c @@ -301,6 +301,63 @@ bms_difference(const Bitmapset *a, const Bitmapset *b) } /* + * bms_shift_members - move all the bits by shift + */ +Bitmapset * +bms_shift_members(const Bitmapset *a, int shift) +{ + Bitmapset *b; + bitmapword h_word; + bitmapword l_word; + int nwords; + int w_shift; + int b_shift; + int i, j; + + /* fast path if result shall be NULL obviously */ + if (a == NULL || a->nwords * BITS_PER_BITMAPWORD + shift <= 0) + return NULL; + /* actually, not shift members */ + if (shift == 0) + return bms_copy(a); + + nwords = (a->nwords * BITS_PER_BITMAPWORD + shift + + BITS_PER_BITMAPWORD - 1) / BITS_PER_BITMAPWORD; + b = palloc(BITMAPSET_SIZE(nwords)); + b->nwords = nwords; + + if (shift > 0) + { + /* Left shift */ + w_shift = WORDNUM(shift); + b_shift = BITNUM(shift); + + for (i=0, j=-w_shift; i < b->nwords; i++, j++) + { + h_word = (j >= 0 && j < a->nwords ? a->words[j] : 0); + l_word = (j-1 >= 0 && j-1 < a->nwords ? a->words[j-1] : 0); + b->words[i] = ((h_word << b_shift) | + (l_word >> (BITS_PER_BITMAPWORD - b_shift))); + } + } + else + { + /* Right shift */ + w_shift = WORDNUM(-shift); + b_shift = BITNUM(-shift); + + for (i=0, j=-w_shift; i < b->nwords; i++, j++) + { + h_word = (j+1 >= 0 && j+1 < a->nwords ? a->words[j+1] : 0); + l_word = (j >= 0 && j < a->nwords ? a->words[j] : 0); + b->words[i] = ((h_word >> (BITS_PER_BITMAPWORD - b_shift)) | + (l_word << b_shift)); + } + } + return b; +} + +/* * bms_is_subset - is A a subset of B? */ bool diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 9300b70..7c85943 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -596,6 +596,7 @@ _copyForeignScan(const ForeignScan *from) COPY_NODE_FIELD(fdw_exprs); COPY_NODE_FIELD(fdw_ps_tlist); COPY_NODE_FIELD(fdw_private); + COPY_BITMAPSET_FIELD(fdw_relids); COPY_SCALAR_FIELD(fsSystemCol); return newnode; @@ -621,6 +622,7 @@ _copyCustomScan(const CustomScan *from) COPY_NODE_FIELD(custom_exprs); COPY_NODE_FIELD(custom_ps_tlist); COPY_NODE_FIELD(custom_private); + COPY_BITMAPSET_FIELD(custom_relids); /* * NOTE: The method field of CustomScan is required to be a pointer to a diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index f3676ec..edeee7e 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -562,6 +562,7 @@ _outForeignScan(StringInfo str, const ForeignScan *node) WRITE_NODE_FIELD(fdw_exprs); WRITE_NODE_FIELD(fdw_ps_tlist); WRITE_NODE_FIELD(fdw_private); + WRITE_BITMAPSET_FIELD(fdw_relids); WRITE_BOOL_FIELD(fsSystemCol); } @@ -576,6 +577,7 @@ _outCustomScan(StringInfo str, const CustomScan *node) WRITE_NODE_FIELD(custom_exprs); WRITE_NODE_FIELD(custom_ps_tlist); WRITE_NODE_FIELD(custom_private); + WRITE_BITMAPSET_FIELD(custom_relids); appendStringInfoString(str, " :methods "); _outToken(str, node->methods->CustomName); if (node->methods->TextOutCustomScan) diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 7a37824..514fcd9 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -2013,6 +2013,8 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path, elog(ERROR, "junk TLE should not apper prior to valid one"); } } + /* Set the relids that are represented by this foreign scan for Explain */ + scan_plan->fdw_relids = best_path->path.parent->relids; /* Copy cost data from Path to Plan; no need to make FDW do this */ copy_path_costsize(&scan_plan->scan.plan, &best_path->path); @@ -2119,6 +2121,8 @@ create_customscan_plan(PlannerInfo *root, CustomPath *best_path, elog(ERROR, "junk TLE should not apper prior to valid one"); } } + /* Set the relids that are represented by this custom scan for Explain */ + cplan->custom_relids = best_path->path.parent->relids; /* * Copy cost data from Path to Plan; no need to make custom-plan providers diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index a41c4f0..2961f44 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -568,6 +568,10 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) { ForeignScan *splan = (ForeignScan *) plan; + if (rtoffset > 0) + splan->fdw_relids = + bms_shift_members(splan->fdw_relids, rtoffset); + if (splan->scan.scanrelid == 0) { indexed_tlist *pscan_itlist = @@ -610,6 +614,10 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) { CustomScan *splan = (CustomScan *) plan; + if (rtoffset > 0) + splan->custom_relids = + bms_shift_members(splan->custom_relids, rtoffset); + if (splan->scan.scanrelid == 0) { indexed_tlist *pscan_itlist = diff --git a/src/include/nodes/bitmapset.h b/src/include/nodes/bitmapset.h index 3a556ee..3ca9791 100644 --- a/src/include/nodes/bitmapset.h +++ b/src/include/nodes/bitmapset.h @@ -66,6 +66,7 @@ extern void bms_free(Bitmapset *a); extern Bitmapset *bms_union(const Bitmapset *a, const Bitmapset *b); extern Bitmapset *bms_intersect(const Bitmapset *a, const Bitmapset *b); extern Bitmapset *bms_difference(const Bitmapset *a, const Bitmapset *b); +extern Bitmapset *bms_shift_members(const Bitmapset *a, int shift); extern bool bms_is_subset(const Bitmapset *a, const Bitmapset *b); extern BMS_Comparison bms_subset_compare(const Bitmapset *a, const Bitmapset *b); extern bool bms_is_member(int x, const Bitmapset *a); diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 213034b..0f1e94c 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -490,6 +490,8 @@ typedef struct ForeignScan List *fdw_exprs; /* expressions that FDW may evaluate */ List *fdw_ps_tlist; /* optional pseudo-scan tlist for FDW */ List *fdw_private; /* private data for FDW */ + Bitmapset *fdw_relids; /* set of relid (index of range-tables) + * represented by this node */ bool fsSystemCol; /* true if any "system column" is needed */ } ForeignScan; @@ -523,6 +525,8 @@ typedef struct CustomScan List *custom_exprs; /* expressions that custom code may evaluate */ List *custom_ps_tlist;/* optional pseudo-scan target list */ List *custom_private; /* private data for custom code */ + Bitmapset *custom_relids; /* set of relid (index of range-tables) + * represented by this node */ const CustomScanMethods *methods; } CustomScan;