@tanstack/db 0.0.14 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/dist/cjs/collection.cjs +117 -104
  2. package/dist/cjs/collection.cjs.map +1 -1
  3. package/dist/cjs/collection.d.cts +18 -21
  4. package/dist/cjs/index.cjs +35 -13
  5. package/dist/cjs/index.cjs.map +1 -1
  6. package/dist/cjs/index.d.cts +0 -1
  7. package/dist/cjs/query/builder/functions.cjs +107 -0
  8. package/dist/cjs/query/builder/functions.cjs.map +1 -0
  9. package/dist/cjs/query/builder/functions.d.cts +38 -0
  10. package/dist/cjs/query/builder/index.cjs +499 -0
  11. package/dist/cjs/query/builder/index.cjs.map +1 -0
  12. package/dist/cjs/query/builder/index.d.cts +324 -0
  13. package/dist/cjs/query/builder/ref-proxy.cjs +96 -0
  14. package/dist/cjs/query/builder/ref-proxy.cjs.map +1 -0
  15. package/dist/cjs/query/builder/ref-proxy.d.cts +28 -0
  16. package/dist/cjs/query/builder/types.d.cts +80 -0
  17. package/dist/cjs/query/compiler/evaluators.cjs +261 -0
  18. package/dist/cjs/query/compiler/evaluators.cjs.map +1 -0
  19. package/dist/cjs/query/compiler/evaluators.d.cts +11 -0
  20. package/dist/cjs/query/compiler/group-by.cjs +271 -0
  21. package/dist/cjs/query/compiler/group-by.cjs.map +1 -0
  22. package/dist/cjs/query/compiler/group-by.d.cts +7 -0
  23. package/dist/cjs/query/compiler/index.cjs +181 -0
  24. package/dist/cjs/query/compiler/index.cjs.map +1 -0
  25. package/dist/cjs/query/compiler/index.d.cts +15 -0
  26. package/dist/cjs/query/compiler/joins.cjs +116 -0
  27. package/dist/cjs/query/compiler/joins.cjs.map +1 -0
  28. package/dist/cjs/query/compiler/joins.d.cts +11 -0
  29. package/dist/cjs/query/compiler/order-by.cjs +89 -0
  30. package/dist/cjs/query/compiler/order-by.cjs.map +1 -0
  31. package/dist/cjs/query/compiler/order-by.d.cts +9 -0
  32. package/dist/cjs/query/compiler/select.cjs +57 -0
  33. package/dist/cjs/query/compiler/select.cjs.map +1 -0
  34. package/dist/cjs/query/compiler/select.d.cts +15 -0
  35. package/dist/cjs/query/index.d.cts +6 -5
  36. package/dist/cjs/query/ir.cjs +57 -0
  37. package/dist/cjs/query/ir.cjs.map +1 -0
  38. package/dist/cjs/query/ir.d.cts +81 -0
  39. package/dist/cjs/query/live-query-collection.cjs +224 -0
  40. package/dist/cjs/query/live-query-collection.cjs.map +1 -0
  41. package/dist/cjs/query/live-query-collection.d.cts +124 -0
  42. package/dist/cjs/transactions.cjs +20 -13
  43. package/dist/cjs/transactions.cjs.map +1 -1
  44. package/dist/cjs/transactions.d.cts +10 -1
  45. package/dist/cjs/types.d.cts +13 -0
  46. package/dist/esm/collection.d.ts +18 -21
  47. package/dist/esm/collection.js +118 -105
  48. package/dist/esm/collection.js.map +1 -1
  49. package/dist/esm/index.d.ts +0 -1
  50. package/dist/esm/index.js +34 -12
  51. package/dist/esm/index.js.map +1 -1
  52. package/dist/esm/query/builder/functions.d.ts +38 -0
  53. package/dist/esm/query/builder/functions.js +107 -0
  54. package/dist/esm/query/builder/functions.js.map +1 -0
  55. package/dist/esm/query/builder/index.d.ts +324 -0
  56. package/dist/esm/query/builder/index.js +499 -0
  57. package/dist/esm/query/builder/index.js.map +1 -0
  58. package/dist/esm/query/builder/ref-proxy.d.ts +28 -0
  59. package/dist/esm/query/builder/ref-proxy.js +96 -0
  60. package/dist/esm/query/builder/ref-proxy.js.map +1 -0
  61. package/dist/esm/query/builder/types.d.ts +80 -0
  62. package/dist/esm/query/compiler/evaluators.d.ts +11 -0
  63. package/dist/esm/query/compiler/evaluators.js +261 -0
  64. package/dist/esm/query/compiler/evaluators.js.map +1 -0
  65. package/dist/esm/query/compiler/group-by.d.ts +7 -0
  66. package/dist/esm/query/compiler/group-by.js +271 -0
  67. package/dist/esm/query/compiler/group-by.js.map +1 -0
  68. package/dist/esm/query/compiler/index.d.ts +15 -0
  69. package/dist/esm/query/compiler/index.js +181 -0
  70. package/dist/esm/query/compiler/index.js.map +1 -0
  71. package/dist/esm/query/compiler/joins.d.ts +11 -0
  72. package/dist/esm/query/compiler/joins.js +116 -0
  73. package/dist/esm/query/compiler/joins.js.map +1 -0
  74. package/dist/esm/query/compiler/order-by.d.ts +9 -0
  75. package/dist/esm/query/compiler/order-by.js +89 -0
  76. package/dist/esm/query/compiler/order-by.js.map +1 -0
  77. package/dist/esm/query/compiler/select.d.ts +15 -0
  78. package/dist/esm/query/compiler/select.js +57 -0
  79. package/dist/esm/query/compiler/select.js.map +1 -0
  80. package/dist/esm/query/index.d.ts +6 -5
  81. package/dist/esm/query/ir.d.ts +81 -0
  82. package/dist/esm/query/ir.js +57 -0
  83. package/dist/esm/query/ir.js.map +1 -0
  84. package/dist/esm/query/live-query-collection.d.ts +124 -0
  85. package/dist/esm/query/live-query-collection.js +224 -0
  86. package/dist/esm/query/live-query-collection.js.map +1 -0
  87. package/dist/esm/transactions.d.ts +10 -1
  88. package/dist/esm/transactions.js +20 -13
  89. package/dist/esm/transactions.js.map +1 -1
  90. package/dist/esm/types.d.ts +13 -0
  91. package/package.json +3 -4
  92. package/src/collection.ts +152 -129
  93. package/src/index.ts +0 -1
  94. package/src/query/builder/functions.ts +267 -0
  95. package/src/query/builder/index.ts +648 -0
  96. package/src/query/builder/ref-proxy.ts +156 -0
  97. package/src/query/builder/types.ts +278 -0
  98. package/src/query/compiler/evaluators.ts +315 -0
  99. package/src/query/compiler/group-by.ts +428 -0
  100. package/src/query/compiler/index.ts +276 -0
  101. package/src/query/compiler/joins.ts +228 -0
  102. package/src/query/compiler/order-by.ts +139 -0
  103. package/src/query/compiler/select.ts +173 -0
  104. package/src/query/index.ts +64 -5
  105. package/src/query/ir.ts +128 -0
  106. package/src/query/live-query-collection.ts +509 -0
  107. package/src/transactions.ts +27 -16
  108. package/src/types.ts +15 -0
  109. package/dist/cjs/query/compiled-query.cjs +0 -160
  110. package/dist/cjs/query/compiled-query.cjs.map +0 -1
  111. package/dist/cjs/query/compiled-query.d.cts +0 -20
  112. package/dist/cjs/query/evaluators.cjs +0 -161
  113. package/dist/cjs/query/evaluators.cjs.map +0 -1
  114. package/dist/cjs/query/evaluators.d.cts +0 -14
  115. package/dist/cjs/query/extractors.cjs +0 -122
  116. package/dist/cjs/query/extractors.cjs.map +0 -1
  117. package/dist/cjs/query/extractors.d.cts +0 -22
  118. package/dist/cjs/query/functions.cjs +0 -152
  119. package/dist/cjs/query/functions.cjs.map +0 -1
  120. package/dist/cjs/query/functions.d.cts +0 -21
  121. package/dist/cjs/query/group-by.cjs +0 -88
  122. package/dist/cjs/query/group-by.cjs.map +0 -1
  123. package/dist/cjs/query/group-by.d.cts +0 -40
  124. package/dist/cjs/query/joins.cjs +0 -141
  125. package/dist/cjs/query/joins.cjs.map +0 -1
  126. package/dist/cjs/query/joins.d.cts +0 -14
  127. package/dist/cjs/query/order-by.cjs +0 -185
  128. package/dist/cjs/query/order-by.cjs.map +0 -1
  129. package/dist/cjs/query/order-by.d.cts +0 -3
  130. package/dist/cjs/query/pipeline-compiler.cjs +0 -89
  131. package/dist/cjs/query/pipeline-compiler.cjs.map +0 -1
  132. package/dist/cjs/query/pipeline-compiler.d.cts +0 -10
  133. package/dist/cjs/query/query-builder.cjs +0 -307
  134. package/dist/cjs/query/query-builder.cjs.map +0 -1
  135. package/dist/cjs/query/query-builder.d.cts +0 -225
  136. package/dist/cjs/query/schema.d.cts +0 -100
  137. package/dist/cjs/query/select.cjs +0 -130
  138. package/dist/cjs/query/select.cjs.map +0 -1
  139. package/dist/cjs/query/select.d.cts +0 -3
  140. package/dist/cjs/query/types.d.cts +0 -189
  141. package/dist/cjs/query/utils.cjs +0 -154
  142. package/dist/cjs/query/utils.cjs.map +0 -1
  143. package/dist/cjs/query/utils.d.cts +0 -37
  144. package/dist/cjs/utils.cjs +0 -17
  145. package/dist/cjs/utils.cjs.map +0 -1
  146. package/dist/cjs/utils.d.cts +0 -3
  147. package/dist/esm/query/compiled-query.d.ts +0 -20
  148. package/dist/esm/query/compiled-query.js +0 -160
  149. package/dist/esm/query/compiled-query.js.map +0 -1
  150. package/dist/esm/query/evaluators.d.ts +0 -14
  151. package/dist/esm/query/evaluators.js +0 -161
  152. package/dist/esm/query/evaluators.js.map +0 -1
  153. package/dist/esm/query/extractors.d.ts +0 -22
  154. package/dist/esm/query/extractors.js +0 -122
  155. package/dist/esm/query/extractors.js.map +0 -1
  156. package/dist/esm/query/functions.d.ts +0 -21
  157. package/dist/esm/query/functions.js +0 -152
  158. package/dist/esm/query/functions.js.map +0 -1
  159. package/dist/esm/query/group-by.d.ts +0 -40
  160. package/dist/esm/query/group-by.js +0 -88
  161. package/dist/esm/query/group-by.js.map +0 -1
  162. package/dist/esm/query/joins.d.ts +0 -14
  163. package/dist/esm/query/joins.js +0 -141
  164. package/dist/esm/query/joins.js.map +0 -1
  165. package/dist/esm/query/order-by.d.ts +0 -3
  166. package/dist/esm/query/order-by.js +0 -185
  167. package/dist/esm/query/order-by.js.map +0 -1
  168. package/dist/esm/query/pipeline-compiler.d.ts +0 -10
  169. package/dist/esm/query/pipeline-compiler.js +0 -89
  170. package/dist/esm/query/pipeline-compiler.js.map +0 -1
  171. package/dist/esm/query/query-builder.d.ts +0 -225
  172. package/dist/esm/query/query-builder.js +0 -307
  173. package/dist/esm/query/query-builder.js.map +0 -1
  174. package/dist/esm/query/schema.d.ts +0 -100
  175. package/dist/esm/query/select.d.ts +0 -3
  176. package/dist/esm/query/select.js +0 -130
  177. package/dist/esm/query/select.js.map +0 -1
  178. package/dist/esm/query/types.d.ts +0 -189
  179. package/dist/esm/query/utils.d.ts +0 -37
  180. package/dist/esm/query/utils.js +0 -154
  181. package/dist/esm/query/utils.js.map +0 -1
  182. package/dist/esm/utils.d.ts +0 -3
  183. package/dist/esm/utils.js +0 -17
  184. package/dist/esm/utils.js.map +0 -1
  185. package/src/query/compiled-query.ts +0 -234
  186. package/src/query/evaluators.ts +0 -250
  187. package/src/query/extractors.ts +0 -214
  188. package/src/query/functions.ts +0 -297
  189. package/src/query/group-by.ts +0 -139
  190. package/src/query/joins.ts +0 -260
  191. package/src/query/order-by.ts +0 -264
  192. package/src/query/pipeline-compiler.ts +0 -149
  193. package/src/query/query-builder.ts +0 -902
  194. package/src/query/schema.ts +0 -268
  195. package/src/query/select.ts +0 -208
  196. package/src/query/types.ts +0 -418
  197. package/src/query/utils.ts +0 -245
  198. package/src/utils.ts +0 -15
