* BuildCachedPlan: construct a new CachedPlan from a CachedPlanSource. * * qlist should be the result value from a previous RevalidateCachedQuery, * or it can be set to NIL if we need to re-copy the plansource's query_list. * * To build a generic, parameter-value-independent plan, pass NULL for * boundParams. To build a custom plan, pass the actual parameter values via * boundParams. For
| 906 | * GPDB: See GetCachedPlan() for why intoClause is added here. |
| 907 | */ |
| 908 | static CachedPlan * |
| 909 | BuildCachedPlan(CachedPlanSource *plansource, List *qlist, |
| 910 | ParamListInfo boundParams, |
| 911 | QueryEnvironment *queryEnv, |
| 912 | IntoClause *intoClause) |
| 913 | { |
| 914 | CachedPlan *plan; |
| 915 | List *plist; |
| 916 | bool snapshot_set = false; |
| 917 | bool is_transient = false; |
| 918 | bool is_oneoff = false; |
| 919 | MemoryContext plan_context; |
| 920 | MemoryContext oldcxt = CurrentMemoryContext; |
| 921 | ListCell *lc; |
| 922 | |
| 923 | /* |
| 924 | * Normally the querytree should be valid already, but if it's not, |
| 925 | * rebuild it. |
| 926 | * |
| 927 | * NOTE: GetCachedPlan should have called RevalidateCachedQuery first, so |
| 928 | * we ought to be holding sufficient locks to prevent any invalidation. |
| 929 | * However, if we're building a custom plan after having built and |
| 930 | * rejected a generic plan, it's possible to reach here with is_valid |
| 931 | * false due to an invalidation while making the generic plan. In theory |
| 932 | * the invalidation must be a false positive, perhaps a consequence of an |
| 933 | * sinval reset event or the debug_discard_caches code. But for safety, |
| 934 | * let's treat it as real and redo the RevalidateCachedQuery call. |
| 935 | */ |
| 936 | if (!plansource->is_valid) |
| 937 | qlist = RevalidateCachedQuery(plansource, queryEnv, intoClause); |
| 938 | |
| 939 | /* |
| 940 | * If we don't already have a copy of the querytree list that can be |
| 941 | * scribbled on by the planner, make one. For a one-shot plan, we assume |
| 942 | * it's okay to scribble on the original query_list. |
| 943 | */ |
| 944 | if (qlist == NIL) |
| 945 | { |
| 946 | if (!plansource->is_oneshot) |
| 947 | qlist = copyObject(plansource->query_list); |
| 948 | else |
| 949 | qlist = plansource->query_list; |
| 950 | } |
| 951 | |
| 952 | /* |
| 953 | * If a snapshot is already set (the normal case), we can just use that |
| 954 | * for planning. But if it isn't, and we need one, install one. |
| 955 | */ |
| 956 | if (!ActiveSnapshotSet() && |
| 957 | plansource->raw_parse_tree && |
| 958 | analyze_requires_snapshot(plansource->raw_parse_tree)) |
| 959 | { |
| 960 | PushActiveSnapshot(GetTransactionSnapshot()); |
| 961 | snapshot_set = true; |
| 962 | } |
| 963 | |
| 964 | /* |
| 965 | * Generate the plan. |
no test coverage detected