@simplysm/orm-common 13.0.68 → 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,150 @@
1
+ /**
2
+ * SELECT - ORDER BY test expected SQL
3
+ */
4
+ import { mysql, pgsql, tsql } from "@simplysm/core-common";
5
+ import type { ExpectedSql } from "../setup/test-utils";
6
+
7
+ //#region ========== Basic ORDER BY ==========
8
+
9
+ export const orderAscDefault: ExpectedSql = {
10
+ mysql: mysql`
11
+ SELECT *
12
+ FROM \`TestDb\`.\`User\` AS \`T1\`
13
+ ORDER BY \`T1\`.\`id\`
14
+ `,
15
+ mssql: tsql`
16
+ SELECT *
17
+ FROM [TestDb].[TestSchema].[User] AS [T1]
18
+ ORDER BY [T1].[id]
19
+ `,
20
+ postgresql: pgsql`
21
+ SELECT *
22
+ FROM "TestSchema"."User" AS "T1"
23
+ ORDER BY "T1"."id"
24
+ `,
25
+ };
26
+
27
+ export const orderAscExplicit: ExpectedSql = {
28
+ mysql: mysql`
29
+ SELECT *
30
+ FROM \`TestDb\`.\`User\` AS \`T1\`
31
+ ORDER BY \`T1\`.\`id\` ASC
32
+ `,
33
+ mssql: tsql`
34
+ SELECT *
35
+ FROM [TestDb].[TestSchema].[User] AS [T1]
36
+ ORDER BY [T1].[id] ASC
37
+ `,
38
+ postgresql: pgsql`
39
+ SELECT *
40
+ FROM "TestSchema"."User" AS "T1"
41
+ ORDER BY "T1"."id" ASC
42
+ `,
43
+ };
44
+
45
+ export const orderDesc: ExpectedSql = {
46
+ mysql: mysql`
47
+ SELECT *
48
+ FROM \`TestDb\`.\`User\` AS \`T1\`
49
+ ORDER BY \`T1\`.\`id\` DESC
50
+ `,
51
+ mssql: tsql`
52
+ SELECT *
53
+ FROM [TestDb].[TestSchema].[User] AS [T1]
54
+ ORDER BY [T1].[id] DESC
55
+ `,
56
+ postgresql: pgsql`
57
+ SELECT *
58
+ FROM "TestSchema"."User" AS "T1"
59
+ ORDER BY "T1"."id" DESC
60
+ `,
61
+ };
62
+
63
+ //#endregion
64
+
65
+ //#region ========== 다중 정렬 ==========
66
+
67
+ export const orderMultiple: ExpectedSql = {
68
+ mysql: mysql`
69
+ SELECT *
70
+ FROM \`TestDb\`.\`User\` AS \`T1\`
71
+ ORDER BY \`T1\`.\`name\` ASC, \`T1\`.\`id\` DESC
72
+ `,
73
+ mssql: tsql`
74
+ SELECT *
75
+ FROM [TestDb].[TestSchema].[User] AS [T1]
76
+ ORDER BY [T1].[name] ASC, [T1].[id] DESC
77
+ `,
78
+ postgresql: pgsql`
79
+ SELECT *
80
+ FROM "TestSchema"."User" AS "T1"
81
+ ORDER BY "T1"."name" ASC, "T1"."id" DESC
82
+ `,
83
+ };
84
+
85
+ //#endregion
86
+
87
+ //#region ========== 표현식 정렬 ==========
88
+
89
+ export const orderExpression: ExpectedSql = {
90
+ mysql: mysql`
91
+ SELECT *
92
+ FROM \`TestDb\`.\`User\` AS \`T1\`
93
+ ORDER BY CHAR_LENGTH(IFNULL(\`T1\`.\`name\`, '')) DESC
94
+ `,
95
+ mssql: tsql`
96
+ SELECT *
97
+ FROM [TestDb].[TestSchema].[User] AS [T1]
98
+ ORDER BY LEN(ISNULL([T1].[name], N'')) DESC
99
+ `,
100
+ postgresql: pgsql`
101
+ SELECT *
102
+ FROM "TestSchema"."User" AS "T1"
103
+ ORDER BY LENGTH(COALESCE("T1"."name", '')) DESC
104
+ `,
105
+ };
106
+
107
+ //#endregion
108
+
109
+ //#region ========== 조합 ==========
110
+
111
+ export const orderSelectCombo: ExpectedSql = {
112
+ mysql: mysql`
113
+ SELECT \`T1\`.\`id\` AS \`id\`, \`T1\`.\`name\` AS \`name\`
114
+ FROM \`TestDb\`.\`User\` AS \`T1\`
115
+ ORDER BY \`T1\`.\`name\` ASC
116
+ `,
117
+ mssql: tsql`
118
+ SELECT [T1].[id] AS [id], [T1].[name] AS [name]
119
+ FROM [TestDb].[TestSchema].[User] AS [T1]
120
+ ORDER BY [T1].[name] ASC
121
+ `,
122
+ postgresql: pgsql`
123
+ SELECT "T1"."id" AS "id", "T1"."name" AS "name"
124
+ FROM "TestSchema"."User" AS "T1"
125
+ ORDER BY "T1"."name" ASC
126
+ `,
127
+ };
128
+
129
+ export const orderLimitCombo: ExpectedSql = {
130
+ mysql: mysql`
131
+ SELECT *
132
+ FROM \`TestDb\`.\`User\` AS \`T1\`
133
+ ORDER BY \`T1\`.\`id\` DESC
134
+ LIMIT 0, 10
135
+ `,
136
+ mssql: tsql`
137
+ SELECT *
138
+ FROM [TestDb].[TestSchema].[User] AS [T1]
139
+ ORDER BY [T1].[id] DESC
140
+ OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY
141
+ `,
142
+ postgresql: pgsql`
143
+ SELECT *
144
+ FROM "TestSchema"."User" AS "T1"
145
+ ORDER BY "T1"."id" DESC
146
+ LIMIT 10 OFFSET 0
147
+ `,
148
+ };
149
+
150
+ //#endregion
@@ -0,0 +1,189 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { createTestDb } from "../setup/TestDbContext";
3
+ import { expr } from "../../src/expr/expr";
4
+ import { createQueryBuilder } from "../../src/query-builder/query-builder";
5
+ import { dialects } from "../setup/test-utils";
6
+ import * as expected from "./order.expected";
7
+
8
+ describe("SELECT - ORDER BY", () => {
9
+ //#region ========== Basic ORDER BY ==========
10
+
11
+ describe("ASC (default)", () => {
12
+ const db = createTestDb();
13
+ const def = db
14
+ .user()
15
+ .orderBy((item) => item.id)
16
+ .getSelectQueryDef();
17
+
18
+ it("Verify QueryDef", () => {
19
+ expect(def).toEqual({
20
+ type: "select",
21
+ as: "T1",
22
+ from: { database: "TestDb", schema: "TestSchema", name: "User" },
23
+ orderBy: [[{ type: "column", path: ["T1", "id"] }]],
24
+ });
25
+ });
26
+
27
+ it.each(dialects)("[%s] Verify SQL", (dialect) => {
28
+ const builder = createQueryBuilder(dialect);
29
+ expect(builder.build(def)).toMatchSql(expected.orderAscDefault[dialect]);
30
+ });
31
+ });
32
+
33
+ describe("ASC (explicit)", () => {
34
+ const db = createTestDb();
35
+ const def = db
36
+ .user()
37
+ .orderBy((item) => item.id, "ASC")
38
+ .getSelectQueryDef();
39
+
40
+ it("Verify QueryDef", () => {
41
+ expect(def).toEqual({
42
+ type: "select",
43
+ as: "T1",
44
+ from: { database: "TestDb", schema: "TestSchema", name: "User" },
45
+ orderBy: [[{ type: "column", path: ["T1", "id"] }, "ASC"]],
46
+ });
47
+ });
48
+
49
+ it.each(dialects)("[%s] Verify SQL", (dialect) => {
50
+ const builder = createQueryBuilder(dialect);
51
+ expect(builder.build(def)).toMatchSql(expected.orderAscExplicit[dialect]);
52
+ });
53
+ });
54
+
55
+ describe("DESC", () => {
56
+ const db = createTestDb();
57
+ const def = db
58
+ .user()
59
+ .orderBy((item) => item.id, "DESC")
60
+ .getSelectQueryDef();
61
+
62
+ it("Verify QueryDef", () => {
63
+ expect(def).toEqual({
64
+ type: "select",
65
+ as: "T1",
66
+ from: { database: "TestDb", schema: "TestSchema", name: "User" },
67
+ orderBy: [[{ type: "column", path: ["T1", "id"] }, "DESC"]],
68
+ });
69
+ });
70
+
71
+ it.each(dialects)("[%s] Verify SQL", (dialect) => {
72
+ const builder = createQueryBuilder(dialect);
73
+ expect(builder.build(def)).toMatchSql(expected.orderDesc[dialect]);
74
+ });
75
+ });
76
+
77
+ //#endregion
78
+
79
+ //#region ========== 다중 정렬 ==========
80
+
81
+ describe("multiple sorting", () => {
82
+ const db = createTestDb();
83
+ const def = db
84
+ .user()
85
+ .orderBy((item) => item.name, "ASC")
86
+ .orderBy((item) => item.id, "DESC")
87
+ .getSelectQueryDef();
88
+
89
+ it("Verify QueryDef", () => {
90
+ expect(def).toEqual({
91
+ type: "select",
92
+ as: "T1",
93
+ from: { database: "TestDb", schema: "TestSchema", name: "User" },
94
+ orderBy: [
95
+ [{ type: "column", path: ["T1", "name"] }, "ASC"],
96
+ [{ type: "column", path: ["T1", "id"] }, "DESC"],
97
+ ],
98
+ });
99
+ });
100
+
101
+ it.each(dialects)("[%s] Verify SQL", (dialect) => {
102
+ const builder = createQueryBuilder(dialect);
103
+ expect(builder.build(def)).toMatchSql(expected.orderMultiple[dialect]);
104
+ });
105
+ });
106
+
107
+ //#endregion
108
+
109
+ //#region ========== 표현식 정렬 ==========
110
+
111
+ describe("sort by expressions", () => {
112
+ const db = createTestDb();
113
+ const def = db
114
+ .user()
115
+ .orderBy((item) => expr.length(item.name), "DESC")
116
+ .getSelectQueryDef();
117
+
118
+ it("Verify QueryDef", () => {
119
+ expect(def).toEqual({
120
+ type: "select",
121
+ as: "T1",
122
+ from: { database: "TestDb", schema: "TestSchema", name: "User" },
123
+ orderBy: [[{ type: "length", arg: { type: "column", path: ["T1", "name"] } }, "DESC"]],
124
+ });
125
+ });
126
+
127
+ it.each(dialects)("[%s] Verify SQL", (dialect) => {
128
+ const builder = createQueryBuilder(dialect);
129
+ expect(builder.build(def)).toMatchSql(expected.orderExpression[dialect]);
130
+ });
131
+ });
132
+
133
+ //#endregion
134
+
135
+ //#region ========== 조합 ==========
136
+
137
+ describe("SELECT + ORDER BY combination", () => {
138
+ const db = createTestDb();
139
+ const def = db
140
+ .user()
141
+ .select((item) => ({ id: item.id, name: item.name }))
142
+ .orderBy((item) => item.name, "ASC")
143
+ .getSelectQueryDef();
144
+
145
+ it("Verify QueryDef", () => {
146
+ expect(def).toEqual({
147
+ type: "select",
148
+ as: "T1",
149
+ from: { database: "TestDb", schema: "TestSchema", name: "User" },
150
+ select: {
151
+ id: { type: "column", path: ["T1", "id"] },
152
+ name: { type: "column", path: ["T1", "name"] },
153
+ },
154
+ orderBy: [[{ type: "column", path: ["T1", "name"] }, "ASC"]],
155
+ });
156
+ });
157
+
158
+ it.each(dialects)("[%s] Verify SQL", (dialect) => {
159
+ const builder = createQueryBuilder(dialect);
160
+ expect(builder.build(def)).toMatchSql(expected.orderSelectCombo[dialect]);
161
+ });
162
+ });
163
+
164
+ describe("ORDER BY + LIMIT combination", () => {
165
+ const db = createTestDb();
166
+ const def = db
167
+ .user()
168
+ .orderBy((item) => item.id, "DESC")
169
+ .limit(0, 10)
170
+ .getSelectQueryDef();
171
+
172
+ it("Verify QueryDef", () => {
173
+ expect(def).toEqual({
174
+ type: "select",
175
+ as: "T1",
176
+ from: { database: "TestDb", schema: "TestSchema", name: "User" },
177
+ orderBy: [[{ type: "column", path: ["T1", "id"] }, "DESC"]],
178
+ limit: [0, 10],
179
+ });
180
+ });
181
+
182
+ it.each(dialects)("[%s] Verify SQL", (dialect) => {
183
+ const builder = createQueryBuilder(dialect);
184
+ expect(builder.build(def)).toMatchSql(expected.orderLimitCombo[dialect]);
185
+ });
186
+ });
187
+
188
+ //#endregion
189
+ });
@@ -0,0 +1,244 @@
1
+ /**
2
+ * SELECT - Recursive CTE test expected SQL
3
+ */
4
+ import { mysql, pgsql, tsql } from "@simplysm/core-common";
5
+ import type { ExpectedSql } from "../setup/test-utils";
6
+
7
+ //#region ========== Basic 재귀 CTE ==========
8
+
9
+ export const basicSubordinates: ExpectedSql = {
10
+ mysql: mysql`
11
+ WITH \`T2\` AS (
12
+ SELECT \`T1\`.\`id\` AS \`id\`, \`T1\`.\`name\` AS \`name\`, \`T1\`.\`managerId\` AS \`managerId\`, 1 AS \`depth\`
13
+ FROM \`TestDb\`.\`Employee\` AS \`T1\`
14
+ WHERE \`T1\`.\`managerId\` <=> 1
15
+ UNION ALL
16
+ SELECT \`T2\`.\`id\` AS \`id\`, \`T2\`.\`name\` AS \`name\`, \`T2\`.\`managerId\` AS \`managerId\`, \`T2.self\`.\`depth\` + 1 AS \`depth\`
17
+ FROM \`TestDb\`.\`Employee\` AS \`T2\`
18
+ LEFT OUTER JOIN \`T2\` AS \`T2.self\` ON TRUE
19
+ WHERE \`T2\`.\`managerId\` <=> \`T2.self\`.\`id\`
20
+ )
21
+ SELECT \`T1\`.\`id\` AS \`id\`, \`T1\`.\`name\` AS \`name\`, \`T1\`.\`managerId\` AS \`managerId\`, \`T1\`.\`depth\` AS \`depth\`
22
+ FROM \`T2\` AS \`T1\`
23
+ `,
24
+ mssql: tsql`
25
+ WITH [T2] AS (
26
+ SELECT [T1].[id] AS [id], [T1].[name] AS [name], [T1].[managerId] AS [managerId], 1 AS [depth]
27
+ FROM [TestDb].[TestSchema].[Employee] AS [T1]
28
+ WHERE (([T1].[managerId] IS NULL AND 1 IS NULL) OR [T1].[managerId] = 1)
29
+ UNION ALL
30
+ SELECT [T2].[id] AS [id], [T2].[name] AS [name], [T2].[managerId] AS [managerId], [T2.self].[depth] + 1 AS [depth]
31
+ FROM [TestDb].[TestSchema].[Employee] AS [T2]
32
+ LEFT OUTER JOIN [T2] AS [T2.self] ON 1 = 1
33
+ WHERE (([T2].[managerId] IS NULL AND [T2.self].[id] IS NULL) OR [T2].[managerId] = [T2.self].[id])
34
+ )
35
+ SELECT [T1].[id] AS [id], [T1].[name] AS [name], [T1].[managerId] AS [managerId], [T1].[depth] AS [depth]
36
+ FROM [T2] AS [T1]
37
+ `,
38
+ postgresql: pgsql`
39
+ WITH RECURSIVE "T2" AS (
40
+ SELECT "T1"."id" AS "id", "T1"."name" AS "name", "T1"."managerId" AS "managerId", 1 AS "depth"
41
+ FROM "TestSchema"."Employee" AS "T1"
42
+ WHERE "T1"."managerId" IS NOT DISTINCT FROM 1
43
+ UNION ALL
44
+ SELECT "T2"."id" AS "id", "T2"."name" AS "name", "T2"."managerId" AS "managerId", "T2.self"."depth" + 1 AS "depth"
45
+ FROM "TestSchema"."Employee" AS "T2"
46
+ LEFT OUTER JOIN "T2" AS "T2.self" ON TRUE
47
+ WHERE "T2"."managerId" IS NOT DISTINCT FROM "T2.self"."id"
48
+ )
49
+ SELECT "T1"."id" AS "id", "T1"."name" AS "name", "T1"."managerId" AS "managerId", "T1"."depth" AS "depth"
50
+ FROM "T2" AS "T1"
51
+ `,
52
+ };
53
+
54
+ export const depthLimit: ExpectedSql = {
55
+ mysql: mysql`
56
+ WITH \`T2\` AS (
57
+ SELECT \`T1\`.\`id\` AS \`id\`, \`T1\`.\`name\` AS \`name\`, 1 AS \`depth\`
58
+ FROM \`TestDb\`.\`Employee\` AS \`T1\`
59
+ WHERE \`T1\`.\`managerId\` <=> 1
60
+ UNION ALL
61
+ SELECT \`T2\`.\`id\` AS \`id\`, \`T2\`.\`name\` AS \`name\`, \`T2.self\`.\`depth\` + 1 AS \`depth\`
62
+ FROM \`TestDb\`.\`Employee\` AS \`T2\`
63
+ LEFT OUTER JOIN \`T2\` AS \`T2.self\` ON TRUE
64
+ WHERE \`T2\`.\`managerId\` <=> \`T2.self\`.\`id\` AND \`T2.self\`.\`depth\` < 3
65
+ )
66
+ SELECT \`T1\`.\`id\` AS \`id\`, \`T1\`.\`name\` AS \`name\`, \`T1\`.\`depth\` AS \`depth\`
67
+ FROM \`T2\` AS \`T1\`
68
+ `,
69
+ mssql: tsql`
70
+ WITH [T2] AS (
71
+ SELECT [T1].[id] AS [id], [T1].[name] AS [name], 1 AS [depth]
72
+ FROM [TestDb].[TestSchema].[Employee] AS [T1]
73
+ WHERE (([T1].[managerId] IS NULL AND 1 IS NULL) OR [T1].[managerId] = 1)
74
+ UNION ALL
75
+ SELECT [T2].[id] AS [id], [T2].[name] AS [name], [T2.self].[depth] + 1 AS [depth]
76
+ FROM [TestDb].[TestSchema].[Employee] AS [T2]
77
+ LEFT OUTER JOIN [T2] AS [T2.self] ON 1 = 1
78
+ WHERE (([T2].[managerId] IS NULL AND [T2.self].[id] IS NULL) OR [T2].[managerId] = [T2.self].[id]) AND [T2.self].[depth] < 3
79
+ )
80
+ SELECT [T1].[id] AS [id], [T1].[name] AS [name], [T1].[depth] AS [depth]
81
+ FROM [T2] AS [T1]
82
+ `,
83
+ postgresql: pgsql`
84
+ WITH RECURSIVE "T2" AS (
85
+ SELECT "T1"."id" AS "id", "T1"."name" AS "name", 1 AS "depth"
86
+ FROM "TestSchema"."Employee" AS "T1"
87
+ WHERE "T1"."managerId" IS NOT DISTINCT FROM 1
88
+ UNION ALL
89
+ SELECT "T2"."id" AS "id", "T2"."name" AS "name", "T2.self"."depth" + 1 AS "depth"
90
+ FROM "TestSchema"."Employee" AS "T2"
91
+ LEFT OUTER JOIN "T2" AS "T2.self" ON TRUE
92
+ WHERE "T2"."managerId" IS NOT DISTINCT FROM "T2.self"."id" AND "T2.self"."depth" < 3
93
+ )
94
+ SELECT "T1"."id" AS "id", "T1"."name" AS "name", "T1"."depth" AS "depth"
95
+ FROM "T2" AS "T1"
96
+ `,
97
+ };
98
+
99
+ export const upwardManagers: ExpectedSql = {
100
+ mysql: mysql`
101
+ WITH \`T2\` AS (
102
+ SELECT \`T1\`.\`id\` AS \`id\`, \`T1\`.\`name\` AS \`name\`, \`T1\`.\`managerId\` AS \`managerId\`, 0 AS \`level\`
103
+ FROM \`TestDb\`.\`Employee\` AS \`T1\`
104
+ WHERE \`T1\`.\`id\` <=> 100
105
+ UNION ALL
106
+ SELECT \`T2\`.\`id\` AS \`id\`, \`T2\`.\`name\` AS \`name\`, \`T2\`.\`managerId\` AS \`managerId\`, \`T2.self\`.\`level\` - 1 AS \`level\`
107
+ FROM \`TestDb\`.\`Employee\` AS \`T2\`
108
+ LEFT OUTER JOIN \`T2\` AS \`T2.self\` ON TRUE
109
+ WHERE \`T2\`.\`id\` <=> \`T2.self\`.\`managerId\`
110
+ )
111
+ SELECT \`T1\`.\`id\` AS \`id\`, \`T1\`.\`name\` AS \`name\`, \`T1\`.\`level\` AS \`level\`
112
+ FROM \`T2\` AS \`T1\`
113
+ `,
114
+ mssql: tsql`
115
+ WITH [T2] AS (
116
+ SELECT [T1].[id] AS [id], [T1].[name] AS [name], [T1].[managerId] AS [managerId], 0 AS [level]
117
+ FROM [TestDb].[TestSchema].[Employee] AS [T1]
118
+ WHERE (([T1].[id] IS NULL AND 100 IS NULL) OR [T1].[id] = 100)
119
+ UNION ALL
120
+ SELECT [T2].[id] AS [id], [T2].[name] AS [name], [T2].[managerId] AS [managerId], [T2.self].[level] - 1 AS [level]
121
+ FROM [TestDb].[TestSchema].[Employee] AS [T2]
122
+ LEFT OUTER JOIN [T2] AS [T2.self] ON 1 = 1
123
+ WHERE (([T2].[id] IS NULL AND [T2.self].[managerId] IS NULL) OR [T2].[id] = [T2.self].[managerId])
124
+ )
125
+ SELECT [T1].[id] AS [id], [T1].[name] AS [name], [T1].[level] AS [level]
126
+ FROM [T2] AS [T1]
127
+ `,
128
+ postgresql: pgsql`
129
+ WITH RECURSIVE "T2" AS (
130
+ SELECT "T1"."id" AS "id", "T1"."name" AS "name", "T1"."managerId" AS "managerId", 0 AS "level"
131
+ FROM "TestSchema"."Employee" AS "T1"
132
+ WHERE "T1"."id" IS NOT DISTINCT FROM 100
133
+ UNION ALL
134
+ SELECT "T2"."id" AS "id", "T2"."name" AS "name", "T2"."managerId" AS "managerId", "T2.self"."level" - 1 AS "level"
135
+ FROM "TestSchema"."Employee" AS "T2"
136
+ LEFT OUTER JOIN "T2" AS "T2.self" ON TRUE
137
+ WHERE "T2"."id" IS NOT DISTINCT FROM "T2.self"."managerId"
138
+ )
139
+ SELECT "T1"."id" AS "id", "T1"."name" AS "name", "T1"."level" AS "level"
140
+ FROM "T2" AS "T1"
141
+ `,
142
+ };
143
+
144
+ //#endregion
145
+
146
+ //#region ========== CTE + 후processing ==========
147
+
148
+ export const cteWithOrderBy: ExpectedSql = {
149
+ mysql: mysql`
150
+ WITH \`T2\` AS (
151
+ SELECT \`T1\`.\`id\` AS \`id\`, \`T1\`.\`name\` AS \`name\`, 1 AS \`depth\`
152
+ FROM \`TestDb\`.\`Employee\` AS \`T1\`
153
+ WHERE \`T1\`.\`managerId\` <=> 1
154
+ UNION ALL
155
+ SELECT \`T2\`.\`id\` AS \`id\`, \`T2\`.\`name\` AS \`name\`, \`T2.self\`.\`depth\` + 1 AS \`depth\`
156
+ FROM \`TestDb\`.\`Employee\` AS \`T2\`
157
+ LEFT OUTER JOIN \`T2\` AS \`T2.self\` ON TRUE
158
+ WHERE \`T2\`.\`managerId\` <=> \`T2.self\`.\`id\`
159
+ )
160
+ SELECT \`T1\`.\`id\` AS \`id\`, \`T1\`.\`name\` AS \`name\`, \`T1\`.\`depth\` AS \`depth\`
161
+ FROM \`T2\` AS \`T1\`
162
+ ORDER BY \`T1\`.\`depth\` ASC, \`T1\`.\`name\` ASC
163
+ `,
164
+ mssql: tsql`
165
+ WITH [T2] AS (
166
+ SELECT [T1].[id] AS [id], [T1].[name] AS [name], 1 AS [depth]
167
+ FROM [TestDb].[TestSchema].[Employee] AS [T1]
168
+ WHERE (([T1].[managerId] IS NULL AND 1 IS NULL) OR [T1].[managerId] = 1)
169
+ UNION ALL
170
+ SELECT [T2].[id] AS [id], [T2].[name] AS [name], [T2.self].[depth] + 1 AS [depth]
171
+ FROM [TestDb].[TestSchema].[Employee] AS [T2]
172
+ LEFT OUTER JOIN [T2] AS [T2.self] ON 1 = 1
173
+ WHERE (([T2].[managerId] IS NULL AND [T2.self].[id] IS NULL) OR [T2].[managerId] = [T2.self].[id])
174
+ )
175
+ SELECT [T1].[id] AS [id], [T1].[name] AS [name], [T1].[depth] AS [depth]
176
+ FROM [T2] AS [T1]
177
+ ORDER BY [T1].[depth] ASC, [T1].[name] ASC
178
+ `,
179
+ postgresql: pgsql`
180
+ WITH RECURSIVE "T2" AS (
181
+ SELECT "T1"."id" AS "id", "T1"."name" AS "name", 1 AS "depth"
182
+ FROM "TestSchema"."Employee" AS "T1"
183
+ WHERE "T1"."managerId" IS NOT DISTINCT FROM 1
184
+ UNION ALL
185
+ SELECT "T2"."id" AS "id", "T2"."name" AS "name", "T2.self"."depth" + 1 AS "depth"
186
+ FROM "TestSchema"."Employee" AS "T2"
187
+ LEFT OUTER JOIN "T2" AS "T2.self" ON TRUE
188
+ WHERE "T2"."managerId" IS NOT DISTINCT FROM "T2.self"."id"
189
+ )
190
+ SELECT "T1"."id" AS "id", "T1"."name" AS "name", "T1"."depth" AS "depth"
191
+ FROM "T2" AS "T1"
192
+ ORDER BY "T1"."depth" ASC, "T1"."name" ASC
193
+ `,
194
+ };
195
+
196
+ export const cteWithWhere: ExpectedSql = {
197
+ mysql: mysql`
198
+ WITH \`T2\` AS (
199
+ SELECT \`T1\`.\`id\` AS \`id\`, \`T1\`.\`name\` AS \`name\`, 1 AS \`depth\`
200
+ FROM \`TestDb\`.\`Employee\` AS \`T1\`
201
+ WHERE \`T1\`.\`managerId\` <=> 1
202
+ UNION ALL
203
+ SELECT \`T2\`.\`id\` AS \`id\`, \`T2\`.\`name\` AS \`name\`, \`T2.self\`.\`depth\` + 1 AS \`depth\`
204
+ FROM \`TestDb\`.\`Employee\` AS \`T2\`
205
+ LEFT OUTER JOIN \`T2\` AS \`T2.self\` ON TRUE
206
+ WHERE \`T2\`.\`managerId\` <=> \`T2.self\`.\`id\`
207
+ )
208
+ SELECT \`T1\`.\`id\` AS \`id\`, \`T1\`.\`name\` AS \`name\`, \`T1\`.\`depth\` AS \`depth\`
209
+ FROM \`T2\` AS \`T1\`
210
+ WHERE \`T1\`.\`depth\` > 1
211
+ `,
212
+ mssql: tsql`
213
+ WITH [T2] AS (
214
+ SELECT [T1].[id] AS [id], [T1].[name] AS [name], 1 AS [depth]
215
+ FROM [TestDb].[TestSchema].[Employee] AS [T1]
216
+ WHERE (([T1].[managerId] IS NULL AND 1 IS NULL) OR [T1].[managerId] = 1)
217
+ UNION ALL
218
+ SELECT [T2].[id] AS [id], [T2].[name] AS [name], [T2.self].[depth] + 1 AS [depth]
219
+ FROM [TestDb].[TestSchema].[Employee] AS [T2]
220
+ LEFT OUTER JOIN [T2] AS [T2.self] ON 1 = 1
221
+ WHERE (([T2].[managerId] IS NULL AND [T2.self].[id] IS NULL) OR [T2].[managerId] = [T2.self].[id])
222
+ )
223
+ SELECT [T1].[id] AS [id], [T1].[name] AS [name], [T1].[depth] AS [depth]
224
+ FROM [T2] AS [T1]
225
+ WHERE [T1].[depth] > 1
226
+ `,
227
+ postgresql: pgsql`
228
+ WITH RECURSIVE "T2" AS (
229
+ SELECT "T1"."id" AS "id", "T1"."name" AS "name", 1 AS "depth"
230
+ FROM "TestSchema"."Employee" AS "T1"
231
+ WHERE "T1"."managerId" IS NOT DISTINCT FROM 1
232
+ UNION ALL
233
+ SELECT "T2"."id" AS "id", "T2"."name" AS "name", "T2.self"."depth" + 1 AS "depth"
234
+ FROM "TestSchema"."Employee" AS "T2"
235
+ LEFT OUTER JOIN "T2" AS "T2.self" ON TRUE
236
+ WHERE "T2"."managerId" IS NOT DISTINCT FROM "T2.self"."id"
237
+ )
238
+ SELECT "T1"."id" AS "id", "T1"."name" AS "name", "T1"."depth" AS "depth"
239
+ FROM "T2" AS "T1"
240
+ WHERE "T1"."depth" > 1
241
+ `,
242
+ };
243
+
244
+ //#endregion