* Step 4: Apply optimizations by lifting single-source clauses into subqueries. * * Creates a new QueryIR with single-source WHERE clauses moved to subqueries * that wrap the original table references. This ensures immutability and prevents * infinite recursion issues. * * @param query - Origi
( query: QueryIR, groupedClauses: GroupedWhereClauses, )
| 713 | * @returns New QueryIR with optimizations applied |
| 714 | */ |
| 715 | function applyOptimizations( |
| 716 | query: QueryIR, |
| 717 | groupedClauses: GroupedWhereClauses, |
| 718 | ): QueryIR { |
| 719 | // Track which single-source clauses were actually optimized |
| 720 | const actuallyOptimized = new Set<string>() |
| 721 | |
| 722 | // Determine which source aliases are on the nullable side of outer joins. |
| 723 | const nullableSources = getNullableJoinSources(query) |
| 724 | |
| 725 | // Build a filtered copy of singleSource that excludes nullable-side clauses. |
| 726 | // Pushing a WHERE clause into the nullable side's subquery pre-filters the |
| 727 | // data before the join, converting "matched but WHERE-excluded" rows into |
| 728 | // "unmatched" outer-join rows. These are indistinguishable from genuinely |
| 729 | // unmatched rows, so the residual WHERE cannot correct the result. |
| 730 | const pushableSingleSource = new Map<string, BasicExpression<boolean>>() |
| 731 | for (const [source, clause] of groupedClauses.singleSource) { |
| 732 | if (!nullableSources.has(source)) { |
| 733 | pushableSingleSource.set(source, clause) |
| 734 | } |
| 735 | } |
| 736 | |
| 737 | // Optimize the main FROM clause and track what was optimized |
| 738 | const optimizedFrom = optimizeFromWithTracking( |
| 739 | query.from, |
| 740 | pushableSingleSource, |
| 741 | actuallyOptimized, |
| 742 | ) |
| 743 | |
| 744 | // Optimize JOIN clauses and track what was optimized |
| 745 | const optimizedJoins = query.join |
| 746 | ? query.join.map((joinClause) => ({ |
| 747 | ...joinClause, |
| 748 | from: optimizeJoinFromWithTracking( |
| 749 | joinClause.from, |
| 750 | pushableSingleSource, |
| 751 | actuallyOptimized, |
| 752 | ), |
| 753 | })) |
| 754 | : undefined |
| 755 | |
| 756 | // Build the remaining WHERE clauses: multi-source + residual single-source clauses |
| 757 | const remainingWhereClauses: Array<Where> = [] |
| 758 | |
| 759 | // Add multi-source clauses |
| 760 | if (groupedClauses.multiSource) { |
| 761 | remainingWhereClauses.push(groupedClauses.multiSource) |
| 762 | } |
| 763 | |
| 764 | // Determine if we need residual clauses (when query has outer JOINs) |
| 765 | const hasOuterJoins = nullableSources.size > 0 |
| 766 | |
| 767 | // Add single-source clauses |
| 768 | for (const [source, clause] of groupedClauses.singleSource) { |
| 769 | if (!actuallyOptimized.has(source)) { |
| 770 | // Wasn't optimized at all - keep as regular WHERE clause |
| 771 | remainingWhereClauses.push(clause) |
| 772 | } else if (hasOuterJoins) { |
no test coverage detected