| 243 | } |
| 244 | |
| 245 | void UpdateInfo::iterateScan(const Transaction* transaction, uint64_t startOffsetToScan, |
| 246 | uint64_t numRowsToScan, uint64_t startPosInOutput, |
| 247 | const iterate_read_from_row_func_t& readFromRowFunc) const { |
| 248 | if (!isSet()) { |
| 249 | return; |
| 250 | } |
| 251 | auto [startVectorIdx, startOffsetInVector] = |
| 252 | StorageUtils::getQuotientRemainder(startOffsetToScan, DEFAULT_VECTOR_CAPACITY); |
| 253 | auto [endVectorIdx, endOffsetInVector] = StorageUtils::getQuotientRemainder( |
| 254 | startOffsetToScan + numRowsToScan, DEFAULT_VECTOR_CAPACITY); |
| 255 | idx_t idx = startVectorIdx; |
| 256 | sel_t posInVector = startPosInOutput; |
| 257 | while (idx <= endVectorIdx) { |
| 258 | const auto startOffsetInclusively = idx == startVectorIdx ? startOffsetInVector : 0; |
| 259 | const auto endOffsetExclusively = |
| 260 | idx == endVectorIdx ? endOffsetInVector : DEFAULT_VECTOR_CAPACITY; |
| 261 | const auto numRowsInVector = endOffsetExclusively - startOffsetInclusively; |
| 262 | // We keep track of the rows that have been applied with updates from updateInfo. The update |
| 263 | // version chain is maintained with the newest version at the head and the oldest version at |
| 264 | // the tail. For each tuple, we iterate through the chain to merge the updates from latest |
| 265 | // visible version. If a row has been updated in the current vectorInfo, we should skip it |
| 266 | // in older versions. |
| 267 | std::bitset<DEFAULT_VECTOR_CAPACITY> rowsUpdated; |
| 268 | iterateVectorInfo(transaction, idx, [&](const VectorUpdateInfo& vecUpdateInfo) -> void { |
| 269 | if (vecUpdateInfo.numRowsUpdated == 0) { |
| 270 | return; |
| 271 | } |
| 272 | if (rowsUpdated.count() == numRowsInVector) { |
| 273 | // All rows in this vector have been updated with a newer visible version already. |
| 274 | return; |
| 275 | } |
| 276 | // TODO(Guodong): Ideally we should make sure vecUpdateInfo.rowsInVector is sorted to |
| 277 | // simplify the checks here. |
| 278 | for (auto i = 0u; i < vecUpdateInfo.numRowsUpdated; i++) { |
| 279 | if (vecUpdateInfo.rowsInVector[i] < startOffsetInclusively || |
| 280 | vecUpdateInfo.rowsInVector[i] >= endOffsetExclusively) { |
| 281 | // Continue if the row is out of the current scan range. |
| 282 | continue; |
| 283 | } |
| 284 | auto updatedRowIdx = vecUpdateInfo.rowsInVector[i] - startOffsetInclusively; |
| 285 | if (rowsUpdated[updatedRowIdx]) { |
| 286 | // Skip the rows that have been updated with a newer visible version already. |
| 287 | continue; |
| 288 | } |
| 289 | readFromRowFunc(vecUpdateInfo, i, posInVector + updatedRowIdx); |
| 290 | rowsUpdated[updatedRowIdx] = true; |
| 291 | } |
| 292 | }); |
| 293 | posInVector += numRowsInVector; |
| 294 | idx++; |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | } // namespace storage |
| 299 | } // namespace lbug |
no test coverage detected