MCPcopy Index your code
hub / github.com/TanStack/db / processGroupBy

Function processGroupBy

packages/db/src/query/compiler/group-by.ts:127–474  ·  view source on GitHub ↗
(
  pipeline: NamespacedAndKeyedStream,
  groupByClause: GroupBy,
  havingClauses?: Array<Having>,
  selectClause?: Select,
  fnHavingClauses?: Array<(row: any) => any>,
  aggregateCollectionId?: string,
  mainSource?: string,
)

Source from the content-addressed store, hash-verified

125 * Works with the new $selected structure from early SELECT processing
126 */
127export function processGroupBy(
128 pipeline: NamespacedAndKeyedStream,
129 groupByClause: GroupBy,
130 havingClauses?: Array<Having>,
131 selectClause?: Select,
132 fnHavingClauses?: Array<(row: any) => any>,
133 aggregateCollectionId?: string,
134 mainSource?: string,
135): NamespacedAndKeyedStream {
136 const virtualAggregates: Record<string, any> = {
137 [VIRTUAL_SYNCED_KEY]: {
138 preMap: ([, row]: [string, NamespacedRow]) =>
139 getRowVirtualMetadata(row).synced,
140 reduce: (values: Array<[boolean, number]>) => {
141 for (const [isSynced, multiplicity] of values) {
142 if (!isSynced && multiplicity > 0) {
143 return false
144 }
145 }
146 return true
147 },
148 },
149 [VIRTUAL_HAS_LOCAL_KEY]: {
150 preMap: ([, row]: [string, NamespacedRow]) =>
151 getRowVirtualMetadata(row).hasLocal,
152 reduce: (values: Array<[boolean, number]>) => {
153 for (const [isLocal, multiplicity] of values) {
154 if (isLocal && multiplicity > 0) {
155 return true
156 }
157 }
158 return false
159 },
160 },
161 }
162
163 // Handle empty GROUP BY (single-group aggregation)
164 if (groupByClause.length === 0) {
165 // For single-group aggregation, create a single group with all data
166 const aggregates: Record<string, any> = virtualAggregates
167
168 // Expressions that wrap aggregates (e.g. coalesce(count(...), 0)).
169 // Keys are the original SELECT aliases; values are pre-compiled evaluators
170 // over the transformed (aggregate-free) expression.
171 const wrappedAggExprs: Record<string, (data: any) => any> = {}
172 const aggCounter = { value: 0 }
173
174 if (selectClause) {
175 // Scan the SELECT clause for aggregate functions
176 for (const [alias, expr] of Object.entries(selectClause)) {
177 if (expr.type === `agg`) {
178 aggregates[alias] = getAggregateFunction(expr)
179 } else if (containsAggregate(expr)) {
180 const { transformed, extracted } = extractAndReplaceAggregates(
181 expr as SelectValueExpression,
182 aggCounter,
183 )
184 for (const [syntheticAlias, aggExpr] of Object.entries(extracted)) {

Callers 1

compileQueryFunction · 0.85

Calls 15

groupByFunction · 0.90
mapFunction · 0.90
serializeValueFunction · 0.90
filterFunction · 0.90
getRowVirtualMetadataFunction · 0.85
getAggregateFunctionFunction · 0.85
containsAggregateFunction · 0.85
getHavingExpressionFunction · 0.85
replaceAggregatesByRefsFunction · 0.85

Tested by

no test coverage detected