compresses multiple consecutive MATCH clauses into a single MATCH clause
| 62 | |
| 63 | // compresses multiple consecutive MATCH clauses into a single MATCH clause |
| 64 | static void _replace_match_clause |
| 65 | ( |
| 66 | cypher_astnode_t *root, // ast root |
| 67 | cypher_astnode_t **clauses, // clause being replaced |
| 68 | int scope_start, // beginning of scope |
| 69 | int scope_end, // ending of scope |
| 70 | replace_func replace // replace function pointer |
| 71 | ) { |
| 72 | uint count = array_len(clauses); |
| 73 | |
| 74 | cypher_astnode_t *predicate = NULL; |
| 75 | struct cypher_input_range range = cypher_astnode_range(clauses[0]); |
| 76 | cypher_astnode_t **paths = array_new(cypher_astnode_t *, count); |
| 77 | |
| 78 | // collect MATCH patterns and predicates |
| 79 | for (uint i = 0; i < count; i++) { |
| 80 | const cypher_astnode_t *pattern = |
| 81 | cypher_ast_match_get_pattern(clauses[i]); |
| 82 | uint npaths = cypher_ast_pattern_npaths(pattern); |
| 83 | |
| 84 | for (uint j = 0; j < npaths; j++) { |
| 85 | const cypher_astnode_t *path = |
| 86 | cypher_ast_pattern_get_path(pattern, j); |
| 87 | array_append(paths, cypher_ast_clone(path)); |
| 88 | } |
| 89 | |
| 90 | // combine MATCH predicates into a single predicate using AND connectors |
| 91 | cypher_astnode_t *new_predicate = |
| 92 | (cypher_astnode_t *)cypher_ast_match_get_predicate(clauses[i]); |
| 93 | if(new_predicate != NULL) { |
| 94 | new_predicate = cypher_ast_clone(new_predicate); |
| 95 | if(predicate == NULL) { |
| 96 | predicate = new_predicate; |
| 97 | } else { |
| 98 | // concat using AND |
| 99 | cypher_astnode_t *children[] = {predicate, new_predicate}; |
| 100 | predicate = cypher_ast_binary_operator(CYPHER_OP_AND, predicate, |
| 101 | new_predicate, children, 2, range); |
| 102 | } |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | // build the replacement pattern |
| 107 | cypher_astnode_t *pattern = |
| 108 | cypher_ast_pattern(paths, array_len(paths), paths, array_len(paths), |
| 109 | range); |
| 110 | |
| 111 | // build the replacement clause |
| 112 | cypher_astnode_t *children[] = {pattern, predicate}; |
| 113 | cypher_astnode_t *new_clause = cypher_ast_match(false, pattern, NULL, 0, |
| 114 | predicate, children, predicate == NULL ? 1 : 2, range); |
| 115 | |
| 116 | // replace original clause with the new one |
| 117 | replace(root, new_clause, scope_start, scope_end); |
| 118 | |
| 119 | array_free(paths); |
| 120 | } |
| 121 |
no test coverage detected