import { ICollectionStrategy, CollectionStrategyType, CollectionAggregationConfig, CollectionAggregationResult } from '../collection-strategy.interface'; import { QueryContext } from '../query-builder'; /** * CTE-based collection strategy * * This is the current/default strategy that uses PostgreSQL CTEs with json_agg * to aggregate related records into JSONB arrays. * * Benefits: * - Single query execution * - No temp table management * - Works well for moderate data sizes * * SQL Pattern: * ```sql * WITH "cte_0" AS ( * SELECT * "user_id" as parent_id, * json_agg( * json_build_object('id', "id", 'title', "title") * ORDER BY "views" DESC * ) as data * FROM ( * SELECT "user_id", "id", "title", "views" * FROM "posts" * WHERE "views" > $1 * ORDER BY "views" DESC * ) sub * GROUP BY "user_id" * ) * SELECT ... COALESCE("cte_0".data, '[]'::jsonb) as "posts" ... * ``` */ export declare class CteCollectionStrategy implements ICollectionStrategy { getType(): CollectionStrategyType; requiresParentIds(): boolean; /** * Compose a final WHERE clause for a CTE inner SELECT by AND-ing the user's * existing where clause with any literal FK predicates declared on the * navigation (e.g. SCD2 `is_current = TRUE` from a * `withForeignKey: [col, isCurrent] / withPrincipalKey: [id, true]` shape). * * Without this, the CTE strategy groups every target row by FK column with no * filtering, leaking historical / closed SCD2 rows into the projected * collection — the exact QA_GO-429 Bug D symptom. * * @param config The aggregation config (carries `foreignKeys`/`matches`). * @param targetTable Alias of the target table inside the CTE's inner SELECT. * @param rewrittenWhereClause User's whereClause already rewritten for collection markers. */ private composeInnerWhere; buildAggregation(config: CollectionAggregationConfig, context: QueryContext): CollectionAggregationResult; /** * Helper to collect all leaf fields from a potentially nested structure * Returns array of { alias, expression } for SELECT clause (flattened with unique aliases) */ private collectLeafFields; /** * Helper to collect nested CTE joins from selected fields * These are joins to CTEs created for nested collections (collections within collections) */ private collectNestedCteJoins; /** * Helper to build json_build_object expression (handles nested structures) * Uses JSON instead of JSONB for better aggregation performance */ private buildJsonbObject; /** * Build navigation JOINs SQL for multi-level navigation in collection queries */ private buildNavigationJoins; /** * Build JSONB aggregation CTE * * When LIMIT/OFFSET is specified, uses ROW_NUMBER() window function to correctly * apply pagination per parent row (not globally). */ private buildJsonbAggregation; /** * Build single JSON object CTE (for firstOrDefault) * Returns a single JSON object per parent, or null if no match. * Uses ROW_NUMBER() to pick the first row per parent. * * SQL Pattern: * ```sql * SELECT * "__fk_user_id" as parent_id, * json_build_object('id', "id", 'title', "title") as data * FROM ( * SELECT *, ROW_NUMBER() OVER (PARTITION BY "__fk_user_id" ORDER BY ...) as __rn * FROM (SELECT ... FROM table) inner_sub * ) sub * WHERE __rn = 1 * ``` */ private buildSingleJsonAggregation; /** * Build JSONB aggregation with ROW_NUMBER() for per-parent LIMIT/OFFSET * * SQL Pattern: * ```sql * SELECT parent_id, json_agg(json_build_object(...)) as data * FROM ( * SELECT *, ROW_NUMBER() OVER (PARTITION BY foreign_key ORDER BY ...) as __rn * FROM (SELECT ... FROM table WHERE ...) inner_sub * ) sub * WHERE __rn > offset AND __rn <= offset + limit * GROUP BY parent_id * ``` */ private buildJsonbAggregationWithRowNumber; /** * Build array aggregation CTE (for toNumberList/toStringList) * * When LIMIT/OFFSET is specified, uses ROW_NUMBER() window function to correctly * apply pagination per parent row (not globally). */ private buildArrayAggregation; /** * Build array aggregation with ROW_NUMBER() for per-parent LIMIT/OFFSET */ private buildArrayAggregationWithRowNumber; /** * Build scalar aggregation CTE (COUNT, MIN, MAX, SUM) */ private buildScalarAggregation; /** * Build EXISTS aggregation CTE * Returns true for each parent that has at least one child row */ private buildExistsAggregation; } //# sourceMappingURL=cte-collection-strategy.d.ts.map