(
deltaA: Index<K, V1>,
deltaB: Index<K, V2>,
results: MultiSet<any>,
)
| 139 | } |
| 140 | |
| 141 | private emitLeftOuterResults( |
| 142 | deltaA: Index<K, V1>, |
| 143 | deltaB: Index<K, V2>, |
| 144 | results: MultiSet<any>, |
| 145 | ): void { |
| 146 | // Emit unmatched left rows from deltaA |
| 147 | if (deltaA.size > 0) { |
| 148 | for (const [key, valueIterator] of deltaA.entriesIterators()) { |
| 149 | const currentMultiplicityB = |
| 150 | this.#indexB.getConsolidatedMultiplicity(key) |
| 151 | const deltaMultiplicityB = deltaB.getConsolidatedMultiplicity(key) |
| 152 | const finalMultiplicityB = currentMultiplicityB + deltaMultiplicityB |
| 153 | |
| 154 | if (finalMultiplicityB === 0) { |
| 155 | for (const [value, multiplicity] of valueIterator) { |
| 156 | if (multiplicity !== 0) { |
| 157 | results.add([key, [value, null]], multiplicity) |
| 158 | } |
| 159 | } |
| 160 | } |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | // Handle presence transitions from right side changes |
| 165 | if (deltaB.size > 0) { |
| 166 | for (const key of deltaB.getPresenceKeys()) { |
| 167 | const before = this.#indexB.getConsolidatedMultiplicity(key) |
| 168 | const deltaMult = deltaB.getConsolidatedMultiplicity(key) |
| 169 | if (deltaMult === 0) continue |
| 170 | const after = before + deltaMult |
| 171 | |
| 172 | // Skip transition handling if presence doesn't flip (both zero or both non-zero) |
| 173 | // Note: Index updates happen later regardless - we're only skipping null-extension emissions here |
| 174 | if ((before === 0) === (after === 0)) continue |
| 175 | |
| 176 | // Determine the type of transition: |
| 177 | // - 0 → non-zero: Right becomes non-empty, left rows transition from unmatched to matched |
| 178 | // → RETRACT previously emitted null-extended rows (emit with negative multiplicity) |
| 179 | // - non-zero → 0: Right becomes empty, left rows transition from matched to unmatched |
| 180 | // → EMIT new null-extended rows (emit with positive multiplicity) |
| 181 | const transitioningToMatched = before === 0 |
| 182 | |
| 183 | for (const [value, multiplicity] of this.#indexA.getIterator(key)) { |
| 184 | if (multiplicity !== 0) { |
| 185 | results.add( |
| 186 | [key, [value, null]], |
| 187 | transitioningToMatched ? -multiplicity : +multiplicity, |
| 188 | ) |
| 189 | } |
| 190 | } |
| 191 | } |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | private emitRightOuterResults( |
| 196 | deltaA: Index<K, V1>, |
no test coverage detected