← Back to Overview

src/backend/parser/parse_cte.c

Coverage: 13/13 lines (100.0%)
Total Lines
13
modified
Covered
13
100.0%
Uncovered
0
0.0%
Keyboard navigation
transformWithClause() lines 118-264
Modified Lines Coverage: 5/5 lines (100.0%)
LineHitsSourceCommit
118 - transformWithClause(ParseState *pstate, WithClause *withClause) -
119 - { -
120 - ListCell *lc; -
121 - -
122 - /* Only one WITH clause per query level */ -
123 - Assert(pstate->p_ctenamespace == NIL); -
124 - Assert(pstate->p_future_ctes == NIL); -
125 - -
126 - /* -
127 - * For either type of WITH, there must not be duplicate CTE names in the -
128 - * list. Check this right away so we needn't worry later. -
129 - * -
130 - * Also, tentatively mark each CTE as non-recursive, and initialize its -
131 - * reference count to zero, and set pstate->p_hasModifyingCTE if needed. -
132 - */ -
133 - foreach(lc, withClause->ctes) -
134 - { -
135 - CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc); -
136 - ListCell *rest; -
137 - -
138 - for_each_cell(rest, withClause->ctes, lnext(withClause->ctes, lc)) -
139 - { -
140 - CommonTableExpr *cte2 = (CommonTableExpr *) lfirst(rest); -
141 - -
142 - if (strcmp(cte->ctename, cte2->ctename) == 0) -
143 - ereport(ERROR, -
144 - (errcode(ERRCODE_DUPLICATE_ALIAS), -
145 - errmsg("WITH query name \"%s\" specified more than once", -
146 - cte2->ctename), -
147 - parser_errposition(pstate, cte2->location))); -
148 - } -
149 - -
150 - cte->cterecursive = false; -
151 - cte->cterefcount = 0; -
152 - -
153 - if (!IsA(cte->ctequery, SelectStmt)) -
154 - { -
155 - /* must be a data-modifying statement */ -
156 - Assert(IsA(cte->ctequery, InsertStmt) || -
157 - IsA(cte->ctequery, UpdateStmt) || -
158 - IsA(cte->ctequery, DeleteStmt) || -
159 - IsA(cte->ctequery, MergeStmt)); -
160 - -
161 - pstate->p_hasModifyingCTE = true; -
162 - } -
163 - } -
164 - -
165 - if (withClause->recursive) -
166 - { -
167 - /* -
168 - * For WITH RECURSIVE, we rearrange the list elements if needed to -
169 - * eliminate forward references. First, build a work array and set up -
170 - * the data structure needed by the tree walkers. -
171 - */ -
172 - CteState cstate; -
173 - int i; -
174 - -
175 - /* c54ba27Row pattern recognition patch (parse/analysis).
176 - * Per ISO/IEC 9075-2:2016 7.17 Syntax Rule 3)e)f), every <with list c54ba27Row pattern recognition patch (parse/analysis).
177 - * element> in a WITH RECURSIVE clause is "potentially recursive" and c54ba27Row pattern recognition patch (parse/analysis).
178 - * shall not contain a <row pattern common syntax>. (PostgreSQL does c54ba27Row pattern recognition patch (parse/analysis).
179 - * not implement <row pattern measures>, so only the common syntax c54ba27Row pattern recognition patch (parse/analysis).
180 - * needs to be checked.) ISO/IEC 19075-5 6.17.5 (R020) and 4.18.5 c54ba27Row pattern recognition patch (parse/analysis).
181 - * (R010) restate the prohibition for CREATE RECURSIVE VIEW, which is c54ba27Row pattern recognition patch (parse/analysis).
182 - * rewritten to WITH RECURSIVE by makeRecursiveViewSelect() and so c54ba27Row pattern recognition patch (parse/analysis).
183 - * flows through here as well. c54ba27Row pattern recognition patch (parse/analysis).
184 - */ c54ba27Row pattern recognition patch (parse/analysis).
185 1622 foreach_node(CommonTableExpr, cte, withClause->ctes) c54ba27Row pattern recognition patch (parse/analysis).
186 - { c54ba27Row pattern recognition patch (parse/analysis).
187 847 ContainRPRContext ctx; c54ba27Row pattern recognition patch (parse/analysis).
188 - c54ba27Row pattern recognition patch (parse/analysis).
189 847 ctx.location = -1; c54ba27Row pattern recognition patch (parse/analysis).
190 847 if (contain_rpr_walker(cte->ctequery, &ctx)) c54ba27Row pattern recognition patch (parse/analysis).
191 847 ereport(ERROR, c54ba27Row pattern recognition patch (parse/analysis).
192 - errcode(ERRCODE_SYNTAX_ERROR), c54ba27Row pattern recognition patch (parse/analysis).
193 - errmsg("cannot use row pattern recognition in a recursive query"), c54ba27Row pattern recognition patch (parse/analysis).
194 - parser_errposition(pstate, ctx.location)); c54ba27Row pattern recognition patch (parse/analysis).
195 - } c54ba27Row pattern recognition patch (parse/analysis).
196 - c54ba27Row pattern recognition patch (parse/analysis).
197 - cstate.pstate = pstate; -
198 - cstate.numitems = list_length(withClause->ctes); -
199 - cstate.items = (CteItem *) palloc0(cstate.numitems * sizeof(CteItem)); -
200 - i = 0; -
201 - foreach(lc, withClause->ctes) -
202 - { -
203 - cstate.items[i].cte = (CommonTableExpr *) lfirst(lc); -
204 - cstate.items[i].id = i; -
205 - i++; -
206 - } -
207 - -
208 - /* -
209 - * Find all the dependencies and sort the CteItems into a safe -
210 - * processing order. Also, mark CTEs that contain self-references. -
211 - */ -
212 - makeDependencyGraph(&cstate); -
213 - -
214 - /* -
215 - * Check that recursive queries are well-formed. -
216 - */ -
217 - checkWellFormedRecursion(&cstate); -
218 - -
219 - /* -
220 - * Set up the ctenamespace for parse analysis. Per spec, all the WITH -
221 - * items are visible to all others, so stuff them all in before parse -
222 - * analysis. We build the list in safe processing order so that the -
223 - * planner can process the queries in sequence. -
224 - */ -
225 - for (i = 0; i < cstate.numitems; i++) -
226 - { -
227 - CommonTableExpr *cte = cstate.items[i].cte; -
228 - -
229 - pstate->p_ctenamespace = lappend(pstate->p_ctenamespace, cte); -
230 - } -
231 - -
232 - /* -
233 - * Do parse analysis in the order determined by the topological sort. -
234 - */ -
235 - for (i = 0; i < cstate.numitems; i++) -
236 - { -
237 - CommonTableExpr *cte = cstate.items[i].cte; -
238 - -
239 - analyzeCTE(pstate, cte); -
240 - } -
241 - } -
242 - else -
243 - { -
244 - /* -
245 - * For non-recursive WITH, just analyze each CTE in sequence and then -
246 - * add it to the ctenamespace. This corresponds to the spec's -
247 - * definition of the scope of each WITH name. However, to allow error -
248 - * reports to be aware of the possibility of an erroneous reference, -
249 - * we maintain a list in p_future_ctes of the not-yet-visible CTEs. -
250 - */ -
251 - pstate->p_future_ctes = list_copy(withClause->ctes); -
252 - -
253 - foreach(lc, withClause->ctes) -
254 - { -
255 - CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc); -
256 - -
257 - analyzeCTE(pstate, cte); -
258 - pstate->p_ctenamespace = lappend(pstate->p_ctenamespace, cte); -
259 - pstate->p_future_ctes = list_delete_first(pstate->p_future_ctes); -
260 - } -
261 - } -
262 - -
263 - return pstate->p_ctenamespace; -
264 - } -
contain_rpr_walker() lines 1309-1324
Modified Lines Coverage: 8/8 lines (100.0%)
LineHitsSourceCommit
1309 98088 contain_rpr_walker(Node *node, void *context) c54ba27Row pattern recognition patch (parse/analysis).
1310 - { c54ba27Row pattern recognition patch (parse/analysis).
1311 98088 if (node == NULL) c54ba27Row pattern recognition patch (parse/analysis).
1312 - return false; c54ba27Row pattern recognition patch (parse/analysis).
1313 42241 if (IsA(node, WindowDef)) c54ba27Row pattern recognition patch (parse/analysis).
1314 - { c54ba27Row pattern recognition patch (parse/analysis).
1315 24 WindowDef *wd = (WindowDef *) node; c54ba27Row pattern recognition patch (parse/analysis).
1316 - c54ba27Row pattern recognition patch (parse/analysis).
1317 24 if (wd->rpCommonSyntax != NULL) c54ba27Row pattern recognition patch (parse/analysis).
1318 - { c54ba27Row pattern recognition patch (parse/analysis).
1319 8 ((ContainRPRContext *) context)->location = wd->rpCommonSyntax->location; c54ba27Row pattern recognition patch (parse/analysis).
1320 8 return true; c54ba27Row pattern recognition patch (parse/analysis).
1321 - } c54ba27Row pattern recognition patch (parse/analysis).
1322 - } c54ba27Row pattern recognition patch (parse/analysis).
1323 42233 return raw_expression_tree_walker(node, contain_rpr_walker, context); c54ba27Row pattern recognition patch (parse/analysis).
1324 - } c54ba27Row pattern recognition patch (parse/analysis).