* set_cte_pathlist * Build the (single) access path for a non-self-reference CTE RTE * * There's no need for a separate set_cte_size phase, since we don't * support join-qual-parameterized paths for CTEs. */
| 2906 | * support join-qual-parameterized paths for CTEs. |
| 2907 | */ |
| 2908 | static void |
| 2909 | set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) |
| 2910 | { |
| 2911 | PlannerInfo *cteroot; |
| 2912 | Index levelsup; |
| 2913 | int ndx; |
| 2914 | ListCell *lc; |
| 2915 | int planinfo_id; |
| 2916 | CommonTableExpr *cte = NULL; |
| 2917 | double tuple_fraction = 0.0; |
| 2918 | CtePlanInfo *cteplaninfo; |
| 2919 | List *pathkeys = NULL; |
| 2920 | PlannerInfo *subroot = NULL; |
| 2921 | RelOptInfo *sub_final_rel; |
| 2922 | Relids required_outer; |
| 2923 | bool is_shared; |
| 2924 | Query *subquery = NULL; |
| 2925 | bool contain_volatile_function = false; |
| 2926 | |
| 2927 | /* |
| 2928 | * Find the referenced CTE based on the given range table entry |
| 2929 | */ |
| 2930 | levelsup = rte->ctelevelsup; |
| 2931 | cteroot = root; |
| 2932 | while (levelsup-- > 0) |
| 2933 | { |
| 2934 | cteroot = cteroot->parent_root; |
| 2935 | if (!cteroot) /* shouldn't happen */ |
| 2936 | elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename); |
| 2937 | } |
| 2938 | |
| 2939 | ndx = 0; |
| 2940 | foreach(lc, cteroot->parse->cteList) |
| 2941 | { |
| 2942 | cte = (CommonTableExpr *) lfirst(lc); |
| 2943 | |
| 2944 | if (strcmp(cte->ctename, rte->ctename) == 0) |
| 2945 | break; |
| 2946 | ndx++; |
| 2947 | } |
| 2948 | if (lc == NULL) /* shouldn't happen */ |
| 2949 | elog(ERROR, "could not find CTE \"%s\"", rte->ctename); |
| 2950 | |
| 2951 | Assert(IsA(cte->ctequery, Query)); |
| 2952 | /* |
| 2953 | * Copy query node since subquery_planner may trash it, and we need it |
| 2954 | * intact in case we need to create another plan for the CTE |
| 2955 | */ |
| 2956 | subquery = (Query *) copyObject(cte->ctequery); |
| 2957 | contain_volatile_function = contain_volatile_functions((Node *) subquery); |
| 2958 | |
| 2959 | /* |
| 2960 | * In PostgreSQL, we use the index to look up the plan ID in the |
| 2961 | * cteroot->cte_plan_ids list. In GPDB, CTE plans work differently, and |
| 2962 | * we look up the CtePlanInfo struct in the list_cteplaninfo instead. |
| 2963 | */ |
| 2964 | planinfo_id = ndx; |
| 2965 |
no test coverage detected