MCPcopy Create free account
hub / github.com/RedisGraph/RedisGraph / _ValidateQueryTermination

Function _ValidateQueryTermination

src/ast/ast_validations.c:1812–1884  ·  view source on GitHub ↗

A query must end in a RETURN clause, a procedure, or an updating clause (CREATE, MERGE, DELETE, SET, REMOVE, FOREACH or CALL {})

Source from the content-addressed store, hash-verified

1810// A query must end in a RETURN clause, a procedure, or an updating clause
1811// (CREATE, MERGE, DELETE, SET, REMOVE, FOREACH or CALL {})
1812static AST_Validation _ValidateQueryTermination
1813(
1814 const AST *ast // ast
1815) {
1816 ASSERT(ast != NULL);
1817
1818 const cypher_astnode_t *root = ast->root;
1819 uint clause_idx = 0;
1820 const cypher_astnode_t *return_clause = NULL;
1821 const cypher_astnode_t *following_clause = NULL;
1822 uint clause_count = cypher_ast_query_nclauses(root);
1823
1824 const cypher_astnode_t *last_clause = cypher_ast_query_get_clause(root,
1825 clause_count - 1);
1826 cypher_astnode_type_t type = cypher_astnode_type(last_clause);
1827 if(type != CYPHER_AST_RETURN &&
1828 type != CYPHER_AST_CREATE &&
1829 type != CYPHER_AST_MERGE &&
1830 type != CYPHER_AST_DELETE &&
1831 type != CYPHER_AST_SET &&
1832 type != CYPHER_AST_CALL &&
1833 type != CYPHER_AST_CALL_SUBQUERY &&
1834 type != CYPHER_AST_REMOVE &&
1835 type != CYPHER_AST_FOREACH
1836 ) {
1837 ErrorCtx_SetError("Query cannot conclude with %s (must be a RETURN \
1838clause, an update clause, a procedure call or a non-returning subquery)",
1839 cypher_astnode_typestr(type));
1840 return AST_INVALID;
1841 }
1842
1843 // if the last clause is CALL {}, it must be non-returning
1844 if(type == CYPHER_AST_CALL_SUBQUERY) {
1845 cypher_astnode_t *query =
1846 cypher_ast_call_subquery_get_query(last_clause);
1847 if(cypher_astnode_type(cypher_ast_query_get_clause(query,
1848 cypher_ast_query_nclauses(query)-1)) ==
1849 CYPHER_AST_RETURN) {
1850 ErrorCtx_SetError("A query cannot conclude with a returning \
1851subquery (must be a RETURN clause, an update clause, a procedure call or a \
1852non-returning subquery)");
1853
1854 return AST_INVALID;
1855 }
1856 }
1857
1858 // validate that `UNION` is the only clause following a `RETURN` clause, and
1859 // termination of embedded call {} clauses
1860 bool last_was_return = false;
1861 for(uint i = 0; i < clause_count; i++) {
1862 const cypher_astnode_t *clause = cypher_ast_query_get_clause(root, i);
1863 cypher_astnode_type_t type = cypher_astnode_type(clause);
1864 if(type != CYPHER_AST_UNION && last_was_return) {
1865 // unexpected clause following RETURN
1866 ErrorCtx_SetError("Unexpected clause following RETURN");
1867 return AST_INVALID;
1868 } else if(type == CYPHER_AST_RETURN) {
1869 last_was_return = true;

Callers 1

_ValidateQuerySequenceFunction · 0.85

Calls 1

ErrorCtx_SetErrorFunction · 0.85

Tested by

no test coverage detected