@simplysm/orm-common 13.0.69 → 13.0.71

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 (204) hide show
  1. package/README.md +54 -1447
  2. package/dist/create-db-context.d.ts +10 -10
  3. package/dist/create-db-context.js +9 -9
  4. package/dist/create-db-context.js.map +1 -1
  5. package/dist/ddl/column-ddl.d.ts +4 -4
  6. package/dist/ddl/initialize.d.ts +17 -17
  7. package/dist/ddl/initialize.js +2 -2
  8. package/dist/ddl/initialize.js.map +1 -1
  9. package/dist/ddl/relation-ddl.d.ts +6 -6
  10. package/dist/ddl/schema-ddl.d.ts +4 -4
  11. package/dist/ddl/table-ddl.d.ts +24 -24
  12. package/dist/ddl/table-ddl.js +4 -4
  13. package/dist/ddl/table-ddl.js.map +1 -1
  14. package/dist/errors/db-transaction-error.d.ts +15 -15
  15. package/dist/errors/db-transaction-error.d.ts.map +1 -1
  16. package/dist/exec/executable.d.ts +23 -23
  17. package/dist/exec/executable.js +3 -3
  18. package/dist/exec/executable.js.map +1 -1
  19. package/dist/exec/queryable.d.ts +160 -160
  20. package/dist/exec/queryable.js +119 -119
  21. package/dist/exec/queryable.js.map +1 -1
  22. package/dist/exec/search-parser.d.ts +37 -37
  23. package/dist/exec/search-parser.d.ts.map +1 -1
  24. package/dist/expr/expr-unit.d.ts +4 -4
  25. package/dist/expr/expr.d.ts +257 -257
  26. package/dist/expr/expr.js +265 -265
  27. package/dist/expr/expr.js.map +1 -1
  28. package/dist/query-builder/base/expr-renderer-base.d.ts +9 -9
  29. package/dist/query-builder/base/expr-renderer-base.js +2 -2
  30. package/dist/query-builder/base/expr-renderer-base.js.map +1 -1
  31. package/dist/query-builder/base/query-builder-base.d.ts +26 -26
  32. package/dist/query-builder/base/query-builder-base.d.ts.map +1 -1
  33. package/dist/query-builder/base/query-builder-base.js +22 -22
  34. package/dist/query-builder/base/query-builder-base.js.map +1 -1
  35. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +4 -4
  36. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
  37. package/dist/query-builder/mssql/mssql-expr-renderer.js +18 -18
  38. package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
  39. package/dist/query-builder/mssql/mssql-query-builder.d.ts +2 -2
  40. package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
  41. package/dist/query-builder/mssql/mssql-query-builder.js +11 -11
  42. package/dist/query-builder/mssql/mssql-query-builder.js.map +1 -1
  43. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +4 -4
  44. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
  45. package/dist/query-builder/mysql/mysql-expr-renderer.js +17 -17
  46. package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
  47. package/dist/query-builder/mysql/mysql-query-builder.d.ts +8 -8
  48. package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
  49. package/dist/query-builder/mysql/mysql-query-builder.js +5 -5
  50. package/dist/query-builder/mysql/mysql-query-builder.js.map +1 -1
  51. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +4 -4
  52. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
  53. package/dist/query-builder/postgresql/postgresql-expr-renderer.js +17 -17
  54. package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
  55. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +5 -5
  56. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
  57. package/dist/query-builder/postgresql/postgresql-query-builder.js +8 -8
  58. package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
  59. package/dist/query-builder/query-builder.d.ts +1 -1
  60. package/dist/schema/factory/column-builder.d.ts +79 -79
  61. package/dist/schema/factory/column-builder.js +42 -42
  62. package/dist/schema/factory/index-builder.d.ts +39 -39
  63. package/dist/schema/factory/index-builder.js +26 -26
  64. package/dist/schema/factory/relation-builder.d.ts +99 -99
  65. package/dist/schema/factory/relation-builder.d.ts.map +1 -1
  66. package/dist/schema/factory/relation-builder.js +38 -38
  67. package/dist/schema/procedure-builder.d.ts +49 -49
  68. package/dist/schema/procedure-builder.d.ts.map +1 -1
  69. package/dist/schema/procedure-builder.js +33 -33
  70. package/dist/schema/table-builder.d.ts +59 -59
  71. package/dist/schema/table-builder.d.ts.map +1 -1
  72. package/dist/schema/table-builder.js +43 -43
  73. package/dist/schema/view-builder.d.ts +49 -49
  74. package/dist/schema/view-builder.d.ts.map +1 -1
  75. package/dist/schema/view-builder.js +32 -32
  76. package/dist/types/column.d.ts +22 -22
  77. package/dist/types/column.js +1 -1
  78. package/dist/types/column.js.map +1 -1
  79. package/dist/types/db.d.ts +40 -40
  80. package/dist/types/expr.d.ts +59 -59
  81. package/dist/types/expr.d.ts.map +1 -1
  82. package/dist/types/query-def.d.ts +44 -44
  83. package/dist/types/query-def.d.ts.map +1 -1
  84. package/dist/utils/result-parser.d.ts +11 -11
  85. package/dist/utils/result-parser.js +3 -3
  86. package/dist/utils/result-parser.js.map +1 -1
  87. package/package.json +5 -5
  88. package/src/create-db-context.ts +20 -20
  89. package/src/ddl/column-ddl.ts +4 -4
  90. package/src/ddl/initialize.ts +259 -259
  91. package/src/ddl/relation-ddl.ts +89 -89
  92. package/src/ddl/schema-ddl.ts +4 -4
  93. package/src/ddl/table-ddl.ts +189 -189
  94. package/src/errors/db-transaction-error.ts +13 -13
  95. package/src/exec/executable.ts +25 -25
  96. package/src/exec/queryable.ts +2033 -2033
  97. package/src/exec/search-parser.ts +57 -57
  98. package/src/expr/expr-unit.ts +4 -4
  99. package/src/expr/expr.ts +2140 -2140
  100. package/src/query-builder/base/expr-renderer-base.ts +237 -237
  101. package/src/query-builder/base/query-builder-base.ts +213 -213
  102. package/src/query-builder/mssql/mssql-expr-renderer.ts +607 -607
  103. package/src/query-builder/mssql/mssql-query-builder.ts +650 -650
  104. package/src/query-builder/mysql/mysql-expr-renderer.ts +613 -613
  105. package/src/query-builder/mysql/mysql-query-builder.ts +759 -759
  106. package/src/query-builder/postgresql/postgresql-expr-renderer.ts +611 -611
  107. package/src/query-builder/postgresql/postgresql-query-builder.ts +686 -686
  108. package/src/query-builder/query-builder.ts +19 -19
  109. package/src/schema/factory/column-builder.ts +423 -423
  110. package/src/schema/factory/index-builder.ts +164 -164
  111. package/src/schema/factory/relation-builder.ts +453 -453
  112. package/src/schema/procedure-builder.ts +232 -232
  113. package/src/schema/table-builder.ts +319 -319
  114. package/src/schema/view-builder.ts +221 -221
  115. package/src/types/column.ts +188 -188
  116. package/src/types/db.ts +208 -208
  117. package/src/types/expr.ts +697 -697
  118. package/src/types/query-def.ts +513 -513
  119. package/src/utils/result-parser.ts +458 -458
  120. package/tests/db-context/create-db-context.spec.ts +224 -0
  121. package/tests/db-context/define-db-context.spec.ts +68 -0
  122. package/tests/ddl/basic.expected.ts +341 -0
  123. package/tests/ddl/basic.spec.ts +714 -0
  124. package/tests/ddl/column-builder.expected.ts +310 -0
  125. package/tests/ddl/column-builder.spec.ts +637 -0
  126. package/tests/ddl/index-builder.expected.ts +38 -0
  127. package/tests/ddl/index-builder.spec.ts +202 -0
  128. package/tests/ddl/procedure-builder.expected.ts +52 -0
  129. package/tests/ddl/procedure-builder.spec.ts +234 -0
  130. package/tests/ddl/relation-builder.expected.ts +36 -0
  131. package/tests/ddl/relation-builder.spec.ts +372 -0
  132. package/tests/ddl/table-builder.expected.ts +113 -0
  133. package/tests/ddl/table-builder.spec.ts +433 -0
  134. package/tests/ddl/view-builder.expected.ts +38 -0
  135. package/tests/ddl/view-builder.spec.ts +176 -0
  136. package/tests/dml/delete.expected.ts +96 -0
  137. package/tests/dml/delete.spec.ts +160 -0
  138. package/tests/dml/insert.expected.ts +192 -0
  139. package/tests/dml/insert.spec.ts +288 -0
  140. package/tests/dml/update.expected.ts +176 -0
  141. package/tests/dml/update.spec.ts +318 -0
  142. package/tests/dml/upsert.expected.ts +215 -0
  143. package/tests/dml/upsert.spec.ts +242 -0
  144. package/tests/errors/queryable-errors.spec.ts +177 -0
  145. package/tests/escape.spec.ts +100 -0
  146. package/tests/examples/pivot.expected.ts +211 -0
  147. package/tests/examples/pivot.spec.ts +533 -0
  148. package/tests/examples/sampling.expected.ts +69 -0
  149. package/tests/examples/sampling.spec.ts +105 -0
  150. package/tests/examples/unpivot.expected.ts +120 -0
  151. package/tests/examples/unpivot.spec.ts +226 -0
  152. package/tests/exec/search-parser.spec.ts +283 -0
  153. package/tests/executable/basic.expected.ts +18 -0
  154. package/tests/executable/basic.spec.ts +54 -0
  155. package/tests/expr/comparison.expected.ts +282 -0
  156. package/tests/expr/comparison.spec.ts +400 -0
  157. package/tests/expr/conditional.expected.ts +134 -0
  158. package/tests/expr/conditional.spec.ts +276 -0
  159. package/tests/expr/date.expected.ts +332 -0
  160. package/tests/expr/date.spec.ts +526 -0
  161. package/tests/expr/math.expected.ts +62 -0
  162. package/tests/expr/math.spec.ts +106 -0
  163. package/tests/expr/string.expected.ts +218 -0
  164. package/tests/expr/string.spec.ts +356 -0
  165. package/tests/expr/utility.expected.ts +147 -0
  166. package/tests/expr/utility.spec.ts +182 -0
  167. package/tests/select/basic.expected.ts +322 -0
  168. package/tests/select/basic.spec.ts +502 -0
  169. package/tests/select/filter.expected.ts +357 -0
  170. package/tests/select/filter.spec.ts +1068 -0
  171. package/tests/select/group.expected.ts +169 -0
  172. package/tests/select/group.spec.ts +244 -0
  173. package/tests/select/join.expected.ts +582 -0
  174. package/tests/select/join.spec.ts +805 -0
  175. package/tests/select/order.expected.ts +150 -0
  176. package/tests/select/order.spec.ts +189 -0
  177. package/tests/select/recursive-cte.expected.ts +244 -0
  178. package/tests/select/recursive-cte.spec.ts +514 -0
  179. package/tests/select/result-meta.spec.ts +270 -0
  180. package/tests/select/subquery.expected.ts +363 -0
  181. package/tests/select/subquery.spec.ts +537 -0
  182. package/tests/select/view.expected.ts +155 -0
  183. package/tests/select/view.spec.ts +235 -0
  184. package/tests/select/window.expected.ts +345 -0
  185. package/tests/select/window.spec.ts +618 -0
  186. package/tests/setup/MockExecutor.ts +18 -0
  187. package/tests/setup/TestDbContext.ts +59 -0
  188. package/tests/setup/models/Company.ts +13 -0
  189. package/tests/setup/models/Employee.ts +10 -0
  190. package/tests/setup/models/MonthlySales.ts +11 -0
  191. package/tests/setup/models/Post.ts +16 -0
  192. package/tests/setup/models/Sales.ts +10 -0
  193. package/tests/setup/models/User.ts +19 -0
  194. package/tests/setup/procedure/GetAllUsers.ts +9 -0
  195. package/tests/setup/procedure/GetUserById.ts +12 -0
  196. package/tests/setup/test-utils.ts +72 -0
  197. package/tests/setup/views/ActiveUsers.ts +8 -0
  198. package/tests/setup/views/UserSummary.ts +11 -0
  199. package/tests/types/nullable-queryable-record.spec.ts +145 -0
  200. package/tests/utils/result-parser-perf.spec.ts +210 -0
  201. package/tests/utils/result-parser.spec.ts +701 -0
  202. package/docs/expressions.md +0 -172
  203. package/docs/queries.md +0 -444
  204. package/docs/schema.md +0 -245
