build a query graph from AST
| 369 | |
| 370 | // build a query graph from AST |
| 371 | QueryGraph *BuildQueryGraph |
| 372 | ( |
| 373 | const AST *ast |
| 374 | ) { |
| 375 | uint node_count; |
| 376 | uint edge_count; |
| 377 | |
| 378 | // AST clauses containing path objects |
| 379 | cypher_astnode_type_t clause_types [2] = {CYPHER_AST_MATCH, CYPHER_AST_MERGE}; |
| 380 | |
| 381 | // the initial node and edge arrays will be large enough to accommodate |
| 382 | // all AST entities (which is overkill, consider reducing) |
| 383 | node_count = edge_count = raxSize(ast->referenced_entities); |
| 384 | QueryGraph *qg = QueryGraph_New(node_count, edge_count); |
| 385 | |
| 386 | // for each relevant clause type |
| 387 | for(int i = 0; i < 2; i ++) { |
| 388 | const uint8_t clause_type = clause_types[i]; |
| 389 | // collect all path objects |
| 390 | const cypher_astnode_t **clauses = AST_GetTypedNodes(ast->root, |
| 391 | clause_type); |
| 392 | uint clause_count = array_len(clauses); |
| 393 | |
| 394 | // for each clause of the current type |
| 395 | for(uint j = 0; j < clause_count; j ++) { |
| 396 | const cypher_astnode_t *clause = clauses[j]; |
| 397 | // collect path objects |
| 398 | const cypher_astnode_t **paths = |
| 399 | AST_GetTypedNodes(clause, CYPHER_AST_PATTERN_PATH); |
| 400 | const cypher_astnode_t **shortest_paths = |
| 401 | AST_GetTypedNodes(clause, CYPHER_AST_SHORTEST_PATH); |
| 402 | |
| 403 | // differentiate between regular paths and shortest paths |
| 404 | // as a path can be marked as shortest |
| 405 | uint path_count = array_len(paths); |
| 406 | uint shortest_path_count = array_len(shortest_paths); |
| 407 | bool only_shortest[path_count]; |
| 408 | memset(only_shortest, 0, path_count*sizeof(bool)); |
| 409 | |
| 410 | uint l = 0; // index to paths array |
| 411 | uint k = 0; // index to shortest paths array |
| 412 | for (; k < shortest_path_count; k++) { |
| 413 | const cypher_astnode_t *shortest = shortest_paths[k]; |
| 414 | // single shortest paths are handled by a procedure |
| 415 | if(cypher_ast_shortest_path_is_single(shortest)) continue; |
| 416 | |
| 417 | const cypher_astnode_t *path = |
| 418 | cypher_ast_shortest_path_get_path(shortest); |
| 419 | |
| 420 | // seek the matching path in the paths array |
| 421 | while(paths[l] != path) l++; |
| 422 | ASSERT(l < path_count); |
| 423 | |
| 424 | // each shortest must find its counterpart path |
| 425 | only_shortest[l] = true; |
| 426 | l++; // advance for next match |
| 427 | } |
| 428 | array_free(shortest_paths); |