diff --git a/src/backend/columnar/columnar_customscan.c b/src/backend/columnar/columnar_customscan.c index 4866c81ad..88760c654 100644 --- a/src/backend/columnar/columnar_customscan.c +++ b/src/backend/columnar/columnar_customscan.c @@ -27,6 +27,7 @@ #include "columnar/columnar_customscan.h" #include "columnar/columnar_metadata.h" #include "columnar/columnar_tableam.h" +#include "distributed/listutils.h" typedef struct ColumnarScanPath { @@ -50,8 +51,13 @@ typedef struct ColumnarScanState } ColumnarScanState; +typedef bool (*PathPredicate)(Path *path); + + static void ColumnarSetRelPathlistHook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte); +static void RemovePathsByPredicate(RelOptInfo *rel, PathPredicate removePathPredicate); +static bool IsNotIndexPath(Path *path); static Path * CreateColumnarScanPath(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte); static Cost ColumnarScanCost(RangeTblEntry *rte); @@ -137,18 +143,6 @@ columnar_customscan_init() } -static void -clear_paths(RelOptInfo *rel) -{ - rel->pathlist = NIL; - rel->partial_pathlist = NIL; - rel->cheapest_startup_path = NULL; - rel->cheapest_total_path = NULL; - rel->cheapest_unique_path = NULL; - rel->cheapest_parameterized_paths = NIL; -} - - static void ColumnarSetRelPathlistHook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte) @@ -188,8 +182,13 @@ ColumnarSetRelPathlistHook(PlannerInfo *root, RelOptInfo *rel, Index rti, ereport(DEBUG1, (errmsg("pathlist hook for columnar table am"))); - /* we propose a new path that will be the only path for scanning this relation */ - clear_paths(rel); + /* + * TODO: Since we don't have a proper costing model for + * ColumnarCustomScan, we remove other paths to force postgres + * using ColumnarCustomScan. Note that we still keep index paths + * since they still might be useful. + */ + RemovePathsByPredicate(rel, IsNotIndexPath); add_path(rel, customPath); } } @@ -197,6 +196,38 @@ ColumnarSetRelPathlistHook(PlannerInfo *root, RelOptInfo *rel, Index rti, } +/* + * RemovePathsByPredicate removes the paths that removePathPredicate + * evaluates to true from pathlist of given rel. + */ +static void +RemovePathsByPredicate(RelOptInfo *rel, PathPredicate removePathPredicate) +{ + List *filteredPathList = NIL; + + Path *path = NULL; + foreach_ptr(path, rel->pathlist) + { + if (!removePathPredicate(path)) + { + filteredPathList = lappend(filteredPathList, path); + } + } + + rel->pathlist = filteredPathList; +} + + +/* + * IsNotIndexPath returns true if given path is not an IndexPath. + */ +static bool +IsNotIndexPath(Path *path) +{ + return !IsA(path, IndexPath); +} + + static Path * CreateColumnarScanPath(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) {