| 58 | } |
| 59 | |
| 60 | static void _UseIdOptimization(ExecutionPlan *plan, OpBase *scan_op) { |
| 61 | /* See if there's a filter of the form |
| 62 | * ID(n) op X |
| 63 | * where X is a constant and op in [EQ, GE, LE, GT, LT] */ |
| 64 | OpBase *parent = scan_op->parent; |
| 65 | OpBase *grandparent; |
| 66 | UnsignedRange *id_range = NULL; |
| 67 | while(parent && parent->type == OPType_FILTER) { |
| 68 | grandparent = parent->parent; // Track the next op to visit in case we free parent. |
| 69 | OpFilter *filter = (OpFilter *)parent; |
| 70 | FT_FilterNode *f = filter->filterTree; |
| 71 | |
| 72 | AST_Operator op; |
| 73 | EntityID id; |
| 74 | bool reverse; |
| 75 | if(_idFilter(f, &op, &id, &reverse)) { |
| 76 | if(!id_range) id_range = UnsignedRange_New(); |
| 77 | if(reverse) op = ArithmeticOp_ReverseOp(op); |
| 78 | UnsignedRange_TightenRange(id_range, op, id); |
| 79 | |
| 80 | // Free replaced operations. |
| 81 | ExecutionPlan_RemoveOp(plan, (OpBase *)filter); |
| 82 | OpBase_Free((OpBase *)filter); |
| 83 | } |
| 84 | // Advance. |
| 85 | parent = grandparent; |
| 86 | } |
| 87 | if(id_range) { |
| 88 | /* Don't replace label scan, but set it to have range query. |
| 89 | * Issue 818 https://github.com/RedisGraph/RedisGraph/issues/818 |
| 90 | * This optimization caused a range query over the entire range of ids in the graph |
| 91 | * regardless to the label. */ |
| 92 | if(scan_op->type == OPType_NODE_BY_LABEL_SCAN) { |
| 93 | NodeByLabelScan *label_scan = (NodeByLabelScan *) scan_op; |
| 94 | NodeByLabelScanOp_SetIDRange(label_scan, id_range); |
| 95 | } else { |
| 96 | const char *alias = ((AllNodeScan *)scan_op)->alias; |
| 97 | OpBase *opNodeByIdSeek = NewNodeByIdSeekOp(scan_op->plan, alias, id_range); |
| 98 | |
| 99 | // Managed to reduce! |
| 100 | ExecutionPlan_ReplaceOp(plan, scan_op, opNodeByIdSeek); |
| 101 | OpBase_Free(scan_op); |
| 102 | } |
| 103 | UnsignedRange_Free(id_range); |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | void seekByID(ExecutionPlan *plan) { |
| 108 | ASSERT(plan != NULL); |
no test coverage detected