| 560 | } |
| 561 | |
| 562 | std::shared_ptr<NodeExpression> Binder::bindQueryNode(const NodePattern& nodePattern, |
| 563 | QueryGraph& queryGraph) { |
| 564 | auto parsedName = nodePattern.getVariableName(); |
| 565 | std::shared_ptr<NodeExpression> queryNode; |
| 566 | if (scope.contains(parsedName)) { // bind to node in scope |
| 567 | auto prevVariable = scope.getExpression(parsedName); |
| 568 | if (!ExpressionUtil::isNodePattern(*prevVariable)) { |
| 569 | if (!scope.hasNodeReplacement(parsedName)) { |
| 570 | throw BinderException(std::format("Cannot bind {} as node pattern.", parsedName)); |
| 571 | } |
| 572 | queryNode = scope.getNodeReplacement(parsedName); |
| 573 | queryNode->addPropertyDataExpr(InternalKeyword::ID, queryNode->getInternalID()); |
| 574 | } else { |
| 575 | queryNode = std::static_pointer_cast<NodeExpression>(prevVariable); |
| 576 | // E.g. MATCH (a:person) MATCH (a:organisation) |
| 577 | // We bind to a single node with both labels |
| 578 | if (!nodePattern.getTableNames().empty()) { |
| 579 | auto otherNodeEntries = bindNodeTableEntries(nodePattern.getTableNames()); |
| 580 | queryNode->addEntries(otherNodeEntries.first); |
| 581 | } |
| 582 | } |
| 583 | } else { |
| 584 | queryNode = createQueryNode(nodePattern); |
| 585 | if (!parsedName.empty()) { |
| 586 | addToScope(parsedName, queryNode); |
| 587 | } |
| 588 | } |
| 589 | for (auto& [propertyName, rhs] : nodePattern.getPropertyKeyVals()) { |
| 590 | auto boundLhs = expressionBinder.bindNodeOrRelPropertyExpression(*queryNode, propertyName); |
| 591 | auto boundRhs = expressionBinder.bindExpression(*rhs); |
| 592 | // For ANY graphs, properties are stored as JSON in the data column |
| 593 | // Skip forceCast for ANY type as it cannot be cast to |
| 594 | if (boundLhs->dataType.getLogicalTypeID() != LogicalTypeID::ANY) { |
| 595 | boundRhs = expressionBinder.forceCast(boundRhs, boundLhs->dataType); |
| 596 | } |
| 597 | queryNode->addPropertyDataExpr(propertyName, std::move(boundRhs)); |
| 598 | } |
| 599 | queryGraph.addQueryNode(queryNode); |
| 600 | return queryNode; |
| 601 | } |
| 602 | |
| 603 | std::shared_ptr<NodeExpression> Binder::createQueryNode(const NodePattern& nodePattern) { |
| 604 | auto parsedName = nodePattern.getVariableName(); |
nothing calls this directly
no test coverage detected