@@ -0,0 +1,224 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { defineDbContext } from "../../src/define-db-context";
3
+ import { createDbContext } from "../../src/create-db-context";
4
+ import { User } from "../setup/models/User";
5
+ import { Post } from "../setup/models/Post";
6
+ import { MockExecutor } from "../setup/MockExecutor";
7
+ import "../setup/test-utils";
8
+
9
+ const TestDb = defineDbContext({
10
+ tables: { user: User, post: Post },
11
+ });
12
+
13
+ describe("createDbContext", () => {
14
+ it("creates instance with queryable accessors", () => {
15
+ const db = createDbContext(TestDb, new MockExecutor(), {
16
+ database: "TestDb",
17
+ schema: "TestSchema",
18
+ });
19
+
20
+ expect(db.database).toBe("TestDb");
21
+ expect(db.schema).toBe("TestSchema");
22
+ expect(db.status).toBe("ready");
23
+ expect(typeof db.user).toBe("function");
24
+ expect(typeof db.post).toBe("function");
25
+ });
26
+
27
+ it("queryable functions create correct QueryDef", () => {
28
+ const db = createDbContext(TestDb, new MockExecutor(), {
29
+ database: "TestDb",
30
+ schema: "TestSchema",
31
+ });
32
+
33
+ const def = db.user().getSelectQueryDef();
34
+ expect(def).toEqual({
35
+ type: "select",
36
+ as: "T1",
37
+ from: { database: "TestDb", schema: "TestSchema", name: "User" },
38
+ });
39
+ });
40
+
41
+ it("alias counter increments between queryable calls", () => {
42
+ const db = createDbContext(TestDb, new MockExecutor(), {
43
+ database: "TestDb",
44
+ schema: "TestSchema",
45
+ });
46
+
47
+ const userDef = db.user().getSelectQueryDef();
48
+ const postDef = db.post().getSelectQueryDef();
49
+ expect(userDef.as).toBe("T1");
50
+ expect(postDef.as).toBe("T2");
51
+ });
52
+
53
+ it("DDL methods exist on instance", () => {
54
+ const db = createDbContext(TestDb, new MockExecutor(), {
55
+ database: "TestDb",
56
+ });
57
+
58
+ // QueryDef generators
59
+ expect(typeof db.getCreateTableQueryDef).toBe("function");
60
+ expect(typeof db.getAddColumnQueryDef).toBe("function");
61
+ expect(typeof db.getClearSchemaQueryDef).toBe("function");
62
+
63
+ // Execution methods
64
+ expect(typeof db.createTable).toBe("function");
65
+ expect(typeof db.addColumn).toBe("function");
66
+ });
67
+
68
+ it("DDL QueryDef generators produce correct output", () => {
69
+ const db = createDbContext(TestDb, new MockExecutor(), {
70
+ database: "TestDb",
71
+ schema: "TestSchema",
72
+ });
73
+
74
+ const clearDef = db.getClearSchemaQueryDef({ database: "TestDb", schema: "TestSchema" });
75
+ expect(clearDef).toEqual({
76
+ type: "clearSchema",
77
+ database: "TestDb",
78
+ schema: "TestSchema",
79
+ });
80
+ });
81
+
82
+ it("connect/trans methods exist", () => {
83
+ const db = createDbContext(TestDb, new MockExecutor(), {
84
+ database: "TestDb",
85
+ });
86
+
87
+ expect(typeof db.connect).toBe("function");
88
+ expect(typeof db.connectWithoutTransaction).toBe("function");
89
+ expect(typeof db.trans).toBe("function");
90
+ });
91
+
92
+ it("connect manages status lifecycle", async () => {
93
+ const db = createDbContext(TestDb, new MockExecutor(), {
94
+ database: "TestDb",
95
+ });
96
+
97
+ expect(db.status).toBe("ready");
98
+ await db.connect(async () => {
99
+ await Promise.resolve();
100
+ expect(db.status).toBe("transact");
101
+ });
102
+ expect(db.status).toBe("ready");
103
+ });
104
+
105
+ it("connectWithoutTransaction manages status lifecycle", async () => {
106
+ const db = createDbContext(TestDb, new MockExecutor(), {
107
+ database: "TestDb",
108
+ });
109
+
110
+ expect(db.status).toBe("ready");
111
+ await db.connectWithoutTransaction(async () => {
112
+ await Promise.resolve();
113
+ expect(db.status).toBe("connect");
114
+ });
115
+ expect(db.status).toBe("ready");
116
+ });
117
+
118
+ it("trans manages status lifecycle within connectWithoutTransaction", async () => {
119
+ const db = createDbContext(TestDb, new MockExecutor(), {
120
+ database: "TestDb",
121
+ });
122
+
123
+ await db.connectWithoutTransaction(async () => {
124
+ await Promise.resolve();
125
+ expect(db.status).toBe("connect");
126
+ await db.trans(async () => {
127
+ await Promise.resolve();
128
+ expect(db.status).toBe("transact");
129
+ });
130
+ expect(db.status).toBe("connect");
131
+ });
132
+ expect(db.status).toBe("ready");
133
+ });
134
+
135
+ it("connect resets alias counter", async () => {
136
+ const db = createDbContext(TestDb, new MockExecutor(), {
137
+ database: "TestDb",
138
+ });
139
+
140
+ // Use some aliases
141
+ db.getNextAlias(); // T1
142
+ db.getNextAlias(); // T2
143
+
144
+ await db.connect(async () => {
145
+ await Promise.resolve();
146
+ // After connect, alias counter should be reset
147
+ const userDef = db.user().getSelectQueryDef();
148
+ expect(userDef.as).toBe("T1");
149
+ });
150
+ });
151
+
152
+ it("connect rolls back and rethrows on callback error", async () => {
153
+ const db = createDbContext(TestDb, new MockExecutor(), {
154
+ database: "TestDb",
155
+ });
156
+
157
+ const testError = new Error("test error");
158
+ await expect(
159
+ db.connect(async () => {
160
+ await Promise.resolve();
161
+ throw testError;
162
+ }),
163
+ ).rejects.toThrow("test error");
164
+
165
+ expect(db.status).toBe("ready");
166
+ });
167
+
168
+ it("connectWithoutTransaction rethrows on callback error", async () => {
169
+ const db = createDbContext(TestDb, new MockExecutor(), {
170
+ database: "TestDb",
171
+ });
172
+
173
+ const testError = new Error("test error");
174
+ await expect(
175
+ db.connectWithoutTransaction(async () => {
176
+ await Promise.resolve();
177
+ throw testError;
178
+ }),
179
+ ).rejects.toThrow("test error");
180
+
181
+ expect(db.status).toBe("ready");
182
+ });
183
+
184
+ it("trans throws when already in transaction state", async () => {
185
+ const db = createDbContext(TestDb, new MockExecutor(), {
186
+ database: "TestDb",
187
+ });
188
+
189
+ await db.connect(async () => {
190
+ // Already in transact state via connect
191
+ await expect(db.trans(async () => {})).rejects.toThrow("Already in TRANSACTION state.");
192
+ });
193
+ });
194
+
195
+ it("_migration accessor exists", () => {
196
+ const db = createDbContext(TestDb, new MockExecutor(), {
197
+ database: "TestDb",
198
+ });
199
+
200
+ expect(typeof db._migration).toBe("function");
201
+ });
202
+
203
+ it("initialize method exists", () => {
204
+ const db = createDbContext(TestDb, new MockExecutor(), {
205
+ database: "TestDb",
206
+ });
207
+
208
+ expect(typeof db.initialize).toBe("function");
209
+ });
210
+
211
+ it("getQueryDefObjectName resolves table with defaults", () => {
212
+ const db = createDbContext(TestDb, new MockExecutor(), {
213
+ database: "TestDb",
214
+ schema: "TestSchema",
215
+ });
216
+
217
+ const objName = db.getQueryDefObjectName(User);
218
+ expect(objName).toEqual({
219
+ database: "TestDb",
220
+ schema: "TestSchema",
221
+ name: "User",
222
+ });
223
+ });
224
+ });
@@ -0,0 +1,68 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import type { DbContextBase, DbContextDef } from "../../src/types/db-context-def";
3
+ import { defineDbContext } from "../../src/define-db-context";
4
+ import { User } from "../setup/models/User";
5
+ import { Post } from "../setup/models/Post";
6
+ import { ActiveUsers } from "../setup/views/ActiveUsers";
7
+
8
+ describe("DbContext Types", () => {
9
+ it("DbContextBase interface has required members", () => {
10
+ // Type-level test: verify the interface exists with correct shape
11
+ const base: DbContextBase = {
12
+ status: "ready",
13
+ database: "test",
14
+ schema: undefined,
15
+ getNextAlias: () => "T1",
16
+ resetAliasCounter: () => {},
17
+ executeDefs: () => Promise.resolve([[]]),
18
+ getQueryDefObjectName: () => ({ database: "test", name: "test" }),
19
+ switchFk: () => Promise.resolve(),
20
+ };
21
+ expect(base.status).toBe("ready");
22
+ expect(base.getNextAlias()).toBe("T1");
23
+ });
24
+
25
+ it("DbContextDef has meta property", () => {
26
+ const def: DbContextDef<{}, {}> = {
27
+ meta: {
28
+ tables: {},
29
+ views: {},
30
+ procedures: {},
31
+ migrations: [],
32
+ },
33
+ };
34
+ expect(def.meta.tables).toEqual({});
35
+ expect(def.meta.migrations).toEqual([]);
36
+ });
37
+ });
38
+
39
+ describe("defineDbContext", () => {
40
+ it("creates a DbContextDef with tables", () => {
41
+ const MyDb = defineDbContext({
42
+ tables: { user: User, post: Post },
43
+ });
44
+
45
+ expect(MyDb.meta.tables.user).toBe(User);
46
+ expect(MyDb.meta.tables.post).toBe(Post);
47
+ expect(MyDb.meta.migrations).toEqual([]);
48
+ });
49
+
50
+ it("creates a DbContextDef with views", () => {
51
+ const MyDb = defineDbContext({
52
+ tables: { user: User },
53
+ views: { activeUsers: ActiveUsers },
54
+ });
55
+
56
+ expect(MyDb.meta.views.activeUsers).toBe(ActiveUsers);
57
+ });
58
+
59
+ it("creates a DbContextDef with migrations", () => {
60
+ const migrations = [{ name: "test", up: async () => {} }];
61
+ const MyDb = defineDbContext({
62
+ tables: { user: User },
63
+ migrations,
64
+ });
65
+
66
+ expect(MyDb.meta.migrations).toBe(migrations);
67
+ });
68
+ });
@@ -0,0 +1,341 @@
1
+ import { mysql, pgsql, tsql } from "@simplysm/core-common";
2
+ import type { ExpectedSql } from "../setup/test-utils";
3
+
4
+ //#region ========== Database ==========
5
+
6
+ export const clearSchema: ExpectedSql = {
7
+ mysql: mysql`
8
+ SET FOREIGN_KEY_CHECKS = 0;
9
+ SET @tables = NULL;
10
+ SELECT GROUP_CONCAT(table_name) INTO @tables FROM information_schema.tables WHERE table_schema = 'TestDb';
11
+ SET @drop_stmt = IF(@tables IS NULL, 'SELECT 1', CONCAT('DROP TABLE IF EXISTS ', @tables));
12
+ PREPARE stmt FROM @drop_stmt;
13
+ EXECUTE stmt;
14
+ DEALLOCATE PREPARE stmt;
15
+ SET FOREIGN_KEY_CHECKS = 1
16
+ `,
17
+ mssql: tsql`
18
+ DECLARE @sql NVARCHAR(MAX);
19
+ SET @sql = N'';
20
+
21
+ -- FK constraint Delete
22
+ SELECT @sql = @sql + N'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.' + QUOTENAME(OBJECT_NAME(parent_object_id)) + N' DROP CONSTRAINT ' + QUOTENAME(name) + N';' + CHAR(13)
23
+ FROM [TestDb].sys.foreign_keys
24
+ WHERE OBJECT_SCHEMA_NAME(parent_object_id) = 'TestSchema';
25
+
26
+ -- Drop table
27
+ SELECT @sql = @sql + N'DROP TABLE ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name) + N';' + CHAR(13)
28
+ FROM [TestDb].sys.tables
29
+ WHERE SCHEMA_NAME(schema_id) = 'TestSchema';
30
+
31
+ -- Drop view
32
+ SELECT @sql = @sql + N'DROP VIEW ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name) + N';' + CHAR(13)
33
+ FROM [TestDb].sys.views
34
+ WHERE schema_id = SCHEMA_ID('TestSchema');
35
+
36
+ -- Procedure Delete
37
+ SELECT @sql = @sql + N'DROP PROCEDURE ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name) + N';' + CHAR(13)
38
+ FROM [TestDb].sys.procedures
39
+ WHERE SCHEMA_NAME(schema_id) = 'TestSchema';
40
+
41
+ EXEC sp_executesql @sql;
42
+ `,
43
+ postgresql: pgsql`
44
+ DO $$
45
+ DECLARE
46
+ r RECORD;
47
+ BEGIN
48
+ -- FK constraint Delete
49
+ FOR r IN (SELECT conname, conrelid::regclass AS tablename
50
+ FROM pg_constraint
51
+ WHERE contype = 'f' AND connamespace = 'TestSchema'::regnamespace)
52
+ LOOP
53
+ EXECUTE 'ALTER TABLE ' || r.tablename || ' DROP CONSTRAINT ' || quote_ident(r.conname);
54
+ END LOOP;
55
+
56
+ -- Drop table
57
+ FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = 'TestSchema')
58
+ LOOP
59
+ EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE';
60
+ END LOOP;
61
+
62
+ -- Drop view
63
+ FOR r IN (SELECT viewname FROM pg_views WHERE schemaname = 'TestSchema')
64
+ LOOP
65
+ EXECUTE 'DROP VIEW IF EXISTS ' || quote_ident(r.viewname) || ' CASCADE';
66
+ END LOOP;
67
+
68
+ -- function Delete
69
+ FOR r IN (SELECT proname, pg_get_function_identity_arguments(oid) AS args
70
+ FROM pg_proc WHERE pronamespace = 'TestSchema'::regnamespace)
71
+ LOOP
72
+ EXECUTE 'DROP FUNCTION IF EXISTS ' || quote_ident(r.proname) || '(' || r.args || ') CASCADE';
73
+ END LOOP;
74
+ END $$
75
+ `,
76
+ };
77
+
78
+ export const schemaExists: ExpectedSql = {
79
+ mysql: mysql`SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = 'TestDb'`,
80
+ mssql: tsql`
81
+ DECLARE @result NVARCHAR(MAX) = NULL;
82
+ IF EXISTS (SELECT 1 FROM sys.databases WHERE name = 'TestDb')
83
+ BEGIN
84
+ DECLARE @sql NVARCHAR(MAX) = N'SELECT @result = name FROM ' + QUOTENAME('TestDb') + N'.sys.schemas WHERE name = ''TestSchema''';
85
+ EXEC sp_executesql @sql, N'@result NVARCHAR(MAX) OUTPUT', @result OUTPUT;
86
+ END
87
+ SELECT @result AS name WHERE @result IS NOT NULL
88
+ `,
89
+ postgresql: pgsql`SELECT nspname FROM pg_namespace WHERE nspname = 'TestSchema'`,
90
+ };
91
+
92
+ //#endregion
93
+
94
+ //#region ========== Table ==========
95
+
96
+ export const createTable: ExpectedSql = {
97
+ mysql: mysql`
98
+ CREATE TABLE \`TestDb\`.\`User\` (
99
+ \`id\` BIGINT NOT NULL AUTO_INCREMENT,
100
+ \`name\` VARCHAR(100) NOT NULL,
101
+ \`email\` VARCHAR(200) NULL,
102
+ \`age\` INT NULL,
103
+ \`isActive\` BOOLEAN NOT NULL DEFAULT TRUE,
104
+ \`companyId\` BIGINT NULL,
105
+ \`createdAt\` DATETIME NOT NULL,
106
+ CONSTRAINT \`PK_User\` PRIMARY KEY (\`id\`)
107
+ )
108
+ `,
109
+ mssql: tsql`
110
+ CREATE TABLE [TestDb].[TestSchema].[User] (
111
+ [id] BIGINT NOT NULL IDENTITY(1,1),
112
+ [name] NVARCHAR(100) NOT NULL,
113
+ [email] NVARCHAR(200) NULL,
114
+ [age] INT NULL,
115
+ [isActive] BIT NOT NULL DEFAULT 1,
116
+ [companyId] BIGINT NULL,
117
+ [createdAt] DATETIME2 NOT NULL,
118
+ CONSTRAINT [PK_User] PRIMARY KEY ([id])
119
+ )
120
+ `,
121
+ postgresql: pgsql`
122
+ CREATE TABLE "TestSchema"."User" (
123
+ "id" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY,
124
+ "name" VARCHAR(100) NOT NULL,
125
+ "email" VARCHAR(200) NULL,
126
+ "age" INTEGER NULL,
127
+ "isActive" BOOLEAN NOT NULL DEFAULT TRUE,
128
+ "companyId" BIGINT NULL,
129
+ "createdAt" TIMESTAMP NOT NULL,
130
+ CONSTRAINT "PK_User" PRIMARY KEY ("id")
131
+ )
132
+ `,
133
+ };
134
+
135
+ export const truncate: ExpectedSql = {
136
+ mysql: mysql`TRUNCATE TABLE \`TestDb\`.\`User\``,
137
+ mssql: tsql`TRUNCATE TABLE [TestDb].[TestSchema].[User]`,
138
+ postgresql: pgsql`TRUNCATE TABLE "TestSchema"."User" RESTART IDENTITY`,
139
+ };
140
+
141
+ export const switchFkOn: ExpectedSql = {
142
+ mysql: mysql`SET FOREIGN_KEY_CHECKS = 1`,
143
+ mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[User] WITH CHECK CHECK CONSTRAINT ALL`,
144
+ postgresql: pgsql`ALTER TABLE "TestSchema"."User" ENABLE TRIGGER ALL`,
145
+ };
146
+
147
+ export const switchFkOff: ExpectedSql = {
148
+ mysql: mysql`SET FOREIGN_KEY_CHECKS = 0`,
149
+ mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[User] NOCHECK CONSTRAINT ALL`,
150
+ postgresql: pgsql`ALTER TABLE "TestSchema"."User" DISABLE TRIGGER ALL`,
151
+ };
152
+
153
+ export const dropTable: ExpectedSql = {
154
+ mysql: mysql`DROP TABLE \`TestDb\`.\`User\``,
155
+ mssql: tsql`DROP TABLE [TestDb].[TestSchema].[User]`,
156
+ postgresql: pgsql`DROP TABLE "TestSchema"."User"`,
157
+ };
158
+
159
+ export const renameTable: ExpectedSql = {
160
+ mysql: mysql`RENAME TABLE \`TestDb\`.\`User\` TO \`Member\``,
161
+ mssql: tsql`EXEC sp_rename '[TestDb].[TestSchema].[User]', 'Member'`,
162
+ postgresql: pgsql`ALTER TABLE "TestSchema"."User" RENAME TO "Member"`,
163
+ };
164
+
165
+ //#endregion
166
+
167
+ //#region ========== Column ==========
168
+
169
+ export const addColumn: ExpectedSql = {
170
+ mysql: mysql`ALTER TABLE \`TestDb\`.\`User\` ADD COLUMN \`nickname\` VARCHAR(50) NULL`,
171
+ mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[User] ADD [nickname] NVARCHAR(50) NULL`,
172
+ postgresql: pgsql`ALTER TABLE "TestSchema"."User" ADD COLUMN "nickname" VARCHAR(50) NULL`,
173
+ };
174
+
175
+ export const addColumnWithDefault: ExpectedSql = {
176
+ mysql: mysql`ALTER TABLE \`TestDb\`.\`User\` ADD COLUMN \`score\` INT NOT NULL DEFAULT 0`,
177
+ mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[User] ADD [score] INT NOT NULL DEFAULT 0`,
178
+ postgresql: pgsql`ALTER TABLE "TestSchema"."User" ADD COLUMN "score" INTEGER NOT NULL DEFAULT 0`,
179
+ };
180
+
181
+ export const addColumnWithAutoIncrement: ExpectedSql = {
182
+ mysql: mysql`ALTER TABLE \`TestDb\`.\`User\` ADD COLUMN \`seq\` BIGINT NOT NULL AUTO_INCREMENT`,
183
+ mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[User] ADD [seq] BIGINT NOT NULL IDENTITY(1,1)`,
184
+ postgresql: pgsql`ALTER TABLE "TestSchema"."User" ADD COLUMN "seq" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY`,
185
+ };
186
+
187
+ export const dropColumn: ExpectedSql = {
188
+ mysql: mysql`ALTER TABLE \`TestDb\`.\`User\` DROP COLUMN \`email\``,
189
+ mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[User] DROP COLUMN [email]`,
190
+ postgresql: pgsql`ALTER TABLE "TestSchema"."User" DROP COLUMN "email"`,
191
+ };
192
+
193
+ export const modifyColumn: ExpectedSql = {
194
+ mysql: mysql`ALTER TABLE \`TestDb\`.\`User\` MODIFY COLUMN \`name\` VARCHAR(200) NULL`,
195
+ mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[User] ALTER COLUMN [name] NVARCHAR(200) NULL`,
196
+ postgresql: pgsql`ALTER TABLE "TestSchema"."User" ALTER COLUMN "name" TYPE VARCHAR(200), ALTER COLUMN "name" DROP NOT NULL`,
197
+ };
198
+
199
+ export const modifyColumnTypeAndDefault: ExpectedSql = {
200
+ mysql: mysql`ALTER TABLE \`TestDb\`.\`User\` MODIFY COLUMN \`score\` INT NOT NULL DEFAULT 100`,
201
+ mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[User] ALTER COLUMN [score] INT NOT NULL`,
202
+ postgresql: pgsql`ALTER TABLE "TestSchema"."User" ALTER COLUMN "score" TYPE INTEGER, ALTER COLUMN "score" DROP NOT NULL, ALTER COLUMN "score" SET DEFAULT 100`,
203
+ };
204
+
205
+ export const renameColumn: ExpectedSql = {
206
+ mysql: mysql`ALTER TABLE \`TestDb\`.\`User\` RENAME COLUMN \`name\` TO \`fullName\``,
207
+ mssql: tsql`EXEC sp_rename '[TestDb].[TestSchema].[User].name', 'fullName', 'COLUMN'`,
208
+ postgresql: pgsql`ALTER TABLE "TestSchema"."User" RENAME COLUMN "name" TO "fullName"`,
209
+ };
210
+
211
+ //#endregion
212
+
213
+ //#region ========== Primary Key ==========
214
+
215
+ export const dropPk: ExpectedSql = {
216
+ mysql: mysql`ALTER TABLE \`TestDb\`.\`User\` DROP PRIMARY KEY`,
217
+ mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[User] DROP CONSTRAINT [PK_User]`,
218
+ postgresql: pgsql`ALTER TABLE "TestSchema"."User" DROP CONSTRAINT "PK_User"`,
219
+ };
220
+
221
+ export const addPk: ExpectedSql = {
222
+ mysql: mysql`ALTER TABLE \`TestDb\`.\`User\` ADD PRIMARY KEY (\`id\`)`,
223
+ mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[User] ADD CONSTRAINT [PK_User] PRIMARY KEY ([id])`,
224
+ postgresql: pgsql`ALTER TABLE "TestSchema"."User" ADD CONSTRAINT "PK_User" PRIMARY KEY ("id")`,
225
+ };
226
+
227
+ export const addPkComposite: ExpectedSql = {
228
+ mysql: mysql`ALTER TABLE \`TestDb\`.\`UserRole\` ADD PRIMARY KEY (\`userId\`, \`roleId\`)`,
229
+ mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[UserRole] ADD CONSTRAINT [PK_UserRole] PRIMARY KEY ([userId], [roleId])`,
230
+ postgresql: pgsql`ALTER TABLE "TestSchema"."UserRole" ADD CONSTRAINT "PK_UserRole" PRIMARY KEY ("userId", "roleId")`,
231
+ };
232
+
233
+ //#endregion
234
+
235
+ //#region ========== Foreign Key / Index ==========
236
+
237
+ export const addFk: ExpectedSql = {
238
+ mysql: mysql`
239
+ ALTER TABLE \`TestDb\`.\`Post\` ADD CONSTRAINT \`FK_Post_user\`
240
+ FOREIGN KEY (\`userId\`) REFERENCES \`TestDb\`.\`User\` (\`id\`)
241
+ `,
242
+ mssql: tsql`
243
+ ALTER TABLE [TestDb].[TestSchema].[Post] ADD CONSTRAINT [FK_Post_user]
244
+ FOREIGN KEY ([userId]) REFERENCES [TestDb].[TestSchema].[User] ([id]);
245
+ CREATE INDEX [IDX_Post_Post_user] ON [TestDb].[TestSchema].[Post] ([userId]);
246
+ `,
247
+ postgresql: pgsql`
248
+ ALTER TABLE "TestSchema"."Post" ADD CONSTRAINT "FK_Post_user"
249
+ FOREIGN KEY ("userId") REFERENCES "TestSchema"."User" ("id");
250
+ CREATE INDEX "IDX_Post_Post_user" ON "TestSchema"."Post" ("userId");
251
+ `,
252
+ };
253
+
254
+ export const dropFk: ExpectedSql = {
255
+ mysql: mysql`ALTER TABLE \`TestDb\`.\`Post\` DROP FOREIGN KEY \`FK_Post_user\``,
256
+ mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[Post] DROP CONSTRAINT [FK_Post_user]`,
257
+ postgresql: pgsql`ALTER TABLE "TestSchema"."Post" DROP CONSTRAINT "FK_Post_user"`,
258
+ };
259
+
260
+ export const addIdx: ExpectedSql = {
261
+ mysql: mysql`CREATE UNIQUE INDEX \`IDX_User_email\` ON \`TestDb\`.\`User\` (\`email\` ASC)`,
262
+ mssql: tsql`CREATE UNIQUE INDEX [IDX_User_email] ON [TestDb].[TestSchema].[User] ([email] ASC)`,
263
+ postgresql: pgsql`CREATE UNIQUE INDEX "IDX_User_email" ON "TestSchema"."User" ("email" ASC)`,
264
+ };
265
+
266
+ export const dropIdx: ExpectedSql = {
267
+ mysql: mysql`DROP INDEX \`IDX_User_email\` ON \`TestDb\`.\`User\``,
268
+ mssql: tsql`DROP INDEX [IDX_User_email] ON [TestDb].[TestSchema].[User]`,
269
+ postgresql: pgsql`DROP INDEX "TestSchema"."IDX_User_email"`,
270
+ };
271
+
272
+ export const dropIdxComposite: ExpectedSql = {
273
+ mysql: mysql`DROP INDEX \`IDX_User_name_email\` ON \`TestDb\`.\`User\``,
274
+ mssql: tsql`DROP INDEX [IDX_User_name_email] ON [TestDb].[TestSchema].[User]`,
275
+ postgresql: pgsql`DROP INDEX "TestSchema"."IDX_User_name_email"`,
276
+ };
277
+
278
+ //#endregion
279
+
280
+ //#region ========== View ==========
281
+
282
+ export const createView: ExpectedSql = {
283
+ mysql: mysql`
284
+ CREATE OR REPLACE VIEW \`TestDb\`.\`ActiveUsers\` AS
285
+ SELECT * FROM \`TestDb\`.\`User\` AS \`T1\`
286
+ WHERE \`T1\`.\`isActive\` <=> TRUE
287
+ `,
288
+ mssql: tsql`
289
+ CREATE OR ALTER VIEW [TestDb].[TestSchema].[ActiveUsers] AS
290
+ SELECT * FROM [TestDb].[TestSchema].[User] AS [T1]
291
+ WHERE (([T1].[isActive] IS NULL AND 1 IS NULL) OR [T1].[isActive] = 1)
292
+ `,
293
+ postgresql: pgsql`
294
+ CREATE OR REPLACE VIEW "TestSchema"."ActiveUsers" AS
295
+ SELECT * FROM "TestSchema"."User" AS "T1"
296
+ WHERE "T1"."isActive" IS NOT DISTINCT FROM TRUE
297
+ `,
298
+ };
299
+
300
+ export const dropView: ExpectedSql = {
301
+ mysql: mysql`DROP VIEW IF EXISTS \`TestDb\`.\`ActiveUsers\``,
302
+ mssql: tsql`DROP VIEW IF EXISTS [TestDb].[TestSchema].[ActiveUsers]`,
303
+ postgresql: pgsql`DROP VIEW IF EXISTS "TestSchema"."ActiveUsers"`,
304
+ };
305
+
306
+ //#endregion
307
+
308
+ //#region ========== Procedure ==========
309
+
310
+ export const createProc: ExpectedSql = {
311
+ mysql: mysql`
312
+ CREATE PROCEDURE \`TestDb\`.\`GetUserById\`(IN \`userId\` BIGINT)
313
+ BEGIN
314
+ -- DBMSwrite matching query --;
315
+ END
316
+ `,
317
+ mssql: tsql`
318
+ CREATE OR ALTER PROCEDURE [TestDb].[TestSchema].[GetUserById] @userId BIGINT
319
+ AS
320
+ BEGIN
321
+ SET NOCOUNT ON;
322
+ -- DBMSwrite matching query --
323
+ END
324
+ `,
325
+ postgresql: pgsql`
326
+ CREATE OR REPLACE FUNCTION "TestSchema"."GetUserById"("userId" BIGINT)
327
+ RETURNS TABLE("id" BIGINT, "name" VARCHAR(100), "email" VARCHAR(200)) AS $$
328
+ BEGIN
329
+ -- DBMSwrite matching query --;
330
+ END;
331
+ $$ LANGUAGE plpgsql
332
+ `,
333
+ };
334
+
335
+ export const dropProc: ExpectedSql = {
336
+ mysql: mysql`DROP PROCEDURE IF EXISTS \`TestDb\`.\`GetUserById\``,
337
+ mssql: tsql`DROP PROCEDURE IF EXISTS [TestDb].[TestSchema].[GetUserById]`,
338
+ postgresql: pgsql`DROP FUNCTION IF EXISTS "TestSchema"."GetUserById"()`,
339
+ };
340
+
341
+ //#endregion