| 250 | } |
| 251 | |
| 252 | NodeGroupScanResult NodeGroup::scanInternal(const UniqLock& lock, Transaction* transaction, |
| 253 | TableScanState& state, offset_t startOffsetInGroup, offset_t numRowsToScan) const { |
| 254 | // Only meant for scanning once |
| 255 | DASSERT(numRowsToScan <= DEFAULT_VECTOR_CAPACITY); |
| 256 | |
| 257 | auto startRowIdxInGroup = getStartRowIdxInGroupNoLock(); |
| 258 | if (startOffsetInGroup < startRowIdxInGroup) { |
| 259 | numRowsToScan = std::min(numRowsToScan, startRowIdxInGroup - startOffsetInGroup); |
| 260 | // If the scan starts before the first row in the group, skip the deleted part and return. |
| 261 | return NodeGroupScanResult{startOffsetInGroup, numRowsToScan}; |
| 262 | } |
| 263 | |
| 264 | auto& nodeGroupScanState = *state.nodeGroupScanState; |
| 265 | nodeGroupScanState.nextRowToScan = startOffsetInGroup; |
| 266 | |
| 267 | const auto newChunkedGroupIdx = findChunkedGroupIdxFromRowIdxNoLock(startOffsetInGroup).first; |
| 268 | DASSERT(newChunkedGroupIdx != INVALID_CHUNKED_GROUP_IDX); |
| 269 | |
| 270 | const auto* chunkedGroupToScan = chunkedGroups.getGroup(lock, newChunkedGroupIdx); |
| 271 | if (newChunkedGroupIdx != nodeGroupScanState.chunkedGroupIdx) { |
| 272 | // If the chunked group matches the scan state, don't re-initialize it. |
| 273 | // E.g., we may scan a group multiple times in parts |
| 274 | initializeScanStateForChunkedGroup(state, chunkedGroupToScan); |
| 275 | nodeGroupScanState.chunkedGroupIdx = newChunkedGroupIdx; |
| 276 | } |
| 277 | |
| 278 | uint64_t numRowsScanned = 0; |
| 279 | const auto rowIdxInChunkToScan = |
| 280 | (startOffsetInGroup + numRowsScanned) - chunkedGroupToScan->getStartRowIdx(); |
| 281 | uint64_t numRowsToScanInChunk = std::min(numRowsToScan - numRowsScanned, |
| 282 | chunkedGroupToScan->getNumRows() - rowIdxInChunkToScan); |
| 283 | DASSERT(startOffsetInGroup + numRowsToScanInChunk <= numRows); |
| 284 | chunkedGroupToScan->scan(transaction, state, nodeGroupScanState, rowIdxInChunkToScan, |
| 285 | numRowsToScanInChunk); |
| 286 | numRowsScanned += numRowsToScanInChunk; |
| 287 | nodeGroupScanState.nextRowToScan += numRowsToScanInChunk; |
| 288 | |
| 289 | return NodeGroupScanResult{startOffsetInGroup, numRowsScanned}; |
| 290 | } |
| 291 | |
| 292 | bool NodeGroup::lookupNoLock(const Transaction* transaction, const TableScanState& state, |
| 293 | sel_t posInSel) const { |
nothing calls this directly
no test coverage detected