| 243 | } |
| 244 | |
| 245 | void RecursiveExtend::executeInternal(ExecutionContext* context) { |
| 246 | if (tryExecuteFunctionalChainFastPath(context, *function, bindData, sharedState.get())) { |
| 247 | return; |
| 248 | } |
| 249 | auto clientContext = context->clientContext; |
| 250 | auto transaction = transaction::Transaction::Get(*clientContext); |
| 251 | auto progressBar = ProgressBar::Get(*clientContext); |
| 252 | auto graph = sharedState->graph.get(); |
| 253 | auto inputNodeMaskMap = sharedState->getInputNodeMaskMap(); |
| 254 | offset_t totalNumNodes = 0; |
| 255 | if (inputNodeMaskMap != nullptr) { |
| 256 | totalNumNodes = inputNodeMaskMap->getNumMaskedNode(); |
| 257 | } else { |
| 258 | for (auto& tableID : graph->getNodeTableIDs()) { |
| 259 | auto nodeTable = storage::StorageManager::Get(*clientContext) |
| 260 | ->getTable(tableID) |
| 261 | ->ptrCast<storage::NodeTable>(); |
| 262 | auto maxOffset = graph->getMaxOffset(transaction, tableID); |
| 263 | for (auto offset = 0u; offset < maxOffset; ++offset) { |
| 264 | totalNumNodes += nodeTable->isVisible(transaction, offset); |
| 265 | } |
| 266 | } |
| 267 | } |
| 268 | std::vector<std::string> propertyNames; |
| 269 | if (requireRelID(*function)) { |
| 270 | propertyNames.push_back(InternalKeyword::ID); |
| 271 | } |
| 272 | if (bindData.weightPropertyExpr != nullptr) { |
| 273 | propertyNames.push_back( |
| 274 | bindData.weightPropertyExpr->ptrCast<PropertyExpression>()->getPropertyName()); |
| 275 | } |
| 276 | offset_t completedNumNodes = 0; |
| 277 | auto inputNodeTableIDSet = bindData.nodeInput->constCast<NodeExpression>().getTableIDsSet(); |
| 278 | for (auto& tableID : graph->getNodeTableIDs()) { |
| 279 | // Input node table IDs could be different from graph node table IDs, e.g. |
| 280 | // Given schema, student-knows->student, teacher-knows->teacher |
| 281 | // MATCH (a:student)-[e*knows]->(b:student) |
| 282 | // the graph node table IDs will include both student and teacher. |
| 283 | if (!inputNodeTableIDSet.contains(tableID)) { |
| 284 | continue; |
| 285 | } |
| 286 | auto calcFunc = [tableID, propertyNames, graph, context, this](offset_t offset) { |
| 287 | auto clientContext = context->clientContext; |
| 288 | auto computeState = function->getComputeState(context, bindData, sharedState.get()); |
| 289 | auto sourceNodeID = nodeID_t{offset, tableID}; |
| 290 | computeState->initSource(sourceNodeID); |
| 291 | GDSUtils::runRecursiveJoinEdgeCompute(context, *computeState, graph, |
| 292 | bindData.extendDirection, bindData.upperBound, sharedState->getOutputNodeMaskMap(), |
| 293 | propertyNames); |
| 294 | auto writer = function->getOutputWriter(context, bindData, *computeState, sourceNodeID, |
| 295 | sharedState.get()); |
| 296 | auto vertexCompute = std::make_unique<RJVertexCompute>( |
| 297 | storage::MemoryManager::Get(*clientContext), sharedState.get(), writer->copy(), |
| 298 | bindData.nodeOutput->constCast<NodeExpression>().getTableIDsSet()); |
| 299 | GDSUtils::runVertexCompute(context, computeState->frontierPair->getState(), graph, |
| 300 | *vertexCompute); |
| 301 | }; |
| 302 | auto maxOffset = graph->getMaxOffset(transaction, tableID); |
nothing calls this directly
no test coverage detected