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