rewrites the projections of a Call {} clause, such that bound vars will remain in the record when passed to the CallSubquery op
| 363 | // rewrites the projections of a Call {} clause, such that bound vars will |
| 364 | // remain in the record when passed to the CallSubquery op |
| 365 | static void _rewrite_projections |
| 366 | ( |
| 367 | cypher_astnode_t *wrapping_clause, // outer-context clause (query/call {}) |
| 368 | uint clause_ind, // index of call {} clause in query |
| 369 | uint start, // start ind of outer-scope bound vars |
| 370 | char ***inter_names // internal representation of bound vars |
| 371 | ) { |
| 372 | //-------------------------------------------------------------------------- |
| 373 | // collect outer scope bound vars |
| 374 | //-------------------------------------------------------------------------- |
| 375 | |
| 376 | rax *outer_mapping = raxNew(); |
| 377 | if(start != clause_ind) { |
| 378 | collect_aliases_in_scope(wrapping_clause, start, clause_ind, |
| 379 | outer_mapping); |
| 380 | } |
| 381 | |
| 382 | uint mapping_size = raxSize(outer_mapping); |
| 383 | if(mapping_size == 0 && array_len(*inter_names) == 0) { |
| 384 | raxFree(outer_mapping); |
| 385 | return; |
| 386 | } |
| 387 | |
| 388 | // create an array for the outer scope bound vars |
| 389 | char **names = array_new(char *, mapping_size); |
| 390 | |
| 391 | _get_vars_inner_rep(outer_mapping, &names, inter_names); |
| 392 | raxFree(outer_mapping); |
| 393 | |
| 394 | //-------------------------------------------------------------------------- |
| 395 | // transform relevant clauses |
| 396 | //-------------------------------------------------------------------------- |
| 397 | |
| 398 | // if there is a UNION clause in the subquery, each branch must be handled |
| 399 | cypher_astnode_t *clause = (cypher_astnode_t *) |
| 400 | cypher_ast_query_get_clause(wrapping_clause, clause_ind); |
| 401 | cypher_astnode_t *subquery = cypher_ast_call_subquery_get_query(clause); |
| 402 | AST ast = {0}; |
| 403 | ast.root = subquery; |
| 404 | uint *union_indices = AST_GetClauseIndices(&ast, CYPHER_AST_UNION); |
| 405 | uint clause_count = cypher_ast_query_nclauses(subquery); |
| 406 | array_append(union_indices, clause_count); |
| 407 | uint n_union_branches = array_len(union_indices); |
| 408 | |
| 409 | uint first_ind = 0; |
| 410 | for(uint i = 0; i < n_union_branches; i++) { |
| 411 | uint last_ind = union_indices[i]; |
| 412 | |
| 413 | // check if first clause is a WITH clause |
| 414 | const cypher_astnode_t *first_clause = |
| 415 | cypher_ast_query_get_clause(subquery, first_ind); |
| 416 | if(cypher_astnode_type(first_clause) == CYPHER_AST_WITH) { |
| 417 | // replace first clause (WITH) with a WITH clause containing |
| 418 | // "n->@n" projections for all bound vars in outer-scope context |
| 419 | _replace_with_clause(clause, first_ind, names, *inter_names); |
| 420 | } else { |
| 421 | // add a leading WITH clause containing "n->@n" projections |
| 422 | // for all bound vars (in outer-scope context) |
no test coverage detected