← Back to Overview

src/backend/optimizer/plan/rpr.c

Coverage: 569/575 lines (99.0%)
Total Lines
575
modified
Covered
569
99.0%
Uncovered
6
1.0%
Keyboard navigation
rprPatternEqual() lines 105-131
Modified Lines Coverage: 10/11 lines (90.9%)
LineHitsSourceCommit
105 1910 rprPatternEqual(RPRPatternNode *a, RPRPatternNode *b) 7521a30Row pattern recognition patch (planner).
106 - { 7521a30Row pattern recognition patch (planner).
107 - /* Pattern nodes in children lists must never be NULL */ 7521a30Row pattern recognition patch (planner).
108 1910 Assert(a != NULL && b != NULL); 7521a30Row pattern recognition patch (planner).
109 - 7521a30Row pattern recognition patch (planner).
110 - /* Must have same node type and quantifiers */ 7521a30Row pattern recognition patch (planner).
111 1910 if (a->nodeType != b->nodeType) 7521a30Row pattern recognition patch (planner).
112 - return false; 7521a30Row pattern recognition patch (planner).
113 1605 if (a->min != b->min || a->max != b->max) 7521a30Row pattern recognition patch (planner).
114 - return false; 7521a30Row pattern recognition patch (planner).
115 1510 if (a->reluctant != b->reluctant) 7521a30Row pattern recognition patch (planner).
116 - return false; 7521a30Row pattern recognition patch (planner).
117 - 7521a30Row pattern recognition patch (planner).
118 1505 switch (a->nodeType) 7521a30Row pattern recognition patch (planner).
119 - { 7521a30Row pattern recognition patch (planner).
120 1345 case RPR_PATTERN_VAR: 7521a30Row pattern recognition patch (planner).
121 1345 return strcmp(a->varName, b->varName) == 0; 7521a30Row pattern recognition patch (planner).
122 - 7521a30Row pattern recognition patch (planner).
123 160 case RPR_PATTERN_SEQ: 7521a30Row pattern recognition patch (planner).
124 - case RPR_PATTERN_ALT: 7521a30Row pattern recognition patch (planner).
125 - case RPR_PATTERN_GROUP: 7521a30Row pattern recognition patch (planner).
126 160 return rprPatternChildrenEqual(a->children, b->children); 7521a30Row pattern recognition patch (planner).
127 - } 7521a30Row pattern recognition patch (planner).
128 - 7521a30Row pattern recognition patch (planner).
129 0 pg_unreachable(); 7521a30Row pattern recognition patch (planner).
UnreachableDefensive (unreachable) · confidence high · rprPatternEqual @129
Reason
Confirmed defensive-unreachable.
RPRPatternNodeType (parsenodes.h:615-621) has exactly four values:
RPR_PATTERN_VAR, RPR_PATTERN_SEQ, RPR_PATTERN_ALT, RPR_PATTERN_GROUP.
The switch at rpr.c:118-127 handles all four and every case ends in a return (VAR returns strcmp;
SEQ/ALT/GROUP share the rprPatternChildrenEqual return).
Control therefore can never fall through to pg_unreachable() at line 129. Every assignment to ->nodeType in the backend (gram.y:17652/17684/17713/17726/21425/21484) uses one of the four valid constants, set only by the grammar;
nothing can inject a fifth value, and the node tree is never constructed with an uninitialized nodeType reachable from SQL.
The two early-return guards (a->nodeType != b->nodeType, etc.) further mean a is always inspected with a valid value.
No SQL or regression input can drive line 129. The claim's root cause is accurate.
Recommended fix
Keep as-is. pg_unreachable() is the standard PostgreSQL idiom for an exhaustive enum switch and correctly documents that control cannot reach here.
Optionally the trailing "return false;
" is only present to satisfy compilers that do not treat pg_unreachable() as noreturn;
no functional change is warranted.
No source change needed.
130 - return false; 7521a30Row pattern recognition patch (planner).
131 - } 7521a30Row pattern recognition patch (planner).
rprPatternChildrenEqual() lines 140-156
Modified Lines Coverage: 8/8 lines (100.0%)
LineHitsSourceCommit
140 535 rprPatternChildrenEqual(List *a, List *b) 7521a30Row pattern recognition patch (planner).
141 - { 7521a30Row pattern recognition patch (planner).
142 535 ListCell *lca, 7521a30Row pattern recognition patch (planner).
143 - *lcb; 7521a30Row pattern recognition patch (planner).
144 - 7521a30Row pattern recognition patch (planner).
145 1605 if (list_length(a) != list_length(b)) 7521a30Row pattern recognition patch (planner).
146 - return false; 7521a30Row pattern recognition patch (planner).
147 - 7521a30Row pattern recognition patch (planner).
148 960 forboth(lca, a, lcb, b) 7521a30Row pattern recognition patch (planner).
149 - { 7521a30Row pattern recognition patch (planner).
150 690 if (!rprPatternEqual((RPRPatternNode *) lfirst(lca), 7521a30Row pattern recognition patch (planner).
151 690 (RPRPatternNode *) lfirst(lcb))) 7521a30Row pattern recognition patch (planner).
152 185 return false; 7521a30Row pattern recognition patch (planner).
153 - } 7521a30Row pattern recognition patch (planner).
154 - 7521a30Row pattern recognition patch (planner).
155 270 return true; 7521a30Row pattern recognition patch (planner).
156 - } 7521a30Row pattern recognition patch (planner).
tryUnwrapSingleChild() lines 171-177
Modified Lines Coverage: 3/3 lines (100.0%)
LineHitsSourceCommit
171 3655 tryUnwrapSingleChild(RPRPatternNode *pattern) 7521a30Row pattern recognition patch (planner).
172 - { 7521a30Row pattern recognition patch (planner).
173 3655 if (list_length(pattern->children) == 1) 7521a30Row pattern recognition patch (planner).
174 145 return (RPRPatternNode *) linitial(pattern->children); 7521a30Row pattern recognition patch (planner).
175 - 7521a30Row pattern recognition patch (planner).
176 - return pattern; 7521a30Row pattern recognition patch (planner).
177 - } 7521a30Row pattern recognition patch (planner).
flattenSeqChildren() lines 190-214
Modified Lines Coverage: 10/10 lines (100.0%)
LineHitsSourceCommit
190 2745 flattenSeqChildren(List *children) 7521a30Row pattern recognition patch (planner).
191 - { 7521a30Row pattern recognition patch (planner).
192 2745 List *newChildren = NIL; 7521a30Row pattern recognition patch (planner).
193 - 7521a30Row pattern recognition patch (planner).
194 10490 foreach_node(RPRPatternNode, child, children) 7521a30Row pattern recognition patch (planner).
195 - { 7521a30Row pattern recognition patch (planner).
196 7745 RPRPatternNode *opt = optimizeRPRPattern(child); 7521a30Row pattern recognition patch (planner).
197 - 7521a30Row pattern recognition patch (planner).
198 - /* GROUP{1,1} should have been unwrapped by optimizeGroupPattern */ 7521a30Row pattern recognition patch (planner).
199 7745 Assert(!(opt->nodeType == RPR_PATTERN_GROUP && 7521a30Row pattern recognition patch (planner).
200 - opt->min == 1 && opt->max == 1 && opt->reluctant == false)); 7521a30Row pattern recognition patch (planner).
201 - 7521a30Row pattern recognition patch (planner).
202 7745 if (opt->nodeType == RPR_PATTERN_SEQ) 7521a30Row pattern recognition patch (planner).
203 - { 7521a30Row pattern recognition patch (planner).
204 50 newChildren = list_concat(newChildren, 7521a30Row pattern recognition patch (planner).
205 50 list_copy(opt->children)); 7521a30Row pattern recognition patch (planner).
206 - } 7521a30Row pattern recognition patch (planner).
207 - else 7521a30Row pattern recognition patch (planner).
208 - { 7521a30Row pattern recognition patch (planner).
209 7695 newChildren = lappend(newChildren, opt); 7521a30Row pattern recognition patch (planner).
210 - } 7521a30Row pattern recognition patch (planner).
211 - } 7521a30Row pattern recognition patch (planner).
212 - 7521a30Row pattern recognition patch (planner).
213 2745 return newChildren; 7521a30Row pattern recognition patch (planner).
214 - } 7521a30Row pattern recognition patch (planner).
mergeConsecutiveVars() lines 226-288
Modified Lines Coverage: 23/23 lines (100.0%)
LineHitsSourceCommit
226 2745 mergeConsecutiveVars(List *children) 7521a30Row pattern recognition patch (planner).
227 - { 7521a30Row pattern recognition patch (planner).
228 2745 List *mergedChildren = NIL; 7521a30Row pattern recognition patch (planner).
229 2745 RPRPatternNode *prev = NULL; 7521a30Row pattern recognition patch (planner).
230 - 7521a30Row pattern recognition patch (planner).
231 10540 foreach_node(RPRPatternNode, child, children) 7521a30Row pattern recognition patch (planner).
232 - { 7521a30Row pattern recognition patch (planner).
233 7795 if (child->nodeType == RPR_PATTERN_VAR && child->reluctant == false) 7521a30Row pattern recognition patch (planner).
234 - { 7521a30Row pattern recognition patch (planner).
235 - /* ---------------------- 7521a30Row pattern recognition patch (planner).
236 - * Can merge consecutive VAR nodes if: 7521a30Row pattern recognition patch (planner).
237 - * 1. Same variable name 7521a30Row pattern recognition patch (planner).
238 - * 2. No min overflow: prev->min + child->min < INF 7521a30Row pattern recognition patch (planner).
239 - * 3. No max overflow: prev->max + child->max < INF (or either is INF) 7521a30Row pattern recognition patch (planner).
240 - * 7521a30Row pattern recognition patch (planner).
241 - * Strict <: a sum equal to INF would alias the unbounded sentinel 7521a30Row pattern recognition patch (planner).
242 - * (min must stay finite; a finite max must not become INF). 7521a30Row pattern recognition patch (planner).
243 - */ 7521a30Row pattern recognition patch (planner).
244 6920 if (prev != NULL && 7521a30Row pattern recognition patch (planner).
245 4175 strcmp(prev->varName, child->varName) == 0 && 7521a30Row pattern recognition patch (planner).
246 125 prev->min < RPR_QUANTITY_INF - child->min && 7521a30Row pattern recognition patch (planner).
247 120 (prev->max < RPR_QUANTITY_INF - child->max || 7521a30Row pattern recognition patch (planner).
248 10 prev->max == RPR_QUANTITY_INF || 7521a30Row pattern recognition patch (planner).
249 - child->max == RPR_QUANTITY_INF)) 7521a30Row pattern recognition patch (planner).
250 - { 7521a30Row pattern recognition patch (planner).
251 - /* 7521a30Row pattern recognition patch (planner).
252 - * Merge: accumulate min/max into prev. prev is guaranteed to 7521a30Row pattern recognition patch (planner).
253 - * be a non-reluctant VAR by the outer condition. 7521a30Row pattern recognition patch (planner).
254 - */ 7521a30Row pattern recognition patch (planner).
255 120 Assert(prev->nodeType == RPR_PATTERN_VAR && prev->reluctant == false); 7521a30Row pattern recognition patch (planner).
256 - 7521a30Row pattern recognition patch (planner).
257 120 prev->min += child->min; 7521a30Row pattern recognition patch (planner).
258 - 7521a30Row pattern recognition patch (planner).
259 120 if (prev->max == RPR_QUANTITY_INF || 7521a30Row pattern recognition patch (planner).
260 95 child->max == RPR_QUANTITY_INF) 7521a30Row pattern recognition patch (planner).
261 35 prev->max = RPR_QUANTITY_INF; 7521a30Row pattern recognition patch (planner).
262 - else 7521a30Row pattern recognition patch (planner).
263 85 prev->max += child->max; 7521a30Row pattern recognition patch (planner).
264 - } 7521a30Row pattern recognition patch (planner).
265 - else 7521a30Row pattern recognition patch (planner).
266 - { 7521a30Row pattern recognition patch (planner).
267 - /* Flush previous and start new */ 7521a30Row pattern recognition patch (planner).
268 - if (prev != NULL) 7521a30Row pattern recognition patch (planner).
269 4055 mergedChildren = lappend(mergedChildren, prev); 7521a30Row pattern recognition patch (planner).
270 - prev = child; 7521a30Row pattern recognition patch (planner).
271 - } 7521a30Row pattern recognition patch (planner).
272 - } 7521a30Row pattern recognition patch (planner).
273 - else 7521a30Row pattern recognition patch (planner).
274 - { 7521a30Row pattern recognition patch (planner).
275 - /* Non-mergeable - flush previous */ 7521a30Row pattern recognition patch (planner).
276 875 if (prev != NULL) 7521a30Row pattern recognition patch (planner).
277 270 mergedChildren = lappend(mergedChildren, prev); 7521a30Row pattern recognition patch (planner).
278 875 mergedChildren = lappend(mergedChildren, child); 7521a30Row pattern recognition patch (planner).
279 - prev = NULL; 7521a30Row pattern recognition patch (planner).
280 - } 7521a30Row pattern recognition patch (planner).
281 - } 7521a30Row pattern recognition patch (planner).
282 - 7521a30Row pattern recognition patch (planner).
283 - /* Flush remaining */ 7521a30Row pattern recognition patch (planner).
284 2745 if (prev != NULL) 7521a30Row pattern recognition patch (planner).
285 2475 mergedChildren = lappend(mergedChildren, prev); 7521a30Row pattern recognition patch (planner).
286 - 7521a30Row pattern recognition patch (planner).
287 2745 return mergedChildren; 7521a30Row pattern recognition patch (planner).
288 - } 7521a30Row pattern recognition patch (planner).
mergeConsecutiveGroups() lines 300-362
Modified Lines Coverage: 23/23 lines (100.0%)
LineHitsSourceCommit
300 2745 mergeConsecutiveGroups(List *children) 7521a30Row pattern recognition patch (planner).
301 - { 7521a30Row pattern recognition patch (planner).
302 2745 List *mergedChildren = NIL; 7521a30Row pattern recognition patch (planner).
303 2745 RPRPatternNode *prev = NULL; 7521a30Row pattern recognition patch (planner).
304 - 7521a30Row pattern recognition patch (planner).
305 10420 foreach_node(RPRPatternNode, child, children) 7521a30Row pattern recognition patch (planner).
306 - { 7521a30Row pattern recognition patch (planner).
307 7675 if (child->nodeType == RPR_PATTERN_GROUP && child->reluctant == false) 7521a30Row pattern recognition patch (planner).
308 - { 7521a30Row pattern recognition patch (planner).
309 - /* ---------------------- 7521a30Row pattern recognition patch (planner).
310 - * Can merge consecutive GROUP nodes if: 7521a30Row pattern recognition patch (planner).
311 - * 1. Identical children 7521a30Row pattern recognition patch (planner).
312 - * 2. No min overflow: prev->min + child->min < INF 7521a30Row pattern recognition patch (planner).
313 - * 3. No max overflow: prev->max + child->max < INF (or either is INF) 7521a30Row pattern recognition patch (planner).
314 - * 7521a30Row pattern recognition patch (planner).
315 - * Strict <: a sum equal to INF would alias the unbounded sentinel 7521a30Row pattern recognition patch (planner).
316 - * (min must stay finite; a finite max must not become INF). 7521a30Row pattern recognition patch (planner).
317 - */ 7521a30Row pattern recognition patch (planner).
318 385 if (prev != NULL && 7521a30Row pattern recognition patch (planner).
319 40 rprPatternChildrenEqual(prev->children, child->children) && 7521a30Row pattern recognition patch (planner).
320 25 prev->min < RPR_QUANTITY_INF - child->min && 7521a30Row pattern recognition patch (planner).
321 20 (prev->max < RPR_QUANTITY_INF - child->max || 7521a30Row pattern recognition patch (planner).
322 5 prev->max == RPR_QUANTITY_INF || 7521a30Row pattern recognition patch (planner).
323 - child->max == RPR_QUANTITY_INF)) 7521a30Row pattern recognition patch (planner).
324 - { 7521a30Row pattern recognition patch (planner).
325 - /* 7521a30Row pattern recognition patch (planner).
326 - * Merge: accumulate min/max into prev. prev is guaranteed to 7521a30Row pattern recognition patch (planner).
327 - * be a non-reluctant GROUP by the outer condition. 7521a30Row pattern recognition patch (planner).
328 - */ 7521a30Row pattern recognition patch (planner).
329 20 Assert(prev->nodeType == RPR_PATTERN_GROUP && prev->reluctant == false); 7521a30Row pattern recognition patch (planner).
330 - 7521a30Row pattern recognition patch (planner).
331 20 prev->min += child->min; 7521a30Row pattern recognition patch (planner).
332 - 7521a30Row pattern recognition patch (planner).
333 20 if (prev->max == RPR_QUANTITY_INF || 7521a30Row pattern recognition patch (planner).
334 10 child->max == RPR_QUANTITY_INF) 7521a30Row pattern recognition patch (planner).
335 15 prev->max = RPR_QUANTITY_INF; 7521a30Row pattern recognition patch (planner).
336 - else 7521a30Row pattern recognition patch (planner).
337 5 prev->max += child->max; 7521a30Row pattern recognition patch (planner).
338 - } 7521a30Row pattern recognition patch (planner).
339 - else 7521a30Row pattern recognition patch (planner).
340 - { 7521a30Row pattern recognition patch (planner).
341 - /* Flush previous and start new */ 7521a30Row pattern recognition patch (planner).
342 - if (prev != NULL) 7521a30Row pattern recognition patch (planner).
343 20 mergedChildren = lappend(mergedChildren, prev); 7521a30Row pattern recognition patch (planner).
344 - prev = child; 7521a30Row pattern recognition patch (planner).
345 - } 7521a30Row pattern recognition patch (planner).
346 - } 7521a30Row pattern recognition patch (planner).
347 - else 7521a30Row pattern recognition patch (planner).
348 - { 7521a30Row pattern recognition patch (planner).
349 - /* Non-mergeable - flush previous */ 7521a30Row pattern recognition patch (planner).
350 7330 if (prev != NULL) 7521a30Row pattern recognition patch (planner).
351 190 mergedChildren = lappend(mergedChildren, prev); 7521a30Row pattern recognition patch (planner).
352 7330 mergedChildren = lappend(mergedChildren, child); 7521a30Row pattern recognition patch (planner).
353 - prev = NULL; 7521a30Row pattern recognition patch (planner).
354 - } 7521a30Row pattern recognition patch (planner).
355 - } 7521a30Row pattern recognition patch (planner).
356 - 7521a30Row pattern recognition patch (planner).
357 - /* Flush remaining */ 7521a30Row pattern recognition patch (planner).
358 2745 if (prev != NULL) 7521a30Row pattern recognition patch (planner).
359 115 mergedChildren = lappend(mergedChildren, prev); 7521a30Row pattern recognition patch (planner).
360 - 7521a30Row pattern recognition patch (planner).
361 2745 return mergedChildren; 7521a30Row pattern recognition patch (planner).
362 - } 7521a30Row pattern recognition patch (planner).
mergeConsecutiveAlts() lines 376-463
Modified Lines Coverage: 44/44 lines (100.0%)
LineHitsSourceCommit
376 2745 mergeConsecutiveAlts(List *children) 7521a30Row pattern recognition patch (planner).
377 - { 7521a30Row pattern recognition patch (planner).
378 2745 List *mergedChildren = NIL; 7521a30Row pattern recognition patch (planner).
379 2745 RPRPatternNode *prev = NULL; 7521a30Row pattern recognition patch (planner).
380 2745 int count = 0; 7521a30Row pattern recognition patch (planner).
381 - 7521a30Row pattern recognition patch (planner).
382 10400 foreach_node(RPRPatternNode, child, children) 7521a30Row pattern recognition patch (planner).
383 - { 7521a30Row pattern recognition patch (planner).
384 7655 if (child->nodeType == RPR_PATTERN_ALT && child->reluctant == false) 7521a30Row pattern recognition patch (planner).
385 - { 7521a30Row pattern recognition patch (planner).
386 540 if (prev != NULL && 7521a30Row pattern recognition patch (planner).
387 120 rprPatternChildrenEqual(prev->children, child->children)) 7521a30Row pattern recognition patch (planner).
388 - { 7521a30Row pattern recognition patch (planner).
389 - /* Same ALT as prev - accumulate */ 7521a30Row pattern recognition patch (planner).
390 80 count++; 7521a30Row pattern recognition patch (planner).
391 - } 7521a30Row pattern recognition patch (planner).
392 - else 7521a30Row pattern recognition patch (planner).
393 - { 7521a30Row pattern recognition patch (planner).
394 - /* Different ALT or first ALT - flush previous */ 7521a30Row pattern recognition patch (planner).
395 40 if (prev != NULL) 7521a30Row pattern recognition patch (planner).
396 - { 7521a30Row pattern recognition patch (planner).
397 40 if (count > 1) 7521a30Row pattern recognition patch (planner).
398 - { 7521a30Row pattern recognition patch (planner).
399 - /* Wrap in GROUP{count,count}(ALT) */ 7521a30Row pattern recognition patch (planner).
400 5 RPRPatternNode *group = makeNode(RPRPatternNode); 7521a30Row pattern recognition patch (planner).
401 - 7521a30Row pattern recognition patch (planner).
402 5 group->nodeType = RPR_PATTERN_GROUP; 7521a30Row pattern recognition patch (planner).
403 5 group->min = count; 7521a30Row pattern recognition patch (planner).
404 5 group->max = count; 7521a30Row pattern recognition patch (planner).
405 5 group->reluctant = false; 7521a30Row pattern recognition patch (planner).
406 5 group->location = -1; 7521a30Row pattern recognition patch (planner).
407 5 group->children = list_make1(prev); 7521a30Row pattern recognition patch (planner).
408 5 mergedChildren = lappend(mergedChildren, group); 7521a30Row pattern recognition patch (planner).
409 - } 7521a30Row pattern recognition patch (planner).
410 - else 7521a30Row pattern recognition patch (planner).
411 35 mergedChildren = lappend(mergedChildren, prev); 7521a30Row pattern recognition patch (planner).
412 - } 7521a30Row pattern recognition patch (planner).
413 - prev = child; 7521a30Row pattern recognition patch (planner).
414 - count = 1; 7521a30Row pattern recognition patch (planner).
415 - } 7521a30Row pattern recognition patch (planner).
416 - } 7521a30Row pattern recognition patch (planner).
417 - else 7521a30Row pattern recognition patch (planner).
418 - { 7521a30Row pattern recognition patch (planner).
419 - /* Non-ALT - flush previous */ 7521a30Row pattern recognition patch (planner).
420 7235 if (prev != NULL) 7521a30Row pattern recognition patch (planner).
421 - { 7521a30Row pattern recognition patch (planner).
422 160 if (count > 1) 7521a30Row pattern recognition patch (planner).
423 - { 7521a30Row pattern recognition patch (planner).
424 5 RPRPatternNode *group = makeNode(RPRPatternNode); 7521a30Row pattern recognition patch (planner).
425 - 7521a30Row pattern recognition patch (planner).
426 5 group->nodeType = RPR_PATTERN_GROUP; 7521a30Row pattern recognition patch (planner).
427 5 group->min = count; 7521a30Row pattern recognition patch (planner).
428 5 group->max = count; 7521a30Row pattern recognition patch (planner).
429 5 group->reluctant = false; 7521a30Row pattern recognition patch (planner).
430 5 group->location = -1; 7521a30Row pattern recognition patch (planner).
431 5 group->children = list_make1(prev); 7521a30Row pattern recognition patch (planner).
432 5 mergedChildren = lappend(mergedChildren, group); 7521a30Row pattern recognition patch (planner).
433 - } 7521a30Row pattern recognition patch (planner).
434 - else 7521a30Row pattern recognition patch (planner).
435 155 mergedChildren = lappend(mergedChildren, prev); 7521a30Row pattern recognition patch (planner).
436 - } 7521a30Row pattern recognition patch (planner).
437 7235 mergedChildren = lappend(mergedChildren, child); 7521a30Row pattern recognition patch (planner).
438 - prev = NULL; 7521a30Row pattern recognition patch (planner).
439 - count = 0; 7521a30Row pattern recognition patch (planner).
440 - } 7521a30Row pattern recognition patch (planner).
441 - } 7521a30Row pattern recognition patch (planner).
442 - 7521a30Row pattern recognition patch (planner).
443 - /* Flush remaining */ 7521a30Row pattern recognition patch (planner).
444 2745 if (prev != NULL) 7521a30Row pattern recognition patch (planner).
445 - { 7521a30Row pattern recognition patch (planner).
446 140 if (count > 1) 7521a30Row pattern recognition patch (planner).
447 - { 7521a30Row pattern recognition patch (planner).
448 10 RPRPatternNode *group = makeNode(RPRPatternNode); 7521a30Row pattern recognition patch (planner).
449 - 7521a30Row pattern recognition patch (planner).
450 10 group->nodeType = RPR_PATTERN_GROUP; 7521a30Row pattern recognition patch (planner).
451 10 group->min = count; 7521a30Row pattern recognition patch (planner).
452 10 group->max = count; 7521a30Row pattern recognition patch (planner).
453 10 group->reluctant = false; 7521a30Row pattern recognition patch (planner).
454 10 group->location = -1; 7521a30Row pattern recognition patch (planner).
455 10 group->children = list_make1(prev); 7521a30Row pattern recognition patch (planner).
456 10 mergedChildren = lappend(mergedChildren, group); 7521a30Row pattern recognition patch (planner).
457 - } 7521a30Row pattern recognition patch (planner).
458 - else 7521a30Row pattern recognition patch (planner).
459 130 mergedChildren = lappend(mergedChildren, prev); 7521a30Row pattern recognition patch (planner).
460 - } 7521a30Row pattern recognition patch (planner).
461 - 7521a30Row pattern recognition patch (planner).
462 2745 return mergedChildren; 7521a30Row pattern recognition patch (planner).
463 - } 7521a30Row pattern recognition patch (planner).
mergeGroupPrefixSuffix() lines 488-640
Modified Lines Coverage: 59/59 lines (100.0%)
LineHitsSourceCommit
488 2745 mergeGroupPrefixSuffix(List *children) 7521a30Row pattern recognition patch (planner).
489 - { 7521a30Row pattern recognition patch (planner).
490 2745 List *result = NIL; 7521a30Row pattern recognition patch (planner).
491 2745 int numChildren = list_length(children); 7521a30Row pattern recognition patch (planner).
492 2745 int i; 7521a30Row pattern recognition patch (planner).
493 2745 int skipUntil = -1; /* skip suffix elements already merged */ 7521a30Row pattern recognition patch (planner).
494 - 7521a30Row pattern recognition patch (planner).
495 10210 for (i = 0; i < numChildren; i++) 7521a30Row pattern recognition patch (planner).
496 - { 7521a30Row pattern recognition patch (planner).
497 7465 RPRPatternNode *child = (RPRPatternNode *) list_nth(children, i); 7521a30Row pattern recognition patch (planner).
498 - 7521a30Row pattern recognition patch (planner).
499 - /* 7521a30Row pattern recognition patch (planner).
500 - * The suffix merge logic below adjusts i to skip merged elements, 7521a30Row pattern recognition patch (planner).
501 - * ensuring we never revisit them. Verify this invariant. 7521a30Row pattern recognition patch (planner).
502 - */ 7521a30Row pattern recognition patch (planner).
503 7465 Assert(i >= skipUntil); 7521a30Row pattern recognition patch (planner).
504 - 7521a30Row pattern recognition patch (planner).
505 - /* 7521a30Row pattern recognition patch (planner).
506 - * If this is a GROUP, see if preceding/following elements match its 7521a30Row pattern recognition patch (planner).
507 - * children. GROUP's content may be wrapped in a SEQ - unwrap for 7521a30Row pattern recognition patch (planner).
508 - * comparison. 7521a30Row pattern recognition patch (planner).
509 - */ 7521a30Row pattern recognition patch (planner).
510 7465 if (child->nodeType == RPR_PATTERN_GROUP && child->reluctant == false) 7521a30Row pattern recognition patch (planner).
511 - { 7521a30Row pattern recognition patch (planner).
512 345 List *groupContent = child->children; 7521a30Row pattern recognition patch (planner).
513 345 int groupChildCount; 7521a30Row pattern recognition patch (planner).
514 345 int prefixLen = list_length(result); 7521a30Row pattern recognition patch (planner).
515 345 List *trimmed; 7521a30Row pattern recognition patch (planner).
516 - 7521a30Row pattern recognition patch (planner).
517 - /* 7521a30Row pattern recognition patch (planner).
518 - * If GROUP has single SEQ child, compare with SEQ's children. 7521a30Row pattern recognition patch (planner).
519 - * e.g., (A B)+ internally contains sequence A B; compare against 7521a30Row pattern recognition patch (planner).
520 - * that. 7521a30Row pattern recognition patch (planner).
521 - */ 7521a30Row pattern recognition patch (planner).
522 345 if (list_length(groupContent) == 1) 7521a30Row pattern recognition patch (planner).
523 - { 7521a30Row pattern recognition patch (planner).
524 345 RPRPatternNode *inner = (RPRPatternNode *) linitial(groupContent); 7521a30Row pattern recognition patch (planner).
525 - 7521a30Row pattern recognition patch (planner).
526 345 if (inner->nodeType == RPR_PATTERN_SEQ) 7521a30Row pattern recognition patch (planner).
527 260 groupContent = inner->children; 7521a30Row pattern recognition patch (planner).
528 - } 7521a30Row pattern recognition patch (planner).
529 - 7521a30Row pattern recognition patch (planner).
530 345 groupChildCount = list_length(groupContent); 7521a30Row pattern recognition patch (planner).
531 - 7521a30Row pattern recognition patch (planner).
532 - /* 7521a30Row pattern recognition patch (planner).
533 - * PREFIX MERGE: Check if preceding elements match. Keep merging 7521a30Row pattern recognition patch (planner).
534 - * as long as we have matching prefixes. 7521a30Row pattern recognition patch (planner).
535 - */ 7521a30Row pattern recognition patch (planner).
536 405 while (prefixLen >= groupChildCount && groupChildCount > 0) 7521a30Row pattern recognition patch (planner).
537 - { 7521a30Row pattern recognition patch (planner).
538 95 List *prefixElements = NIL; 7521a30Row pattern recognition patch (planner).
539 95 int j; 7521a30Row pattern recognition patch (planner).
540 - 7521a30Row pattern recognition patch (planner).
541 - /* Extract last groupChildCount elements from prefix */ 7521a30Row pattern recognition patch (planner).
542 265 for (j = prefixLen - groupChildCount; j < prefixLen; j++) 7521a30Row pattern recognition patch (planner).
543 - { 7521a30Row pattern recognition patch (planner).
544 170 prefixElements = lappend(prefixElements, 7521a30Row pattern recognition patch (planner).
545 - list_nth(result, j)); 7521a30Row pattern recognition patch (planner).
546 - } 7521a30Row pattern recognition patch (planner).
547 - 7521a30Row pattern recognition patch (planner).
548 - /* Compare with GROUP's (possibly unwrapped) children */ 7521a30Row pattern recognition patch (planner).
549 95 if (rprPatternChildrenEqual(prefixElements, groupContent) && 7521a30Row pattern recognition patch (planner).
550 60 child->min < RPR_QUANTITY_INF - 1 && 7521a30Row pattern recognition patch (planner).
551 60 (child->max == RPR_QUANTITY_INF || 7521a30Row pattern recognition patch (planner).
552 - child->max < RPR_QUANTITY_INF - 1)) 7521a30Row pattern recognition patch (planner).
553 - { 7521a30Row pattern recognition patch (planner).
554 - /* 7521a30Row pattern recognition patch (planner).
555 - * Match! Merge by incrementing GROUP's quantifier. Remove 7521a30Row pattern recognition patch (planner).
556 - * the prefix elements from output. 7521a30Row pattern recognition patch (planner).
557 - */ 7521a30Row pattern recognition patch (planner).
558 60 child->min += 1; 7521a30Row pattern recognition patch (planner).
559 60 if (child->max != RPR_QUANTITY_INF) 7521a30Row pattern recognition patch (planner).
560 5 child->max += 1; 7521a30Row pattern recognition patch (planner).
561 - 7521a30Row pattern recognition patch (planner).
562 - /* Rebuild result without matched prefix */ 7521a30Row pattern recognition patch (planner).
563 - trimmed = NIL; 7521a30Row pattern recognition patch (planner).
564 85 for (j = 0; j < prefixLen - groupChildCount; j++) 7521a30Row pattern recognition patch (planner).
565 - { 7521a30Row pattern recognition patch (planner).
566 25 trimmed = lappend(trimmed, 7521a30Row pattern recognition patch (planner).
567 - list_nth(result, j)); 7521a30Row pattern recognition patch (planner).
568 - } 7521a30Row pattern recognition patch (planner).
569 60 result = trimmed; 7521a30Row pattern recognition patch (planner).
570 60 prefixLen = list_length(result); 7521a30Row pattern recognition patch (planner).
571 - } 7521a30Row pattern recognition patch (planner).
572 - else 7521a30Row pattern recognition patch (planner).
573 - { 7521a30Row pattern recognition patch (planner).
574 35 list_free(prefixElements); 7521a30Row pattern recognition patch (planner).
575 35 break; 7521a30Row pattern recognition patch (planner).
576 - } 7521a30Row pattern recognition patch (planner).
577 - 7521a30Row pattern recognition patch (planner).
578 60 list_free(prefixElements); 7521a30Row pattern recognition patch (planner).
579 - } 7521a30Row pattern recognition patch (planner).
580 - 7521a30Row pattern recognition patch (planner).
581 - /* 7521a30Row pattern recognition patch (planner).
582 - * SUFFIX MERGE: Check if following elements match. Keep merging 7521a30Row pattern recognition patch (planner).
583 - * as long as we have matching suffixes. 7521a30Row pattern recognition patch (planner).
584 - */ 7521a30Row pattern recognition patch (planner).
585 405 while (i + groupChildCount < numChildren && groupChildCount > 0) 7521a30Row pattern recognition patch (planner).
586 - { 7521a30Row pattern recognition patch (planner).
587 120 List *suffixElements = NIL; 7521a30Row pattern recognition patch (planner).
588 120 int j; 7521a30Row pattern recognition patch (planner).
589 120 int suffixStart = i + 1; 7521a30Row pattern recognition patch (planner).
590 - 7521a30Row pattern recognition patch (planner).
591 - /* suffixStart always >= skipUntil after i adjustment */ 7521a30Row pattern recognition patch (planner).
592 120 Assert(skipUntil <= suffixStart); 7521a30Row pattern recognition patch (planner).
593 - 7521a30Row pattern recognition patch (planner).
594 - /* Extract next groupChildCount elements as suffix */ 7521a30Row pattern recognition patch (planner).
595 295 for (j = 0; j < groupChildCount; j++) 7521a30Row pattern recognition patch (planner).
596 - { 7521a30Row pattern recognition patch (planner).
597 175 int idx = suffixStart + j; 7521a30Row pattern recognition patch (planner).
598 - 7521a30Row pattern recognition patch (planner).
599 - /* while condition guarantees idx < numChildren */ 7521a30Row pattern recognition patch (planner).
600 175 Assert(idx < numChildren); 7521a30Row pattern recognition patch (planner).
601 175 suffixElements = lappend(suffixElements, 7521a30Row pattern recognition patch (planner).
602 - list_nth(children, idx)); 7521a30Row pattern recognition patch (planner).
603 - } 7521a30Row pattern recognition patch (planner).
604 - 7521a30Row pattern recognition patch (planner).
605 - /* Compare with GROUP's children */ 7521a30Row pattern recognition patch (planner).
606 360 if (list_length(suffixElements) == groupChildCount && 7521a30Row pattern recognition patch (planner).
607 120 rprPatternChildrenEqual(suffixElements, groupContent) && 7521a30Row pattern recognition patch (planner).
608 60 child->min < RPR_QUANTITY_INF - 1 && 7521a30Row pattern recognition patch (planner).
609 60 (child->max == RPR_QUANTITY_INF || 7521a30Row pattern recognition patch (planner).
610 - child->max < RPR_QUANTITY_INF - 1)) 7521a30Row pattern recognition patch (planner).
611 - { 7521a30Row pattern recognition patch (planner).
612 - /* 7521a30Row pattern recognition patch (planner).
613 - * Match! Merge suffix by incrementing quantifier and 7521a30Row pattern recognition patch (planner).
614 - * skipping. 7521a30Row pattern recognition patch (planner).
615 - */ 7521a30Row pattern recognition patch (planner).
616 60 child->min += 1; 7521a30Row pattern recognition patch (planner).
617 60 if (child->max != RPR_QUANTITY_INF) 7521a30Row pattern recognition patch (planner).
618 5 child->max += 1; 7521a30Row pattern recognition patch (planner).
619 60 skipUntil = suffixStart + groupChildCount; 7521a30Row pattern recognition patch (planner).
620 - 7521a30Row pattern recognition patch (planner).
621 - /* 7521a30Row pattern recognition patch (planner).
622 - * Update i to continue suffix check after merged elements 7521a30Row pattern recognition patch (planner).
623 - */ 7521a30Row pattern recognition patch (planner).
624 60 i = skipUntil - 1; 7521a30Row pattern recognition patch (planner).
625 - } 7521a30Row pattern recognition patch (planner).
626 - else 7521a30Row pattern recognition patch (planner).
627 - { 7521a30Row pattern recognition patch (planner).
628 60 list_free(suffixElements); 7521a30Row pattern recognition patch (planner).
629 60 break; 7521a30Row pattern recognition patch (planner).
630 - } 7521a30Row pattern recognition patch (planner).
631 - 7521a30Row pattern recognition patch (planner).
632 60 list_free(suffixElements); 7521a30Row pattern recognition patch (planner).
633 - } 7521a30Row pattern recognition patch (planner).
634 - } 7521a30Row pattern recognition patch (planner).
635 - 7521a30Row pattern recognition patch (planner).
636 7465 result = lappend(result, child); 7521a30Row pattern recognition patch (planner).
637 - } 7521a30Row pattern recognition patch (planner).
638 - 7521a30Row pattern recognition patch (planner).
639 2745 return result; 7521a30Row pattern recognition patch (planner).
640 - } 7521a30Row pattern recognition patch (planner).
optimizeSeqPattern() lines 655-674
Modified Lines Coverage: 7/7 lines (100.0%)
LineHitsSourceCommit
655 2745 optimizeSeqPattern(RPRPatternNode *pattern) 7521a30Row pattern recognition patch (planner).
656 - { 7521a30Row pattern recognition patch (planner).
657 - /* Recursively optimize children and flatten nested SEQ/GROUP{1,1} */ 7521a30Row pattern recognition patch (planner).
658 2745 pattern->children = flattenSeqChildren(pattern->children); 7521a30Row pattern recognition patch (planner).
659 - 7521a30Row pattern recognition patch (planner).
660 - /* Merge consecutive identical VAR nodes */ 7521a30Row pattern recognition patch (planner).
661 2745 pattern->children = mergeConsecutiveVars(pattern->children); 7521a30Row pattern recognition patch (planner).
662 - 7521a30Row pattern recognition patch (planner).
663 - /* Merge consecutive identical GROUP nodes */ 7521a30Row pattern recognition patch (planner).
664 2745 pattern->children = mergeConsecutiveGroups(pattern->children); 7521a30Row pattern recognition patch (planner).
665 - 7521a30Row pattern recognition patch (planner).
666 - /* Merge consecutive identical ALT nodes into GROUP */ 7521a30Row pattern recognition patch (planner).
667 2745 pattern->children = mergeConsecutiveAlts(pattern->children); 7521a30Row pattern recognition patch (planner).
668 - 7521a30Row pattern recognition patch (planner).
669 - /* Merge prefix/suffix into GROUP with matching children */ 7521a30Row pattern recognition patch (planner).
670 2745 pattern->children = mergeGroupPrefixSuffix(pattern->children); 7521a30Row pattern recognition patch (planner).
671 - 7521a30Row pattern recognition patch (planner).
672 - /* Unwrap single-item SEQ */ 7521a30Row pattern recognition patch (planner).
673 2745 return tryUnwrapSingleChild(pattern); 7521a30Row pattern recognition patch (planner).
674 - } 7521a30Row pattern recognition patch (planner).
flattenAltChildren() lines 687-702
Modified Lines Coverage: 8/8 lines (100.0%)
LineHitsSourceCommit
687 910 flattenAltChildren(List *children) 7521a30Row pattern recognition patch (planner).
688 - { 7521a30Row pattern recognition patch (planner).
689 910 List *newChildren = NIL; 7521a30Row pattern recognition patch (planner).
690 - 7521a30Row pattern recognition patch (planner).
691 2860 foreach_node(RPRPatternNode, child, children) 7521a30Row pattern recognition patch (planner).
692 - { 7521a30Row pattern recognition patch (planner).
693 1950 RPRPatternNode *opt = optimizeRPRPattern(child); 7521a30Row pattern recognition patch (planner).
694 - 7521a30Row pattern recognition patch (planner).
695 1950 if (opt->nodeType == RPR_PATTERN_ALT) 7521a30Row pattern recognition patch (planner).
696 10 newChildren = list_concat(newChildren, list_copy(opt->children)); 7521a30Row pattern recognition patch (planner).
697 - else 7521a30Row pattern recognition patch (planner).
698 1940 newChildren = lappend(newChildren, opt); 7521a30Row pattern recognition patch (planner).
699 - } 7521a30Row pattern recognition patch (planner).
700 - 7521a30Row pattern recognition patch (planner).
701 910 return newChildren; 7521a30Row pattern recognition patch (planner).
702 - } 7521a30Row pattern recognition patch (planner).
removeDuplicateAlternatives() lines 715-737
Modified Lines Coverage: 8/8 lines (100.0%)
LineHitsSourceCommit
715 910 removeDuplicateAlternatives(List *children) 7521a30Row pattern recognition patch (planner).
716 - { 7521a30Row pattern recognition patch (planner).
717 910 List *uniqueChildren = NIL; 7521a30Row pattern recognition patch (planner).
718 - 7521a30Row pattern recognition patch (planner).
719 2870 foreach_node(RPRPatternNode, child, children) 7521a30Row pattern recognition patch (planner).
720 - { 7521a30Row pattern recognition patch (planner).
721 - bool isDuplicate = false; 7521a30Row pattern recognition patch (planner).
722 - 7521a30Row pattern recognition patch (planner).
723 3160 foreach_node(RPRPatternNode, uchild, uniqueChildren) 7521a30Row pattern recognition patch (planner).
724 - { 7521a30Row pattern recognition patch (planner).
725 1220 if (rprPatternEqual(uchild, child)) 7521a30Row pattern recognition patch (planner).
726 - { 7521a30Row pattern recognition patch (planner).
727 - isDuplicate = true; 7521a30Row pattern recognition patch (planner).
728 - break; 7521a30Row pattern recognition patch (planner).
729 - } 7521a30Row pattern recognition patch (planner).
730 - } 7521a30Row pattern recognition patch (planner).
731 - 7521a30Row pattern recognition patch (planner).
732 1960 if (!isDuplicate) 7521a30Row pattern recognition patch (planner).
733 1940 uniqueChildren = lappend(uniqueChildren, child); 7521a30Row pattern recognition patch (planner).
734 - } 7521a30Row pattern recognition patch (planner).
735 - 7521a30Row pattern recognition patch (planner).
736 910 return uniqueChildren; 7521a30Row pattern recognition patch (planner).
737 - } 7521a30Row pattern recognition patch (planner).
optimizeAltPattern() lines 749-759
Modified Lines Coverage: 4/4 lines (100.0%)
LineHitsSourceCommit
749 910 optimizeAltPattern(RPRPatternNode *pattern) 7521a30Row pattern recognition patch (planner).
750 - { 7521a30Row pattern recognition patch (planner).
751 - /* Recursively optimize children and flatten nested ALT */ 7521a30Row pattern recognition patch (planner).
752 910 pattern->children = flattenAltChildren(pattern->children); 7521a30Row pattern recognition patch (planner).
753 - 7521a30Row pattern recognition patch (planner).
754 - /* Remove duplicate alternatives */ 7521a30Row pattern recognition patch (planner).
755 910 pattern->children = removeDuplicateAlternatives(pattern->children); 7521a30Row pattern recognition patch (planner).
756 - 7521a30Row pattern recognition patch (planner).
757 - /* Unwrap single-item ALT */ 7521a30Row pattern recognition patch (planner).
758 910 return tryUnwrapSingleChild(pattern); 7521a30Row pattern recognition patch (planner).
759 - } 7521a30Row pattern recognition patch (planner).
tryMultiplyQuantifiers() lines 787-861
Modified Lines Coverage: 28/28 lines (100.0%)
LineHitsSourceCommit
787 4041 tryMultiplyQuantifiers(RPRPatternNode *pattern) 7521a30Row pattern recognition patch (planner).
788 - { 7521a30Row pattern recognition patch (planner).
789 4041 RPRPatternNode *child; 7521a30Row pattern recognition patch (planner).
790 4041 bool safe; 7521a30Row pattern recognition patch (planner).
791 4041 int64 new_min_64; 7521a30Row pattern recognition patch (planner).
792 4041 int64 new_max_64; 7521a30Row pattern recognition patch (planner).
793 - 7521a30Row pattern recognition patch (planner).
794 - /* Parser always creates GROUP with exactly one child */ 7521a30Row pattern recognition patch (planner).
795 4041 Assert(list_length(pattern->children) == 1); 7521a30Row pattern recognition patch (planner).
796 - 7521a30Row pattern recognition patch (planner).
797 4041 if (pattern->reluctant) 7521a30Row pattern recognition patch (planner).
798 - return pattern; 7521a30Row pattern recognition patch (planner).
799 - 7521a30Row pattern recognition patch (planner).
800 1680 child = (RPRPatternNode *) linitial(pattern->children); 7521a30Row pattern recognition patch (planner).
801 - 7521a30Row pattern recognition patch (planner).
802 1680 if ((child->nodeType != RPR_PATTERN_VAR && 7521a30Row pattern recognition patch (planner).
803 410 child->nodeType != RPR_PATTERN_GROUP) || 7521a30Row pattern recognition patch (planner).
804 410 child->reluctant) 7521a30Row pattern recognition patch (planner).
805 - return pattern; 7521a30Row pattern recognition patch (planner).
806 - 7521a30Row pattern recognition patch (planner).
807 - /* 7521a30Row pattern recognition patch (planner).
808 - * Decide whether the achievable counts form one contiguous interval. The 7521a30Row pattern recognition patch (planner).
809 - * child quantifier is {child->min, child->max} and the outer one is 7521a30Row pattern recognition patch (planner).
810 - * {pattern->min, pattern->max}; either max may be RPR_QUANTITY_INF. 7521a30Row pattern recognition patch (planner).
811 - */ 7521a30Row pattern recognition patch (planner).
812 380 if (pattern->min == pattern->max || child->min == 0) 7521a30Row pattern recognition patch (planner).
813 - safe = true; 7521a30Row pattern recognition patch (planner).
814 - else 7521a30Row pattern recognition patch (planner).
815 - { 7521a30Row pattern recognition patch (planner).
816 170 bool touch; 7521a30Row pattern recognition patch (planner).
817 170 bool zero_ok; 7521a30Row pattern recognition patch (planner).
818 - 7521a30Row pattern recognition patch (planner).
819 - /* 7521a30Row pattern recognition patch (planner).
820 - * Consecutive intervals [t*min, t*max] and [(t+1)*min, (t+1)*max] 7521a30Row pattern recognition patch (planner).
821 - * touch when (t+1)*min <= t*max + 1, i.e. min <= t*(max-min) + 1. 7521a30Row pattern recognition patch (planner).
822 - * This is tightest at the smallest t in play, Max(pattern->min, 1). 7521a30Row pattern recognition patch (planner).
823 - * An unbounded child->max makes every interval reach INF, so they 7521a30Row pattern recognition patch (planner).
824 - * always touch. 7521a30Row pattern recognition patch (planner).
825 - */ 7521a30Row pattern recognition patch (planner).
826 170 if (child->max == RPR_QUANTITY_INF) 7521a30Row pattern recognition patch (planner).
827 - touch = true; 7521a30Row pattern recognition patch (planner).
828 - else 7521a30Row pattern recognition patch (planner).
829 100 touch = ((int64) child->min <= 7521a30Row pattern recognition patch (planner).
830 100 (int64) Max(pattern->min, 1) * (child->max - child->min) + 1); 7521a30Row pattern recognition patch (planner).
831 - 7521a30Row pattern recognition patch (planner).
832 - /* 7521a30Row pattern recognition patch (planner).
833 - * A skippable outer (min 0) also needs {0} adjacent to the child 7521a30Row pattern recognition patch (planner).
834 - * range. 7521a30Row pattern recognition patch (planner).
835 - */ 7521a30Row pattern recognition patch (planner).
836 170 zero_ok = (pattern->min >= 1 || child->min <= 1); 7521a30Row pattern recognition patch (planner).
837 - 7521a30Row pattern recognition patch (planner).
838 145 safe = touch && zero_ok; 7521a30Row pattern recognition patch (planner).
839 - } 7521a30Row pattern recognition patch (planner).
840 - 7521a30Row pattern recognition patch (planner).
841 145 if (!safe) 7521a30Row pattern recognition patch (planner).
842 - return pattern; 7521a30Row pattern recognition patch (planner).
843 - 7521a30Row pattern recognition patch (planner).
844 - /* Flatten the child quantifier, guarding against overflow. */ 7521a30Row pattern recognition patch (planner).
845 305 new_min_64 = (int64) pattern->min * child->min; 7521a30Row pattern recognition patch (planner).
846 305 if (new_min_64 >= RPR_QUANTITY_INF) 7521a30Row pattern recognition patch (planner).
847 - return pattern; /* overflow, skip optimization */ 7521a30Row pattern recognition patch (planner).
848 - 7521a30Row pattern recognition patch (planner).
849 295 if (pattern->max == RPR_QUANTITY_INF || child->max == RPR_QUANTITY_INF) 7521a30Row pattern recognition patch (planner).
850 - new_max_64 = RPR_QUANTITY_INF; 7521a30Row pattern recognition patch (planner).
851 - else 7521a30Row pattern recognition patch (planner).
852 - { 7521a30Row pattern recognition patch (planner).
853 145 new_max_64 = (int64) pattern->max * child->max; 7521a30Row pattern recognition patch (planner).
854 145 if (new_max_64 >= RPR_QUANTITY_INF) 7521a30Row pattern recognition patch (planner).
855 - return pattern; 7521a30Row pattern recognition patch (planner).
856 - } 7521a30Row pattern recognition patch (planner).
857 - 7521a30Row pattern recognition patch (planner).
858 290 child->min = (int) new_min_64; 7521a30Row pattern recognition patch (planner).
859 290 child->max = (int) new_max_64; 7521a30Row pattern recognition patch (planner).
860 290 return child; 7521a30Row pattern recognition patch (planner).
861 - } 7521a30Row pattern recognition patch (planner).
tryUnwrapGroup() lines 881-908
Modified Lines Coverage: 11/11 lines (100.0%)
LineHitsSourceCommit
881 3751 tryUnwrapGroup(RPRPatternNode *pattern) 7521a30Row pattern recognition patch (planner).
882 - { 7521a30Row pattern recognition patch (planner).
883 3751 RPRPatternNode *child; 7521a30Row pattern recognition patch (planner).
884 - 7521a30Row pattern recognition patch (planner).
885 - /* Parser always creates GROUP with single child */ 7521a30Row pattern recognition patch (planner).
886 3751 Assert(list_length(pattern->children) == 1); 7521a30Row pattern recognition patch (planner).
887 - 7521a30Row pattern recognition patch (planner).
888 3751 child = (RPRPatternNode *) linitial(pattern->children); 7521a30Row pattern recognition patch (planner).
889 - 7521a30Row pattern recognition patch (planner).
890 - /* GROUP{1,1}: unwrap directly (reluctant on {1,1} is meaningless) */ 7521a30Row pattern recognition patch (planner).
891 3751 if (pattern->min == 1 && pattern->max == 1) 7521a30Row pattern recognition patch (planner).
892 - return child; 7521a30Row pattern recognition patch (planner).
893 - 7521a30Row pattern recognition patch (planner).
894 - /* 7521a30Row pattern recognition patch (planner).
895 - * Single VAR child with default {1,1}: propagate GROUP's quantifier to 7521a30Row pattern recognition patch (planner).
896 - * the child and unwrap. E.g., (A)?? -> A??, (A)+? -> A+? 7521a30Row pattern recognition patch (planner).
897 - */ 7521a30Row pattern recognition patch (planner).
898 3176 if (child->nodeType == RPR_PATTERN_VAR && 7521a30Row pattern recognition patch (planner).
899 109 child->min == 1 && child->max == 1 && child->reluctant == false) 7521a30Row pattern recognition patch (planner).
900 - { 7521a30Row pattern recognition patch (planner).
901 5 child->min = pattern->min; 7521a30Row pattern recognition patch (planner).
902 5 child->max = pattern->max; 7521a30Row pattern recognition patch (planner).
903 5 child->reluctant = pattern->reluctant; 7521a30Row pattern recognition patch (planner).
904 5 return child; 7521a30Row pattern recognition patch (planner).
905 - } 7521a30Row pattern recognition patch (planner).
906 - 7521a30Row pattern recognition patch (planner).
907 - return pattern; 7521a30Row pattern recognition patch (planner).
908 - } 7521a30Row pattern recognition patch (planner).
optimizeGroupPattern() lines 919-939
Modified Lines Coverage: 10/10 lines (100.0%)
LineHitsSourceCommit
919 4041 optimizeGroupPattern(RPRPatternNode *pattern) 7521a30Row pattern recognition patch (planner).
920 - { 7521a30Row pattern recognition patch (planner).
921 4041 List *newChildren; 7521a30Row pattern recognition patch (planner).
922 4041 RPRPatternNode *result; 7521a30Row pattern recognition patch (planner).
923 - 7521a30Row pattern recognition patch (planner).
924 - /* Recursively optimize children */ 7521a30Row pattern recognition patch (planner).
925 4041 newChildren = NIL; 7521a30Row pattern recognition patch (planner).
926 8082 foreach_node(RPRPatternNode, child, pattern->children) 7521a30Row pattern recognition patch (planner).
927 - { 7521a30Row pattern recognition patch (planner).
928 4041 newChildren = lappend(newChildren, optimizeRPRPattern(child)); 7521a30Row pattern recognition patch (planner).
929 - } 7521a30Row pattern recognition patch (planner).
930 4041 pattern->children = newChildren; 7521a30Row pattern recognition patch (planner).
931 - 7521a30Row pattern recognition patch (planner).
932 - /* Try quantifier multiplication */ 7521a30Row pattern recognition patch (planner).
933 4041 result = tryMultiplyQuantifiers(pattern); 7521a30Row pattern recognition patch (planner).
934 4041 if (result != pattern) 7521a30Row pattern recognition patch (planner).
935 - return result; 7521a30Row pattern recognition patch (planner).
936 - 7521a30Row pattern recognition patch (planner).
937 - /* Try unwrapping GROUP{1,1} */ 7521a30Row pattern recognition patch (planner).
938 3751 return tryUnwrapGroup(pattern); 7521a30Row pattern recognition patch (planner).
939 - } 7521a30Row pattern recognition patch (planner).
optimizeRPRPattern() lines 949-970
Modified Lines Coverage: 10/11 lines (90.9%)
LineHitsSourceCommit
949 17465 optimizeRPRPattern(RPRPatternNode *pattern) 7521a30Row pattern recognition patch (planner).
950 - { 7521a30Row pattern recognition patch (planner).
951 - /* Pattern nodes from parser are never NULL */ 7521a30Row pattern recognition patch (planner).
952 17465 Assert(pattern != NULL); 7521a30Row pattern recognition patch (planner).
953 - 7521a30Row pattern recognition patch (planner).
954 17465 check_stack_depth(); 7521a30Row pattern recognition patch (planner).
955 - 7521a30Row pattern recognition patch (planner).
956 17465 switch (pattern->nodeType) 7521a30Row pattern recognition patch (planner).
957 - { 7521a30Row pattern recognition patch (planner).
958 - case RPR_PATTERN_VAR: 7521a30Row pattern recognition patch (planner).
959 - return pattern; 7521a30Row pattern recognition patch (planner).
960 2745 case RPR_PATTERN_SEQ: 7521a30Row pattern recognition patch (planner).
961 2745 return optimizeSeqPattern(pattern); 7521a30Row pattern recognition patch (planner).
962 910 case RPR_PATTERN_ALT: 7521a30Row pattern recognition patch (planner).
963 910 return optimizeAltPattern(pattern); 7521a30Row pattern recognition patch (planner).
964 4041 case RPR_PATTERN_GROUP: 7521a30Row pattern recognition patch (planner).
965 4041 return optimizeGroupPattern(pattern); 7521a30Row pattern recognition patch (planner).
966 - } 7521a30Row pattern recognition patch (planner).
967 - 7521a30Row pattern recognition patch (planner).
968 0 pg_unreachable(); 7521a30Row pattern recognition patch (planner).
UnreachableDefensive (unreachable) · confidence high · optimizeRPRPattern @968
Reason
Confirmed unreachable.
The switch at rpr.c:956 enumerates all four members of RPRPatternNodeType (RPR_PATTERN_VAR/SEQ/ALT/GROUP, parsenodes.h:617-620) and every case ends in a return, so control falls through to pg_unreachable() at line 968 only if pattern->nodeType holds a value outside the enum. nodeType is set exclusively by the parser when building the pattern tree (always a valid member), and under -DWRITE_READ_PARSE_PLAN_TREES the round-trip uses WRITE_ENUM_FIELD/READ_ENUM_FIELD (outfuncs.funcs.c:1131, readfuncs.funcs.c:1296), which serializes and restores the identical integer it was given.
No SQL or regression input can inject an out-of-range nodeType.
I tried to refute via the read path (deserialization) and the parser path;
both only yield the four valid values.
The Assert(pattern != NULL) and check_stack_depth above are unrelated to line 968.
Recommended fix
Keep as-is.
The pg_unreachable() + return is the standard PostgreSQL exhaustive-switch guard.
No change needed;
this line should be excluded from coverage expectations.
969 - return pattern; 7521a30Row pattern recognition patch (planner).
970 - } 7521a30Row pattern recognition patch (planner).
collectDefineVariables() lines 981-994
Modified Lines Coverage: 6/6 lines (100.0%)
LineHitsSourceCommit
981 3729 collectDefineVariables(List *defineVariableList, char **varNames) 7521a30Row pattern recognition patch (planner).
982 - { 7521a30Row pattern recognition patch (planner).
983 3729 int numVars = 0; 7521a30Row pattern recognition patch (planner).
984 - 7521a30Row pattern recognition patch (planner).
985 12388 foreach_node(String, varname, defineVariableList) 7521a30Row pattern recognition patch (planner).
986 - { 7521a30Row pattern recognition patch (planner).
987 - /* Parser already checked this limit in transformDefineClause */ 7521a30Row pattern recognition patch (planner).
988 8659 Assert(numVars <= RPR_VARID_MAX); 7521a30Row pattern recognition patch (planner).
989 - 7521a30Row pattern recognition patch (planner).
990 8659 varNames[numVars++] = strVal(varname); 7521a30Row pattern recognition patch (planner).
991 - } 7521a30Row pattern recognition patch (planner).
992 - 7521a30Row pattern recognition patch (planner).
993 3729 return numVars; 7521a30Row pattern recognition patch (planner).
994 - } 7521a30Row pattern recognition patch (planner).
scanRPRPatternRecursive() lines 1005-1091
Modified Lines Coverage: 30/30 lines (100.0%)
LineHitsSourceCommit
1005 15685 scanRPRPatternRecursive(RPRPatternNode *node, char **varNames, int *numVars, 7521a30Row pattern recognition patch (planner).
1006 - int *numElements, RPRDepth depth, RPRDepth *maxDepth) 7521a30Row pattern recognition patch (planner).
1007 - { 7521a30Row pattern recognition patch (planner).
1008 15685 int i; 7521a30Row pattern recognition patch (planner).
1009 - 7521a30Row pattern recognition patch (planner).
1010 - /* Pattern nodes from parser are never NULL */ 7521a30Row pattern recognition patch (planner).
1011 15685 Assert(node != NULL); 7521a30Row pattern recognition patch (planner).
1012 - 7521a30Row pattern recognition patch (planner).
1013 15685 check_stack_depth(); 7521a30Row pattern recognition patch (planner).
1014 - 7521a30Row pattern recognition patch (planner).
1015 - /* Check recursion depth limit before overflow occurs */ 7521a30Row pattern recognition patch (planner).
1016 15685 if (depth >= RPR_DEPTH_MAX) 7521a30Row pattern recognition patch (planner).
1017 4 ereport(ERROR, 7521a30Row pattern recognition patch (planner).
1018 - errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), 7521a30Row pattern recognition patch (planner).
1019 - errmsg("pattern nesting too deep"), 7521a30Row pattern recognition patch (planner).
1020 - errdetail("Pattern nesting depth %d exceeds maximum %d.", 7521a30Row pattern recognition patch (planner).
1021 - depth, RPR_DEPTH_MAX - 1)); 7521a30Row pattern recognition patch (planner).
1022 - 7521a30Row pattern recognition patch (planner).
1023 - /* Track maximum depth */ 7521a30Row pattern recognition patch (planner).
1024 15681 *maxDepth = Max(*maxDepth, depth); 7521a30Row pattern recognition patch (planner).
1025 - 7521a30Row pattern recognition patch (planner).
1026 15681 switch (node->nodeType) 7521a30Row pattern recognition patch (planner).
1027 - { 7521a30Row pattern recognition patch (planner).
1028 9180 case RPR_PATTERN_VAR: 7521a30Row pattern recognition patch (planner).
1029 - /* Count element */ 7521a30Row pattern recognition patch (planner).
1030 9180 (*numElements)++; 7521a30Row pattern recognition patch (planner).
1031 - 7521a30Row pattern recognition patch (planner).
1032 - /* Collect variable name if not already present */ 7521a30Row pattern recognition patch (planner).
1033 159975 for (i = 0; i < *numVars; i++) 7521a30Row pattern recognition patch (planner).
1034 - { 7521a30Row pattern recognition patch (planner).
1035 159710 if (strcmp(varNames[i], node->varName) == 0) 7521a30Row pattern recognition patch (planner).
1036 - return; /* Already have this variable */ 7521a30Row pattern recognition patch (planner).
1037 - } 7521a30Row pattern recognition patch (planner).
1038 - 7521a30Row pattern recognition patch (planner).
1039 - /* 7521a30Row pattern recognition patch (planner).
1040 - * Variable not in DEFINE clause - this is valid per ISO/IEC 7521a30Row pattern recognition patch (planner).
1041 - * 19075-5 Feature R020. Such variables are implicitly TRUE. Add 7521a30Row pattern recognition patch (planner).
1042 - * to varNames so they get a varId >= defineVariableList length, 7521a30Row pattern recognition patch (planner).
1043 - * which executor treats as TRUE. 7521a30Row pattern recognition patch (planner).
1044 - */ 7521a30Row pattern recognition patch (planner).
1045 265 Assert(*numVars <= RPR_VARID_MAX); 7521a30Row pattern recognition patch (planner).
1046 265 varNames[(*numVars)++] = node->varName; 7521a30Row pattern recognition patch (planner).
1047 265 break; 7521a30Row pattern recognition patch (planner).
1048 - 7521a30Row pattern recognition patch (planner).
1049 - case RPR_PATTERN_SEQ: 7521a30Row pattern recognition patch (planner).
1050 - /* Sequence: just recurse into children */ 7521a30Row pattern recognition patch (planner).
1051 9610 foreach_node(RPRPatternNode, child, node->children) 7521a30Row pattern recognition patch (planner).
1052 - { 7521a30Row pattern recognition patch (planner).
1053 7070 scanRPRPatternRecursive(child, varNames, 7521a30Row pattern recognition patch (planner).
1054 - numVars, numElements, depth, maxDepth); 7521a30Row pattern recognition patch (planner).
1055 - } 7521a30Row pattern recognition patch (planner).
1056 - break; 7521a30Row pattern recognition patch (planner).
1057 - 7521a30Row pattern recognition patch (planner).
1058 3166 case RPR_PATTERN_GROUP: 7521a30Row pattern recognition patch (planner).
1059 - 7521a30Row pattern recognition patch (planner).
1060 - /* 7521a30Row pattern recognition patch (planner).
1061 - * Add BEGIN element if group has non-trivial quantifier (not 7521a30Row pattern recognition patch (planner).
1062 - * {1,1}) 7521a30Row pattern recognition patch (planner).
1063 - */ 7521a30Row pattern recognition patch (planner).
1064 3166 if (node->min != 1 || node->max != 1) 7521a30Row pattern recognition patch (planner).
1065 3166 (*numElements)++; 7521a30Row pattern recognition patch (planner).
1066 - 7521a30Row pattern recognition patch (planner).
1067 - /* Recurse into children at increased depth */ 7521a30Row pattern recognition patch (planner).
1068 5316 foreach_node(RPRPatternNode, child, node->children) 7521a30Row pattern recognition patch (planner).
1069 - { 7521a30Row pattern recognition patch (planner).
1070 3166 scanRPRPatternRecursive(child, varNames, 7521a30Row pattern recognition patch (planner).
1071 3166 numVars, numElements, depth + 1, maxDepth); 7521a30Row pattern recognition patch (planner).
1072 - } 7521a30Row pattern recognition patch (planner).
1073 - 7521a30Row pattern recognition patch (planner).
1074 - /* Add END element if group has non-trivial quantifier (not {1,1}) */ 7521a30Row pattern recognition patch (planner).
1075 2150 if (node->min != 1 || node->max != 1) 7521a30Row pattern recognition patch (planner).
1076 2150 (*numElements)++; 7521a30Row pattern recognition patch (planner).
1077 - break; 7521a30Row pattern recognition patch (planner).
1078 - 7521a30Row pattern recognition patch (planner).
1079 795 case RPR_PATTERN_ALT: 7521a30Row pattern recognition patch (planner).
1080 - /* Count ALT start element */ 7521a30Row pattern recognition patch (planner).
1081 795 (*numElements)++; 7521a30Row pattern recognition patch (planner).
1082 - 7521a30Row pattern recognition patch (planner).
1083 - /* Recurse into children at increased depth */ 7521a30Row pattern recognition patch (planner).
1084 2515 foreach_node(RPRPatternNode, child, node->children) 7521a30Row pattern recognition patch (planner).
1085 - { 7521a30Row pattern recognition patch (planner).
1086 1720 scanRPRPatternRecursive(child, varNames, 7521a30Row pattern recognition patch (planner).
1087 1720 numVars, numElements, depth + 1, maxDepth); 7521a30Row pattern recognition patch (planner).
1088 - } 7521a30Row pattern recognition patch (planner).
1089 - break; 7521a30Row pattern recognition patch (planner).
1090 - } 7521a30Row pattern recognition patch (planner).
1091 - } 7521a30Row pattern recognition patch (planner).
scanRPRPattern() lines 1102-1118
Modified Lines Coverage: 7/8 lines (87.5%)
LineHitsSourceCommit
1102 3729 scanRPRPattern(RPRPatternNode *node, char **varNames, int *numVars, 7521a30Row pattern recognition patch (planner).
1103 - int *numElements, RPRDepth *maxDepth) 7521a30Row pattern recognition patch (planner).
1104 - { 7521a30Row pattern recognition patch (planner).
1105 3729 *numElements = 0; 7521a30Row pattern recognition patch (planner).
1106 3729 *maxDepth = 0; 7521a30Row pattern recognition patch (planner).
1107 - 7521a30Row pattern recognition patch (planner).
1108 3729 scanRPRPatternRecursive(node, varNames, numVars, numElements, 0, maxDepth); 7521a30Row pattern recognition patch (planner).
1109 - 7521a30Row pattern recognition patch (planner).
1110 3725 (*numElements)++; /* +1 for FIN marker */ 7521a30Row pattern recognition patch (planner).
1111 - 7521a30Row pattern recognition patch (planner).
1112 3725 if (*numElements > RPR_ELEMIDX_MAX) 7521a30Row pattern recognition patch (planner).
1113 0 ereport(ERROR, 7521a30Row pattern recognition patch (planner).
ReachableHard to reach · confidence high · scanRPRPattern @1113
How to test
Use alternating distinct variables so the optimizer's mergeConsecutiveVars cannot collapse them, while staying within RPR_VARID_MAX (only 2 distinct vars).
Programmatic test (avoid a giant literal in rpr.sql for .out portability):

SELECT format($$SELECT count(*) OVER w
FROM (SELECT 1 i) t
WINDOW w AS (ORDER BY i
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
    INITIAL
PATTERN (%s)
DEFINE A AS TRUE, B AS TRUE)$$,
    repeat('A B ', 16384)) \gexec

Expected (LC_MESSAGES=C):
  ERROR:  pattern too complex
  DETAIL:
Pattern has 32769 elements, maximum is 32767.

Mechanism: 16384 'A B ' pairs = 32768 VAR elements;
scanRPRPattern adds +1 FIN (rpr.c:1110) -> 32769 > RPR_ELEMIDX_MAX (PG_INT16_MAX = 32767), firing line 1113. mergeConsecutiveVars only merges same-name neighbors, so alternating A/B survives optimization.
Verified live: 16383 pairs (32767 elements) passes, 16384 pairs (32769 elements) errors.
The originally proposed repeat('A ', 32767) does NOT work.
Verdict
Line 1113 is genuinely reachable (classification hard-to-reach is correct), but the PROPOSED test is WRONG and would NOT cover it.
I empirically triggered the line on the RPR build (ERROR: pattern too complex / DETAIL:
Pattern has 32769 elements, maximum is 32767) using ALTERNATING variables, and empirically confirmed the proposed single-variable test (repeat('A ', 32767), even 100000 reps) SUCCEEDS with no error.
Root cause of the refutation: buildRPRPattern (rpr.c:1929) calls optimizeRPRPattern BEFORE scanRPRPattern (rpr.c:1935).
The pass mergeConsecutiveVars (rpr.c:225-288) merges consecutive identical non-reluctant VARs into one element with summed quantifiers (A A A -> A{3,3}).
So repeating the SAME variable collapses to a single element and never approaches RPR_ELEMIDX_MAX.
The proposal's stated mechanism (repetition of one var inflating numElements) is false.
Fix the test by alternating two distinct variable names (A B A B ...) which the merge cannot combine, staying within RPR_VARID_MAX=240 (only 2 vars used).
Boundary verified: 16383 'A B' pairs (32767 elements) passes;
16384 pairs (32769 elements) errors at line 1113. Also the proposed query syntax was invalid: the RPR grammar (gram.y:17361-17595) has no
MEASURES in the window spec, and clause order is frame then [AFTER MATCH SKIP] [INITIAL]
PATTERN (...)
DEFINE.
1114 - errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), 7521a30Row pattern recognition patch (planner).
1115 - errmsg("pattern too complex"), 7521a30Row pattern recognition patch (planner).
1116 - errdetail("Pattern has %d elements, maximum is %d.", 7521a30Row pattern recognition patch (planner).
1117 - *numElements, RPR_ELEMIDX_MAX)); 7521a30Row pattern recognition patch (planner).
1118 3725 } 7521a30Row pattern recognition patch (planner).
makeRPRPattern() lines 1128-1153
Modified Lines Coverage: 15/15 lines (100.0%)
LineHitsSourceCommit
1128 3725 makeRPRPattern(int numVars, int numElements, RPRDepth maxDepth, 7521a30Row pattern recognition patch (planner).
1129 - char **varNamesStack) 7521a30Row pattern recognition patch (planner).
1130 - { 7521a30Row pattern recognition patch (planner).
1131 3725 RPRPattern *result; 7521a30Row pattern recognition patch (planner).
1132 3725 int i; 7521a30Row pattern recognition patch (planner).
1133 - 7521a30Row pattern recognition patch (planner).
1134 3725 result = makeNode(RPRPattern); 7521a30Row pattern recognition patch (planner).
1135 3725 result->numVars = numVars; 7521a30Row pattern recognition patch (planner).
1136 - 7521a30Row pattern recognition patch (planner).
1137 - /* depth < RPR_DEPTH_MAX, so maxDepth+1 never aliases RPR_DEPTH_NONE. */ 7521a30Row pattern recognition patch (planner).
1138 3725 Assert(maxDepth < RPR_DEPTH_MAX); 7521a30Row pattern recognition patch (planner).
1139 3725 result->maxDepth = maxDepth + 1; /* +1: depth is 0-based */ 7521a30Row pattern recognition patch (planner).
1140 3725 result->numElements = numElements; 7521a30Row pattern recognition patch (planner).
1141 - 7521a30Row pattern recognition patch (planner).
1142 - /* Copy varNames (pattern must have at least one variable) */ 7521a30Row pattern recognition patch (planner).
1143 3725 Assert(numVars > 0); 7521a30Row pattern recognition patch (planner).
1144 3725 result->varNames = palloc(numVars * sizeof(char *)); 7521a30Row pattern recognition patch (planner).
1145 12645 for (i = 0; i < numVars; i++) 7521a30Row pattern recognition patch (planner).
1146 8920 result->varNames[i] = pstrdup(varNamesStack[i]); 7521a30Row pattern recognition patch (planner).
1147 - 7521a30Row pattern recognition patch (planner).
1148 - /* Allocate elements array (zero-init for reserved fields) */ 7521a30Row pattern recognition patch (planner).
1149 3725 Assert(numElements >= 2); 7521a30Row pattern recognition patch (planner).
1150 3725 result->elements = palloc0(numElements * sizeof(RPRPatternElement)); 7521a30Row pattern recognition patch (planner).
1151 - 7521a30Row pattern recognition patch (planner).
1152 3725 return result; 7521a30Row pattern recognition patch (planner).
1153 - } 7521a30Row pattern recognition patch (planner).
getVarIdFromPattern() lines 1162-1173
Modified Lines Coverage: 4/5 lines (80.0%)
LineHitsSourceCommit
1162 9180 getVarIdFromPattern(RPRPattern *pat, const char *varName) 7521a30Row pattern recognition patch (planner).
1163 - { 7521a30Row pattern recognition patch (planner).
1164 159975 for (int i = 0; i < pat->numVars; i++) 7521a30Row pattern recognition patch (planner).
1165 - { 7521a30Row pattern recognition patch (planner).
1166 159975 if (strcmp(pat->varNames[i], varName) == 0) 7521a30Row pattern recognition patch (planner).
1167 9180 return (RPRVarId) i; 7521a30Row pattern recognition patch (planner).
1168 - } 7521a30Row pattern recognition patch (planner).
1169 - 7521a30Row pattern recognition patch (planner).
1170 - /* Should not happen - variable should already be collected */ 7521a30Row pattern recognition patch (planner).
1171 0 elog(ERROR, "pattern variable \"%s\" not found", varName); 7521a30Row pattern recognition patch (planner).
UnreachableDefensive (unreachable) · confidence high · getVarIdFromPattern @1171
Reason
Confirmed unreachable via any SQL/regression input. getVarIdFromPattern has a single call site (rpr.c:1187) inside fillRPRPatternVar, passing node->varName from a RPR_PATTERN_VAR node. buildRPRPattern (rpr.c:1929-1942) builds one optimized tree, scans it in pass 1 (scanRPRPattern -> scanRPRPatternRecursive), then fills the SAME tree in pass 2 (fillRPRPattern).
In pass 1, every RPR_PATTERN_VAR node unconditionally appends its varName to varNames (rpr.c:1046) unless already present (rpr.c:1036), and the switch recurses identically into SEQ/GROUP/ALT children. makeRPRPattern (rpr.c:1144-1146) copies all numVars names.
Thus when pass 2 reaches a VAR node, its name is guaranteed already in pat->varNames, so the loop at 1164 always returns before line 1171. Hitting 1171 would require a VAR node in the fill pass that was absent from the scan pass;
since both passes traverse the identical optimized pointer with no intervening mutation or re-optimization, this cannot occur.
I attempted to refute by looking for a tree-shape mismatch or a VAR introduced after scanning -- none exists.
This is a legitimate internal-invariant guard.
Recommended fix
Keep the elog(ERROR) as an internal-error consistency guard followed by pg_unreachable();
no behavioral change.
Downgrading to Assert is possible but elog provides a safer hard-failure for production builds where Asserts are compiled out, so the current code is appropriate.
Marking the line as deliberately uncovered (or wrapping with a coverage-exclusion comment) is the only reasonable action.
1172 - pg_unreachable(); 7521a30Row pattern recognition patch (planner).
1173 - } 7521a30Row pattern recognition patch (planner).
fillRPRPatternVar() lines 1182-1201
Modified Lines Coverage: 14/14 lines (100.0%)
LineHitsSourceCommit
1182 9180 fillRPRPatternVar(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth depth) 7521a30Row pattern recognition patch (planner).
1183 - { 7521a30Row pattern recognition patch (planner).
1184 9180 RPRPatternElement *elem = &pat->elements[*idx]; 7521a30Row pattern recognition patch (planner).
1185 - 7521a30Row pattern recognition patch (planner).
1186 9180 memset(elem, 0, sizeof(RPRPatternElement)); 7521a30Row pattern recognition patch (planner).
1187 9180 elem->varId = getVarIdFromPattern(pat, node->varName); 7521a30Row pattern recognition patch (planner).
1188 9180 elem->depth = depth; 7521a30Row pattern recognition patch (planner).
1189 9180 elem->min = node->min; 7521a30Row pattern recognition patch (planner).
1190 9180 elem->max = (node->max == PG_INT32_MAX) ? RPR_QUANTITY_INF : node->max; 7521a30Row pattern recognition patch (planner).
1191 9180 Assert(elem->min >= 0 && elem->min < RPR_QUANTITY_INF && 7521a30Row pattern recognition patch (planner).
1192 - elem->max >= 1 && 7521a30Row pattern recognition patch (planner).
1193 - (elem->max == RPR_QUANTITY_INF || elem->min <= elem->max)); 7521a30Row pattern recognition patch (planner).
1194 9180 elem->next = RPR_ELEMIDX_INVALID; 7521a30Row pattern recognition patch (planner).
1195 9180 elem->jump = RPR_ELEMIDX_INVALID; 7521a30Row pattern recognition patch (planner).
1196 9180 if (node->reluctant) 7521a30Row pattern recognition patch (planner).
1197 235 elem->flags |= RPR_ELEM_RELUCTANT; 7521a30Row pattern recognition patch (planner).
1198 9180 (*idx)++; 7521a30Row pattern recognition patch (planner).
1199 - 7521a30Row pattern recognition patch (planner).
1200 9180 return (node->min == 0); 7521a30Row pattern recognition patch (planner).
1201 - } 7521a30Row pattern recognition patch (planner).
fillRPRPatternGroup() lines 1226-1294
Modified Lines Coverage: 40/40 lines (100.0%)
LineHitsSourceCommit
1226 2150 fillRPRPatternGroup(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth depth) 7521a30Row pattern recognition patch (planner).
1227 - { 7521a30Row pattern recognition patch (planner).
1228 2150 int groupStartIdx = *idx; 7521a30Row pattern recognition patch (planner).
1229 2150 int beginIdx = -1; 7521a30Row pattern recognition patch (planner).
1230 2150 bool bodyNullable = true; 7521a30Row pattern recognition patch (planner).
1231 - 7521a30Row pattern recognition patch (planner).
1232 - /* Add BEGIN marker if group has non-trivial quantifier (not {1,1}) */ 7521a30Row pattern recognition patch (planner).
1233 2150 if (node->min != 1 || node->max != 1) 7521a30Row pattern recognition patch (planner).
1234 - { 7521a30Row pattern recognition patch (planner).
1235 2150 RPRPatternElement *elem = &pat->elements[*idx]; 7521a30Row pattern recognition patch (planner).
1236 - 7521a30Row pattern recognition patch (planner).
1237 2150 beginIdx = *idx; 7521a30Row pattern recognition patch (planner).
1238 2150 memset(elem, 0, sizeof(RPRPatternElement)); 7521a30Row pattern recognition patch (planner).
1239 2150 elem->varId = RPR_VARID_BEGIN; 7521a30Row pattern recognition patch (planner).
1240 2150 elem->depth = depth; 7521a30Row pattern recognition patch (planner).
1241 2150 elem->min = node->min; 7521a30Row pattern recognition patch (planner).
1242 2150 elem->max = (node->max == PG_INT32_MAX) ? RPR_QUANTITY_INF : node->max; 7521a30Row pattern recognition patch (planner).
1243 2150 Assert(elem->min >= 0 && elem->min < RPR_QUANTITY_INF && 7521a30Row pattern recognition patch (planner).
1244 - elem->max >= 1 && 7521a30Row pattern recognition patch (planner).
1245 - (elem->max == RPR_QUANTITY_INF || elem->min <= elem->max)); 7521a30Row pattern recognition patch (planner).
1246 2150 elem->next = RPR_ELEMIDX_INVALID; /* set by finalize */ 7521a30Row pattern recognition patch (planner).
1247 2150 elem->jump = RPR_ELEMIDX_INVALID; /* set after END */ 7521a30Row pattern recognition patch (planner).
1248 2150 if (node->reluctant) 7521a30Row pattern recognition patch (planner).
1249 1340 elem->flags |= RPR_ELEM_RELUCTANT; 7521a30Row pattern recognition patch (planner).
1250 2150 (*idx)++; 7521a30Row pattern recognition patch (planner).
1251 2150 groupStartIdx = *idx; /* children start after BEGIN */ 7521a30Row pattern recognition patch (planner).
1252 - } 7521a30Row pattern recognition patch (planner).
1253 - 7521a30Row pattern recognition patch (planner).
1254 4300 foreach_node(RPRPatternNode, child, node->children) 7521a30Row pattern recognition patch (planner).
1255 - { 7521a30Row pattern recognition patch (planner).
1256 2150 if (!fillRPRPattern(child, pat, idx, depth + 1)) 7521a30Row pattern recognition patch (planner).
1257 2080 bodyNullable = false; 7521a30Row pattern recognition patch (planner).
1258 - } 7521a30Row pattern recognition patch (planner).
1259 - 7521a30Row pattern recognition patch (planner).
1260 - /* Add group end marker if group has non-trivial quantifier (not {1,1}) */ 7521a30Row pattern recognition patch (planner).
1261 2150 if (node->min != 1 || node->max != 1) 7521a30Row pattern recognition patch (planner).
1262 - { 7521a30Row pattern recognition patch (planner).
1263 2150 RPRPatternElement *beginElem = &pat->elements[beginIdx]; 7521a30Row pattern recognition patch (planner).
1264 2150 RPRPatternElement *endElem = &pat->elements[*idx]; 7521a30Row pattern recognition patch (planner).
1265 - 7521a30Row pattern recognition patch (planner).
1266 2150 memset(endElem, 0, sizeof(RPRPatternElement)); 7521a30Row pattern recognition patch (planner).
1267 2150 endElem->varId = RPR_VARID_END; 7521a30Row pattern recognition patch (planner).
1268 2150 endElem->depth = depth; 7521a30Row pattern recognition patch (planner).
1269 2150 endElem->min = node->min; 7521a30Row pattern recognition patch (planner).
1270 2150 endElem->max = (node->max == PG_INT32_MAX) ? RPR_QUANTITY_INF : node->max; 7521a30Row pattern recognition patch (planner).
1271 2150 Assert(endElem->min >= 0 && endElem->min < RPR_QUANTITY_INF && 7521a30Row pattern recognition patch (planner).
1272 - endElem->max >= 1 && 7521a30Row pattern recognition patch (planner).
1273 - (endElem->max == RPR_QUANTITY_INF || endElem->min <= endElem->max)); 7521a30Row pattern recognition patch (planner).
1274 2150 endElem->next = RPR_ELEMIDX_INVALID; 7521a30Row pattern recognition patch (planner).
1275 2150 endElem->jump = groupStartIdx; /* loop to first child */ 7521a30Row pattern recognition patch (planner).
1276 2150 if (node->reluctant) 7521a30Row pattern recognition patch (planner).
1277 1340 endElem->flags |= RPR_ELEM_RELUCTANT; 7521a30Row pattern recognition patch (planner).
1278 - 7521a30Row pattern recognition patch (planner).
1279 - /* 7521a30Row pattern recognition patch (planner).
1280 - * If the group body is nullable (all paths can match empty), mark the 7521a30Row pattern recognition patch (planner).
1281 - * END element so that nfa_advance_end can fast-forward the iteration 7521a30Row pattern recognition patch (planner).
1282 - * count to min when reached via empty-match skip paths. 7521a30Row pattern recognition patch (planner).
1283 - */ 7521a30Row pattern recognition patch (planner).
1284 2150 if (bodyNullable) 7521a30Row pattern recognition patch (planner).
1285 70 endElem->flags |= RPR_ELEM_EMPTY_LOOP; 7521a30Row pattern recognition patch (planner).
1286 - 7521a30Row pattern recognition patch (planner).
1287 2150 (*idx)++; 7521a30Row pattern recognition patch (planner).
1288 - 7521a30Row pattern recognition patch (planner).
1289 - /* Set BEGIN skip pointer (next is set by finalize) */ 7521a30Row pattern recognition patch (planner).
1290 2150 beginElem->jump = *idx; /* skip: go to after END */ 7521a30Row pattern recognition patch (planner).
1291 - } 7521a30Row pattern recognition patch (planner).
1292 - 7521a30Row pattern recognition patch (planner).
1293 2150 return (node->min == 0 || bodyNullable); 7521a30Row pattern recognition patch (planner).
1294 - } 7521a30Row pattern recognition patch (planner).
fillRPRPatternAlt() lines 1307-1382
Modified Lines Coverage: 39/39 lines (100.0%)
LineHitsSourceCommit
1307 795 fillRPRPatternAlt(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth depth) 7521a30Row pattern recognition patch (planner).
1308 - { 7521a30Row pattern recognition patch (planner).
1309 795 ListCell *lc; 7521a30Row pattern recognition patch (planner).
1310 795 ListCell *lc2; 7521a30Row pattern recognition patch (planner).
1311 795 RPRPatternElement *elem; 7521a30Row pattern recognition patch (planner).
1312 795 List *altBranchStarts = NIL; 7521a30Row pattern recognition patch (planner).
1313 795 List *altEndPositions = NIL; 7521a30Row pattern recognition patch (planner).
1314 795 int afterAltIdx; 7521a30Row pattern recognition patch (planner).
1315 795 bool anyNullable = false; 7521a30Row pattern recognition patch (planner).
1316 - 7521a30Row pattern recognition patch (planner).
1317 - /* Add alternation start marker */ 7521a30Row pattern recognition patch (planner).
1318 795 elem = &pat->elements[*idx]; 7521a30Row pattern recognition patch (planner).
1319 795 memset(elem, 0, sizeof(RPRPatternElement)); 7521a30Row pattern recognition patch (planner).
1320 795 elem->varId = RPR_VARID_ALT; 7521a30Row pattern recognition patch (planner).
1321 795 elem->depth = depth; 7521a30Row pattern recognition patch (planner).
1322 795 elem->min = 1; 7521a30Row pattern recognition patch (planner).
1323 795 elem->max = 1; 7521a30Row pattern recognition patch (planner).
1324 795 elem->next = RPR_ELEMIDX_INVALID; 7521a30Row pattern recognition patch (planner).
1325 795 elem->jump = RPR_ELEMIDX_INVALID; 7521a30Row pattern recognition patch (planner).
1326 795 (*idx)++; 7521a30Row pattern recognition patch (planner).
1327 - 7521a30Row pattern recognition patch (planner).
1328 - /* Fill each alternative */ 7521a30Row pattern recognition patch (planner).
1329 2515 foreach_node(RPRPatternNode, alt, node->children) 7521a30Row pattern recognition patch (planner).
1330 - { 7521a30Row pattern recognition patch (planner).
1331 1720 int branchStart = *idx; 7521a30Row pattern recognition patch (planner).
1332 - 7521a30Row pattern recognition patch (planner).
1333 1720 altBranchStarts = lappend_int(altBranchStarts, branchStart); 7521a30Row pattern recognition patch (planner).
1334 1720 if (fillRPRPattern(alt, pat, idx, depth + 1)) 7521a30Row pattern recognition patch (planner).
1335 35 anyNullable = true; 7521a30Row pattern recognition patch (planner).
1336 1720 altEndPositions = lappend_int(altEndPositions, *idx - 1); 7521a30Row pattern recognition patch (planner).
1337 - } 7521a30Row pattern recognition patch (planner).
1338 - 7521a30Row pattern recognition patch (planner).
1339 - /* Set jump on first element of each alternative to next alternative */ 7521a30Row pattern recognition patch (planner).
1340 2515 foreach(lc, altBranchStarts) 7521a30Row pattern recognition patch (planner).
1341 - { 7521a30Row pattern recognition patch (planner).
1342 1720 int firstElemIdx = lfirst_int(lc); 7521a30Row pattern recognition patch (planner).
1343 - 7521a30Row pattern recognition patch (planner).
1344 1720 if (lnext(altBranchStarts, lc) != NULL) 7521a30Row pattern recognition patch (planner).
1345 925 pat->elements[firstElemIdx].jump = lfirst_int(lnext(altBranchStarts, lc)); 7521a30Row pattern recognition patch (planner).
1346 - } 7521a30Row pattern recognition patch (planner).
1347 - 7521a30Row pattern recognition patch (planner).
1348 - /* Set next on last element of each alternative to after the alternation */ 7521a30Row pattern recognition patch (planner).
1349 795 afterAltIdx = *idx; 7521a30Row pattern recognition patch (planner).
1350 - 7521a30Row pattern recognition patch (planner).
1351 2515 forboth(lc, altEndPositions, lc2, altBranchStarts) 7521a30Row pattern recognition patch (planner).
1352 - { 7521a30Row pattern recognition patch (planner).
1353 1720 int endPos = lfirst_int(lc); 7521a30Row pattern recognition patch (planner).
1354 1720 int branchStart = lfirst_int(lc2); 7521a30Row pattern recognition patch (planner).
1355 - 7521a30Row pattern recognition patch (planner).
1356 1720 if (pat->elements[endPos].next != RPR_ELEMIDX_INVALID) 7521a30Row pattern recognition patch (planner).
1357 - { 7521a30Row pattern recognition patch (planner).
1358 - /* 7521a30Row pattern recognition patch (planner).
1359 - * An inner ALT already set next on this element. Redirect all 7521a30Row pattern recognition patch (planner).
1360 - * elements in this branch that share the same target to point to 7521a30Row pattern recognition patch (planner).
1361 - * after this ALT instead. 7521a30Row pattern recognition patch (planner).
1362 - */ 7521a30Row pattern recognition patch (planner).
1363 - int oldTarget = pat->elements[endPos].next; 7521a30Row pattern recognition patch (planner).
1364 - int j; 7521a30Row pattern recognition patch (planner).
1365 - 7521a30Row pattern recognition patch (planner).
1366 425 for (j = branchStart; j <= endPos; j++) 7521a30Row pattern recognition patch (planner).
1367 - { 7521a30Row pattern recognition patch (planner).
1368 365 if (pat->elements[j].next == oldTarget) 7521a30Row pattern recognition patch (planner).
1369 160 pat->elements[j].next = afterAltIdx; 7521a30Row pattern recognition patch (planner).
1370 - } 7521a30Row pattern recognition patch (planner).
1371 - } 7521a30Row pattern recognition patch (planner).
1372 - else 7521a30Row pattern recognition patch (planner).
1373 - { 7521a30Row pattern recognition patch (planner).
1374 1660 pat->elements[endPos].next = afterAltIdx; 7521a30Row pattern recognition patch (planner).
1375 - } 7521a30Row pattern recognition patch (planner).
1376 - } 7521a30Row pattern recognition patch (planner).
1377 - 7521a30Row pattern recognition patch (planner).
1378 795 list_free(altBranchStarts); 7521a30Row pattern recognition patch (planner).
1379 795 list_free(altEndPositions); 7521a30Row pattern recognition patch (planner).
1380 - 7521a30Row pattern recognition patch (planner).
1381 795 return anyNullable; 7521a30Row pattern recognition patch (planner).
1382 - } 7521a30Row pattern recognition patch (planner).
fillRPRPattern() lines 1396-1427
Modified Lines Coverage: 14/15 lines (93.3%)
LineHitsSourceCommit
1396 14665 fillRPRPattern(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth depth) 7521a30Row pattern recognition patch (planner).
1397 - { 7521a30Row pattern recognition patch (planner).
1398 14665 bool allNullable = true; 7521a30Row pattern recognition patch (planner).
1399 - 7521a30Row pattern recognition patch (planner).
1400 - /* Pattern nodes from parser are never NULL */ 7521a30Row pattern recognition patch (planner).
1401 14665 Assert(node != NULL); 7521a30Row pattern recognition patch (planner).
1402 - 7521a30Row pattern recognition patch (planner).
1403 14665 check_stack_depth(); 7521a30Row pattern recognition patch (planner).
1404 - 7521a30Row pattern recognition patch (planner).
1405 14665 switch (node->nodeType) 7521a30Row pattern recognition patch (planner).
1406 - { 7521a30Row pattern recognition patch (planner).
1407 - case RPR_PATTERN_SEQ: 7521a30Row pattern recognition patch (planner).
1408 9610 foreach_node(RPRPatternNode, child, node->children) 7521a30Row pattern recognition patch (planner).
1409 - { 7521a30Row pattern recognition patch (planner).
1410 7070 if (!fillRPRPattern(child, pat, idx, depth)) 7521a30Row pattern recognition patch (planner).
1411 6835 allNullable = false; 7521a30Row pattern recognition patch (planner).
1412 - } 7521a30Row pattern recognition patch (planner).
1413 - return allNullable; 7521a30Row pattern recognition patch (planner).
1414 - 7521a30Row pattern recognition patch (planner).
1415 9180 case RPR_PATTERN_VAR: 7521a30Row pattern recognition patch (planner).
1416 9180 return fillRPRPatternVar(node, pat, idx, depth); 7521a30Row pattern recognition patch (planner).
1417 - 7521a30Row pattern recognition patch (planner).
1418 2150 case RPR_PATTERN_GROUP: 7521a30Row pattern recognition patch (planner).
1419 2150 return fillRPRPatternGroup(node, pat, idx, depth); 7521a30Row pattern recognition patch (planner).
1420 - 7521a30Row pattern recognition patch (planner).
1421 795 case RPR_PATTERN_ALT: 7521a30Row pattern recognition patch (planner).
1422 795 return fillRPRPatternAlt(node, pat, idx, depth); 7521a30Row pattern recognition patch (planner).
1423 - } 7521a30Row pattern recognition patch (planner).
1424 - 7521a30Row pattern recognition patch (planner).
1425 0 pg_unreachable(); 7521a30Row pattern recognition patch (planner).
UnreachableDefensive (unreachable) · confidence high · fillRPRPattern @1425
Reason
Confirmed defensive-unreachable.
The switch at rpr.c:1405 dispatches on RPRPatternNode->nodeType, whose type RPRPatternNodeType (parsenodes.h:615-621) is an enum with exactly four values:
RPR_PATTERN_VAR, RPR_PATTERN_SEQ, RPR_PATTERN_ALT, RPR_PATTERN_GROUP.
All four are handled by case labels at lines 1407/1415/1418/1421, and every branch returns unconditionally (no break/fall-through).
I checked every site that sets nodeType (gram.y:17652/17684/17713/17726/21425/21484 and the makeRPR* helpers) and each assigns one of the four valid values.
There is no makeNode/palloc0 path that leaves nodeType zero-initialized to an out-of-enum sentinel before it reaches fillRPRPattern;
the parser always populates it.
Therefore the fall-through pg_unreachable() at line 1425 can only fire on memory corruption or an enum extension never produced by any SQL/regression input.
No input reaches it.
Recommended fix
Keep as-is.
The pg_unreachable() following an exhaustive enum switch is the standard PostgreSQL idiom for an exhaustive-switch guard and silences compiler warnings about missing return.
No change needed.
1426 - return false; 7521a30Row pattern recognition patch (planner).
1427 - } 7521a30Row pattern recognition patch (planner).
finalizeRPRPattern() lines 1439-1471
Modified Lines Coverage: 19/19 lines (100.0%)
LineHitsSourceCommit
1439 3725 finalizeRPRPattern(RPRPattern *result) 7521a30Row pattern recognition patch (planner).
1440 - { 7521a30Row pattern recognition patch (planner).
1441 3725 int finIdx = result->numElements - 1; 7521a30Row pattern recognition patch (planner).
1442 3725 int i; 7521a30Row pattern recognition patch (planner).
1443 3725 RPRPatternElement *finElem; 7521a30Row pattern recognition patch (planner).
1444 - 7521a30Row pattern recognition patch (planner).
1445 - /* Initialize absorption flag */ 7521a30Row pattern recognition patch (planner).
1446 3725 result->isAbsorbable = false; 7521a30Row pattern recognition patch (planner).
1447 - 7521a30Row pattern recognition patch (planner).
1448 - /* Set up next pointers for elements that don't have one */ 7521a30Row pattern recognition patch (planner).
1449 18000 for (i = 0; i < finIdx; i++) 7521a30Row pattern recognition patch (planner).
1450 - { 7521a30Row pattern recognition patch (planner).
1451 14275 RPRPatternElement *elem = &result->elements[i]; 7521a30Row pattern recognition patch (planner).
1452 - 7521a30Row pattern recognition patch (planner).
1453 14275 if (elem->next == RPR_ELEMIDX_INVALID) 7521a30Row pattern recognition patch (planner).
1454 12615 elem->next = (i < finIdx - 1) ? i + 1 : finIdx; 7521a30Row pattern recognition patch (planner).
1455 - 7521a30Row pattern recognition patch (planner).
1456 - /* Verify quantifier range is valid */ 7521a30Row pattern recognition patch (planner).
1457 14275 Assert(elem->min >= 0 && elem->min < RPR_QUANTITY_INF && 7521a30Row pattern recognition patch (planner).
1458 - elem->max >= 1 && 7521a30Row pattern recognition patch (planner).
1459 - (elem->max == RPR_QUANTITY_INF || elem->min <= elem->max)); 7521a30Row pattern recognition patch (planner).
1460 - } 7521a30Row pattern recognition patch (planner).
1461 - 7521a30Row pattern recognition patch (planner).
1462 - /* Add FIN marker at the end */ 7521a30Row pattern recognition patch (planner).
1463 3725 finElem = &result->elements[finIdx]; 7521a30Row pattern recognition patch (planner).
1464 3725 memset(finElem, 0, sizeof(RPRPatternElement)); 7521a30Row pattern recognition patch (planner).
1465 3725 finElem->varId = RPR_VARID_FIN; 7521a30Row pattern recognition patch (planner).
1466 3725 finElem->depth = 0; 7521a30Row pattern recognition patch (planner).
1467 3725 finElem->min = 1; 7521a30Row pattern recognition patch (planner).
1468 3725 finElem->max = 1; 7521a30Row pattern recognition patch (planner).
1469 3725 finElem->next = RPR_ELEMIDX_INVALID; 7521a30Row pattern recognition patch (planner).
1470 3725 finElem->jump = RPR_ELEMIDX_INVALID; 7521a30Row pattern recognition patch (planner).
1471 3725 } 7521a30Row pattern recognition patch (planner).
isFixedLengthChildren() lines 1574-1616
Modified Lines Coverage: 16/16 lines (100.0%)
LineHitsSourceCommit
1574 163470 isFixedLengthChildren(RPRPattern *pattern, RPRElemIdx idx, RPRDepth scopeDepth) 7521a30Row pattern recognition patch (planner).
1575 - { 7521a30Row pattern recognition patch (planner).
1576 163470 RPRPatternElement *e = &pattern->elements[idx]; 7521a30Row pattern recognition patch (planner).
1577 - 7521a30Row pattern recognition patch (planner).
1578 163470 check_stack_depth(); 7521a30Row pattern recognition patch (planner).
1579 - 7521a30Row pattern recognition patch (planner).
1580 168025 while (e->depth == scopeDepth) 7521a30Row pattern recognition patch (planner).
1581 - { 7521a30Row pattern recognition patch (planner).
1582 166675 if (RPRElemIsVar(e)) 7521a30Row pattern recognition patch (planner).
1583 - { 7521a30Row pattern recognition patch (planner).
1584 6600 if (e->min != e->max) 7521a30Row pattern recognition patch (planner).
1585 - return false; 7521a30Row pattern recognition patch (planner).
1586 - } 7521a30Row pattern recognition patch (planner).
1587 160075 else if (RPRElemIsBegin(e)) 7521a30Row pattern recognition patch (planner).
1588 - { 7521a30Row pattern recognition patch (planner).
1589 159550 RPRElemIdx childIdx = e->next; 7521a30Row pattern recognition patch (planner).
1590 - 7521a30Row pattern recognition patch (planner).
1591 - /* Recurse into subgroup children at scopeDepth + 1 */ 7521a30Row pattern recognition patch (planner).
1592 159550 if (!isFixedLengthChildren(pattern, childIdx, scopeDepth + 1)) 7521a30Row pattern recognition patch (planner).
1593 - return false; 7521a30Row pattern recognition patch (planner).
1594 - 7521a30Row pattern recognition patch (planner).
1595 - /* Advance past the subgroup to its END element */ 7521a30Row pattern recognition patch (planner).
1596 130 e = &pattern->elements[e->next]; 7521a30Row pattern recognition patch (planner).
1597 445 while (e->depth > scopeDepth) 7521a30Row pattern recognition patch (planner).
1598 315 e = &pattern->elements[e->next]; 7521a30Row pattern recognition patch (planner).
1599 - 7521a30Row pattern recognition patch (planner).
1600 - /* e is now the END at scopeDepth; check its quantifier */ 7521a30Row pattern recognition patch (planner).
1601 130 Assert(RPRElemIsEnd(e) && e->depth == scopeDepth); 7521a30Row pattern recognition patch (planner).
1602 130 if (e->min != e->max) 7521a30Row pattern recognition patch (planner).
1603 - return false; 7521a30Row pattern recognition patch (planner).
1604 - } 7521a30Row pattern recognition patch (planner).
1605 - else 7521a30Row pattern recognition patch (planner).
1606 - { 7521a30Row pattern recognition patch (planner).
1607 - /* ALT inside group: not supported for absorption */ 7521a30Row pattern recognition patch (planner).
1608 - return false; 7521a30Row pattern recognition patch (planner).
1609 - } 7521a30Row pattern recognition patch (planner).
1610 - 7521a30Row pattern recognition patch (planner).
1611 4555 Assert(e->next != RPR_ELEMIDX_INVALID); 7521a30Row pattern recognition patch (planner).
1612 4555 e = &pattern->elements[e->next]; 7521a30Row pattern recognition patch (planner).
1613 - } 7521a30Row pattern recognition patch (planner).
1614 - 7521a30Row pattern recognition patch (planner).
1615 - return true; 7521a30Row pattern recognition patch (planner).
1616 - } 7521a30Row pattern recognition patch (planner).
isUnboundedStart() lines 1648-1692
Modified Lines Coverage: 21/21 lines (100.0%)
LineHitsSourceCommit
1648 5110 isUnboundedStart(RPRPattern *pattern, RPRElemIdx idx) 7521a30Row pattern recognition patch (planner).
1649 - { 7521a30Row pattern recognition patch (planner).
1650 5110 RPRPatternElement *elem = &pattern->elements[idx]; 7521a30Row pattern recognition patch (planner).
1651 5110 RPRDepth startDepth = elem->depth; 7521a30Row pattern recognition patch (planner).
1652 5110 RPRPatternElement *e; 7521a30Row pattern recognition patch (planner).
1653 - 7521a30Row pattern recognition patch (planner).
1654 - /* Case 1: Simple unbounded VAR at start (greedy only) */ 7521a30Row pattern recognition patch (planner).
1655 5110 if (RPRElemIsVar(elem) && elem->max == RPR_QUANTITY_INF && 7521a30Row pattern recognition patch (planner).
1656 1270 !RPRElemIsReluctant(elem)) 7521a30Row pattern recognition patch (planner).
1657 - { 7521a30Row pattern recognition patch (planner).
1658 - /* Set both flags on first element */ 7521a30Row pattern recognition patch (planner).
1659 1190 elem->flags |= RPR_ELEM_ABSORBABLE_BRANCH | RPR_ELEM_ABSORBABLE; 7521a30Row pattern recognition patch (planner).
1660 1190 return true; 7521a30Row pattern recognition patch (planner).
1661 - } 7521a30Row pattern recognition patch (planner).
1662 - 7521a30Row pattern recognition patch (planner).
1663 - /* 7521a30Row pattern recognition patch (planner).
1664 - * Case 2: Unbounded GROUP with fixed-length children. Each child must 7521a30Row pattern recognition patch (planner).
1665 - * have min == max (recursively for nested subgroups), ensuring a fixed 7521a30Row pattern recognition patch (planner).
1666 - * step size per iteration so that count-dominance holds. 7521a30Row pattern recognition patch (planner).
1667 - */ 7521a30Row pattern recognition patch (planner).
1668 3920 if (!isFixedLengthChildren(pattern, idx, startDepth)) 7521a30Row pattern recognition patch (planner).
1669 - return false; 7521a30Row pattern recognition patch (planner).
1670 - 7521a30Row pattern recognition patch (planner).
1671 - /* Find the END element at startDepth - 1 */ 7521a30Row pattern recognition patch (planner).
1672 1220 e = &pattern->elements[idx]; 7521a30Row pattern recognition patch (planner).
1673 3180 while (e->depth >= startDepth) 7521a30Row pattern recognition patch (planner).
1674 1960 e = &pattern->elements[e->next]; 7521a30Row pattern recognition patch (planner).
1675 - 7521a30Row pattern recognition patch (planner).
1676 - /* END must be unbounded greedy */ 7521a30Row pattern recognition patch (planner).
1677 1220 if (e->depth == startDepth - 1 && 7521a30Row pattern recognition patch (planner).
1678 915 RPRElemIsEnd(e) && e->max == RPR_QUANTITY_INF && 7521a30Row pattern recognition patch (planner).
1679 280 !RPRElemIsReluctant(e)) 7521a30Row pattern recognition patch (planner).
1680 - { 7521a30Row pattern recognition patch (planner).
1681 250 Assert(e->jump == idx); /* END points back to first child */ 7521a30Row pattern recognition patch (planner).
1682 - 7521a30Row pattern recognition patch (planner).
1683 - /* Set ABSORBABLE_BRANCH on all children, ABSORBABLE on END only */ 7521a30Row pattern recognition patch (planner).
1684 955 for (e = elem; !RPRElemIsEnd(e) || e->depth >= startDepth; 7521a30Row pattern recognition patch (planner).
1685 705 e = &pattern->elements[e->next]) 7521a30Row pattern recognition patch (planner).
1686 705 e->flags |= RPR_ELEM_ABSORBABLE_BRANCH; 7521a30Row pattern recognition patch (planner).
1687 250 e->flags |= RPR_ELEM_ABSORBABLE_BRANCH | RPR_ELEM_ABSORBABLE; 7521a30Row pattern recognition patch (planner).
1688 250 return true; 7521a30Row pattern recognition patch (planner).
1689 - } 7521a30Row pattern recognition patch (planner).
1690 - 7521a30Row pattern recognition patch (planner).
1691 - return false; 7521a30Row pattern recognition patch (planner).
1692 - } 7521a30Row pattern recognition patch (planner).
computeAbsorbabilityRecursive() lines 1708-1780
Modified Lines Coverage: 29/29 lines (100.0%)
LineHitsSourceCommit
1708 5620 computeAbsorbabilityRecursive(RPRPattern *pattern, RPRElemIdx startIdx, 7521a30Row pattern recognition patch (planner).
1709 - bool *hasAbsorbable) 7521a30Row pattern recognition patch (planner).
1710 - { 7521a30Row pattern recognition patch (planner).
1711 5620 RPRPatternElement *elem = &pattern->elements[startIdx]; 7521a30Row pattern recognition patch (planner).
1712 - 7521a30Row pattern recognition patch (planner).
1713 5620 check_stack_depth(); 7521a30Row pattern recognition patch (planner).
1714 - 7521a30Row pattern recognition patch (planner).
1715 5620 if (RPRElemIsAlt(elem)) 7521a30Row pattern recognition patch (planner).
1716 - { 7521a30Row pattern recognition patch (planner).
1717 - /* ALT: recursively check each branch */ 7521a30Row pattern recognition patch (planner).
1718 510 RPRElemIdx branchIdx = elem->next; 7521a30Row pattern recognition patch (planner).
1719 510 RPRPatternElement *branchFirst; 7521a30Row pattern recognition patch (planner).
1720 510 bool branchAbsorbable; 7521a30Row pattern recognition patch (planner).
1721 - 7521a30Row pattern recognition patch (planner).
1722 1630 while (branchIdx != RPR_ELEMIDX_INVALID) 7521a30Row pattern recognition patch (planner).
1723 - { 7521a30Row pattern recognition patch (planner).
1724 1145 branchAbsorbable = false; 7521a30Row pattern recognition patch (planner).
1725 - 7521a30Row pattern recognition patch (planner).
1726 1145 Assert(branchIdx < pattern->numElements); 7521a30Row pattern recognition patch (planner).
1727 1145 branchFirst = &pattern->elements[branchIdx]; 7521a30Row pattern recognition patch (planner).
1728 - 7521a30Row pattern recognition patch (planner).
1729 - /* Stop if element is outside ALT scope (not a branch) */ 7521a30Row pattern recognition patch (planner).
1730 1145 if (branchFirst->depth <= elem->depth) 7521a30Row pattern recognition patch (planner).
1731 - break; 7521a30Row pattern recognition patch (planner).
1732 - 7521a30Row pattern recognition patch (planner).
1733 - /* Recursively check this branch */ 7521a30Row pattern recognition patch (planner).
1734 1120 computeAbsorbabilityRecursive(pattern, branchIdx, &branchAbsorbable); 7521a30Row pattern recognition patch (planner).
1735 1120 if (branchAbsorbable) 7521a30Row pattern recognition patch (planner).
1736 - { 7521a30Row pattern recognition patch (planner).
1737 220 *hasAbsorbable = true; 7521a30Row pattern recognition patch (planner).
1738 - } 7521a30Row pattern recognition patch (planner).
1739 - 7521a30Row pattern recognition patch (planner).
1740 1120 branchIdx = branchFirst->jump; 7521a30Row pattern recognition patch (planner).
1741 - } 7521a30Row pattern recognition patch (planner).
1742 - 7521a30Row pattern recognition patch (planner).
1743 - /* Mark ALT element if any branch is absorbable */ 7521a30Row pattern recognition patch (planner).
1744 510 if (*hasAbsorbable) 7521a30Row pattern recognition patch (planner).
1745 170 elem->flags |= RPR_ELEM_ABSORBABLE_BRANCH; 7521a30Row pattern recognition patch (planner).
1746 - } 7521a30Row pattern recognition patch (planner).
1747 5110 else if (RPRElemIsBegin(elem)) 7521a30Row pattern recognition patch (planner).
1748 - { 7521a30Row pattern recognition patch (planner).
1749 - /* 7521a30Row pattern recognition patch (planner).
1750 - * BEGIN: first try to treat this BEGIN's children as an unbounded 7521a30Row pattern recognition patch (planner).
1751 - * group directly (handles nested fixed-length groups like ((A{2} 7521a30Row pattern recognition patch (planner).
1752 - * B{3}){2})+). If that fails, skip to first child and recurse as 7521a30Row pattern recognition patch (planner).
1753 - * before. 7521a30Row pattern recognition patch (planner).
1754 - */ 7521a30Row pattern recognition patch (planner).
1755 1895 if (isUnboundedStart(pattern, elem->next)) 7521a30Row pattern recognition patch (planner).
1756 - { 7521a30Row pattern recognition patch (planner).
1757 270 *hasAbsorbable = true; 7521a30Row pattern recognition patch (planner).
1758 270 elem->flags |= RPR_ELEM_ABSORBABLE_BRANCH; 7521a30Row pattern recognition patch (planner).
1759 - } 7521a30Row pattern recognition patch (planner).
1760 - else 7521a30Row pattern recognition patch (planner).
1761 - { 7521a30Row pattern recognition patch (planner).
1762 1625 computeAbsorbabilityRecursive(pattern, elem->next, hasAbsorbable); 7521a30Row pattern recognition patch (planner).
1763 - 7521a30Row pattern recognition patch (planner).
1764 - /* Mark BEGIN element if contents are absorbable */ 7521a30Row pattern recognition patch (planner).
1765 1625 if (*hasAbsorbable) 7521a30Row pattern recognition patch (planner).
1766 35 elem->flags |= RPR_ELEM_ABSORBABLE_BRANCH; 7521a30Row pattern recognition patch (planner).
1767 - } 7521a30Row pattern recognition patch (planner).
1768 - } 7521a30Row pattern recognition patch (planner).
1769 - else 7521a30Row pattern recognition patch (planner).
1770 - { 7521a30Row pattern recognition patch (planner).
1771 - /* Should never reach END - structural invariant of pattern parse tree */ 9c7e5bcImprove comments, documentation, and naming for row pattern recognition
1772 3215 Assert(!RPRElemIsEnd(elem)); 7521a30Row pattern recognition patch (planner).
1773 - 7521a30Row pattern recognition patch (planner).
1774 - /* Non-ALT, non-BEGIN: check if unbounded start */ 7521a30Row pattern recognition patch (planner).
1775 3215 if (isUnboundedStart(pattern, startIdx)) 7521a30Row pattern recognition patch (planner).
1776 - { 7521a30Row pattern recognition patch (planner).
1777 1170 *hasAbsorbable = true; 7521a30Row pattern recognition patch (planner).
1778 - } 7521a30Row pattern recognition patch (planner).
1779 - } 7521a30Row pattern recognition patch (planner).
1780 5620 } 7521a30Row pattern recognition patch (planner).
computeAbsorbability() lines 1812-1822
Modified Lines Coverage: 6/6 lines (100.0%)
LineHitsSourceCommit
1812 2875 computeAbsorbability(RPRPattern *pattern) 7521a30Row pattern recognition patch (planner).
1813 - { 7521a30Row pattern recognition patch (planner).
1814 2875 bool hasAbsorbable = false; 7521a30Row pattern recognition patch (planner).
1815 - 7521a30Row pattern recognition patch (planner).
1816 - /* Parser always produces at least one element + FIN */ 7521a30Row pattern recognition patch (planner).
1817 2875 Assert(pattern->numElements >= 2); 7521a30Row pattern recognition patch (planner).
1818 - 7521a30Row pattern recognition patch (planner).
1819 - /* Start recursion from first element */ 7521a30Row pattern recognition patch (planner).
1820 2875 computeAbsorbabilityRecursive(pattern, 0, &hasAbsorbable); 7521a30Row pattern recognition patch (planner).
1821 2875 pattern->isAbsorbable = hasAbsorbable; 7521a30Row pattern recognition patch (planner).
1822 2875 } 7521a30Row pattern recognition patch (planner).
rpr_volatile_func_checker() lines 1829-1832
Modified Lines Coverage: 2/2 lines (100.0%)
LineHitsSourceCommit
1829 11054 rpr_volatile_func_checker(Oid funcid, void *context) 7521a30Row pattern recognition patch (planner).
1830 - { 7521a30Row pattern recognition patch (planner).
1831 11054 return (func_volatile(funcid) == PROVOLATILE_VOLATILE); 7521a30Row pattern recognition patch (planner).
1832 - } 7521a30Row pattern recognition patch (planner).
rpr_define_errposition() lines 1843-1848
Modified Lines Coverage: 3/3 lines (100.0%)
LineHitsSourceCommit
1843 24 rpr_define_errposition(int location) 7521a30Row pattern recognition patch (planner).
1844 - { 7521a30Row pattern recognition patch (planner).
1845 24 if (location < 0 || debug_query_string == NULL) 7521a30Row pattern recognition patch (planner).
1846 - return 0; 7521a30Row pattern recognition patch (planner).
1847 20 return errposition(pg_mbstrlen_with_len(debug_query_string, location) + 1); 7521a30Row pattern recognition patch (planner).
1848 - } 7521a30Row pattern recognition patch (planner).
reject_volatile_in_define_walker() lines 1861-1876
Modified Lines Coverage: 6/7 lines (85.7%)
LineHitsSourceCommit
1861 35927 reject_volatile_in_define_walker(Node *node, void *context) 7521a30Row pattern recognition patch (planner).
1862 - { 7521a30Row pattern recognition patch (planner).
1863 35927 if (node == NULL) 7521a30Row pattern recognition patch (planner).
1864 - return false; 7521a30Row pattern recognition patch (planner).
1865 35842 if (check_functions_in_node(node, rpr_volatile_func_checker, NULL)) 7521a30Row pattern recognition patch (planner).
1866 24 ereport(ERROR, 7521a30Row pattern recognition patch (planner).
1867 - errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 7521a30Row pattern recognition patch (planner).
1868 - errmsg("volatile functions are not allowed in DEFINE clause"), 7521a30Row pattern recognition patch (planner).
1869 - rpr_define_errposition(exprLocation(node))); 7521a30Row pattern recognition patch (planner).
1870 35818 if (IsA(node, NextValueExpr)) 7521a30Row pattern recognition patch (planner).
1871 0 ereport(ERROR, 7521a30Row pattern recognition patch (planner).
UnreachableDefensive (unreachable) · confidence high · reject_volatile_in_define_walker @1871
Reason
CONFIRMED unreachable via any SQL input.
Line 1871 (the IsA(node, NextValueExpr) -> ereport sequence-operations error) cannot fire from user SQL.
NextValueExpr nodes are synthesized ONLY by build_column_default (rewriteHandler.c:1290 for identity columns;
also tablecmds.c:7566 for ALTER TABLE column rewrites), and that output is only ever spliced into INSERT/UPDATE/COPY target-column DEFAULT positions (rewriteHandler.c:1052,1599,4745).
There is no SQL syntax that embeds a column-default/identity expression into a scalar predicate position such as a window
DEFINE condition (the DEFAULT keyword is valid only in INSERT
VALUES / UPDATE
SET targets).
A user-written nextval('seq') inside
DEFINE parses to a volatile FuncExpr (pg_proc.dat: nextval provolatile='v'), which check_functions_in_node detects, so it is rejected earlier at line 1865 with the volatile-functions error before reaching 1870-1871. Verified that check_functions_in_node deliberately ignores NextValueExpr (nodeFuncs.c:1941 comment: it carries no SQL function OID), which is exactly why the separate IsA guard exists as belt-and-suspenders.
No rewrite/view-expansion/rule path can inject a NextValueExpr into wc->defineClause, which is what validate_rpr_define_volatility (planner.c:1062) walks.
I attempted to refute the classification and could not find any reaching input.
Recommended fix
No source change required.
Keep the IsA(node, NextValueExpr) guard at 1870-1874 as intentional defensive code: it documents that sequence operations are disallowed in
DEFINE and guards against any future path that could embed a NextValueExpr (which check_functions_in_node intentionally does not inspect).
Optionally annotate the line with a brief comment noting it is currently unreachable from SQL because user nextval() parses to a volatile FuncExpr caught at line 1865, so coverage tooling can be told to ignore it.
1872 - errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 7521a30Row pattern recognition patch (planner).
1873 - errmsg("sequence operations are not allowed in DEFINE clause"), 7521a30Row pattern recognition patch (planner).
1874 - rpr_define_errposition(exprLocation(node))); 7521a30Row pattern recognition patch (planner).
1875 35818 return expression_tree_walker(node, reject_volatile_in_define_walker, context); 7521a30Row pattern recognition patch (planner).
1876 - } 7521a30Row pattern recognition patch (planner).
validate_rpr_define_volatility() lines 1888-1894
Modified Lines Coverage: 4/4 lines (100.0%)
LineHitsSourceCommit
1888 3753 validate_rpr_define_volatility(List *defineClause) 7521a30Row pattern recognition patch (planner).
1889 - { 7521a30Row pattern recognition patch (planner).
1890 12412 foreach_node(TargetEntry, te, defineClause) 4cf9108Further tidy up row pattern recognition plumbing
1891 - { 7521a30Row pattern recognition patch (planner).
1892 8683 (void) reject_volatile_in_define_walker((Node *) te->expr, NULL); 7521a30Row pattern recognition patch (planner).
1893 - } 7521a30Row pattern recognition patch (planner).
1894 3729 } 7521a30Row pattern recognition patch (planner).
buildRPRPattern() lines 1911-1974
Modified Lines Coverage: 21/21 lines (100.0%)
LineHitsSourceCommit
1911 3729 buildRPRPattern(RPRPatternNode *pattern, List *defineVariableList, 7521a30Row pattern recognition patch (planner).
1912 - RPSkipTo rpSkipTo, int frameOptions, 7521a30Row pattern recognition patch (planner).
1913 - bool hasMatchStartDependent) 7521a30Row pattern recognition patch (planner).
1914 - { 7521a30Row pattern recognition patch (planner).
1915 3729 RPRPattern *result; 7521a30Row pattern recognition patch (planner).
1916 3729 RPRPatternNode *optimized; 7521a30Row pattern recognition patch (planner).
1917 3729 char *varNamesStack[RPR_VARID_MAX + 1]; 7521a30Row pattern recognition patch (planner).
1918 3729 int numVars; 7521a30Row pattern recognition patch (planner).
1919 3729 int numElements; 7521a30Row pattern recognition patch (planner).
1920 3729 RPRDepth maxDepth; 7521a30Row pattern recognition patch (planner).
1921 3729 int idx; 7521a30Row pattern recognition patch (planner).
1922 - 7521a30Row pattern recognition patch (planner).
1923 - /* Caller must check for NULL pattern before calling */ 7521a30Row pattern recognition patch (planner).
1924 3729 Assert(pattern != NULL); 7521a30Row pattern recognition patch (planner).
1925 - /* RPR is ROWS-only: transformRPR() rejects RANGE/GROUPS up front */ 7521a30Row pattern recognition patch (planner).
1926 3729 Assert(frameOptions & FRAMEOPTION_ROWS); 7521a30Row pattern recognition patch (planner).
1927 - 7521a30Row pattern recognition patch (planner).
1928 - /* Optimize the pattern tree */ 7521a30Row pattern recognition patch (planner).
1929 3729 optimized = optimizeRPRPattern(copyObject(pattern)); 7521a30Row pattern recognition patch (planner).
1930 - 7521a30Row pattern recognition patch (planner).
1931 - /* Collect variable names from DEFINE clause */ 7521a30Row pattern recognition patch (planner).
1932 3729 numVars = collectDefineVariables(defineVariableList, varNamesStack); 7521a30Row pattern recognition patch (planner).
1933 - 7521a30Row pattern recognition patch (planner).
1934 - /* Scan pattern: collect variables, count elements, validate limits */ 7521a30Row pattern recognition patch (planner).
1935 3729 scanRPRPattern(optimized, varNamesStack, &numVars, &numElements, &maxDepth); 7521a30Row pattern recognition patch (planner).
1936 - 7521a30Row pattern recognition patch (planner).
1937 - /* Allocate result structure */ 7521a30Row pattern recognition patch (planner).
1938 3725 result = makeRPRPattern(numVars, numElements, maxDepth, varNamesStack); 7521a30Row pattern recognition patch (planner).
1939 - 7521a30Row pattern recognition patch (planner).
1940 - /* Fill elements (pass 2) */ 7521a30Row pattern recognition patch (planner).
1941 3725 idx = 0; 7521a30Row pattern recognition patch (planner).
1942 3725 fillRPRPattern(optimized, result, &idx, 0); 7521a30Row pattern recognition patch (planner).
1943 - 7521a30Row pattern recognition patch (planner).
1944 - /* Finalize: set up next pointers, flags, and add FIN marker */ 7521a30Row pattern recognition patch (planner).
1945 3725 finalizeRPRPattern(result); 7521a30Row pattern recognition patch (planner).
1946 - 7521a30Row pattern recognition patch (planner).
1947 - /* 7521a30Row pattern recognition patch (planner).
1948 - * Compute context absorption eligibility. Absorption requires both 7521a30Row pattern recognition patch (planner).
1949 - * structural absorbability and runtime conditions. Check runtime 7521a30Row pattern recognition patch (planner).
1950 - * conditions first to avoid unnecessary pattern analysis. 7521a30Row pattern recognition patch (planner).
1951 - * 7521a30Row pattern recognition patch (planner).
1952 - * Runtime conditions for absorption: 7521a30Row pattern recognition patch (planner).
1953 - * 7521a30Row pattern recognition patch (planner).
1954 - * 1. SKIP TO PAST LAST ROW required (not SKIP TO NEXT ROW): With NEXT 7521a30Row pattern recognition patch (planner).
1955 - * ROW, after each match the search resumes from the next row, so contexts 7521a30Row pattern recognition patch (planner).
1956 - * are immediately discarded. No redundant contexts accumulate, making 7521a30Row pattern recognition patch (planner).
1957 - * absorption unnecessary. 7521a30Row pattern recognition patch (planner).
1958 - * 7521a30Row pattern recognition patch (planner).
1959 - * 2. Unbounded frame end required (not ROWS with bounded end): With a 7521a30Row pattern recognition patch (planner).
1960 - * bounded frame (e.g., ROWS BETWEEN CURRENT ROW AND 10 FOLLOWING), 7521a30Row pattern recognition patch (planner).
1961 - * matches may be truncated at frame boundaries. This changes the 7521a30Row pattern recognition patch (planner).
1962 - * absorption semantics - older contexts don't necessarily produce longer 7521a30Row pattern recognition patch (planner).
1963 - * matches when frame limits apply differently to each context. 7521a30Row pattern recognition patch (planner).
1964 - */ 7521a30Row pattern recognition patch (planner).
1965 3725 if (rpSkipTo == ST_PAST_LAST_ROW && 7521a30Row pattern recognition patch (planner).
1966 3115 (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) && 7521a30Row pattern recognition patch (planner).
1967 - !hasMatchStartDependent) 7521a30Row pattern recognition patch (planner).
1968 - { 7521a30Row pattern recognition patch (planner).
1969 - /* Runtime conditions met - check structural absorbability */ 7521a30Row pattern recognition patch (planner).
1970 2875 computeAbsorbability(result); 7521a30Row pattern recognition patch (planner).
1971 - } 7521a30Row pattern recognition patch (planner).
1972 - 7521a30Row pattern recognition patch (planner).
1973 3725 return result; 7521a30Row pattern recognition patch (planner).
1974 - } 7521a30Row pattern recognition patch (planner).
nav_traversal_walker() lines 1993-2007
Modified Lines Coverage: 7/7 lines (100.0%)
LineHitsSourceCommit
1993 31542 nav_traversal_walker(Node *node, void *ctx) 7521a30Row pattern recognition patch (planner).
1994 - { 7521a30Row pattern recognition patch (planner).
1995 31542 if (node == NULL) 7521a30Row pattern recognition patch (planner).
1996 - return false; 7521a30Row pattern recognition patch (planner).
1997 - 7521a30Row pattern recognition patch (planner).
1998 31457 if (IsA(node, RPRNavExpr)) 7521a30Row pattern recognition patch (planner).
1999 - { 7521a30Row pattern recognition patch (planner).
2000 1299 NavTraversal *t = (NavTraversal *) ctx; 7521a30Row pattern recognition patch (planner).
2001 - 7521a30Row pattern recognition patch (planner).
2002 1299 t->visit(t, (RPRNavExpr *) node); 7521a30Row pattern recognition patch (planner).
2003 1299 return false; 7521a30Row pattern recognition patch (planner).
2004 - } 7521a30Row pattern recognition patch (planner).
2005 - 7521a30Row pattern recognition patch (planner).
2006 30158 return expression_tree_walker(node, nav_traversal_walker, ctx); 7521a30Row pattern recognition patch (planner).
2007 - } 7521a30Row pattern recognition patch (planner).