{"version":3,"file":"group-by.cjs","sources":["../../../../src/query/compiler/group-by.ts"],"sourcesContent":["import {\n  filter,\n  groupBy,\n  groupByOperators,\n  map,\n  serializeValue,\n} from '@tanstack/db-ivm'\nimport {\n  ConditionalSelect,\n  Func,\n  PropRef,\n  getHavingExpression,\n  isExpressionLike,\n} from '../ir.js'\nimport {\n  AggregateFunctionNotInSelectError,\n  NonAggregateExpressionNotInGroupByError,\n  UnknownHavingExpressionTypeError,\n  UnsupportedAggregateFunctionError,\n} from '../../errors.js'\nimport {\n  getEqualityValueIdentity,\n  getParentContextIdentity,\n  getParentContextValue,\n} from '../equality-value-identity.js'\nimport {\n  compileExpression,\n  isCaseWhenConditionTrue,\n  toBooleanPredicate,\n} from './evaluators.js'\nimport {\n  INCLUDES_PUBLIC_KEY,\n  attachRouteMetadata,\n  getNamespacedRouteMetadata,\n  stripInternalCallbackMetadata,\n} from './route-metadata.js'\nimport type { ValueIdentity } from '../equality-value-identity.js'\nimport type { RouteMetadata } from './route-metadata.js'\nimport type {\n  Aggregate,\n  BasicExpression,\n  GroupBy,\n  Having,\n  Select,\n  SelectValueExpression,\n} from '../ir.js'\nimport type { NamespacedAndKeyedStream, NamespacedRow } from '../../types.js'\nimport type { VirtualOrigin } from '../../virtual-props.js'\n\nconst RAW_REPRESENTATIVE = Symbol(`raw_group_representative`)\n\ntype InternalGroupFields = ReturnType<typeof createInternalGroupFields>\n\nfunction createInternalGroupFields(groupCount: number, selectClause?: Select) {\n  const aliases = Object.keys(selectClause ?? {})\n  let prefix = `__tanstack_group_`\n  while (aliases.some((alias) => alias.startsWith(prefix))) prefix += `_`\n\n  return {\n    virtual: `${prefix}virtual`,\n    route: `${prefix}route`,\n    correlationIdentity: `${prefix}correlation_identity`,\n    parentContextIdentity: `${prefix}parent_context_identity`,\n    singleGroup: `${prefix}single_group`,\n    aggregatePrefix: `${prefix}aggregate_`,\n    groupKeys: Array.from(\n      { length: groupCount },\n      (_, i) => `${prefix}key_${i}`,\n    ),\n    groupValues: Array.from(\n      { length: groupCount },\n      (_, i) => `${prefix}value_${i}`,\n    ),\n    groupKeyRefs: Array.from(\n      { length: groupCount },\n      (_, i) => `${prefix}key_ref_${i}`,\n    ),\n  }\n}\n\ntype RowVirtualMetadata = {\n  synced: boolean\n  hasLocal: boolean\n}\n\ntype Representative<T> = {\n  key: string\n  [RAW_REPRESENTATIVE]: T\n}\n\nfunction createPublicGroupKey(values: Array<unknown>): unknown {\n  const identities = values.map(getEqualityValueIdentity)\n  if (identities.length === 1) {\n    const identity = identities[0]\n    if (\n      identity == null ||\n      (typeof identity !== `object` &&\n        typeof identity !== `function` &&\n        typeof identity !== `symbol`)\n    ) {\n      return identity\n    }\n  }\n  return serializeValue(identities)\n}\n\nfunction attachPublicGroupKey(\n  row: Record<string, any>,\n  publicKey: unknown,\n): void {\n  const keyedRow = row as Record<PropertyKey, unknown>\n  keyedRow[INCLUDES_PUBLIC_KEY] = publicKey\n}\n\nfunction createRepresentative<T>(\n  rowKey: string,\n  value: T,\n  identity: unknown,\n): Representative<T> {\n  // Encode once per contribution, not once per member on every group change.\n  const representative = {\n    key: serializeValue([rowKey, identity]),\n  } as Representative<T>\n  Object.defineProperty(representative, RAW_REPRESENTATIVE, { value })\n  return representative\n}\n\nfunction getRepresentative<T>(\n  values: Array<[Representative<T>, number]>,\n): Representative<T> | undefined {\n  let selected: Representative<T> | undefined\n  for (const [candidate, multiplicity] of values) {\n    if (multiplicity <= 0) continue\n    if (selected === undefined || candidate.key < selected.key) {\n      selected = candidate\n    }\n  }\n  return selected\n}\n\nfunction unwrapRepresentative<T>(\n  value: Representative<T> | undefined,\n): T | undefined {\n  return value?.[RAW_REPRESENTATIVE]\n}\n\nfunction addCorrelationRouteIdentityToGroupKey(\n  key: Record<string, unknown>,\n  row: NamespacedRow,\n  mainSource: string,\n  fields: InternalGroupFields,\n  valueIdentity: ValueIdentity,\n): void {\n  const route = getNamespacedRouteMetadata(row, mainSource)\n  key[fields.correlationIdentity] = valueIdentity.equality(\n    route?.correlationKey,\n  )\n  if (route?.parentContext != null) {\n    key[fields.parentContextIdentity] = getParentContextIdentity(\n      route.parentContext,\n    )\n  }\n}\n\n/** One representative carries the whole route so both parts come from one row. */\nfunction addCorrelationRouteAggregate(\n  aggregates: Record<string, any>,\n  mainSource: string,\n  fields: InternalGroupFields,\n  valueIdentity: ValueIdentity,\n): void {\n  aggregates[fields.route] = {\n    preMap: ([rowKey, row]: [string, NamespacedRow]) => {\n      const route = getNamespacedRouteMetadata(row, mainSource)\n      return createRepresentative(rowKey, route, [\n        valueIdentity.exact(route?.correlationKey),\n        getParentContextIdentity(route?.parentContext),\n      ])\n    },\n    reduce: getRepresentative,\n    postMap: unwrapRepresentative,\n  }\n}\n\nfunction getGroupRoute(\n  aggregatedRow: Record<string, unknown>,\n  fields: InternalGroupFields,\n): RouteMetadata | undefined {\n  return aggregatedRow[fields.route] as RouteMetadata | undefined\n}\n\nfunction getCorrelationRouteIdentity(\n  aggregatedRow: Record<string, unknown>,\n  fields: InternalGroupFields,\n): unknown {\n  return getGroupRoute(aggregatedRow, fields)?.parentContext == null\n    ? aggregatedRow[fields.correlationIdentity]\n    : [\n        aggregatedRow[fields.correlationIdentity],\n        aggregatedRow[fields.parentContextIdentity],\n      ]\n}\n\nfunction getGroupEvaluationRow(\n  row: Record<string, unknown>,\n  fields: InternalGroupFields,\n  selected = row.$selected as Record<string, unknown>,\n): NamespacedRow {\n  return {\n    ...getParentContextValue(getGroupRoute(row, fields)?.parentContext),\n    $selected: selected,\n  }\n}\n\nfunction getRowVirtualMetadata(row: NamespacedRow): RowVirtualMetadata {\n  let found = false\n  let allSynced = true\n  let hasLocal = false\n\n  for (const [alias, value] of Object.entries(row as Record<string, unknown>)) {\n    if (alias === `$selected`) continue\n    if (value === null || typeof value !== `object`) continue\n    const asRecord = value as Record<string, unknown>\n    const hasSyncedProp = `$synced` in asRecord\n    const hasOriginProp = `$origin` in asRecord\n    if (!hasSyncedProp && !hasOriginProp) {\n      continue\n    }\n    found = true\n    if (asRecord.$synced === false) {\n      allSynced = false\n    }\n    if (asRecord.$origin === `local`) {\n      hasLocal = true\n    }\n  }\n\n  return {\n    synced: found ? allSynced : true,\n    hasLocal,\n  }\n}\n\nconst { sum, count, avg, min, max } = groupByOperators\n\n/**\n * Validates that all non-aggregate expressions in SELECT are present in GROUP BY\n * and creates a cached mapping for efficient lookup during processing\n */\nfunction validateAndCreateMapping(\n  groupByClause: GroupBy,\n  selectClause?: Select,\n): Map<string, number> {\n  const selectToGroupByIndex = new Map<string, number>()\n\n  if (!selectClause) {\n    return selectToGroupByIndex\n  }\n\n  // Validate each SELECT expression\n  for (const [alias, expr] of Object.entries(selectClause)) {\n    if (expr.type === `agg` || containsAggregate(expr)) {\n      // Aggregate expressions (plain or wrapped) are allowed and don't need to be in GROUP BY\n      continue\n    }\n\n    // Non-aggregate expression must be in GROUP BY\n    const groupIndex = groupByClause.findIndex((groupExpr) =>\n      expressionsEqual(expr, groupExpr),\n    )\n\n    if (groupIndex === -1) {\n      throw new NonAggregateExpressionNotInGroupByError(alias)\n    }\n\n    // Cache the mapping\n    selectToGroupByIndex.set(alias, groupIndex)\n  }\n\n  return selectToGroupByIndex\n}\n\n/**\n * Processes the GROUP BY clause with optional HAVING and SELECT\n * Works with the new $selected structure from early SELECT processing\n */\nexport function processGroupBy(\n  pipeline: NamespacedAndKeyedStream,\n  groupByClause: GroupBy,\n  valueIdentity: ValueIdentity,\n  havingClauses?: Array<Having>,\n  selectClause?: Select,\n  fnHavingClauses?: Array<(row: any) => any>,\n  aggregateCollectionId?: string,\n  mainSource?: string,\n  sanitizeCallbackRows = false,\n): NamespacedAndKeyedStream {\n  const fields = createInternalGroupFields(groupByClause.length, selectClause)\n  const virtualAggregates: Record<string, any> = {\n    [fields.virtual]: {\n      preMap: ([, row]: [string, NamespacedRow]) => getRowVirtualMetadata(row),\n      reduce: (values: Array<[RowVirtualMetadata, number]>) => {\n        const group: RowVirtualMetadata = { synced: true, hasLocal: false }\n        for (const [metadata, multiplicity] of values) {\n          if (multiplicity <= 0) continue\n          if (!metadata.synced) group.synced = false\n          if (metadata.hasLocal) group.hasLocal = true\n        }\n        return group\n      },\n    },\n  }\n\n  if (mainSource) {\n    addCorrelationRouteAggregate(\n      virtualAggregates,\n      mainSource,\n      fields,\n      valueIdentity,\n    )\n  }\n\n  const singleGroup = groupByClause.length === 0\n  // Single-group aggregation accepts selections without grouping validation.\n  const mapping = singleGroup\n    ? undefined\n    : validateAndCreateMapping(groupByClause, selectClause)\n\n  // Pre-compile groupBy expressions\n  const compiledGroupByExpressions = groupByClause.map((e) =>\n    compileExpression(e),\n  )\n\n  // Include the complete route so distinct parent inputs stay apart.\n  const keyExtractor = ([, row]: [\n    string,\n    NamespacedRow & { $selected?: any },\n  ]) => {\n    // Use the original namespaced row for GROUP BY expressions, not $selected\n    const namespacedRow = singleGroup ? row : { ...row }\n    if (!singleGroup) delete namespacedRow.$selected\n\n    const key: Record<string, unknown> = singleGroup\n      ? { [fields.singleGroup]: true }\n      : {}\n\n    // D2 must key groups by the same relation as the query evaluator. The raw\n    // representative is retained separately as an aggregate for projection.\n    for (let i = 0; i < groupByClause.length; i++) {\n      const compiledExpr = compiledGroupByExpressions[i]!\n      const value = compiledExpr(namespacedRow)\n      key[fields.groupKeys[i]!] = valueIdentity.equality(value)\n    }\n\n    if (mainSource) {\n      addCorrelationRouteIdentityToGroupKey(\n        key,\n        row,\n        mainSource,\n        fields,\n        valueIdentity,\n      )\n    }\n\n    return key\n  }\n\n  // Create aggregate functions for any aggregated columns in the SELECT clause\n  const aggregates: Record<string, any> = virtualAggregates\n  const wrappedAggExprs: Record<string, (data: any) => any> = {}\n  const aggCounter = { value: 0 }\n\n  for (let i = 0; i < compiledGroupByExpressions.length; i++) {\n    const compiledExpr = compiledGroupByExpressions[i]!\n    aggregates[fields.groupValues[i]!] = {\n      preMap: ([rowKey, row]: [string, NamespacedRow]) => {\n        const value = compiledExpr(row)\n        return createRepresentative(rowKey, value, valueIdentity.exact(value))\n      },\n      reduce: getRepresentative,\n      postMap: unwrapRepresentative,\n    }\n  }\n\n  if (selectClause) {\n    // Scan the SELECT clause for aggregate functions\n    for (const [alias, expr] of Object.entries(selectClause)) {\n      if (expr.type === `agg`) {\n        aggregates[alias] = getAggregateFunction(expr)\n      } else if (containsAggregate(expr)) {\n        const { transformed, extracted } = extractAndReplaceAggregates(\n          expr as SelectValueExpression,\n          aggCounter,\n          fields.aggregatePrefix,\n        )\n        for (const [syntheticAlias, aggExpr] of Object.entries(extracted)) {\n          aggregates[syntheticAlias] = getAggregateFunction(aggExpr)\n        }\n        wrappedAggExprs[alias] = compileGroupedSelectValue(\n          singleGroup\n            ? transformed\n            : replaceGroupByRefsInSelectValue(\n                transformed,\n                groupByClause,\n                fields.groupKeyRefs,\n              ),\n        )\n      }\n    }\n  }\n\n  // Apply the groupBy operator\n  pipeline = pipeline.pipe(groupBy(keyExtractor, aggregates))\n\n  // Update $selected to handle GROUP BY results\n  pipeline = pipeline.pipe(\n    map(([, aggregatedRow]) => {\n      // Start with the existing $selected from early SELECT processing\n      const selectResults = (aggregatedRow as any).$selected || {}\n      const finalResults: Record<string, any> = singleGroup\n        ? { ...selectResults }\n        : {}\n\n      if (selectClause) {\n        // First pass: populate group keys, plain aggregates, and synthetic aliases\n        for (const [alias, expr] of Object.entries(selectClause)) {\n          if (expr.type === `agg`) {\n            finalResults[alias] = aggregatedRow[alias]\n          } else if (!singleGroup && !wrappedAggExprs[alias]) {\n            // Use cached mapping to get the corresponding __key_X for non-aggregates\n            const groupIndex = mapping?.get(alias)\n            if (groupIndex !== undefined) {\n              finalResults[alias] =\n                aggregatedRow[fields.groupValues[groupIndex]!]\n            } else {\n              // Fallback to original SELECT results\n              finalResults[alias] = selectResults[alias]\n            }\n          }\n        }\n        evaluateWrappedAggregates(\n          finalResults,\n          aggregatedRow as Record<string, any>,\n          wrappedAggExprs,\n          fields,\n        )\n      } else {\n        // No SELECT clause - just use the group keys\n        for (let i = 0; i < groupByClause.length; i++) {\n          finalResults[`__key_${i}`] = aggregatedRow[fields.groupValues[i]!]\n        }\n      }\n\n      // Generate a simple key for the live collection using group values.\n      // In includes mode, add the complete route so correlated groups do not\n      // collide.\n      const route = mainSource\n        ? getGroupRoute(aggregatedRow, fields)\n        : undefined\n      const correlationKey = route?.correlationKey\n      const correlationRoute = mainSource\n        ? getCorrelationRouteIdentity(aggregatedRow, fields)\n        : undefined\n      const keyParts: Array<unknown> = []\n      const publicKeyParts: Array<unknown> = []\n      for (let i = 0; i < groupByClause.length; i++) {\n        keyParts.push(aggregatedRow[fields.groupKeys[i]!])\n        publicKeyParts.push(aggregatedRow[fields.groupValues[i]!])\n      }\n      if (correlationRoute !== undefined) {\n        keyParts.push(correlationRoute)\n      }\n      const finalKey = singleGroup\n        ? correlationRoute !== undefined\n          ? `single_group_${serializeValue(correlationRoute)}`\n          : `single_group`\n        : keyParts.length === 1\n          ? keyParts[0]\n          : serializeValue(keyParts)\n      const publicKey = singleGroup\n        ? `single_group`\n        : createPublicGroupKey(publicKeyParts)\n\n      // When in includes mode, restore route metadata for output routing.\n      const resultRow: Record<string, any> = {\n        ...(aggregatedRow as Record<string, any>),\n        $selected: finalResults,\n      }\n      const virtual = (aggregatedRow as Record<string, any>)[fields.virtual] as\n        | RowVirtualMetadata\n        | undefined\n      resultRow.$synced = virtual?.synced ?? true\n      resultRow.$origin = (\n        virtual?.hasLocal ? `local` : `remote`\n      ) satisfies VirtualOrigin\n      resultRow.$key = publicKey\n      resultRow.$collectionId = aggregateCollectionId ?? resultRow.$collectionId\n      if (mainSource && correlationKey !== undefined) {\n        attachPublicGroupKey(resultRow, publicKey)\n        attachRouteMetadata(\n          resultRow,\n          correlationKey,\n          route?.parentContext ?? null,\n        )\n      }\n      return [mainSource ? finalKey : publicKey, resultRow] as [\n        unknown,\n        Record<string, any>,\n      ]\n    }),\n  )\n\n  // Apply HAVING clauses if present\n  if (havingClauses && havingClauses.length > 0) {\n    for (const havingClause of havingClauses) {\n      const havingExpression = getHavingExpression(havingClause)\n      const transformedHavingClause = replaceAggregatesByRefs(\n        havingExpression,\n        selectClause || {},\n      )\n      const compiledHaving = compileExpression(transformedHavingClause)\n\n      pipeline = pipeline.pipe(\n        filter(([, row]) => {\n          const namespacedRow = getGroupEvaluationRow(row, fields)\n          const result = compiledHaving(namespacedRow)\n          // Preserve each path's coercion for unchecked nonboolean IR values.\n          return singleGroup ? toBooleanPredicate(result) : result\n        }),\n      )\n    }\n  }\n\n  // Apply functional HAVING clauses if present\n  if (fnHavingClauses && fnHavingClauses.length > 0) {\n    for (const fnHaving of fnHavingClauses) {\n      pipeline = pipeline.pipe(\n        filter(([, row]) => {\n          const namespacedRow = getGroupEvaluationRow(row, fields)\n          const callbackRow = sanitizeCallbackRows\n            ? stripInternalCallbackMetadata(namespacedRow)\n            : namespacedRow\n          return toBooleanPredicate(fnHaving(callbackRow))\n        }),\n      )\n    }\n  }\n\n  return pipeline\n}\n\n/**\n * Helper function to check if two expressions are equal\n */\nfunction expressionsEqual(expr1: any, expr2: any): boolean {\n  if (!expr1 || !expr2) return false\n  if (expr1.type !== expr2.type) return false\n\n  switch (expr1.type) {\n    case `ref`:\n      // Compare paths as arrays\n      if (!expr1.path || !expr2.path) return false\n      if (expr1.path.length !== expr2.path.length) return false\n      return expr1.path.every(\n        (segment: string, i: number) => segment === expr2.path[i],\n      )\n    case `val`:\n      return expr1.value === expr2.value\n    case `func`:\n      return (\n        expr1.name === expr2.name &&\n        expr1.args?.length === expr2.args?.length &&\n        (expr1.args || []).every((arg: any, i: number) =>\n          expressionsEqual(arg, expr2.args[i]),\n        )\n      )\n    case `agg`:\n      return (\n        expr1.name === expr2.name &&\n        expr1.args?.length === expr2.args?.length &&\n        (expr1.args || []).every((arg: any, i: number) =>\n          expressionsEqual(arg, expr2.args[i]),\n        )\n      )\n    default:\n      return false\n  }\n}\n\n/**\n * Helper function to get an aggregate function based on the Agg expression\n */\nfunction getAggregateFunction(aggExpr: Aggregate) {\n  // Pre-compile the value extractor expression\n  const compiledExpr = compileExpression(aggExpr.args[0]!)\n\n  // Create a value extractor function for the expression to aggregate\n  const valueExtractor = ([, namespacedRow]: [string, NamespacedRow]) => {\n    const value = compiledExpr(namespacedRow)\n    // Ensure we return a number for numeric aggregate functions\n    if (typeof value === `number`) {\n      return value\n    }\n    return value != null ? Number(value) : 0\n  }\n\n  // Create a value extractor function for min/max that preserves comparable types\n  const valueExtractorForMinMax = ([, namespacedRow]: [\n    string,\n    NamespacedRow,\n  ]) => {\n    const value = compiledExpr(namespacedRow)\n    // Preserve strings, numbers, Dates, and bigints for comparison\n    if (\n      typeof value === `number` ||\n      typeof value === `string` ||\n      typeof value === `bigint` ||\n      value instanceof Date\n    ) {\n      return value\n    }\n    return value != null ? Number(value) : 0\n  }\n\n  // Create a raw value extractor function for the expression to aggregate\n  const rawValueExtractor = ([, namespacedRow]: [string, NamespacedRow]) => {\n    return compiledExpr(namespacedRow)\n  }\n\n  // Return the appropriate aggregate function\n  switch (aggExpr.name.toLowerCase()) {\n    case `sum`:\n      return sum(valueExtractor)\n    case `count`:\n      return count(rawValueExtractor)\n    case `avg`:\n      return avg(valueExtractor)\n    case `min`:\n      return min(valueExtractorForMinMax)\n    case `max`:\n      return max(valueExtractorForMinMax)\n    default:\n      throw new UnsupportedAggregateFunctionError(aggExpr.name)\n  }\n}\n\n/**\n * Transforms expressions to replace aggregate functions with references to computed values.\n *\n * For aggregate expressions, finds matching aggregates in the SELECT clause and replaces them\n * with PropRef([resultAlias, alias]) to reference the computed aggregate value.\n *\n * Ref expressions (table columns and $selected fields) and value expressions are passed through unchanged.\n * Function expressions are recursively transformed.\n *\n * @param havingExpr - The expression to transform (can be aggregate, ref, func, or val)\n * @param selectClause - The SELECT clause containing aliases and aggregate definitions\n * @param resultAlias - The namespace alias for SELECT results (default: '$selected')\n * @returns A transformed BasicExpression that references computed values instead of raw expressions\n */\nexport function replaceAggregatesByRefs(\n  havingExpr: BasicExpression | Aggregate,\n  selectClause: Select,\n  resultAlias: string = `$selected`,\n): BasicExpression {\n  switch (havingExpr.type) {\n    case `agg`: {\n      const aggExpr = havingExpr\n      // Find matching aggregate in SELECT clause\n      for (const [alias, selectExpr] of Object.entries(selectClause)) {\n        if (selectExpr.type === `agg` && aggregatesEqual(aggExpr, selectExpr)) {\n          // Replace with a reference to the computed aggregate\n          return new PropRef([resultAlias, alias])\n        }\n      }\n      // If no matching aggregate found in SELECT, throw error\n      throw new AggregateFunctionNotInSelectError(aggExpr.name)\n    }\n\n    case `func`: {\n      const funcExpr = havingExpr\n      // Transform function arguments recursively\n      const transformedArgs = funcExpr.args.map(\n        (arg: BasicExpression | Aggregate) =>\n          replaceAggregatesByRefs(arg, selectClause),\n      )\n      return new Func(funcExpr.name, transformedArgs)\n    }\n\n    case `ref`:\n      // Ref expressions are passed through unchanged - they reference either:\n      // - $selected fields (which are already in the correct namespace)\n      // - Table column references (which remain valid)\n      return havingExpr as BasicExpression\n\n    case `val`:\n      // Return as-is\n      return havingExpr as BasicExpression\n\n    default:\n      throw new UnknownHavingExpressionTypeError((havingExpr as any).type)\n  }\n}\n\n/**\n * Evaluates wrapped-aggregate expressions against the aggregated row.\n * Copies synthetic __agg_N values into finalResults so the compiled wrapper\n * expressions can reference them, evaluates each wrapper, then removes the\n * synthetic keys so they don't leak onto user-visible result rows.\n */\nfunction evaluateWrappedAggregates(\n  finalResults: Record<string, any>,\n  aggregatedRow: Record<string, any>,\n  wrappedAggExprs: Record<string, (data: any) => any>,\n  fields: InternalGroupFields,\n): void {\n  for (const key of Object.keys(aggregatedRow)) {\n    if (key.startsWith(fields.aggregatePrefix)) {\n      finalResults[key] = aggregatedRow[key]\n    }\n  }\n  for (let i = 0; i < fields.groupKeyRefs.length; i++) {\n    finalResults[fields.groupKeyRefs[i]!] =\n      aggregatedRow[fields.groupValues[i]!]\n  }\n  for (const [alias, evaluator] of Object.entries(wrappedAggExprs)) {\n    finalResults[alias] = evaluator(\n      getGroupEvaluationRow(aggregatedRow, fields, finalResults),\n    )\n  }\n  for (const key of Object.keys(finalResults)) {\n    if (\n      key.startsWith(fields.aggregatePrefix) ||\n      fields.groupKeyRefs.includes(key)\n    ) {\n      delete finalResults[key]\n    }\n  }\n}\n\n/**\n * Checks whether an expression contains an aggregate anywhere in its tree.\n * Returns true for a top-level Aggregate, or a Func whose args (recursively)\n * contain an Aggregate. Safely returns false for nested Select objects.\n */\nexport function containsAggregate(\n  expr: BasicExpression | Aggregate | Select | { type: string },\n): boolean {\n  if (isConditionalSelect(expr)) {\n    const branchHasAggregate = expr.branches.some(\n      (branch) =>\n        containsAggregate(branch.condition) || containsAggregate(branch.value),\n    )\n\n    return (\n      branchHasAggregate ||\n      (expr.defaultValue !== undefined && containsAggregate(expr.defaultValue))\n    )\n  }\n\n  if (isNestedSelectObject(expr)) {\n    return Object.values(expr).some((value) =>\n      containsAggregate(value as BasicExpression | Aggregate | Select),\n    )\n  }\n\n  if (!isExpressionLike(expr)) {\n    return false\n  }\n\n  if (expr.type === `agg`) {\n    return true\n  }\n  if (expr.type === `func` && `args` in expr) {\n    return (expr.args as Array<BasicExpression | Aggregate>).some(\n      (arg: BasicExpression | Aggregate) => containsAggregate(arg),\n    )\n  }\n  return false\n}\n\n/**\n * Walks an expression tree containing nested aggregates.\n * Each Aggregate node is extracted, assigned a synthetic alias (__agg_N),\n * and replaced with PropRef([\"$selected\", \"__agg_N\"]) so the wrapper\n * expression can be compiled as a pure BasicExpression after groupBy\n * populates the synthetic values.\n */\nfunction extractAndReplaceAggregates(\n  expr: SelectValueExpression,\n  counter: { value: number },\n  aggregatePrefix: string,\n): {\n  transformed: SelectValueExpression\n  extracted: Record<string, Aggregate>\n} {\n  if (expr.type === `includesSubquery`) {\n    return { transformed: expr, extracted: {} }\n  }\n\n  if (expr.type === `agg`) {\n    const alias = `${aggregatePrefix}${counter.value++}`\n    return {\n      transformed: new PropRef([`$selected`, alias]),\n      extracted: { [alias]: expr },\n    }\n  }\n\n  if (expr.type === `func`) {\n    const allExtracted: Record<string, Aggregate> = {}\n    const newArgs = expr.args.map((arg: BasicExpression | Aggregate) => {\n      const result = extractAndReplaceAggregates(arg, counter, aggregatePrefix)\n      Object.assign(allExtracted, result.extracted)\n      return result.transformed as BasicExpression\n    })\n    return {\n      transformed: new Func(expr.name, newArgs),\n      extracted: allExtracted,\n    }\n  }\n\n  if (isConditionalSelect(expr)) {\n    const allExtracted: Record<string, Aggregate> = {}\n    const branches = expr.branches.map((branch) => {\n      const condition = extractAndReplaceAggregates(\n        branch.condition,\n        counter,\n        aggregatePrefix,\n      )\n      const value = extractAndReplaceAggregates(\n        branch.value,\n        counter,\n        aggregatePrefix,\n      )\n      Object.assign(allExtracted, condition.extracted, value.extracted)\n      return {\n        condition: condition.transformed as BasicExpression,\n        value: value.transformed,\n      }\n    })\n    const defaultValue =\n      expr.defaultValue === undefined\n        ? undefined\n        : extractAndReplaceAggregates(\n            expr.defaultValue,\n            counter,\n            aggregatePrefix,\n          )\n\n    if (defaultValue) {\n      Object.assign(allExtracted, defaultValue.extracted)\n    }\n\n    return {\n      transformed: new ConditionalSelect(branches, defaultValue?.transformed),\n      extracted: allExtracted,\n    }\n  }\n\n  if (isNestedSelectObject(expr)) {\n    const allExtracted: Record<string, Aggregate> = {}\n    const transformed: Select = {}\n\n    for (const [key, value] of Object.entries(expr)) {\n      const result = extractAndReplaceAggregates(\n        value as SelectValueExpression,\n        counter,\n        aggregatePrefix,\n      )\n      Object.assign(allExtracted, result.extracted)\n      transformed[key] = result.transformed\n    }\n\n    return { transformed, extracted: allExtracted }\n  }\n\n  // ref / val – pass through unchanged\n  return { transformed: expr, extracted: {} }\n}\n\nfunction replaceGroupByRefsInSelectValue(\n  value: SelectValueExpression,\n  groupByClause: GroupBy,\n  groupKeyRefs: Array<string>,\n): SelectValueExpression {\n  if (isConditionalSelect(value)) {\n    return new ConditionalSelect(\n      value.branches.map((branch) => ({\n        condition: replaceGroupByRefsInExpression(\n          branch.condition,\n          groupByClause,\n          groupKeyRefs,\n        ),\n        value: replaceGroupByRefsInSelectValue(\n          branch.value,\n          groupByClause,\n          groupKeyRefs,\n        ),\n      })),\n      value.defaultValue === undefined\n        ? undefined\n        : replaceGroupByRefsInSelectValue(\n            value.defaultValue,\n            groupByClause,\n            groupKeyRefs,\n          ),\n    )\n  }\n\n  if (isNestedSelectObject(value)) {\n    const transformed: Select = {}\n    for (const [key, entry] of Object.entries(value)) {\n      transformed[key] = replaceGroupByRefsInSelectValue(\n        entry as SelectValueExpression,\n        groupByClause,\n        groupKeyRefs,\n      )\n    }\n    return transformed\n  }\n\n  if (!isExpressionLike(value)) {\n    return value\n  }\n\n  if (value.type === `includesSubquery` || value.type === `agg`) {\n    return value\n  }\n\n  return replaceGroupByRefsInExpression(value, groupByClause, groupKeyRefs)\n}\n\nfunction replaceGroupByRefsInExpression(\n  expr: BasicExpression,\n  groupByClause: GroupBy,\n  groupKeyRefs: Array<string>,\n): BasicExpression {\n  if (expr.type === `ref`) {\n    const groupIndex = groupByClause.findIndex((groupExpr) =>\n      expressionsEqual(expr, groupExpr),\n    )\n    return groupIndex === -1\n      ? expr\n      : new PropRef([`$selected`, groupKeyRefs[groupIndex]!])\n  }\n\n  if (expr.type === `func`) {\n    return new Func(\n      expr.name,\n      expr.args.map((arg) =>\n        replaceGroupByRefsInExpression(arg, groupByClause, groupKeyRefs),\n      ),\n    )\n  }\n\n  return expr\n}\n\nfunction compileGroupedSelectValue(\n  value: SelectValueExpression,\n): (row: NamespacedRow) => any {\n  if (isConditionalSelect(value)) {\n    return compileGroupedConditionalSelect(value)\n  }\n\n  if (value.type === `includesSubquery`) {\n    return () => null\n  }\n\n  if (isNestedSelectObject(value)) {\n    return compileGroupedSelectObject(value)\n  }\n\n  if (!isExpressionLike(value)) {\n    return () => value\n  }\n\n  return compileExpression(value as BasicExpression)\n}\n\nfunction compileGroupedSelectObject(\n  obj: Select,\n): (row: NamespacedRow) => Record<string, any> {\n  const entries = Object.entries(obj).map(([key, value]) => {\n    if (key.startsWith(`__SPREAD_SENTINEL__`)) {\n      const rest = key.slice(`__SPREAD_SENTINEL__`.length)\n      const splitIndex = rest.lastIndexOf(`__`)\n      const pathStr = splitIndex >= 0 ? rest.slice(0, splitIndex) : rest\n      const isRefExpr =\n        typeof value === `object` && `type` in value && value.type === `ref`\n      const expression = isRefExpr\n        ? (value as BasicExpression)\n        : (new PropRef(pathStr.split(`.`)) as BasicExpression)\n\n      return {\n        key,\n        spread: true,\n        value: compileExpression(expression),\n      }\n    }\n\n    return {\n      key,\n      spread: false,\n      value: compileGroupedSelectValue(value as SelectValueExpression),\n    }\n  })\n\n  return (row) => {\n    const result: Record<string, any> = {}\n    for (const entry of entries) {\n      const value = entry.value(row)\n      if (entry.spread) {\n        if (value && typeof value === `object`) {\n          Object.assign(result, value)\n        }\n      } else {\n        result[entry.key] = value\n      }\n    }\n    return result\n  }\n}\n\nfunction compileGroupedConditionalSelect(\n  conditional: ConditionalSelect,\n): (row: NamespacedRow) => any {\n  const branches = conditional.branches.map((branch) => ({\n    condition: compileExpression(branch.condition),\n    value: compileGroupedSelectValue(branch.value),\n  }))\n  const defaultValue =\n    conditional.defaultValue === undefined\n      ? undefined\n      : compileGroupedSelectValue(conditional.defaultValue)\n\n  return (row) => {\n    for (const branch of branches) {\n      if (isCaseWhenConditionTrue(branch.condition(row))) {\n        return branch.value(row)\n      }\n    }\n\n    return defaultValue !== undefined ? defaultValue(row) : null\n  }\n}\n\nfunction isNestedSelectObject(value: unknown): value is Select {\n  return (\n    value != null &&\n    typeof value === `object` &&\n    !Array.isArray(value) &&\n    !(value as any).__refProxy &&\n    !isExpressionLike(value)\n  )\n}\n\nfunction isConditionalSelect(value: unknown): value is ConditionalSelect {\n  return (\n    value instanceof ConditionalSelect ||\n    (value != null &&\n      typeof value === `object` &&\n      (value as { type?: string }).type === `conditionalSelect`)\n  )\n}\n\n/**\n * Checks if two aggregate expressions are equal\n */\nfunction aggregatesEqual(agg1: Aggregate, agg2: Aggregate): boolean {\n  return (\n    agg1.name === agg2.name &&\n    agg1.args.length === agg2.args.length &&\n    agg1.args.every((arg, i) => expressionsEqual(arg, agg2.args[i]))\n  )\n}\n"],"names":["getEqualityValueIdentity","serializeValue","INCLUDES_PUBLIC_KEY","getNamespacedRouteMetadata","getParentContextIdentity","getParentContextValue","groupByOperators","NonAggregateExpressionNotInGroupByError","compileExpression","groupBy","map","attachRouteMetadata","getHavingExpression","filter","toBooleanPredicate","stripInternalCallbackMetadata","UnsupportedAggregateFunctionError","PropRef","AggregateFunctionNotInSelectError","Func","UnknownHavingExpressionTypeError","isExpressionLike","ConditionalSelect","isCaseWhenConditionTrue"],"mappings":"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"}