src/backend/optimizer/plan/rpr.c - Coverage Report

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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