free the execution plans and all of the operations
| 547 | |
| 548 | // free the execution plans and all of the operations |
| 549 | void ExecutionPlan_Free |
| 550 | ( |
| 551 | ExecutionPlan *plan |
| 552 | ) { |
| 553 | ASSERT(plan != NULL); |
| 554 | if(plan->root == NULL) { |
| 555 | _ExecutionPlan_FreeInternals(plan); |
| 556 | return; |
| 557 | } |
| 558 | |
| 559 | // ------------------------------------------------------------------------- |
| 560 | // free op tree and collect execution-plans |
| 561 | // ------------------------------------------------------------------------- |
| 562 | |
| 563 | // traverse the execution-plan graph (DAG -> no endless cycles), while |
| 564 | // collecting the different segments, and freeing the op tree |
| 565 | dict *plans = HashTableCreate(&def_dt); |
| 566 | OpBase **visited = array_new(OpBase *, 1); |
| 567 | OpBase **to_visit = array_new(OpBase *, 1); |
| 568 | |
| 569 | OpBase *op = plan->root; |
| 570 | array_append(to_visit, op); |
| 571 | |
| 572 | while(array_len(to_visit) > 0) { |
| 573 | op = array_pop(to_visit); |
| 574 | |
| 575 | // add the plan this op is affiliated with |
| 576 | HashTableAdd(plans, (void *)op->plan, (void *)op->plan); |
| 577 | |
| 578 | // add all direct children of op to to_visit |
| 579 | for(uint i = 0; i < op->childCount; i++) { |
| 580 | if(op->children[i] != NULL) { |
| 581 | array_append(to_visit, op->children[i]); |
| 582 | } |
| 583 | } |
| 584 | |
| 585 | // add op to `visited` array |
| 586 | array_append(visited, op); |
| 587 | } |
| 588 | |
| 589 | // free the collected ops |
| 590 | for(int i = array_len(visited)-1; i >= 0; i--) { |
| 591 | op = visited[i]; |
| 592 | OpBase_Free(op); |
| 593 | } |
| 594 | array_free(visited); |
| 595 | array_free(to_visit); |
| 596 | |
| 597 | // ------------------------------------------------------------------------- |
| 598 | // free internals of the plans |
| 599 | // ------------------------------------------------------------------------- |
| 600 | |
| 601 | dictEntry *entry; |
| 602 | ExecutionPlan *curr_plan; |
| 603 | dictIterator *it = HashTableGetIterator(plans); |
| 604 | while((entry = HashTableNext(it)) != NULL) { |
| 605 | curr_plan = (ExecutionPlan *)HashTableGetVal(entry); |
| 606 | _ExecutionPlan_FreeInternals(curr_plan); |