* Recursively analyze a condition tree.
(condition: Condition, hints: IndexHint[])
| 78 | * Recursively analyze a condition tree. |
| 79 | */ |
| 80 | function analyzeConditionRecursive(condition: Condition, hints: IndexHint[]): void { |
| 81 | const [operator, ...args] = condition; |
| 82 | |
| 83 | switch (operator) { |
| 84 | case "and": |
| 85 | case "or": |
| 86 | case "xor": |
| 87 | // Recursively analyze sub-conditions |
| 88 | for (const subCondition of args as Condition[]) { |
| 89 | analyzeConditionRecursive(subCondition, hints); |
| 90 | } |
| 91 | break; |
| 92 | |
| 93 | case "not": |
| 94 | // NOT conditions generally can't use indexes efficiently |
| 95 | // (though NOT IN could potentially use hash index) |
| 96 | break; |
| 97 | |
| 98 | case "exists": |
| 99 | case "isNull": |
| 100 | case "isNotNull": |
| 101 | // Existence checks can't use value indexes |
| 102 | break; |
| 103 | |
| 104 | case "=": |
| 105 | case "<": |
| 106 | case "<=": |
| 107 | case ">": |
| 108 | case ">=": |
| 109 | case "startsWith": |
| 110 | case "contains": { |
| 111 | const [property, value] = args; |
| 112 | |
| 113 | // Skip special properties (@id, @label) |
| 114 | if (typeof property !== "string" || property.startsWith("@")) { |
| 115 | break; |
| 116 | } |
| 117 | |
| 118 | // Skip if value is a reference (not a literal) |
| 119 | if (value !== null && typeof value === "object" && "type" in value) { |
| 120 | break; |
| 121 | } |
| 122 | |
| 123 | const mapping = OPERATOR_TO_OPERATION[operator]; |
| 124 | if (mapping) { |
| 125 | for (const indexType of mapping.indexTypes) { |
| 126 | hints.push({ |
| 127 | type: indexType, |
| 128 | property, |
| 129 | operation: mapping.operation, |
| 130 | value, |
| 131 | condition, |
| 132 | }); |
| 133 | } |
| 134 | } |
| 135 | break; |
| 136 | } |
| 137 |
no test coverage detected