@@ -1,268 +0,0 @@
1
- import type {
2
- Context,
3
- InputReference,
4
- PropertyReference,
5
- PropertyReferenceString,
6
- Schema,
7
- WildcardReferenceString,
8
- } from "./types.js"
9
- import type { Collection } from "../collection"
10
-
11
- // Identifiers
12
- export type ColumnName<TColumnNames extends string> = TColumnNames
13
-
14
- // JSONLike supports any JSON-compatible value plus Date objects.
15
- export type JSONLike =
16
- | string
17
- | number
18
- | boolean
19
- | Date
20
- | null
21
- | Array<JSONLike>
22
- | { [key: string]: JSONLike }
23
-
24
- // LiteralValue supports common primitives, JS Date, or undefined.
25
- // We exclude strings that start with "@" because they are property references.
26
- export type LiteralValue =
27
- | (string & {})
28
- | number
29
- | boolean
30
- | Date
31
- | null
32
- | undefined
33
-
34
- // `in` and `not in` operators require an array of values
35
- // the other operators require a single literal value
36
- export type ComparatorValue<
37
- T extends Comparator,
38
- TContext extends Context<Schema>,
39
- > = T extends `in` | `not in`
40
- ? Array<LiteralValue>
41
- : PropertyReferenceString<TContext> | LiteralValue
42
-
43
- // These versions are for use with methods on the query builder where we want to
44
- // ensure that the argument is a string that does not start with "@".
45
- // Can be combined with PropertyReference for validating references.
46
- export type SafeString<T extends string> = T extends `@${string}` ? never : T
47
- export type OptionalSafeString<T extends any> = T extends string
48
- ? SafeString<T>
49
- : never
50
- export type LiteralValueWithSafeString<T extends any> =
51
- | (OptionalSafeString<T> & {})
52
- | number
53
- | boolean
54
- | Date
55
- | null
56
- | undefined
57
-
58
- // To force a literal value (which may be arbitrary JSON or a Date), wrap it in an object with the "value" key.
59
- export interface ExplicitLiteral {
60
- value: JSONLike
61
- }
62
-
63
- // Allowed function names (common SQL functions)
64
- export type AllowedFunctionName =
65
- | `DATE`
66
- | `JSON_EXTRACT`
67
- | `JSON_EXTRACT_PATH`
68
- | `UPPER`
69
- | `LOWER`
70
- | `COALESCE`
71
- | `CONCAT`
72
- | `LENGTH`
73
- | `ORDER_INDEX`
74
-
75
- // A function call is represented as a union of objects—each having exactly one key that is one of the allowed function names.
76
- export type FunctionCall<TContext extends Context = Context> = {
77
- [K in AllowedFunctionName]: {
78
- [key in K]: ConditionOperand<TContext> | Array<ConditionOperand<TContext>>
79
- }
80
- }[AllowedFunctionName]
81
-
82
- export type AggregateFunctionName =
83
- | `SUM`
84
- | `COUNT`
85
- | `AVG`
86
- | `MIN`
87
- | `MAX`
88
- | `MEDIAN`
89
- | `MODE`
90
-
91
- export type AggregateFunctionCall<TContext extends Context = Context> = {
92
- [K in AggregateFunctionName]: {
93
- [key in K]: ConditionOperand<TContext> | Array<ConditionOperand<TContext>>
94
- }
95
- }[AggregateFunctionName]
96
-
97
- /**
98
- * An operand in a condition may be:
99
- * - A literal value (LiteralValue)
100
- * - A column reference (a string starting with "@" or an explicit { col: string } object)
101
- * - An explicit literal (to wrap arbitrary JSON or Date values) as { value: ... }
102
- * - A function call (as defined above)
103
- * - An array of operands (for example, for "in" clauses)
104
- */
105
- export type ConditionOperand<
106
- TContext extends Context = Context,
107
- T extends any = any,
108
- > =
109
- | LiteralValue
110
- | PropertyReference<TContext>
111
- | ExplicitLiteral
112
- | FunctionCall<TContext>
113
- | Array<ConditionOperand<TContext, T>>
114
-
115
- // Allowed SQL comparators.
116
- export type Comparator =
117
- | `=`
118
- | `!=`
119
- | `<`
120
- | `<=`
121
- | `>`
122
- | `>=`
123
- | `like`
124
- | `not like`
125
- | `in`
126
- | `not in`
127
- | `is`
128
- | `is not`
129
-
130
- // Logical operators.
131
- export type LogicalOperator = `and` | `or`
132
-
133
- // A simple condition is a tuple: [left operand, comparator, right operand].
134
- export type SimpleCondition<
135
- TContext extends Context = Context,
136
- T extends any = any,
137
- > = [ConditionOperand<TContext, T>, Comparator, ConditionOperand<TContext, T>]
138
-
139
- // A flat composite condition allows all elements to be at the same level:
140
- // [left1, op1, right1, 'and'/'or', left2, op2, right2, ...]
141
- export type FlatCompositeCondition<
142
- TContext extends Context = Context,
143
- T extends any = any,
144
- > = [
145
- ConditionOperand<TContext, T>,
146
- Comparator,
147
- ConditionOperand<TContext, T>,
148
- ...Array<LogicalOperator | ConditionOperand<TContext, T> | Comparator>,
149
- ]
150
-
151
- // A nested composite condition combines conditions with logical operators
152
- // The first element can be a SimpleCondition or FlatCompositeCondition
153
- // followed by logical operators and more conditions
154
- export type NestedCompositeCondition<
155
- TContext extends Context = Context,
156
- T extends any = any,
157
- > = [
158
- SimpleCondition<TContext, T> | FlatCompositeCondition<TContext, T>,
159
- ...Array<
160
- | LogicalOperator
161
- | SimpleCondition<TContext, T>
162
- | FlatCompositeCondition<TContext, T>
163
- >,
164
- ]
165
-
166
- // A condition is either a simple condition or a composite condition (flat or nested).
167
- export type Condition<
168
- TContext extends Context = Context,
169
- T extends any = any,
170
- > =
171
- | SimpleCondition<TContext, T>
172
- | FlatCompositeCondition<TContext, T>
173
- | NestedCompositeCondition<TContext, T>
174
-
175
- // A join clause includes a join type, the table to join, an optional alias,
176
- // an "on" condition, and an optional "where" clause specific to the join.
177
- export interface JoinClause<TContext extends Context = Context> {
178
- type: `inner` | `left` | `right` | `full` | `cross`
179
- from: string
180
- as?: string
181
- on: Condition<TContext>
182
- }
183
-
184
- // The orderBy clause can be a string, an object mapping a column to "asc" or "desc",
185
- // or an array of such items.
186
- export type OrderBy<TContext extends Context = Context> =
187
- | PropertyReferenceString<TContext>
188
- | { [column in PropertyReferenceString<TContext>]?: `asc` | `desc` }
189
- | Record<PropertyReferenceString<TContext>, `asc` | `desc`>
190
- | Array<
191
- | PropertyReferenceString<TContext>
192
- | { [column in PropertyReferenceString<TContext>]?: `asc` | `desc` }
193
- >
194
-
195
- export type Select<TContext extends Context = Context> =
196
- | PropertyReferenceString<TContext>
197
- | {
198
- [alias: string]:
199
- | PropertyReference<TContext>
200
- | FunctionCall<TContext>
201
- | AggregateFunctionCall<TContext>
202
- }
203
- | WildcardReferenceString<TContext>
204
- | SelectCallback<TContext>
205
-
206
- export type SelectCallback<TContext extends Context = Context> = (
207
- context: TContext extends { schema: infer S } ? S : any
208
- ) => any
209
-
210
- export type As<_TContext extends Context = Context> = string
211
-
212
- export type From<TContext extends Context = Context> = InputReference<{
213
- baseSchema: TContext[`baseSchema`]
214
- schema: TContext[`baseSchema`]
215
- }>
216
-
217
- export type WhereCallback<TContext extends Context = Context> = (
218
- context: TContext extends { schema: infer S } ? S : any
219
- ) => boolean
220
-
221
- export type Where<TContext extends Context = Context> = Array<
222
- Condition<TContext> | WhereCallback<TContext>
223
- >
224
-
225
- // Having is the same implementation as a where clause, its just run after the group by
226
- export type Having<TContext extends Context = Context> = Where<TContext>
227
-
228
- export type GroupBy<TContext extends Context = Context> =
229
- | PropertyReference<TContext>
230
- | Array<PropertyReference<TContext>>
231
-
232
- export type Limit<_TContext extends Context = Context> = number
233
-
234
- export type Offset<_TContext extends Context = Context> = number
235
-
236
- export interface BaseQuery<TContext extends Context = Context> {
237
- // The select clause is an array of either plain strings or objects mapping alias names
238
- // to expressions. Plain strings starting with "@" denote column references.
239
- // Plain string "@*" denotes all columns from all tables.
240
- // Plain string "@table.*" denotes all columns from a specific table.
241
- select?: Array<Select<TContext>>
242
- as?: As<TContext>
243
- from: From<TContext>
244
- join?: Array<JoinClause<TContext>>
245
- where?: Where<TContext>
246
- groupBy?: GroupBy<TContext>
247
- having?: Having<TContext>
248
- orderBy?: OrderBy<TContext>
249
- limit?: Limit<TContext>
250
- offset?: Offset<TContext>
251
- }
252
-
253
- // The top-level query interface.
254
- export interface Query<TContext extends Context = Context>
255
- extends BaseQuery<TContext> {
256
- with?: Array<WithQuery<TContext>>
257
- collections?: {
258
- [K: string]: Collection<any>
259
- }
260
- }
261
-
262
- // A WithQuery is a query that is used as a Common Table Expression (CTE)
263
- // It cannot be keyed and must have an alias (as)
264
- // There is no support for recursive CTEs
265
- export interface WithQuery<TContext extends Context = Context>
266
- extends BaseQuery<TContext> {
267
- as: string
268
- }
@@ -1,208 +0,0 @@
1
- import { map } from "@electric-sql/d2mini"
2
- import {
3
- evaluateOperandOnNamespacedRow,
4
- extractValueFromNamespacedRow,
5
- } from "./extractors"
6
- import type { ConditionOperand, Query, SelectCallback } from "./schema"
7
- import type { KeyedStream, NamespacedAndKeyedStream } from "../types"
8
-
9
- export function processSelect(
10
- pipeline: NamespacedAndKeyedStream,
11
- query: Query,
12
- mainTableAlias: string,
13
- inputs: Record<string, KeyedStream>
14
- ): KeyedStream {
15
- return pipeline.pipe(
16
- map(([key, namespacedRow]) => {
17
- const result: Record<string, unknown> = {}
18
-
19
- // Check if this is a grouped result (has no nested table structure)
20
- // If it's a grouped result, we need to handle it differently
21
- const isGroupedResult =
22
- query.groupBy &&
23
- Object.keys(namespacedRow).some(
24
- (namespaceKey) =>
25
- !Object.keys(inputs).includes(namespaceKey) &&
26
- typeof namespacedRow[namespaceKey] !== `object`
27
- )
28
-
29
- if (!query.select) {
30
- throw new Error(`Cannot process missing SELECT clause`)
31
- }
32
-
33
- for (const item of query.select) {
34
- // Handle callback functions
35
- if (typeof item === `function`) {
36
- const callback = item as SelectCallback
37
- const callbackResult = callback(namespacedRow)
38
-
39
- // If the callback returns an object, merge its properties into the result
40
- if (
41
- callbackResult &&
42
- typeof callbackResult === `object` &&
43
- !Array.isArray(callbackResult)
44
- ) {
45
- Object.assign(result, callbackResult)
46
- } else {
47
- // If the callback returns a primitive value, we can't merge it
48
- // This would need a specific key, but since we don't have one, we'll skip it
49
- // In practice, select callbacks should return objects with keys
50
- console.warn(
51
- `SelectCallback returned a non-object value. SelectCallbacks should return objects with key-value pairs.`
52
- )
53
- }
54
- continue
55
- }
56
-
57
- if (typeof item === `string`) {
58
- // Handle wildcard select - all columns from all tables
59
- if ((item as string) === `@*`) {
60
- // For grouped results, just return the row as is
61
- if (isGroupedResult) {
62
- Object.assign(result, namespacedRow)
63
- } else {
64
- // Extract all columns from all tables
65
- Object.assign(
66
- result,
67
- extractAllColumnsFromAllTables(namespacedRow)
68
- )
69
- }
70
- continue
71
- }
72
-
73
- // Handle @table.* syntax - all columns from a specific table
74
- if (
75
- (item as string).startsWith(`@`) &&
76
- (item as string).endsWith(`.*`)
77
- ) {
78
- const tableAlias = (item as string).slice(1, -2) // Remove the '@' and '.*' parts
79
-
80
- // For grouped results, check if we have columns from this table
81
- if (isGroupedResult) {
82
- // In grouped results, we don't have the nested structure anymore
83
- // So we can't extract by table. Just continue to the next item.
84
- continue
85
- } else {
86
- // Extract all columns from the specified table
87
- Object.assign(
88
- result,
89
- extractAllColumnsFromTable(namespacedRow, tableAlias)
90
- )
91
- }
92
- continue
93
- }
94
-
95
- // Handle simple column references like "@table.column" or "@column"
96
- if ((item as string).startsWith(`@`)) {
97
- const columnRef = (item as string).substring(1)
98
- const alias = columnRef
99
-
100
- // For grouped results, check if the column is directly in the row first
101
- if (isGroupedResult && columnRef in namespacedRow) {
102
- result[alias] = namespacedRow[columnRef]
103
- } else {
104
- // Extract the value from the nested structure
105
- result[alias] = extractValueFromNamespacedRow(
106
- namespacedRow,
107
- columnRef,
108
- mainTableAlias,
109
- undefined
110
- )
111
- }
112
-
113
- // If the alias contains a dot (table.column),
114
- // use just the column part as the field name
115
- if (alias.includes(`.`)) {
116
- const columnName = alias.split(`.`)[1]
117
- result[columnName!] = result[alias]
118
- delete result[alias]
119
- }
120
- }
121
- } else {
122
- // Handle aliased columns like { alias: "@column_name" }
123
- for (const [alias, expr] of Object.entries(item)) {
124
- if (typeof expr === `string` && (expr as string).startsWith(`@`)) {
125
- const columnRef = (expr as string).substring(1)
126
-
127
- // For grouped results, check if the column is directly in the row first
128
- if (isGroupedResult && columnRef in namespacedRow) {
129
- result[alias] = namespacedRow[columnRef]
130
- } else {
131
- // Extract the value from the nested structure
132
- result[alias] = extractValueFromNamespacedRow(
133
- namespacedRow,
134
- columnRef,
135
- mainTableAlias,
136
- undefined
137
- )
138
- }
139
- } else if (typeof expr === `object`) {
140
- // For grouped results, the aggregate results are already in the row
141
- if (isGroupedResult && alias in namespacedRow) {
142
- result[alias] = namespacedRow[alias]
143
- } else if ((expr as { ORDER_INDEX: unknown }).ORDER_INDEX) {
144
- result[alias] = namespacedRow[mainTableAlias]![alias]
145
- } else {
146
- // This might be a function call
147
- result[alias] = evaluateOperandOnNamespacedRow(
148
- namespacedRow,
149
- expr as ConditionOperand,
150
- mainTableAlias,
151
- undefined
152
- )
153
- }
154
- }
155
- }
156
- }
157
- }
158
-
159
- return [key, result] as [string, typeof result]
160
- })
161
- )
162
- }
163
-
164
- // Helper function to extract all columns from all tables in a nested row
165
- function extractAllColumnsFromAllTables(
166
- namespacedRow: Record<string, unknown>
167
- ): Record<string, unknown> {
168
- const result: Record<string, unknown> = {}
169
-
170
- // Process each table in the nested row
171
- for (const [tableAlias, tableData] of Object.entries(namespacedRow)) {
172
- if (tableData && typeof tableData === `object`) {
173
- // Add all columns from this table to the result
174
- // If there are column name conflicts, the last table's columns will overwrite previous ones
175
- Object.assign(
176
- result,
177
- extractAllColumnsFromTable(namespacedRow, tableAlias)
178
- )
179
- }
180
- }
181
-
182
- return result
183
- }
184
-
185
- // Helper function to extract all columns from a table in a nested row
186
- function extractAllColumnsFromTable(
187
- namespacedRow: Record<string, unknown>,
188
- tableAlias: string
189
- ): Record<string, unknown> {
190
- const result: Record<string, unknown> = {}
191
-
192
- // Get the table data
193
- const tableData = namespacedRow[tableAlias] as
194
- | Record<string, unknown>
195
- | null
196
- | undefined
197
-
198
- if (!tableData || typeof tableData !== `object`) {
199
- return result
200
- }
201
-
202
- // Add all columns from the table to the result
203
- for (const [columnName, value] of Object.entries(tableData)) {
204
- result[columnName] = value
205
- }
206
-
207
- return result
208
- }