@anthonyalayo/drizzle-kit 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/.gitignore +25 -0
  2. package/README.md +79 -0
  3. package/build.dev.ts +51 -0
  4. package/build.ts +112 -0
  5. package/imports-checker/analyze.ts +78 -0
  6. package/imports-checker/checker.ts +296 -0
  7. package/imports-checker/grammar/grammar.ohm +121 -0
  8. package/imports-checker/grammar/grammar.ohm-bundle.d.ts +164 -0
  9. package/imports-checker/grammar/grammar.ohm-bundle.js +753 -0
  10. package/imports-checker/index.ts +48 -0
  11. package/package.json +142 -0
  12. package/patches/difflib@0.2.4.patch +31 -0
  13. package/src/@types/utils.ts +58 -0
  14. package/src/api.ts +504 -0
  15. package/src/cli/commands/_es5.ts +2 -0
  16. package/src/cli/commands/check.ts +52 -0
  17. package/src/cli/commands/drop.ts +60 -0
  18. package/src/cli/commands/introspect.ts +772 -0
  19. package/src/cli/commands/libSqlPushUtils.ts +355 -0
  20. package/src/cli/commands/migrate.ts +1526 -0
  21. package/src/cli/commands/mysqlIntrospect.ts +53 -0
  22. package/src/cli/commands/mysqlPushUtils.ts +352 -0
  23. package/src/cli/commands/mysqlUp.ts +102 -0
  24. package/src/cli/commands/pgIntrospect.ts +55 -0
  25. package/src/cli/commands/pgPushUtils.ts +269 -0
  26. package/src/cli/commands/pgUp.ts +217 -0
  27. package/src/cli/commands/push.ts +637 -0
  28. package/src/cli/commands/singlestoreIntrospect.ts +53 -0
  29. package/src/cli/commands/singlestorePushUtils.ts +456 -0
  30. package/src/cli/commands/singlestoreUp.ts +1 -0
  31. package/src/cli/commands/sqliteIntrospect.ts +96 -0
  32. package/src/cli/commands/sqlitePushUtils.ts +322 -0
  33. package/src/cli/commands/sqliteUp.ts +52 -0
  34. package/src/cli/commands/utils.ts +858 -0
  35. package/src/cli/connections.ts +914 -0
  36. package/src/cli/index.ts +48 -0
  37. package/src/cli/schema.ts +794 -0
  38. package/src/cli/selector-ui.ts +38 -0
  39. package/src/cli/utils.ts +112 -0
  40. package/src/cli/validations/cli.ts +79 -0
  41. package/src/cli/validations/common.ts +193 -0
  42. package/src/cli/validations/libsql.ts +27 -0
  43. package/src/cli/validations/mysql.ts +61 -0
  44. package/src/cli/validations/outputs.ts +91 -0
  45. package/src/cli/validations/postgres.ts +83 -0
  46. package/src/cli/validations/singlestore.ts +61 -0
  47. package/src/cli/validations/sqlite.ts +104 -0
  48. package/src/cli/validations/studio.ts +24 -0
  49. package/src/cli/views.ts +658 -0
  50. package/src/extensions/getTablesFilterByExtensions.ts +16 -0
  51. package/src/extensions/vector.ts +10 -0
  52. package/src/global.ts +61 -0
  53. package/src/index.ts +326 -0
  54. package/src/introspect-mysql.ts +1030 -0
  55. package/src/introspect-pg.ts +1435 -0
  56. package/src/introspect-singlestore.ts +913 -0
  57. package/src/introspect-sqlite.ts +533 -0
  58. package/src/jsonDiffer.js +882 -0
  59. package/src/jsonStatements.ts +3590 -0
  60. package/src/loader.mjs +57 -0
  61. package/src/migrationPreparator.ts +217 -0
  62. package/src/schemaValidator.ts +23 -0
  63. package/src/serializer/index.ts +142 -0
  64. package/src/serializer/mysqlImports.ts +38 -0
  65. package/src/serializer/mysqlSchema.ts +423 -0
  66. package/src/serializer/mysqlSerializer.ts +999 -0
  67. package/src/serializer/pgImports.ts +106 -0
  68. package/src/serializer/pgSchema.ts +937 -0
  69. package/src/serializer/pgSerializer.ts +2223 -0
  70. package/src/serializer/singlestoreImports.ts +38 -0
  71. package/src/serializer/singlestoreSchema.ts +257 -0
  72. package/src/serializer/singlestoreSerializer.ts +767 -0
  73. package/src/serializer/sqliteImports.ts +41 -0
  74. package/src/serializer/sqliteSchema.ts +352 -0
  75. package/src/serializer/sqliteSerializer.ts +931 -0
  76. package/src/serializer/studio.ts +694 -0
  77. package/src/serializer/utils.ts +45 -0
  78. package/src/simulator.ts +157 -0
  79. package/src/snapshotsDiffer.ts +4398 -0
  80. package/src/sqlgenerator.ts +4212 -0
  81. package/src/statementCombiner.ts +597 -0
  82. package/src/utils/certs.ts +44 -0
  83. package/src/utils/words.ts +1333 -0
  84. package/src/utils.ts +370 -0
  85. package/tests/bin.test.ts +58 -0
  86. package/tests/cli/d1http.config.ts +12 -0
  87. package/tests/cli/drizzle.config.ts +9 -0
  88. package/tests/cli/durable-sqlite.config.ts +7 -0
  89. package/tests/cli/expo.config.ts +7 -0
  90. package/tests/cli/postgres.config.ts +13 -0
  91. package/tests/cli/postgres2.config.ts +17 -0
  92. package/tests/cli/schema.ts +1 -0
  93. package/tests/cli/turso.config.ts +10 -0
  94. package/tests/cli-export.test.ts +79 -0
  95. package/tests/cli-generate.test.ts +259 -0
  96. package/tests/cli-migrate.test.ts +103 -0
  97. package/tests/cli-push.test.ts +126 -0
  98. package/tests/common.ts +15 -0
  99. package/tests/indexes/common.ts +21 -0
  100. package/tests/indexes/pg.test.ts +245 -0
  101. package/tests/introspect/libsql.test.ts +35 -0
  102. package/tests/introspect/mysql.test.ts +319 -0
  103. package/tests/introspect/pg.test.ts +894 -0
  104. package/tests/introspect/singlestore.test.ts +275 -0
  105. package/tests/introspect/sqlite.test.ts +122 -0
  106. package/tests/libsql-checks.test.ts +308 -0
  107. package/tests/libsql-statements.test.ts +989 -0
  108. package/tests/libsql-views.test.ts +218 -0
  109. package/tests/migrate/libsq-schema.ts +6 -0
  110. package/tests/migrate/libsql-migrate.test.ts +58 -0
  111. package/tests/migrate/migrations/0000_little_blizzard.sql +4 -0
  112. package/tests/migrate/migrations/0001_nebulous_storm.sql +10 -0
  113. package/tests/migrate/migrations/meta/0000_snapshot.json +40 -0
  114. package/tests/migrate/migrations/meta/0001_snapshot.json +40 -0
  115. package/tests/migrate/migrations/meta/_journal.json +20 -0
  116. package/tests/mysql-checks.test.ts +291 -0
  117. package/tests/mysql-generated.test.ts +1290 -0
  118. package/tests/mysql-schemas.test.ts +156 -0
  119. package/tests/mysql-views.test.ts +553 -0
  120. package/tests/mysql.test.ts +863 -0
  121. package/tests/pg-array.test.ts +368 -0
  122. package/tests/pg-checks.test.ts +329 -0
  123. package/tests/pg-columns.test.ts +484 -0
  124. package/tests/pg-domains.test.ts +306 -0
  125. package/tests/pg-enums.test.ts +751 -0
  126. package/tests/pg-generated.test.ts +529 -0
  127. package/tests/pg-identity.test.ts +447 -0
  128. package/tests/pg-schemas.test.ts +105 -0
  129. package/tests/pg-sequences.test.ts +298 -0
  130. package/tests/pg-tables.test.ts +1021 -0
  131. package/tests/pg-views.test.ts +1929 -0
  132. package/tests/push/common.ts +58 -0
  133. package/tests/push/libsql.test.ts +1400 -0
  134. package/tests/push/mysql-push.test.ts +345 -0
  135. package/tests/push/mysql.test.ts +788 -0
  136. package/tests/push/pg.test.ts +4341 -0
  137. package/tests/push/singlestore-push.test.ts +894 -0
  138. package/tests/push/singlestore.test.ts +444 -0
  139. package/tests/push/sqlite.test.ts +1613 -0
  140. package/tests/rls/pg-policy.test.ts +1656 -0
  141. package/tests/rls/pg-role.test.ts +234 -0
  142. package/tests/schemaDiffer.ts +2852 -0
  143. package/tests/singlestore-generated.test.ts +1290 -0
  144. package/tests/singlestore-schemas.test.ts +155 -0
  145. package/tests/singlestore.test.ts +978 -0
  146. package/tests/sqlite-checks.test.ts +308 -0
  147. package/tests/sqlite-columns.test.ts +1049 -0
  148. package/tests/sqlite-generated.test.ts +1726 -0
  149. package/tests/sqlite-tables.test.ts +637 -0
  150. package/tests/sqlite-views.test.ts +218 -0
  151. package/tests/statements-combiner/libsql-statements-combiner.test.ts +1812 -0
  152. package/tests/statements-combiner/singlestore-statements-combiner.test.ts +882 -0
  153. package/tests/statements-combiner/sqlite-statements-combiner.test.ts +1211 -0
  154. package/tests/test/sqlite.test.ts +39 -0
  155. package/tests/testsinglestore.ts +29 -0
  156. package/tests/validations.test.ts +869 -0
  157. package/tests/wrap-param.test.ts +16 -0
  158. package/tsconfig.build.json +4 -0
  159. package/tsconfig.cli-types.json +9 -0
  160. package/tsconfig.json +28 -0
  161. package/vitest.config.ts +34 -0
