validate a CALL {} (subquery) clause
| 1252 | |
| 1253 | // validate a CALL {} (subquery) clause |
| 1254 | static VISITOR_STRATEGY _Validate_call_subquery |
| 1255 | ( |
| 1256 | const cypher_astnode_t *n, // ast-node |
| 1257 | bool start, // first traversal |
| 1258 | ast_visitor *visitor // visitor |
| 1259 | ) { |
| 1260 | validations_ctx *vctx = AST_Visitor_GetContext(visitor); |
| 1261 | |
| 1262 | vctx->clause = cypher_astnode_type(n); |
| 1263 | |
| 1264 | // create a query astnode with the body of the subquery as its body |
| 1265 | cypher_astnode_t *body = cypher_ast_call_subquery_get_query(n); |
| 1266 | uint nclauses = cypher_ast_query_nclauses(body); |
| 1267 | |
| 1268 | // clone the bound vars context. |
| 1269 | rax *in_env = raxClone(vctx->defined_identifiers); |
| 1270 | |
| 1271 | // if there are no imports, set the env of bound-vars to the empty env |
| 1272 | const cypher_astnode_t *first_clause = cypher_ast_query_get_clause(body, 0); |
| 1273 | if(cypher_astnode_type(first_clause) != |
| 1274 | CYPHER_AST_WITH) { |
| 1275 | raxFree(vctx->defined_identifiers); |
| 1276 | vctx->defined_identifiers = raxNew(); |
| 1277 | } else { |
| 1278 | // validate that the with imports (if exist) are simple, i.e., 'WITH a' |
| 1279 | if(!_ValidateCallInitialWith(first_clause, vctx)) { |
| 1280 | raxFree(in_env); |
| 1281 | ErrorCtx_SetError( |
| 1282 | "WITH imports in CALL {} must consist of only simple references\ |
| 1283 | to outside variables"); |
| 1284 | return VISITOR_BREAK; |
| 1285 | } |
| 1286 | } |
| 1287 | |
| 1288 | // visit the subquery clauses |
| 1289 | bool last_is_union = false; |
| 1290 | for(uint i = 0; i < nclauses; i++) { |
| 1291 | const cypher_astnode_t *clause = |
| 1292 | cypher_ast_query_get_clause(body, i); |
| 1293 | cypher_astnode_type_t type = cypher_astnode_type(clause); |
| 1294 | |
| 1295 | // if the current clause is a `UNION` clause, it has reset the bound |
| 1296 | // vars env to the empty env. We compensate for that in case there is no |
| 1297 | // initial `WITH` clause |
| 1298 | if(last_is_union && type == CYPHER_AST_WITH) { |
| 1299 | // set the env of bound-vars to the input env |
| 1300 | raxFree(vctx->defined_identifiers); |
| 1301 | vctx->defined_identifiers = raxClone(in_env); |
| 1302 | |
| 1303 | // validate that the with imports (if exist) are simple, i.e., |
| 1304 | // 'WITH a' |
| 1305 | if(!_ValidateCallInitialWith(clause, vctx)) { |
| 1306 | raxFree(in_env); |
| 1307 | ErrorCtx_SetError( |
| 1308 | "WITH imports in CALL {} must consist of only simple \ |
| 1309 | references to outside variables"); |
| 1310 | return VISITOR_BREAK; |
| 1311 | } |
nothing calls this directly
no test coverage detected