@xata.io/drizzle 0.0.0-alpha.ve565538 → 0.0.0-alpha.ve69ec6a

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.
@@ -0,0 +1,2187 @@
1
+ import { getHostUrl, parseProviderString, XataApiClient } from '@xata.io/client';
2
+ import type { TestFn } from 'ava';
3
+ import anyTest from 'ava';
4
+ import dotenv from 'dotenv';
5
+ import {
6
+ and,
7
+ asc,
8
+ eq,
9
+ gt,
10
+ gte,
11
+ inArray,
12
+ lt,
13
+ name,
14
+ placeholder,
15
+ sql,
16
+ TransactionRollbackError,
17
+ type SQL,
18
+ type SQLWrapper
19
+ } from 'drizzle-orm';
20
+ import {
21
+ alias,
22
+ boolean,
23
+ char,
24
+ cidr,
25
+ getMaterializedViewConfig,
26
+ getViewConfig,
27
+ inet,
28
+ integer,
29
+ jsonb,
30
+ macaddr,
31
+ macaddr8,
32
+ pgEnum,
33
+ pgMaterializedView,
34
+ pgTable,
35
+ pgTableCreator,
36
+ uuid as pgUuid,
37
+ pgView,
38
+ serial,
39
+ text,
40
+ timestamp,
41
+ varchar,
42
+ type PgColumn
43
+ } from 'drizzle-orm/pg-core';
44
+ import { migrate } from 'drizzle-orm/vercel-postgres/migrator';
45
+ import fetch from 'node-fetch';
46
+ import { join } from 'path';
47
+ import { v4 as uuid } from 'uuid';
48
+ import { drizzle, type XataDatabase } from '../src';
49
+ import { Expect, type Equal } from './utils';
50
+ import { tables, XataClient } from './xata.codegen';
51
+
52
+ const ENABLE_LOGGING = false;
53
+
54
+ // Get environment variables before reading them
55
+ dotenv.config({ path: join(process.cwd(), '.env') });
56
+
57
+ const apiKey = process.env.XATA_API_KEY ?? '';
58
+ if (apiKey === '') throw new Error('XATA_API_KEY environment variable is not set');
59
+
60
+ const workspace = process.env.XATA_WORKSPACE ?? '';
61
+ if (workspace === '') throw new Error('XATA_WORKSPACE environment variable is not set');
62
+
63
+ const region = process.env.XATA_REGION || 'eu-west-1';
64
+
65
+ const host = parseProviderString(process.env.XATA_API_PROVIDER);
66
+ if (host === null) {
67
+ throw new Error(
68
+ `Invalid XATA_API_PROVIDER environment variable, expected either "production", "staging" or "apiUrl,workspacesUrl"`
69
+ );
70
+ }
71
+
72
+ const usersTable = pgTable('users', {
73
+ id: serial('id').primaryKey(),
74
+ name: text('name').notNull(),
75
+ verified: boolean('verified').notNull().default(false),
76
+ jsonb: jsonb('jsonb').$type<string[]>(),
77
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow()
78
+ });
79
+
80
+ const citiesTable = pgTable('cities', {
81
+ id: serial('id').primaryKey(),
82
+ name: text('name').notNull(),
83
+ state: char('state', { length: 2 })
84
+ });
85
+
86
+ const users2Table = pgTable('users2', {
87
+ id: serial('id').primaryKey(),
88
+ name: text('name').notNull(),
89
+ cityId: integer('city_id').references(() => citiesTable.id)
90
+ });
91
+
92
+ const coursesTable = pgTable('courses', {
93
+ id: serial('id').primaryKey(),
94
+ name: text('name').notNull(),
95
+ categoryId: integer('category_id').references(() => courseCategoriesTable.id)
96
+ });
97
+
98
+ const courseCategoriesTable = pgTable('course_categories', {
99
+ id: serial('id').primaryKey(),
100
+ name: text('name').notNull()
101
+ });
102
+
103
+ const orders = pgTable('orders', {
104
+ id: serial('id').primaryKey(),
105
+ region: text('region').notNull(),
106
+ product: text('product').notNull(),
107
+ amount: integer('amount').notNull(),
108
+ quantity: integer('quantity').notNull()
109
+ });
110
+
111
+ const network = pgTable('network_table', {
112
+ inet: inet('inet').notNull(),
113
+ cidr: cidr('cidr').notNull(),
114
+ macaddr: macaddr('macaddr').notNull(),
115
+ macaddr8: macaddr8('macaddr8').notNull()
116
+ });
117
+
118
+ const salEmp = pgTable('sal_emp', {
119
+ name: text('name'),
120
+ payByQuarter: integer('pay_by_quarter').array(),
121
+ schedule: text('schedule').array().array()
122
+ });
123
+
124
+ const _tictactoe = pgTable('tictactoe', {
125
+ squares: integer('squares').array(3).array(3)
126
+ });
127
+
128
+ const usersMigratorTable = pgTable('users12', {
129
+ id: serial('id').primaryKey(),
130
+ name: text('name').notNull(),
131
+ email: text('email').notNull()
132
+ });
133
+
134
+ interface Context {
135
+ id: string;
136
+ db: XataDatabase;
137
+ client: XataClient;
138
+ api: XataApiClient;
139
+ }
140
+
141
+ const test = anyTest as TestFn<Context>;
142
+
143
+ test.before(async (t) => {
144
+ const ctx = t.context;
145
+ ctx.api = new XataApiClient({ apiKey, fetch, host, clientName: 'sdk-tests' });
146
+ });
147
+
148
+ test.beforeEach(async (t) => {
149
+ const ctx = t.context;
150
+ ctx.id = Date.now().toString(36);
151
+
152
+ const { databaseName: database } = await ctx.api.database.createDatabase({
153
+ workspace,
154
+ database: `sdk-integration-test-drizzle-${ctx.id}`,
155
+ data: { region },
156
+ headers: { 'X-Xata-Files': 'true' }
157
+ });
158
+
159
+ const { edits } = await ctx.api.migrations.compareBranchWithUserSchema({
160
+ workspace,
161
+ region,
162
+ database,
163
+ branch: 'main',
164
+ schema: { tables: tables as any }
165
+ });
166
+
167
+ await ctx.api.migrations.applyBranchSchemaEdit({ workspace, region, database, branch: 'main', edits });
168
+
169
+ const workspaceUrl = getHostUrl(host, 'workspaces').replace('{workspaceId}', workspace).replace('{region}', region);
170
+
171
+ ctx.client = new XataClient({
172
+ databaseURL: `${workspaceUrl}/db/${database}`,
173
+ branch: 'main',
174
+ apiKey,
175
+ fetch,
176
+ clientName: 'sdk-tests'
177
+ });
178
+
179
+ ctx.db = drizzle(ctx.client, { logger: ENABLE_LOGGING });
180
+ });
181
+
182
+ test.afterEach.always(async (t) => {
183
+ const ctx = t.context;
184
+
185
+ await ctx.api.database.deleteDatabase({ workspace, database: `sdk-integration-test-drizzle-${ctx.id}` });
186
+ });
187
+
188
+ test.skip('select all fields', async (t) => {
189
+ const { db } = t.context;
190
+
191
+ const now = Date.now();
192
+
193
+ await db.insert(usersTable).values({ name: 'John' });
194
+ const result = await db.select().from(usersTable);
195
+
196
+ t.assert(result[0]!.createdAt instanceof Date);
197
+ t.assert(Math.abs(result[0]!.createdAt.getTime() - now) < 100);
198
+ t.deepEqual(result, [{ id: 1, name: 'John', verified: false, jsonb: null, createdAt: result[0]!.createdAt }]);
199
+ });
200
+
201
+ test.skip('select sql', async (t) => {
202
+ const { db } = t.context;
203
+
204
+ await db.insert(usersTable).values({ name: 'John' });
205
+ const users = await db
206
+ .select({
207
+ name: sql`upper(${usersTable.name})`
208
+ })
209
+ .from(usersTable);
210
+
211
+ t.deepEqual(users, [{ name: 'JOHN' }]);
212
+ });
213
+
214
+ test.skip('select typed sql', async (t) => {
215
+ const { db } = t.context;
216
+
217
+ await db.insert(usersTable).values({ name: 'John' });
218
+
219
+ const users = await db
220
+ .select({
221
+ name: sql<string>`upper(${usersTable.name})`
222
+ })
223
+ .from(usersTable);
224
+
225
+ t.deepEqual(users, [{ name: 'JOHN' }]);
226
+ });
227
+
228
+ test.skip('select distinct', async (t) => {
229
+ const { db } = t.context;
230
+
231
+ const usersDistinctTable = pgTable('users_distinct', {
232
+ id: integer('id').notNull(),
233
+ name: text('name').notNull()
234
+ });
235
+
236
+ await db.execute(sql`drop table if exists ${usersDistinctTable}`);
237
+ await db.execute(sql`create table ${usersDistinctTable} (id integer, name text)`);
238
+
239
+ await db.insert(usersDistinctTable).values([
240
+ { id: 1, name: 'John' },
241
+ { id: 1, name: 'John' },
242
+ { id: 2, name: 'John' },
243
+ { id: 1, name: 'Jane' }
244
+ ]);
245
+ const users1 = await db
246
+ .selectDistinct()
247
+ .from(usersDistinctTable)
248
+ .orderBy(usersDistinctTable.id, usersDistinctTable.name);
249
+ const users2 = await db
250
+ .selectDistinctOn([usersDistinctTable.id])
251
+ .from(usersDistinctTable)
252
+ .orderBy(usersDistinctTable.id);
253
+ const users3 = await db
254
+ .selectDistinctOn([usersDistinctTable.name], { name: usersDistinctTable.name })
255
+ .from(usersDistinctTable)
256
+ .orderBy(usersDistinctTable.name);
257
+
258
+ await db.execute(sql`drop table ${usersDistinctTable}`);
259
+
260
+ t.deepEqual(users1, [
261
+ { id: 1, name: 'Jane' },
262
+ { id: 1, name: 'John' },
263
+ { id: 2, name: 'John' }
264
+ ]);
265
+
266
+ t.deepEqual(users2.length, 2);
267
+ t.deepEqual(users2[0]?.id, 1);
268
+ t.deepEqual(users2[1]?.id, 2);
269
+
270
+ t.deepEqual(users3.length, 2);
271
+ t.deepEqual(users3[0]?.name, 'Jane');
272
+ t.deepEqual(users3[1]?.name, 'John');
273
+ });
274
+
275
+ test.skip('insert returning sql', async (t) => {
276
+ const { db } = t.context;
277
+
278
+ const users = await db
279
+ .insert(usersTable)
280
+ .values({ name: 'John' })
281
+ .returning({
282
+ name: sql`upper(${usersTable.name})`
283
+ });
284
+
285
+ t.deepEqual(users, [{ name: 'JOHN' }]);
286
+ });
287
+
288
+ test.skip('delete returning sql', async (t) => {
289
+ const { db } = t.context;
290
+
291
+ await db.insert(usersTable).values({ name: 'John' });
292
+ const users = await db
293
+ .delete(usersTable)
294
+ .where(eq(usersTable.name, 'John'))
295
+ .returning({
296
+ name: sql`upper(${usersTable.name})`
297
+ });
298
+
299
+ t.deepEqual(users, [{ name: 'JOHN' }]);
300
+ });
301
+
302
+ test.skip('update returning sql', async (t) => {
303
+ const { db } = t.context;
304
+
305
+ await db.insert(usersTable).values({ name: 'John' });
306
+ const users = await db
307
+ .update(usersTable)
308
+ .set({ name: 'Jane' })
309
+ .where(eq(usersTable.name, 'John'))
310
+ .returning({
311
+ name: sql`upper(${usersTable.name})`
312
+ });
313
+
314
+ t.deepEqual(users, [{ name: 'JANE' }]);
315
+ });
316
+
317
+ test.skip('update with returning all fields', async (t) => {
318
+ const { db } = t.context;
319
+
320
+ const now = Date.now();
321
+
322
+ await db.insert(usersTable).values({ name: 'John' });
323
+ const users = await db.update(usersTable).set({ name: 'Jane' }).where(eq(usersTable.name, 'John')).returning();
324
+
325
+ t.assert(users[0]!.createdAt instanceof Date);
326
+ t.assert(Math.abs(users[0]!.createdAt.getTime() - now) < 100);
327
+ t.deepEqual(users, [{ id: 1, name: 'Jane', verified: false, jsonb: null, createdAt: users[0]!.createdAt }]);
328
+ });
329
+
330
+ test.skip('update with returning partial', async (t) => {
331
+ const { db } = t.context;
332
+
333
+ await db.insert(usersTable).values({ name: 'John' });
334
+ const users = await db.update(usersTable).set({ name: 'Jane' }).where(eq(usersTable.name, 'John')).returning({
335
+ id: usersTable.id,
336
+ name: usersTable.name
337
+ });
338
+
339
+ t.deepEqual(users, [{ id: 1, name: 'Jane' }]);
340
+ });
341
+
342
+ test.skip('delete with returning all fields', async (t) => {
343
+ const { db } = t.context;
344
+
345
+ const now = Date.now();
346
+
347
+ await db.insert(usersTable).values({ name: 'John' });
348
+ const users = await db.delete(usersTable).where(eq(usersTable.name, 'John')).returning();
349
+
350
+ t.assert(users[0]!.createdAt instanceof Date);
351
+ t.assert(Math.abs(users[0]!.createdAt.getTime() - now) < 100);
352
+ t.deepEqual(users, [{ id: 1, name: 'John', verified: false, jsonb: null, createdAt: users[0]!.createdAt }]);
353
+ });
354
+
355
+ test.skip('delete with returning partial', async (t) => {
356
+ const { db } = t.context;
357
+
358
+ await db.insert(usersTable).values({ name: 'John' });
359
+ const users = await db.delete(usersTable).where(eq(usersTable.name, 'John')).returning({
360
+ id: usersTable.id,
361
+ name: usersTable.name
362
+ });
363
+
364
+ t.deepEqual(users, [{ id: 1, name: 'John' }]);
365
+ });
366
+
367
+ test.skip('insert + select', async (t) => {
368
+ const { db } = t.context;
369
+
370
+ await db.insert(usersTable).values({ name: 'John' });
371
+ const result = await db.select().from(usersTable);
372
+ t.deepEqual(result, [{ id: 1, name: 'John', verified: false, jsonb: null, createdAt: result[0]!.createdAt }]);
373
+
374
+ await db.insert(usersTable).values({ name: 'Jane' });
375
+ const result2 = await db.select().from(usersTable);
376
+ t.deepEqual(result2, [
377
+ { id: 1, name: 'John', verified: false, jsonb: null, createdAt: result2[0]!.createdAt },
378
+ { id: 2, name: 'Jane', verified: false, jsonb: null, createdAt: result2[1]!.createdAt }
379
+ ]);
380
+ });
381
+
382
+ test.skip('json insert', async (t) => {
383
+ const { db } = t.context;
384
+
385
+ await db.insert(usersTable).values({ name: 'John', jsonb: ['foo', 'bar'] });
386
+ const result = await db
387
+ .select({
388
+ id: usersTable.id,
389
+ name: usersTable.name,
390
+ jsonb: usersTable.jsonb
391
+ })
392
+ .from(usersTable);
393
+
394
+ t.deepEqual(result, [{ id: 1, name: 'John', jsonb: ['foo', 'bar'] }]);
395
+ });
396
+
397
+ test.skip('char insert', async (t) => {
398
+ const { db } = t.context;
399
+
400
+ await db.insert(citiesTable).values({ name: 'Austin', state: 'TX' });
401
+ const result = await db
402
+ .select({ id: citiesTable.id, name: citiesTable.name, state: citiesTable.state })
403
+ .from(citiesTable);
404
+
405
+ t.deepEqual(result, [{ id: 1, name: 'Austin', state: 'TX' }]);
406
+ });
407
+
408
+ test.skip('char update', async (t) => {
409
+ const { db } = t.context;
410
+
411
+ await db.insert(citiesTable).values({ name: 'Austin', state: 'TX' });
412
+ await db.update(citiesTable).set({ name: 'Atlanta', state: 'GA' }).where(eq(citiesTable.id, 1));
413
+ const result = await db
414
+ .select({ id: citiesTable.id, name: citiesTable.name, state: citiesTable.state })
415
+ .from(citiesTable);
416
+
417
+ t.deepEqual(result, [{ id: 1, name: 'Atlanta', state: 'GA' }]);
418
+ });
419
+
420
+ test.skip('char delete', async (t) => {
421
+ const { db } = t.context;
422
+
423
+ await db.insert(citiesTable).values({ name: 'Austin', state: 'TX' });
424
+ await db.delete(citiesTable).where(eq(citiesTable.state, 'TX'));
425
+ const result = await db
426
+ .select({ id: citiesTable.id, name: citiesTable.name, state: citiesTable.state })
427
+ .from(citiesTable);
428
+
429
+ t.deepEqual(result, []);
430
+ });
431
+
432
+ test.skip('insert with overridden default values', async (t) => {
433
+ const { db } = t.context;
434
+
435
+ await db.insert(usersTable).values({ name: 'John', verified: true });
436
+ const result = await db.select().from(usersTable);
437
+
438
+ t.deepEqual(result, [{ id: 1, name: 'John', verified: true, jsonb: null, createdAt: result[0]!.createdAt }]);
439
+ });
440
+
441
+ test.skip('insert many', async (t) => {
442
+ const { db } = t.context;
443
+
444
+ await db
445
+ .insert(usersTable)
446
+ .values([
447
+ { name: 'John' },
448
+ { name: 'Bruce', jsonb: ['foo', 'bar'] },
449
+ { name: 'Jane' },
450
+ { name: 'Austin', verified: true }
451
+ ]);
452
+ const result = await db
453
+ .select({
454
+ id: usersTable.id,
455
+ name: usersTable.name,
456
+ jsonb: usersTable.jsonb,
457
+ verified: usersTable.verified
458
+ })
459
+ .from(usersTable);
460
+
461
+ t.deepEqual(result, [
462
+ { id: 1, name: 'John', jsonb: null, verified: false },
463
+ { id: 2, name: 'Bruce', jsonb: ['foo', 'bar'], verified: false },
464
+ { id: 3, name: 'Jane', jsonb: null, verified: false },
465
+ { id: 4, name: 'Austin', jsonb: null, verified: true }
466
+ ]);
467
+ });
468
+
469
+ test.skip('insert many with returning', async (t) => {
470
+ const { db } = t.context;
471
+
472
+ const result = await db
473
+ .insert(usersTable)
474
+ .values([
475
+ { name: 'John' },
476
+ { name: 'Bruce', jsonb: ['foo', 'bar'] },
477
+ { name: 'Jane' },
478
+ { name: 'Austin', verified: true }
479
+ ])
480
+ .returning({
481
+ id: usersTable.id,
482
+ name: usersTable.name,
483
+ jsonb: usersTable.jsonb,
484
+ verified: usersTable.verified
485
+ });
486
+
487
+ t.deepEqual(result, [
488
+ { id: 1, name: 'John', jsonb: null, verified: false },
489
+ { id: 2, name: 'Bruce', jsonb: ['foo', 'bar'], verified: false },
490
+ { id: 3, name: 'Jane', jsonb: null, verified: false },
491
+ { id: 4, name: 'Austin', jsonb: null, verified: true }
492
+ ]);
493
+ });
494
+
495
+ test.skip('select with group by as field', async (t) => {
496
+ const { db } = t.context;
497
+
498
+ await db.insert(usersTable).values([{ name: 'John' }, { name: 'Jane' }, { name: 'Jane' }]);
499
+
500
+ const result = await db.select({ name: usersTable.name }).from(usersTable).groupBy(usersTable.name);
501
+
502
+ t.deepEqual(result, [{ name: 'Jane' }, { name: 'John' }]);
503
+ });
504
+
505
+ test.skip('select with group by as sql', async (t) => {
506
+ const { db } = t.context;
507
+
508
+ await db.insert(usersTable).values([{ name: 'John' }, { name: 'Jane' }, { name: 'Jane' }]);
509
+
510
+ const result = await db
511
+ .select({ name: usersTable.name })
512
+ .from(usersTable)
513
+ .groupBy(sql`${usersTable.name}`);
514
+
515
+ t.deepEqual(result, [{ name: 'Jane' }, { name: 'John' }]);
516
+ });
517
+
518
+ test.skip('select with group by as sql + column', async (t) => {
519
+ const { db } = t.context;
520
+
521
+ await db.insert(usersTable).values([{ name: 'John' }, { name: 'Jane' }, { name: 'Jane' }]);
522
+
523
+ const result = await db
524
+ .select({ name: usersTable.name })
525
+ .from(usersTable)
526
+ .groupBy(sql`${usersTable.name}`, usersTable.id);
527
+
528
+ t.deepEqual(result, [{ name: 'Jane' }, { name: 'Jane' }, { name: 'John' }]);
529
+ });
530
+
531
+ test.skip('select with group by as column + sql', async (t) => {
532
+ const { db } = t.context;
533
+
534
+ await db.insert(usersTable).values([{ name: 'John' }, { name: 'Jane' }, { name: 'Jane' }]);
535
+
536
+ const result = await db
537
+ .select({ name: usersTable.name })
538
+ .from(usersTable)
539
+ .groupBy(usersTable.id, sql`${usersTable.name}`);
540
+
541
+ t.deepEqual(result, [{ name: 'Jane' }, { name: 'Jane' }, { name: 'John' }]);
542
+ });
543
+
544
+ test.skip('select with group by complex query', async (t) => {
545
+ const { db } = t.context;
546
+
547
+ await db.insert(usersTable).values([{ name: 'John' }, { name: 'Jane' }, { name: 'Jane' }]);
548
+
549
+ const result = await db
550
+ .select({ name: usersTable.name })
551
+ .from(usersTable)
552
+ .groupBy(usersTable.id, sql`${usersTable.name}`)
553
+ .orderBy(asc(usersTable.name))
554
+ .limit(1);
555
+
556
+ t.deepEqual(result, [{ name: 'Jane' }]);
557
+ });
558
+
559
+ test('build query', async (t) => {
560
+ const { db } = t.context;
561
+
562
+ const query = db
563
+ .select({ id: usersTable.id, name: usersTable.name })
564
+ .from(usersTable)
565
+ .groupBy(usersTable.id, usersTable.name)
566
+ .toSQL();
567
+
568
+ t.deepEqual(query, {
569
+ sql: 'select "id", "name" from "users" group by "users"."id", "users"."name"',
570
+ params: []
571
+ });
572
+ });
573
+
574
+ test.skip('insert sql', async (t) => {
575
+ const { db } = t.context;
576
+
577
+ await db.insert(usersTable).values({ name: sql`${'John'}` });
578
+ const result = await db.select({ id: usersTable.id, name: usersTable.name }).from(usersTable);
579
+ t.deepEqual(result, [{ id: 1, name: 'John' }]);
580
+ });
581
+
582
+ test.skip('partial join with alias', async (t) => {
583
+ const { db } = t.context;
584
+ const customerAlias = alias(usersTable, 'customer');
585
+
586
+ await db.insert(usersTable).values([
587
+ { id: 10, name: 'Ivan' },
588
+ { id: 11, name: 'Hans' }
589
+ ]);
590
+ const result = await db
591
+ .select({
592
+ user: {
593
+ id: usersTable.id,
594
+ name: usersTable.name
595
+ },
596
+ customer: {
597
+ id: customerAlias.id,
598
+ name: customerAlias.name
599
+ }
600
+ })
601
+ .from(usersTable)
602
+ .leftJoin(customerAlias, eq(customerAlias.id, 11))
603
+ .where(eq(usersTable.id, 10));
604
+
605
+ t.deepEqual(result, [
606
+ {
607
+ user: { id: 10, name: 'Ivan' },
608
+ customer: { id: 11, name: 'Hans' }
609
+ }
610
+ ]);
611
+ });
612
+
613
+ test.skip('full join with alias', async (t) => {
614
+ const { db } = t.context;
615
+
616
+ const pgTable = pgTableCreator((name) => `prefixed_${name}`);
617
+
618
+ const users = pgTable('users', {
619
+ id: serial('id').primaryKey(),
620
+ name: text('name').notNull()
621
+ });
622
+
623
+ await db.execute(sql`drop table if exists ${users}`);
624
+ await db.execute(sql`create table ${users} (id serial primary key, name text not null)`);
625
+
626
+ const customers = alias(users, 'customer');
627
+
628
+ await db.insert(users).values([
629
+ { id: 10, name: 'Ivan' },
630
+ { id: 11, name: 'Hans' }
631
+ ]);
632
+ const result = await db.select().from(users).leftJoin(customers, eq(customers.id, 11)).where(eq(users.id, 10));
633
+
634
+ t.deepEqual(result, [
635
+ {
636
+ users: {
637
+ id: 10,
638
+ name: 'Ivan'
639
+ },
640
+ customer: {
641
+ id: 11,
642
+ name: 'Hans'
643
+ }
644
+ }
645
+ ]);
646
+
647
+ await db.execute(sql`drop table ${users}`);
648
+ });
649
+
650
+ test.skip('select from alias', async (t) => {
651
+ const { db } = t.context;
652
+
653
+ const pgTable = pgTableCreator((name) => `prefixed_${name}`);
654
+
655
+ const users = pgTable('users', {
656
+ id: serial('id').primaryKey(),
657
+ name: text('name').notNull()
658
+ });
659
+
660
+ await db.execute(sql`drop table if exists ${users}`);
661
+ await db.execute(sql`create table ${users} (id serial primary key, name text not null)`);
662
+
663
+ const user = alias(users, 'user');
664
+ const customers = alias(users, 'customer');
665
+
666
+ await db.insert(users).values([
667
+ { id: 10, name: 'Ivan' },
668
+ { id: 11, name: 'Hans' }
669
+ ]);
670
+ const result = await db.select().from(user).leftJoin(customers, eq(customers.id, 11)).where(eq(user.id, 10));
671
+
672
+ t.deepEqual(result, [
673
+ {
674
+ user: {
675
+ id: 10,
676
+ name: 'Ivan'
677
+ },
678
+ customer: {
679
+ id: 11,
680
+ name: 'Hans'
681
+ }
682
+ }
683
+ ]);
684
+
685
+ await db.execute(sql`drop table ${users}`);
686
+ });
687
+
688
+ test.skip('insert with spaces', async (t) => {
689
+ const { db } = t.context;
690
+
691
+ await db.insert(usersTable).values({ name: sql`'Jo h n'` });
692
+ const result = await db.select({ id: usersTable.id, name: usersTable.name }).from(usersTable);
693
+
694
+ t.deepEqual(result, [{ id: 1, name: 'Jo h n' }]);
695
+ });
696
+
697
+ test.skip('prepared statement', async (t) => {
698
+ const { db } = t.context;
699
+
700
+ await db.insert(usersTable).values({ name: 'John' });
701
+ const statement = db
702
+ .select({
703
+ id: usersTable.id,
704
+ name: usersTable.name
705
+ })
706
+ .from(usersTable)
707
+ .prepare('statement1');
708
+ const result = await statement.execute();
709
+
710
+ t.deepEqual(result, [{ id: 1, name: 'John' }]);
711
+ });
712
+
713
+ test.skip('prepared statement reuse', async (t) => {
714
+ const { db } = t.context;
715
+
716
+ const stmt = db
717
+ .insert(usersTable)
718
+ .values({
719
+ verified: true,
720
+ name: placeholder('name')
721
+ })
722
+ .prepare('stmt2');
723
+
724
+ for (let i = 0; i < 10; i++) {
725
+ await stmt.execute({ name: `John ${i}` });
726
+ }
727
+
728
+ const result = await db
729
+ .select({
730
+ id: usersTable.id,
731
+ name: usersTable.name,
732
+ verified: usersTable.verified
733
+ })
734
+ .from(usersTable);
735
+
736
+ t.deepEqual(result, [
737
+ { id: 1, name: 'John 0', verified: true },
738
+ { id: 2, name: 'John 1', verified: true },
739
+ { id: 3, name: 'John 2', verified: true },
740
+ { id: 4, name: 'John 3', verified: true },
741
+ { id: 5, name: 'John 4', verified: true },
742
+ { id: 6, name: 'John 5', verified: true },
743
+ { id: 7, name: 'John 6', verified: true },
744
+ { id: 8, name: 'John 7', verified: true },
745
+ { id: 9, name: 'John 8', verified: true },
746
+ { id: 10, name: 'John 9', verified: true }
747
+ ]);
748
+ });
749
+
750
+ test.skip('prepared statement with placeholder in .where', async (t) => {
751
+ const { db } = t.context;
752
+
753
+ await db.insert(usersTable).values({ name: 'John' });
754
+ const stmt = db
755
+ .select({
756
+ id: usersTable.id,
757
+ name: usersTable.name
758
+ })
759
+ .from(usersTable)
760
+ .where(eq(usersTable.id, placeholder('id')))
761
+ .prepare('stmt3');
762
+ const result = await stmt.execute({ id: 1 });
763
+
764
+ t.deepEqual(result, [{ id: 1, name: 'John' }]);
765
+ });
766
+
767
+ test.skip('prepared statement with placeholder in .limit', async (t) => {
768
+ const { db } = t.context;
769
+
770
+ await db.insert(usersTable).values({ name: 'John' });
771
+ const stmt = db
772
+ .select({
773
+ id: usersTable.id,
774
+ name: usersTable.name
775
+ })
776
+ .from(usersTable)
777
+ .where(eq(usersTable.id, placeholder('id')))
778
+ .limit(placeholder('limit'))
779
+ .prepare('stmt_limit');
780
+
781
+ const result = await stmt.execute({ id: 1, limit: 1 });
782
+
783
+ t.deepEqual(result, [{ id: 1, name: 'John' }]);
784
+ t.is(result.length, 1);
785
+ });
786
+
787
+ test.skip('prepared statement with placeholder in .offset', async (t) => {
788
+ const { db } = t.context;
789
+
790
+ await db.insert(usersTable).values([{ name: 'John' }, { name: 'John1' }]);
791
+ const stmt = db
792
+ .select({
793
+ id: usersTable.id,
794
+ name: usersTable.name
795
+ })
796
+ .from(usersTable)
797
+ .offset(placeholder('offset'))
798
+ .prepare('stmt_offset');
799
+
800
+ const result = await stmt.execute({ offset: 1 });
801
+
802
+ t.deepEqual(result, [{ id: 2, name: 'John1' }]);
803
+ });
804
+
805
+ // TODO change tests to new structure
806
+ test.skip('migrator', async (t) => {
807
+ const { db } = t.context;
808
+
809
+ await db.execute(sql`drop table if exists all_columns`);
810
+ await db.execute(sql`drop table if exists users12`);
811
+ await db.execute(sql`drop table if exists "drizzle"."__drizzle_migrations"`);
812
+
813
+ await migrate(db, { migrationsFolder: './drizzle2/pg' });
814
+
815
+ await db.insert(usersMigratorTable).values({ name: 'John', email: 'email' });
816
+
817
+ const result = await db.select().from(usersMigratorTable);
818
+
819
+ t.deepEqual(result, [{ id: 1, name: 'John', email: 'email' }]);
820
+
821
+ await db.execute(sql`drop table all_columns`);
822
+ await db.execute(sql`drop table users12`);
823
+ await db.execute(sql`drop table "drizzle"."__drizzle_migrations"`);
824
+ });
825
+
826
+ test.skip('insert via db.execute + select via db.execute', async (t) => {
827
+ const { db } = t.context;
828
+
829
+ await db.execute(sql`insert into ${usersTable} (${name(usersTable.name.name)}) values (${'John'})`);
830
+
831
+ const result = await db.execute<{ id: number; name: string }>(sql`select id, name from "users"`);
832
+ t.deepEqual(result.rows, [{ id: 1, name: 'John' }]);
833
+ });
834
+
835
+ test.skip('insert via db.execute + returning', async (t) => {
836
+ const { db } = t.context;
837
+
838
+ const inserted = await db.execute<{ id: number; name: string }>(
839
+ sql`insert into ${usersTable} (${name(usersTable.name.name)}) values (${'John'}) returning ${usersTable.id}, ${
840
+ usersTable.name
841
+ }`
842
+ );
843
+ t.deepEqual(inserted.rows, [{ id: 1, name: 'John' }]);
844
+ });
845
+
846
+ test.skip('insert via db.execute w/ query builder', async (t) => {
847
+ const { db } = t.context;
848
+
849
+ const inserted = await db.execute<Pick<typeof usersTable.$inferSelect, 'id' | 'name'>>(
850
+ db.insert(usersTable).values({ name: 'John' }).returning({ id: usersTable.id, name: usersTable.name })
851
+ );
852
+ t.deepEqual(inserted.rows, [{ id: 1, name: 'John' }]);
853
+ });
854
+
855
+ test.skip('build query insert with onConflict do update', async (t) => {
856
+ const { db } = t.context;
857
+
858
+ const query = db
859
+ .insert(usersTable)
860
+ .values({ name: 'John', jsonb: ['foo', 'bar'] })
861
+ .onConflictDoUpdate({ target: usersTable.id, set: { name: 'John1' } })
862
+ .toSQL();
863
+
864
+ t.deepEqual(query, {
865
+ sql: 'insert into "users" ("name", "jsonb") values ($1, $2) on conflict ("id") do update set "name" = $3',
866
+ params: ['John', '["foo","bar"]', 'John1']
867
+ });
868
+ });
869
+
870
+ test.skip('build query insert with onConflict do update / multiple columns', async (t) => {
871
+ const { db } = t.context;
872
+
873
+ const query = db
874
+ .insert(usersTable)
875
+ .values({ name: 'John', jsonb: ['foo', 'bar'] })
876
+ .onConflictDoUpdate({ target: [usersTable.id, usersTable.name], set: { name: 'John1' } })
877
+ .toSQL();
878
+
879
+ t.deepEqual(query, {
880
+ sql: 'insert into "users" ("name", "jsonb") values ($1, $2) on conflict ("id","name") do update set "name" = $3',
881
+ params: ['John', '["foo","bar"]', 'John1']
882
+ });
883
+ });
884
+
885
+ test.skip('build query insert with onConflict do nothing', async (t) => {
886
+ const { db } = t.context;
887
+
888
+ const query = db
889
+ .insert(usersTable)
890
+ .values({ name: 'John', jsonb: ['foo', 'bar'] })
891
+ .onConflictDoNothing()
892
+ .toSQL();
893
+
894
+ t.deepEqual(query, {
895
+ sql: 'insert into "users" ("name", "jsonb") values ($1, $2) on conflict do nothing',
896
+ params: ['John', '["foo","bar"]']
897
+ });
898
+ });
899
+
900
+ test.skip('build query insert with onConflict do nothing + target', async (t) => {
901
+ const { db } = t.context;
902
+
903
+ const query = db
904
+ .insert(usersTable)
905
+ .values({ name: 'John', jsonb: ['foo', 'bar'] })
906
+ .onConflictDoNothing({ target: usersTable.id })
907
+ .toSQL();
908
+
909
+ t.deepEqual(query, {
910
+ sql: 'insert into "users" ("name", "jsonb") values ($1, $2) on conflict ("id") do nothing',
911
+ params: ['John', '["foo","bar"]']
912
+ });
913
+ });
914
+
915
+ test.skip('insert with onConflict do update', async (t) => {
916
+ const { db } = t.context;
917
+
918
+ await db.insert(usersTable).values({ name: 'John' });
919
+
920
+ await db
921
+ .insert(usersTable)
922
+ .values({ id: 1, name: 'John' })
923
+ .onConflictDoUpdate({ target: usersTable.id, set: { name: 'John1' } });
924
+
925
+ const res = await db
926
+ .select({ id: usersTable.id, name: usersTable.name })
927
+ .from(usersTable)
928
+ .where(eq(usersTable.id, 1));
929
+
930
+ t.deepEqual(res, [{ id: 1, name: 'John1' }]);
931
+ });
932
+
933
+ test.skip('insert with onConflict do nothing', async (t) => {
934
+ const { db } = t.context;
935
+
936
+ await db.insert(usersTable).values({ name: 'John' });
937
+
938
+ await db.insert(usersTable).values({ id: 1, name: 'John' }).onConflictDoNothing();
939
+
940
+ const res = await db
941
+ .select({ id: usersTable.id, name: usersTable.name })
942
+ .from(usersTable)
943
+ .where(eq(usersTable.id, 1));
944
+
945
+ t.deepEqual(res, [{ id: 1, name: 'John' }]);
946
+ });
947
+
948
+ test.skip('insert with onConflict do nothing + target', async (t) => {
949
+ const { db } = t.context;
950
+
951
+ await db.insert(usersTable).values({ name: 'John' });
952
+
953
+ await db.insert(usersTable).values({ id: 1, name: 'John' }).onConflictDoNothing({ target: usersTable.id });
954
+
955
+ const res = await db
956
+ .select({ id: usersTable.id, name: usersTable.name })
957
+ .from(usersTable)
958
+ .where(eq(usersTable.id, 1));
959
+
960
+ t.deepEqual(res, [{ id: 1, name: 'John' }]);
961
+ });
962
+
963
+ test.skip('left join (flat object fields)', async (t) => {
964
+ const { db } = t.context;
965
+
966
+ const { id: cityId } = await db
967
+ .insert(citiesTable)
968
+ .values([{ name: 'Paris' }, { name: 'London' }])
969
+ .returning({ id: citiesTable.id })
970
+ .then((rows) => rows[0]!);
971
+
972
+ await db.insert(users2Table).values([{ name: 'John', cityId }, { name: 'Jane' }]);
973
+
974
+ const res = await db
975
+ .select({
976
+ userId: users2Table.id,
977
+ userName: users2Table.name,
978
+ cityId: citiesTable.id,
979
+ cityName: citiesTable.name
980
+ })
981
+ .from(users2Table)
982
+ .leftJoin(citiesTable, eq(users2Table.cityId, citiesTable.id));
983
+
984
+ t.deepEqual(res, [
985
+ { userId: 1, userName: 'John', cityId, cityName: 'Paris' },
986
+ { userId: 2, userName: 'Jane', cityId: null, cityName: null }
987
+ ]);
988
+ });
989
+
990
+ test.skip('left join (grouped fields)', async (t) => {
991
+ const { db } = t.context;
992
+
993
+ const { id: cityId } = await db
994
+ .insert(citiesTable)
995
+ .values([{ name: 'Paris' }, { name: 'London' }])
996
+ .returning({ id: citiesTable.id })
997
+ .then((rows) => rows[0]!);
998
+
999
+ await db.insert(users2Table).values([{ name: 'John', cityId }, { name: 'Jane' }]);
1000
+
1001
+ const res = await db
1002
+ .select({
1003
+ id: users2Table.id,
1004
+ user: {
1005
+ name: users2Table.name,
1006
+ nameUpper: sql<string>`upper(${users2Table.name})`
1007
+ },
1008
+ city: {
1009
+ id: citiesTable.id,
1010
+ name: citiesTable.name,
1011
+ nameUpper: sql<string>`upper(${citiesTable.name})`
1012
+ }
1013
+ })
1014
+ .from(users2Table)
1015
+ .leftJoin(citiesTable, eq(users2Table.cityId, citiesTable.id));
1016
+
1017
+ t.deepEqual(res, [
1018
+ {
1019
+ id: 1,
1020
+ user: { name: 'John', nameUpper: 'JOHN' },
1021
+ city: { id: cityId, name: 'Paris', nameUpper: 'PARIS' }
1022
+ },
1023
+ {
1024
+ id: 2,
1025
+ user: { name: 'Jane', nameUpper: 'JANE' },
1026
+ city: null
1027
+ }
1028
+ ]);
1029
+ });
1030
+
1031
+ test.skip('left join (all fields)', async (t) => {
1032
+ const { db } = t.context;
1033
+
1034
+ const { id: cityId } = await db
1035
+ .insert(citiesTable)
1036
+ .values([{ name: 'Paris' }, { name: 'London' }])
1037
+ .returning({ id: citiesTable.id })
1038
+ .then((rows) => rows[0]!);
1039
+
1040
+ await db.insert(users2Table).values([{ name: 'John', cityId }, { name: 'Jane' }]);
1041
+
1042
+ const res = await db.select().from(users2Table).leftJoin(citiesTable, eq(users2Table.cityId, citiesTable.id));
1043
+
1044
+ t.deepEqual(res, [
1045
+ {
1046
+ users2: {
1047
+ id: 1,
1048
+ name: 'John',
1049
+ cityId
1050
+ },
1051
+ cities: {
1052
+ id: cityId,
1053
+ name: 'Paris',
1054
+ state: null
1055
+ }
1056
+ },
1057
+ {
1058
+ users2: {
1059
+ id: 2,
1060
+ name: 'Jane',
1061
+ cityId: null
1062
+ },
1063
+ cities: null
1064
+ }
1065
+ ]);
1066
+ });
1067
+
1068
+ test.skip('join subquery', async (t) => {
1069
+ const { db } = t.context;
1070
+
1071
+ await db
1072
+ .insert(courseCategoriesTable)
1073
+ .values([{ name: 'Category 1' }, { name: 'Category 2' }, { name: 'Category 3' }, { name: 'Category 4' }]);
1074
+
1075
+ await db.insert(coursesTable).values([
1076
+ { name: 'Development', categoryId: 2 },
1077
+ { name: 'IT & Software', categoryId: 3 },
1078
+ { name: 'Marketing', categoryId: 4 },
1079
+ { name: 'Design', categoryId: 1 }
1080
+ ]);
1081
+
1082
+ const sq2 = db
1083
+ .select({
1084
+ categoryId: courseCategoriesTable.id,
1085
+ category: courseCategoriesTable.name,
1086
+ total: sql<number>`count(${courseCategoriesTable.id})`
1087
+ })
1088
+ .from(courseCategoriesTable)
1089
+ .groupBy(courseCategoriesTable.id, courseCategoriesTable.name)
1090
+ .as('sq2');
1091
+
1092
+ const res = await db
1093
+ .select({
1094
+ courseName: coursesTable.name,
1095
+ categoryId: sq2.categoryId
1096
+ })
1097
+ .from(coursesTable)
1098
+ .leftJoin(sq2, eq(coursesTable.categoryId, sq2.categoryId))
1099
+ .orderBy(coursesTable.name);
1100
+
1101
+ t.deepEqual(res, [
1102
+ { courseName: 'Design', categoryId: 1 },
1103
+ { courseName: 'Development', categoryId: 2 },
1104
+ { courseName: 'IT & Software', categoryId: 3 },
1105
+ { courseName: 'Marketing', categoryId: 4 }
1106
+ ]);
1107
+ });
1108
+
1109
+ test.skip('with ... select', async (t) => {
1110
+ const { db } = t.context;
1111
+
1112
+ await db.insert(orders).values([
1113
+ { region: 'Europe', product: 'A', amount: 10, quantity: 1 },
1114
+ { region: 'Europe', product: 'A', amount: 20, quantity: 2 },
1115
+ { region: 'Europe', product: 'B', amount: 20, quantity: 2 },
1116
+ { region: 'Europe', product: 'B', amount: 30, quantity: 3 },
1117
+ { region: 'US', product: 'A', amount: 30, quantity: 3 },
1118
+ { region: 'US', product: 'A', amount: 40, quantity: 4 },
1119
+ { region: 'US', product: 'B', amount: 40, quantity: 4 },
1120
+ { region: 'US', product: 'B', amount: 50, quantity: 5 }
1121
+ ]);
1122
+
1123
+ const regionalSales = db.$with('regional_sales').as(
1124
+ db
1125
+ .select({
1126
+ region: orders.region,
1127
+ totalSales: sql<number>`sum(${orders.amount})`.as('total_sales')
1128
+ })
1129
+ .from(orders)
1130
+ .groupBy(orders.region)
1131
+ );
1132
+
1133
+ const topRegions = db.$with('top_regions').as(
1134
+ db
1135
+ .select({
1136
+ region: regionalSales.region
1137
+ })
1138
+ .from(regionalSales)
1139
+ .where(
1140
+ gt(regionalSales.totalSales, db.select({ sales: sql`sum(${regionalSales.totalSales})/10` }).from(regionalSales))
1141
+ )
1142
+ );
1143
+
1144
+ const result = await db
1145
+ .with(regionalSales, topRegions)
1146
+ .select({
1147
+ region: orders.region,
1148
+ product: orders.product,
1149
+ productUnits: sql<number>`sum(${orders.quantity})::int`,
1150
+ productSales: sql<number>`sum(${orders.amount})::int`
1151
+ })
1152
+ .from(orders)
1153
+ .where(inArray(orders.region, db.select({ region: topRegions.region }).from(topRegions)))
1154
+ .groupBy(orders.region, orders.product)
1155
+ .orderBy(orders.region, orders.product);
1156
+
1157
+ t.deepEqual(result, [
1158
+ {
1159
+ region: 'Europe',
1160
+ product: 'A',
1161
+ productUnits: 3,
1162
+ productSales: 30
1163
+ },
1164
+ {
1165
+ region: 'Europe',
1166
+ product: 'B',
1167
+ productUnits: 5,
1168
+ productSales: 50
1169
+ },
1170
+ {
1171
+ region: 'US',
1172
+ product: 'A',
1173
+ productUnits: 7,
1174
+ productSales: 70
1175
+ },
1176
+ {
1177
+ region: 'US',
1178
+ product: 'B',
1179
+ productUnits: 9,
1180
+ productSales: 90
1181
+ }
1182
+ ]);
1183
+ });
1184
+
1185
+ test.skip('select from subquery sql', async (t) => {
1186
+ const { db } = t.context;
1187
+
1188
+ await db.insert(users2Table).values([{ name: 'John' }, { name: 'Jane' }]);
1189
+
1190
+ const sq = db
1191
+ .select({ name: sql<string>`${users2Table.name} || ' modified'`.as('name') })
1192
+ .from(users2Table)
1193
+ .as('sq');
1194
+
1195
+ const res = await db.select({ name: sq.name }).from(sq);
1196
+
1197
+ t.deepEqual(res, [{ name: 'John modified' }, { name: 'Jane modified' }]);
1198
+ });
1199
+
1200
+ test('select a field without joining its table', (t) => {
1201
+ const { db } = t.context;
1202
+
1203
+ t.throws(() => db.select({ name: users2Table.name }).from(usersTable).prepare('query'));
1204
+ });
1205
+
1206
+ test('select all fields from subquery without alias', (t) => {
1207
+ const { db } = t.context;
1208
+
1209
+ const sq = db.$with('sq').as(db.select({ name: sql<string>`upper(${users2Table.name})` }).from(users2Table));
1210
+
1211
+ t.throws(() => db.select().from(sq).prepare('query'));
1212
+ });
1213
+
1214
+ test.skip('select count()', async (t) => {
1215
+ const { db } = t.context;
1216
+
1217
+ await db.insert(usersTable).values([{ name: 'John' }, { name: 'Jane' }]);
1218
+
1219
+ const res = await db.select({ count: sql`count(*)` }).from(usersTable);
1220
+
1221
+ t.deepEqual(res, [{ count: '2' }]);
1222
+ });
1223
+
1224
+ test.skip('select count w/ custom mapper', async (t) => {
1225
+ const { db } = t.context;
1226
+
1227
+ function count(value: PgColumn | SQLWrapper): SQL<number>;
1228
+ function count(value: PgColumn | SQLWrapper, alias: string): SQL.Aliased<number>;
1229
+ function count(value: PgColumn | SQLWrapper, alias?: string): SQL<number> | SQL.Aliased<number> {
1230
+ const result = sql`count(${value})`.mapWith(Number);
1231
+ if (!alias) {
1232
+ return result;
1233
+ }
1234
+ return result.as(alias);
1235
+ }
1236
+
1237
+ await db.insert(usersTable).values([{ name: 'John' }, { name: 'Jane' }]);
1238
+
1239
+ const res = await db.select({ count: count(sql`*`) }).from(usersTable);
1240
+
1241
+ t.deepEqual(res, [{ count: 2 }]);
1242
+ });
1243
+
1244
+ test.skip('network types', async (t) => {
1245
+ const { db } = t.context;
1246
+
1247
+ const value: typeof network.$inferSelect = {
1248
+ inet: '127.0.0.1',
1249
+ cidr: '192.168.100.128/25',
1250
+ macaddr: '08:00:2b:01:02:03',
1251
+ macaddr8: '08:00:2b:01:02:03:04:05'
1252
+ };
1253
+
1254
+ await db.insert(network).values(value);
1255
+
1256
+ const res = await db.select().from(network);
1257
+
1258
+ t.deepEqual(res, [value]);
1259
+ });
1260
+
1261
+ test.skip('array types', async (t) => {
1262
+ const { db } = t.context;
1263
+
1264
+ const values: (typeof salEmp.$inferSelect)[] = [
1265
+ {
1266
+ name: 'John',
1267
+ payByQuarter: [10000, 10000, 10000, 10000],
1268
+ schedule: [
1269
+ ['meeting', 'lunch'],
1270
+ ['training', 'presentation']
1271
+ ]
1272
+ },
1273
+ {
1274
+ name: 'Carol',
1275
+ payByQuarter: [20000, 25000, 25000, 25000],
1276
+ schedule: [
1277
+ ['breakfast', 'consulting'],
1278
+ ['meeting', 'lunch']
1279
+ ]
1280
+ }
1281
+ ];
1282
+
1283
+ await db.insert(salEmp).values(values);
1284
+
1285
+ const res = await db.select().from(salEmp);
1286
+
1287
+ t.deepEqual(res, values);
1288
+ });
1289
+
1290
+ test('select for ...', (t) => {
1291
+ const { db } = t.context;
1292
+
1293
+ const query = db
1294
+ .select()
1295
+ .from(users2Table)
1296
+ .for('update')
1297
+ .for('no key update', { of: users2Table })
1298
+ .for('no key update', { of: users2Table, skipLocked: true })
1299
+ .for('share', { of: users2Table, noWait: true })
1300
+ .toSQL();
1301
+
1302
+ t.regex(
1303
+ query.sql,
1304
+ / for update for no key update of "users2" for no key update of "users2" skip locked for share of "users2" no wait$/
1305
+ );
1306
+ });
1307
+
1308
+ test.skip('having', async (t) => {
1309
+ const { db } = t.context;
1310
+
1311
+ await db.insert(citiesTable).values([{ name: 'London' }, { name: 'Paris' }, { name: 'New York' }]);
1312
+
1313
+ await db.insert(users2Table).values([
1314
+ { name: 'John', cityId: 1 },
1315
+ { name: 'Jane', cityId: 1 },
1316
+ {
1317
+ name: 'Jack',
1318
+ cityId: 2
1319
+ }
1320
+ ]);
1321
+
1322
+ const result = await db
1323
+ .select({
1324
+ id: citiesTable.id,
1325
+ name: sql<string>`upper(${citiesTable.name})`.as('upper_name'),
1326
+ usersCount: sql<number>`count(${users2Table.id})::int`.as('users_count')
1327
+ })
1328
+ .from(citiesTable)
1329
+ .leftJoin(users2Table, eq(users2Table.cityId, citiesTable.id))
1330
+ .where(({ name }) => sql`length(${name}) >= 3`)
1331
+ .groupBy(citiesTable.id)
1332
+ .having(({ usersCount }) => sql`${usersCount} > 0`)
1333
+ .orderBy(({ name }) => name);
1334
+
1335
+ t.deepEqual(result, [
1336
+ {
1337
+ id: 1,
1338
+ name: 'LONDON',
1339
+ usersCount: 2
1340
+ },
1341
+ {
1342
+ id: 2,
1343
+ name: 'PARIS',
1344
+ usersCount: 1
1345
+ }
1346
+ ]);
1347
+ });
1348
+
1349
+ test.skip('view', async (t) => {
1350
+ const { db } = t.context;
1351
+
1352
+ const newYorkers1 = pgView('new_yorkers').as((qb) => qb.select().from(users2Table).where(eq(users2Table.cityId, 1)));
1353
+
1354
+ const newYorkers2 = pgView('new_yorkers', {
1355
+ id: serial('id').primaryKey(),
1356
+ name: text('name').notNull(),
1357
+ cityId: integer('city_id').notNull()
1358
+ }).as(sql`select * from ${users2Table} where ${eq(users2Table.cityId, 1)}`);
1359
+
1360
+ const newYorkers3 = pgView('new_yorkers', {
1361
+ id: serial('id').primaryKey(),
1362
+ name: text('name').notNull(),
1363
+ cityId: integer('city_id').notNull()
1364
+ }).existing();
1365
+
1366
+ await db.execute(sql`create view ${newYorkers1} as ${getViewConfig(newYorkers1).query}`);
1367
+
1368
+ await db.insert(citiesTable).values([{ name: 'New York' }, { name: 'Paris' }]);
1369
+
1370
+ await db.insert(users2Table).values([
1371
+ { name: 'John', cityId: 1 },
1372
+ { name: 'Jane', cityId: 1 },
1373
+ { name: 'Jack', cityId: 2 }
1374
+ ]);
1375
+
1376
+ {
1377
+ const result = await db.select().from(newYorkers1);
1378
+ t.deepEqual(result, [
1379
+ { id: 1, name: 'John', cityId: 1 },
1380
+ { id: 2, name: 'Jane', cityId: 1 }
1381
+ ]);
1382
+ }
1383
+
1384
+ {
1385
+ const result = await db.select().from(newYorkers2);
1386
+ t.deepEqual(result, [
1387
+ { id: 1, name: 'John', cityId: 1 },
1388
+ { id: 2, name: 'Jane', cityId: 1 }
1389
+ ]);
1390
+ }
1391
+
1392
+ {
1393
+ const result = await db.select().from(newYorkers3);
1394
+ t.deepEqual(result, [
1395
+ { id: 1, name: 'John', cityId: 1 },
1396
+ { id: 2, name: 'Jane', cityId: 1 }
1397
+ ]);
1398
+ }
1399
+
1400
+ {
1401
+ const result = await db.select({ name: newYorkers1.name }).from(newYorkers1);
1402
+ t.deepEqual(result, [{ name: 'John' }, { name: 'Jane' }]);
1403
+ }
1404
+
1405
+ await db.execute(sql`drop view ${newYorkers1}`);
1406
+ });
1407
+
1408
+ test.skip('materialized view', async (t) => {
1409
+ const { db } = t.context;
1410
+
1411
+ const newYorkers1 = pgMaterializedView('new_yorkers').as((qb) =>
1412
+ qb.select().from(users2Table).where(eq(users2Table.cityId, 1))
1413
+ );
1414
+
1415
+ const newYorkers2 = pgMaterializedView('new_yorkers', {
1416
+ id: serial('id').primaryKey(),
1417
+ name: text('name').notNull(),
1418
+ cityId: integer('city_id').notNull()
1419
+ }).as(sql`select * from ${users2Table} where ${eq(users2Table.cityId, 1)}`);
1420
+
1421
+ const newYorkers3 = pgMaterializedView('new_yorkers', {
1422
+ id: serial('id').primaryKey(),
1423
+ name: text('name').notNull(),
1424
+ cityId: integer('city_id').notNull()
1425
+ }).existing();
1426
+
1427
+ await db.execute(sql`create materialized view ${newYorkers1} as ${getMaterializedViewConfig(newYorkers1).query}`);
1428
+
1429
+ await db.insert(citiesTable).values([{ name: 'New York' }, { name: 'Paris' }]);
1430
+
1431
+ await db.insert(users2Table).values([
1432
+ { name: 'John', cityId: 1 },
1433
+ { name: 'Jane', cityId: 1 },
1434
+ { name: 'Jack', cityId: 2 }
1435
+ ]);
1436
+
1437
+ {
1438
+ const result = await db.select().from(newYorkers1);
1439
+ t.deepEqual(result, []);
1440
+ }
1441
+
1442
+ await db.refreshMaterializedView(newYorkers1);
1443
+
1444
+ {
1445
+ const result = await db.select().from(newYorkers1);
1446
+ t.deepEqual(result, [
1447
+ { id: 1, name: 'John', cityId: 1 },
1448
+ { id: 2, name: 'Jane', cityId: 1 }
1449
+ ]);
1450
+ }
1451
+
1452
+ {
1453
+ const result = await db.select().from(newYorkers2);
1454
+ t.deepEqual(result, [
1455
+ { id: 1, name: 'John', cityId: 1 },
1456
+ { id: 2, name: 'Jane', cityId: 1 }
1457
+ ]);
1458
+ }
1459
+
1460
+ {
1461
+ const result = await db.select().from(newYorkers3);
1462
+ t.deepEqual(result, [
1463
+ { id: 1, name: 'John', cityId: 1 },
1464
+ { id: 2, name: 'Jane', cityId: 1 }
1465
+ ]);
1466
+ }
1467
+
1468
+ {
1469
+ const result = await db.select({ name: newYorkers1.name }).from(newYorkers1);
1470
+ t.deepEqual(result, [{ name: 'John' }, { name: 'Jane' }]);
1471
+ }
1472
+
1473
+ await db.execute(sql`drop materialized view ${newYorkers1}`);
1474
+ });
1475
+
1476
+ // TODO: copy to SQLite and MySQL, add to docs
1477
+ test('select from raw sql', async (t) => {
1478
+ const { db } = t.context;
1479
+
1480
+ const result = await db
1481
+ .select({
1482
+ id: sql<number>`id`,
1483
+ name: sql<string>`name`
1484
+ })
1485
+ .from(sql`(select 1 as id, 'John' as name) as users`);
1486
+
1487
+ Expect<Equal<{ id: number; name: string }[], typeof result>>;
1488
+
1489
+ t.deepEqual(result, [{ id: 1, name: 'John' }]);
1490
+ });
1491
+
1492
+ test.skip('select from raw sql with joins', async (t) => {
1493
+ const { db } = t.context;
1494
+
1495
+ const result = await db
1496
+ .select({
1497
+ id: sql<number>`users.id`,
1498
+ name: sql<string>`users.name`,
1499
+ userCity: sql<string>`users.city`,
1500
+ cityName: sql<string>`cities.name`
1501
+ })
1502
+ .from(sql`(select 1 as id, 'John' as name, 'New York' as city) as users`)
1503
+ .leftJoin(sql`(select 1 as id, 'Paris' as name) as cities`, sql`cities.id = users.id`);
1504
+
1505
+ Expect<Equal<{ id: number; name: string; userCity: string; cityName: string }[], typeof result>>;
1506
+
1507
+ t.deepEqual(result, [{ id: 1, name: 'John', userCity: 'New York', cityName: 'Paris' }]);
1508
+ });
1509
+
1510
+ test.skip('join on aliased sql from select', async (t) => {
1511
+ const { db } = t.context;
1512
+
1513
+ const result = await db
1514
+ .select({
1515
+ userId: sql<number>`users.id`.as('userId'),
1516
+ name: sql<string>`users.name`,
1517
+ userCity: sql<string>`users.city`,
1518
+ cityId: sql<number>`cities.id`.as('cityId'),
1519
+ cityName: sql<string>`cities.name`
1520
+ })
1521
+ .from(sql`(select 1 as id, 'John' as name, 'New York' as city) as users`)
1522
+ .leftJoin(sql`(select 1 as id, 'Paris' as name) as cities`, (cols) => eq(cols.cityId, cols.userId));
1523
+
1524
+ Expect<Equal<{ userId: number; name: string; userCity: string; cityId: number; cityName: string }[], typeof result>>;
1525
+
1526
+ t.deepEqual(result, [{ userId: 1, name: 'John', userCity: 'New York', cityId: 1, cityName: 'Paris' }]);
1527
+ });
1528
+
1529
+ test.skip('join on aliased sql from with clause', async (t) => {
1530
+ const { db } = t.context;
1531
+
1532
+ const users = db.$with('users').as(
1533
+ db
1534
+ .select({
1535
+ id: sql<number>`id`.as('userId'),
1536
+ name: sql<string>`name`.as('userName'),
1537
+ city: sql<string>`city`.as('city')
1538
+ })
1539
+ .from(sql`(select 1 as id, 'John' as name, 'New York' as city) as users`)
1540
+ );
1541
+
1542
+ const cities = db.$with('cities').as(
1543
+ db
1544
+ .select({
1545
+ id: sql<number>`id`.as('cityId'),
1546
+ name: sql<string>`name`.as('cityName')
1547
+ })
1548
+ .from(sql`(select 1 as id, 'Paris' as name) as cities`)
1549
+ );
1550
+
1551
+ const result = await db
1552
+ .with(users, cities)
1553
+ .select({
1554
+ userId: users.id,
1555
+ name: users.name,
1556
+ userCity: users.city,
1557
+ cityId: cities.id,
1558
+ cityName: cities.name
1559
+ })
1560
+ .from(users)
1561
+ .leftJoin(cities, (cols) => eq(cols.cityId, cols.userId));
1562
+
1563
+ Expect<Equal<{ userId: number; name: string; userCity: string; cityId: number; cityName: string }[], typeof result>>;
1564
+
1565
+ t.deepEqual(result, [{ userId: 1, name: 'John', userCity: 'New York', cityId: 1, cityName: 'Paris' }]);
1566
+ });
1567
+
1568
+ test.skip('prefixed table', async (t) => {
1569
+ const { db } = t.context;
1570
+
1571
+ const pgTable = pgTableCreator((name) => `myprefix_${name}`);
1572
+
1573
+ const users = pgTable('test_prefixed_table_with_unique_name', {
1574
+ id: integer('id').primaryKey(),
1575
+ name: text('name').notNull()
1576
+ });
1577
+
1578
+ await db.execute(sql`drop table if exists ${users}`);
1579
+
1580
+ await db.execute(
1581
+ sql`create table myprefix_test_prefixed_table_with_unique_name (id integer not null primary key, name text not null)`
1582
+ );
1583
+
1584
+ await db.insert(users).values({ id: 1, name: 'John' });
1585
+
1586
+ const result = await db.select().from(users);
1587
+
1588
+ t.deepEqual(result, [{ id: 1, name: 'John' }]);
1589
+
1590
+ await db.execute(sql`drop table ${users}`);
1591
+ });
1592
+
1593
+ test.skip('select from enum', async (t) => {
1594
+ const { db } = t.context;
1595
+
1596
+ const muscleEnum = pgEnum('muscle', [
1597
+ 'abdominals',
1598
+ 'hamstrings',
1599
+ 'adductors',
1600
+ 'quadriceps',
1601
+ 'biceps',
1602
+ 'shoulders',
1603
+ 'chest',
1604
+ 'middle_back',
1605
+ 'calves',
1606
+ 'glutes',
1607
+ 'lower_back',
1608
+ 'lats',
1609
+ 'triceps',
1610
+ 'traps',
1611
+ 'forearms',
1612
+ 'neck',
1613
+ 'abductors'
1614
+ ]);
1615
+
1616
+ const forceEnum = pgEnum('force', ['isometric', 'isotonic', 'isokinetic']);
1617
+
1618
+ const levelEnum = pgEnum('level', ['beginner', 'intermediate', 'advanced']);
1619
+
1620
+ const mechanicEnum = pgEnum('mechanic', ['compound', 'isolation']);
1621
+
1622
+ const equipmentEnum = pgEnum('equipment', ['barbell', 'dumbbell', 'bodyweight', 'machine', 'cable', 'kettlebell']);
1623
+
1624
+ const categoryEnum = pgEnum('category', ['upper_body', 'lower_body', 'full_body']);
1625
+
1626
+ const exercises = pgTable('exercises', {
1627
+ id: serial('id').primaryKey(),
1628
+ name: varchar('name').notNull(),
1629
+ force: forceEnum('force'),
1630
+ level: levelEnum('level'),
1631
+ mechanic: mechanicEnum('mechanic'),
1632
+ equipment: equipmentEnum('equipment'),
1633
+ instructions: text('instructions'),
1634
+ category: categoryEnum('category'),
1635
+ primaryMuscles: muscleEnum('primary_muscles').array(),
1636
+ secondaryMuscles: muscleEnum('secondary_muscles').array(),
1637
+ createdAt: timestamp('created_at')
1638
+ .notNull()
1639
+ .default(sql`now()`),
1640
+ updatedAt: timestamp('updated_at')
1641
+ .notNull()
1642
+ .default(sql`now()`)
1643
+ });
1644
+
1645
+ await db.execute(sql`drop table if exists ${exercises}`);
1646
+ await db.execute(sql`drop type if exists ${name(muscleEnum.enumName)}`);
1647
+ await db.execute(sql`drop type if exists ${name(forceEnum.enumName)}`);
1648
+ await db.execute(sql`drop type if exists ${name(levelEnum.enumName)}`);
1649
+ await db.execute(sql`drop type if exists ${name(mechanicEnum.enumName)}`);
1650
+ await db.execute(sql`drop type if exists ${name(equipmentEnum.enumName)}`);
1651
+ await db.execute(sql`drop type if exists ${name(categoryEnum.enumName)}`);
1652
+
1653
+ await db.execute(
1654
+ sql`create type ${name(
1655
+ muscleEnum.enumName
1656
+ )} as enum ('abdominals', 'hamstrings', 'adductors', 'quadriceps', 'biceps', 'shoulders', 'chest', 'middle_back', 'calves', 'glutes', 'lower_back', 'lats', 'triceps', 'traps', 'forearms', 'neck', 'abductors')`
1657
+ );
1658
+ await db.execute(sql`create type ${name(forceEnum.enumName)} as enum ('isometric', 'isotonic', 'isokinetic')`);
1659
+ await db.execute(sql`create type ${name(levelEnum.enumName)} as enum ('beginner', 'intermediate', 'advanced')`);
1660
+ await db.execute(sql`create type ${name(mechanicEnum.enumName)} as enum ('compound', 'isolation')`);
1661
+ await db.execute(
1662
+ sql`create type ${name(
1663
+ equipmentEnum.enumName
1664
+ )} as enum ('barbell', 'dumbbell', 'bodyweight', 'machine', 'cable', 'kettlebell')`
1665
+ );
1666
+ await db.execute(sql`create type ${name(categoryEnum.enumName)} as enum ('upper_body', 'lower_body', 'full_body')`);
1667
+ await db.execute(sql`
1668
+ create table ${exercises} (
1669
+ id serial primary key,
1670
+ name varchar not null,
1671
+ force force,
1672
+ level level,
1673
+ mechanic mechanic,
1674
+ equipment equipment,
1675
+ instructions text,
1676
+ category category,
1677
+ primary_muscles muscle[],
1678
+ secondary_muscles muscle[],
1679
+ created_at timestamp not null default now(),
1680
+ updated_at timestamp not null default now()
1681
+ )
1682
+ `);
1683
+
1684
+ await db.insert(exercises).values({
1685
+ name: 'Bench Press',
1686
+ force: 'isotonic',
1687
+ level: 'beginner',
1688
+ mechanic: 'compound',
1689
+ equipment: 'barbell',
1690
+ instructions:
1691
+ 'Lie on your back on a flat bench. Grasp the barbell with an overhand grip, slightly wider than shoulder width. Unrack the barbell and hold it over you with your arms locked. Lower the barbell to your chest. Press the barbell back to the starting position.',
1692
+ category: 'upper_body',
1693
+ primaryMuscles: ['chest', 'triceps'],
1694
+ secondaryMuscles: ['shoulders', 'traps']
1695
+ });
1696
+
1697
+ const result = await db.select().from(exercises);
1698
+
1699
+ t.deepEqual(result, [
1700
+ {
1701
+ id: 1,
1702
+ name: 'Bench Press',
1703
+ force: 'isotonic',
1704
+ level: 'beginner',
1705
+ mechanic: 'compound',
1706
+ equipment: 'barbell',
1707
+ instructions:
1708
+ 'Lie on your back on a flat bench. Grasp the barbell with an overhand grip, slightly wider than shoulder width. Unrack the barbell and hold it over you with your arms locked. Lower the barbell to your chest. Press the barbell back to the starting position.',
1709
+ category: 'upper_body',
1710
+ primaryMuscles: ['chest', 'triceps'],
1711
+ secondaryMuscles: ['shoulders', 'traps'],
1712
+ createdAt: result[0]!.createdAt,
1713
+ updatedAt: result[0]!.updatedAt
1714
+ }
1715
+ ]);
1716
+
1717
+ await db.execute(sql`drop table ${exercises}`);
1718
+ await db.execute(sql`drop type ${name(muscleEnum.enumName)}`);
1719
+ await db.execute(sql`drop type ${name(forceEnum.enumName)}`);
1720
+ await db.execute(sql`drop type ${name(levelEnum.enumName)}`);
1721
+ await db.execute(sql`drop type ${name(mechanicEnum.enumName)}`);
1722
+ await db.execute(sql`drop type ${name(equipmentEnum.enumName)}`);
1723
+ await db.execute(sql`drop type ${name(categoryEnum.enumName)}`);
1724
+ });
1725
+
1726
+ test('orderBy with aliased column', (t) => {
1727
+ const { db } = t.context;
1728
+
1729
+ const query = db
1730
+ .select({
1731
+ test: sql`something`.as('test')
1732
+ })
1733
+ .from(users2Table)
1734
+ .orderBy((fields) => fields.test)
1735
+ .toSQL();
1736
+
1737
+ t.deepEqual(query.sql, 'select something as "test" from "users2" order by "test"');
1738
+ });
1739
+
1740
+ test.skip('select from sql', async (t) => {
1741
+ const { db } = t.context;
1742
+
1743
+ const metricEntry = pgTable('metric_entry', {
1744
+ id: pgUuid('id').notNull(),
1745
+ createdAt: timestamp('created_at').notNull()
1746
+ });
1747
+
1748
+ await db.execute(sql`drop table if exists ${metricEntry}`);
1749
+ await db.execute(sql`create table ${metricEntry} (id uuid not null, created_at timestamp not null)`);
1750
+
1751
+ const metricId = uuid();
1752
+
1753
+ const intervals = db.$with('intervals').as(
1754
+ db
1755
+ .select({
1756
+ startTime: sql<string>`(date'2023-03-01'+ x * '1 day'::interval)`.as('start_time'),
1757
+ endTime: sql<string>`(date'2023-03-01'+ (x+1) *'1 day'::interval)`.as('end_time')
1758
+ })
1759
+ .from(sql`generate_series(0, 29, 1) as t(x)`)
1760
+ );
1761
+
1762
+ await t.notThrowsAsync(() =>
1763
+ db
1764
+ .with(intervals)
1765
+ .select({
1766
+ startTime: intervals.startTime,
1767
+ endTime: intervals.endTime,
1768
+ count: sql<number>`count(${metricEntry})`
1769
+ })
1770
+ .from(metricEntry)
1771
+ .rightJoin(
1772
+ intervals,
1773
+ and(
1774
+ eq(metricEntry.id, metricId),
1775
+ gte(metricEntry.createdAt, intervals.startTime),
1776
+ lt(metricEntry.createdAt, intervals.endTime)
1777
+ )
1778
+ )
1779
+ .groupBy(intervals.startTime, intervals.endTime)
1780
+ .orderBy(asc(intervals.startTime))
1781
+ );
1782
+ });
1783
+
1784
+ test.skip('timestamp timezone', async (t) => {
1785
+ const { db } = t.context;
1786
+
1787
+ const usersTableWithAndWithoutTimezone = pgTable('users_test_with_and_without_timezone', {
1788
+ id: serial('id').primaryKey(),
1789
+ name: text('name').notNull(),
1790
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
1791
+ updatedAt: timestamp('updated_at', { withTimezone: false }).notNull().defaultNow()
1792
+ });
1793
+
1794
+ await db.execute(sql`drop table if exists ${usersTableWithAndWithoutTimezone}`);
1795
+
1796
+ await db.execute(
1797
+ sql`
1798
+ create table users_test_with_and_without_timezone (
1799
+ id serial not null primary key,
1800
+ name text not null,
1801
+ created_at timestamptz not null default now(),
1802
+ updated_at timestamp not null default now()
1803
+ )
1804
+ `
1805
+ );
1806
+
1807
+ const date = new Date(Date.parse('2020-01-01T00:00:00+04:00'));
1808
+
1809
+ await db.insert(usersTableWithAndWithoutTimezone).values({ name: 'With default times' });
1810
+ await db.insert(usersTableWithAndWithoutTimezone).values({
1811
+ name: 'Without default times',
1812
+ createdAt: date,
1813
+ updatedAt: date
1814
+ });
1815
+ const users = await db.select().from(usersTableWithAndWithoutTimezone);
1816
+
1817
+ // check that the timestamps are set correctly for default times
1818
+ t.assert(Math.abs(users[0]!.updatedAt.getTime() - Date.now()) < 2000);
1819
+ t.assert(Math.abs(users[0]!.createdAt.getTime() - Date.now()) < 2000);
1820
+
1821
+ // check that the timestamps are set correctly for non default times
1822
+ t.assert(Math.abs(users[1]!.updatedAt.getTime() - date.getTime()) < 2000);
1823
+ t.assert(Math.abs(users[1]!.createdAt.getTime() - date.getTime()) < 2000);
1824
+ });
1825
+
1826
+ test.skip('transaction', async (t) => {
1827
+ const { db } = t.context;
1828
+
1829
+ const users = pgTable('users_transactions', {
1830
+ id: serial('id').primaryKey(),
1831
+ balance: integer('balance').notNull()
1832
+ });
1833
+ const products = pgTable('products_transactions', {
1834
+ id: serial('id').primaryKey(),
1835
+ price: integer('price').notNull(),
1836
+ stock: integer('stock').notNull()
1837
+ });
1838
+
1839
+ await db.execute(sql`drop table if exists ${users}`);
1840
+ await db.execute(sql`drop table if exists ${products}`);
1841
+
1842
+ await db.execute(sql`create table users_transactions (id serial not null primary key, balance integer not null)`);
1843
+ await db.execute(
1844
+ sql`create table products_transactions (id serial not null primary key, price integer not null, stock integer not null)`
1845
+ );
1846
+
1847
+ const user = await db
1848
+ .insert(users)
1849
+ .values({ balance: 100 })
1850
+ .returning()
1851
+ .then((rows) => rows[0]!);
1852
+ const product = await db
1853
+ .insert(products)
1854
+ .values({ price: 10, stock: 10 })
1855
+ .returning()
1856
+ .then((rows) => rows[0]!);
1857
+
1858
+ await db.transaction(async (tx) => {
1859
+ await tx
1860
+ .update(users)
1861
+ .set({ balance: user.balance - product.price })
1862
+ .where(eq(users.id, user.id));
1863
+ await tx
1864
+ .update(products)
1865
+ .set({ stock: product.stock - 1 })
1866
+ .where(eq(products.id, product.id));
1867
+ });
1868
+
1869
+ const result = await db.select().from(users);
1870
+
1871
+ t.deepEqual(result, [{ id: 1, balance: 90 }]);
1872
+
1873
+ await db.execute(sql`drop table ${users}`);
1874
+ await db.execute(sql`drop table ${products}`);
1875
+ });
1876
+
1877
+ test.skip('transaction rollback', async (t) => {
1878
+ const { db } = t.context;
1879
+
1880
+ const users = pgTable('users_transactions_rollback', {
1881
+ id: serial('id').primaryKey(),
1882
+ balance: integer('balance').notNull()
1883
+ });
1884
+
1885
+ await db.execute(sql`drop table if exists ${users}`);
1886
+
1887
+ await db.execute(
1888
+ sql`create table users_transactions_rollback (id serial not null primary key, balance integer not null)`
1889
+ );
1890
+
1891
+ await t.throwsAsync(
1892
+ async () =>
1893
+ await db.transaction(async (tx) => {
1894
+ await tx.insert(users).values({ balance: 100 });
1895
+ tx.rollback();
1896
+ }),
1897
+ new TransactionRollbackError()
1898
+ );
1899
+
1900
+ const result = await db.select().from(users);
1901
+
1902
+ t.deepEqual(result, []);
1903
+
1904
+ await db.execute(sql`drop table ${users}`);
1905
+ });
1906
+
1907
+ test.skip('nested transaction', async (t) => {
1908
+ const { db } = t.context;
1909
+
1910
+ const users = pgTable('users_nested_transactions', {
1911
+ id: serial('id').primaryKey(),
1912
+ balance: integer('balance').notNull()
1913
+ });
1914
+
1915
+ await db.execute(sql`drop table if exists ${users}`);
1916
+
1917
+ await db.execute(
1918
+ sql`create table users_nested_transactions (id serial not null primary key, balance integer not null)`
1919
+ );
1920
+
1921
+ await db.transaction(async (tx) => {
1922
+ await tx.insert(users).values({ balance: 100 });
1923
+
1924
+ await tx.transaction(async (tx) => {
1925
+ await tx.update(users).set({ balance: 200 });
1926
+ });
1927
+ });
1928
+
1929
+ const result = await db.select().from(users);
1930
+
1931
+ t.deepEqual(result, [{ id: 1, balance: 200 }]);
1932
+
1933
+ await db.execute(sql`drop table ${users}`);
1934
+ });
1935
+
1936
+ test.skip('nested transaction rollback', async (t) => {
1937
+ const { db } = t.context;
1938
+
1939
+ const users = pgTable('users_nested_transactions_rollback', {
1940
+ id: serial('id').primaryKey(),
1941
+ balance: integer('balance').notNull()
1942
+ });
1943
+
1944
+ await db.execute(sql`drop table if exists ${users}`);
1945
+
1946
+ await db.execute(
1947
+ sql`create table users_nested_transactions_rollback (id serial not null primary key, balance integer not null)`
1948
+ );
1949
+
1950
+ await db.transaction(async (tx) => {
1951
+ await tx.insert(users).values({ balance: 100 });
1952
+
1953
+ await t.throwsAsync(
1954
+ async () =>
1955
+ await tx.transaction(async (tx) => {
1956
+ await tx.update(users).set({ balance: 200 });
1957
+ tx.rollback();
1958
+ }),
1959
+ new TransactionRollbackError()
1960
+ );
1961
+ });
1962
+
1963
+ const result = await db.select().from(users);
1964
+
1965
+ t.deepEqual(result, [{ id: 1, balance: 100 }]);
1966
+
1967
+ await db.execute(sql`drop table ${users}`);
1968
+ });
1969
+
1970
+ test.skip('join subquery with join', async (t) => {
1971
+ const { db } = t.context;
1972
+
1973
+ const internalStaff = pgTable('internal_staff', {
1974
+ userId: integer('user_id').notNull()
1975
+ });
1976
+
1977
+ const customUser = pgTable('custom_user', {
1978
+ id: integer('id').notNull()
1979
+ });
1980
+
1981
+ const ticket = pgTable('ticket', {
1982
+ staffId: integer('staff_id').notNull()
1983
+ });
1984
+
1985
+ await db.execute(sql`drop table if exists ${internalStaff}`);
1986
+ await db.execute(sql`drop table if exists ${customUser}`);
1987
+ await db.execute(sql`drop table if exists ${ticket}`);
1988
+
1989
+ await db.execute(sql`create table internal_staff (user_id integer not null)`);
1990
+ await db.execute(sql`create table custom_user (id integer not null)`);
1991
+ await db.execute(sql`create table ticket (staff_id integer not null)`);
1992
+
1993
+ await db.insert(internalStaff).values({ userId: 1 });
1994
+ await db.insert(customUser).values({ id: 1 });
1995
+ await db.insert(ticket).values({ staffId: 1 });
1996
+
1997
+ const subq = db
1998
+ .select()
1999
+ .from(internalStaff)
2000
+ .leftJoin(customUser, eq(internalStaff.userId, customUser.id))
2001
+ .as('internal_staff');
2002
+
2003
+ const mainQuery = await db.select().from(ticket).leftJoin(subq, eq(subq.internal_staff.userId, ticket.staffId));
2004
+
2005
+ t.deepEqual(mainQuery, [
2006
+ {
2007
+ ticket: { staffId: 1 },
2008
+ internal_staff: {
2009
+ internal_staff: { userId: 1 },
2010
+ custom_user: { id: 1 }
2011
+ }
2012
+ }
2013
+ ]);
2014
+
2015
+ await db.execute(sql`drop table ${internalStaff}`);
2016
+ await db.execute(sql`drop table ${customUser}`);
2017
+ await db.execute(sql`drop table ${ticket}`);
2018
+ });
2019
+
2020
+ test.skip('subquery with view', async (t) => {
2021
+ const { db } = t.context;
2022
+
2023
+ const users = pgTable('users_subquery_view', {
2024
+ id: serial('id').primaryKey(),
2025
+ name: text('name').notNull(),
2026
+ cityId: integer('city_id').notNull()
2027
+ });
2028
+
2029
+ const newYorkers = pgView('new_yorkers').as((qb) => qb.select().from(users).where(eq(users.cityId, 1)));
2030
+
2031
+ await db.execute(sql`drop table if exists ${users}`);
2032
+ await db.execute(sql`drop view if exists ${newYorkers}`);
2033
+
2034
+ await db.execute(
2035
+ sql`create table ${users} (id serial not null primary key, name text not null, city_id integer not null)`
2036
+ );
2037
+ await db.execute(sql`create view ${newYorkers} as select * from ${users} where city_id = 1`);
2038
+
2039
+ await db.insert(users).values([
2040
+ { name: 'John', cityId: 1 },
2041
+ { name: 'Jane', cityId: 2 },
2042
+ { name: 'Jack', cityId: 1 },
2043
+ { name: 'Jill', cityId: 2 }
2044
+ ]);
2045
+
2046
+ const sq = db.$with('sq').as(db.select().from(newYorkers));
2047
+ const result = await db.with(sq).select().from(sq);
2048
+
2049
+ t.deepEqual(result, [
2050
+ { id: 1, name: 'John', cityId: 1 },
2051
+ { id: 3, name: 'Jack', cityId: 1 }
2052
+ ]);
2053
+
2054
+ await db.execute(sql`drop view ${newYorkers}`);
2055
+ await db.execute(sql`drop table ${users}`);
2056
+ });
2057
+
2058
+ test.skip('join view as subquery', async (t) => {
2059
+ const { db } = t.context;
2060
+
2061
+ const users = pgTable('users_join_view', {
2062
+ id: serial('id').primaryKey(),
2063
+ name: text('name').notNull(),
2064
+ cityId: integer('city_id').notNull()
2065
+ });
2066
+
2067
+ const newYorkers = pgView('new_yorkers').as((qb) => qb.select().from(users).where(eq(users.cityId, 1)));
2068
+
2069
+ await db.execute(sql`drop table if exists ${users}`);
2070
+ await db.execute(sql`drop view if exists ${newYorkers}`);
2071
+
2072
+ await db.execute(
2073
+ sql`create table ${users} (id serial not null primary key, name text not null, city_id integer not null)`
2074
+ );
2075
+ await db.execute(sql`create view ${newYorkers} as select * from ${users} where city_id = 1`);
2076
+
2077
+ await db.insert(users).values([
2078
+ { name: 'John', cityId: 1 },
2079
+ { name: 'Jane', cityId: 2 },
2080
+ { name: 'Jack', cityId: 1 },
2081
+ { name: 'Jill', cityId: 2 }
2082
+ ]);
2083
+
2084
+ const sq = db.select().from(newYorkers).as('new_yorkers_sq');
2085
+
2086
+ const result = await db.select().from(users).leftJoin(sq, eq(users.id, sq.id));
2087
+
2088
+ t.deepEqual(result, [
2089
+ {
2090
+ users_join_view: { id: 1, name: 'John', cityId: 1 },
2091
+ new_yorkers_sq: { id: 1, name: 'John', cityId: 1 }
2092
+ },
2093
+ {
2094
+ users_join_view: { id: 2, name: 'Jane', cityId: 2 },
2095
+ new_yorkers_sq: null
2096
+ },
2097
+ {
2098
+ users_join_view: { id: 3, name: 'Jack', cityId: 1 },
2099
+ new_yorkers_sq: { id: 3, name: 'Jack', cityId: 1 }
2100
+ },
2101
+ {
2102
+ users_join_view: { id: 4, name: 'Jill', cityId: 2 },
2103
+ new_yorkers_sq: null
2104
+ }
2105
+ ]);
2106
+
2107
+ await db.execute(sql`drop view ${newYorkers}`);
2108
+ await db.execute(sql`drop table ${users}`);
2109
+ });
2110
+
2111
+ test.skip('table selection with single table', async (t) => {
2112
+ const { db } = t.context;
2113
+
2114
+ const users = pgTable('users', {
2115
+ id: serial('id').primaryKey(),
2116
+ name: text('name').notNull(),
2117
+ cityId: integer('city_id').notNull()
2118
+ });
2119
+
2120
+ await db.execute(sql`drop table if exists ${users}`);
2121
+
2122
+ await db.execute(
2123
+ sql`create table ${users} (id serial not null primary key, name text not null, city_id integer not null)`
2124
+ );
2125
+
2126
+ await db.insert(users).values({ name: 'John', cityId: 1 });
2127
+
2128
+ const result = await db.select({ users }).from(users);
2129
+
2130
+ t.deepEqual(result, [{ users: { id: 1, name: 'John', cityId: 1 } }]);
2131
+
2132
+ await db.execute(sql`drop table ${users}`);
2133
+ });
2134
+
2135
+ test.skip('set null to jsonb field', async (t) => {
2136
+ const { db } = t.context;
2137
+
2138
+ const users = pgTable('users', {
2139
+ id: serial('id').primaryKey(),
2140
+ jsonb: jsonb('jsonb')
2141
+ });
2142
+
2143
+ await db.execute(sql`drop table if exists ${users}`);
2144
+
2145
+ await db.execute(sql`create table ${users} (id serial not null primary key, jsonb jsonb)`);
2146
+
2147
+ const result = await db.insert(users).values({ jsonb: null }).returning();
2148
+
2149
+ t.deepEqual(result, [{ id: 1, jsonb: null }]);
2150
+
2151
+ await db.execute(sql`drop table ${users}`);
2152
+ });
2153
+
2154
+ test.skip('insert undefined', async (t) => {
2155
+ const { db } = t.context;
2156
+
2157
+ const users = pgTable('users', {
2158
+ id: serial('id').primaryKey(),
2159
+ name: text('name')
2160
+ });
2161
+
2162
+ await db.execute(sql`drop table if exists ${users}`);
2163
+
2164
+ await db.execute(sql`create table ${users} (id serial not null primary key, name text)`);
2165
+
2166
+ await t.notThrowsAsync(async () => await db.insert(users).values({ name: undefined }));
2167
+
2168
+ await db.execute(sql`drop table ${users}`);
2169
+ });
2170
+
2171
+ test.skip('update undefined', async (t) => {
2172
+ const { db } = t.context;
2173
+
2174
+ const users = pgTable('users', {
2175
+ id: serial('id').primaryKey(),
2176
+ name: text('name')
2177
+ });
2178
+
2179
+ await db.execute(sql`drop table if exists ${users}`);
2180
+
2181
+ await db.execute(sql`create table ${users} (id serial not null primary key, name text)`);
2182
+
2183
+ await t.throwsAsync(async () => await db.update(users).set({ name: undefined }));
2184
+ await t.notThrowsAsync(async () => await db.update(users).set({ id: 1, name: undefined }));
2185
+
2186
+ await db.execute(sql`drop table ${users}`);
2187
+ });