@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,1929 @@
1
+ import { sql } from 'drizzle-orm';
2
+ import { integer, pgMaterializedView, pgSchema, pgTable, pgView } from 'drizzle-orm/pg-core';
3
+ import { expect, test } from 'vitest';
4
+ import { diffTestSchemas } from './schemaDiffer';
5
+
6
+ test('create table and view #1', async () => {
7
+ const users = pgTable('users', {
8
+ id: integer('id').primaryKey().notNull(),
9
+ });
10
+ const to = {
11
+ users: users,
12
+ view: pgView('some_view').as((qb) => qb.select().from(users)),
13
+ };
14
+
15
+ const { statements, sqlStatements } = await diffTestSchemas({}, to, []);
16
+
17
+ expect(statements.length).toBe(2);
18
+ expect(statements[0]).toStrictEqual({
19
+ type: 'create_table',
20
+ tableName: 'users',
21
+ schema: '',
22
+ columns: [{
23
+ name: 'id',
24
+ notNull: true,
25
+ primaryKey: true,
26
+ type: 'integer',
27
+ }],
28
+ compositePKs: [],
29
+ uniqueConstraints: [],
30
+ isRLSEnabled: false,
31
+ compositePkName: '',
32
+ checkConstraints: [],
33
+ policies: [],
34
+ });
35
+ expect(statements[1]).toStrictEqual({
36
+ type: 'create_view',
37
+ name: 'some_view',
38
+ definition: `select "id" from "users"`,
39
+ schema: 'public',
40
+ with: undefined,
41
+ materialized: false,
42
+ tablespace: undefined,
43
+ using: undefined,
44
+ withNoData: false,
45
+ });
46
+
47
+ expect(sqlStatements.length).toBe(2);
48
+ expect(sqlStatements[0]).toBe(`CREATE TABLE "users" (
49
+ \t"id" integer PRIMARY KEY NOT NULL
50
+ );\n`);
51
+ expect(sqlStatements[1]).toBe(`CREATE VIEW "public"."some_view" AS (select "id" from "users");`);
52
+ });
53
+
54
+ test('create table and view #2', async () => {
55
+ const users = pgTable('users', {
56
+ id: integer('id').primaryKey().notNull(),
57
+ });
58
+ const to = {
59
+ users: users,
60
+ view: pgView('some_view', { id: integer('id') }).as(sql`SELECT * FROM ${users}`),
61
+ };
62
+
63
+ const { statements, sqlStatements } = await diffTestSchemas({}, to, []);
64
+
65
+ expect(statements.length).toBe(2);
66
+ expect(statements[0]).toStrictEqual({
67
+ type: 'create_table',
68
+ tableName: 'users',
69
+ schema: '',
70
+ columns: [{
71
+ name: 'id',
72
+ notNull: true,
73
+ primaryKey: true,
74
+ type: 'integer',
75
+ }],
76
+ compositePKs: [],
77
+ uniqueConstraints: [],
78
+ isRLSEnabled: false,
79
+ compositePkName: '',
80
+ policies: [],
81
+ checkConstraints: [],
82
+ });
83
+ expect(statements[1]).toStrictEqual({
84
+ type: 'create_view',
85
+ name: 'some_view',
86
+ definition: `SELECT * FROM "users"`,
87
+ schema: 'public',
88
+ with: undefined,
89
+ materialized: false,
90
+ tablespace: undefined,
91
+ using: undefined,
92
+ withNoData: false,
93
+ });
94
+
95
+ expect(sqlStatements.length).toBe(2);
96
+ expect(sqlStatements[0]).toBe(`CREATE TABLE "users" (
97
+ \t"id" integer PRIMARY KEY NOT NULL
98
+ );\n`);
99
+ expect(sqlStatements[1]).toBe(`CREATE VIEW "public"."some_view" AS (SELECT * FROM "users");`);
100
+ });
101
+
102
+ test('create table and view #3', async () => {
103
+ const users = pgTable('users', {
104
+ id: integer('id').primaryKey().notNull(),
105
+ });
106
+ const to = {
107
+ users: users,
108
+ view1: pgView('some_view1', { id: integer('id') }).with({
109
+ checkOption: 'local',
110
+ securityBarrier: false,
111
+ securityInvoker: true,
112
+ }).as(sql`SELECT * FROM ${users}`),
113
+ view2: pgView('some_view2').with({
114
+ checkOption: 'cascaded',
115
+ securityBarrier: true,
116
+ securityInvoker: false,
117
+ }).as((qb) => qb.select().from(users)),
118
+ };
119
+
120
+ const { statements, sqlStatements } = await diffTestSchemas({}, to, []);
121
+
122
+ expect(statements.length).toBe(3);
123
+ expect(statements[0]).toStrictEqual({
124
+ type: 'create_table',
125
+ tableName: 'users',
126
+ schema: '',
127
+ columns: [{
128
+ name: 'id',
129
+ notNull: true,
130
+ primaryKey: true,
131
+ type: 'integer',
132
+ }],
133
+ compositePKs: [],
134
+ uniqueConstraints: [],
135
+ compositePkName: '',
136
+ checkConstraints: [],
137
+ isRLSEnabled: false,
138
+ policies: [],
139
+ });
140
+ expect(statements[1]).toStrictEqual({
141
+ type: 'create_view',
142
+ name: 'some_view1',
143
+ definition: `SELECT * FROM "users"`,
144
+ schema: 'public',
145
+ with: {
146
+ checkOption: 'local',
147
+ securityBarrier: false,
148
+ securityInvoker: true,
149
+ },
150
+ materialized: false,
151
+ tablespace: undefined,
152
+ using: undefined,
153
+ withNoData: false,
154
+ });
155
+ expect(statements[2]).toStrictEqual({
156
+ type: 'create_view',
157
+ name: 'some_view2',
158
+ definition: `select "id" from "users"`,
159
+ schema: 'public',
160
+ with: {
161
+ checkOption: 'cascaded',
162
+ securityBarrier: true,
163
+ securityInvoker: false,
164
+ },
165
+ materialized: false,
166
+ tablespace: undefined,
167
+ using: undefined,
168
+ withNoData: false,
169
+ });
170
+
171
+ expect(sqlStatements.length).toBe(3);
172
+ expect(sqlStatements[0]).toBe(`CREATE TABLE "users" (
173
+ \t"id" integer PRIMARY KEY NOT NULL
174
+ );\n`);
175
+ expect(sqlStatements[1]).toBe(
176
+ `CREATE VIEW "public"."some_view1" WITH (check_option = local, security_barrier = false, security_invoker = true) AS (SELECT * FROM "users");`,
177
+ );
178
+ expect(sqlStatements[2]).toBe(
179
+ `CREATE VIEW "public"."some_view2" WITH (check_option = cascaded, security_barrier = true, security_invoker = false) AS (select "id" from "users");`,
180
+ );
181
+ });
182
+
183
+ test('create table and view #4', async () => {
184
+ const schema = pgSchema('new_schema');
185
+
186
+ const users = schema.table('users', {
187
+ id: integer('id').primaryKey().notNull(),
188
+ });
189
+ const to = {
190
+ schema,
191
+ users: users,
192
+ view1: schema.view('some_view1', { id: integer('id') }).with({
193
+ checkOption: 'local',
194
+ securityBarrier: false,
195
+ securityInvoker: true,
196
+ }).as(sql`SELECT * FROM ${users}`),
197
+ view2: schema.view('some_view2').with({
198
+ checkOption: 'cascaded',
199
+ securityBarrier: true,
200
+ securityInvoker: false,
201
+ }).as((qb) => qb.select().from(users)),
202
+ };
203
+
204
+ const { statements, sqlStatements } = await diffTestSchemas({}, to, []);
205
+
206
+ expect(statements.length).toBe(4);
207
+ expect(statements[0]).toStrictEqual({
208
+ type: 'create_schema',
209
+ name: 'new_schema',
210
+ });
211
+ expect(statements[1]).toStrictEqual({
212
+ type: 'create_table',
213
+ tableName: 'users',
214
+ schema: 'new_schema',
215
+ columns: [{
216
+ name: 'id',
217
+ notNull: true,
218
+ primaryKey: true,
219
+ type: 'integer',
220
+ }],
221
+ compositePKs: [],
222
+ uniqueConstraints: [],
223
+ compositePkName: '',
224
+ isRLSEnabled: false,
225
+ policies: [],
226
+ checkConstraints: [],
227
+ });
228
+ expect(statements[2]).toStrictEqual({
229
+ type: 'create_view',
230
+ name: 'some_view1',
231
+ definition: `SELECT * FROM "new_schema"."users"`,
232
+ schema: 'new_schema',
233
+ with: {
234
+ checkOption: 'local',
235
+ securityBarrier: false,
236
+ securityInvoker: true,
237
+ },
238
+ materialized: false,
239
+ tablespace: undefined,
240
+ using: undefined,
241
+ withNoData: false,
242
+ });
243
+ expect(statements[3]).toStrictEqual({
244
+ type: 'create_view',
245
+ name: 'some_view2',
246
+ definition: `select "id" from "new_schema"."users"`,
247
+ schema: 'new_schema',
248
+ with: {
249
+ checkOption: 'cascaded',
250
+ securityBarrier: true,
251
+ securityInvoker: false,
252
+ },
253
+ materialized: false,
254
+ tablespace: undefined,
255
+ using: undefined,
256
+ withNoData: false,
257
+ });
258
+
259
+ expect(sqlStatements.length).toBe(4);
260
+ expect(sqlStatements[0]).toBe(`CREATE SCHEMA "new_schema";\n`);
261
+ expect(sqlStatements[1]).toBe(`CREATE TABLE "new_schema"."users" (
262
+ \t"id" integer PRIMARY KEY NOT NULL
263
+ );\n`);
264
+ expect(sqlStatements[2]).toBe(
265
+ `CREATE VIEW "new_schema"."some_view1" WITH (check_option = local, security_barrier = false, security_invoker = true) AS (SELECT * FROM "new_schema"."users");`,
266
+ );
267
+ expect(sqlStatements[3]).toBe(
268
+ `CREATE VIEW "new_schema"."some_view2" WITH (check_option = cascaded, security_barrier = true, security_invoker = false) AS (select "id" from "new_schema"."users");`,
269
+ );
270
+ });
271
+
272
+ test('create table and view #5', async () => {
273
+ const users = pgTable('users', {
274
+ id: integer('id').primaryKey().notNull(),
275
+ });
276
+ const to = {
277
+ users: users,
278
+ view1: pgView('some_view', { id: integer('id') }).as(sql`SELECT * FROM ${users}`),
279
+ view2: pgView('some_view', { id: integer('id') }).as(sql`SELECT * FROM ${users}`),
280
+ };
281
+
282
+ await expect(diffTestSchemas({}, to, [])).rejects.toThrowError();
283
+ });
284
+
285
+ test('create table and view #6', async () => {
286
+ const users = pgTable('users', {
287
+ id: integer('id').primaryKey().notNull(),
288
+ });
289
+ const to = {
290
+ users: users,
291
+ view1: pgView('some_view', { id: integer('id') }).with({ checkOption: 'cascaded' }).as(sql`SELECT * FROM ${users}`),
292
+ };
293
+
294
+ const { statements, sqlStatements } = await diffTestSchemas({}, to, []);
295
+
296
+ expect(statements.length).toBe(2);
297
+ expect(statements[0]).toStrictEqual({
298
+ columns: [
299
+ {
300
+ name: 'id',
301
+ notNull: true,
302
+ primaryKey: true,
303
+ type: 'integer',
304
+ },
305
+ ],
306
+ compositePKs: [],
307
+ compositePkName: '',
308
+ schema: '',
309
+ tableName: 'users',
310
+ type: 'create_table',
311
+ uniqueConstraints: [],
312
+ checkConstraints: [],
313
+ isRLSEnabled: false,
314
+ policies: [],
315
+ });
316
+ expect(statements[1]).toStrictEqual({
317
+ definition: 'SELECT * FROM "users"',
318
+ name: 'some_view',
319
+ schema: 'public',
320
+ type: 'create_view',
321
+ with: {
322
+ checkOption: 'cascaded',
323
+ },
324
+ materialized: false,
325
+ tablespace: undefined,
326
+ using: undefined,
327
+ withNoData: false,
328
+ });
329
+
330
+ expect(sqlStatements.length).toBe(2);
331
+ expect(sqlStatements[0]).toBe(`CREATE TABLE "users" (
332
+ \t"id" integer PRIMARY KEY NOT NULL
333
+ );\n`);
334
+ expect(sqlStatements[1]).toBe(
335
+ `CREATE VIEW "public"."some_view" WITH (check_option = cascaded) AS (SELECT * FROM "users");`,
336
+ );
337
+ });
338
+
339
+ test('create view with existing flag', async () => {
340
+ const users = pgTable('users', {
341
+ id: integer('id').primaryKey().notNull(),
342
+ });
343
+
344
+ const from = {
345
+ users,
346
+ };
347
+
348
+ const to = {
349
+ users: users,
350
+ view1: pgView('some_view', { id: integer('id') }).with({ checkOption: 'cascaded' }).existing(),
351
+ };
352
+
353
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
354
+
355
+ expect(statements.length).toBe(0);
356
+ expect(sqlStatements.length).toBe(0);
357
+ });
358
+
359
+ test('create table and materialized view #1', async () => {
360
+ const users = pgTable('users', {
361
+ id: integer('id').primaryKey().notNull(),
362
+ });
363
+ const to = {
364
+ users: users,
365
+ view: pgMaterializedView('some_view').as((qb) => qb.select().from(users)),
366
+ };
367
+
368
+ const { statements, sqlStatements } = await diffTestSchemas({}, to, []);
369
+
370
+ expect(statements.length).toBe(2);
371
+ expect(statements[0]).toStrictEqual({
372
+ type: 'create_table',
373
+ tableName: 'users',
374
+ schema: '',
375
+ columns: [{
376
+ name: 'id',
377
+ notNull: true,
378
+ primaryKey: true,
379
+ type: 'integer',
380
+ }],
381
+ compositePKs: [],
382
+ uniqueConstraints: [],
383
+ isRLSEnabled: false,
384
+ policies: [],
385
+ compositePkName: '',
386
+ checkConstraints: [],
387
+ });
388
+ expect(statements[1]).toStrictEqual({
389
+ type: 'create_view',
390
+ name: 'some_view',
391
+ definition: `select "id" from "users"`,
392
+ schema: 'public',
393
+ with: undefined,
394
+ materialized: true,
395
+ tablespace: undefined,
396
+ using: undefined,
397
+ withNoData: false,
398
+ });
399
+
400
+ expect(sqlStatements.length).toBe(2);
401
+ expect(sqlStatements[0]).toBe(`CREATE TABLE "users" (
402
+ \t"id" integer PRIMARY KEY NOT NULL
403
+ );\n`);
404
+ expect(sqlStatements[1]).toBe(`CREATE MATERIALIZED VIEW "public"."some_view" AS (select "id" from "users");`);
405
+ });
406
+
407
+ test('create table and materialized view #2', async () => {
408
+ const users = pgTable('users', {
409
+ id: integer('id').primaryKey().notNull(),
410
+ });
411
+ const to = {
412
+ users: users,
413
+ view: pgMaterializedView('some_view', { id: integer('id') }).as(sql`SELECT * FROM ${users}`),
414
+ };
415
+
416
+ const { statements, sqlStatements } = await diffTestSchemas({}, to, []);
417
+
418
+ expect(statements.length).toBe(2);
419
+ expect(statements[0]).toStrictEqual({
420
+ type: 'create_table',
421
+ tableName: 'users',
422
+ schema: '',
423
+ columns: [{
424
+ name: 'id',
425
+ notNull: true,
426
+ primaryKey: true,
427
+ type: 'integer',
428
+ }],
429
+ compositePKs: [],
430
+ uniqueConstraints: [],
431
+ compositePkName: '',
432
+ isRLSEnabled: false,
433
+ policies: [],
434
+ checkConstraints: [],
435
+ });
436
+ expect(statements[1]).toStrictEqual({
437
+ type: 'create_view',
438
+ name: 'some_view',
439
+ definition: `SELECT * FROM "users"`,
440
+ schema: 'public',
441
+ with: undefined,
442
+ materialized: true,
443
+ tablespace: undefined,
444
+ using: undefined,
445
+ withNoData: false,
446
+ });
447
+
448
+ expect(sqlStatements.length).toBe(2);
449
+ expect(sqlStatements[0]).toBe(`CREATE TABLE "users" (
450
+ \t"id" integer PRIMARY KEY NOT NULL
451
+ );\n`);
452
+ expect(sqlStatements[1]).toBe(`CREATE MATERIALIZED VIEW "public"."some_view" AS (SELECT * FROM "users");`);
453
+ });
454
+
455
+ test('create table and materialized view #3', async () => {
456
+ const users = pgTable('users', {
457
+ id: integer('id').primaryKey().notNull(),
458
+ });
459
+ const to = {
460
+ users: users,
461
+ view1: pgMaterializedView('some_view1', { id: integer('id') }).as(sql`SELECT * FROM ${users}`),
462
+ view2: pgMaterializedView('some_view2').tablespace('some_tablespace').using('heap').withNoData().with({
463
+ autovacuumEnabled: true,
464
+ autovacuumFreezeMaxAge: 1,
465
+ autovacuumFreezeMinAge: 1,
466
+ autovacuumFreezeTableAge: 1,
467
+ autovacuumMultixactFreezeMaxAge: 1,
468
+ autovacuumMultixactFreezeMinAge: 1,
469
+ autovacuumMultixactFreezeTableAge: 1,
470
+ autovacuumVacuumCostDelay: 1,
471
+ autovacuumVacuumCostLimit: 1,
472
+ autovacuumVacuumScaleFactor: 1,
473
+ autovacuumVacuumThreshold: 1,
474
+ fillfactor: 1,
475
+ logAutovacuumMinDuration: 1,
476
+ parallelWorkers: 1,
477
+ toastTupleTarget: 1,
478
+ userCatalogTable: true,
479
+ vacuumIndexCleanup: 'off',
480
+ vacuumTruncate: false,
481
+ }).as((qb) => qb.select().from(users)),
482
+ };
483
+
484
+ const { statements, sqlStatements } = await diffTestSchemas({}, to, []);
485
+
486
+ expect(statements.length).toBe(3);
487
+ expect(statements[0]).toStrictEqual({
488
+ type: 'create_table',
489
+ tableName: 'users',
490
+ schema: '',
491
+ columns: [{
492
+ name: 'id',
493
+ notNull: true,
494
+ primaryKey: true,
495
+ type: 'integer',
496
+ }],
497
+ compositePKs: [],
498
+ uniqueConstraints: [],
499
+ isRLSEnabled: false,
500
+ compositePkName: '',
501
+ policies: [],
502
+ checkConstraints: [],
503
+ });
504
+ expect(statements[1]).toStrictEqual({
505
+ type: 'create_view',
506
+ name: 'some_view1',
507
+ definition: `SELECT * FROM "users"`,
508
+ schema: 'public',
509
+ with: undefined,
510
+ materialized: true,
511
+ withNoData: false,
512
+ using: undefined,
513
+ tablespace: undefined,
514
+ });
515
+ expect(statements[2]).toStrictEqual({
516
+ type: 'create_view',
517
+ name: 'some_view2',
518
+ definition: `select "id" from "users"`,
519
+ schema: 'public',
520
+ with: {
521
+ autovacuumEnabled: true,
522
+ autovacuumFreezeMaxAge: 1,
523
+ autovacuumFreezeMinAge: 1,
524
+ autovacuumFreezeTableAge: 1,
525
+ autovacuumMultixactFreezeMaxAge: 1,
526
+ autovacuumMultixactFreezeMinAge: 1,
527
+ autovacuumMultixactFreezeTableAge: 1,
528
+ autovacuumVacuumCostDelay: 1,
529
+ autovacuumVacuumCostLimit: 1,
530
+ autovacuumVacuumScaleFactor: 1,
531
+ autovacuumVacuumThreshold: 1,
532
+ fillfactor: 1,
533
+ logAutovacuumMinDuration: 1,
534
+ parallelWorkers: 1,
535
+ toastTupleTarget: 1,
536
+ userCatalogTable: true,
537
+ vacuumIndexCleanup: 'off',
538
+ vacuumTruncate: false,
539
+ },
540
+ materialized: true,
541
+ tablespace: 'some_tablespace',
542
+ using: 'heap',
543
+ withNoData: true,
544
+ });
545
+
546
+ expect(sqlStatements.length).toBe(3);
547
+ expect(sqlStatements[0]).toBe(`CREATE TABLE "users" (
548
+ \t"id" integer PRIMARY KEY NOT NULL
549
+ );\n`);
550
+ expect(sqlStatements[1]).toBe(
551
+ `CREATE MATERIALIZED VIEW "public"."some_view1" AS (SELECT * FROM "users");`,
552
+ );
553
+ expect(sqlStatements[2]).toBe(
554
+ `CREATE MATERIALIZED VIEW "public"."some_view2" USING "heap" WITH (autovacuum_enabled = true, autovacuum_freeze_max_age = 1, autovacuum_freeze_min_age = 1, autovacuum_freeze_table_age = 1, autovacuum_multixact_freeze_max_age = 1, autovacuum_multixact_freeze_min_age = 1, autovacuum_multixact_freeze_table_age = 1, autovacuum_vacuum_cost_delay = 1, autovacuum_vacuum_cost_limit = 1, autovacuum_vacuum_scale_factor = 1, autovacuum_vacuum_threshold = 1, fillfactor = 1, log_autovacuum_min_duration = 1, parallel_workers = 1, toast_tuple_target = 1, user_catalog_table = true, vacuum_index_cleanup = off, vacuum_truncate = false) TABLESPACE some_tablespace AS (select "id" from "users") WITH NO DATA;`,
555
+ );
556
+ });
557
+
558
+ test('create table and materialized view #4', async () => {
559
+ // same names
560
+ const users = pgTable('users', {
561
+ id: integer('id').primaryKey().notNull(),
562
+ });
563
+ const to = {
564
+ users: users,
565
+ view1: pgMaterializedView('some_view', { id: integer('id') }).as(sql`SELECT * FROM ${users}`),
566
+ view2: pgMaterializedView('some_view', { id: integer('id') }).as(sql`SELECT * FROM ${users}`),
567
+ };
568
+
569
+ await expect(diffTestSchemas({}, to, [])).rejects.toThrowError();
570
+ });
571
+
572
+ test('create table and materialized view #5', async () => {
573
+ const users = pgTable('users', {
574
+ id: integer('id').primaryKey().notNull(),
575
+ });
576
+ const to = {
577
+ users: users,
578
+ view1: pgMaterializedView('some_view', { id: integer('id') }).with({ autovacuumFreezeMinAge: 14 }).as(
579
+ sql`SELECT * FROM ${users}`,
580
+ ),
581
+ };
582
+
583
+ const { statements, sqlStatements } = await diffTestSchemas({}, to, []);
584
+
585
+ expect(statements.length).toBe(2);
586
+ expect(statements[0]).toStrictEqual({
587
+ columns: [
588
+ {
589
+ name: 'id',
590
+ notNull: true,
591
+ primaryKey: true,
592
+ type: 'integer',
593
+ },
594
+ ],
595
+ compositePKs: [],
596
+ compositePkName: '',
597
+ schema: '',
598
+ tableName: 'users',
599
+ type: 'create_table',
600
+ uniqueConstraints: [],
601
+ isRLSEnabled: false,
602
+ policies: [],
603
+ checkConstraints: [],
604
+ });
605
+ expect(statements[1]).toEqual({
606
+ definition: 'SELECT * FROM "users"',
607
+ name: 'some_view',
608
+ schema: 'public',
609
+ type: 'create_view',
610
+ with: {
611
+ autovacuumFreezeMinAge: 14,
612
+ },
613
+ materialized: true,
614
+ tablespace: undefined,
615
+ using: undefined,
616
+ withNoData: false,
617
+ });
618
+
619
+ expect(sqlStatements.length).toBe(2);
620
+ expect(sqlStatements[0]).toBe(`CREATE TABLE "users" (
621
+ \t"id" integer PRIMARY KEY NOT NULL
622
+ );\n`);
623
+ expect(sqlStatements[1]).toBe(
624
+ `CREATE MATERIALIZED VIEW "public"."some_view" WITH (autovacuum_freeze_min_age = 14) AS (SELECT * FROM "users");`,
625
+ );
626
+ });
627
+
628
+ test('create materialized view with existing flag', async () => {
629
+ const users = pgTable('users', {
630
+ id: integer('id').primaryKey().notNull(),
631
+ });
632
+
633
+ const from = {
634
+ users,
635
+ };
636
+
637
+ const to = {
638
+ users: users,
639
+ view1: pgMaterializedView('some_view', { id: integer('id') }).with({ autovacuumEnabled: true }).existing(),
640
+ };
641
+
642
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
643
+
644
+ expect(statements.length).toBe(0);
645
+ expect(sqlStatements.length).toBe(0);
646
+ });
647
+
648
+ test('drop view #1', async () => {
649
+ const users = pgTable('users', {
650
+ id: integer('id').primaryKey().notNull(),
651
+ });
652
+
653
+ const from = {
654
+ users,
655
+ view: pgView('some_view', { id: integer('id') }).as(sql`SELECT * FROM ${users}`),
656
+ };
657
+
658
+ const to = {
659
+ users: users,
660
+ };
661
+
662
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
663
+
664
+ expect(statements.length).toBe(1);
665
+ expect(statements[0]).toStrictEqual({
666
+ type: 'drop_view',
667
+ name: 'some_view',
668
+ schema: 'public',
669
+ });
670
+
671
+ expect(sqlStatements.length).toBe(1);
672
+ expect(sqlStatements[0]).toBe(`DROP VIEW "public"."some_view";`);
673
+ });
674
+
675
+ test('drop view with existing flag', async () => {
676
+ const users = pgTable('users', {
677
+ id: integer('id').primaryKey().notNull(),
678
+ });
679
+
680
+ const from = {
681
+ users,
682
+ view: pgView('some_view', { id: integer('id') }).existing(),
683
+ };
684
+
685
+ const to = {
686
+ users: users,
687
+ };
688
+
689
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
690
+
691
+ expect(statements.length).toBe(0);
692
+ expect(sqlStatements.length).toBe(0);
693
+ });
694
+
695
+ test('drop materialized view #1', async () => {
696
+ const users = pgTable('users', {
697
+ id: integer('id').primaryKey().notNull(),
698
+ });
699
+
700
+ const from = {
701
+ users,
702
+ view: pgMaterializedView('some_view', { id: integer('id') }).as(sql`SELECT * FROM ${users}`),
703
+ };
704
+
705
+ const to = {
706
+ users: users,
707
+ };
708
+
709
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
710
+
711
+ expect(statements.length).toBe(1);
712
+ expect(statements[0]).toStrictEqual({
713
+ type: 'drop_view',
714
+ name: 'some_view',
715
+ schema: 'public',
716
+ materialized: true,
717
+ });
718
+
719
+ expect(sqlStatements.length).toBe(1);
720
+ expect(sqlStatements[0]).toBe(`DROP MATERIALIZED VIEW "public"."some_view";`);
721
+ });
722
+
723
+ test('drop materialized view with existing flag', async () => {
724
+ const users = pgTable('users', {
725
+ id: integer('id').primaryKey().notNull(),
726
+ });
727
+
728
+ const from = {
729
+ users,
730
+ view: pgMaterializedView('some_view', { id: integer('id') }).existing(),
731
+ };
732
+
733
+ const to = {
734
+ users: users,
735
+ };
736
+
737
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
738
+
739
+ expect(statements.length).toBe(0);
740
+ expect(sqlStatements.length).toBe(0);
741
+ });
742
+
743
+ test('rename view #1', async () => {
744
+ const from = {
745
+ view: pgView('some_view', { id: integer('id') }).as(sql`SELECT * FROM "users"`),
746
+ };
747
+
748
+ const to = {
749
+ view: pgView('new_some_view', { id: integer('id') }).as(sql`SELECT * FROM "users"`),
750
+ };
751
+
752
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, ['public.some_view->public.new_some_view']);
753
+
754
+ expect(statements.length).toBe(1);
755
+ expect(statements[0]).toStrictEqual({
756
+ type: 'rename_view',
757
+ nameFrom: 'some_view',
758
+ nameTo: 'new_some_view',
759
+ schema: 'public',
760
+ });
761
+ expect(sqlStatements.length).toBe(1);
762
+ expect(sqlStatements[0]).toBe(`ALTER VIEW "public"."some_view" RENAME TO "new_some_view";`);
763
+ });
764
+
765
+ test('rename view with existing flag', async () => {
766
+ const from = {
767
+ view: pgView('some_view', { id: integer('id') }).existing(),
768
+ };
769
+
770
+ const to = {
771
+ view: pgView('new_some_view', { id: integer('id') }).existing(),
772
+ };
773
+
774
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, ['public.some_view->public.new_some_view']);
775
+
776
+ expect(statements.length).toBe(0);
777
+ expect(sqlStatements.length).toBe(0);
778
+ });
779
+
780
+ test('rename materialized view #1', async () => {
781
+ const from = {
782
+ view: pgMaterializedView('some_view', { id: integer('id') }).as(sql`SELECT * FROM "users"`),
783
+ };
784
+
785
+ const to = {
786
+ view: pgMaterializedView('new_some_view', { id: integer('id') }).as(sql`SELECT * FROM "users"`),
787
+ };
788
+
789
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, ['public.some_view->public.new_some_view']);
790
+
791
+ expect(statements.length).toBe(1);
792
+ expect(statements[0]).toStrictEqual({
793
+ type: 'rename_view',
794
+ nameFrom: 'some_view',
795
+ nameTo: 'new_some_view',
796
+ schema: 'public',
797
+ materialized: true,
798
+ });
799
+ expect(sqlStatements.length).toBe(1);
800
+ expect(sqlStatements[0]).toBe(`ALTER MATERIALIZED VIEW "public"."some_view" RENAME TO "new_some_view";`);
801
+ });
802
+
803
+ test('rename materialized view with existing flag', async () => {
804
+ const from = {
805
+ view: pgMaterializedView('some_view', { id: integer('id') }).existing(),
806
+ };
807
+
808
+ const to = {
809
+ view: pgMaterializedView('new_some_view', { id: integer('id') }).existing(),
810
+ };
811
+
812
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, ['public.some_view->public.new_some_view']);
813
+
814
+ expect(statements.length).toBe(0);
815
+ expect(sqlStatements.length).toBe(0);
816
+ });
817
+
818
+ test('view alter schema', async () => {
819
+ const schema = pgSchema('new_schema');
820
+
821
+ const from = {
822
+ view: pgView('some_view', { id: integer('id') }).as(sql`SELECT * FROM "users"`),
823
+ };
824
+
825
+ const to = {
826
+ schema,
827
+ view: schema.view('some_view', { id: integer('id') }).as(sql`SELECT * FROM "users"`),
828
+ };
829
+
830
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, ['public.some_view->new_schema.some_view']);
831
+
832
+ expect(statements.length).toBe(2);
833
+ expect(statements[0]).toStrictEqual({
834
+ type: 'create_schema',
835
+ name: 'new_schema',
836
+ });
837
+ expect(statements[1]).toStrictEqual({
838
+ type: 'alter_view_alter_schema',
839
+ toSchema: 'new_schema',
840
+ fromSchema: 'public',
841
+ name: 'some_view',
842
+ });
843
+ expect(sqlStatements.length).toBe(2);
844
+ expect(sqlStatements[0]).toBe(`CREATE SCHEMA "new_schema";\n`);
845
+ expect(sqlStatements[1]).toBe(`ALTER VIEW "public"."some_view" SET SCHEMA "new_schema";`);
846
+ });
847
+
848
+ test('view alter schema with existing flag', async () => {
849
+ const schema = pgSchema('new_schema');
850
+
851
+ const from = {
852
+ view: pgView('some_view', { id: integer('id') }).existing(),
853
+ };
854
+
855
+ const to = {
856
+ schema,
857
+ view: schema.view('some_view', { id: integer('id') }).existing(),
858
+ };
859
+
860
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, ['public.some_view->new_schema.some_view']);
861
+
862
+ expect(statements.length).toBe(1);
863
+ expect(statements[0]).toStrictEqual({
864
+ type: 'create_schema',
865
+ name: 'new_schema',
866
+ });
867
+ expect(sqlStatements.length).toBe(1);
868
+ expect(sqlStatements[0]).toBe(`CREATE SCHEMA "new_schema";\n`);
869
+ });
870
+
871
+ test('view alter schema for materialized', async () => {
872
+ const schema = pgSchema('new_schema');
873
+
874
+ const from = {
875
+ view: pgMaterializedView('some_view', { id: integer('id') }).as(sql`SELECT * FROM "users"`),
876
+ };
877
+
878
+ const to = {
879
+ schema,
880
+ view: schema.materializedView('some_view', { id: integer('id') }).as(sql`SELECT * FROM "users"`),
881
+ };
882
+
883
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, ['public.some_view->new_schema.some_view']);
884
+
885
+ expect(statements.length).toBe(2);
886
+ expect(statements[0]).toStrictEqual({
887
+ type: 'create_schema',
888
+ name: 'new_schema',
889
+ });
890
+ expect(statements[1]).toStrictEqual({
891
+ type: 'alter_view_alter_schema',
892
+ toSchema: 'new_schema',
893
+ fromSchema: 'public',
894
+ name: 'some_view',
895
+ materialized: true,
896
+ });
897
+ expect(sqlStatements.length).toBe(2);
898
+ expect(sqlStatements[0]).toBe(`CREATE SCHEMA "new_schema";\n`);
899
+ expect(sqlStatements[1]).toBe(`ALTER MATERIALIZED VIEW "public"."some_view" SET SCHEMA "new_schema";`);
900
+ });
901
+
902
+ test('view alter schema for materialized with existing flag', async () => {
903
+ const schema = pgSchema('new_schema');
904
+
905
+ const from = {
906
+ view: pgMaterializedView('some_view', { id: integer('id') }).existing(),
907
+ };
908
+
909
+ const to = {
910
+ schema,
911
+ view: schema.materializedView('some_view', { id: integer('id') }).existing(),
912
+ };
913
+
914
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, ['public.some_view->new_schema.some_view']);
915
+
916
+ expect(statements.length).toBe(1);
917
+ expect(statements[0]).toStrictEqual({
918
+ type: 'create_schema',
919
+ name: 'new_schema',
920
+ });
921
+ expect(sqlStatements.length).toBe(1);
922
+ expect(sqlStatements[0]).toBe(`CREATE SCHEMA "new_schema";\n`);
923
+ });
924
+
925
+ test('add with option to view #1', async () => {
926
+ const users = pgTable('users', {
927
+ id: integer('id').primaryKey().notNull(),
928
+ });
929
+
930
+ const from = {
931
+ users,
932
+ view: pgView('some_view').as((qb) => qb.select().from(users)),
933
+ };
934
+
935
+ const to = {
936
+ users,
937
+ view: pgView('some_view').with({ checkOption: 'cascaded', securityBarrier: true }).as((qb) =>
938
+ qb.select().from(users)
939
+ ),
940
+ };
941
+
942
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
943
+
944
+ expect(statements.length).toBe(1);
945
+ expect(statements[0]).toStrictEqual({
946
+ name: 'some_view',
947
+ schema: 'public',
948
+ type: 'alter_view_add_with_option',
949
+ with: {
950
+ checkOption: 'cascaded',
951
+ securityBarrier: true,
952
+ },
953
+ materialized: false,
954
+ });
955
+
956
+ expect(sqlStatements.length).toBe(1);
957
+ expect(sqlStatements[0]).toBe(
958
+ `ALTER VIEW "public"."some_view" SET (check_option = cascaded, security_barrier = true);`,
959
+ );
960
+ });
961
+
962
+ test('add with option to view with existing flag', async () => {
963
+ const users = pgTable('users', {
964
+ id: integer('id').primaryKey().notNull(),
965
+ });
966
+
967
+ const from = {
968
+ users,
969
+ view: pgView('some_view', {}).existing(),
970
+ };
971
+
972
+ const to = {
973
+ users,
974
+ view: pgView('some_view', {}).with({ checkOption: 'cascaded', securityBarrier: true }).existing(),
975
+ };
976
+
977
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
978
+
979
+ expect(statements.length).toBe(0);
980
+ expect(sqlStatements.length).toBe(0);
981
+ });
982
+
983
+ test('add with option to materialized view #1', async () => {
984
+ const users = pgTable('users', {
985
+ id: integer('id').primaryKey().notNull(),
986
+ });
987
+
988
+ const from = {
989
+ users,
990
+ view: pgMaterializedView('some_view').as((qb) => qb.select().from(users)),
991
+ };
992
+
993
+ const to = {
994
+ users,
995
+ view: pgMaterializedView('some_view').with({ autovacuumMultixactFreezeMaxAge: 3 }).as((qb) =>
996
+ qb.select().from(users)
997
+ ),
998
+ };
999
+
1000
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1001
+
1002
+ expect(statements.length).toBe(1);
1003
+ expect(statements[0]).toStrictEqual({
1004
+ name: 'some_view',
1005
+ schema: 'public',
1006
+ type: 'alter_view_add_with_option',
1007
+ with: {
1008
+ autovacuumMultixactFreezeMaxAge: 3,
1009
+ },
1010
+ materialized: true,
1011
+ });
1012
+
1013
+ expect(sqlStatements.length).toBe(1);
1014
+ expect(sqlStatements[0]).toBe(
1015
+ `ALTER MATERIALIZED VIEW "public"."some_view" SET (autovacuum_multixact_freeze_max_age = 3);`,
1016
+ );
1017
+ });
1018
+
1019
+ test('add with option to materialized view with existing flag', async () => {
1020
+ const users = pgTable('users', {
1021
+ id: integer('id').primaryKey().notNull(),
1022
+ });
1023
+
1024
+ const from = {
1025
+ users,
1026
+ view: pgMaterializedView('some_view', {}).existing(),
1027
+ };
1028
+
1029
+ const to = {
1030
+ users,
1031
+ view: pgMaterializedView('some_view', {}).with({ autovacuumMultixactFreezeMaxAge: 3 }).existing(),
1032
+ };
1033
+
1034
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1035
+
1036
+ expect(statements.length).toBe(0);
1037
+ expect(sqlStatements.length).toBe(0);
1038
+ });
1039
+
1040
+ test('drop with option from view #1', async () => {
1041
+ const users = pgTable('users', {
1042
+ id: integer('id').primaryKey().notNull(),
1043
+ });
1044
+
1045
+ const from = {
1046
+ users,
1047
+ view: pgView('some_view').with({ checkOption: 'cascaded', securityBarrier: true, securityInvoker: true }).as((qb) =>
1048
+ qb.select().from(users)
1049
+ ),
1050
+ };
1051
+
1052
+ const to = {
1053
+ users,
1054
+ view: pgView('some_view').as((qb) => qb.select().from(users)),
1055
+ };
1056
+
1057
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1058
+
1059
+ expect(statements.length).toBe(1);
1060
+ expect(statements[0]).toStrictEqual({
1061
+ name: 'some_view',
1062
+ schema: 'public',
1063
+ type: 'alter_view_drop_with_option',
1064
+ materialized: false,
1065
+ with: {
1066
+ checkOption: 'cascaded',
1067
+ securityBarrier: true,
1068
+ securityInvoker: true,
1069
+ },
1070
+ });
1071
+
1072
+ expect(sqlStatements.length).toBe(1);
1073
+ expect(sqlStatements[0]).toBe(
1074
+ `ALTER VIEW "public"."some_view" RESET (check_option, security_barrier, security_invoker);`,
1075
+ );
1076
+ });
1077
+
1078
+ test('drop with option from view with existing flag', async () => {
1079
+ const users = pgTable('users', {
1080
+ id: integer('id').primaryKey().notNull(),
1081
+ });
1082
+
1083
+ const from = {
1084
+ users,
1085
+ view: pgView('some_view', {}).with({ checkOption: 'cascaded', securityBarrier: true, securityInvoker: true })
1086
+ .existing(),
1087
+ };
1088
+
1089
+ const to = {
1090
+ users,
1091
+ view: pgView('some_view', {}).existing(),
1092
+ };
1093
+
1094
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1095
+
1096
+ expect(statements.length).toBe(0);
1097
+ expect(sqlStatements.length).toBe(0);
1098
+ });
1099
+
1100
+ test('drop with option from materialized view #1', async () => {
1101
+ const users = pgTable('users', {
1102
+ id: integer('id').primaryKey().notNull(),
1103
+ });
1104
+
1105
+ const from = {
1106
+ users,
1107
+ view: pgMaterializedView('some_view').with({ autovacuumEnabled: true, autovacuumFreezeMaxAge: 10 }).as((qb) =>
1108
+ qb.select().from(users)
1109
+ ),
1110
+ };
1111
+
1112
+ const to = {
1113
+ users,
1114
+ view: pgMaterializedView('some_view').as((qb) => qb.select().from(users)),
1115
+ };
1116
+
1117
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1118
+
1119
+ expect(statements.length).toBe(1);
1120
+ expect(statements[0]).toStrictEqual({
1121
+ name: 'some_view',
1122
+ schema: 'public',
1123
+ type: 'alter_view_drop_with_option',
1124
+ materialized: true,
1125
+ with: {
1126
+ autovacuumEnabled: true,
1127
+ autovacuumFreezeMaxAge: 10,
1128
+ },
1129
+ });
1130
+
1131
+ expect(sqlStatements.length).toBe(1);
1132
+ expect(sqlStatements[0]).toBe(
1133
+ `ALTER MATERIALIZED VIEW "public"."some_view" RESET (autovacuum_enabled, autovacuum_freeze_max_age);`,
1134
+ );
1135
+ });
1136
+
1137
+ test('drop with option from materialized view with existing flag', async () => {
1138
+ const users = pgTable('users', {
1139
+ id: integer('id').primaryKey().notNull(),
1140
+ });
1141
+
1142
+ const from = {
1143
+ users,
1144
+ view: pgMaterializedView('some_view', {}).with({ autovacuumEnabled: true, autovacuumFreezeMaxAge: 10 }).existing(),
1145
+ };
1146
+
1147
+ const to = {
1148
+ users,
1149
+ view: pgMaterializedView('some_view', {}).existing(),
1150
+ };
1151
+
1152
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1153
+
1154
+ expect(statements.length).toBe(0);
1155
+ expect(sqlStatements.length).toBe(0);
1156
+ });
1157
+
1158
+ test('alter with option in view #1', async () => {
1159
+ const users = pgTable('users', {
1160
+ id: integer('id').primaryKey().notNull(),
1161
+ });
1162
+
1163
+ const from = {
1164
+ users,
1165
+ view: pgView('some_view').with({ securityBarrier: true, securityInvoker: true }).as((qb) =>
1166
+ qb.select().from(users)
1167
+ ),
1168
+ };
1169
+
1170
+ const to = {
1171
+ users,
1172
+ view: pgView('some_view').with({ securityBarrier: true }).as((qb) => qb.select().from(users)),
1173
+ };
1174
+
1175
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1176
+
1177
+ expect(statements.length).toBe(1);
1178
+ expect(statements[0]).toStrictEqual({
1179
+ name: 'some_view',
1180
+ schema: 'public',
1181
+ type: 'alter_view_drop_with_option',
1182
+ with: {
1183
+ securityInvoker: true,
1184
+ },
1185
+ materialized: false,
1186
+ });
1187
+
1188
+ expect(sqlStatements.length).toBe(1);
1189
+ expect(sqlStatements[0]).toBe(
1190
+ `ALTER VIEW "public"."some_view" RESET (security_invoker);`,
1191
+ );
1192
+ });
1193
+
1194
+ test('alter with option in view with existing flag', async () => {
1195
+ const users = pgTable('users', {
1196
+ id: integer('id').primaryKey().notNull(),
1197
+ });
1198
+
1199
+ const from = {
1200
+ users,
1201
+ view: pgView('some_view', {}).with({ securityBarrier: true, securityInvoker: true }).existing(),
1202
+ };
1203
+
1204
+ const to = {
1205
+ users,
1206
+ view: pgView('some_view', {}).with({ securityBarrier: true }).existing(),
1207
+ };
1208
+
1209
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1210
+
1211
+ expect(statements.length).toBe(0);
1212
+ expect(sqlStatements.length).toBe(0);
1213
+ });
1214
+
1215
+ test('alter with option in materialized view #1', async () => {
1216
+ const users = pgTable('users', {
1217
+ id: integer('id').primaryKey().notNull(),
1218
+ });
1219
+
1220
+ const from = {
1221
+ users,
1222
+ view: pgMaterializedView('some_view').with({ autovacuumEnabled: true, autovacuumVacuumScaleFactor: 1 }).as((qb) =>
1223
+ qb.select().from(users)
1224
+ ),
1225
+ };
1226
+
1227
+ const to = {
1228
+ users,
1229
+ view: pgMaterializedView('some_view').with({ autovacuumEnabled: true }).as((qb) => qb.select().from(users)),
1230
+ };
1231
+
1232
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1233
+
1234
+ expect(statements.length).toBe(1);
1235
+ expect(statements[0]).toStrictEqual({
1236
+ name: 'some_view',
1237
+ schema: 'public',
1238
+ type: 'alter_view_drop_with_option',
1239
+ with: {
1240
+ autovacuumVacuumScaleFactor: 1,
1241
+ },
1242
+ materialized: true,
1243
+ });
1244
+
1245
+ expect(sqlStatements.length).toBe(1);
1246
+ expect(sqlStatements[0]).toBe(
1247
+ `ALTER MATERIALIZED VIEW "public"."some_view" RESET (autovacuum_vacuum_scale_factor);`,
1248
+ );
1249
+ });
1250
+
1251
+ test('alter with option in materialized view with existing flag', async () => {
1252
+ const users = pgTable('users', {
1253
+ id: integer('id').primaryKey().notNull(),
1254
+ });
1255
+
1256
+ const from = {
1257
+ users,
1258
+ view: pgMaterializedView('some_view', {}).with({ autovacuumEnabled: true, autovacuumVacuumScaleFactor: 1 })
1259
+ .existing(),
1260
+ };
1261
+
1262
+ const to = {
1263
+ users,
1264
+ view: pgMaterializedView('some_view', {}).with({ autovacuumEnabled: true }).existing(),
1265
+ };
1266
+
1267
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1268
+
1269
+ expect(statements.length).toBe(0);
1270
+ expect(sqlStatements.length).toBe(0);
1271
+ });
1272
+
1273
+ test('alter with option in view #2', async () => {
1274
+ const users = pgTable('users', {
1275
+ id: integer('id').primaryKey().notNull(),
1276
+ });
1277
+
1278
+ const from = {
1279
+ users,
1280
+ view: pgView('some_view').with({ checkOption: 'local', securityBarrier: true, securityInvoker: true }).as((qb) =>
1281
+ qb.selectDistinct().from(users)
1282
+ ),
1283
+ };
1284
+
1285
+ const to = {
1286
+ users,
1287
+ view: pgView('some_view').with({ checkOption: 'cascaded', securityBarrier: true, securityInvoker: true }).as((qb) =>
1288
+ qb.selectDistinct().from(users)
1289
+ ),
1290
+ };
1291
+
1292
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1293
+
1294
+ expect(statements.length).toBe(1);
1295
+ expect(statements[0]).toStrictEqual({
1296
+ type: 'alter_view_add_with_option',
1297
+ name: 'some_view',
1298
+ schema: 'public',
1299
+ with: {
1300
+ checkOption: 'cascaded',
1301
+ },
1302
+ materialized: false,
1303
+ });
1304
+
1305
+ expect(sqlStatements.length).toBe(1);
1306
+
1307
+ expect(sqlStatements[0]).toBe(
1308
+ `ALTER VIEW "public"."some_view" SET (check_option = cascaded);`,
1309
+ );
1310
+ });
1311
+
1312
+ test('alter with option in materialized view #2', async () => {
1313
+ const users = pgTable('users', {
1314
+ id: integer('id').primaryKey().notNull(),
1315
+ });
1316
+
1317
+ const from = {
1318
+ users,
1319
+ view: pgMaterializedView('some_view').with({ autovacuumEnabled: true, fillfactor: 1 }).as((qb) =>
1320
+ qb.select().from(users)
1321
+ ),
1322
+ };
1323
+
1324
+ const to = {
1325
+ users,
1326
+ view: pgMaterializedView('some_view').with({ autovacuumEnabled: false, fillfactor: 1 }).as((qb) =>
1327
+ qb.select().from(users)
1328
+ ),
1329
+ };
1330
+
1331
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1332
+
1333
+ expect(statements.length).toBe(1);
1334
+ expect(statements[0]).toStrictEqual({
1335
+ type: 'alter_view_add_with_option',
1336
+ name: 'some_view',
1337
+ schema: 'public',
1338
+ with: {
1339
+ autovacuumEnabled: false,
1340
+ },
1341
+ materialized: true,
1342
+ });
1343
+
1344
+ expect(sqlStatements.length).toBe(1);
1345
+ expect(sqlStatements[0]).toBe(
1346
+ `ALTER MATERIALIZED VIEW "public"."some_view" SET (autovacuum_enabled = false);`,
1347
+ );
1348
+ });
1349
+
1350
+ test('alter view ".as" value', async () => {
1351
+ const users = pgTable('users', {
1352
+ id: integer('id').primaryKey().notNull(),
1353
+ });
1354
+
1355
+ const from = {
1356
+ users,
1357
+ view: pgView('some_view', { id: integer('id') }).with({
1358
+ checkOption: 'local',
1359
+ securityBarrier: true,
1360
+ securityInvoker: true,
1361
+ }).as(sql`SELECT '123'`),
1362
+ };
1363
+
1364
+ const to = {
1365
+ users,
1366
+ view: pgView('some_view', { id: integer('id') }).with({
1367
+ checkOption: 'local',
1368
+ securityBarrier: true,
1369
+ securityInvoker: true,
1370
+ }).as(sql`SELECT '1234'`),
1371
+ };
1372
+
1373
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1374
+
1375
+ expect(statements.length).toBe(2);
1376
+ expect(statements[0]).toStrictEqual(
1377
+ {
1378
+ name: 'some_view',
1379
+ schema: 'public',
1380
+ type: 'drop_view',
1381
+ },
1382
+ );
1383
+ expect(statements[1]).toStrictEqual(
1384
+ {
1385
+ definition: "SELECT '1234'",
1386
+ name: 'some_view',
1387
+ schema: 'public',
1388
+ type: 'create_view',
1389
+ materialized: false,
1390
+ with: {
1391
+ checkOption: 'local',
1392
+ securityBarrier: true,
1393
+ securityInvoker: true,
1394
+ },
1395
+ withNoData: false,
1396
+ tablespace: undefined,
1397
+ using: undefined,
1398
+ },
1399
+ );
1400
+ expect(sqlStatements.length).toBe(2);
1401
+ expect(sqlStatements[0]).toBe('DROP VIEW "public"."some_view";');
1402
+ expect(sqlStatements[1]).toBe(
1403
+ `CREATE VIEW "public"."some_view" WITH (check_option = local, security_barrier = true, security_invoker = true) AS (SELECT '1234');`,
1404
+ );
1405
+ });
1406
+
1407
+ test('alter view ".as" value with existing flag', async () => {
1408
+ const users = pgTable('users', {
1409
+ id: integer('id').primaryKey().notNull(),
1410
+ });
1411
+
1412
+ const from = {
1413
+ users,
1414
+ view: pgView('some_view', { id: integer('id') }).with({
1415
+ checkOption: 'local',
1416
+ securityBarrier: true,
1417
+ securityInvoker: true,
1418
+ }).existing(),
1419
+ };
1420
+
1421
+ const to = {
1422
+ users,
1423
+ view: pgView('some_view', { id: integer('id') }).with({
1424
+ checkOption: 'local',
1425
+ securityBarrier: true,
1426
+ securityInvoker: true,
1427
+ }).existing(),
1428
+ };
1429
+
1430
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1431
+
1432
+ expect(statements.length).toBe(0);
1433
+ expect(sqlStatements.length).toBe(0);
1434
+ });
1435
+
1436
+ test('alter materialized view ".as" value', async () => {
1437
+ const users = pgTable('users', {
1438
+ id: integer('id').primaryKey().notNull(),
1439
+ });
1440
+
1441
+ const from = {
1442
+ users,
1443
+ view: pgMaterializedView('some_view', { id: integer('id') }).with({
1444
+ autovacuumVacuumCostLimit: 1,
1445
+ }).as(sql`SELECT '123'`),
1446
+ };
1447
+
1448
+ const to = {
1449
+ users,
1450
+ view: pgMaterializedView('some_view', { id: integer('id') }).with({
1451
+ autovacuumVacuumCostLimit: 1,
1452
+ }).as(sql`SELECT '1234'`),
1453
+ };
1454
+
1455
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1456
+
1457
+ expect(statements.length).toBe(2);
1458
+ expect(statements[0]).toStrictEqual(
1459
+ {
1460
+ name: 'some_view',
1461
+ schema: 'public',
1462
+ type: 'drop_view',
1463
+ materialized: true,
1464
+ },
1465
+ );
1466
+ expect(statements[1]).toStrictEqual(
1467
+ {
1468
+ definition: "SELECT '1234'",
1469
+ name: 'some_view',
1470
+ schema: 'public',
1471
+ type: 'create_view',
1472
+ with: {
1473
+ autovacuumVacuumCostLimit: 1,
1474
+ },
1475
+ materialized: true,
1476
+ withNoData: false,
1477
+ tablespace: undefined,
1478
+ using: undefined,
1479
+ },
1480
+ );
1481
+ expect(sqlStatements.length).toBe(2);
1482
+ expect(sqlStatements[0]).toBe('DROP MATERIALIZED VIEW "public"."some_view";');
1483
+ expect(sqlStatements[1]).toBe(
1484
+ `CREATE MATERIALIZED VIEW "public"."some_view" WITH (autovacuum_vacuum_cost_limit = 1) AS (SELECT '1234');`,
1485
+ );
1486
+ });
1487
+
1488
+ test('alter materialized view ".as" value with existing flag', async () => {
1489
+ const users = pgTable('users', {
1490
+ id: integer('id').primaryKey().notNull(),
1491
+ });
1492
+
1493
+ const from = {
1494
+ users,
1495
+ view: pgMaterializedView('some_view', { id: integer('id') }).with({
1496
+ autovacuumVacuumCostLimit: 1,
1497
+ }).existing(),
1498
+ };
1499
+
1500
+ const to = {
1501
+ users,
1502
+ view: pgMaterializedView('some_view', { id: integer('id') }).with({
1503
+ autovacuumVacuumCostLimit: 1,
1504
+ }).existing(),
1505
+ };
1506
+
1507
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1508
+
1509
+ expect(statements.length).toBe(0);
1510
+ expect(sqlStatements.length).toBe(0);
1511
+ });
1512
+
1513
+ test('drop existing flag', async () => {
1514
+ const users = pgTable('users', {
1515
+ id: integer('id').primaryKey().notNull(),
1516
+ });
1517
+
1518
+ const from = {
1519
+ users,
1520
+ view: pgMaterializedView('some_view', { id: integer('id') }).with({
1521
+ autovacuumVacuumCostLimit: 1,
1522
+ }).existing(),
1523
+ };
1524
+
1525
+ const to = {
1526
+ users,
1527
+ view: pgMaterializedView('some_view', { id: integer('id') }).with({
1528
+ autovacuumVacuumCostLimit: 1,
1529
+ }).as(sql`SELECT 'asd'`),
1530
+ };
1531
+
1532
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1533
+
1534
+ expect(statements.length).toBe(2);
1535
+ expect(statements[0]).toEqual({
1536
+ type: 'drop_view',
1537
+ name: 'some_view',
1538
+ schema: 'public',
1539
+ materialized: true,
1540
+ });
1541
+ expect(statements[1]).toEqual({
1542
+ definition: "SELECT 'asd'",
1543
+ materialized: true,
1544
+ name: 'some_view',
1545
+ schema: 'public',
1546
+ tablespace: undefined,
1547
+ type: 'create_view',
1548
+ using: undefined,
1549
+ with: {
1550
+ autovacuumVacuumCostLimit: 1,
1551
+ },
1552
+ withNoData: false,
1553
+ });
1554
+ expect(sqlStatements.length).toBe(2);
1555
+ expect(sqlStatements[0]).toBe(`DROP MATERIALIZED VIEW "public"."some_view";`);
1556
+ expect(sqlStatements[1]).toBe(
1557
+ `CREATE MATERIALIZED VIEW "public"."some_view" WITH (autovacuum_vacuum_cost_limit = 1) AS (SELECT 'asd');`,
1558
+ );
1559
+ });
1560
+
1561
+ test('alter tablespace - materialize', async () => {
1562
+ const users = pgTable('users', {
1563
+ id: integer('id').primaryKey().notNull(),
1564
+ });
1565
+
1566
+ const from = {
1567
+ users,
1568
+ view: pgMaterializedView('some_view', { id: integer('id') }).tablespace('some_tablespace').with({
1569
+ autovacuumVacuumCostLimit: 1,
1570
+ }).as(sql`SELECT 'asd'`),
1571
+ };
1572
+
1573
+ const to = {
1574
+ users,
1575
+ view: pgMaterializedView('some_view', { id: integer('id') }).tablespace('new_tablespace').with({
1576
+ autovacuumVacuumCostLimit: 1,
1577
+ }).as(sql`SELECT 'asd'`),
1578
+ };
1579
+
1580
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1581
+
1582
+ expect(statements.length).toBe(1);
1583
+ expect(statements[0]).toEqual({
1584
+ type: 'alter_view_alter_tablespace',
1585
+ name: 'some_view',
1586
+ schema: 'public',
1587
+ materialized: true,
1588
+ toTablespace: 'new_tablespace',
1589
+ });
1590
+
1591
+ expect(sqlStatements.length).toBe(1);
1592
+ expect(sqlStatements[0]).toBe(
1593
+ `ALTER MATERIALIZED VIEW "public"."some_view" SET TABLESPACE new_tablespace;`,
1594
+ );
1595
+ });
1596
+
1597
+ test('set tablespace - materialize', async () => {
1598
+ const users = pgTable('users', {
1599
+ id: integer('id').primaryKey().notNull(),
1600
+ });
1601
+
1602
+ const from = {
1603
+ users,
1604
+ view: pgMaterializedView('some_view', { id: integer('id') }).with({
1605
+ autovacuumVacuumCostLimit: 1,
1606
+ }).as(sql`SELECT 'asd'`),
1607
+ };
1608
+
1609
+ const to = {
1610
+ users,
1611
+ view: pgMaterializedView('some_view', { id: integer('id') }).tablespace('new_tablespace').with({
1612
+ autovacuumVacuumCostLimit: 1,
1613
+ }).as(sql`SELECT 'asd'`),
1614
+ };
1615
+
1616
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1617
+
1618
+ expect(statements.length).toBe(1);
1619
+ expect(statements[0]).toEqual({
1620
+ type: 'alter_view_alter_tablespace',
1621
+ name: 'some_view',
1622
+ schema: 'public',
1623
+ materialized: true,
1624
+ toTablespace: 'new_tablespace',
1625
+ });
1626
+
1627
+ expect(sqlStatements.length).toBe(1);
1628
+ expect(sqlStatements[0]).toBe(
1629
+ `ALTER MATERIALIZED VIEW "public"."some_view" SET TABLESPACE new_tablespace;`,
1630
+ );
1631
+ });
1632
+
1633
+ test('drop tablespace - materialize', async () => {
1634
+ const users = pgTable('users', {
1635
+ id: integer('id').primaryKey().notNull(),
1636
+ });
1637
+
1638
+ const from = {
1639
+ users,
1640
+ view: pgMaterializedView('some_view', { id: integer('id') }).tablespace('new_tablespace').with({
1641
+ autovacuumVacuumCostLimit: 1,
1642
+ }).as(sql`SELECT 'asd'`),
1643
+ };
1644
+
1645
+ const to = {
1646
+ users,
1647
+ view: pgMaterializedView('some_view', { id: integer('id') }).with({
1648
+ autovacuumVacuumCostLimit: 1,
1649
+ }).as(sql`SELECT 'asd'`),
1650
+ };
1651
+
1652
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1653
+
1654
+ expect(statements.length).toBe(1);
1655
+ expect(statements[0]).toEqual({
1656
+ type: 'alter_view_alter_tablespace',
1657
+ name: 'some_view',
1658
+ schema: 'public',
1659
+ materialized: true,
1660
+ toTablespace: 'pg_default',
1661
+ });
1662
+
1663
+ expect(sqlStatements.length).toBe(1);
1664
+ expect(sqlStatements[0]).toBe(
1665
+ `ALTER MATERIALIZED VIEW "public"."some_view" SET TABLESPACE pg_default;`,
1666
+ );
1667
+ });
1668
+
1669
+ test('set existing - materialized', async () => {
1670
+ const users = pgTable('users', {
1671
+ id: integer('id').primaryKey().notNull(),
1672
+ });
1673
+
1674
+ const from = {
1675
+ users,
1676
+ view: pgMaterializedView('some_view', { id: integer('id') }).tablespace('new_tablespace').with({
1677
+ autovacuumVacuumCostLimit: 1,
1678
+ }).as(sql`SELECT 'asd'`),
1679
+ };
1680
+
1681
+ const to = {
1682
+ users,
1683
+ view: pgMaterializedView('new_some_view', { id: integer('id') }).with({
1684
+ autovacuumVacuumCostLimit: 1,
1685
+ autovacuumFreezeMinAge: 1,
1686
+ }).withNoData().existing(),
1687
+ };
1688
+
1689
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, ['public.some_view->public.new_some_view']);
1690
+
1691
+ expect(statements.length).toBe(0);
1692
+
1693
+ expect(sqlStatements.length).toBe(0);
1694
+ });
1695
+
1696
+ test('drop existing - materialized', async () => {
1697
+ const users = pgTable('users', {
1698
+ id: integer('id').primaryKey().notNull(),
1699
+ });
1700
+
1701
+ const from = {
1702
+ users,
1703
+ view: pgMaterializedView('some_view', { id: integer('id') }).tablespace('new_tablespace').with({
1704
+ autovacuumVacuumCostLimit: 1,
1705
+ }).existing(),
1706
+ };
1707
+
1708
+ const to = {
1709
+ users,
1710
+ view: pgMaterializedView('some_view', { id: integer('id') }).with({
1711
+ autovacuumVacuumCostLimit: 1,
1712
+ autovacuumFreezeMinAge: 1,
1713
+ }).withNoData().as(sql`SELECT 'asd'`),
1714
+ };
1715
+
1716
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1717
+
1718
+ expect(statements.length).toBe(2);
1719
+
1720
+ expect(sqlStatements.length).toBe(2);
1721
+ });
1722
+
1723
+ test('set existing', async () => {
1724
+ const users = pgTable('users', {
1725
+ id: integer('id').primaryKey().notNull(),
1726
+ });
1727
+
1728
+ const from = {
1729
+ users,
1730
+ view: pgView('some_view', { id: integer('id') }).with({
1731
+ checkOption: 'cascaded',
1732
+ }).as(sql`SELECT 'asd'`),
1733
+ };
1734
+
1735
+ const to = {
1736
+ users,
1737
+ view: pgView('new_some_view', { id: integer('id') }).with({
1738
+ checkOption: 'cascaded',
1739
+ securityBarrier: true,
1740
+ }).existing(),
1741
+ };
1742
+
1743
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, ['public.some_view->public.new_some_view']);
1744
+
1745
+ expect(statements.length).toBe(0);
1746
+
1747
+ expect(sqlStatements.length).toBe(0);
1748
+ });
1749
+
1750
+ test('alter using - materialize', async () => {
1751
+ const users = pgTable('users', {
1752
+ id: integer('id').primaryKey().notNull(),
1753
+ });
1754
+
1755
+ const from = {
1756
+ users,
1757
+ view: pgMaterializedView('some_view', { id: integer('id') }).tablespace('some_tablespace').using('some_using').with(
1758
+ {
1759
+ autovacuumVacuumCostLimit: 1,
1760
+ },
1761
+ ).as(sql`SELECT 'asd'`),
1762
+ };
1763
+
1764
+ const to = {
1765
+ users,
1766
+ view: pgMaterializedView('some_view', { id: integer('id') }).tablespace('some_tablespace').using('new_using').with({
1767
+ autovacuumVacuumCostLimit: 1,
1768
+ }).as(sql`SELECT 'asd'`),
1769
+ };
1770
+
1771
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1772
+
1773
+ expect(statements.length).toBe(1);
1774
+ expect(statements[0]).toEqual({
1775
+ type: 'alter_view_alter_using',
1776
+ name: 'some_view',
1777
+ schema: 'public',
1778
+ materialized: true,
1779
+ toUsing: 'new_using',
1780
+ });
1781
+
1782
+ expect(sqlStatements.length).toBe(1);
1783
+ expect(sqlStatements[0]).toBe(
1784
+ `ALTER MATERIALIZED VIEW "public"."some_view" SET ACCESS METHOD "new_using";`,
1785
+ );
1786
+ });
1787
+
1788
+ test('set using - materialize', async () => {
1789
+ const users = pgTable('users', {
1790
+ id: integer('id').primaryKey().notNull(),
1791
+ });
1792
+
1793
+ const from = {
1794
+ users,
1795
+ view: pgMaterializedView('some_view', { id: integer('id') }).with({
1796
+ autovacuumVacuumCostLimit: 1,
1797
+ }).as(sql`SELECT 'asd'`),
1798
+ };
1799
+
1800
+ const to = {
1801
+ users,
1802
+ view: pgMaterializedView('some_view', { id: integer('id') }).using('new_using').with({
1803
+ autovacuumVacuumCostLimit: 1,
1804
+ }).as(sql`SELECT 'asd'`),
1805
+ };
1806
+
1807
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1808
+
1809
+ expect(statements.length).toBe(1);
1810
+ expect(statements[0]).toEqual({
1811
+ type: 'alter_view_alter_using',
1812
+ name: 'some_view',
1813
+ schema: 'public',
1814
+ materialized: true,
1815
+ toUsing: 'new_using',
1816
+ });
1817
+
1818
+ expect(sqlStatements.length).toBe(1);
1819
+ expect(sqlStatements[0]).toBe(
1820
+ `ALTER MATERIALIZED VIEW "public"."some_view" SET ACCESS METHOD "new_using";`,
1821
+ );
1822
+ });
1823
+
1824
+ test('drop using - materialize', async () => {
1825
+ const users = pgTable('users', {
1826
+ id: integer('id').primaryKey().notNull(),
1827
+ });
1828
+
1829
+ const from = {
1830
+ users,
1831
+ view: pgMaterializedView('some_view', { id: integer('id') }).using('new_using').with({
1832
+ autovacuumVacuumCostLimit: 1,
1833
+ }).as(sql`SELECT 'asd'`),
1834
+ };
1835
+
1836
+ const to = {
1837
+ users,
1838
+ view: pgMaterializedView('some_view', { id: integer('id') }).with({
1839
+ autovacuumVacuumCostLimit: 1,
1840
+ }).as(sql`SELECT 'asd'`),
1841
+ };
1842
+
1843
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, []);
1844
+
1845
+ expect(statements.length).toBe(1);
1846
+ expect(statements[0]).toEqual({
1847
+ type: 'alter_view_alter_using',
1848
+ name: 'some_view',
1849
+ schema: 'public',
1850
+ materialized: true,
1851
+ toUsing: 'heap',
1852
+ });
1853
+
1854
+ expect(sqlStatements.length).toBe(1);
1855
+ expect(sqlStatements[0]).toBe(
1856
+ `ALTER MATERIALIZED VIEW "public"."some_view" SET ACCESS METHOD "heap";`,
1857
+ );
1858
+ });
1859
+
1860
+ test('rename view and alter view', async () => {
1861
+ const from = {
1862
+ view: pgView('some_view', { id: integer('id') }).as(sql`SELECT * FROM "users"`),
1863
+ };
1864
+
1865
+ const to = {
1866
+ view: pgView('new_some_view', { id: integer('id') }).with({ checkOption: 'cascaded' }).as(
1867
+ sql`SELECT * FROM "users"`,
1868
+ ),
1869
+ };
1870
+
1871
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, ['public.some_view->public.new_some_view']);
1872
+
1873
+ expect(statements.length).toBe(2);
1874
+ expect(statements[0]).toStrictEqual({
1875
+ type: 'rename_view',
1876
+ nameFrom: 'some_view',
1877
+ nameTo: 'new_some_view',
1878
+ schema: 'public',
1879
+ });
1880
+ expect(statements[1]).toStrictEqual({
1881
+ materialized: false,
1882
+ name: 'new_some_view',
1883
+ schema: 'public',
1884
+ type: 'alter_view_add_with_option',
1885
+ with: {
1886
+ checkOption: 'cascaded',
1887
+ },
1888
+ });
1889
+ expect(sqlStatements.length).toBe(2);
1890
+ expect(sqlStatements[0]).toBe(`ALTER VIEW "public"."some_view" RENAME TO "new_some_view";`);
1891
+ expect(sqlStatements[1]).toBe(`ALTER VIEW "public"."new_some_view" SET (check_option = cascaded);`);
1892
+ });
1893
+
1894
+ test('moved schema and alter view', async () => {
1895
+ const schema = pgSchema('my_schema');
1896
+ const from = {
1897
+ schema,
1898
+ view: pgView('some_view', { id: integer('id') }).as(sql`SELECT * FROM "users"`),
1899
+ };
1900
+
1901
+ const to = {
1902
+ schema,
1903
+ view: schema.view('some_view', { id: integer('id') }).with({ checkOption: 'cascaded' }).as(
1904
+ sql`SELECT * FROM "users"`,
1905
+ ),
1906
+ };
1907
+
1908
+ const { statements, sqlStatements } = await diffTestSchemas(from, to, ['public.some_view->my_schema.some_view']);
1909
+
1910
+ expect(statements.length).toBe(2);
1911
+ expect(statements[0]).toStrictEqual({
1912
+ fromSchema: 'public',
1913
+ name: 'some_view',
1914
+ toSchema: 'my_schema',
1915
+ type: 'alter_view_alter_schema',
1916
+ });
1917
+ expect(statements[1]).toStrictEqual({
1918
+ name: 'some_view',
1919
+ schema: 'my_schema',
1920
+ type: 'alter_view_add_with_option',
1921
+ materialized: false,
1922
+ with: {
1923
+ checkOption: 'cascaded',
1924
+ },
1925
+ });
1926
+ expect(sqlStatements.length).toBe(2);
1927
+ expect(sqlStatements[0]).toBe(`ALTER VIEW "public"."some_view" SET SCHEMA "my_schema";`);
1928
+ expect(sqlStatements[1]).toBe(`ALTER VIEW "my_schema"."some_view" SET (check_option = cascaded);`);
1929
+ });