| 27 | } |
| 28 | |
| 29 | static void _reduceScans(ExecutionPlan *plan, OpBase *scan) { |
| 30 | // Return early if the scan has no child operations. |
| 31 | if(scan->childCount == 0) return; |
| 32 | |
| 33 | // The scan operation should be operating on a single alias. |
| 34 | ASSERT(array_len(scan->modifies) == 1); |
| 35 | const char *scanned_alias = scan->modifies[0]; |
| 36 | |
| 37 | // Collect variables bound before this operation. |
| 38 | rax *bound_vars = raxNew(); |
| 39 | for(int i = 0; i < scan->childCount; i ++) { |
| 40 | ExecutionPlan_BoundVariables(scan->children[i], bound_vars, |
| 41 | scan->children[i]->plan); |
| 42 | } |
| 43 | |
| 44 | if(raxFind(bound_vars, (unsigned char *)scanned_alias, strlen(scanned_alias)) != raxNotFound) { |
| 45 | // If the alias the scan operates on is already bound, the scan operation is redundant. |
| 46 | if(scan->type == OPType_NODE_BY_LABEL_SCAN) { |
| 47 | // If we are performing a label scan, introduce a conditional traversal to filter by label. |
| 48 | OpBase *traverse = _LabelScanToConditionalTraverse((NodeByLabelScan *)scan); |
| 49 | ExecutionPlan_ReplaceOp(plan, scan, traverse); |
| 50 | } else { |
| 51 | // Remove the redundant scan op. |
| 52 | ExecutionPlan_RemoveOp(plan, scan); |
| 53 | } |
| 54 | OpBase_Free(scan); |
| 55 | } |
| 56 | raxFree(bound_vars); |
| 57 | } |
| 58 | |
| 59 | void reduceScans(ExecutionPlan *plan) { |
| 60 | // Collect all SCAN operations within the execution plan. |
no test coverage detected