| 438 | } |
| 439 | |
| 440 | void TableScan::preload(std::shared_ptr<connector::ConnectorSplit> split) { |
| 441 | // The AsyncSource returns a unique_ptr to the shared_ptr of the |
| 442 | // DataSource. The callback may outlive the Task, hence it captures |
| 443 | // a shared_ptr to it. This is required to keep memory pools live |
| 444 | // for the duration. The callback checks for task cancellation to |
| 445 | // avoid needless work. |
| 446 | split->dataSource = std::make_unique<AsyncSource<connector::DataSource>>( |
| 447 | [type = outputType_, |
| 448 | table = tableHandle_, |
| 449 | columns = columnHandles_, |
| 450 | connector = connector_, |
| 451 | ctx = operatorCtx_->createConnectorQueryCtx( |
| 452 | split->connectorId, |
| 453 | planNodeId(), |
| 454 | connectorPool_, |
| 455 | nullptr, |
| 456 | asyncThreadCtx_), |
| 457 | task = operatorCtx_->task(), |
| 458 | pendingDynamicFilters = pendingDynamicFilters_, |
| 459 | split]() -> std::unique_ptr<connector::DataSource> { |
| 460 | if (task->isCancelled()) { |
| 461 | return nullptr; |
| 462 | } |
| 463 | auto debugString = |
| 464 | fmt::format("Split {} Task {}", split->toString(), task->taskId()); |
| 465 | ExceptionContextSetter exceptionContext( |
| 466 | {[](BoltException::Type /*exceptionType*/, auto* debugString) { |
| 467 | return *static_cast<std::string*>(debugString); |
| 468 | }, |
| 469 | &debugString}); |
| 470 | |
| 471 | auto ptr = connector->createDataSource( |
| 472 | type, table, columns, ctx, task->queryCtx()->queryConfig()); |
| 473 | if (task->isCancelled()) { |
| 474 | return nullptr; |
| 475 | } |
| 476 | for (const auto& entry : pendingDynamicFilters) { |
| 477 | ptr->addDynamicFilter(entry.first, entry.second); |
| 478 | } |
| 479 | ptr->addSplit(split); |
| 480 | return ptr; |
| 481 | }, |
| 482 | true); |
| 483 | } |
| 484 | |
| 485 | void TableScan::checkPreload() { |
| 486 | auto executor = connector_->executor(); |
nothing calls this directly
no test coverage detected