@simplysm/orm-common 13.0.69 → 13.0.70

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 +104 -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,514 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { createTestDb } from "../setup/TestDbContext";
3
+ import { expr } from "../../src/expr/expr";
4
+ import { Employee } from "../setup/models/Employee";
5
+ import { createQueryBuilder } from "../../src/query-builder/query-builder";
6
+ import { dialects } from "../setup/test-utils";
7
+ import "../setup/test-utils"; // toMatchSql matcher
8
+ import * as expected from "./recursive-cte.expected";
9
+
10
+ describe("SELECT - Recursive CTE", () => {
11
+ describe("Basic: select all subordinates of a specific manager", () => {
12
+ const db = createTestDb();
13
+ const def = db
14
+ .employee()
15
+ .where((e) => [expr.eq(e.managerId, 1)])
16
+ .select((e) => ({
17
+ id: e.id,
18
+ name: e.name,
19
+ managerId: e.managerId,
20
+ depth: expr.val("number", 1),
21
+ }))
22
+ .recursive((qr) => {
23
+ return qr
24
+ .from(Employee)
25
+ .where((e) => [expr.eq(e.managerId, e.self![0].id)])
26
+ .select((e) => ({
27
+ id: e.id,
28
+ name: e.name,
29
+ managerId: e.managerId,
30
+ depth: expr.raw("number")`${e.self![0].depth} + 1`.n,
31
+ }));
32
+ })
33
+ .select((s) => ({
34
+ id: s.id,
35
+ name: s.name,
36
+ managerId: s.managerId,
37
+ depth: s.depth,
38
+ }))
39
+ .getSelectQueryDef();
40
+
41
+ it("Verify QueryDef", () => {
42
+ expect(def).toEqual({
43
+ type: "select",
44
+ as: "T1",
45
+ from: "T2",
46
+ with: {
47
+ name: "T2",
48
+ base: {
49
+ type: "select",
50
+ as: "T1",
51
+ from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
52
+ where: [
53
+ {
54
+ type: "eq",
55
+ source: { type: "column", path: ["T1", "managerId"] },
56
+ target: { type: "value", value: 1 },
57
+ },
58
+ ],
59
+ select: {
60
+ id: { type: "column", path: ["T1", "id"] },
61
+ name: { type: "column", path: ["T1", "name"] },
62
+ managerId: { type: "column", path: ["T1", "managerId"] },
63
+ depth: { type: "value", value: 1 },
64
+ },
65
+ },
66
+ recursive: {
67
+ type: "select",
68
+ as: "T2",
69
+ from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
70
+ joins: [
71
+ {
72
+ type: "select",
73
+ as: "T2.self",
74
+ from: "T2",
75
+ isSingle: false,
76
+ },
77
+ ],
78
+ where: [
79
+ {
80
+ type: "eq",
81
+ source: { type: "column", path: ["T2", "managerId"] },
82
+ target: { type: "column", path: ["T2.self", "id"] },
83
+ },
84
+ ],
85
+ select: {
86
+ id: { type: "column", path: ["T2", "id"] },
87
+ name: { type: "column", path: ["T2", "name"] },
88
+ managerId: { type: "column", path: ["T2", "managerId"] },
89
+ depth: {
90
+ type: "raw",
91
+ sql: "$1 + 1",
92
+ params: [{ type: "column", path: ["T2.self", "depth"] }],
93
+ },
94
+ },
95
+ },
96
+ },
97
+ select: {
98
+ id: { type: "column", path: ["T1", "id"] },
99
+ name: { type: "column", path: ["T1", "name"] },
100
+ managerId: { type: "column", path: ["T1", "managerId"] },
101
+ depth: { type: "column", path: ["T1", "depth"] },
102
+ },
103
+ });
104
+ });
105
+
106
+ it.each(dialects)("[%s] Verify SQL", (dialect) => {
107
+ const builder = createQueryBuilder(dialect);
108
+ expect(builder.build(def)).toMatchSql(expected.basicSubordinates[dialect]);
109
+ });
110
+ });
111
+
112
+ describe("depth limit: check depth in recursive WHERE", () => {
113
+ const db = createTestDb();
114
+ const def = db
115
+ .employee()
116
+ .where((e) => [expr.eq(e.managerId, 1)])
117
+ .select((e) => ({
118
+ id: e.id,
119
+ name: e.name,
120
+ depth: expr.val("number", 1),
121
+ }))
122
+ .recursive((qr) =>
123
+ qr
124
+ .from(Employee)
125
+ .where((e) => [expr.eq(e.managerId, e.self![0].id), expr.lt(e.self![0].depth, 3)])
126
+ .select((e) => ({
127
+ id: e.id,
128
+ name: e.name,
129
+ depth: expr.raw("number")`${e.self![0].depth} + 1`.n,
130
+ })),
131
+ )
132
+ .select((s) => ({
133
+ id: s.id,
134
+ name: s.name,
135
+ depth: s.depth,
136
+ }))
137
+ .getSelectQueryDef();
138
+
139
+ it("Verify QueryDef", () => {
140
+ expect(def).toEqual({
141
+ type: "select",
142
+ as: "T1",
143
+ from: "T2",
144
+ with: {
145
+ name: "T2",
146
+ base: {
147
+ type: "select",
148
+ as: "T1",
149
+ from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
150
+ where: [
151
+ {
152
+ type: "eq",
153
+ source: { type: "column", path: ["T1", "managerId"] },
154
+ target: { type: "value", value: 1 },
155
+ },
156
+ ],
157
+ select: {
158
+ id: { type: "column", path: ["T1", "id"] },
159
+ name: { type: "column", path: ["T1", "name"] },
160
+ depth: { type: "value", value: 1 },
161
+ },
162
+ },
163
+ recursive: {
164
+ type: "select",
165
+ as: "T2",
166
+ from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
167
+ joins: [
168
+ {
169
+ type: "select",
170
+ as: "T2.self",
171
+ from: "T2",
172
+ isSingle: false,
173
+ },
174
+ ],
175
+ where: [
176
+ {
177
+ type: "eq",
178
+ source: { type: "column", path: ["T2", "managerId"] },
179
+ target: { type: "column", path: ["T2.self", "id"] },
180
+ },
181
+ {
182
+ type: "lt",
183
+ source: { type: "column", path: ["T2.self", "depth"] },
184
+ target: { type: "value", value: 3 },
185
+ },
186
+ ],
187
+ select: {
188
+ id: { type: "column", path: ["T2", "id"] },
189
+ name: { type: "column", path: ["T2", "name"] },
190
+ depth: {
191
+ type: "raw",
192
+ sql: "$1 + 1",
193
+ params: [{ type: "column", path: ["T2.self", "depth"] }],
194
+ },
195
+ },
196
+ },
197
+ },
198
+ select: {
199
+ id: { type: "column", path: ["T1", "id"] },
200
+ name: { type: "column", path: ["T1", "name"] },
201
+ depth: { type: "column", path: ["T1", "depth"] },
202
+ },
203
+ });
204
+ });
205
+
206
+ it.each(dialects)("[%s] Verify SQL", (dialect) => {
207
+ const builder = createQueryBuilder(dialect);
208
+ expect(builder.build(def)).toMatchSql(expected.depthLimit[dialect]);
209
+ });
210
+ });
211
+
212
+ describe("upward search: select all managers above a specific employee", () => {
213
+ const db = createTestDb();
214
+ const def = db
215
+ .employee()
216
+ .where((e) => [expr.eq(e.id, 100)])
217
+ .select((e) => ({
218
+ id: e.id,
219
+ name: e.name,
220
+ managerId: e.managerId,
221
+ level: expr.val("number", 0),
222
+ }))
223
+ .recursive((qr) =>
224
+ qr
225
+ .from(Employee)
226
+ .where((e) => [expr.eq(e.id, e.self![0].managerId)])
227
+ .select((e) => ({
228
+ id: e.id,
229
+ name: e.name,
230
+ managerId: e.managerId,
231
+ level: expr.raw("number")`${e.self![0].level} - 1`.n,
232
+ })),
233
+ )
234
+ .select((s) => ({
235
+ id: s.id,
236
+ name: s.name,
237
+ level: s.level,
238
+ }))
239
+ .getSelectQueryDef();
240
+
241
+ it("Verify QueryDef", () => {
242
+ expect(def).toEqual({
243
+ type: "select",
244
+ as: "T1",
245
+ from: "T2",
246
+ with: {
247
+ name: "T2",
248
+ base: {
249
+ type: "select",
250
+ as: "T1",
251
+ from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
252
+ where: [
253
+ {
254
+ type: "eq",
255
+ source: { type: "column", path: ["T1", "id"] },
256
+ target: { type: "value", value: 100 },
257
+ },
258
+ ],
259
+ select: {
260
+ id: { type: "column", path: ["T1", "id"] },
261
+ name: { type: "column", path: ["T1", "name"] },
262
+ managerId: { type: "column", path: ["T1", "managerId"] },
263
+ level: { type: "value", value: 0 },
264
+ },
265
+ },
266
+ recursive: {
267
+ type: "select",
268
+ as: "T2",
269
+ from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
270
+ joins: [
271
+ {
272
+ type: "select",
273
+ as: "T2.self",
274
+ from: "T2",
275
+ isSingle: false,
276
+ },
277
+ ],
278
+ where: [
279
+ {
280
+ type: "eq",
281
+ source: { type: "column", path: ["T2", "id"] },
282
+ target: { type: "column", path: ["T2.self", "managerId"] },
283
+ },
284
+ ],
285
+ select: {
286
+ id: { type: "column", path: ["T2", "id"] },
287
+ name: { type: "column", path: ["T2", "name"] },
288
+ managerId: { type: "column", path: ["T2", "managerId"] },
289
+ level: {
290
+ type: "raw",
291
+ sql: "$1 - 1",
292
+ params: [{ type: "column", path: ["T2.self", "level"] }],
293
+ },
294
+ },
295
+ },
296
+ },
297
+ select: {
298
+ id: { type: "column", path: ["T1", "id"] },
299
+ name: { type: "column", path: ["T1", "name"] },
300
+ level: { type: "column", path: ["T1", "level"] },
301
+ },
302
+ });
303
+ });
304
+
305
+ it.each(dialects)("[%s] Verify SQL", (dialect) => {
306
+ const builder = createQueryBuilder(dialect);
307
+ expect(builder.build(def)).toMatchSql(expected.upwardManagers[dialect]);
308
+ });
309
+ });
310
+
311
+ describe("Apply orderBy to CTE result", () => {
312
+ const db = createTestDb();
313
+ const def = db
314
+ .employee()
315
+ .where((e) => [expr.eq(e.managerId, 1)])
316
+ .select((e) => ({
317
+ id: e.id,
318
+ name: e.name,
319
+ depth: expr.val("number", 1),
320
+ }))
321
+ .recursive((qr) =>
322
+ qr
323
+ .from(Employee)
324
+ .where((e) => [expr.eq(e.managerId, e.self![0].id)])
325
+ .select((e) => ({
326
+ id: e.id,
327
+ name: e.name,
328
+ depth: expr.raw("number")`${e.self![0].depth} + 1`.n,
329
+ })),
330
+ )
331
+ .orderBy((s) => s.depth, "ASC")
332
+ .orderBy((s) => s.name, "ASC")
333
+ .select((s) => ({
334
+ id: s.id,
335
+ name: s.name,
336
+ depth: s.depth,
337
+ }))
338
+ .getSelectQueryDef();
339
+
340
+ it("Verify QueryDef", () => {
341
+ expect(def).toEqual({
342
+ type: "select",
343
+ as: "T1",
344
+ from: "T2",
345
+ with: {
346
+ name: "T2",
347
+ base: {
348
+ type: "select",
349
+ as: "T1",
350
+ from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
351
+ where: [
352
+ {
353
+ type: "eq",
354
+ source: { type: "column", path: ["T1", "managerId"] },
355
+ target: { type: "value", value: 1 },
356
+ },
357
+ ],
358
+ select: {
359
+ id: { type: "column", path: ["T1", "id"] },
360
+ name: { type: "column", path: ["T1", "name"] },
361
+ depth: { type: "value", value: 1 },
362
+ },
363
+ },
364
+ recursive: {
365
+ type: "select",
366
+ as: "T2",
367
+ from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
368
+ joins: [
369
+ {
370
+ type: "select",
371
+ as: "T2.self",
372
+ from: "T2",
373
+ isSingle: false,
374
+ },
375
+ ],
376
+ where: [
377
+ {
378
+ type: "eq",
379
+ source: { type: "column", path: ["T2", "managerId"] },
380
+ target: { type: "column", path: ["T2.self", "id"] },
381
+ },
382
+ ],
383
+ select: {
384
+ id: { type: "column", path: ["T2", "id"] },
385
+ name: { type: "column", path: ["T2", "name"] },
386
+ depth: {
387
+ type: "raw",
388
+ sql: "$1 + 1",
389
+ params: [{ type: "column", path: ["T2.self", "depth"] }],
390
+ },
391
+ },
392
+ },
393
+ },
394
+ orderBy: [
395
+ [{ type: "column", path: ["T1", "depth"] }, "ASC"],
396
+ [{ type: "column", path: ["T1", "name"] }, "ASC"],
397
+ ],
398
+ select: {
399
+ id: { type: "column", path: ["T1", "id"] },
400
+ name: { type: "column", path: ["T1", "name"] },
401
+ depth: { type: "column", path: ["T1", "depth"] },
402
+ },
403
+ });
404
+ });
405
+
406
+ it.each(dialects)("[%s] Verify SQL", (dialect) => {
407
+ const builder = createQueryBuilder(dialect);
408
+ expect(builder.build(def)).toMatchSql(expected.cteWithOrderBy[dialect]);
409
+ });
410
+ });
411
+
412
+ describe("Apply where to CTE result", () => {
413
+ const db = createTestDb();
414
+ const def = db
415
+ .employee()
416
+ .where((e) => [expr.eq(e.managerId, 1)])
417
+ .select((e) => ({
418
+ id: e.id,
419
+ name: e.name,
420
+ depth: expr.val("number", 1),
421
+ }))
422
+ .recursive((qr) =>
423
+ qr
424
+ .from(Employee)
425
+ .where((e) => [expr.eq(e.managerId, e.self![0].id)])
426
+ .select((e) => ({
427
+ id: e.id,
428
+ name: e.name,
429
+ depth: expr.raw("number")`${e.self![0].depth} + 1`.n,
430
+ })),
431
+ )
432
+ .where((s) => [expr.gt(s.depth, 1)])
433
+ .select((s) => ({
434
+ id: s.id,
435
+ name: s.name,
436
+ depth: s.depth,
437
+ }))
438
+ .getSelectQueryDef();
439
+
440
+ it("Verify QueryDef", () => {
441
+ expect(def).toEqual({
442
+ type: "select",
443
+ as: "T1",
444
+ from: "T2",
445
+ with: {
446
+ name: "T2",
447
+ base: {
448
+ type: "select",
449
+ as: "T1",
450
+ from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
451
+ where: [
452
+ {
453
+ type: "eq",
454
+ source: { type: "column", path: ["T1", "managerId"] },
455
+ target: { type: "value", value: 1 },
456
+ },
457
+ ],
458
+ select: {
459
+ id: { type: "column", path: ["T1", "id"] },
460
+ name: { type: "column", path: ["T1", "name"] },
461
+ depth: { type: "value", value: 1 },
462
+ },
463
+ },
464
+ recursive: {
465
+ type: "select",
466
+ as: "T2",
467
+ from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
468
+ joins: [
469
+ {
470
+ type: "select",
471
+ as: "T2.self",
472
+ from: "T2",
473
+ isSingle: false,
474
+ },
475
+ ],
476
+ where: [
477
+ {
478
+ type: "eq",
479
+ source: { type: "column", path: ["T2", "managerId"] },
480
+ target: { type: "column", path: ["T2.self", "id"] },
481
+ },
482
+ ],
483
+ select: {
484
+ id: { type: "column", path: ["T2", "id"] },
485
+ name: { type: "column", path: ["T2", "name"] },
486
+ depth: {
487
+ type: "raw",
488
+ sql: "$1 + 1",
489
+ params: [{ type: "column", path: ["T2.self", "depth"] }],
490
+ },
491
+ },
492
+ },
493
+ },
494
+ where: [
495
+ {
496
+ type: "gt",
497
+ source: { type: "column", path: ["T1", "depth"] },
498
+ target: { type: "value", value: 1 },
499
+ },
500
+ ],
501
+ select: {
502
+ id: { type: "column", path: ["T1", "id"] },
503
+ name: { type: "column", path: ["T1", "name"] },
504
+ depth: { type: "column", path: ["T1", "depth"] },
505
+ },
506
+ });
507
+ });
508
+
509
+ it.each(dialects)("[%s] Verify SQL", (dialect) => {
510
+ const builder = createQueryBuilder(dialect);
511
+ expect(builder.build(def)).toMatchSql(expected.cteWithWhere[dialect]);
512
+ });
513
+ });
514
+ });