diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2022-04-21 17:58:52 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2022-04-21 17:58:52 -0400 |
commit | 92e7a537520927107742af654619e55f34072942 (patch) | |
tree | bf56aee0d30e9a79a2e49f7e764216fd304bdb66 /src/backend | |
parent | 914611ea738a3601717990faff0f5d71a0f14a3d (diff) | |
download | postgresql-92e7a537520927107742af654619e55f34072942.tar.gz |
Remove inadequate assertion check in CTE inlining.
inline_cte() expected to find exactly as many references to the
target CTE as its cterefcount indicates. While that should be
accurate for the tree as emitted by the parser, there are some
optimizations that occur upstream of here that could falsify it,
notably removal of unused subquery output expressions.
Trying to make the accounting 100% accurate seems expensive and
doomed to future breakage. It's not really worth it, because
all this code is protecting is downstream assumptions that every
referenced CTE has a plan. Let's convert those assertions to
regular test-and-elog just in case there's some actual problem,
and then drop the failing assertion.
Per report from Tomas Vondra (thanks also to Richard Guo for
analysis). Back-patch to v12 where the faulty code came in.
Discussion: https://postgr.es/m/29196a1e-ed47-c7ca-9be2-b1c636816183@enterprisedb.com
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/optimizer/path/allpaths.c | 3 | ||||
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 3 | ||||
-rw-r--r-- | src/backend/optimizer/plan/subselect.c | 8 |
3 files changed, 4 insertions, 10 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 998212dda8..d84f66a81b 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -2804,7 +2804,8 @@ set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) if (ndx >= list_length(cteroot->cte_plan_ids)) elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename); plan_id = list_nth_int(cteroot->cte_plan_ids, ndx); - Assert(plan_id > 0); + if (plan_id <= 0) + elog(ERROR, "no plan was made for CTE \"%s\"", rte->ctename); cteplan = (Plan *) list_nth(root->glob->subplans, plan_id - 1); /* Mark rel with estimated output rows, width, etc */ diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 95476ada0b..7905bc4654 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -3898,7 +3898,8 @@ create_ctescan_plan(PlannerInfo *root, Path *best_path, if (ndx >= list_length(cteroot->cte_plan_ids)) elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename); plan_id = list_nth_int(cteroot->cte_plan_ids, ndx); - Assert(plan_id > 0); + if (plan_id <= 0) + elog(ERROR, "no plan was made for CTE \"%s\"", rte->ctename); foreach(lc, cteroot->init_plans) { ctesplan = (SubPlan *) lfirst(lc); diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 863e0e24a1..df4ca12919 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -61,7 +61,6 @@ typedef struct inline_cte_walker_context { const char *ctename; /* name and relative level of target CTE */ int levelsup; - int refcount; /* number of remaining references */ Query *ctequery; /* query to substitute */ } inline_cte_walker_context; @@ -1157,13 +1156,9 @@ inline_cte(PlannerInfo *root, CommonTableExpr *cte) context.ctename = cte->ctename; /* Start at levelsup = -1 because we'll immediately increment it */ context.levelsup = -1; - context.refcount = cte->cterefcount; context.ctequery = castNode(Query, cte->ctequery); (void) inline_cte_walker((Node *) root->parse, &context); - - /* Assert we replaced all references */ - Assert(context.refcount == 0); } static bool @@ -1226,9 +1221,6 @@ inline_cte_walker(Node *node, inline_cte_walker_context *context) rte->coltypes = NIL; rte->coltypmods = NIL; rte->colcollations = NIL; - - /* Count the number of replacements we've done */ - context->refcount--; } return false; |