@@ -0,0 +1,1400 @@
1
+ import { createClient } from '@libsql/client';
2
+ import chalk from 'chalk';
3
+ import { sql } from 'drizzle-orm';
4
+ import {
5
+ blob,
6
+ check,
7
+ foreignKey,
8
+ getTableConfig,
9
+ index,
10
+ int,
11
+ integer,
12
+ numeric,
13
+ real,
14
+ sqliteTable,
15
+ sqliteView,
16
+ text,
17
+ uniqueIndex,
18
+ } from 'drizzle-orm/sqlite-core';
19
+ import { diffTestSchemasPushLibSQL } from 'tests/schemaDiffer';
20
+ import { expect, test } from 'vitest';
21
+
22
+ test('nothing changed in schema', async (t) => {
23
+ const turso = createClient({
24
+ url: ':memory:',
25
+ });
26
+
27
+ const users = sqliteTable('users', {
28
+ id: integer('id').primaryKey().notNull(),
29
+ name: text('name').notNull(),
30
+ email: text('email'),
31
+ textJson: text('text_json', { mode: 'json' }),
32
+ blobJon: blob('blob_json', { mode: 'json' }),
33
+ blobBigInt: blob('blob_bigint', { mode: 'bigint' }),
34
+ numeric: numeric('numeric'),
35
+ createdAt: integer('created_at', { mode: 'timestamp' }),
36
+ createdAtMs: integer('created_at_ms', { mode: 'timestamp_ms' }),
37
+ real: real('real'),
38
+ text: text('text', { length: 255 }),
39
+ role: text('role', { enum: ['admin', 'user'] }).default('user'),
40
+ isConfirmed: integer('is_confirmed', {
41
+ mode: 'boolean',
42
+ }),
43
+ });
44
+
45
+ const schema1 = {
46
+ users,
47
+
48
+ customers: sqliteTable('customers', {
49
+ id: integer('id').primaryKey(),
50
+ address: text('address').notNull(),
51
+ isConfirmed: integer('is_confirmed', { mode: 'boolean' }),
52
+ registrationDate: integer('registration_date', { mode: 'timestamp_ms' })
53
+ .notNull()
54
+ .$defaultFn(() => new Date()),
55
+ userId: integer('user_id')
56
+ .references(() => users.id)
57
+ .notNull(),
58
+ }),
59
+
60
+ posts: sqliteTable('posts', {
61
+ id: integer('id').primaryKey(),
62
+ content: text('content'),
63
+ authorId: integer('author_id'),
64
+ }),
65
+ };
66
+
67
+ const {
68
+ sqlStatements,
69
+ statements,
70
+ columnsToRemove,
71
+ infoToPrint,
72
+ shouldAskForApprove,
73
+ tablesToRemove,
74
+ tablesToTruncate,
75
+ } = await diffTestSchemasPushLibSQL(turso, schema1, schema1, [], false);
76
+ expect(sqlStatements.length).toBe(0);
77
+ expect(statements.length).toBe(0);
78
+ expect(columnsToRemove!.length).toBe(0);
79
+ expect(infoToPrint!.length).toBe(0);
80
+ expect(shouldAskForApprove).toBe(false);
81
+ expect(tablesToRemove!.length).toBe(0);
82
+ expect(tablesToTruncate!.length).toBe(0);
83
+ expect(shouldAskForApprove).toBe(false);
84
+ });
85
+
86
+ test('added, dropped index', async (t) => {
87
+ const turso = createClient({
88
+ url: ':memory:',
89
+ });
90
+
91
+ const users = sqliteTable('users', {
92
+ id: integer('id').primaryKey().notNull(),
93
+ name: text('name').notNull(),
94
+ email: text('email'),
95
+ textJson: text('text_json', { mode: 'json' }),
96
+ blobJon: blob('blob_json', { mode: 'json' }),
97
+ blobBigInt: blob('blob_bigint', { mode: 'bigint' }),
98
+ numeric: numeric('numeric'),
99
+ createdAt: integer('created_at', { mode: 'timestamp' }),
100
+ createdAtMs: integer('created_at_ms', { mode: 'timestamp_ms' }),
101
+ real: real('real'),
102
+ text: text('text', { length: 255 }),
103
+ role: text('role', { enum: ['admin', 'user'] }).default('user'),
104
+ isConfirmed: integer('is_confirmed', {
105
+ mode: 'boolean',
106
+ }),
107
+ });
108
+
109
+ const schema1 = {
110
+ users,
111
+ customers: sqliteTable(
112
+ 'customers',
113
+ {
114
+ id: integer('id').primaryKey(),
115
+ address: text('address').notNull(),
116
+ isConfirmed: integer('is_confirmed', { mode: 'boolean' }),
117
+ registrationDate: integer('registration_date', { mode: 'timestamp_ms' })
118
+ .notNull()
119
+ .$defaultFn(() => new Date()),
120
+ userId: integer('user_id').notNull(),
121
+ },
122
+ (table) => ({
123
+ uniqueIndex: uniqueIndex('customers_address_unique').on(table.address),
124
+ }),
125
+ ),
126
+
127
+ posts: sqliteTable('posts', {
128
+ id: integer('id').primaryKey(),
129
+ content: text('content'),
130
+ authorId: integer('author_id'),
131
+ }),
132
+ };
133
+
134
+ const schema2 = {
135
+ users,
136
+ customers: sqliteTable(
137
+ 'customers',
138
+ {
139
+ id: integer('id').primaryKey(),
140
+ address: text('address').notNull(),
141
+ isConfirmed: integer('is_confirmed', { mode: 'boolean' }),
142
+ registrationDate: integer('registration_date', { mode: 'timestamp_ms' })
143
+ .notNull()
144
+ .$defaultFn(() => new Date()),
145
+ userId: integer('user_id').notNull(),
146
+ },
147
+ (table) => ({
148
+ uniqueIndex: uniqueIndex('customers_is_confirmed_unique').on(
149
+ table.isConfirmed,
150
+ ),
151
+ }),
152
+ ),
153
+
154
+ posts: sqliteTable('posts', {
155
+ id: integer('id').primaryKey(),
156
+ content: text('content'),
157
+ authorId: integer('author_id'),
158
+ }),
159
+ };
160
+
161
+ const {
162
+ sqlStatements,
163
+ statements,
164
+ columnsToRemove,
165
+ infoToPrint,
166
+ shouldAskForApprove,
167
+ tablesToRemove,
168
+ tablesToTruncate,
169
+ } = await diffTestSchemasPushLibSQL(turso, schema1, schema2, [], false);
170
+
171
+ expect(statements.length).toBe(2);
172
+ expect(statements[0]).toStrictEqual({
173
+ type: 'drop_index',
174
+ tableName: 'customers',
175
+ data: 'customers_address_unique;address;true;',
176
+ schema: '',
177
+ });
178
+ expect(statements[1]).toStrictEqual({
179
+ type: 'create_index',
180
+ tableName: 'customers',
181
+ data: 'customers_is_confirmed_unique;is_confirmed;true;',
182
+ schema: '',
183
+ internal: { indexes: {} },
184
+ });
185
+
186
+ expect(sqlStatements.length).toBe(2);
187
+ expect(sqlStatements[0]).toBe(
188
+ `DROP INDEX \`customers_address_unique\`;`,
189
+ );
190
+ expect(sqlStatements[1]).toBe(
191
+ `CREATE UNIQUE INDEX \`customers_is_confirmed_unique\` ON \`customers\` (\`is_confirmed\`);`,
192
+ );
193
+
194
+ expect(columnsToRemove!.length).toBe(0);
195
+ expect(infoToPrint!.length).toBe(0);
196
+ expect(shouldAskForApprove).toBe(false);
197
+ expect(tablesToRemove!.length).toBe(0);
198
+ expect(tablesToTruncate!.length).toBe(0);
199
+ });
200
+
201
+ test('added column not null and without default to table with data', async (t) => {
202
+ const turso = createClient({
203
+ url: ':memory:',
204
+ });
205
+
206
+ const schema1 = {
207
+ companies: sqliteTable('companies', {
208
+ id: integer('id').primaryKey(),
209
+ name: text('name').notNull(),
210
+ }),
211
+ };
212
+
213
+ const schema2 = {
214
+ companies: sqliteTable('companies', {
215
+ id: integer('id').primaryKey(),
216
+ name: text('name').notNull(),
217
+ age: integer('age').notNull(),
218
+ }),
219
+ };
220
+
221
+ const table = getTableConfig(schema1.companies);
222
+
223
+ const seedStatements = [
224
+ `INSERT INTO \`${table.name}\` ("${schema1.companies.name.name}") VALUES ('drizzle');`,
225
+ `INSERT INTO \`${table.name}\` ("${schema1.companies.name.name}") VALUES ('turso');`,
226
+ ];
227
+
228
+ const {
229
+ statements,
230
+ sqlStatements,
231
+ columnsToRemove,
232
+ infoToPrint,
233
+ shouldAskForApprove,
234
+ tablesToRemove,
235
+ tablesToTruncate,
236
+ } = await diffTestSchemasPushLibSQL(
237
+ turso,
238
+ schema1,
239
+ schema2,
240
+ [],
241
+ false,
242
+ seedStatements,
243
+ );
244
+
245
+ expect(statements.length).toBe(1);
246
+ expect(statements[0]).toStrictEqual({
247
+ type: 'sqlite_alter_table_add_column',
248
+ tableName: 'companies',
249
+ column: {
250
+ name: 'age',
251
+ type: 'integer',
252
+ primaryKey: false,
253
+ notNull: true,
254
+ autoincrement: false,
255
+ },
256
+ referenceData: undefined,
257
+ });
258
+
259
+ expect(sqlStatements.length).toBe(2);
260
+ expect(sqlStatements[0]).toBe(`delete from companies;`);
261
+ expect(sqlStatements[1]).toBe(
262
+ `ALTER TABLE \`companies\` ADD \`age\` integer NOT NULL;`,
263
+ );
264
+
265
+ expect(columnsToRemove!.length).toBe(0);
266
+ expect(infoToPrint!.length).toBe(1);
267
+ expect(infoToPrint![0]).toBe(
268
+ `· You're about to add not-null ${
269
+ chalk.underline(
270
+ 'age',
271
+ )
272
+ } column without default value, which contains 2 items`,
273
+ );
274
+ expect(shouldAskForApprove).toBe(true);
275
+ expect(tablesToRemove!.length).toBe(0);
276
+ expect(tablesToTruncate!.length).toBe(1);
277
+ expect(tablesToTruncate![0]).toBe('companies');
278
+ });
279
+
280
+ test('added column not null and without default to table without data', async (t) => {
281
+ const turso = createClient({
282
+ url: ':memory:',
283
+ });
284
+
285
+ const schema1 = {
286
+ companies: sqliteTable('companies', {
287
+ id: integer('id').primaryKey(),
288
+ name: text('name').notNull(),
289
+ }),
290
+ };
291
+
292
+ const schema2 = {
293
+ companies: sqliteTable('companies', {
294
+ id: integer('id').primaryKey(),
295
+ name: text('name').notNull(),
296
+ age: integer('age').notNull(),
297
+ }),
298
+ };
299
+
300
+ const {
301
+ sqlStatements,
302
+ statements,
303
+ columnsToRemove,
304
+ infoToPrint,
305
+ shouldAskForApprove,
306
+ tablesToRemove,
307
+ tablesToTruncate,
308
+ } = await diffTestSchemasPushLibSQL(turso, schema1, schema2, [], false);
309
+
310
+ expect(statements.length).toBe(1);
311
+ expect(statements[0]).toStrictEqual({
312
+ type: 'sqlite_alter_table_add_column',
313
+ tableName: 'companies',
314
+ column: {
315
+ name: 'age',
316
+ type: 'integer',
317
+ primaryKey: false,
318
+ notNull: true,
319
+ autoincrement: false,
320
+ },
321
+ referenceData: undefined,
322
+ });
323
+
324
+ expect(sqlStatements.length).toBe(1);
325
+ expect(sqlStatements[0]).toBe(
326
+ `ALTER TABLE \`companies\` ADD \`age\` integer NOT NULL;`,
327
+ );
328
+
329
+ expect(infoToPrint!.length).toBe(0);
330
+ expect(columnsToRemove!.length).toBe(0);
331
+ expect(shouldAskForApprove).toBe(false);
332
+ expect(tablesToRemove!.length).toBe(0);
333
+ expect(tablesToTruncate!.length).toBe(0);
334
+ });
335
+
336
+ test('drop autoincrement. drop column with data', async (t) => {
337
+ const turso = createClient({
338
+ url: ':memory:',
339
+ });
340
+
341
+ const schema1 = {
342
+ companies: sqliteTable('companies', {
343
+ id: integer('id').primaryKey({ autoIncrement: true }),
344
+ name: text('name'),
345
+ }),
346
+ };
347
+
348
+ const schema2 = {
349
+ companies: sqliteTable('companies', {
350
+ id: integer('id').primaryKey({ autoIncrement: false }),
351
+ }),
352
+ };
353
+
354
+ const table = getTableConfig(schema1.companies);
355
+ const seedStatements = [
356
+ `INSERT INTO \`${table.name}\` ("${schema1.companies.id.name}", "${schema1.companies.name.name}") VALUES (1, 'drizzle');`,
357
+ `INSERT INTO \`${table.name}\` ("${schema1.companies.id.name}", "${schema1.companies.name.name}") VALUES (2, 'turso');`,
358
+ ];
359
+
360
+ const {
361
+ sqlStatements,
362
+ statements,
363
+ columnsToRemove,
364
+ infoToPrint,
365
+ shouldAskForApprove,
366
+ tablesToRemove,
367
+ tablesToTruncate,
368
+ } = await diffTestSchemasPushLibSQL(
369
+ turso,
370
+ schema1,
371
+ schema2,
372
+ [],
373
+ false,
374
+ seedStatements,
375
+ );
376
+
377
+ expect(statements.length).toBe(1);
378
+ expect(statements[0]).toStrictEqual({
379
+ type: 'recreate_table',
380
+ tableName: 'companies',
381
+ columns: [
382
+ {
383
+ name: 'id',
384
+ type: 'integer',
385
+ autoincrement: false,
386
+ notNull: true,
387
+ primaryKey: true,
388
+ generated: undefined,
389
+ },
390
+ ],
391
+ compositePKs: [],
392
+ referenceData: [],
393
+ uniqueConstraints: [],
394
+ checkConstraints: [],
395
+ });
396
+
397
+ expect(sqlStatements.length).toBe(4);
398
+ expect(sqlStatements[0]).toBe(
399
+ `CREATE TABLE \`__new_companies\` (
400
+ \t\`id\` integer PRIMARY KEY NOT NULL
401
+ );\n`,
402
+ );
403
+ expect(sqlStatements[1]).toBe(`INSERT INTO \`__new_companies\`("id") SELECT "id" FROM \`companies\`;`);
404
+ expect(sqlStatements[2]).toBe(`DROP TABLE \`companies\`;`);
405
+ expect(sqlStatements[3]).toBe(
406
+ `ALTER TABLE \`__new_companies\` RENAME TO \`companies\`;`,
407
+ );
408
+
409
+ expect(columnsToRemove!.length).toBe(1);
410
+ expect(infoToPrint!.length).toBe(1);
411
+ expect(infoToPrint![0]).toBe(
412
+ `· You're about to delete ${
413
+ chalk.underline(
414
+ 'name',
415
+ )
416
+ } column in companies table with 2 items`,
417
+ );
418
+ expect(shouldAskForApprove).toBe(true);
419
+ expect(tablesToRemove!.length).toBe(0);
420
+ expect(tablesToTruncate!.length).toBe(0);
421
+ });
422
+
423
+ test('change autoincrement. table is part of foreign key', async (t) => {
424
+ const turso = createClient({
425
+ url: ':memory:',
426
+ });
427
+
428
+ const companies1 = sqliteTable('companies', {
429
+ id: integer('id').primaryKey({ autoIncrement: true }),
430
+ });
431
+ const users1 = sqliteTable('users', {
432
+ id: integer('id').primaryKey({ autoIncrement: true }),
433
+ name: text('name').unique(),
434
+ companyId: integer('company_id').references(() => companies1.id),
435
+ });
436
+ const schema1 = {
437
+ companies: companies1,
438
+ users: users1,
439
+ };
440
+
441
+ const companies2 = sqliteTable('companies', {
442
+ id: integer('id').primaryKey({ autoIncrement: false }),
443
+ });
444
+ const users2 = sqliteTable('users', {
445
+ id: integer('id').primaryKey({ autoIncrement: true }),
446
+ name: text('name').unique(),
447
+ companyId: integer('company_id').references(() => companies2.id),
448
+ });
449
+ const schema2 = {
450
+ companies: companies2,
451
+ users: users2,
452
+ };
453
+
454
+ const { name: usersTableName } = getTableConfig(users1);
455
+ const { name: companiesTableName } = getTableConfig(companies1);
456
+ const seedStatements = [
457
+ `INSERT INTO \`${usersTableName}\` ("${schema1.users.name.name}") VALUES ('drizzle');`,
458
+ `INSERT INTO \`${usersTableName}\` ("${schema1.users.name.name}") VALUES ('turso');`,
459
+ `INSERT INTO \`${companiesTableName}\` ("${schema1.companies.id.name}") VALUES (1);`,
460
+ `INSERT INTO \`${companiesTableName}\` ("${schema1.companies.id.name}") VALUES (2);`,
461
+ ];
462
+
463
+ const {
464
+ statements,
465
+ sqlStatements,
466
+ columnsToRemove,
467
+ infoToPrint,
468
+ shouldAskForApprove,
469
+ tablesToRemove,
470
+ tablesToTruncate,
471
+ } = await diffTestSchemasPushLibSQL(
472
+ turso,
473
+ schema1,
474
+ schema2,
475
+ [],
476
+ false,
477
+ seedStatements,
478
+ );
479
+
480
+ expect(statements.length).toBe(1);
481
+ expect(statements[0]).toStrictEqual({
482
+ type: 'recreate_table',
483
+ tableName: 'companies',
484
+ columns: [
485
+ {
486
+ name: 'id',
487
+ type: 'integer',
488
+ autoincrement: false,
489
+ notNull: true,
490
+ primaryKey: true,
491
+ generated: undefined,
492
+ },
493
+ ],
494
+ compositePKs: [],
495
+ referenceData: [],
496
+ uniqueConstraints: [],
497
+ checkConstraints: [],
498
+ });
499
+
500
+ expect(sqlStatements.length).toBe(4);
501
+ expect(sqlStatements[0]).toBe(
502
+ `CREATE TABLE \`__new_companies\` (
503
+ \t\`id\` integer PRIMARY KEY NOT NULL
504
+ );\n`,
505
+ );
506
+ expect(sqlStatements[1]).toBe(
507
+ `INSERT INTO \`__new_companies\`("id") SELECT "id" FROM \`companies\`;`,
508
+ );
509
+ expect(sqlStatements[2]).toBe(`DROP TABLE \`companies\`;`);
510
+ expect(sqlStatements[3]).toBe(
511
+ `ALTER TABLE \`__new_companies\` RENAME TO \`companies\`;`,
512
+ );
513
+
514
+ expect(columnsToRemove!.length).toBe(0);
515
+ expect(infoToPrint!.length).toBe(0);
516
+ expect(shouldAskForApprove).toBe(false);
517
+ expect(tablesToRemove!.length).toBe(0);
518
+ expect(tablesToTruncate!.length).toBe(0);
519
+ });
520
+
521
+ test('drop not null, add not null', async (t) => {
522
+ const turso = createClient({
523
+ url: ':memory:',
524
+ });
525
+
526
+ const schema1 = {
527
+ users: sqliteTable('users', {
528
+ id: int('id').primaryKey({ autoIncrement: true }),
529
+ name: text('name').notNull(),
530
+ }),
531
+ posts: sqliteTable(
532
+ 'posts',
533
+ {
534
+ id: int('id').primaryKey({ autoIncrement: true }),
535
+ name: text('name'),
536
+ userId: int('user_id'),
537
+ },
538
+ ),
539
+ };
540
+
541
+ const schema2 = {
542
+ users: sqliteTable('users', {
543
+ id: int('id').primaryKey({ autoIncrement: true }),
544
+ name: text('name'),
545
+ }),
546
+ posts: sqliteTable(
547
+ 'posts',
548
+ {
549
+ id: int('id').primaryKey({ autoIncrement: true }),
550
+ name: text('name').notNull(),
551
+ userId: int('user_id'),
552
+ },
553
+ ),
554
+ };
555
+ const {
556
+ statements,
557
+ sqlStatements,
558
+ columnsToRemove,
559
+ infoToPrint,
560
+ shouldAskForApprove,
561
+ tablesToRemove,
562
+ tablesToTruncate,
563
+ } = await diffTestSchemasPushLibSQL(
564
+ turso,
565
+ schema1,
566
+ schema2,
567
+ [],
568
+ );
569
+
570
+ expect(statements!.length).toBe(2);
571
+ expect(statements![0]).toStrictEqual({
572
+ columnAutoIncrement: false,
573
+ columnDefault: undefined,
574
+ columnName: 'name',
575
+ columnNotNull: false,
576
+ columnOnUpdate: undefined,
577
+ columnPk: false,
578
+ newDataType: 'text',
579
+ schema: '',
580
+ tableName: 'users',
581
+ type: 'alter_table_alter_column_drop_notnull',
582
+ });
583
+ expect(statements![1]).toStrictEqual({
584
+ columnAutoIncrement: false,
585
+ columnDefault: undefined,
586
+ columnName: 'name',
587
+ columnNotNull: true,
588
+ columnOnUpdate: undefined,
589
+ columnPk: false,
590
+ newDataType: 'text',
591
+ schema: '',
592
+ tableName: 'posts',
593
+ type: 'alter_table_alter_column_set_notnull',
594
+ });
595
+ expect(sqlStatements!.length).toBe(2);
596
+ expect(sqlStatements![0]).toBe(`ALTER TABLE \`users\` ALTER COLUMN "name" TO "name" text;`);
597
+ expect(sqlStatements![1]).toBe(`ALTER TABLE \`posts\` ALTER COLUMN "name" TO "name" text NOT NULL;`);
598
+ expect(columnsToRemove!.length).toBe(0);
599
+ expect(infoToPrint!.length).toBe(0);
600
+ expect(shouldAskForApprove).toBe(false);
601
+ expect(tablesToRemove!.length).toBe(0);
602
+ expect(tablesToTruncate!.length).toBe(0);
603
+ });
604
+
605
+ test('drop table with data', async (t) => {
606
+ const turso = createClient({
607
+ url: ':memory:',
608
+ });
609
+
610
+ const schema1 = {
611
+ users: sqliteTable('users', {
612
+ id: int('id').primaryKey({ autoIncrement: true }),
613
+ name: text('name').notNull(),
614
+ }),
615
+ posts: sqliteTable(
616
+ 'posts',
617
+ {
618
+ id: int('id').primaryKey({ autoIncrement: true }),
619
+ name: text('name'),
620
+ userId: int('user_id'),
621
+ },
622
+ ),
623
+ };
624
+
625
+ const schema2 = {
626
+ posts: sqliteTable(
627
+ 'posts',
628
+ {
629
+ id: int('id').primaryKey({ autoIncrement: true }),
630
+ name: text('name'),
631
+ userId: int('user_id'),
632
+ },
633
+ ),
634
+ };
635
+
636
+ const seedStatements = [
637
+ `INSERT INTO \`users\` ("name") VALUES ('drizzle')`,
638
+ ];
639
+ const {
640
+ statements,
641
+ sqlStatements,
642
+ columnsToRemove,
643
+ infoToPrint,
644
+ shouldAskForApprove,
645
+ tablesToRemove,
646
+ tablesToTruncate,
647
+ } = await diffTestSchemasPushLibSQL(
648
+ turso,
649
+ schema1,
650
+ schema2,
651
+ [],
652
+ false,
653
+ seedStatements,
654
+ );
655
+
656
+ expect(statements!.length).toBe(1);
657
+ expect(statements![0]).toStrictEqual({
658
+ policies: [],
659
+ schema: undefined,
660
+ tableName: 'users',
661
+ type: 'drop_table',
662
+ });
663
+
664
+ expect(sqlStatements!.length).toBe(1);
665
+ expect(sqlStatements![0]).toBe(`DROP TABLE \`users\`;`);
666
+ expect(columnsToRemove!.length).toBe(0);
667
+ expect(infoToPrint!.length).toBe(1);
668
+ expect(infoToPrint![0]).toBe(`· You're about to delete ${chalk.underline('users')} table with 1 items`);
669
+ expect(shouldAskForApprove).toBe(true);
670
+ expect(tablesToRemove!.length).toBe(1);
671
+ expect(tablesToRemove![0]).toBe('users');
672
+ expect(tablesToTruncate!.length).toBe(0);
673
+ });
674
+
675
+ test('recreate table with nested references', async (t) => {
676
+ const turso = createClient({
677
+ url: ':memory:',
678
+ });
679
+
680
+ let users = sqliteTable('users', {
681
+ id: int('id').primaryKey({ autoIncrement: true }),
682
+ name: text('name'),
683
+ age: integer('age'),
684
+ });
685
+ let subscriptions = sqliteTable('subscriptions', {
686
+ id: int('id').primaryKey({ autoIncrement: true }),
687
+ userId: integer('user_id').references(() => users.id),
688
+ customerId: text('customer_id'),
689
+ });
690
+ const schema1 = {
691
+ users: users,
692
+ subscriptions: subscriptions,
693
+ subscriptionMetadata: sqliteTable('subscriptions_metadata', {
694
+ id: int('id').primaryKey({ autoIncrement: true }),
695
+ subscriptionId: text('subscription_id').references(
696
+ () => subscriptions.id,
697
+ ),
698
+ }),
699
+ };
700
+
701
+ users = sqliteTable('users', {
702
+ id: int('id').primaryKey({ autoIncrement: false }),
703
+ name: text('name'),
704
+ age: integer('age'),
705
+ });
706
+ const schema2 = {
707
+ users: users,
708
+ subscriptions: subscriptions,
709
+ subscriptionMetadata: sqliteTable('subscriptions_metadata', {
710
+ id: int('id').primaryKey({ autoIncrement: true }),
711
+ subscriptionId: text('subscription_id').references(
712
+ () => subscriptions.id,
713
+ ),
714
+ }),
715
+ };
716
+
717
+ const {
718
+ statements,
719
+ sqlStatements,
720
+ columnsToRemove,
721
+ infoToPrint,
722
+ shouldAskForApprove,
723
+ tablesToRemove,
724
+ tablesToTruncate,
725
+ } = await diffTestSchemasPushLibSQL(turso, schema1, schema2, []);
726
+
727
+ expect(statements!.length).toBe(1);
728
+ expect(statements![0]).toStrictEqual({
729
+ columns: [
730
+ {
731
+ autoincrement: false,
732
+ name: 'id',
733
+ notNull: true,
734
+ generated: undefined,
735
+ primaryKey: true,
736
+ type: 'integer',
737
+ },
738
+ {
739
+ autoincrement: false,
740
+ name: 'name',
741
+ notNull: false,
742
+ generated: undefined,
743
+ primaryKey: false,
744
+ type: 'text',
745
+ },
746
+ {
747
+ autoincrement: false,
748
+ name: 'age',
749
+ notNull: false,
750
+ generated: undefined,
751
+ primaryKey: false,
752
+ type: 'integer',
753
+ },
754
+ ],
755
+ compositePKs: [],
756
+ referenceData: [],
757
+ tableName: 'users',
758
+ type: 'recreate_table',
759
+ uniqueConstraints: [],
760
+ checkConstraints: [],
761
+ });
762
+
763
+ expect(sqlStatements!.length).toBe(4);
764
+ expect(sqlStatements![0]).toBe(`CREATE TABLE \`__new_users\` (
765
+ \t\`id\` integer PRIMARY KEY NOT NULL,
766
+ \t\`name\` text,
767
+ \t\`age\` integer
768
+ );\n`);
769
+ expect(sqlStatements![1]).toBe(
770
+ `INSERT INTO \`__new_users\`("id", "name", "age") SELECT "id", "name", "age" FROM \`users\`;`,
771
+ );
772
+ expect(sqlStatements![2]).toBe(`DROP TABLE \`users\`;`);
773
+ expect(sqlStatements![3]).toBe(
774
+ `ALTER TABLE \`__new_users\` RENAME TO \`users\`;`,
775
+ );
776
+
777
+ expect(columnsToRemove!.length).toBe(0);
778
+ expect(infoToPrint!.length).toBe(0);
779
+ expect(shouldAskForApprove).toBe(false);
780
+ expect(tablesToRemove!.length).toBe(0);
781
+ expect(tablesToTruncate!.length).toBe(0);
782
+ });
783
+
784
+ test('recreate table with added column not null and without default', async (t) => {
785
+ const turso = createClient({
786
+ url: ':memory:',
787
+ });
788
+
789
+ const schema1 = {
790
+ users: sqliteTable('users', {
791
+ id: int('id').primaryKey({ autoIncrement: true }),
792
+ name: text('name'),
793
+ age: integer('age'),
794
+ }),
795
+ };
796
+
797
+ const schema2 = {
798
+ users: sqliteTable('users', {
799
+ id: int('id').primaryKey({ autoIncrement: false }),
800
+ name: text('name'),
801
+ age: integer('age'),
802
+ newColumn: text('new_column').notNull(),
803
+ }),
804
+ };
805
+
806
+ const seedStatements = [
807
+ `INSERT INTO \`users\` ("name", "age") VALUES ('drizzle', 12)`,
808
+ `INSERT INTO \`users\` ("name", "age") VALUES ('turso', 12)`,
809
+ ];
810
+
811
+ const {
812
+ statements,
813
+ sqlStatements,
814
+ columnsToRemove,
815
+ infoToPrint,
816
+ shouldAskForApprove,
817
+ tablesToRemove,
818
+ tablesToTruncate,
819
+ } = await diffTestSchemasPushLibSQL(
820
+ turso,
821
+ schema1,
822
+ schema2,
823
+ [],
824
+ false,
825
+ seedStatements,
826
+ );
827
+
828
+ expect(statements!.length).toBe(1);
829
+ expect(statements![0]).toStrictEqual({
830
+ columns: [
831
+ {
832
+ autoincrement: false,
833
+ name: 'id',
834
+ notNull: true,
835
+ generated: undefined,
836
+ primaryKey: true,
837
+ type: 'integer',
838
+ },
839
+ {
840
+ autoincrement: false,
841
+ name: 'name',
842
+ notNull: false,
843
+ generated: undefined,
844
+ primaryKey: false,
845
+ type: 'text',
846
+ },
847
+ {
848
+ autoincrement: false,
849
+ name: 'age',
850
+ notNull: false,
851
+ generated: undefined,
852
+ primaryKey: false,
853
+ type: 'integer',
854
+ },
855
+ {
856
+ autoincrement: false,
857
+ name: 'new_column',
858
+ notNull: true,
859
+ generated: undefined,
860
+ primaryKey: false,
861
+ type: 'text',
862
+ },
863
+ ],
864
+ compositePKs: [],
865
+ referenceData: [],
866
+ tableName: 'users',
867
+ type: 'recreate_table',
868
+ uniqueConstraints: [],
869
+ checkConstraints: [],
870
+ });
871
+
872
+ expect(sqlStatements!.length).toBe(4);
873
+ expect(sqlStatements[0]).toBe('DELETE FROM \`users\`;');
874
+ expect(sqlStatements![1]).toBe(`CREATE TABLE \`__new_users\` (
875
+ \t\`id\` integer PRIMARY KEY NOT NULL,
876
+ \t\`name\` text,
877
+ \t\`age\` integer,
878
+ \t\`new_column\` text NOT NULL
879
+ );\n`);
880
+ expect(sqlStatements![2]).toBe(`DROP TABLE \`users\`;`);
881
+ expect(sqlStatements![3]).toBe(
882
+ `ALTER TABLE \`__new_users\` RENAME TO \`users\`;`,
883
+ );
884
+
885
+ expect(columnsToRemove!.length).toBe(0);
886
+ expect(infoToPrint!.length).toBe(1);
887
+ expect(infoToPrint![0]).toBe(
888
+ `· You're about to add not-null ${
889
+ chalk.underline('new_column')
890
+ } column without default value to table, which contains 2 items`,
891
+ );
892
+ expect(shouldAskForApprove).toBe(true);
893
+ expect(tablesToRemove!.length).toBe(0);
894
+ expect(tablesToTruncate!.length).toBe(1);
895
+ expect(tablesToTruncate![0]).toBe('users');
896
+ });
897
+
898
+ test('set not null with index', async (t) => {
899
+ const turso = createClient({
900
+ url: ':memory:',
901
+ });
902
+
903
+ const schema1 = {
904
+ users: sqliteTable('users', {
905
+ id: int('id').primaryKey({ autoIncrement: true }),
906
+ name: text('name'),
907
+ }, (table) => ({
908
+ someIndex: index('users_name_index').on(table.name),
909
+ })),
910
+ };
911
+
912
+ const schema2 = {
913
+ users: sqliteTable('users', {
914
+ id: int('id').primaryKey({ autoIncrement: true }),
915
+ name: text('name').notNull(),
916
+ }, (table) => ({
917
+ someIndex: index('users_name_index').on(table.name),
918
+ })),
919
+ };
920
+
921
+ const {
922
+ statements,
923
+ sqlStatements,
924
+ columnsToRemove,
925
+ infoToPrint,
926
+ shouldAskForApprove,
927
+ tablesToRemove,
928
+ tablesToTruncate,
929
+ } = await diffTestSchemasPushLibSQL(
930
+ turso,
931
+ schema1,
932
+ schema2,
933
+ [],
934
+ );
935
+
936
+ expect(statements!.length).toBe(1);
937
+ expect(statements![0]).toStrictEqual({
938
+ columnAutoIncrement: false,
939
+ columnDefault: undefined,
940
+ columnName: 'name',
941
+ columnNotNull: true,
942
+ columnOnUpdate: undefined,
943
+ columnPk: false,
944
+ newDataType: 'text',
945
+ schema: '',
946
+ tableName: 'users',
947
+ type: 'alter_table_alter_column_set_notnull',
948
+ });
949
+
950
+ expect(statements.length).toBe(1);
951
+ expect(statements[0]).toStrictEqual({
952
+ type: 'alter_table_alter_column_set_notnull',
953
+ tableName: 'users',
954
+ columnName: 'name',
955
+ schema: '',
956
+ newDataType: 'text',
957
+ columnDefault: undefined,
958
+ columnOnUpdate: undefined,
959
+ columnNotNull: true,
960
+ columnAutoIncrement: false,
961
+ columnPk: false,
962
+ });
963
+
964
+ expect(sqlStatements.length).toBe(3);
965
+ expect(sqlStatements[0]).toBe(
966
+ `DROP INDEX "users_name_index";`,
967
+ );
968
+ expect(sqlStatements[1]).toBe(
969
+ `ALTER TABLE \`users\` ALTER COLUMN "name" TO "name" text NOT NULL;`,
970
+ );
971
+ expect(sqlStatements[2]).toBe(
972
+ `CREATE INDEX \`users_name_index\` ON \`users\` (\`name\`);`,
973
+ );
974
+ expect(columnsToRemove!.length).toBe(0), expect(infoToPrint!.length).toBe(0);
975
+ expect(shouldAskForApprove).toBe(false);
976
+ expect(tablesToRemove!.length).toBe(0);
977
+ expect(tablesToTruncate!.length).toBe(0);
978
+ });
979
+
980
+ test('drop not null with two indexes', async (t) => {
981
+ const turso = createClient({
982
+ url: ':memory:',
983
+ });
984
+
985
+ const schema1 = {
986
+ users: sqliteTable('users', {
987
+ id: int('id').primaryKey({ autoIncrement: true }),
988
+ name: text('name').notNull(),
989
+ age: int('age').notNull(),
990
+ }, (table) => ({
991
+ someUniqeIndex: uniqueIndex('users_name_unique').on(table.name),
992
+ someIndex: index('users_age_index').on(table.age),
993
+ })),
994
+ };
995
+
996
+ const schema2 = {
997
+ users: sqliteTable('users', {
998
+ id: int('id').primaryKey({ autoIncrement: true }),
999
+ name: text('name'),
1000
+ age: int('age').notNull(),
1001
+ }, (table) => ({
1002
+ someUniqeIndex: uniqueIndex('users_name_unique').on(table.name),
1003
+ someIndex: index('users_age_index').on(table.age),
1004
+ })),
1005
+ };
1006
+
1007
+ const {
1008
+ statements,
1009
+ sqlStatements,
1010
+ columnsToRemove,
1011
+ infoToPrint,
1012
+ shouldAskForApprove,
1013
+ tablesToRemove,
1014
+ tablesToTruncate,
1015
+ } = await diffTestSchemasPushLibSQL(
1016
+ turso,
1017
+ schema1,
1018
+ schema2,
1019
+ [],
1020
+ );
1021
+
1022
+ expect(statements.length).toBe(1);
1023
+ expect(statements[0]).toStrictEqual({
1024
+ type: 'alter_table_alter_column_drop_notnull',
1025
+ tableName: 'users',
1026
+ columnName: 'name',
1027
+ schema: '',
1028
+ newDataType: 'text',
1029
+ columnDefault: undefined,
1030
+ columnOnUpdate: undefined,
1031
+ columnNotNull: false,
1032
+ columnAutoIncrement: false,
1033
+ columnPk: false,
1034
+ });
1035
+
1036
+ expect(sqlStatements.length).toBe(5);
1037
+ expect(sqlStatements[0]).toBe(
1038
+ `DROP INDEX "users_name_unique";`,
1039
+ );
1040
+ expect(sqlStatements[1]).toBe(
1041
+ `DROP INDEX "users_age_index";`,
1042
+ );
1043
+ expect(sqlStatements[2]).toBe(
1044
+ `ALTER TABLE \`users\` ALTER COLUMN "name" TO "name" text;`,
1045
+ );
1046
+ expect(sqlStatements[3]).toBe(
1047
+ `CREATE UNIQUE INDEX \`users_name_unique\` ON \`users\` (\`name\`);`,
1048
+ );
1049
+ expect(sqlStatements[4]).toBe(
1050
+ `CREATE INDEX \`users_age_index\` ON \`users\` (\`age\`);`,
1051
+ );
1052
+ expect(columnsToRemove!.length).toBe(0), expect(infoToPrint!.length).toBe(0);
1053
+ expect(shouldAskForApprove).toBe(false);
1054
+ expect(tablesToRemove!.length).toBe(0);
1055
+ expect(tablesToTruncate!.length).toBe(0);
1056
+ });
1057
+
1058
+ test('add check constraint to table', async (t) => {
1059
+ const turso = createClient({
1060
+ url: ':memory:',
1061
+ });
1062
+
1063
+ const schema1 = {
1064
+ users: sqliteTable('users', {
1065
+ id: int('id').primaryKey({ autoIncrement: false }),
1066
+ name: text('name'),
1067
+ age: integer('age'),
1068
+ }),
1069
+ };
1070
+
1071
+ const schema2 = {
1072
+ users: sqliteTable('users', {
1073
+ id: int('id').primaryKey({ autoIncrement: false }),
1074
+ name: text('name'),
1075
+ age: integer('age'),
1076
+ }, (table) => ({
1077
+ someCheck: check('some_check', sql`${table.age} > 21`),
1078
+ })),
1079
+ };
1080
+
1081
+ const {
1082
+ statements,
1083
+ sqlStatements,
1084
+ columnsToRemove,
1085
+ infoToPrint,
1086
+ shouldAskForApprove,
1087
+ tablesToRemove,
1088
+ tablesToTruncate,
1089
+ } = await diffTestSchemasPushLibSQL(
1090
+ turso,
1091
+ schema1,
1092
+ schema2,
1093
+ [],
1094
+ );
1095
+
1096
+ expect(statements!.length).toBe(1);
1097
+ expect(statements![0]).toStrictEqual({
1098
+ columns: [
1099
+ {
1100
+ autoincrement: false,
1101
+ name: 'id',
1102
+ notNull: true,
1103
+ generated: undefined,
1104
+ primaryKey: true,
1105
+ type: 'integer',
1106
+ },
1107
+ {
1108
+ autoincrement: false,
1109
+ name: 'name',
1110
+ notNull: false,
1111
+ generated: undefined,
1112
+ primaryKey: false,
1113
+ type: 'text',
1114
+ },
1115
+ {
1116
+ autoincrement: false,
1117
+ name: 'age',
1118
+ notNull: false,
1119
+ generated: undefined,
1120
+ primaryKey: false,
1121
+ type: 'integer',
1122
+ },
1123
+ ],
1124
+ compositePKs: [],
1125
+ referenceData: [],
1126
+ tableName: 'users',
1127
+ type: 'recreate_table',
1128
+ uniqueConstraints: [],
1129
+ checkConstraints: ['some_check;"users"."age" > 21'],
1130
+ });
1131
+
1132
+ expect(sqlStatements!.length).toBe(4);
1133
+ expect(sqlStatements![0]).toBe(`CREATE TABLE \`__new_users\` (
1134
+ \t\`id\` integer PRIMARY KEY NOT NULL,
1135
+ \t\`name\` text,
1136
+ \t\`age\` integer,
1137
+ \tCONSTRAINT "some_check" CHECK("__new_users"."age" > 21)
1138
+ );\n`);
1139
+ expect(sqlStatements[1]).toBe(
1140
+ 'INSERT INTO `__new_users`("id", "name", "age") SELECT "id", "name", "age" FROM `users`;',
1141
+ );
1142
+ expect(sqlStatements![2]).toBe(`DROP TABLE \`users\`;`);
1143
+ expect(sqlStatements![3]).toBe(
1144
+ `ALTER TABLE \`__new_users\` RENAME TO \`users\`;`,
1145
+ );
1146
+
1147
+ expect(columnsToRemove!.length).toBe(0);
1148
+ expect(infoToPrint!.length).toBe(0);
1149
+ expect(shouldAskForApprove).toBe(false);
1150
+ expect(tablesToRemove!.length).toBe(0);
1151
+ expect(tablesToTruncate!.length).toBe(0);
1152
+ });
1153
+
1154
+ test('drop check constraint', async (t) => {
1155
+ const turso = createClient({
1156
+ url: ':memory:',
1157
+ });
1158
+
1159
+ const schema1 = {
1160
+ users: sqliteTable('users', {
1161
+ id: int('id').primaryKey({ autoIncrement: false }),
1162
+ name: text('name'),
1163
+ age: integer('age'),
1164
+ }, (table) => ({
1165
+ someCheck: check('some_check', sql`${table.age} > 21`),
1166
+ })),
1167
+ };
1168
+
1169
+ const schema2 = {
1170
+ users: sqliteTable('users', {
1171
+ id: int('id').primaryKey({ autoIncrement: false }),
1172
+ name: text('name'),
1173
+ age: integer('age'),
1174
+ }),
1175
+ };
1176
+
1177
+ const {
1178
+ statements,
1179
+ sqlStatements,
1180
+ columnsToRemove,
1181
+ infoToPrint,
1182
+ shouldAskForApprove,
1183
+ tablesToRemove,
1184
+ tablesToTruncate,
1185
+ } = await diffTestSchemasPushLibSQL(
1186
+ turso,
1187
+ schema1,
1188
+ schema2,
1189
+ [],
1190
+ );
1191
+
1192
+ expect(statements!.length).toBe(1);
1193
+ expect(statements![0]).toStrictEqual({
1194
+ columns: [
1195
+ {
1196
+ autoincrement: false,
1197
+ name: 'id',
1198
+ notNull: true,
1199
+ generated: undefined,
1200
+ primaryKey: true,
1201
+ type: 'integer',
1202
+ },
1203
+ {
1204
+ autoincrement: false,
1205
+ name: 'name',
1206
+ notNull: false,
1207
+ generated: undefined,
1208
+ primaryKey: false,
1209
+ type: 'text',
1210
+ },
1211
+ {
1212
+ autoincrement: false,
1213
+ name: 'age',
1214
+ notNull: false,
1215
+ generated: undefined,
1216
+ primaryKey: false,
1217
+ type: 'integer',
1218
+ },
1219
+ ],
1220
+ compositePKs: [],
1221
+ referenceData: [],
1222
+ tableName: 'users',
1223
+ type: 'recreate_table',
1224
+ uniqueConstraints: [],
1225
+ checkConstraints: [],
1226
+ });
1227
+
1228
+ expect(sqlStatements!.length).toBe(4);
1229
+ expect(sqlStatements![0]).toBe(`CREATE TABLE \`__new_users\` (
1230
+ \t\`id\` integer PRIMARY KEY NOT NULL,
1231
+ \t\`name\` text,
1232
+ \t\`age\` integer
1233
+ );\n`);
1234
+ expect(sqlStatements[1]).toBe(
1235
+ 'INSERT INTO `__new_users`("id", "name", "age") SELECT "id", "name", "age" FROM `users`;',
1236
+ );
1237
+ expect(sqlStatements![2]).toBe(`DROP TABLE \`users\`;`);
1238
+ expect(sqlStatements![3]).toBe(
1239
+ `ALTER TABLE \`__new_users\` RENAME TO \`users\`;`,
1240
+ );
1241
+
1242
+ expect(columnsToRemove!.length).toBe(0);
1243
+ expect(infoToPrint!.length).toBe(0);
1244
+ expect(shouldAskForApprove).toBe(false);
1245
+ expect(tablesToRemove!.length).toBe(0);
1246
+ expect(tablesToTruncate!.length).toBe(0);
1247
+ });
1248
+
1249
+ test('db has checks. Push with same names', async () => {
1250
+ const turso = createClient({
1251
+ url: ':memory:',
1252
+ });
1253
+
1254
+ const schema1 = {
1255
+ users: sqliteTable('users', {
1256
+ id: int('id').primaryKey({ autoIncrement: false }),
1257
+ name: text('name'),
1258
+ age: integer('age'),
1259
+ }, (table) => ({
1260
+ someCheck: check('some_check', sql`${table.age} > 21`),
1261
+ })),
1262
+ };
1263
+
1264
+ const schema2 = {
1265
+ users: sqliteTable('users', {
1266
+ id: int('id').primaryKey({ autoIncrement: false }),
1267
+ name: text('name'),
1268
+ age: integer('age'),
1269
+ }, (table) => ({
1270
+ someCheck: check('some_check', sql`some new value`),
1271
+ })),
1272
+ };
1273
+
1274
+ const {
1275
+ statements,
1276
+ sqlStatements,
1277
+ columnsToRemove,
1278
+ infoToPrint,
1279
+ shouldAskForApprove,
1280
+ tablesToRemove,
1281
+ tablesToTruncate,
1282
+ } = await diffTestSchemasPushLibSQL(
1283
+ turso,
1284
+ schema1,
1285
+ schema2,
1286
+ [],
1287
+ false,
1288
+ [],
1289
+ );
1290
+ expect(statements).toStrictEqual([]);
1291
+ expect(sqlStatements).toStrictEqual([]);
1292
+ expect(columnsToRemove!.length).toBe(0);
1293
+ expect(infoToPrint!.length).toBe(0);
1294
+ expect(shouldAskForApprove).toBe(false);
1295
+ expect(tablesToRemove!.length).toBe(0);
1296
+ expect(tablesToTruncate!.length).toBe(0);
1297
+ });
1298
+
1299
+ test('create view', async () => {
1300
+ const turso = createClient({
1301
+ url: ':memory:',
1302
+ });
1303
+
1304
+ const table = sqliteTable('test', {
1305
+ id: int('id').primaryKey(),
1306
+ });
1307
+
1308
+ const schema1 = {
1309
+ test: table,
1310
+ };
1311
+
1312
+ const schema2 = {
1313
+ test: table,
1314
+ view: sqliteView('view').as((qb) => qb.select().from(table)),
1315
+ };
1316
+
1317
+ const { statements, sqlStatements } = await diffTestSchemasPushLibSQL(
1318
+ turso,
1319
+ schema1,
1320
+ schema2,
1321
+ [],
1322
+ );
1323
+
1324
+ expect(statements).toStrictEqual([
1325
+ {
1326
+ definition: 'select "id" from "test"',
1327
+ name: 'view',
1328
+ type: 'sqlite_create_view',
1329
+ },
1330
+ ]);
1331
+ expect(sqlStatements).toStrictEqual([
1332
+ `CREATE VIEW \`view\` AS select "id" from "test";`,
1333
+ ]);
1334
+ });
1335
+
1336
+ test('drop view', async () => {
1337
+ const turso = createClient({
1338
+ url: ':memory:',
1339
+ });
1340
+
1341
+ const table = sqliteTable('test', {
1342
+ id: int('id').primaryKey(),
1343
+ });
1344
+
1345
+ const schema1 = {
1346
+ test: table,
1347
+ view: sqliteView('view').as((qb) => qb.select().from(table)),
1348
+ };
1349
+
1350
+ const schema2 = {
1351
+ test: table,
1352
+ };
1353
+
1354
+ const { statements, sqlStatements } = await diffTestSchemasPushLibSQL(
1355
+ turso,
1356
+ schema1,
1357
+ schema2,
1358
+ [],
1359
+ );
1360
+
1361
+ expect(statements).toStrictEqual([
1362
+ {
1363
+ name: 'view',
1364
+ type: 'drop_view',
1365
+ },
1366
+ ]);
1367
+ expect(sqlStatements).toStrictEqual([
1368
+ 'DROP VIEW \`view\`;',
1369
+ ]);
1370
+ });
1371
+
1372
+ test('alter view ".as"', async () => {
1373
+ const turso = createClient({
1374
+ url: ':memory:',
1375
+ });
1376
+
1377
+ const table = sqliteTable('test', {
1378
+ id: int('id').primaryKey(),
1379
+ });
1380
+
1381
+ const schema1 = {
1382
+ test: table,
1383
+ view: sqliteView('view').as((qb) => qb.select().from(table).where(sql`${table.id} = 1`)),
1384
+ };
1385
+
1386
+ const schema2 = {
1387
+ test: table,
1388
+ view: sqliteView('view').as((qb) => qb.select().from(table)),
1389
+ };
1390
+
1391
+ const { statements, sqlStatements } = await diffTestSchemasPushLibSQL(
1392
+ turso,
1393
+ schema1,
1394
+ schema2,
1395
+ [],
1396
+ );
1397
+
1398
+ expect(statements.length).toBe(0);
1399
+ expect(sqlStatements.length).toBe(0);
1400
+ });