src/backend/parser/parse_cte.c - Coverage Report

← 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%)

Line | Hits | Source | Commit
--- | --- | --- | ---
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%)

Line | Hits | Source | Commit
--- | --- | --- | ---
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).