@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,788 @@
1
+ import 'dotenv/config';
2
+ import Docker from 'dockerode';
3
+ import { SQL, sql } from 'drizzle-orm';
4
+ import {
5
+ bigint,
6
+ binary,
7
+ char,
8
+ date,
9
+ datetime,
10
+ decimal,
11
+ double,
12
+ float,
13
+ int,
14
+ json,
15
+ mediumint,
16
+ mysqlEnum,
17
+ mysqlTable,
18
+ primaryKey,
19
+ serial,
20
+ smallint,
21
+ text,
22
+ time,
23
+ timestamp,
24
+ tinyint,
25
+ varbinary,
26
+ varchar,
27
+ year,
28
+ } from 'drizzle-orm/mysql-core';
29
+ import getPort from 'get-port';
30
+ import { Connection, createConnection } from 'mysql2/promise';
31
+ import { diffTestSchemasMysql, diffTestSchemasPushMysql } from 'tests/schemaDiffer';
32
+ import { v4 as uuid } from 'uuid';
33
+ import { expect, test } from 'vitest';
34
+ import { DialectSuite, run } from './common';
35
+
36
+ async function createDockerDB(context: any): Promise<string> {
37
+ const docker = new Docker();
38
+ const port = await getPort({ port: 3306 });
39
+ const image = 'mysql:8';
40
+
41
+ const pullStream = await docker.pull(image);
42
+ await new Promise((resolve, reject) =>
43
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
44
+ docker.modem.followProgress(pullStream, (err) => err ? reject(err) : resolve(err))
45
+ );
46
+
47
+ context.mysqlContainer = await docker.createContainer({
48
+ Image: image,
49
+ Env: ['MYSQL_ROOT_PASSWORD=mysql', 'MYSQL_DATABASE=drizzle'],
50
+ name: `drizzle-integration-tests-${uuid()}`,
51
+ HostConfig: {
52
+ AutoRemove: true,
53
+ PortBindings: {
54
+ '3306/tcp': [{ HostPort: `${port}` }],
55
+ },
56
+ },
57
+ });
58
+
59
+ await context.mysqlContainer.start();
60
+
61
+ return `mysql://root:mysql@127.0.0.1:${port}/drizzle`;
62
+ }
63
+
64
+ const mysqlSuite: DialectSuite = {
65
+ allTypes: async function(context: any): Promise<void> {
66
+ const schema1 = {
67
+ allBigInts: mysqlTable('all_big_ints', {
68
+ simple: bigint('simple', { mode: 'number' }),
69
+ columnNotNull: bigint('column_not_null', { mode: 'number' }).notNull(),
70
+ columnDefault: bigint('column_default', { mode: 'number' }).default(12),
71
+ columnDefaultSql: bigint('column_default_sql', {
72
+ mode: 'number',
73
+ }).default(12),
74
+ }),
75
+ allBools: mysqlTable('all_bools', {
76
+ simple: tinyint('simple'),
77
+ columnNotNull: tinyint('column_not_null').notNull(),
78
+ columnDefault: tinyint('column_default').default(1),
79
+ }),
80
+ allChars: mysqlTable('all_chars', {
81
+ simple: char('simple', { length: 1 }),
82
+ columnNotNull: char('column_not_null', { length: 45 }).notNull(),
83
+ // columnDefault: char("column_default", { length: 1 }).default("h"),
84
+ columnDefaultSql: char('column_default_sql', { length: 1 }).default(
85
+ 'h',
86
+ ),
87
+ }),
88
+ allDateTimes: mysqlTable('all_date_times', {
89
+ simple: datetime('simple', { mode: 'string', fsp: 1 }),
90
+ columnNotNull: datetime('column_not_null', {
91
+ mode: 'string',
92
+ }).notNull(),
93
+ columnDefault: datetime('column_default', { mode: 'string' }).default(
94
+ '2023-03-01 14:05:29',
95
+ ),
96
+ }),
97
+ allDates: mysqlTable('all_dates', {
98
+ simple: date('simple', { mode: 'string' }),
99
+ column_not_null: date('column_not_null', { mode: 'string' }).notNull(),
100
+ column_default: date('column_default', { mode: 'string' }).default(
101
+ '2023-03-01',
102
+ ),
103
+ }),
104
+ allDecimals: mysqlTable('all_decimals', {
105
+ simple: decimal('simple', { precision: 1, scale: 0 }),
106
+ columnNotNull: decimal('column_not_null', {
107
+ precision: 45,
108
+ scale: 3,
109
+ }).notNull(),
110
+ columnDefault: decimal('column_default', {
111
+ precision: 10,
112
+ scale: 0,
113
+ }).default('100'),
114
+ columnDefaultSql: decimal('column_default_sql', {
115
+ precision: 10,
116
+ scale: 0,
117
+ }).default('101'),
118
+ }),
119
+
120
+ allDoubles: mysqlTable('all_doubles', {
121
+ simple: double('simple'),
122
+ columnNotNull: double('column_not_null').notNull(),
123
+ columnDefault: double('column_default').default(100),
124
+ columnDefaultSql: double('column_default_sql').default(101),
125
+ }),
126
+
127
+ allEnums: mysqlTable('all_enums', {
128
+ simple: mysqlEnum('simple', ['hi', 'hello']),
129
+ }),
130
+
131
+ allEnums1: mysqlTable('all_enums1', {
132
+ simple: mysqlEnum('simple', ['hi', 'hello']).default('hi'),
133
+ }),
134
+
135
+ allFloats: mysqlTable('all_floats', {
136
+ columnNotNull: float('column_not_null').notNull(),
137
+ columnDefault: float('column_default').default(100),
138
+ columnDefaultSql: float('column_default_sql').default(101),
139
+ }),
140
+
141
+ allInts: mysqlTable('all_ints', {
142
+ simple: int('simple'),
143
+ columnNotNull: int('column_not_null').notNull(),
144
+ columnDefault: int('column_default').default(100),
145
+ columnDefaultSql: int('column_default_sql').default(101),
146
+ }),
147
+
148
+ allIntsRef: mysqlTable('all_ints_ref', {
149
+ simple: int('simple'),
150
+ columnNotNull: int('column_not_null').notNull(),
151
+ columnDefault: int('column_default').default(100),
152
+ columnDefaultSql: int('column_default_sql').default(101),
153
+ }),
154
+
155
+ allJsons: mysqlTable('all_jsons', {
156
+ columnDefaultObject: json('column_default_object')
157
+ .default({ hello: 'world world' })
158
+ .notNull(),
159
+ columnDefaultArray: json('column_default_array').default({
160
+ hello: { 'world world': ['foo', 'bar'] },
161
+ foo: 'bar',
162
+ fe: 23,
163
+ }),
164
+ column: json('column'),
165
+ }),
166
+
167
+ allMInts: mysqlTable('all_m_ints', {
168
+ simple: mediumint('simple'),
169
+ columnNotNull: mediumint('column_not_null').notNull(),
170
+ columnDefault: mediumint('column_default').default(100),
171
+ columnDefaultSql: mediumint('column_default_sql').default(101),
172
+ }),
173
+
174
+ allReals: mysqlTable('all_reals', {
175
+ simple: double('simple', { precision: 5, scale: 2 }),
176
+ columnNotNull: double('column_not_null').notNull(),
177
+ columnDefault: double('column_default').default(100),
178
+ columnDefaultSql: double('column_default_sql').default(101),
179
+ }),
180
+
181
+ allSInts: mysqlTable('all_s_ints', {
182
+ simple: smallint('simple'),
183
+ columnNotNull: smallint('column_not_null').notNull(),
184
+ columnDefault: smallint('column_default').default(100),
185
+ columnDefaultSql: smallint('column_default_sql').default(101),
186
+ }),
187
+
188
+ allSmallSerials: mysqlTable('all_small_serials', {
189
+ columnAll: serial('column_all').primaryKey().notNull(),
190
+ }),
191
+
192
+ allTInts: mysqlTable('all_t_ints', {
193
+ simple: tinyint('simple'),
194
+ columnNotNull: tinyint('column_not_null').notNull(),
195
+ columnDefault: tinyint('column_default').default(10),
196
+ columnDefaultSql: tinyint('column_default_sql').default(11),
197
+ }),
198
+
199
+ allTexts: mysqlTable('all_texts', {
200
+ simple: text('simple'),
201
+ columnNotNull: text('column_not_null').notNull(),
202
+ columnDefault: text('column_default').default('hello'),
203
+ columnDefaultSql: text('column_default_sql').default('hello'),
204
+ }),
205
+
206
+ allTimes: mysqlTable('all_times', {
207
+ simple: time('simple', { fsp: 1 }),
208
+ columnNotNull: time('column_not_null').notNull(),
209
+ columnDefault: time('column_default').default('22:12:12'),
210
+ }),
211
+
212
+ allTimestamps: mysqlTable('all_timestamps', {
213
+ columnDateNow: timestamp('column_date_now', {
214
+ fsp: 1,
215
+ mode: 'string',
216
+ }).default(sql`(now())`),
217
+ columnAll: timestamp('column_all', { mode: 'string' })
218
+ .default('2023-03-01 14:05:29')
219
+ .notNull(),
220
+ column: timestamp('column', { mode: 'string' }).default(
221
+ '2023-02-28 16:18:31',
222
+ ),
223
+ }),
224
+
225
+ allVarChars: mysqlTable('all_var_chars', {
226
+ simple: varchar('simple', { length: 100 }),
227
+ columnNotNull: varchar('column_not_null', { length: 45 }).notNull(),
228
+ columnDefault: varchar('column_default', { length: 100 }).default(
229
+ 'hello',
230
+ ),
231
+ columnDefaultSql: varchar('column_default_sql', {
232
+ length: 100,
233
+ }).default('hello'),
234
+ }),
235
+
236
+ allVarbinaries: mysqlTable('all_varbinaries', {
237
+ simple: varbinary('simple', { length: 100 }),
238
+ columnNotNull: varbinary('column_not_null', { length: 100 }).notNull(),
239
+ columnDefault: varbinary('column_default', { length: 12 }).default(
240
+ sql`(uuid_to_bin(uuid()))`,
241
+ ),
242
+ }),
243
+
244
+ allYears: mysqlTable('all_years', {
245
+ simple: year('simple'),
246
+ columnNotNull: year('column_not_null').notNull(),
247
+ columnDefault: year('column_default').default(2022),
248
+ }),
249
+
250
+ binafry: mysqlTable('binary', {
251
+ simple: binary('simple', { length: 1 }),
252
+ columnNotNull: binary('column_not_null', { length: 1 }).notNull(),
253
+ columnDefault: binary('column_default', { length: 12 }).default(
254
+ sql`(uuid_to_bin(uuid()))`,
255
+ ),
256
+ }),
257
+ };
258
+
259
+ const { statements } = await diffTestSchemasPushMysql(
260
+ context.client as Connection,
261
+ schema1,
262
+ schema1,
263
+ [],
264
+ 'drizzle',
265
+ false,
266
+ );
267
+ expect(statements.length).toBe(2);
268
+ expect(statements).toEqual([
269
+ {
270
+ type: 'delete_unique_constraint',
271
+ tableName: 'all_small_serials',
272
+ data: 'column_all;column_all',
273
+ schema: '',
274
+ },
275
+ {
276
+ type: 'delete_unique_constraint',
277
+ tableName: 'all_small_serials',
278
+ data: 'column_all;column_all',
279
+ schema: '',
280
+ },
281
+ ]);
282
+
283
+ const { sqlStatements: dropStatements } = await diffTestSchemasMysql(
284
+ schema1,
285
+ {},
286
+ [],
287
+ false,
288
+ );
289
+
290
+ for (const st of dropStatements) {
291
+ await context.client.query(st);
292
+ }
293
+ },
294
+ addBasicIndexes: function(context?: any): Promise<void> {
295
+ return {} as any;
296
+ },
297
+ changeIndexFields: function(context?: any): Promise<void> {
298
+ return {} as any;
299
+ },
300
+ dropIndex: function(context?: any): Promise<void> {
301
+ return {} as any;
302
+ },
303
+ indexesToBeNotTriggered: function(context?: any): Promise<void> {
304
+ return {} as any;
305
+ },
306
+ indexesTestCase1: function(context?: any): Promise<void> {
307
+ return {} as any;
308
+ },
309
+ async case1() {
310
+ // TODO: implement if needed
311
+ expect(true).toBe(true);
312
+ },
313
+ addNotNull: function(context?: any): Promise<void> {
314
+ return {} as any;
315
+ },
316
+ addNotNullWithDataNoRollback: function(context?: any): Promise<void> {
317
+ return {} as any;
318
+ },
319
+ addBasicSequences: function(context?: any): Promise<void> {
320
+ return {} as any;
321
+ },
322
+ addGeneratedColumn: async function(context: any): Promise<void> {
323
+ const schema1 = {
324
+ users: mysqlTable('users', {
325
+ id: int('id'),
326
+ id2: int('id2'),
327
+ name: text('name'),
328
+ }),
329
+ };
330
+ const schema2 = {
331
+ users: mysqlTable('users', {
332
+ id: int('id'),
333
+ id2: int('id2'),
334
+ name: text('name'),
335
+ generatedName: text('gen_name').generatedAlwaysAs(
336
+ (): SQL => sql`${schema2.users.name} || 'hello'`,
337
+ { mode: 'stored' },
338
+ ),
339
+ generatedName1: text('gen_name1').generatedAlwaysAs(
340
+ (): SQL => sql`${schema2.users.name} || 'hello'`,
341
+ { mode: 'virtual' },
342
+ ),
343
+ }),
344
+ };
345
+
346
+ const { statements, sqlStatements } = await diffTestSchemasPushMysql(
347
+ context.client as Connection,
348
+ schema1,
349
+ schema2,
350
+ [],
351
+ 'drizzle',
352
+ false,
353
+ );
354
+
355
+ expect(statements).toStrictEqual([
356
+ {
357
+ column: {
358
+ autoincrement: false,
359
+ generated: {
360
+ as: "`users`.`name` || 'hello'",
361
+ type: 'stored',
362
+ },
363
+ name: 'gen_name',
364
+ notNull: false,
365
+ primaryKey: false,
366
+ type: 'text',
367
+ },
368
+ schema: '',
369
+ tableName: 'users',
370
+ type: 'alter_table_add_column',
371
+ },
372
+ {
373
+ column: {
374
+ autoincrement: false,
375
+ generated: {
376
+ as: "`users`.`name` || 'hello'",
377
+ type: 'virtual',
378
+ },
379
+ name: 'gen_name1',
380
+ notNull: false,
381
+ primaryKey: false,
382
+ type: 'text',
383
+ },
384
+ schema: '',
385
+ tableName: 'users',
386
+ type: 'alter_table_add_column',
387
+ },
388
+ ]);
389
+ expect(sqlStatements).toStrictEqual([
390
+ "ALTER TABLE `users` ADD `gen_name` text GENERATED ALWAYS AS (`users`.`name` || 'hello') STORED;",
391
+ "ALTER TABLE `users` ADD `gen_name1` text GENERATED ALWAYS AS (`users`.`name` || 'hello') VIRTUAL;",
392
+ ]);
393
+
394
+ for (const st of sqlStatements) {
395
+ await context.client.query(st);
396
+ }
397
+
398
+ const { sqlStatements: dropStatements } = await diffTestSchemasMysql(
399
+ schema2,
400
+ {},
401
+ [],
402
+ false,
403
+ );
404
+
405
+ for (const st of dropStatements) {
406
+ await context.client.query(st);
407
+ }
408
+ },
409
+ addGeneratedToColumn: async function(context: any): Promise<void> {
410
+ const schema1 = {
411
+ users: mysqlTable('users', {
412
+ id: int('id'),
413
+ id2: int('id2'),
414
+ name: text('name'),
415
+ generatedName: text('gen_name'),
416
+ generatedName1: text('gen_name1'),
417
+ }),
418
+ };
419
+ const schema2 = {
420
+ users: mysqlTable('users', {
421
+ id: int('id'),
422
+ id2: int('id2'),
423
+ name: text('name'),
424
+ generatedName: text('gen_name').generatedAlwaysAs(
425
+ (): SQL => sql`${schema2.users.name} || 'hello'`,
426
+ { mode: 'stored' },
427
+ ),
428
+ generatedName1: text('gen_name1').generatedAlwaysAs(
429
+ (): SQL => sql`${schema2.users.name} || 'hello'`,
430
+ { mode: 'virtual' },
431
+ ),
432
+ }),
433
+ };
434
+
435
+ const { statements, sqlStatements } = await diffTestSchemasPushMysql(
436
+ context.client as Connection,
437
+ schema1,
438
+ schema2,
439
+ [],
440
+ 'drizzle',
441
+ false,
442
+ );
443
+
444
+ expect(statements).toStrictEqual([
445
+ {
446
+ columnAutoIncrement: false,
447
+ columnDefault: undefined,
448
+ columnGenerated: {
449
+ as: "`users`.`name` || 'hello'",
450
+ type: 'stored',
451
+ },
452
+ columnName: 'gen_name',
453
+ columnNotNull: false,
454
+ columnOnUpdate: undefined,
455
+ columnPk: false,
456
+ newDataType: 'text',
457
+ schema: '',
458
+ tableName: 'users',
459
+ type: 'alter_table_alter_column_set_generated',
460
+ },
461
+ {
462
+ columnAutoIncrement: false,
463
+ columnDefault: undefined,
464
+ columnGenerated: {
465
+ as: "`users`.`name` || 'hello'",
466
+ type: 'virtual',
467
+ },
468
+ columnName: 'gen_name1',
469
+ columnNotNull: false,
470
+ columnOnUpdate: undefined,
471
+ columnPk: false,
472
+ newDataType: 'text',
473
+ schema: '',
474
+ tableName: 'users',
475
+ type: 'alter_table_alter_column_set_generated',
476
+ },
477
+ ]);
478
+ expect(sqlStatements).toStrictEqual([
479
+ "ALTER TABLE `users` MODIFY COLUMN `gen_name` text GENERATED ALWAYS AS (`users`.`name` || 'hello') STORED;",
480
+ 'ALTER TABLE `users` DROP COLUMN `gen_name1`;',
481
+ "ALTER TABLE `users` ADD `gen_name1` text GENERATED ALWAYS AS (`users`.`name` || 'hello') VIRTUAL;",
482
+ ]);
483
+
484
+ for (const st of sqlStatements) {
485
+ await context.client.query(st);
486
+ }
487
+
488
+ const { sqlStatements: dropStatements } = await diffTestSchemasMysql(
489
+ schema2,
490
+ {},
491
+ [],
492
+ false,
493
+ );
494
+
495
+ for (const st of dropStatements) {
496
+ await context.client.query(st);
497
+ }
498
+ },
499
+ dropGeneratedConstraint: async function(context: any): Promise<void> {
500
+ const schema1 = {
501
+ users: mysqlTable('users', {
502
+ id: int('id'),
503
+ id2: int('id2'),
504
+ name: text('name'),
505
+ generatedName: text('gen_name').generatedAlwaysAs(
506
+ (): SQL => sql`${schema2.users.name}`,
507
+ { mode: 'stored' },
508
+ ),
509
+ generatedName1: text('gen_name1').generatedAlwaysAs(
510
+ (): SQL => sql`${schema2.users.name}`,
511
+ { mode: 'virtual' },
512
+ ),
513
+ }),
514
+ };
515
+ const schema2 = {
516
+ users: mysqlTable('users', {
517
+ id: int('id'),
518
+ id2: int('id2'),
519
+ name: text('name'),
520
+ generatedName: text('gen_name'),
521
+ generatedName1: text('gen_name1'),
522
+ }),
523
+ };
524
+
525
+ const { statements, sqlStatements } = await diffTestSchemasPushMysql(
526
+ context.client as Connection,
527
+ schema1,
528
+ schema2,
529
+ [],
530
+ 'drizzle',
531
+ false,
532
+ );
533
+
534
+ expect(statements).toStrictEqual([
535
+ {
536
+ columnAutoIncrement: false,
537
+ columnDefault: undefined,
538
+ columnGenerated: undefined,
539
+ columnName: 'gen_name',
540
+ columnNotNull: false,
541
+ columnOnUpdate: undefined,
542
+ columnPk: false,
543
+ newDataType: 'text',
544
+ oldColumn: {
545
+ autoincrement: false,
546
+ default: undefined,
547
+ generated: {
548
+ as: '`name`',
549
+ type: 'stored',
550
+ },
551
+ name: 'gen_name',
552
+ notNull: false,
553
+ onUpdate: undefined,
554
+ primaryKey: false,
555
+ type: 'text',
556
+ },
557
+ schema: '',
558
+ tableName: 'users',
559
+ type: 'alter_table_alter_column_drop_generated',
560
+ },
561
+ {
562
+ columnAutoIncrement: false,
563
+ columnDefault: undefined,
564
+ columnGenerated: undefined,
565
+ columnName: 'gen_name1',
566
+ columnNotNull: false,
567
+ columnOnUpdate: undefined,
568
+ columnPk: false,
569
+ newDataType: 'text',
570
+ oldColumn: {
571
+ autoincrement: false,
572
+ default: undefined,
573
+ generated: {
574
+ as: '`name`',
575
+ type: 'virtual',
576
+ },
577
+ name: 'gen_name1',
578
+ notNull: false,
579
+ onUpdate: undefined,
580
+ primaryKey: false,
581
+ type: 'text',
582
+ },
583
+ schema: '',
584
+ tableName: 'users',
585
+ type: 'alter_table_alter_column_drop_generated',
586
+ },
587
+ ]);
588
+ expect(sqlStatements).toStrictEqual([
589
+ 'ALTER TABLE `users` MODIFY COLUMN `gen_name` text;',
590
+ 'ALTER TABLE `users` DROP COLUMN `gen_name1`;',
591
+ 'ALTER TABLE `users` ADD `gen_name1` text;',
592
+ ]);
593
+
594
+ for (const st of sqlStatements) {
595
+ await context.client.query(st);
596
+ }
597
+
598
+ const { sqlStatements: dropStatements } = await diffTestSchemasMysql(
599
+ schema2,
600
+ {},
601
+ [],
602
+ false,
603
+ );
604
+
605
+ for (const st of dropStatements) {
606
+ await context.client.query(st);
607
+ }
608
+ },
609
+ alterGeneratedConstraint: async function(context: any): Promise<void> {
610
+ const schema1 = {
611
+ users: mysqlTable('users', {
612
+ id: int('id'),
613
+ id2: int('id2'),
614
+ name: text('name'),
615
+ generatedName: text('gen_name').generatedAlwaysAs(
616
+ (): SQL => sql`${schema2.users.name}`,
617
+ { mode: 'stored' },
618
+ ),
619
+ generatedName1: text('gen_name1').generatedAlwaysAs(
620
+ (): SQL => sql`${schema2.users.name}`,
621
+ { mode: 'virtual' },
622
+ ),
623
+ }),
624
+ };
625
+ const schema2 = {
626
+ users: mysqlTable('users', {
627
+ id: int('id'),
628
+ id2: int('id2'),
629
+ name: text('name'),
630
+ generatedName: text('gen_name').generatedAlwaysAs(
631
+ (): SQL => sql`${schema2.users.name} || 'hello'`,
632
+ { mode: 'stored' },
633
+ ),
634
+ generatedName1: text('gen_name1').generatedAlwaysAs(
635
+ (): SQL => sql`${schema2.users.name} || 'hello'`,
636
+ { mode: 'virtual' },
637
+ ),
638
+ }),
639
+ };
640
+
641
+ const { statements, sqlStatements } = await diffTestSchemasPushMysql(
642
+ context.client as Connection,
643
+ schema1,
644
+ schema2,
645
+ [],
646
+ 'drizzle',
647
+ false,
648
+ );
649
+
650
+ expect(statements).toStrictEqual([]);
651
+ expect(sqlStatements).toStrictEqual([]);
652
+
653
+ const { sqlStatements: dropStatements } = await diffTestSchemasMysql(
654
+ schema2,
655
+ {},
656
+ [],
657
+ false,
658
+ );
659
+
660
+ for (const st of dropStatements) {
661
+ await context.client.query(st);
662
+ }
663
+ },
664
+ createTableWithGeneratedConstraint: function(context?: any): Promise<void> {
665
+ return {} as any;
666
+ },
667
+ createCompositePrimaryKey: async function(context: any): Promise<void> {
668
+ const schema1 = {};
669
+
670
+ const schema2 = {
671
+ table: mysqlTable('table', {
672
+ col1: int('col1').notNull(),
673
+ col2: int('col2').notNull(),
674
+ }, (t) => ({
675
+ pk: primaryKey({
676
+ columns: [t.col1, t.col2],
677
+ }),
678
+ })),
679
+ };
680
+
681
+ const { statements, sqlStatements } = await diffTestSchemasPushMysql(
682
+ context.client as Connection,
683
+ schema1,
684
+ schema2,
685
+ [],
686
+ 'drizzle',
687
+ false,
688
+ );
689
+
690
+ expect(statements).toStrictEqual([
691
+ {
692
+ type: 'create_table',
693
+ tableName: 'table',
694
+ schema: undefined,
695
+ internals: {
696
+ indexes: {},
697
+ tables: {},
698
+ },
699
+ compositePKs: ['table_col1_col2_pk;col1,col2'],
700
+ compositePkName: 'table_col1_col2_pk',
701
+ uniqueConstraints: [],
702
+ checkConstraints: [],
703
+ columns: [
704
+ { name: 'col1', type: 'int', primaryKey: false, notNull: true, autoincrement: false },
705
+ { name: 'col2', type: 'int', primaryKey: false, notNull: true, autoincrement: false },
706
+ ],
707
+ },
708
+ ]);
709
+ expect(sqlStatements).toStrictEqual([
710
+ 'CREATE TABLE `table` (\n\t`col1` int NOT NULL,\n\t`col2` int NOT NULL,\n\tCONSTRAINT `table_col1_col2_pk` PRIMARY KEY(`col1`,`col2`)\n);\n',
711
+ ]);
712
+ },
713
+ renameTableWithCompositePrimaryKey: async function(context?: any): Promise<void> {
714
+ const productsCategoriesTable = (tableName: string) => {
715
+ return mysqlTable(tableName, {
716
+ productId: varchar('product_id', { length: 10 }).notNull(),
717
+ categoryId: varchar('category_id', { length: 10 }).notNull(),
718
+ }, (t) => ({
719
+ pk: primaryKey({
720
+ columns: [t.productId, t.categoryId],
721
+ }),
722
+ }));
723
+ };
724
+
725
+ const schema1 = {
726
+ table: productsCategoriesTable('products_categories'),
727
+ };
728
+ const schema2 = {
729
+ test: productsCategoriesTable('products_to_categories'),
730
+ };
731
+
732
+ const { sqlStatements } = await diffTestSchemasPushMysql(
733
+ context.client as Connection,
734
+ schema1,
735
+ schema2,
736
+ ['public.products_categories->public.products_to_categories'],
737
+ 'drizzle',
738
+ false,
739
+ );
740
+
741
+ expect(sqlStatements).toStrictEqual([
742
+ 'RENAME TABLE `products_categories` TO `products_to_categories`;',
743
+ 'ALTER TABLE `products_to_categories` DROP PRIMARY KEY;',
744
+ 'ALTER TABLE `products_to_categories` ADD PRIMARY KEY(`product_id`,`category_id`);',
745
+ ]);
746
+
747
+ await context.client.query(`DROP TABLE \`products_categories\``);
748
+ },
749
+ };
750
+
751
+ run(
752
+ mysqlSuite,
753
+ async (context: any) => {
754
+ const connectionString = process.env.MYSQL_CONNECTION_STRING ?? await createDockerDB(context);
755
+
756
+ const sleep = 1000;
757
+ let timeLeft = 20000;
758
+ let connected = false;
759
+ let lastError: unknown | undefined;
760
+ do {
761
+ try {
762
+ context.client = await createConnection(connectionString);
763
+ await context.client.connect();
764
+ connected = true;
765
+ break;
766
+ } catch (e) {
767
+ lastError = e;
768
+ await new Promise((resolve) => setTimeout(resolve, sleep));
769
+ timeLeft -= sleep;
770
+ }
771
+ } while (timeLeft > 0);
772
+ if (!connected) {
773
+ console.error('Cannot connect to MySQL');
774
+ await context.client?.end().catch(console.error);
775
+ await context.mysqlContainer?.stop().catch(console.error);
776
+ throw lastError;
777
+ }
778
+ },
779
+ async (context: any) => {
780
+ await context.client?.end().catch(console.error);
781
+ await context.mysqlContainer?.stop().catch(console.error);
782
+ },
783
+ async (context: any) => {
784
+ await context.client?.query(`drop database if exists \`drizzle\`;`);
785
+ await context.client?.query(`create database \`drizzle\`;`);
786
+ await context.client?.query(`use \`drizzle\`;`);
787
+ },
788
+ );