| 336 | //------------------------------------------------------------------------------ |
| 337 | |
| 338 | AST_MergeContext AST_PrepareMergeOp |
| 339 | ( |
| 340 | const cypher_astnode_t *merge_clause, |
| 341 | GraphContext *gc, |
| 342 | QueryGraph *qg, |
| 343 | rax *bound_vars |
| 344 | ) { |
| 345 | AST_MergeContext merge_ctx = { .nodes_to_merge = NULL, |
| 346 | .edges_to_merge = NULL, |
| 347 | .on_match = NULL, |
| 348 | .on_create = NULL |
| 349 | }; |
| 350 | |
| 351 | // Prepare all create contexts for nodes and edges on Merge path. |
| 352 | rax *on_match_items = NULL; |
| 353 | rax *on_create_items = NULL; |
| 354 | NodeCreateCtx *nodes_to_merge = array_new(NodeCreateCtx, 1); |
| 355 | EdgeCreateCtx *edges_to_merge = array_new(EdgeCreateCtx, 1); |
| 356 | const cypher_astnode_t *path = cypher_ast_merge_get_pattern_path(merge_clause); |
| 357 | |
| 358 | // Shouldn't operate on the original bound variables map, as this function may insert aliases. |
| 359 | rax *bound_and_introduced_entities = (bound_vars) ? raxClone(bound_vars) : raxNew(); |
| 360 | AST_PreparePathCreation(path, qg, bound_and_introduced_entities, &nodes_to_merge, &edges_to_merge); |
| 361 | raxFree(bound_and_introduced_entities); |
| 362 | |
| 363 | |
| 364 | // Convert any ON MATCH and ON CREATE directives. |
| 365 | uint directive_count = cypher_ast_merge_nactions(merge_clause); |
| 366 | |
| 367 | for(uint i = 0; i < directive_count; i ++) { |
| 368 | const cypher_astnode_t *directive = cypher_ast_merge_get_action(merge_clause, i); |
| 369 | cypher_astnode_type_t type = cypher_astnode_type(directive); |
| 370 | |
| 371 | if(type == CYPHER_AST_ON_CREATE) { |
| 372 | uint create_prop_count = cypher_ast_on_create_nitems(directive); |
| 373 | if(on_create_items == NULL) on_create_items = raxNew(); |
| 374 | for(uint j = 0; j < create_prop_count; j ++) { |
| 375 | const cypher_astnode_t *create_item = cypher_ast_on_create_get_item(directive, j); |
| 376 | _ConvertUpdateItem(gc, on_create_items, create_item); |
| 377 | } |
| 378 | } else if(type == CYPHER_AST_ON_MATCH) { |
| 379 | uint match_prop_count = cypher_ast_on_match_nitems(directive); |
| 380 | if(on_match_items == NULL) on_match_items = raxNew(); |
| 381 | for(uint j = 0; j < match_prop_count; j ++) { |
| 382 | const cypher_astnode_t *match_item = cypher_ast_on_match_get_item(directive, j); |
| 383 | _ConvertUpdateItem(gc, on_match_items, match_item); |
| 384 | } |
| 385 | } else { |
| 386 | ASSERT(false); |
| 387 | } |
| 388 | } |
| 389 | |
| 390 | merge_ctx.on_match = on_match_items; |
| 391 | merge_ctx.on_create = on_create_items; |
| 392 | merge_ctx.edges_to_merge = edges_to_merge; |
| 393 | merge_ctx.nodes_to_merge = nodes_to_merge; |
| 394 | return merge_ctx; |
| 395 | } |
no test coverage detected