pqb 0.0.1

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 (122) hide show
  1. package/dist/index.d.ts +3630 -0
  2. package/dist/index.esm.js +4587 -0
  3. package/dist/index.esm.js.map +1 -0
  4. package/dist/index.js +4691 -0
  5. package/dist/index.js.map +1 -0
  6. package/package.json +59 -0
  7. package/rollup.config.js +35 -0
  8. package/src/adapter.test.ts +10 -0
  9. package/src/adapter.ts +171 -0
  10. package/src/columnSchema/array.ts +21 -0
  11. package/src/columnSchema/boolean.ts +10 -0
  12. package/src/columnSchema/columnType.test.ts +129 -0
  13. package/src/columnSchema/columnType.ts +77 -0
  14. package/src/columnSchema/columnTypes.ts +145 -0
  15. package/src/columnSchema/columnsSchema.test.ts +32 -0
  16. package/src/columnSchema/columnsSchema.ts +100 -0
  17. package/src/columnSchema/commonMethods.ts +130 -0
  18. package/src/columnSchema/dateTime.ts +104 -0
  19. package/src/columnSchema/enum.ts +13 -0
  20. package/src/columnSchema/index.ts +11 -0
  21. package/src/columnSchema/json/array.ts +55 -0
  22. package/src/columnSchema/json/discriminatedUnion.ts +91 -0
  23. package/src/columnSchema/json/enum.ts +29 -0
  24. package/src/columnSchema/json/instanceOf.ts +16 -0
  25. package/src/columnSchema/json/intersection.ts +23 -0
  26. package/src/columnSchema/json/lazy.ts +22 -0
  27. package/src/columnSchema/json/literal.ts +12 -0
  28. package/src/columnSchema/json/map.ts +29 -0
  29. package/src/columnSchema/json/nativeEnum.ts +30 -0
  30. package/src/columnSchema/json/nullable.ts +33 -0
  31. package/src/columnSchema/json/nullish.ts +30 -0
  32. package/src/columnSchema/json/object.ts +206 -0
  33. package/src/columnSchema/json/optional.ts +28 -0
  34. package/src/columnSchema/json/record.ts +40 -0
  35. package/src/columnSchema/json/scalarTypes.ts +117 -0
  36. package/src/columnSchema/json/set.ts +34 -0
  37. package/src/columnSchema/json/tuple.ts +40 -0
  38. package/src/columnSchema/json/typeBase.ts +202 -0
  39. package/src/columnSchema/json/union.ts +16 -0
  40. package/src/columnSchema/json.ts +64 -0
  41. package/src/columnSchema/number.ts +122 -0
  42. package/src/columnSchema/string.ts +222 -0
  43. package/src/columnSchema/utils.ts +27 -0
  44. package/src/common.ts +86 -0
  45. package/src/db.test.ts +67 -0
  46. package/src/db.ts +212 -0
  47. package/src/errors.ts +7 -0
  48. package/src/index.ts +18 -0
  49. package/src/operators.test.ts +608 -0
  50. package/src/operators.ts +177 -0
  51. package/src/query.ts +292 -0
  52. package/src/queryDataUtils.ts +50 -0
  53. package/src/queryMethods/aggregate.test.ts +583 -0
  54. package/src/queryMethods/aggregate.ts +878 -0
  55. package/src/queryMethods/callbacks.test.ts +69 -0
  56. package/src/queryMethods/callbacks.ts +55 -0
  57. package/src/queryMethods/clear.test.ts +64 -0
  58. package/src/queryMethods/clear.ts +58 -0
  59. package/src/queryMethods/columnInfo.test.ts +45 -0
  60. package/src/queryMethods/columnInfo.ts +67 -0
  61. package/src/queryMethods/delete.test.ts +135 -0
  62. package/src/queryMethods/delete.ts +50 -0
  63. package/src/queryMethods/for.test.ts +57 -0
  64. package/src/queryMethods/for.ts +99 -0
  65. package/src/queryMethods/from.test.ts +66 -0
  66. package/src/queryMethods/from.ts +58 -0
  67. package/src/queryMethods/get.test.ts +66 -0
  68. package/src/queryMethods/get.ts +88 -0
  69. package/src/queryMethods/having.test.ts +247 -0
  70. package/src/queryMethods/having.ts +99 -0
  71. package/src/queryMethods/insert.test.ts +555 -0
  72. package/src/queryMethods/insert.ts +453 -0
  73. package/src/queryMethods/join.test.ts +150 -0
  74. package/src/queryMethods/join.ts +508 -0
  75. package/src/queryMethods/json.test.ts +398 -0
  76. package/src/queryMethods/json.ts +259 -0
  77. package/src/queryMethods/log.test.ts +172 -0
  78. package/src/queryMethods/log.ts +123 -0
  79. package/src/queryMethods/queryMethods.test.ts +629 -0
  80. package/src/queryMethods/queryMethods.ts +428 -0
  81. package/src/queryMethods/select.test.ts +479 -0
  82. package/src/queryMethods/select.ts +249 -0
  83. package/src/queryMethods/then.ts +236 -0
  84. package/src/queryMethods/transaction.test.ts +66 -0
  85. package/src/queryMethods/transaction.ts +66 -0
  86. package/src/queryMethods/union.test.ts +59 -0
  87. package/src/queryMethods/union.ts +89 -0
  88. package/src/queryMethods/update.test.ts +417 -0
  89. package/src/queryMethods/update.ts +350 -0
  90. package/src/queryMethods/upsert.test.ts +56 -0
  91. package/src/queryMethods/upsert.ts +43 -0
  92. package/src/queryMethods/where.test.ts +1594 -0
  93. package/src/queryMethods/where.ts +450 -0
  94. package/src/queryMethods/window.test.ts +66 -0
  95. package/src/queryMethods/window.ts +108 -0
  96. package/src/queryMethods/with.test.ts +191 -0
  97. package/src/queryMethods/with.ts +92 -0
  98. package/src/quote.ts +36 -0
  99. package/src/relations.ts +194 -0
  100. package/src/sql/aggregate.ts +80 -0
  101. package/src/sql/columnInfo.ts +22 -0
  102. package/src/sql/common.ts +42 -0
  103. package/src/sql/delete.ts +41 -0
  104. package/src/sql/distinct.ts +19 -0
  105. package/src/sql/fromAndAs.ts +51 -0
  106. package/src/sql/having.ts +140 -0
  107. package/src/sql/index.ts +2 -0
  108. package/src/sql/insert.ts +102 -0
  109. package/src/sql/join.ts +242 -0
  110. package/src/sql/orderBy.ts +41 -0
  111. package/src/sql/select.ts +153 -0
  112. package/src/sql/toSql.ts +153 -0
  113. package/src/sql/truncate.ts +13 -0
  114. package/src/sql/types.ts +355 -0
  115. package/src/sql/update.ts +62 -0
  116. package/src/sql/where.ts +314 -0
  117. package/src/sql/window.ts +38 -0
  118. package/src/sql/with.ts +32 -0
  119. package/src/test-utils.ts +172 -0
  120. package/src/utils.ts +140 -0
  121. package/tsconfig.build.json +6 -0
  122. package/tsconfig.json +8 -0
