validate a FOREACH clause MATCH (n) FOREACH(x in [1,2,3] | CREATE (n)-[:R]->({v:x}))
| 1629 | // validate a FOREACH clause |
| 1630 | // MATCH (n) FOREACH(x in [1,2,3] | CREATE (n)-[:R]->({v:x})) |
| 1631 | static VISITOR_STRATEGY _Validate_FOREACH_Clause |
| 1632 | ( |
| 1633 | const cypher_astnode_t *n, // ast-node |
| 1634 | bool start, // first traversal |
| 1635 | ast_visitor *visitor // visitor |
| 1636 | ) { |
| 1637 | validations_ctx *vctx = visitor->ctx; |
| 1638 | |
| 1639 | // we enter ONLY when start=true, so no check is needed |
| 1640 | |
| 1641 | // build a new environment of bounded vars from the current one to be |
| 1642 | // used in the traversal of the visitor in the clauses of the FOREACH |
| 1643 | // clause - as they are local to the FOREACH clause |
| 1644 | rax *orig_env = vctx->defined_identifiers; |
| 1645 | rax *scoped_env = raxClone(orig_env); |
| 1646 | vctx->defined_identifiers = scoped_env; |
| 1647 | |
| 1648 | // set the clause of the context |
| 1649 | vctx->clause = CYPHER_AST_FOREACH; |
| 1650 | |
| 1651 | // visit FOREACH array expression |
| 1652 | const cypher_astnode_t *list_node = |
| 1653 | cypher_ast_foreach_get_expression(n); |
| 1654 | AST_Visitor_visit(list_node, visitor); |
| 1655 | |
| 1656 | // introduce loop variable to bound vars |
| 1657 | const cypher_astnode_t *identifier_node = |
| 1658 | cypher_ast_foreach_get_identifier(n); |
| 1659 | |
| 1660 | const char *identifier = |
| 1661 | cypher_ast_identifier_get_name(identifier_node); |
| 1662 | |
| 1663 | raxInsert(vctx->defined_identifiers, (unsigned char *) identifier, |
| 1664 | strlen(identifier), NULL, NULL); |
| 1665 | |
| 1666 | // visit FOREACH loop body clauses |
| 1667 | uint nclauses = cypher_ast_foreach_nclauses(n); |
| 1668 | for(uint i = 0; i < nclauses; i++) { |
| 1669 | const cypher_astnode_t *clause = cypher_ast_foreach_get_clause(n, i); |
| 1670 | // make sure it is an updating clause |
| 1671 | cypher_astnode_type_t child_clause_type = |
| 1672 | cypher_astnode_type(clause); |
| 1673 | if(child_clause_type != CYPHER_AST_CREATE && |
| 1674 | child_clause_type != CYPHER_AST_SET && |
| 1675 | child_clause_type != CYPHER_AST_REMOVE && |
| 1676 | child_clause_type != CYPHER_AST_MERGE && |
| 1677 | child_clause_type != CYPHER_AST_DELETE && |
| 1678 | child_clause_type != CYPHER_AST_FOREACH |
| 1679 | ) { |
| 1680 | ErrorCtx_SetError("Error: Only updating clauses may reside in FOREACH"); |
| 1681 | break; |
| 1682 | } |
| 1683 | |
| 1684 | // visit the clause |
| 1685 | AST_Visitor_visit(clause, visitor); |
| 1686 | } |
| 1687 | |
| 1688 | // restore original environment of bounded vars |
nothing calls this directly
no test coverage detected