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,1594 @@
1
+ import { expectSql, Message, User } from '../test-utils';
2
+ import { raw } from '../common';
3
+ import { Sql } from '../sql';
4
+ import { Query } from '../query';
5
+ import { pushQueryOn } from './join';
6
+
7
+ describe('and', () => {
8
+ const [where, _where] = [User.where, User._where];
9
+ beforeEach(() => {
10
+ User.where = jest.fn();
11
+ User._where = jest.fn();
12
+ });
13
+ afterAll(() => {
14
+ User.where = where;
15
+ User._where = _where;
16
+ });
17
+
18
+ it('is alias for where', () => {
19
+ User.and({});
20
+ expect(User.where).toBeCalled();
21
+ });
22
+
23
+ it('has modifier', () => {
24
+ User._and({});
25
+ expect(User._where).toBeCalled();
26
+ });
27
+ });
28
+
29
+ describe('andNot', () => {
30
+ const [whereNot, _whereNot] = [User.whereNot, User._whereNot];
31
+ beforeEach(() => {
32
+ User.whereNot = jest.fn();
33
+ User._whereNot = jest.fn();
34
+ });
35
+ afterAll(() => {
36
+ User.whereNot = whereNot;
37
+ User._whereNot = _whereNot;
38
+ });
39
+
40
+ it('is alias for where', () => {
41
+ User.andNot({});
42
+ expect(User.whereNot).toBeCalled();
43
+ });
44
+
45
+ it('has modifier', () => {
46
+ User._andNot({});
47
+ expect(User._whereNot).toBeCalled();
48
+ });
49
+ });
50
+
51
+ export const testWhere = (
52
+ buildSql: (cb: (q: Query) => Query) => Sql,
53
+ startSql: string,
54
+ ) => {
55
+ describe('where', () => {
56
+ it('should handle null value', () => {
57
+ expectSql(
58
+ buildSql((q) => q.where({ id: 1, 'user.picture': null })),
59
+ `
60
+ ${startSql} "user"."id" = $1 AND "user"."picture" IS NULL
61
+ `,
62
+ [1],
63
+ );
64
+ });
65
+
66
+ it('should accept sub query', () => {
67
+ expectSql(
68
+ [
69
+ buildSql((q) =>
70
+ q.where(
71
+ { id: 1 },
72
+ q.where({ OR: [{ id: 2 }, { id: 3, name: 'n' }] }),
73
+ ),
74
+ ),
75
+ buildSql((q) =>
76
+ q.where({ id: 1 }, q.or({ id: 2 }, { id: 3, name: 'n' })),
77
+ ),
78
+ ],
79
+ `
80
+ ${startSql} "user"."id" = $1 AND (
81
+ "user"."id" = $2 OR "user"."id" = $3 AND "user"."name" = $4
82
+ )
83
+ `,
84
+ [1, 2, 3, 'n'],
85
+ );
86
+ });
87
+
88
+ it('should handle condition with operator', () => {
89
+ expectSql(
90
+ buildSql((q) => q.where({ age: { gt: 20 } })),
91
+ `
92
+ ${startSql} "user"."age" > $1
93
+ `,
94
+ [20],
95
+ );
96
+ });
97
+
98
+ it('should handle condition with operator and sub query', () => {
99
+ expectSql(
100
+ buildSql((q) => q.where({ id: { in: User.select('id') } })),
101
+ `
102
+ ${startSql}
103
+ "user"."id" IN (SELECT "user"."id" FROM "user")
104
+ `,
105
+ );
106
+ });
107
+
108
+ it('should handle condition with operator and raw', () => {
109
+ expectSql(
110
+ buildSql((q) => q.where({ id: { in: raw('(1, 2, 3)') } })),
111
+ `
112
+ ${startSql}
113
+ "user"."id" IN (1, 2, 3)
114
+ `,
115
+ );
116
+ });
117
+
118
+ it('should accept raw sql', () => {
119
+ expectSql(
120
+ buildSql((q) => q.where({ id: raw('1 + 2') })),
121
+ `
122
+ ${startSql} "user"."id" = 1 + 2
123
+ `,
124
+ );
125
+ });
126
+ });
127
+
128
+ describe('whereNot', () => {
129
+ it('should handle null value', () => {
130
+ expectSql(
131
+ [
132
+ buildSql((q) => q.where({ NOT: { id: 1, picture: null } })),
133
+ buildSql((q) => q.whereNot({ id: 1, picture: null })),
134
+ ],
135
+ `
136
+ ${startSql}
137
+ NOT "user"."id" = $1 AND NOT "user"."picture" IS NULL
138
+ `,
139
+ [1],
140
+ );
141
+ });
142
+
143
+ it('should accept sub query', () => {
144
+ expectSql(
145
+ [
146
+ buildSql((q) =>
147
+ q.where({
148
+ NOT: [
149
+ { id: 1 },
150
+ q.where({ OR: [{ id: 2 }, { id: 3, name: 'n' }] }),
151
+ ],
152
+ }),
153
+ ),
154
+ buildSql((q) =>
155
+ q.whereNot({ id: 1 }, q.or({ id: 2 }, { id: 3, name: 'n' })),
156
+ ),
157
+ ],
158
+ `
159
+ ${startSql}
160
+ NOT "user"."id" = $1 AND NOT (
161
+ "user"."id" = $2 OR "user"."id" = $3 AND "user"."name" = $4
162
+ )
163
+ `,
164
+ [1, 2, 3, 'n'],
165
+ );
166
+ });
167
+
168
+ it('should handle condition with operator', () => {
169
+ expectSql(
170
+ [
171
+ buildSql((q) => q.where({ NOT: { age: { gt: 20 } } })),
172
+ buildSql((q) => q.whereNot({ age: { gt: 20 } })),
173
+ ],
174
+ `
175
+ ${startSql}
176
+ NOT "user"."age" > $1
177
+ `,
178
+ [20],
179
+ );
180
+ });
181
+
182
+ it('should handle condition with operator and sub query', () => {
183
+ expectSql(
184
+ [
185
+ buildSql((q) => q.where({ NOT: { id: { in: User.select('id') } } })),
186
+ buildSql((q) => q.whereNot({ id: { in: User.select('id') } })),
187
+ ],
188
+ `
189
+ ${startSql}
190
+ NOT "user"."id" IN (SELECT "user"."id" FROM "user")
191
+ `,
192
+ );
193
+ });
194
+
195
+ it('should handle condition with operator and raw', () => {
196
+ expectSql(
197
+ [
198
+ buildSql((q) => q.where({ NOT: { id: { in: raw('(1, 2, 3)') } } })),
199
+ buildSql((q) => q.whereNot({ id: { in: raw('(1, 2, 3)') } })),
200
+ ],
201
+ `
202
+ ${startSql}
203
+ NOT "user"."id" IN (1, 2, 3)
204
+ `,
205
+ );
206
+ });
207
+
208
+ it('should accept raw sql', () => {
209
+ expectSql(
210
+ [
211
+ buildSql((q) => q.where({ NOT: { id: raw('1 + 2') } })),
212
+ buildSql((q) => q.whereNot({ id: raw('1 + 2') })),
213
+ ],
214
+ `
215
+ ${startSql} NOT "user"."id" = 1 + 2
216
+ `,
217
+ );
218
+ });
219
+
220
+ it('should handle sub query builder', () => {
221
+ expectSql(
222
+ [
223
+ buildSql((q) =>
224
+ q.where({
225
+ NOT: (q) =>
226
+ q.where({
227
+ IN: { columns: ['id'], values: [[1, 2, 3]] },
228
+ EXISTS: [Message, 'authorId', 'id'],
229
+ }),
230
+ }),
231
+ ),
232
+ buildSql((q) =>
233
+ q.whereNot((q) =>
234
+ q.whereIn('id', [1, 2, 3]).whereExists(Message, 'authorId', 'id'),
235
+ ),
236
+ ),
237
+ ],
238
+ `
239
+ ${startSql}
240
+ NOT "user"."id" IN ($1, $2, $3)
241
+ AND NOT EXISTS (SELECT 1 FROM "message" WHERE "message"."authorId" = "user"."id" LIMIT 1)
242
+ `,
243
+ [1, 2, 3],
244
+ );
245
+ });
246
+ });
247
+
248
+ describe('or', () => {
249
+ it('should join conditions with or', () => {
250
+ expectSql(
251
+ [
252
+ buildSql((q) => q.where({ OR: [{ id: 1 }, { name: 'ko' }] })),
253
+ buildSql((q) => q.or({ id: 1 }, { name: 'ko' })),
254
+ ],
255
+ `
256
+ ${startSql}
257
+ "user"."id" = $1 OR "user"."name" = $2
258
+ `,
259
+ [1, 'ko'],
260
+ );
261
+ });
262
+
263
+ it('should handle sub queries', () => {
264
+ expectSql(
265
+ [
266
+ buildSql((q) =>
267
+ q.where({
268
+ OR: [{ id: 1 }, User.where({ id: 2 }).and({ name: 'n' })],
269
+ }),
270
+ ),
271
+ buildSql((q) =>
272
+ q.or({ id: 1 }, User.where({ id: 2 }).and({ name: 'n' })),
273
+ ),
274
+ ],
275
+ `
276
+ ${startSql}
277
+ "user"."id" = $1 OR ("user"."id" = $2 AND "user"."name" = $3)
278
+ `,
279
+ [1, 2, 'n'],
280
+ );
281
+ });
282
+
283
+ it('should accept raw sql', () => {
284
+ expectSql(
285
+ [
286
+ buildSql((q) =>
287
+ q.where({ OR: [{ id: raw('1 + 2') }, { name: raw('2 + 3') }] }),
288
+ ),
289
+ buildSql((q) => q.or({ id: raw('1 + 2') }, { name: raw('2 + 3') })),
290
+ ],
291
+ `
292
+ ${startSql}
293
+ "user"."id" = 1 + 2 OR "user"."name" = 2 + 3
294
+ `,
295
+ );
296
+ });
297
+ });
298
+
299
+ describe('orNot', () => {
300
+ it('should join conditions with or', () => {
301
+ expectSql(
302
+ [
303
+ buildSql((q) =>
304
+ q.where({ OR: [{ NOT: { id: 1 } }, { NOT: { name: 'ko' } }] }),
305
+ ),
306
+ buildSql((q) => q.orNot({ id: 1 }, { name: 'ko' })),
307
+ ],
308
+ `
309
+ ${startSql}
310
+ NOT "user"."id" = $1 OR NOT "user"."name" = $2
311
+ `,
312
+ [1, 'ko'],
313
+ );
314
+ });
315
+
316
+ it('should handle sub queries', () => {
317
+ expectSql(
318
+ [
319
+ buildSql((q) =>
320
+ q.where({
321
+ OR: [
322
+ { NOT: { id: 1 } },
323
+ { NOT: User.where({ id: 2 }).and({ name: 'n' }) },
324
+ ],
325
+ }),
326
+ ),
327
+ buildSql((q) =>
328
+ q.orNot(
329
+ {
330
+ id: 1,
331
+ },
332
+ User.where({ id: 2 }).and({ name: 'n' }),
333
+ ),
334
+ ),
335
+ ],
336
+ `
337
+ ${startSql}
338
+ NOT "user"."id" = $1 OR NOT ("user"."id" = $2 AND "user"."name" = $3)
339
+ `,
340
+ [1, 2, 'n'],
341
+ );
342
+ });
343
+
344
+ it('should accept raw sql', () => {
345
+ expectSql(
346
+ [
347
+ buildSql((q) =>
348
+ q.where({
349
+ OR: [
350
+ { NOT: { id: raw('1 + 2') } },
351
+ { NOT: { name: raw('2 + 3') } },
352
+ ],
353
+ }),
354
+ ),
355
+ buildSql((q) =>
356
+ q.orNot({ id: raw('1 + 2') }, { name: raw('2 + 3') }),
357
+ ),
358
+ ],
359
+ `
360
+ ${startSql}
361
+ NOT "user"."id" = 1 + 2 OR NOT "user"."name" = 2 + 3
362
+ `,
363
+ );
364
+ });
365
+ });
366
+
367
+ describe('whereIn', () => {
368
+ it('should handle (column, array)', () => {
369
+ expectSql(
370
+ [
371
+ buildSql((q) =>
372
+ q.where({ IN: { columns: ['id'], values: [[1, 2, 3]] } }),
373
+ ),
374
+ buildSql((q) => q.whereIn('id', [1, 2, 3])),
375
+ ],
376
+ `
377
+ ${startSql}
378
+ "user"."id" IN ($1, $2, $3)
379
+ `,
380
+ [1, 2, 3],
381
+ );
382
+ });
383
+
384
+ it('should handle multiple expressions', () => {
385
+ expectSql(
386
+ [
387
+ buildSql((q) =>
388
+ q.where({
389
+ IN: [
390
+ { columns: ['id'], values: [[1, 2, 3]] },
391
+ { columns: ['name'], values: [['a', 'b', 'c']] },
392
+ ],
393
+ }),
394
+ ),
395
+ buildSql((q) =>
396
+ q.whereIn({
397
+ id: [1, 2, 3],
398
+ name: ['a', 'b', 'c'],
399
+ }),
400
+ ),
401
+ ],
402
+ `
403
+ ${startSql}
404
+ "user"."id" IN ($1, $2, $3)
405
+ AND "user"."name" IN ($4, $5, $6)
406
+ `,
407
+ [1, 2, 3, 'a', 'b', 'c'],
408
+ );
409
+ });
410
+
411
+ it('should handle raw query', () => {
412
+ expectSql(
413
+ [
414
+ buildSql((q) =>
415
+ q.where({ IN: { columns: ['id'], values: raw('(1, 2, 3)') } }),
416
+ ),
417
+ buildSql((q) => q.whereIn('id', raw('(1, 2, 3)'))),
418
+ ],
419
+ `
420
+ ${startSql}
421
+ "user"."id" IN (1, 2, 3)
422
+ `,
423
+ );
424
+
425
+ expectSql(
426
+ [
427
+ buildSql((q) =>
428
+ q.where({
429
+ IN: [
430
+ { columns: ['id'], values: raw('(1, 2, 3)') },
431
+ { columns: ['name'], values: raw(`('a', 'b', 'c')`) },
432
+ ],
433
+ }),
434
+ ),
435
+ buildSql((q) =>
436
+ q.whereIn({
437
+ id: raw('(1, 2, 3)'),
438
+ name: raw(`('a', 'b', 'c')`),
439
+ }),
440
+ ),
441
+ ],
442
+ `
443
+ ${startSql}
444
+ "user"."id" IN (1, 2, 3)
445
+ AND "user"."name" IN ('a', 'b', 'c')
446
+ `,
447
+ );
448
+ });
449
+
450
+ it('should handle sub query', () => {
451
+ expectSql(
452
+ [
453
+ buildSql((q) =>
454
+ q.where({ IN: { columns: ['id'], values: User.select('id') } }),
455
+ ),
456
+ buildSql((q) => q.whereIn('id', User.select('id'))),
457
+ ],
458
+ `
459
+ ${startSql}
460
+ "user"."id" IN (SELECT "user"."id" FROM "user")
461
+ `,
462
+ );
463
+
464
+ expectSql(
465
+ [
466
+ buildSql((q) =>
467
+ q.where({
468
+ IN: [
469
+ { columns: ['id'], values: User.select('id') },
470
+ { columns: ['name'], values: User.select('name') },
471
+ ],
472
+ }),
473
+ ),
474
+ buildSql((q) =>
475
+ q.whereIn({
476
+ id: User.select('id'),
477
+ name: User.select('name'),
478
+ }),
479
+ ),
480
+ ],
481
+ `
482
+ ${startSql}
483
+ "user"."id" IN (SELECT "user"."id" FROM "user")
484
+ AND "user"."name" IN (SELECT "user"."name" FROM "user")
485
+ `,
486
+ );
487
+ });
488
+
489
+ describe('tuple', () => {
490
+ it('should handle values', () => {
491
+ expectSql(
492
+ [
493
+ buildSql((q) =>
494
+ q.where({
495
+ IN: {
496
+ columns: ['id', 'name'],
497
+ values: [
498
+ [1, 'a'],
499
+ [2, 'b'],
500
+ ],
501
+ },
502
+ }),
503
+ ),
504
+ buildSql((q) =>
505
+ q.whereIn(
506
+ ['id', 'name'],
507
+ [
508
+ [1, 'a'],
509
+ [2, 'b'],
510
+ ],
511
+ ),
512
+ ),
513
+ ],
514
+ `
515
+ ${startSql}
516
+ ("user"."id", "user"."name") IN (($1, $2), ($3, $4))
517
+ `,
518
+ [1, 'a', 2, 'b'],
519
+ );
520
+ });
521
+
522
+ it('should handle raw query', () => {
523
+ expectSql(
524
+ [
525
+ buildSql((q) =>
526
+ q.where({
527
+ IN: {
528
+ columns: ['id', 'name'],
529
+ values: raw(`((1, 'a'), (2, 'b'))`),
530
+ },
531
+ }),
532
+ ),
533
+ buildSql((q) =>
534
+ q.whereIn(['id', 'name'], raw(`((1, 'a'), (2, 'b'))`)),
535
+ ),
536
+ ],
537
+ `
538
+ ${startSql}
539
+ ("user"."id", "user"."name") IN ((1, 'a'), (2, 'b'))
540
+ `,
541
+ );
542
+ });
543
+
544
+ it('should handle sub query', () => {
545
+ expectSql(
546
+ [
547
+ buildSql((q) =>
548
+ q.where({
549
+ IN: {
550
+ columns: ['id', 'name'],
551
+ values: User.select('id', 'name'),
552
+ },
553
+ }),
554
+ ),
555
+ buildSql((q) =>
556
+ q.whereIn(['id', 'name'], User.select('id', 'name')),
557
+ ),
558
+ ],
559
+ `
560
+ ${startSql}
561
+ ("user"."id", "user"."name")
562
+ IN (SELECT "user"."id", "user"."name" FROM "user")
563
+ `,
564
+ );
565
+ });
566
+ });
567
+ });
568
+
569
+ describe('orWhereIn', () => {
570
+ it('should handle (column, array)', () => {
571
+ expectSql(
572
+ [
573
+ buildSql((q) =>
574
+ q.where({
575
+ OR: [{ id: 1 }, { IN: { columns: ['id'], values: [[1, 2, 3]] } }],
576
+ }),
577
+ ),
578
+ buildSql((q) => q.where({ id: 1 }).orWhereIn('id', [1, 2, 3])),
579
+ ],
580
+ `
581
+ ${startSql}
582
+ "user"."id" = $1 OR "user"."id" IN ($2, $3, $4)
583
+ `,
584
+ [1, 1, 2, 3],
585
+ );
586
+ });
587
+
588
+ it('should handle object of columns and arrays', () => {
589
+ expectSql(
590
+ [
591
+ buildSql((q) =>
592
+ q.where({
593
+ OR: [
594
+ { id: 1 },
595
+ {
596
+ IN: [
597
+ { columns: ['id'], values: [[1, 2, 3]] },
598
+ { columns: ['name'], values: [['a', 'b', 'c']] },
599
+ ],
600
+ },
601
+ ],
602
+ }),
603
+ ),
604
+ buildSql((q) =>
605
+ q.where({ id: 1 }).orWhereIn({
606
+ id: [1, 2, 3],
607
+ name: ['a', 'b', 'c'],
608
+ }),
609
+ ),
610
+ ],
611
+ `
612
+ ${startSql}
613
+ "user"."id" = $1
614
+ OR "user"."id" IN ($2, $3, $4) AND "user"."name" IN ($5, $6, $7)
615
+ `,
616
+ [1, 1, 2, 3, 'a', 'b', 'c'],
617
+ );
618
+ });
619
+
620
+ it('should handle raw query', () => {
621
+ expectSql(
622
+ [
623
+ buildSql((q) =>
624
+ q.where({
625
+ OR: [
626
+ { id: 1 },
627
+ { IN: { columns: ['id'], values: raw('(1, 2, 3)') } },
628
+ ],
629
+ }),
630
+ ),
631
+ buildSql((q) =>
632
+ q.where({ id: 1 }).orWhereIn({ id: raw('(1, 2, 3)') }),
633
+ ),
634
+ ],
635
+ `
636
+ ${startSql}
637
+ "user"."id" = $1 OR "user"."id" IN (1, 2, 3)
638
+ `,
639
+ [1],
640
+ );
641
+
642
+ expectSql(
643
+ [
644
+ buildSql((q) =>
645
+ q.where({
646
+ OR: [
647
+ { id: 1 },
648
+ {
649
+ IN: [
650
+ { columns: ['id'], values: raw('(1, 2, 3)') },
651
+ { columns: ['name'], values: raw(`('a', 'b', 'c')`) },
652
+ ],
653
+ },
654
+ ],
655
+ }),
656
+ ),
657
+ buildSql((q) =>
658
+ q.where({ id: 1 }).orWhereIn({
659
+ id: raw('(1, 2, 3)'),
660
+ name: raw(`('a', 'b', 'c')`),
661
+ }),
662
+ ),
663
+ ],
664
+ `
665
+ ${startSql}
666
+ "user"."id" = $1
667
+ OR "user"."id" IN (1, 2, 3)
668
+ AND "user"."name" IN ('a', 'b', 'c')
669
+ `,
670
+ [1],
671
+ );
672
+ });
673
+
674
+ it('should handle sub query', () => {
675
+ expectSql(
676
+ [
677
+ buildSql((q) =>
678
+ q.where({
679
+ OR: [
680
+ { id: 1 },
681
+ { IN: { columns: ['id'], values: User.select('id') } },
682
+ ],
683
+ }),
684
+ ),
685
+ buildSql((q) =>
686
+ q.where({ id: 1 }).orWhereIn({ id: User.select('id') }),
687
+ ),
688
+ ],
689
+ `
690
+ ${startSql}
691
+ "user"."id" = $1
692
+ OR "user"."id" IN (SELECT "user"."id" FROM "user")
693
+ `,
694
+ [1],
695
+ );
696
+
697
+ expectSql(
698
+ [
699
+ buildSql((q) =>
700
+ q.where({
701
+ OR: [
702
+ { id: 1 },
703
+ {
704
+ IN: [
705
+ { columns: ['id'], values: User.select('id') },
706
+ { columns: ['name'], values: User.select('name') },
707
+ ],
708
+ },
709
+ ],
710
+ }),
711
+ ),
712
+ buildSql((q) =>
713
+ q.where({ id: 1 }).orWhereIn({
714
+ id: User.select('id'),
715
+ name: User.select('name'),
716
+ }),
717
+ ),
718
+ ],
719
+ `
720
+ ${startSql}
721
+ "user"."id" = $1
722
+ OR "user"."id" IN (SELECT "user"."id" FROM "user")
723
+ AND "user"."name" IN (SELECT "user"."name" FROM "user")
724
+ `,
725
+ [1],
726
+ );
727
+ });
728
+
729
+ describe('tuple', () => {
730
+ it('should handle values', () => {
731
+ expectSql(
732
+ [
733
+ buildSql((q) =>
734
+ q.where({
735
+ OR: [
736
+ { id: 1 },
737
+ {
738
+ IN: {
739
+ columns: ['id', 'name'],
740
+ values: [
741
+ [1, 'a'],
742
+ [2, 'b'],
743
+ ],
744
+ },
745
+ },
746
+ ],
747
+ }),
748
+ ),
749
+ buildSql((q) =>
750
+ q.where({ id: 1 }).orWhereIn(
751
+ ['id', 'name'],
752
+ [
753
+ [1, 'a'],
754
+ [2, 'b'],
755
+ ],
756
+ ),
757
+ ),
758
+ ],
759
+ `
760
+ ${startSql}
761
+ "user"."id" = $1
762
+ OR ("user"."id", "user"."name") IN (($2, $3), ($4, $5))
763
+ `,
764
+ [1, 1, 'a', 2, 'b'],
765
+ );
766
+ });
767
+
768
+ it('should handle raw query', () => {
769
+ expectSql(
770
+ [
771
+ buildSql((q) =>
772
+ q.where({
773
+ OR: [
774
+ { id: 1 },
775
+ {
776
+ IN: {
777
+ columns: ['id', 'name'],
778
+ values: raw(`((1, 'a'), (2, 'b'))`),
779
+ },
780
+ },
781
+ ],
782
+ }),
783
+ ),
784
+ buildSql((q) =>
785
+ q
786
+ .where({ id: 1 })
787
+ .orWhereIn(['id', 'name'], raw(`((1, 'a'), (2, 'b'))`)),
788
+ ),
789
+ ],
790
+ `
791
+ ${startSql}
792
+ "user"."id" = $1
793
+ OR ("user"."id", "user"."name") IN ((1, 'a'), (2, 'b'))
794
+ `,
795
+ [1],
796
+ );
797
+ });
798
+
799
+ it('should handle sub query', () => {
800
+ expectSql(
801
+ [
802
+ buildSql((q) =>
803
+ q.where({
804
+ OR: [
805
+ { id: 1 },
806
+ {
807
+ IN: {
808
+ columns: ['id', 'name'],
809
+ values: User.select('id', 'name'),
810
+ },
811
+ },
812
+ ],
813
+ }),
814
+ ),
815
+ buildSql((q) =>
816
+ q
817
+ .where({ id: 1 })
818
+ .orWhereIn(['id', 'name'], User.select('id', 'name')),
819
+ ),
820
+ ],
821
+ `
822
+ ${startSql}
823
+ "user"."id" = $1
824
+ OR ("user"."id", "user"."name")
825
+ IN (SELECT "user"."id", "user"."name" FROM "user")
826
+ `,
827
+ [1],
828
+ );
829
+ });
830
+ });
831
+ });
832
+
833
+ // TODO: add tests for methods below
834
+ describe('whereNotIn', () => {
835
+ it('should handle (column, array)', () => {
836
+ expectSql(
837
+ [
838
+ buildSql((q) =>
839
+ q.where({ NOT: { IN: { columns: ['id'], values: [[1, 2, 3]] } } }),
840
+ ),
841
+ buildSql((q) => q.whereNotIn('id', [1, 2, 3])),
842
+ ],
843
+ `
844
+ ${startSql}
845
+ NOT "user"."id" IN ($1, $2, $3)
846
+ `,
847
+ [1, 2, 3],
848
+ );
849
+ });
850
+
851
+ it('should handle object of columns and arrays', () => {
852
+ expectSql(
853
+ [
854
+ buildSql((q) =>
855
+ q.where({
856
+ NOT: {
857
+ IN: [
858
+ { columns: ['id'], values: [[1, 2, 3]] },
859
+ { columns: ['name'], values: [['a', 'b', 'c']] },
860
+ ],
861
+ },
862
+ }),
863
+ ),
864
+ buildSql((q) =>
865
+ q.whereNotIn({
866
+ id: [1, 2, 3],
867
+ name: ['a', 'b', 'c'],
868
+ }),
869
+ ),
870
+ ],
871
+ `
872
+ ${startSql}
873
+ NOT "user"."id" IN ($1, $2, $3)
874
+ AND NOT "user"."name" IN ($4, $5, $6)
875
+ `,
876
+ [1, 2, 3, 'a', 'b', 'c'],
877
+ );
878
+ });
879
+
880
+ it('should handle raw query', () => {
881
+ expectSql(
882
+ [
883
+ buildSql((q) =>
884
+ q.where({
885
+ NOT: { IN: { columns: ['id'], values: raw('(1, 2, 3)') } },
886
+ }),
887
+ ),
888
+ buildSql((q) =>
889
+ q.whereNotIn({
890
+ id: raw('(1, 2, 3)'),
891
+ }),
892
+ ),
893
+ ],
894
+ `
895
+ ${startSql}
896
+ NOT "user"."id" IN (1, 2, 3)
897
+ `,
898
+ );
899
+
900
+ expectSql(
901
+ [
902
+ buildSql((q) =>
903
+ q.where({
904
+ NOT: {
905
+ IN: [
906
+ { columns: ['id'], values: raw('(1, 2, 3)') },
907
+ { columns: ['name'], values: raw(`('a', 'b', 'c')`) },
908
+ ],
909
+ },
910
+ }),
911
+ ),
912
+ buildSql((q) =>
913
+ q.whereNotIn({
914
+ id: raw('(1, 2, 3)'),
915
+ name: raw(`('a', 'b', 'c')`),
916
+ }),
917
+ ),
918
+ ],
919
+ `
920
+ ${startSql}
921
+ NOT "user"."id" IN (1, 2, 3)
922
+ AND NOT "user"."name" IN ('a', 'b', 'c')
923
+ `,
924
+ );
925
+ });
926
+
927
+ it('should handle sub query', () => {
928
+ expectSql(
929
+ [
930
+ buildSql((q) =>
931
+ q.where({
932
+ NOT: { IN: { columns: ['id'], values: User.select('id') } },
933
+ }),
934
+ ),
935
+ buildSql((q) =>
936
+ q.whereNotIn({
937
+ id: User.select('id'),
938
+ }),
939
+ ),
940
+ ],
941
+ `
942
+ ${startSql}
943
+ NOT "user"."id" IN (SELECT "user"."id" FROM "user")
944
+ `,
945
+ );
946
+
947
+ expectSql(
948
+ [
949
+ buildSql((q) =>
950
+ q.where({
951
+ NOT: {
952
+ IN: [
953
+ { columns: ['id'], values: User.select('id') },
954
+ { columns: ['name'], values: User.select('name') },
955
+ ],
956
+ },
957
+ }),
958
+ ),
959
+ buildSql((q) =>
960
+ q.whereNotIn({
961
+ id: User.select('id'),
962
+ name: User.select('name'),
963
+ }),
964
+ ),
965
+ ],
966
+ `
967
+ ${startSql}
968
+ NOT "user"."id" IN (SELECT "user"."id" FROM "user")
969
+ AND NOT "user"."name" IN (SELECT "user"."name" FROM "user")
970
+ `,
971
+ );
972
+ });
973
+
974
+ describe('tuple', () => {
975
+ it('should handle values', () => {
976
+ expectSql(
977
+ [
978
+ buildSql((q) =>
979
+ q.where({
980
+ NOT: {
981
+ IN: {
982
+ columns: ['id', 'name'],
983
+ values: [
984
+ [1, 'a'],
985
+ [2, 'b'],
986
+ ],
987
+ },
988
+ },
989
+ }),
990
+ ),
991
+ buildSql((q) =>
992
+ q.whereNotIn(
993
+ ['id', 'name'],
994
+ [
995
+ [1, 'a'],
996
+ [2, 'b'],
997
+ ],
998
+ ),
999
+ ),
1000
+ ],
1001
+ `
1002
+ ${startSql}
1003
+ NOT ("user"."id", "user"."name") IN (($1, $2), ($3, $4))
1004
+ `,
1005
+ [1, 'a', 2, 'b'],
1006
+ );
1007
+ });
1008
+
1009
+ it('should handle raw query', () => {
1010
+ expectSql(
1011
+ [
1012
+ buildSql((q) =>
1013
+ q.where({
1014
+ NOT: {
1015
+ IN: {
1016
+ columns: ['id', 'name'],
1017
+ values: raw(`((1, 'a'), (2, 'b'))`),
1018
+ },
1019
+ },
1020
+ }),
1021
+ ),
1022
+ buildSql((q) =>
1023
+ q.whereNotIn(['id', 'name'], raw(`((1, 'a'), (2, 'b'))`)),
1024
+ ),
1025
+ ],
1026
+ `
1027
+ ${startSql}
1028
+ NOT ("user"."id", "user"."name") IN ((1, 'a'), (2, 'b'))
1029
+ `,
1030
+ );
1031
+ });
1032
+
1033
+ it('should handle sub query', () => {
1034
+ expectSql(
1035
+ [
1036
+ buildSql((q) =>
1037
+ q.where({
1038
+ NOT: {
1039
+ IN: {
1040
+ columns: ['id', 'name'],
1041
+ values: User.select('id', 'name'),
1042
+ },
1043
+ },
1044
+ }),
1045
+ ),
1046
+ buildSql((q) =>
1047
+ q.whereNotIn(['id', 'name'], User.select('id', 'name')),
1048
+ ),
1049
+ ],
1050
+ `
1051
+ ${startSql}
1052
+ NOT ("user"."id", "user"."name")
1053
+ IN (SELECT "user"."id", "user"."name" FROM "user")
1054
+ `,
1055
+ );
1056
+ });
1057
+ });
1058
+ });
1059
+
1060
+ describe('orWhereNotIn', () => {
1061
+ it('should handle (column, array)', () => {
1062
+ expectSql(
1063
+ [
1064
+ buildSql((q) =>
1065
+ q.where({
1066
+ OR: [
1067
+ { id: 1 },
1068
+ { NOT: { IN: { columns: ['id'], values: [[1, 2, 3]] } } },
1069
+ ],
1070
+ }),
1071
+ ),
1072
+ buildSql((q) =>
1073
+ q.where({ id: 1 }).orWhereNotIn({
1074
+ id: [1, 2, 3],
1075
+ }),
1076
+ ),
1077
+ ],
1078
+ `
1079
+ ${startSql}
1080
+ "user"."id" = $1 OR NOT "user"."id" IN ($2, $3, $4)
1081
+ `,
1082
+ [1, 1, 2, 3],
1083
+ );
1084
+ });
1085
+
1086
+ it('should handle object of columns and arrays', () => {
1087
+ expectSql(
1088
+ [
1089
+ buildSql((q) =>
1090
+ q.where({
1091
+ OR: [
1092
+ { id: 1 },
1093
+ {
1094
+ NOT: {
1095
+ IN: [
1096
+ { columns: ['id'], values: [[1, 2, 3]] },
1097
+ { columns: ['name'], values: [['a', 'b', 'c']] },
1098
+ ],
1099
+ },
1100
+ },
1101
+ ],
1102
+ }),
1103
+ ),
1104
+ buildSql((q) =>
1105
+ q.where({ id: 1 }).orWhereNotIn({
1106
+ id: [1, 2, 3],
1107
+ name: ['a', 'b', 'c'],
1108
+ }),
1109
+ ),
1110
+ ],
1111
+ `
1112
+ ${startSql}
1113
+ "user"."id" = $1
1114
+ OR NOT "user"."id" IN ($2, $3, $4) AND NOT "user"."name" IN ($5, $6, $7)
1115
+ `,
1116
+ [1, 1, 2, 3, 'a', 'b', 'c'],
1117
+ );
1118
+ });
1119
+
1120
+ it('should handle raw query', () => {
1121
+ expectSql(
1122
+ [
1123
+ buildSql((q) =>
1124
+ q.where({
1125
+ OR: [
1126
+ { id: 1 },
1127
+ {
1128
+ NOT: { IN: { columns: ['id'], values: raw('(1, 2, 3)') } },
1129
+ },
1130
+ ],
1131
+ }),
1132
+ ),
1133
+ buildSql((q) =>
1134
+ q.where({ id: 1 }).orWhereNotIn({
1135
+ id: raw('(1, 2, 3)'),
1136
+ }),
1137
+ ),
1138
+ ],
1139
+ `
1140
+ ${startSql}
1141
+ "user"."id" = $1 OR NOT "user"."id" IN (1, 2, 3)
1142
+ `,
1143
+ [1],
1144
+ );
1145
+
1146
+ expectSql(
1147
+ [
1148
+ buildSql((q) =>
1149
+ q.where({
1150
+ OR: [
1151
+ { id: 1 },
1152
+ {
1153
+ NOT: {
1154
+ IN: [
1155
+ { columns: ['id'], values: raw('(1, 2, 3)') },
1156
+ { columns: ['name'], values: raw(`('a', 'b', 'c')`) },
1157
+ ],
1158
+ },
1159
+ },
1160
+ ],
1161
+ }),
1162
+ ),
1163
+ buildSql((q) =>
1164
+ q.where({ id: 1 }).orWhereNotIn({
1165
+ id: raw('(1, 2, 3)'),
1166
+ name: raw(`('a', 'b', 'c')`),
1167
+ }),
1168
+ ),
1169
+ ],
1170
+ `
1171
+ ${startSql}
1172
+ "user"."id" = $1
1173
+ OR NOT "user"."id" IN (1, 2, 3)
1174
+ AND NOT "user"."name" IN ('a', 'b', 'c')
1175
+ `,
1176
+ [1],
1177
+ );
1178
+ });
1179
+
1180
+ it('should handle sub query', () => {
1181
+ expectSql(
1182
+ [
1183
+ buildSql((q) =>
1184
+ q.where({
1185
+ OR: [
1186
+ { id: 1 },
1187
+ { NOT: { IN: { columns: ['id'], values: User.select('id') } } },
1188
+ ],
1189
+ }),
1190
+ ),
1191
+ buildSql((q) =>
1192
+ q.where({ id: 1 }).orWhereNotIn({
1193
+ id: User.select('id'),
1194
+ }),
1195
+ ),
1196
+ ],
1197
+ `
1198
+ ${startSql}
1199
+ "user"."id" = $1
1200
+ OR NOT "user"."id" IN (SELECT "user"."id" FROM "user")
1201
+ `,
1202
+ [1],
1203
+ );
1204
+
1205
+ expectSql(
1206
+ [
1207
+ buildSql((q) =>
1208
+ q.where({
1209
+ OR: [
1210
+ { id: 1 },
1211
+ {
1212
+ NOT: {
1213
+ IN: [
1214
+ { columns: ['id'], values: User.select('id') },
1215
+ { columns: ['name'], values: User.select('name') },
1216
+ ],
1217
+ },
1218
+ },
1219
+ ],
1220
+ }),
1221
+ ),
1222
+ buildSql((q) =>
1223
+ q.where({ id: 1 }).orWhereNotIn({
1224
+ id: User.select('id'),
1225
+ name: User.select('name'),
1226
+ }),
1227
+ ),
1228
+ ],
1229
+ `
1230
+ ${startSql}
1231
+ "user"."id" = $1
1232
+ OR NOT "user"."id" IN (SELECT "user"."id" FROM "user")
1233
+ AND NOT "user"."name" IN (SELECT "user"."name" FROM "user")
1234
+ `,
1235
+ [1],
1236
+ );
1237
+ });
1238
+
1239
+ describe('tuple', () => {
1240
+ it('should handle values', () => {
1241
+ expectSql(
1242
+ [
1243
+ buildSql((q) =>
1244
+ q.where({
1245
+ OR: [
1246
+ { id: 1 },
1247
+ {
1248
+ NOT: {
1249
+ IN: {
1250
+ columns: ['id', 'name'],
1251
+ values: [
1252
+ [1, 'a'],
1253
+ [2, 'b'],
1254
+ ],
1255
+ },
1256
+ },
1257
+ },
1258
+ ],
1259
+ }),
1260
+ ),
1261
+ buildSql((q) =>
1262
+ q.where({ id: 1 }).orWhereNotIn(
1263
+ ['id', 'name'],
1264
+ [
1265
+ [1, 'a'],
1266
+ [2, 'b'],
1267
+ ],
1268
+ ),
1269
+ ),
1270
+ ],
1271
+ `
1272
+ ${startSql}
1273
+ "user"."id" = $1
1274
+ OR NOT ("user"."id", "user"."name") IN (($2, $3), ($4, $5))
1275
+ `,
1276
+ [1, 1, 'a', 2, 'b'],
1277
+ );
1278
+ });
1279
+
1280
+ it('should handle raw query', () => {
1281
+ expectSql(
1282
+ [
1283
+ buildSql((q) =>
1284
+ q.where({
1285
+ OR: [
1286
+ { id: 1 },
1287
+ {
1288
+ NOT: {
1289
+ IN: {
1290
+ columns: ['id', 'name'],
1291
+ values: raw(`((1, 'a'), (2, 'b'))`),
1292
+ },
1293
+ },
1294
+ },
1295
+ ],
1296
+ }),
1297
+ ),
1298
+ buildSql((q) =>
1299
+ q
1300
+ .where({ id: 1 })
1301
+ .orWhereNotIn(['id', 'name'], raw(`((1, 'a'), (2, 'b'))`)),
1302
+ ),
1303
+ ],
1304
+ `
1305
+ ${startSql}
1306
+ "user"."id" = $1
1307
+ OR NOT ("user"."id", "user"."name") IN ((1, 'a'), (2, 'b'))
1308
+ `,
1309
+ [1],
1310
+ );
1311
+ });
1312
+
1313
+ it('should handle sub query', () => {
1314
+ expectSql(
1315
+ [
1316
+ buildSql((q) =>
1317
+ q.where({
1318
+ OR: [
1319
+ { id: 1 },
1320
+ {
1321
+ NOT: {
1322
+ IN: {
1323
+ columns: ['id', 'name'],
1324
+ values: User.select('id', 'name'),
1325
+ },
1326
+ },
1327
+ },
1328
+ ],
1329
+ }),
1330
+ ),
1331
+ buildSql((q) =>
1332
+ q
1333
+ .where({ id: 1 })
1334
+ .orWhereNotIn(['id', 'name'], User.select('id', 'name')),
1335
+ ),
1336
+ ],
1337
+ `
1338
+ ${startSql}
1339
+ "user"."id" = $1
1340
+ OR NOT ("user"."id", "user"."name")
1341
+ IN (SELECT "user"."id", "user"."name" FROM "user")
1342
+ `,
1343
+ [1],
1344
+ );
1345
+ });
1346
+ });
1347
+ });
1348
+
1349
+ describe('whereExists', () => {
1350
+ testJoin(
1351
+ 'whereExists',
1352
+ (target: string, conditions: string) => `
1353
+ SELECT * FROM "user"
1354
+ WHERE EXISTS (
1355
+ SELECT 1 FROM ${target}
1356
+ WHERE ${conditions}
1357
+ LIMIT 1
1358
+ )
1359
+ `,
1360
+ );
1361
+ });
1362
+
1363
+ describe('orWhereExists', () => {
1364
+ testJoin(
1365
+ 'orWhereExists',
1366
+ (target: string, conditions: string) => `
1367
+ SELECT * FROM "user"
1368
+ WHERE "user"."id" = $1 OR EXISTS (
1369
+ SELECT 1 FROM ${target}
1370
+ WHERE ${conditions}
1371
+ LIMIT 1
1372
+ )
1373
+ `,
1374
+ User.where({ id: 1 }),
1375
+ [1],
1376
+ );
1377
+ });
1378
+
1379
+ describe('whereNotExists', () => {
1380
+ testJoin(
1381
+ 'whereNotExists',
1382
+ (target: string, conditions: string) => `
1383
+ SELECT * FROM "user"
1384
+ WHERE NOT EXISTS (
1385
+ SELECT 1 FROM ${target}
1386
+ WHERE ${conditions}
1387
+ LIMIT 1
1388
+ )
1389
+ `,
1390
+ );
1391
+ });
1392
+
1393
+ describe('orWhereNotExists', () => {
1394
+ testJoin(
1395
+ 'orWhereNotExists',
1396
+ (target: string, conditions: string) => `
1397
+ SELECT * FROM "user"
1398
+ WHERE "user"."id" = $1 OR NOT EXISTS (
1399
+ SELECT 1 FROM ${target}
1400
+ WHERE ${conditions}
1401
+ LIMIT 1
1402
+ )
1403
+ `,
1404
+ User.where({ id: 1 }),
1405
+ [1],
1406
+ );
1407
+ });
1408
+ };
1409
+
1410
+ export const testJoin = (
1411
+ method: string,
1412
+ sql: (target: string, conditions: string) => string,
1413
+ q: Query = User.all(),
1414
+ values: unknown[] = [],
1415
+ ) => {
1416
+ const join = method as unknown as 'join';
1417
+ const initialSql = q.toSql().text;
1418
+
1419
+ it('should accept left column and right column', () => {
1420
+ expectSql(
1421
+ q[join](Message, 'authorId', 'id').toSql(),
1422
+ sql(`"message"`, `"message"."authorId" = "user"."id"`),
1423
+ values,
1424
+ );
1425
+ expectSql(
1426
+ q[join](Message.as('as'), 'authorId', 'id').toSql(),
1427
+ sql(`"message" AS "as"`, `"as"."authorId" = "user"."id"`),
1428
+ values,
1429
+ );
1430
+ expect(q.toSql().text).toBe(initialSql);
1431
+ });
1432
+
1433
+ it('should accept left column, op and right column', () => {
1434
+ expectSql(
1435
+ q[join](Message, 'authorId', '=', 'id').toSql(),
1436
+ sql(`"message"`, `"message"."authorId" = "user"."id"`),
1437
+ values,
1438
+ );
1439
+ expectSql(
1440
+ q[join](Message.as('as'), 'authorId', '=', 'id').toSql(),
1441
+ sql(`"message" AS "as"`, `"as"."authorId" = "user"."id"`),
1442
+ values,
1443
+ );
1444
+ expect(q.toSql().text).toBe(initialSql);
1445
+ });
1446
+
1447
+ it('should accept raw and raw', () => {
1448
+ expectSql(
1449
+ q[join](Message, raw('"message"."authorId"'), raw('"user"."id"')).toSql(),
1450
+ sql(`"message"`, `"message"."authorId" = "user"."id"`),
1451
+ values,
1452
+ );
1453
+ expectSql(
1454
+ q[join](
1455
+ Message.as('as'),
1456
+ raw('"as"."authorId"'),
1457
+ raw('"user"."id"'),
1458
+ ).toSql(),
1459
+ sql(`"message" AS "as"`, `"as"."authorId" = "user"."id"`),
1460
+ values,
1461
+ );
1462
+ expect(q.toSql().text).toBe(initialSql);
1463
+ });
1464
+
1465
+ it('should accept raw, op and raw', () => {
1466
+ expectSql(
1467
+ q[join](
1468
+ Message,
1469
+ raw('"message"."authorId"'),
1470
+ '=',
1471
+ raw('"user"."id"'),
1472
+ ).toSql(),
1473
+ sql(`"message"`, `"message"."authorId" = "user"."id"`),
1474
+ values,
1475
+ );
1476
+ expectSql(
1477
+ q[join](
1478
+ Message.as('as'),
1479
+ raw('"as"."authorId"'),
1480
+ '=',
1481
+ raw('"user"."id"'),
1482
+ ).toSql(),
1483
+ sql(`"message" AS "as"`, `"as"."authorId" = "user"."id"`),
1484
+ values,
1485
+ );
1486
+ expect(q.toSql().text).toBe(initialSql);
1487
+ });
1488
+
1489
+ it('should accept object of columns', () => {
1490
+ expectSql(
1491
+ q[join](Message, { authorId: 'id' }).toSql(),
1492
+ sql(`"message"`, `"message"."authorId" = "user"."id"`),
1493
+ values,
1494
+ );
1495
+ expectSql(
1496
+ q[join](Message.as('as'), { authorId: 'id' }).toSql(),
1497
+ sql(`"message" AS "as"`, `"as"."authorId" = "user"."id"`),
1498
+ values,
1499
+ );
1500
+ expect(q.toSql().text).toBe(initialSql);
1501
+ });
1502
+
1503
+ it('should accept object of columns with raw value', () => {
1504
+ expectSql(
1505
+ q[join](Message, { authorId: raw('"user"."id"') }).toSql(),
1506
+ sql(`"message"`, `"message"."authorId" = "user"."id"`),
1507
+ values,
1508
+ );
1509
+ expectSql(
1510
+ q[join](Message.as('as'), { authorId: raw('"user"."id"') }).toSql(),
1511
+ sql(`"message" AS "as"`, `"as"."authorId" = "user"."id"`),
1512
+ values,
1513
+ );
1514
+ expect(q.toSql().text).toBe(initialSql);
1515
+ });
1516
+
1517
+ it('should accept raw sql', () => {
1518
+ expectSql(
1519
+ q[join](Message, raw('"authorId" = "user".id')).toSql(),
1520
+ sql(`"message"`, `"authorId" = "user".id`),
1521
+ values,
1522
+ );
1523
+ expectSql(
1524
+ q[join](Message.as('as'), raw('"authorId" = "user".id')).toSql(),
1525
+ sql(`"message" AS "as"`, `"authorId" = "user".id`),
1526
+ values,
1527
+ );
1528
+ expect(q.toSql().text).toBe(initialSql);
1529
+ });
1530
+
1531
+ it('should use conditions from provided query', () => {
1532
+ expectSql(
1533
+ q[join](Message.where({ text: 'text' }), (q) =>
1534
+ q.on('authorId', 'id'),
1535
+ ).toSql(),
1536
+ sql(
1537
+ `"message"`,
1538
+ `"message"."authorId" = "user"."id" AND "message"."text" = $${
1539
+ values.length + 1
1540
+ }`,
1541
+ ),
1542
+ [...values, 'text'],
1543
+ );
1544
+ });
1545
+
1546
+ describe('relation', () => {
1547
+ const withRelation = q as Query & {
1548
+ relations: {
1549
+ message: { key: 'message'; model: typeof Message; joinQuery: Query };
1550
+ };
1551
+ };
1552
+
1553
+ withRelation.relations = {
1554
+ message: {
1555
+ key: 'message',
1556
+ model: Message,
1557
+ joinQuery: pushQueryOn(Message.clone(), Message, q, 'authorId', 'id'),
1558
+ },
1559
+ };
1560
+
1561
+ it('should join relation', () => {
1562
+ expectSql(
1563
+ withRelation[join]('message').toSql(),
1564
+ sql(`"message"`, `"message"."authorId" = "user"."id"`),
1565
+ values,
1566
+ );
1567
+ });
1568
+
1569
+ it('should join relation with additional conditions', () => {
1570
+ expectSql(
1571
+ withRelation[join]('message', (q) =>
1572
+ q.where({
1573
+ 'message.text': 'text',
1574
+ }),
1575
+ ).toSql(),
1576
+ sql(
1577
+ `"message"`,
1578
+ `"message"."authorId" = "user"."id" AND "message"."text" = $${
1579
+ values.length + 1
1580
+ }`,
1581
+ ),
1582
+ [...values, 'text'],
1583
+ );
1584
+ });
1585
+ });
1586
+ };
1587
+
1588
+ const buildSql = (cb: (q: Query) => Query) => {
1589
+ return cb(User.all()).toSql();
1590
+ };
1591
+
1592
+ const startSql = `SELECT * FROM "user" WHERE`;
1593
+
1594
+ testWhere(buildSql, startSql);