@@ -0,0 +1,450 @@
1
+ import { Query, QueryBase, SelectableBase, WithDataBase } from '../query';
2
+ import { ColumnOperators, QueryData } from '../sql';
3
+ import { pushQueryArray, pushQueryValue } from '../queryDataUtils';
4
+ import { RawExpression } from '../common';
5
+ import { getClonedQueryData, MaybeArray } from '../utils';
6
+ import { JoinArgs, JoinCallback, JoinCallbackArg } from './join';
7
+ import { RelationsBase } from '../relations';
8
+
9
+ export type WhereArg<T extends QueryBase> =
10
+ | (Omit<
11
+ {
12
+ [K in keyof T['selectable']]?:
13
+ | T['selectable'][K]['column']['type']
14
+ | null
15
+ | ColumnOperators<T['selectable'], K>
16
+ | RawExpression;
17
+ },
18
+ 'NOT' | 'OR' | 'IN' | 'EXISTS'
19
+ > & {
20
+ NOT?: MaybeArray<WhereArg<T>>;
21
+ OR?: MaybeArray<WhereArg<T>>[];
22
+ IN?: MaybeArray<{
23
+ columns: (keyof T['selectable'])[];
24
+ values: unknown[][] | Query | RawExpression;
25
+ }>;
26
+ EXISTS?: MaybeArray<JoinArgs<T> | JoinCallbackArg<T>>;
27
+ })
28
+ | QueryBase
29
+ | RawExpression
30
+ | ((q: WhereQueryBuilder<T>) => WhereQueryBuilder);
31
+
32
+ export type WhereInColumn<T extends QueryBase> =
33
+ | keyof T['selectable']
34
+ | [keyof T['selectable'], ...(keyof T['selectable'])[]];
35
+
36
+ export type WhereInValues<
37
+ T extends QueryBase,
38
+ Column extends WhereInColumn<T>,
39
+ > = Column extends keyof T['selectable']
40
+ ? T['selectable'][Column]['column']['type'][] | Query | RawExpression
41
+ :
42
+ | ({
43
+ [I in keyof Column]: Column[I] extends keyof T['selectable']
44
+ ? T['selectable'][Column[I]]['column']['type']
45
+ : never;
46
+ } & {
47
+ length: Column extends { length: number } ? Column['length'] : never;
48
+ })[]
49
+ | Query
50
+ | RawExpression;
51
+
52
+ export type WhereResult<T extends QueryBase> = Omit<T, 'hasWhere'> & {
53
+ hasWhere: true;
54
+ };
55
+
56
+ export type WhereInArg<T extends Pick<Query, 'selectable'>> = {
57
+ [K in keyof T['selectable']]?:
58
+ | T['selectable'][K]['column']['type'][]
59
+ | Query
60
+ | RawExpression;
61
+ };
62
+
63
+ export const addWhere = <T extends Where>(
64
+ q: T,
65
+ args: WhereArg<T>[],
66
+ ): WhereResult<T> => {
67
+ return pushQueryArray(q, 'and', args) as unknown as WhereResult<T>;
68
+ };
69
+
70
+ export const addWhereNot = <T extends QueryBase>(
71
+ q: T,
72
+ args: WhereArg<T>[],
73
+ ): WhereResult<T> => {
74
+ return pushQueryValue(q, 'and', {
75
+ NOT: args,
76
+ }) as unknown as WhereResult<T>;
77
+ };
78
+
79
+ export const addOr = <T extends QueryBase>(
80
+ q: T,
81
+ args: WhereArg<T>[],
82
+ ): WhereResult<T> => {
83
+ return pushQueryArray(
84
+ q,
85
+ 'or',
86
+ args.map((item) => [item]),
87
+ ) as unknown as WhereResult<T>;
88
+ };
89
+
90
+ export const addOrNot = <T extends QueryBase>(
91
+ q: T,
92
+ args: WhereArg<T>[],
93
+ ): WhereResult<T> => {
94
+ return pushQueryArray(
95
+ q,
96
+ 'or',
97
+ args.map((item) => [{ NOT: item }]),
98
+ ) as unknown as WhereResult<T>;
99
+ };
100
+
101
+ export const addWhereIn = <T extends QueryBase>(
102
+ q: T,
103
+ and: boolean,
104
+ arg: unknown,
105
+ values: unknown[] | unknown[][] | Query | RawExpression | undefined,
106
+ not?: boolean,
107
+ ): WhereResult<T> => {
108
+ const op = not ? 'notIn' : 'in';
109
+
110
+ let item;
111
+ if (values) {
112
+ if (Array.isArray(arg)) {
113
+ item = {
114
+ IN: {
115
+ columns: arg,
116
+ values,
117
+ },
118
+ };
119
+ if (not) item = { NOT: item };
120
+ } else {
121
+ item = { [arg as string]: { [op]: values } };
122
+ }
123
+ } else {
124
+ item = {} as Record<string, { in: unknown[] }>;
125
+ for (const key in arg as Record<string, unknown[]>) {
126
+ item[key] = { [op as 'in']: (arg as Record<string, unknown[]>)[key] };
127
+ }
128
+ }
129
+
130
+ if (and) {
131
+ pushQueryValue(q, 'and', item);
132
+ } else {
133
+ pushQueryValue(q, 'or', [item]);
134
+ }
135
+
136
+ return q as unknown as WhereResult<T>;
137
+ };
138
+
139
+ export abstract class Where implements QueryBase {
140
+ abstract clone<T extends this>(this: T): T;
141
+ abstract selectable: SelectableBase;
142
+ abstract relations: RelationsBase;
143
+ abstract withData: WithDataBase;
144
+ abstract __model: Query;
145
+
146
+ query = {} as QueryData;
147
+ table?: string;
148
+ tableAlias?: string;
149
+
150
+ where<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T> {
151
+ return this.clone()._where(...args);
152
+ }
153
+
154
+ _where<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T> {
155
+ return addWhere(this, args);
156
+ }
157
+
158
+ whereNot<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T> {
159
+ return this.clone()._whereNot(...args);
160
+ }
161
+
162
+ _whereNot<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T> {
163
+ return addWhereNot(this, args);
164
+ }
165
+
166
+ and<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T> {
167
+ return this.where(...args);
168
+ }
169
+
170
+ _and<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T> {
171
+ return this._where(...args);
172
+ }
173
+
174
+ andNot<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T> {
175
+ return this.whereNot(...args);
176
+ }
177
+
178
+ _andNot<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T> {
179
+ return this._whereNot(...args);
180
+ }
181
+
182
+ or<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T> {
183
+ return this.clone()._or(...args);
184
+ }
185
+
186
+ _or<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T> {
187
+ return addOr(this, args);
188
+ }
189
+
190
+ orNot<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T> {
191
+ return this.clone()._orNot(...args);
192
+ }
193
+
194
+ _orNot<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T> {
195
+ return addOrNot(this, args);
196
+ }
197
+
198
+ whereIn<T extends Where, Column extends WhereInColumn<T>>(
199
+ this: T,
200
+ column: Column,
201
+ values: WhereInValues<T, Column>,
202
+ ): T;
203
+ whereIn<T extends Where>(this: T, arg: WhereInArg<T>): T;
204
+ whereIn<T extends Where>(
205
+ this: T,
206
+ arg: unknown | unknown[],
207
+ values?: unknown[] | unknown[][] | Query | RawExpression,
208
+ ): WhereResult<T> {
209
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
210
+ return this.clone()._whereIn(
211
+ arg as any,
212
+ values as any,
213
+ ) as unknown as WhereResult<T>;
214
+ }
215
+
216
+ _whereIn<T extends Where, Column extends WhereInColumn<T>>(
217
+ this: T,
218
+ column: Column,
219
+ values: WhereInValues<T, Column>,
220
+ ): WhereResult<T>;
221
+ _whereIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
222
+ _whereIn<T extends Where>(
223
+ this: T,
224
+ arg: unknown,
225
+ values?: unknown[] | unknown[][] | Query | RawExpression,
226
+ ): WhereResult<T> {
227
+ return addWhereIn(this, true, arg, values);
228
+ }
229
+
230
+ orWhereIn<T extends Where, Column extends WhereInColumn<T>>(
231
+ this: T,
232
+ column: Column,
233
+ values: WhereInValues<T, Column>,
234
+ ): WhereResult<T>;
235
+ orWhereIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
236
+ orWhereIn<T extends Where>(
237
+ this: T,
238
+ arg: unknown | unknown[],
239
+ values?: unknown[] | unknown[][] | Query | RawExpression,
240
+ ): WhereResult<T> {
241
+ return this.clone()._orWhereIn(
242
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
243
+ arg as any,
244
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
245
+ values as any,
246
+ ) as unknown as WhereResult<T>;
247
+ }
248
+
249
+ _orWhereIn<T extends Where, Column extends WhereInColumn<T>>(
250
+ this: T,
251
+ column: Column,
252
+ values: WhereInValues<T, Column>,
253
+ ): WhereResult<T>;
254
+ _orWhereIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
255
+ _orWhereIn<T extends Where>(
256
+ this: T,
257
+ arg: unknown,
258
+ values?: unknown[] | unknown[][] | Query | RawExpression,
259
+ ): WhereResult<T> {
260
+ return addWhereIn(this, false, arg, values);
261
+ }
262
+
263
+ whereNotIn<T extends Where, Column extends WhereInColumn<T>>(
264
+ this: T,
265
+ column: Column,
266
+ values: WhereInValues<T, Column>,
267
+ ): WhereResult<T>;
268
+ whereNotIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
269
+ whereNotIn<T extends Where>(
270
+ this: T,
271
+ arg: unknown | unknown[],
272
+ values?: unknown[] | unknown[][] | Query | RawExpression,
273
+ ): WhereResult<T> {
274
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
275
+ return this.clone()._whereNotIn(arg as any, values as any);
276
+ }
277
+
278
+ _whereNotIn<T extends Where, Column extends WhereInColumn<T>>(
279
+ this: T,
280
+ column: Column,
281
+ values: WhereInValues<T, Column>,
282
+ ): WhereResult<T>;
283
+ _whereNotIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
284
+ _whereNotIn<T extends Where>(
285
+ this: T,
286
+ arg: unknown,
287
+ values?: unknown[] | unknown[][] | Query | RawExpression,
288
+ ): WhereResult<T> {
289
+ return addWhereIn(this, true, arg, values, true);
290
+ }
291
+
292
+ orWhereNotIn<T extends Where, Column extends WhereInColumn<T>>(
293
+ this: T,
294
+ column: Column,
295
+ values: WhereInValues<T, Column>,
296
+ ): WhereResult<T>;
297
+ orWhereNotIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
298
+ orWhereNotIn<T extends Where>(
299
+ this: T,
300
+ arg: unknown | unknown[],
301
+ values?: unknown[] | unknown[][] | Query | RawExpression,
302
+ ): WhereResult<T> {
303
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
304
+ return this.clone()._orWhereNotIn(arg as any, values as any);
305
+ }
306
+
307
+ _orWhereNotIn<T extends Where, Column extends WhereInColumn<T>>(
308
+ this: T,
309
+ column: Column,
310
+ values: WhereInValues<T, Column>,
311
+ ): WhereResult<T>;
312
+ _orWhereNotIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
313
+ _orWhereNotIn<T extends Where>(
314
+ this: T,
315
+ arg: unknown,
316
+ values?: unknown[] | unknown[][] | Query | RawExpression,
317
+ ): WhereResult<T> {
318
+ return addWhereIn(this, false, arg, values, true);
319
+ }
320
+
321
+ whereExists<T extends Where, Args extends JoinArgs<T>>(
322
+ this: T,
323
+ ...args: Args
324
+ ): WhereResult<T>;
325
+ whereExists<T extends Where, Arg extends JoinCallbackArg<T>>(
326
+ this: T,
327
+ arg: Arg,
328
+ cb: JoinCallback<T, Arg>,
329
+ ): WhereResult<T>;
330
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
331
+ whereExists(...args: any) {
332
+ return this.clone()._whereExists(...args);
333
+ }
334
+ _whereExists<T extends Where, Args extends JoinArgs<T>>(
335
+ this: T,
336
+ ...args: Args
337
+ ): WhereResult<T>;
338
+ _whereExists<T extends Where, Arg extends JoinCallbackArg<T>>(
339
+ this: T,
340
+ arg: Arg,
341
+ cb: JoinCallback<T, Arg>,
342
+ ): WhereResult<T>;
343
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
344
+ _whereExists(this: Where, ...args: any) {
345
+ return this._where({ EXISTS: args });
346
+ }
347
+
348
+ orWhereExists<T extends Where, Args extends JoinArgs<T>>(
349
+ this: T,
350
+ ...args: Args
351
+ ): WhereResult<T>;
352
+ orWhereExists<T extends Where, Arg extends JoinCallbackArg<T>>(
353
+ this: T,
354
+ arg: Arg,
355
+ cb: JoinCallback<T, Arg>,
356
+ ): WhereResult<T>;
357
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
358
+ orWhereExists(...args: any) {
359
+ return this.clone()._orWhereExists(...args);
360
+ }
361
+ _orWhereExists<T extends Where, Args extends JoinArgs<T>>(
362
+ this: T,
363
+ ...args: Args
364
+ ): WhereResult<T>;
365
+ _orWhereExists<T extends Where, Arg extends JoinCallbackArg<T>>(
366
+ this: T,
367
+ arg: Arg,
368
+ cb: JoinCallback<T, Arg>,
369
+ ): WhereResult<T>;
370
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
371
+ _orWhereExists(this: Where, ...args: any) {
372
+ return this._or({ EXISTS: args });
373
+ }
374
+
375
+ whereNotExists<T extends Where, Args extends JoinArgs<T>>(
376
+ this: T,
377
+ ...args: Args
378
+ ): WhereResult<T>;
379
+ whereNotExists<T extends Where, Arg extends JoinCallbackArg<T>>(
380
+ this: T,
381
+ arg: Arg,
382
+ cb: JoinCallback<T, Arg>,
383
+ ): WhereResult<T>;
384
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
385
+ whereNotExists(...args: any) {
386
+ return this.clone()._whereNotExists(...args);
387
+ }
388
+ _whereNotExists<T extends Where, Args extends JoinArgs<T>>(
389
+ this: T,
390
+ ...args: Args
391
+ ): WhereResult<T>;
392
+ _whereNotExists<T extends Where, Arg extends JoinCallbackArg<T>>(
393
+ this: T,
394
+ arg: Arg,
395
+ cb: JoinCallback<T, Arg>,
396
+ ): WhereResult<T>;
397
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
398
+ _whereNotExists(this: Where, ...args: any) {
399
+ return this._whereNot({ EXISTS: args });
400
+ }
401
+
402
+ orWhereNotExists<T extends Where, Args extends JoinArgs<T>>(
403
+ this: T,
404
+ ...args: Args
405
+ ): WhereResult<T>;
406
+ orWhereNotExists<T extends Where, Arg extends JoinCallbackArg<T>>(
407
+ this: T,
408
+ arg: Arg,
409
+ cb: JoinCallback<T, Arg>,
410
+ ): WhereResult<T>;
411
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
412
+ orWhereNotExists(...args: any) {
413
+ return this.clone()._orWhereNotExists(...args);
414
+ }
415
+ _orWhereNotExists<T extends Where, Args extends JoinArgs<T>>(
416
+ this: T,
417
+ ...args: Args
418
+ ): WhereResult<T>;
419
+ _orWhereNotExists<T extends Where, Arg extends JoinCallbackArg<T>>(
420
+ this: T,
421
+ arg: Arg,
422
+ cb: JoinCallback<T, Arg>,
423
+ ): WhereResult<T>;
424
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
425
+ _orWhereNotExists(this: Where, ...args: any) {
426
+ return this._orNot({ EXISTS: args });
427
+ }
428
+ }
429
+
430
+ export class WhereQueryBuilder<Q extends QueryBase = QueryBase>
431
+ extends Where
432
+ implements QueryBase
433
+ {
434
+ query = {} as QueryData;
435
+ selectable!: Q['selectable'];
436
+ __model: Query;
437
+ relations = {};
438
+ withData = {};
439
+
440
+ constructor(public table: Q['table'], public tableAlias: Q['tableAlias']) {
441
+ super();
442
+ this.__model = this as unknown as Query;
443
+ }
444
+
445
+ clone<T extends this>(this: T): T {
446
+ const cloned = Object.create(this.__model);
447
+ cloned.query = getClonedQueryData(this.query);
448
+ return cloned as unknown as T;
449
+ }
450
+ }
@@ -0,0 +1,66 @@
1
+ import {
2
+ AssertEqual,
3
+ expectQueryNotMutated,
4
+ expectSql,
5
+ User,
6
+ userData,
7
+ useTestDatabase,
8
+ } from '../test-utils';
9
+
10
+ describe('window functions', () => {
11
+ useTestDatabase();
12
+
13
+ describe.each`
14
+ method | functionName | results
15
+ ${'selectRowNumber'} | ${'row_number'} | ${[1, 2, 1, 2]}
16
+ ${'selectRank'} | ${'rank'} | ${[1, 1, 1, 1]}
17
+ ${'selectDenseRank'} | ${'dense_rank'} | ${[1, 1, 1, 1]}
18
+ ${'selectPercentRank'} | ${'percent_rank'} | ${[0, 0, 0, 0]}
19
+ ${'selectCumeDist'} | ${'cume_dist'} | ${[1, 1, 1, 1]}
20
+ `('$method', ({ method, functionName, results }) => {
21
+ it('should return array of objects with number value', async () => {
22
+ if (method === 'selectCumeDist') {
23
+ await User.insert([
24
+ { ...userData, age: 20 },
25
+ { ...userData, age: 20 },
26
+ ]);
27
+ await User.insert([
28
+ { ...userData, age: 30 },
29
+ { ...userData, age: 30 },
30
+ ]);
31
+
32
+ const value = await User[method as 'selectRowNumber']({
33
+ partitionBy: 'age',
34
+ });
35
+
36
+ const eq: AssertEqual<typeof value, { row_number: number }[]> = true;
37
+ expect(eq).toBe(true);
38
+
39
+ expect(value).toEqual(
40
+ (results as number[]).map((item) => ({ [functionName]: item })),
41
+ );
42
+ }
43
+ });
44
+
45
+ it(`should perform ${method} query`, () => {
46
+ const q = User.clone();
47
+ const expectedSql = `SELECT ${functionName}() OVER (PARTITION BY "user"."name" ORDER BY "user"."createdAt" DESC) AS "as" FROM "user"`;
48
+ expectSql(
49
+ q[method as 'selectRank']({
50
+ as: 'as',
51
+ partitionBy: 'name',
52
+ order: { createdAt: 'DESC' },
53
+ }).toSql(),
54
+ expectedSql,
55
+ );
56
+ expectQueryNotMutated(q);
57
+
58
+ q[`_${method}` as '_selectRank']({
59
+ as: 'as',
60
+ partitionBy: 'name',
61
+ order: { createdAt: 'DESC' },
62
+ });
63
+ expectSql(q.toSql(), expectedSql);
64
+ });
65
+ });
66
+ });
@@ -0,0 +1,108 @@
1
+ import { Query } from '../query';
2
+ import { ColumnType, IntegerColumn } from '../columnSchema';
3
+ import { SelectAgg, WindowFunctionOptions } from './aggregate';
4
+ import { pushQueryValue } from '../queryDataUtils';
5
+ import { addParserToQuery } from './select';
6
+
7
+ const selectWindowFunction = <
8
+ T extends Query,
9
+ Func extends string,
10
+ As extends string | undefined,
11
+ Value extends ColumnType,
12
+ >(
13
+ self: T,
14
+ functionName: Func,
15
+ options: WindowFunctionOptions<T, As>,
16
+ parse?: (input: unknown) => Value['type'],
17
+ ): SelectAgg<T, Func, As, Value> => {
18
+ pushQueryValue(self, 'select', {
19
+ function: functionName,
20
+ options: {
21
+ as: options.as,
22
+ over: options,
23
+ },
24
+ });
25
+
26
+ if (parse) {
27
+ addParserToQuery(self.query, options.as || functionName, parse);
28
+ }
29
+
30
+ return self as unknown as SelectAgg<T, Func, As, Value>;
31
+ };
32
+
33
+ const toInt = (input: unknown) => parseInt(input as string);
34
+
35
+ export class Window {
36
+ selectRowNumber<T extends Query, As extends string | undefined = undefined>(
37
+ this: T,
38
+ options: WindowFunctionOptions<T, As>,
39
+ ): SelectAgg<T, 'row_number', As, IntegerColumn> {
40
+ return this.clone()._selectRowNumber(options);
41
+ }
42
+
43
+ _selectRowNumber<T extends Query, As extends string | undefined = undefined>(
44
+ this: T,
45
+ options: WindowFunctionOptions<T, As>,
46
+ ): SelectAgg<T, 'row_number', As, IntegerColumn> {
47
+ return selectWindowFunction(this, 'row_number', options, toInt);
48
+ }
49
+
50
+ selectRank<T extends Query, As extends string | undefined = undefined>(
51
+ this: T,
52
+ options: WindowFunctionOptions<T, As>,
53
+ ): SelectAgg<T, 'rank', As, IntegerColumn> {
54
+ return this.clone()._selectRank(options);
55
+ }
56
+
57
+ _selectRank<T extends Query, As extends string | undefined = undefined>(
58
+ this: T,
59
+ options: WindowFunctionOptions<T, As>,
60
+ ): SelectAgg<T, 'rank', As, IntegerColumn> {
61
+ return selectWindowFunction(this, 'rank', options, toInt);
62
+ }
63
+
64
+ selectDenseRank<T extends Query, As extends string | undefined = undefined>(
65
+ this: T,
66
+ options: WindowFunctionOptions<T, As>,
67
+ ): SelectAgg<T, 'dense_rank', As, IntegerColumn> {
68
+ return this.clone()._selectDenseRank(options);
69
+ }
70
+
71
+ _selectDenseRank<T extends Query, As extends string | undefined = undefined>(
72
+ this: T,
73
+ options: WindowFunctionOptions<T, As>,
74
+ ): SelectAgg<T, 'dense_rank', As, IntegerColumn> {
75
+ return selectWindowFunction(this, 'dense_rank', options, toInt);
76
+ }
77
+
78
+ selectPercentRank<T extends Query, As extends string | undefined = undefined>(
79
+ this: T,
80
+ options: WindowFunctionOptions<T, As>,
81
+ ): SelectAgg<T, 'percent_rank', As, IntegerColumn> {
82
+ return this.clone()._selectPercentRank(options);
83
+ }
84
+
85
+ _selectPercentRank<
86
+ T extends Query,
87
+ As extends string | undefined = undefined,
88
+ >(
89
+ this: T,
90
+ options: WindowFunctionOptions<T, As>,
91
+ ): SelectAgg<T, 'percent_rank', As, IntegerColumn> {
92
+ return selectWindowFunction(this, 'percent_rank', options, toInt);
93
+ }
94
+
95
+ selectCumeDist<T extends Query, As extends string | undefined = undefined>(
96
+ this: T,
97
+ options: WindowFunctionOptions<T, As>,
98
+ ): SelectAgg<T, 'cume_dist', As, IntegerColumn> {
99
+ return this.clone()._selectCumeDist(options);
100
+ }
101
+
102
+ _selectCumeDist<T extends Query, As extends string | undefined = undefined>(
103
+ this: T,
104
+ options: WindowFunctionOptions<T, As>,
105
+ ): SelectAgg<T, 'cume_dist', As, IntegerColumn> {
106
+ return selectWindowFunction(this, 'cume_dist', options, toInt);
107
+ }
108
+ }