@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.
- package/README.md +54 -1447
- package/dist/create-db-context.d.ts +10 -10
- package/dist/create-db-context.js +9 -9
- package/dist/create-db-context.js.map +1 -1
- package/dist/ddl/column-ddl.d.ts +4 -4
- package/dist/ddl/initialize.d.ts +17 -17
- package/dist/ddl/initialize.js +2 -2
- package/dist/ddl/initialize.js.map +1 -1
- package/dist/ddl/relation-ddl.d.ts +6 -6
- package/dist/ddl/schema-ddl.d.ts +4 -4
- package/dist/ddl/table-ddl.d.ts +24 -24
- package/dist/ddl/table-ddl.js +4 -4
- package/dist/ddl/table-ddl.js.map +1 -1
- package/dist/errors/db-transaction-error.d.ts +15 -15
- package/dist/errors/db-transaction-error.d.ts.map +1 -1
- package/dist/exec/executable.d.ts +23 -23
- package/dist/exec/executable.js +3 -3
- package/dist/exec/executable.js.map +1 -1
- package/dist/exec/queryable.d.ts +160 -160
- package/dist/exec/queryable.js +119 -119
- package/dist/exec/queryable.js.map +1 -1
- package/dist/exec/search-parser.d.ts +37 -37
- package/dist/exec/search-parser.d.ts.map +1 -1
- package/dist/expr/expr-unit.d.ts +4 -4
- package/dist/expr/expr.d.ts +257 -257
- package/dist/expr/expr.js +265 -265
- package/dist/expr/expr.js.map +1 -1
- package/dist/query-builder/base/expr-renderer-base.d.ts +9 -9
- package/dist/query-builder/base/expr-renderer-base.js +2 -2
- package/dist/query-builder/base/expr-renderer-base.js.map +1 -1
- package/dist/query-builder/base/query-builder-base.d.ts +26 -26
- package/dist/query-builder/base/query-builder-base.d.ts.map +1 -1
- package/dist/query-builder/base/query-builder-base.js +22 -22
- package/dist/query-builder/base/query-builder-base.js.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +4 -4
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.js +18 -18
- package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.d.ts +2 -2
- package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.js +11 -11
- package/dist/query-builder/mssql/mssql-query-builder.js.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +4 -4
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.js +17 -17
- package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.d.ts +8 -8
- package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.js +5 -5
- package/dist/query-builder/mysql/mysql-query-builder.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +4 -4
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js +17 -17
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +5 -5
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.js +8 -8
- package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
- package/dist/query-builder/query-builder.d.ts +1 -1
- package/dist/schema/factory/column-builder.d.ts +79 -79
- package/dist/schema/factory/column-builder.js +42 -42
- package/dist/schema/factory/index-builder.d.ts +39 -39
- package/dist/schema/factory/index-builder.js +26 -26
- package/dist/schema/factory/relation-builder.d.ts +99 -99
- package/dist/schema/factory/relation-builder.d.ts.map +1 -1
- package/dist/schema/factory/relation-builder.js +38 -38
- package/dist/schema/procedure-builder.d.ts +49 -49
- package/dist/schema/procedure-builder.d.ts.map +1 -1
- package/dist/schema/procedure-builder.js +33 -33
- package/dist/schema/table-builder.d.ts +59 -59
- package/dist/schema/table-builder.d.ts.map +1 -1
- package/dist/schema/table-builder.js +43 -43
- package/dist/schema/view-builder.d.ts +49 -49
- package/dist/schema/view-builder.d.ts.map +1 -1
- package/dist/schema/view-builder.js +32 -32
- package/dist/types/column.d.ts +22 -22
- package/dist/types/column.js +1 -1
- package/dist/types/column.js.map +1 -1
- package/dist/types/db.d.ts +40 -40
- package/dist/types/expr.d.ts +59 -59
- package/dist/types/expr.d.ts.map +1 -1
- package/dist/types/query-def.d.ts +44 -44
- package/dist/types/query-def.d.ts.map +1 -1
- package/dist/utils/result-parser.d.ts +11 -11
- package/dist/utils/result-parser.js +3 -3
- package/dist/utils/result-parser.js.map +1 -1
- package/package.json +5 -5
- package/src/create-db-context.ts +20 -20
- package/src/ddl/column-ddl.ts +4 -4
- package/src/ddl/initialize.ts +259 -259
- package/src/ddl/relation-ddl.ts +89 -89
- package/src/ddl/schema-ddl.ts +4 -4
- package/src/ddl/table-ddl.ts +189 -189
- package/src/errors/db-transaction-error.ts +13 -13
- package/src/exec/executable.ts +25 -25
- package/src/exec/queryable.ts +2033 -2033
- package/src/exec/search-parser.ts +57 -57
- package/src/expr/expr-unit.ts +4 -4
- package/src/expr/expr.ts +2140 -2140
- package/src/query-builder/base/expr-renderer-base.ts +237 -237
- package/src/query-builder/base/query-builder-base.ts +213 -213
- package/src/query-builder/mssql/mssql-expr-renderer.ts +607 -607
- package/src/query-builder/mssql/mssql-query-builder.ts +650 -650
- package/src/query-builder/mysql/mysql-expr-renderer.ts +613 -613
- package/src/query-builder/mysql/mysql-query-builder.ts +759 -759
- package/src/query-builder/postgresql/postgresql-expr-renderer.ts +611 -611
- package/src/query-builder/postgresql/postgresql-query-builder.ts +686 -686
- package/src/query-builder/query-builder.ts +19 -19
- package/src/schema/factory/column-builder.ts +423 -423
- package/src/schema/factory/index-builder.ts +164 -164
- package/src/schema/factory/relation-builder.ts +453 -453
- package/src/schema/procedure-builder.ts +232 -232
- package/src/schema/table-builder.ts +319 -319
- package/src/schema/view-builder.ts +221 -221
- package/src/types/column.ts +188 -188
- package/src/types/db.ts +208 -208
- package/src/types/expr.ts +697 -697
- package/src/types/query-def.ts +513 -513
- package/src/utils/result-parser.ts +458 -458
- package/tests/db-context/create-db-context.spec.ts +224 -0
- package/tests/db-context/define-db-context.spec.ts +68 -0
- package/tests/ddl/basic.expected.ts +341 -0
- package/tests/ddl/basic.spec.ts +714 -0
- package/tests/ddl/column-builder.expected.ts +310 -0
- package/tests/ddl/column-builder.spec.ts +637 -0
- package/tests/ddl/index-builder.expected.ts +38 -0
- package/tests/ddl/index-builder.spec.ts +202 -0
- package/tests/ddl/procedure-builder.expected.ts +52 -0
- package/tests/ddl/procedure-builder.spec.ts +234 -0
- package/tests/ddl/relation-builder.expected.ts +36 -0
- package/tests/ddl/relation-builder.spec.ts +372 -0
- package/tests/ddl/table-builder.expected.ts +113 -0
- package/tests/ddl/table-builder.spec.ts +433 -0
- package/tests/ddl/view-builder.expected.ts +38 -0
- package/tests/ddl/view-builder.spec.ts +176 -0
- package/tests/dml/delete.expected.ts +96 -0
- package/tests/dml/delete.spec.ts +160 -0
- package/tests/dml/insert.expected.ts +192 -0
- package/tests/dml/insert.spec.ts +288 -0
- package/tests/dml/update.expected.ts +176 -0
- package/tests/dml/update.spec.ts +318 -0
- package/tests/dml/upsert.expected.ts +215 -0
- package/tests/dml/upsert.spec.ts +242 -0
- package/tests/errors/queryable-errors.spec.ts +177 -0
- package/tests/escape.spec.ts +100 -0
- package/tests/examples/pivot.expected.ts +211 -0
- package/tests/examples/pivot.spec.ts +533 -0
- package/tests/examples/sampling.expected.ts +69 -0
- package/tests/examples/sampling.spec.ts +104 -0
- package/tests/examples/unpivot.expected.ts +120 -0
- package/tests/examples/unpivot.spec.ts +226 -0
- package/tests/exec/search-parser.spec.ts +283 -0
- package/tests/executable/basic.expected.ts +18 -0
- package/tests/executable/basic.spec.ts +54 -0
- package/tests/expr/comparison.expected.ts +282 -0
- package/tests/expr/comparison.spec.ts +400 -0
- package/tests/expr/conditional.expected.ts +134 -0
- package/tests/expr/conditional.spec.ts +276 -0
- package/tests/expr/date.expected.ts +332 -0
- package/tests/expr/date.spec.ts +526 -0
- package/tests/expr/math.expected.ts +62 -0
- package/tests/expr/math.spec.ts +106 -0
- package/tests/expr/string.expected.ts +218 -0
- package/tests/expr/string.spec.ts +356 -0
- package/tests/expr/utility.expected.ts +147 -0
- package/tests/expr/utility.spec.ts +182 -0
- package/tests/select/basic.expected.ts +322 -0
- package/tests/select/basic.spec.ts +502 -0
- package/tests/select/filter.expected.ts +357 -0
- package/tests/select/filter.spec.ts +1068 -0
- package/tests/select/group.expected.ts +169 -0
- package/tests/select/group.spec.ts +244 -0
- package/tests/select/join.expected.ts +582 -0
- package/tests/select/join.spec.ts +805 -0
- package/tests/select/order.expected.ts +150 -0
- package/tests/select/order.spec.ts +189 -0
- package/tests/select/recursive-cte.expected.ts +244 -0
- package/tests/select/recursive-cte.spec.ts +514 -0
- package/tests/select/result-meta.spec.ts +270 -0
- package/tests/select/subquery.expected.ts +363 -0
- package/tests/select/subquery.spec.ts +537 -0
- package/tests/select/view.expected.ts +155 -0
- package/tests/select/view.spec.ts +235 -0
- package/tests/select/window.expected.ts +345 -0
- package/tests/select/window.spec.ts +618 -0
- package/tests/setup/MockExecutor.ts +18 -0
- package/tests/setup/TestDbContext.ts +59 -0
- package/tests/setup/models/Company.ts +13 -0
- package/tests/setup/models/Employee.ts +10 -0
- package/tests/setup/models/MonthlySales.ts +11 -0
- package/tests/setup/models/Post.ts +16 -0
- package/tests/setup/models/Sales.ts +10 -0
- package/tests/setup/models/User.ts +19 -0
- package/tests/setup/procedure/GetAllUsers.ts +9 -0
- package/tests/setup/procedure/GetUserById.ts +12 -0
- package/tests/setup/test-utils.ts +72 -0
- package/tests/setup/views/ActiveUsers.ts +8 -0
- package/tests/setup/views/UserSummary.ts +11 -0
- package/tests/types/nullable-queryable-record.spec.ts +145 -0
- package/tests/utils/result-parser-perf.spec.ts +210 -0
- package/tests/utils/result-parser.spec.ts +701 -0
- package/docs/expressions.md +0 -172
- package/docs/queries.md +0 -444
- package/docs/schema.md +0 -245
|
@@ -0,0 +1,318 @@
|
|
|
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 "../setup/test-utils";
|
|
7
|
+
import * as expected from "./update.expected";
|
|
8
|
+
|
|
9
|
+
describe("UPDATE - Basic", () => {
|
|
10
|
+
describe("simple UPDATE", () => {
|
|
11
|
+
const db = createTestDb();
|
|
12
|
+
|
|
13
|
+
const def = db
|
|
14
|
+
.employee()
|
|
15
|
+
.where((e) => [expr.eq(e.id, 1)])
|
|
16
|
+
.getUpdateQueryDef((_e) => ({
|
|
17
|
+
name: expr.val("string", "new name"),
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
it("should validate QueryDef", () => {
|
|
21
|
+
expect(def).toEqual({
|
|
22
|
+
type: "update",
|
|
23
|
+
table: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
24
|
+
as: "T1",
|
|
25
|
+
record: {
|
|
26
|
+
name: { type: "value", value: "new name" },
|
|
27
|
+
},
|
|
28
|
+
where: [
|
|
29
|
+
{
|
|
30
|
+
type: "eq",
|
|
31
|
+
source: { type: "column", path: ["T1", "id"] },
|
|
32
|
+
target: { type: "value", value: 1 },
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
39
|
+
const builder = createQueryBuilder(dialect);
|
|
40
|
+
expect(builder.build(def)).toMatchSql(expected.updateSimple[dialect]);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe("UPDATE multiple columns", () => {
|
|
45
|
+
const db = createTestDb();
|
|
46
|
+
|
|
47
|
+
const def = db
|
|
48
|
+
.employee()
|
|
49
|
+
.where((e) => [expr.eq(e.id, 1)])
|
|
50
|
+
.getUpdateQueryDef(() => ({
|
|
51
|
+
name: expr.val("string", "New Name"),
|
|
52
|
+
departmentId: expr.val("number", 2),
|
|
53
|
+
}));
|
|
54
|
+
|
|
55
|
+
it("Verify QueryDef", () => {
|
|
56
|
+
expect(def).toEqual({
|
|
57
|
+
type: "update",
|
|
58
|
+
table: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
59
|
+
as: "T1",
|
|
60
|
+
record: {
|
|
61
|
+
name: { type: "value", value: "New Name" },
|
|
62
|
+
departmentId: { type: "value", value: 2 },
|
|
63
|
+
},
|
|
64
|
+
where: [
|
|
65
|
+
{
|
|
66
|
+
type: "eq",
|
|
67
|
+
source: { type: "column", path: ["T1", "id"] },
|
|
68
|
+
target: { type: "value", value: 1 },
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
75
|
+
const builder = createQueryBuilder(dialect);
|
|
76
|
+
expect(builder.build(def)).toMatchSql(expected.updateMultiCol[dialect]);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe("UPDATE with literal values (without expr.val)", () => {
|
|
81
|
+
const db = createTestDb();
|
|
82
|
+
|
|
83
|
+
const def = db
|
|
84
|
+
.employee()
|
|
85
|
+
.where((e) => [expr.eq(e.id, 1)])
|
|
86
|
+
.getUpdateQueryDef(() => ({
|
|
87
|
+
name: "New Name",
|
|
88
|
+
departmentId: 2,
|
|
89
|
+
}));
|
|
90
|
+
|
|
91
|
+
it("Verify QueryDef", () => {
|
|
92
|
+
expect(def).toEqual({
|
|
93
|
+
type: "update",
|
|
94
|
+
table: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
95
|
+
as: "T1",
|
|
96
|
+
record: {
|
|
97
|
+
name: { type: "value", value: "New Name" },
|
|
98
|
+
departmentId: { type: "value", value: 2 },
|
|
99
|
+
},
|
|
100
|
+
where: [
|
|
101
|
+
{
|
|
102
|
+
type: "eq",
|
|
103
|
+
source: { type: "column", path: ["T1", "id"] },
|
|
104
|
+
target: { type: "value", value: 1 },
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
111
|
+
const builder = createQueryBuilder(dialect);
|
|
112
|
+
expect(builder.build(def)).toMatchSql(expected.updatePlainValues[dialect]);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe("UPDATE mixing literal values and expressions", () => {
|
|
117
|
+
const db = createTestDb();
|
|
118
|
+
|
|
119
|
+
const def = db
|
|
120
|
+
.employee()
|
|
121
|
+
.where((e) => [expr.eq(e.id, 1)])
|
|
122
|
+
.getUpdateQueryDef((e) => ({
|
|
123
|
+
name: "New Name",
|
|
124
|
+
managerId: expr.raw("number")`${e.managerId} + 1`,
|
|
125
|
+
}));
|
|
126
|
+
|
|
127
|
+
it("Verify QueryDef", () => {
|
|
128
|
+
expect(def).toEqual({
|
|
129
|
+
type: "update",
|
|
130
|
+
table: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
131
|
+
as: "T1",
|
|
132
|
+
record: {
|
|
133
|
+
name: { type: "value", value: "New Name" },
|
|
134
|
+
managerId: {
|
|
135
|
+
type: "raw",
|
|
136
|
+
sql: "$1 + 1",
|
|
137
|
+
params: [{ type: "column", path: ["T1", "managerId"] }],
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
where: [
|
|
141
|
+
{
|
|
142
|
+
type: "eq",
|
|
143
|
+
source: { type: "column", path: ["T1", "id"] },
|
|
144
|
+
target: { type: "value", value: 1 },
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
151
|
+
const builder = createQueryBuilder(dialect);
|
|
152
|
+
expect(builder.build(def)).toMatchSql(expected.updateMixed[dialect]);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe("UPDATE referencing current values (e.g., count = count + 1)", () => {
|
|
157
|
+
const db = createTestDb();
|
|
158
|
+
|
|
159
|
+
const def = db
|
|
160
|
+
.employee()
|
|
161
|
+
.where((e) => [expr.eq(e.id, 1)])
|
|
162
|
+
.getUpdateQueryDef((e) => ({
|
|
163
|
+
// managerId = managerId + 1 (예시)
|
|
164
|
+
managerId: expr.raw("number")`${e.managerId} + 1`,
|
|
165
|
+
}));
|
|
166
|
+
|
|
167
|
+
it("Verify QueryDef", () => {
|
|
168
|
+
expect(def).toEqual({
|
|
169
|
+
type: "update",
|
|
170
|
+
table: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
171
|
+
as: "T1",
|
|
172
|
+
record: {
|
|
173
|
+
managerId: {
|
|
174
|
+
type: "raw",
|
|
175
|
+
sql: "$1 + 1",
|
|
176
|
+
params: [{ type: "column", path: ["T1", "managerId"] }],
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
where: [
|
|
180
|
+
{
|
|
181
|
+
type: "eq",
|
|
182
|
+
source: { type: "column", path: ["T1", "id"] },
|
|
183
|
+
target: { type: "value", value: 1 },
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
190
|
+
const builder = createQueryBuilder(dialect);
|
|
191
|
+
expect(builder.build(def)).toMatchSql(expected.updateWithRef[dialect]);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
describe("Specify output column", () => {
|
|
196
|
+
const db = createTestDb();
|
|
197
|
+
|
|
198
|
+
const def = db
|
|
199
|
+
.employee()
|
|
200
|
+
.where((e) => [expr.eq(e.id, 1)])
|
|
201
|
+
.getUpdateQueryDef(
|
|
202
|
+
() => ({
|
|
203
|
+
name: expr.val("string", "New Name"),
|
|
204
|
+
}),
|
|
205
|
+
["id", "name"],
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
it("Verify QueryDef", () => {
|
|
209
|
+
expect(def).toEqual({
|
|
210
|
+
type: "update",
|
|
211
|
+
table: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
212
|
+
as: "T1",
|
|
213
|
+
record: {
|
|
214
|
+
name: { type: "value", value: "New Name" },
|
|
215
|
+
},
|
|
216
|
+
where: [
|
|
217
|
+
{
|
|
218
|
+
type: "eq",
|
|
219
|
+
source: { type: "column", path: ["T1", "id"] },
|
|
220
|
+
target: { type: "value", value: 1 },
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
output: {
|
|
224
|
+
columns: ["id", "name"],
|
|
225
|
+
pkColNames: ["id"],
|
|
226
|
+
aiColName: "id",
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
232
|
+
const builder = createQueryBuilder(dialect);
|
|
233
|
+
expect(builder.build(def)).toMatchSql(expected.updateWithOutput[dialect]);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
describe("Limit update count with TOP", () => {
|
|
238
|
+
const db = createTestDb();
|
|
239
|
+
|
|
240
|
+
const def = db
|
|
241
|
+
.employee()
|
|
242
|
+
.where((e) => [expr.eq(e.departmentId, 1)])
|
|
243
|
+
.top(10)
|
|
244
|
+
.getUpdateQueryDef(() => ({
|
|
245
|
+
name: expr.val("string", "New Name"),
|
|
246
|
+
}));
|
|
247
|
+
|
|
248
|
+
it("Verify QueryDef", () => {
|
|
249
|
+
expect(def).toEqual({
|
|
250
|
+
type: "update",
|
|
251
|
+
table: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
252
|
+
as: "T1",
|
|
253
|
+
record: {
|
|
254
|
+
name: { type: "value", value: "New Name" },
|
|
255
|
+
},
|
|
256
|
+
top: 10,
|
|
257
|
+
where: [
|
|
258
|
+
{
|
|
259
|
+
type: "eq",
|
|
260
|
+
source: { type: "column", path: ["T1", "departmentId"] },
|
|
261
|
+
target: { type: "value", value: 1 },
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
268
|
+
const builder = createQueryBuilder(dialect);
|
|
269
|
+
expect(builder.build(def)).toMatchSql(expected.updateWithTop[dialect]);
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
describe("FK switch", () => {
|
|
275
|
+
describe("FK off", () => {
|
|
276
|
+
const db = createTestDb();
|
|
277
|
+
|
|
278
|
+
const def = db.getSwitchFkQueryDef(
|
|
279
|
+
{ database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
280
|
+
"off",
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
it("Verify QueryDef", () => {
|
|
284
|
+
expect(def).toEqual({
|
|
285
|
+
type: "switchFk",
|
|
286
|
+
table: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
287
|
+
switch: "off",
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
292
|
+
const builder = createQueryBuilder(dialect);
|
|
293
|
+
expect(builder.build(def)).toMatchSql(expected.fkOff[dialect]);
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
describe("FK on", () => {
|
|
298
|
+
const db = createTestDb();
|
|
299
|
+
|
|
300
|
+
const def = db.getSwitchFkQueryDef(
|
|
301
|
+
{ database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
302
|
+
"on",
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
it("Verify QueryDef", () => {
|
|
306
|
+
expect(def).toEqual({
|
|
307
|
+
type: "switchFk",
|
|
308
|
+
table: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
309
|
+
switch: "on",
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
314
|
+
const builder = createQueryBuilder(dialect);
|
|
315
|
+
expect(builder.build(def)).toMatchSql(expected.fkOn[dialect]);
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
});
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UPSERT test expected SQL
|
|
3
|
+
*/
|
|
4
|
+
import { mysql, pgsql, tsql } from "@simplysm/core-common";
|
|
5
|
+
import type { ExpectedSql } from "../setup/test-utils";
|
|
6
|
+
|
|
7
|
+
//#region ========== UPSERT - Basic ==========
|
|
8
|
+
|
|
9
|
+
export const upsertSimple: ExpectedSql = {
|
|
10
|
+
mysql: mysql`
|
|
11
|
+
UPDATE \`TestDb\`.\`Employee\` AS \`T1\`
|
|
12
|
+
SET \`T1\`.\`name\` = 'new name'
|
|
13
|
+
WHERE \`T1\`.\`id\` <=> 1;
|
|
14
|
+
INSERT INTO \`TestDb\`.\`Employee\` (\`name\`, \`departmentId\`)
|
|
15
|
+
SELECT 'new name', 1
|
|
16
|
+
WHERE NOT EXISTS (SELECT * FROM \`TestDb\`.\`Employee\` AS \`T1\` WHERE \`T1\`.\`id\` <=> 1)
|
|
17
|
+
`,
|
|
18
|
+
mssql: tsql`
|
|
19
|
+
MERGE [TestDb].[TestSchema].[Employee] AS [T1]
|
|
20
|
+
USING (SELECT 1 AS [_]) AS [_src]
|
|
21
|
+
ON (([T1].[id] IS NULL AND 1 IS NULL) OR [T1].[id] = 1)
|
|
22
|
+
WHEN MATCHED THEN
|
|
23
|
+
UPDATE SET [name] = N'new name'
|
|
24
|
+
WHEN NOT MATCHED THEN
|
|
25
|
+
INSERT ([name], [departmentId]) VALUES (N'new name', 1);
|
|
26
|
+
`,
|
|
27
|
+
postgresql: pgsql`
|
|
28
|
+
WITH matched AS (
|
|
29
|
+
SELECT "T1".* FROM "TestSchema"."Employee" AS "T1"
|
|
30
|
+
WHERE "T1"."id" IS NOT DISTINCT FROM 1
|
|
31
|
+
),
|
|
32
|
+
updated AS (
|
|
33
|
+
UPDATE "TestSchema"."Employee" AS "T1"
|
|
34
|
+
SET "name" = 'new name'
|
|
35
|
+
WHERE "T1"."id" IS NOT DISTINCT FROM 1
|
|
36
|
+
RETURNING *
|
|
37
|
+
),
|
|
38
|
+
inserted AS (
|
|
39
|
+
INSERT INTO "TestSchema"."Employee" ("name", "departmentId")
|
|
40
|
+
SELECT 'new name', 1
|
|
41
|
+
WHERE NOT EXISTS (SELECT 1 FROM matched)
|
|
42
|
+
RETURNING *
|
|
43
|
+
)
|
|
44
|
+
SELECT * FROM updated UNION ALL SELECT * FROM inserted
|
|
45
|
+
`,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const upsertReuse: ExpectedSql = {
|
|
49
|
+
mysql: mysql`
|
|
50
|
+
UPDATE \`TestDb\`.\`Employee\` AS \`T1\`
|
|
51
|
+
SET \`T1\`.\`name\` = 'Gildong Hong', \`T1\`.\`departmentId\` = 2
|
|
52
|
+
WHERE \`T1\`.\`id\` <=> 1;
|
|
53
|
+
INSERT INTO \`TestDb\`.\`Employee\` (\`name\`, \`departmentId\`, \`managerId\`)
|
|
54
|
+
SELECT 'Gildong Hong', 2, 100
|
|
55
|
+
WHERE NOT EXISTS (SELECT * FROM \`TestDb\`.\`Employee\` AS \`T1\` WHERE \`T1\`.\`id\` <=> 1)
|
|
56
|
+
`,
|
|
57
|
+
mssql: tsql`
|
|
58
|
+
MERGE [TestDb].[TestSchema].[Employee] AS [T1]
|
|
59
|
+
USING (SELECT 1 AS [_]) AS [_src]
|
|
60
|
+
ON (([T1].[id] IS NULL AND 1 IS NULL) OR [T1].[id] = 1)
|
|
61
|
+
WHEN MATCHED THEN
|
|
62
|
+
UPDATE SET [name] = N'Gildong Hong', [departmentId] = 2
|
|
63
|
+
WHEN NOT MATCHED THEN
|
|
64
|
+
INSERT ([name], [departmentId], [managerId]) VALUES (N'Gildong Hong', 2, 100);
|
|
65
|
+
`,
|
|
66
|
+
postgresql: pgsql`
|
|
67
|
+
WITH matched AS (
|
|
68
|
+
SELECT "T1".* FROM "TestSchema"."Employee" AS "T1"
|
|
69
|
+
WHERE "T1"."id" IS NOT DISTINCT FROM 1
|
|
70
|
+
),
|
|
71
|
+
updated AS (
|
|
72
|
+
UPDATE "TestSchema"."Employee" AS "T1"
|
|
73
|
+
SET "name" = 'Gildong Hong', "departmentId" = 2
|
|
74
|
+
WHERE "T1"."id" IS NOT DISTINCT FROM 1
|
|
75
|
+
RETURNING *
|
|
76
|
+
),
|
|
77
|
+
inserted AS (
|
|
78
|
+
INSERT INTO "TestSchema"."Employee" ("name", "departmentId", "managerId")
|
|
79
|
+
SELECT 'Gildong Hong', 2, 100
|
|
80
|
+
WHERE NOT EXISTS (SELECT 1 FROM matched)
|
|
81
|
+
RETURNING *
|
|
82
|
+
)
|
|
83
|
+
SELECT * FROM updated UNION ALL SELECT * FROM inserted
|
|
84
|
+
`,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const upsertWithOutput: ExpectedSql = {
|
|
88
|
+
mysql: mysql`
|
|
89
|
+
CREATE TEMPORARY TABLE \`SD_TEMP\` AS SELECT \`id\` FROM \`TestDb\`.\`Employee\` AS \`T1\` WHERE \`T1\`.\`id\` <=> 1;
|
|
90
|
+
UPDATE \`TestDb\`.\`Employee\` AS \`T1\`
|
|
91
|
+
SET \`T1\`.\`name\` = 'New Name'
|
|
92
|
+
WHERE \`T1\`.\`id\` <=> 1;
|
|
93
|
+
INSERT INTO \`TestDb\`.\`Employee\` (\`name\`)
|
|
94
|
+
SELECT 'New Name'
|
|
95
|
+
WHERE NOT EXISTS (SELECT * FROM \`TestDb\`.\`Employee\` AS \`T1\` WHERE \`T1\`.\`id\` <=> 1);
|
|
96
|
+
SELECT \`id\`, \`name\` FROM \`TestDb\`.\`Employee\`
|
|
97
|
+
WHERE \`TestDb\`.\`Employee\`.\`id\` IN (SELECT \`id\` FROM \`SD_TEMP\`)
|
|
98
|
+
UNION ALL
|
|
99
|
+
SELECT \`id\`, \`name\` FROM \`TestDb\`.\`Employee\`
|
|
100
|
+
WHERE \`id\` = LAST_INSERT_ID() AND NOT EXISTS (SELECT 1 FROM \`SD_TEMP\`);
|
|
101
|
+
DROP TEMPORARY TABLE \`SD_TEMP\`
|
|
102
|
+
`,
|
|
103
|
+
mssql: tsql`
|
|
104
|
+
MERGE [TestDb].[TestSchema].[Employee] AS [T1]
|
|
105
|
+
USING (SELECT 1 AS [_]) AS [_src]
|
|
106
|
+
ON (([T1].[id] IS NULL AND 1 IS NULL) OR [T1].[id] = 1)
|
|
107
|
+
WHEN MATCHED THEN
|
|
108
|
+
UPDATE SET [name] = N'New Name'
|
|
109
|
+
WHEN NOT MATCHED THEN
|
|
110
|
+
INSERT ([name]) VALUES (N'New Name')
|
|
111
|
+
OUTPUT INSERTED.[id], INSERTED.[name];
|
|
112
|
+
`,
|
|
113
|
+
postgresql: pgsql`
|
|
114
|
+
WITH matched AS (
|
|
115
|
+
SELECT "T1".* FROM "TestSchema"."Employee" AS "T1"
|
|
116
|
+
WHERE "T1"."id" IS NOT DISTINCT FROM 1
|
|
117
|
+
),
|
|
118
|
+
updated AS (
|
|
119
|
+
UPDATE "TestSchema"."Employee" AS "T1"
|
|
120
|
+
SET "name" = 'New Name'
|
|
121
|
+
WHERE "T1"."id" IS NOT DISTINCT FROM 1
|
|
122
|
+
RETURNING "id", "name"
|
|
123
|
+
),
|
|
124
|
+
inserted AS (
|
|
125
|
+
INSERT INTO "TestSchema"."Employee" ("name")
|
|
126
|
+
SELECT 'New Name'
|
|
127
|
+
WHERE NOT EXISTS (SELECT 1 FROM matched)
|
|
128
|
+
RETURNING "id", "name"
|
|
129
|
+
)
|
|
130
|
+
SELECT * FROM updated UNION ALL SELECT * FROM inserted
|
|
131
|
+
`,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const upsertMultiWhere: ExpectedSql = {
|
|
135
|
+
mysql: mysql`
|
|
136
|
+
UPDATE \`TestDb\`.\`Employee\` AS \`T1\`
|
|
137
|
+
SET \`T1\`.\`managerId\` = 10
|
|
138
|
+
WHERE \`T1\`.\`name\` <=> 'Gildong Hong' AND \`T1\`.\`departmentId\` <=> 1;
|
|
139
|
+
INSERT INTO \`TestDb\`.\`Employee\` (\`name\`, \`departmentId\`, \`managerId\`)
|
|
140
|
+
SELECT 'Gildong Hong', 1, 10
|
|
141
|
+
WHERE NOT EXISTS (SELECT * FROM \`TestDb\`.\`Employee\` AS \`T1\` WHERE \`T1\`.\`name\` <=> 'Gildong Hong' AND \`T1\`.\`departmentId\` <=> 1)
|
|
142
|
+
`,
|
|
143
|
+
mssql: tsql`
|
|
144
|
+
MERGE [TestDb].[TestSchema].[Employee] AS [T1]
|
|
145
|
+
USING (SELECT 1 AS [_]) AS [_src]
|
|
146
|
+
ON (([T1].[name] IS NULL AND N'Gildong Hong' IS NULL) OR [T1].[name] = N'Gildong Hong')
|
|
147
|
+
AND (([T1].[departmentId] IS NULL AND 1 IS NULL) OR [T1].[departmentId] = 1)
|
|
148
|
+
WHEN MATCHED THEN
|
|
149
|
+
UPDATE SET [managerId] = 10
|
|
150
|
+
WHEN NOT MATCHED THEN
|
|
151
|
+
INSERT ([name], [departmentId], [managerId]) VALUES (N'Gildong Hong', 1, 10);
|
|
152
|
+
`,
|
|
153
|
+
postgresql: pgsql`
|
|
154
|
+
WITH matched AS (
|
|
155
|
+
SELECT "T1".* FROM "TestSchema"."Employee" AS "T1"
|
|
156
|
+
WHERE "T1"."name" IS NOT DISTINCT FROM 'Gildong Hong'
|
|
157
|
+
AND "T1"."departmentId" IS NOT DISTINCT FROM 1
|
|
158
|
+
),
|
|
159
|
+
updated AS (
|
|
160
|
+
UPDATE "TestSchema"."Employee" AS "T1"
|
|
161
|
+
SET "managerId" = 10
|
|
162
|
+
WHERE "T1"."name" IS NOT DISTINCT FROM 'Gildong Hong'
|
|
163
|
+
AND "T1"."departmentId" IS NOT DISTINCT FROM 1
|
|
164
|
+
RETURNING *
|
|
165
|
+
),
|
|
166
|
+
inserted AS (
|
|
167
|
+
INSERT INTO "TestSchema"."Employee" ("name", "departmentId", "managerId")
|
|
168
|
+
SELECT 'Gildong Hong', 1, 10
|
|
169
|
+
WHERE NOT EXISTS (SELECT 1 FROM matched)
|
|
170
|
+
RETURNING *
|
|
171
|
+
)
|
|
172
|
+
SELECT * FROM updated UNION ALL SELECT * FROM inserted
|
|
173
|
+
`,
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
export const upsertPlainValues: ExpectedSql = {
|
|
177
|
+
mysql: mysql`
|
|
178
|
+
UPDATE \`TestDb\`.\`Employee\` AS \`T1\`
|
|
179
|
+
SET \`T1\`.\`name\` = 'New Name'
|
|
180
|
+
WHERE \`T1\`.\`id\` <=> 1;
|
|
181
|
+
INSERT INTO \`TestDb\`.\`Employee\` (\`name\`, \`departmentId\`)
|
|
182
|
+
SELECT 'New Name', 1
|
|
183
|
+
WHERE NOT EXISTS (SELECT * FROM \`TestDb\`.\`Employee\` AS \`T1\` WHERE \`T1\`.\`id\` <=> 1)
|
|
184
|
+
`,
|
|
185
|
+
mssql: tsql`
|
|
186
|
+
MERGE [TestDb].[TestSchema].[Employee] AS [T1]
|
|
187
|
+
USING (SELECT 1 AS [_]) AS [_src]
|
|
188
|
+
ON (([T1].[id] IS NULL AND 1 IS NULL) OR [T1].[id] = 1)
|
|
189
|
+
WHEN MATCHED THEN
|
|
190
|
+
UPDATE SET [name] = N'New Name'
|
|
191
|
+
WHEN NOT MATCHED THEN
|
|
192
|
+
INSERT ([name], [departmentId]) VALUES (N'New Name', 1);
|
|
193
|
+
`,
|
|
194
|
+
postgresql: pgsql`
|
|
195
|
+
WITH matched AS (
|
|
196
|
+
SELECT "T1".* FROM "TestSchema"."Employee" AS "T1"
|
|
197
|
+
WHERE "T1"."id" IS NOT DISTINCT FROM 1
|
|
198
|
+
),
|
|
199
|
+
updated AS (
|
|
200
|
+
UPDATE "TestSchema"."Employee" AS "T1"
|
|
201
|
+
SET "name" = 'New Name'
|
|
202
|
+
WHERE "T1"."id" IS NOT DISTINCT FROM 1
|
|
203
|
+
RETURNING *
|
|
204
|
+
),
|
|
205
|
+
inserted AS (
|
|
206
|
+
INSERT INTO "TestSchema"."Employee" ("name", "departmentId")
|
|
207
|
+
SELECT 'New Name', 1
|
|
208
|
+
WHERE NOT EXISTS (SELECT 1 FROM matched)
|
|
209
|
+
RETURNING *
|
|
210
|
+
)
|
|
211
|
+
SELECT * FROM updated UNION ALL SELECT * FROM inserted
|
|
212
|
+
`,
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
//#endregion
|