@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.
- 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 +105 -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
package/dist/exec/queryable.js
CHANGED
|
@@ -18,19 +18,19 @@ class JoinQueryable {
|
|
|
18
18
|
this._joinAlias = _joinAlias;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* Specify the table to join
|
|
22
22
|
*
|
|
23
|
-
* @param table -
|
|
24
|
-
* @returns
|
|
23
|
+
* @param table - Table to join
|
|
24
|
+
* @returns Joined Queryable
|
|
25
25
|
*/
|
|
26
26
|
from(table) {
|
|
27
27
|
return queryable(this._db, table, this._joinAlias)();
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
30
|
+
* Directly specify columns in join result
|
|
31
31
|
*
|
|
32
|
-
* @param columns -
|
|
33
|
-
* @returns
|
|
32
|
+
* @param columns - Custom column definition
|
|
33
|
+
* @returns Queryable with custom columns applied
|
|
34
34
|
*/
|
|
35
35
|
select(columns) {
|
|
36
36
|
return new Queryable({
|
|
@@ -41,15 +41,15 @@ class JoinQueryable {
|
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
44
|
+
* Combine multiple Queryables with UNION
|
|
45
45
|
*
|
|
46
|
-
* @param queries -
|
|
47
|
-
* @returns UNION
|
|
48
|
-
* @throws 2
|
|
46
|
+
* @param queries - Array of Queryables to UNION (minimum 2)
|
|
47
|
+
* @returns UNION-ed Queryable
|
|
48
|
+
* @throws If less than 2 queryables are passed
|
|
49
49
|
*/
|
|
50
50
|
union(...queries) {
|
|
51
51
|
if (queries.length < 2) {
|
|
52
|
-
throw new ArgumentError("union
|
|
52
|
+
throw new ArgumentError("union requires at least 2 queryables.", {
|
|
53
53
|
provided: queries.length,
|
|
54
54
|
minimum: 2
|
|
55
55
|
});
|
|
@@ -58,7 +58,7 @@ class JoinQueryable {
|
|
|
58
58
|
return new Queryable({
|
|
59
59
|
db: first.meta.db,
|
|
60
60
|
from: queries,
|
|
61
|
-
// Queryable[]
|
|
61
|
+
// stored as Queryable[] array
|
|
62
62
|
as: this._joinAlias,
|
|
63
63
|
columns: transformColumnsAlias(first.meta.columns, this._joinAlias, "")
|
|
64
64
|
});
|
|
@@ -70,10 +70,10 @@ class RecursiveQueryable {
|
|
|
70
70
|
this._cteName = _cteName;
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
73
|
-
*
|
|
73
|
+
* specify the target table for recursive query
|
|
74
74
|
*
|
|
75
|
-
* @param table -
|
|
76
|
-
* @returns self
|
|
75
|
+
* @param table - Target table to recurse
|
|
76
|
+
* @returns Queryable with self property added (for self-reference)
|
|
77
77
|
*/
|
|
78
78
|
from(table) {
|
|
79
79
|
const selfAlias = `${this._cteName}.self`;
|
|
@@ -89,10 +89,10 @@ class RecursiveQueryable {
|
|
|
89
89
|
);
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
|
-
*
|
|
92
|
+
* Directly specify columns in recursive query
|
|
93
93
|
*
|
|
94
|
-
* @param columns -
|
|
95
|
-
* @returns self
|
|
94
|
+
* @param columns - Custom column definition
|
|
95
|
+
* @returns Queryable with self property added
|
|
96
96
|
*/
|
|
97
97
|
select(columns) {
|
|
98
98
|
const selfAlias = `${this._cteName}.self`;
|
|
@@ -113,15 +113,15 @@ class RecursiveQueryable {
|
|
|
113
113
|
);
|
|
114
114
|
}
|
|
115
115
|
/**
|
|
116
|
-
*
|
|
116
|
+
* Combine multiple Queryables with UNION (for recursive query)
|
|
117
117
|
*
|
|
118
|
-
* @param queries -
|
|
119
|
-
* @returns
|
|
120
|
-
* @throws 2
|
|
118
|
+
* @param queries - Array of Queryables to UNION (minimum 2)
|
|
119
|
+
* @returns UNION Queryable with self property added
|
|
120
|
+
* @throws If less than 2 queryables are passed
|
|
121
121
|
*/
|
|
122
122
|
union(...queries) {
|
|
123
123
|
if (queries.length < 2) {
|
|
124
|
-
throw new ArgumentError("union
|
|
124
|
+
throw new ArgumentError("union requires at least 2 queryables.", {
|
|
125
125
|
provided: queries.length,
|
|
126
126
|
minimum: 2
|
|
127
127
|
});
|
|
@@ -131,7 +131,7 @@ class RecursiveQueryable {
|
|
|
131
131
|
return new Queryable({
|
|
132
132
|
db: first.meta.db,
|
|
133
133
|
from: queries,
|
|
134
|
-
// Queryable[]
|
|
134
|
+
// stored as Queryable[] array
|
|
135
135
|
as: this._cteName,
|
|
136
136
|
columns: transformColumnsAlias(first.meta.columns, this._cteName, "")
|
|
137
137
|
}).join(
|
|
@@ -150,12 +150,12 @@ class Queryable {
|
|
|
150
150
|
constructor(meta) {
|
|
151
151
|
this.meta = meta;
|
|
152
152
|
}
|
|
153
|
-
//#region ==========
|
|
153
|
+
//#region ========== option - SELECT / DISTINCT / LOCK ==========
|
|
154
154
|
/**
|
|
155
|
-
*
|
|
155
|
+
* Specify columns to SELECT.
|
|
156
156
|
*
|
|
157
|
-
* @param fn -
|
|
158
|
-
* @returns
|
|
157
|
+
* @param fn - Column mapping function. Receives original columns and returns new column structure
|
|
158
|
+
* @returns Queryable with new column structure applied
|
|
159
159
|
*
|
|
160
160
|
* @example
|
|
161
161
|
* ```typescript
|
|
@@ -182,9 +182,9 @@ class Queryable {
|
|
|
182
182
|
});
|
|
183
183
|
}
|
|
184
184
|
/**
|
|
185
|
-
* DISTINCT
|
|
185
|
+
* Apply DISTINCT option to remove duplicate rows
|
|
186
186
|
*
|
|
187
|
-
* @returns DISTINCT
|
|
187
|
+
* @returns Queryable with DISTINCT applied
|
|
188
188
|
*
|
|
189
189
|
* @example
|
|
190
190
|
* ```typescript
|
|
@@ -207,11 +207,11 @@ class Queryable {
|
|
|
207
207
|
});
|
|
208
208
|
}
|
|
209
209
|
/**
|
|
210
|
-
*
|
|
210
|
+
* Apply row lock (FOR UPDATE)
|
|
211
211
|
*
|
|
212
|
-
*
|
|
212
|
+
* Acquire exclusive lock on selected rows within transaction
|
|
213
213
|
*
|
|
214
|
-
* @returns
|
|
214
|
+
* @returns Queryable with lock applied
|
|
215
215
|
*
|
|
216
216
|
* @example
|
|
217
217
|
* ```typescript
|
|
@@ -237,16 +237,16 @@ class Queryable {
|
|
|
237
237
|
});
|
|
238
238
|
}
|
|
239
239
|
//#endregion
|
|
240
|
-
//#region ==========
|
|
240
|
+
//#region ========== restrict - TOP / LIMIT ==========
|
|
241
241
|
/**
|
|
242
|
-
*
|
|
242
|
+
* Select only top N rows (can be used without ORDER BY)
|
|
243
243
|
*
|
|
244
|
-
* @param count -
|
|
245
|
-
* @returns TOP
|
|
244
|
+
* @param count - number of rows to select
|
|
245
|
+
* @returns Queryable with TOP applied
|
|
246
246
|
*
|
|
247
247
|
* @example
|
|
248
248
|
* ```typescript
|
|
249
|
-
* //
|
|
249
|
+
* // Latest 10 users
|
|
250
250
|
* db.user()
|
|
251
251
|
* .orderBy((u) => u.createdAt, "DESC")
|
|
252
252
|
* .top(10)
|
|
@@ -266,19 +266,19 @@ class Queryable {
|
|
|
266
266
|
});
|
|
267
267
|
}
|
|
268
268
|
/**
|
|
269
|
-
*
|
|
270
|
-
*
|
|
269
|
+
* Set LIMIT/OFFSET for pagination.
|
|
270
|
+
* Must call orderBy() first.
|
|
271
271
|
*
|
|
272
|
-
* @param skip -
|
|
273
|
-
* @param take -
|
|
274
|
-
* @returns
|
|
275
|
-
* @throws ORDER BY
|
|
272
|
+
* @param skip - number of rows to skip (OFFSET)
|
|
273
|
+
* @param take - number of rows to fetch (LIMIT)
|
|
274
|
+
* @returns Queryable with pagination applied
|
|
275
|
+
* @throws Error if no ORDER BY clause
|
|
276
276
|
*
|
|
277
277
|
* @example
|
|
278
278
|
* ```typescript
|
|
279
279
|
* db.user
|
|
280
280
|
* .orderBy((u) => u.createdAt)
|
|
281
|
-
* .limit(0, 20) //
|
|
281
|
+
* .limit(0, 20) // first 20
|
|
282
282
|
* ```
|
|
283
283
|
*/
|
|
284
284
|
limit(skip, take) {
|
|
@@ -290,7 +290,7 @@ class Queryable {
|
|
|
290
290
|
});
|
|
291
291
|
}
|
|
292
292
|
if (!this.meta.orderBy) {
|
|
293
|
-
throw new ArgumentError("limit()
|
|
293
|
+
throw new ArgumentError("limit() requires ORDER BY clause.", {
|
|
294
294
|
method: "limit",
|
|
295
295
|
required: "orderBy"
|
|
296
296
|
});
|
|
@@ -301,13 +301,13 @@ class Queryable {
|
|
|
301
301
|
});
|
|
302
302
|
}
|
|
303
303
|
//#endregion
|
|
304
|
-
//#region ==========
|
|
304
|
+
//#region ========== sorting - ORDER BY ==========
|
|
305
305
|
/**
|
|
306
|
-
*
|
|
306
|
+
* Add sorting condition. Multiple calls apply in order.
|
|
307
307
|
*
|
|
308
|
-
* @param fn -
|
|
309
|
-
* @param orderBy -
|
|
310
|
-
* @returns
|
|
308
|
+
* @param fn - function returning columns to sort by
|
|
309
|
+
* @param orderBy - Sort direction (ASC/DESC). Default: ASC
|
|
310
|
+
* @returns sorting 조건이 추가된 Queryable
|
|
311
311
|
*
|
|
312
312
|
* @example
|
|
313
313
|
* ```typescript
|
|
@@ -333,9 +333,9 @@ class Queryable {
|
|
|
333
333
|
//#endregion
|
|
334
334
|
//#region ========== 검색 - WHERE ==========
|
|
335
335
|
/**
|
|
336
|
-
* WHERE
|
|
336
|
+
* WHERE condition을 추가합니다. 여러 번 호출하면 AND로 결합됩니다.
|
|
337
337
|
*
|
|
338
|
-
* @param predicate -
|
|
338
|
+
* @param predicate - Condition 배열을 반환하는 function
|
|
339
339
|
* @returns 조건이 추가된 Queryable
|
|
340
340
|
*
|
|
341
341
|
* @example
|
|
@@ -363,18 +363,18 @@ class Queryable {
|
|
|
363
363
|
* 텍스트 검색을 수행
|
|
364
364
|
*
|
|
365
365
|
* 검색 문법은 {@link parseSearchQuery}를 참조
|
|
366
|
-
* - 공백으로 구분된 단어는 OR
|
|
367
|
-
* - `+`로 시작하는 단어는
|
|
368
|
-
* - `-`로 시작하는 단어는
|
|
366
|
+
* - 공백으로 구분된 단어는 OR condition
|
|
367
|
+
* - `+`로 시작하는 단어는 required include (AND Condition)
|
|
368
|
+
* - `-`로 시작하는 단어는 exclude (NOT Condition)
|
|
369
369
|
*
|
|
370
|
-
* @param fn - 검색 대상
|
|
370
|
+
* @param fn - 검색 대상 column을 반환하는 function
|
|
371
371
|
* @param searchText - 검색 텍스트
|
|
372
372
|
* @returns 검색 조건이 추가된 Queryable
|
|
373
373
|
*
|
|
374
374
|
* @example
|
|
375
375
|
* ```typescript
|
|
376
376
|
* db.user()
|
|
377
|
-
* .search((u) => [u.name, u.email], "
|
|
377
|
+
* .search((u) => [u.name, u.email], "Gildong Hong -탈퇴")
|
|
378
378
|
* ```
|
|
379
379
|
*/
|
|
380
380
|
search(fn, searchText) {
|
|
@@ -420,10 +420,10 @@ class Queryable {
|
|
|
420
420
|
//#endregion
|
|
421
421
|
//#region ========== 그룹 - GROUP BY / HAVING ==========
|
|
422
422
|
/**
|
|
423
|
-
* GROUP BY 절을
|
|
423
|
+
* GROUP BY 절을 Add
|
|
424
424
|
*
|
|
425
|
-
* @param fn -
|
|
426
|
-
* @returns GROUP BY
|
|
425
|
+
* @param fn - Group화 기준 column을 반환하는 function
|
|
426
|
+
* @returns Queryable with GROUP BY applied
|
|
427
427
|
*
|
|
428
428
|
* @example
|
|
429
429
|
* ```typescript
|
|
@@ -447,10 +447,10 @@ class Queryable {
|
|
|
447
447
|
return new Queryable({ ...this.meta, groupBy });
|
|
448
448
|
}
|
|
449
449
|
/**
|
|
450
|
-
* HAVING 절을
|
|
450
|
+
* HAVING 절을 Add (GROUP BY 후 filtering)
|
|
451
451
|
*
|
|
452
|
-
* @param predicate -
|
|
453
|
-
* @returns HAVING이
|
|
452
|
+
* @param predicate - Condition 배열을 반환하는 function
|
|
453
|
+
* @returns HAVING이 apply된 Queryable
|
|
454
454
|
*
|
|
455
455
|
* @example
|
|
456
456
|
* ```typescript
|
|
@@ -478,13 +478,13 @@ class Queryable {
|
|
|
478
478
|
});
|
|
479
479
|
}
|
|
480
480
|
//#endregion
|
|
481
|
-
//#region ==========
|
|
481
|
+
//#region ========== join - JOIN / JOIN SINGLE ==========
|
|
482
482
|
/**
|
|
483
|
-
* 1:N 관계의 LEFT OUTER JOIN을 수행 (배열로
|
|
483
|
+
* 1:N 관계의 LEFT OUTER JOIN을 수행 (배열로 result Add)
|
|
484
484
|
*
|
|
485
|
-
* @param as -
|
|
486
|
-
* @param fwd -
|
|
487
|
-
* @returns
|
|
485
|
+
* @param as - Result에 추가할 property 이름
|
|
486
|
+
* @param fwd - Join 조건을 정의하는 콜백 function
|
|
487
|
+
* @returns join 결과가 배열로 추가된 Queryable
|
|
488
488
|
*
|
|
489
489
|
* @example
|
|
490
490
|
* ```typescript
|
|
@@ -493,7 +493,7 @@ class Queryable {
|
|
|
493
493
|
* qr.from(Post)
|
|
494
494
|
* .where((p) => [expr.eq(p.userId, u.id)])
|
|
495
495
|
* )
|
|
496
|
-
* //
|
|
496
|
+
* // Result: { id, name, posts: [{ id, title }, ...] }
|
|
497
497
|
* ```
|
|
498
498
|
*/
|
|
499
499
|
join(as, fwd) {
|
|
@@ -520,11 +520,11 @@ class Queryable {
|
|
|
520
520
|
});
|
|
521
521
|
}
|
|
522
522
|
/**
|
|
523
|
-
* N:1 또는 1:1 관계의 LEFT OUTER JOIN을 수행 (단일 객체로
|
|
523
|
+
* N:1 또는 1:1 관계의 LEFT OUTER JOIN을 수행 (단일 객체로 result Add)
|
|
524
524
|
*
|
|
525
|
-
* @param as -
|
|
526
|
-
* @param fwd -
|
|
527
|
-
* @returns
|
|
525
|
+
* @param as - Result에 추가할 property 이름
|
|
526
|
+
* @param fwd - Join 조건을 정의하는 콜백 function
|
|
527
|
+
* @returns join 결과가 단일 객체로 추가된 Queryable
|
|
528
528
|
*
|
|
529
529
|
* @example
|
|
530
530
|
* ```typescript
|
|
@@ -533,7 +533,7 @@ class Queryable {
|
|
|
533
533
|
* qr.from(User)
|
|
534
534
|
* .where((u) => [expr.eq(u.id, p.userId)])
|
|
535
535
|
* )
|
|
536
|
-
* //
|
|
536
|
+
* // Result: { id, title, user: { id, name } | undefined }
|
|
537
537
|
* ```
|
|
538
538
|
*/
|
|
539
539
|
joinSingle(as, fwd) {
|
|
@@ -560,24 +560,24 @@ class Queryable {
|
|
|
560
560
|
});
|
|
561
561
|
}
|
|
562
562
|
//#endregion
|
|
563
|
-
//#region ==========
|
|
563
|
+
//#region ========== join - INCLUDE ==========
|
|
564
564
|
/**
|
|
565
|
-
* 관계된
|
|
565
|
+
* 관계된 Table을 automatic으로 JOIN합니다.
|
|
566
566
|
* TableBuilder에 정의된 FK/FKT 관계를 기반으로 동작합니다.
|
|
567
567
|
*
|
|
568
|
-
* @param fn - 포함할 관계를 선택하는
|
|
568
|
+
* @param fn - 포함할 관계를 선택하는 function (PathProxy를 통해 type 체크됨)
|
|
569
569
|
* @returns JOIN이 추가된 Queryable
|
|
570
570
|
* @throws 관계가 정의되지 않은 경우 에러
|
|
571
571
|
*
|
|
572
572
|
* @example
|
|
573
573
|
* ```typescript
|
|
574
|
-
* // 단일
|
|
574
|
+
* // 단일 relationship include
|
|
575
575
|
* db.post.include((p) => p.user)
|
|
576
576
|
*
|
|
577
|
-
* // 중첩
|
|
577
|
+
* // 중첩 relationship include
|
|
578
578
|
* db.post.include((p) => p.user.company)
|
|
579
579
|
*
|
|
580
|
-
* // 다중
|
|
580
|
+
* // 다중 relationship include
|
|
581
581
|
* db.user
|
|
582
582
|
* .include((u) => u.company)
|
|
583
583
|
* .include((u) => u.posts)
|
|
@@ -605,7 +605,7 @@ class Queryable {
|
|
|
605
605
|
const chainParts = [];
|
|
606
606
|
for (const relationName of relationNames) {
|
|
607
607
|
if (!(currentTable instanceof TableBuilder)) {
|
|
608
|
-
throw new Error("include()
|
|
608
|
+
throw new Error("include() can only be used on TableBuilder-based queryables.");
|
|
609
609
|
}
|
|
610
610
|
const parentChain = chainParts.join(".");
|
|
611
611
|
chainParts.push(relationName);
|
|
@@ -620,7 +620,7 @@ class Queryable {
|
|
|
620
620
|
}
|
|
621
621
|
const relationDef = (_b = currentTable.meta.relations) == null ? void 0 : _b[relationName];
|
|
622
622
|
if (relationDef == null) {
|
|
623
|
-
throw new Error(
|
|
623
|
+
throw new Error(`Relation '${relationName}' not found.`);
|
|
624
624
|
}
|
|
625
625
|
if (relationDef instanceof ForeignKeyBuilder || relationDef instanceof RelationKeyBuilder) {
|
|
626
626
|
const targetTable = relationDef.meta.targetFn();
|
|
@@ -645,7 +645,7 @@ class Queryable {
|
|
|
645
645
|
const sourceFk = (_c = targetTable.meta.relations) == null ? void 0 : _c[fkRelName];
|
|
646
646
|
if (!(sourceFk instanceof ForeignKeyBuilder) && !(sourceFk instanceof RelationKeyBuilder)) {
|
|
647
647
|
throw new Error(
|
|
648
|
-
`'${relationName}'\uC774 \uCC38\uC870\uD558\uB294 '${fkRelName}'\uC774(\uAC00) ${targetTable.meta.name} \
|
|
648
|
+
`'${relationName}'\uC774 \uCC38\uC870\uD558\uB294 '${fkRelName}'\uC774(\uAC00) ${targetTable.meta.name} Table\uC758 \uC720\uD6A8\uD55C ForeignKey/RelationKey\uAC00 \uC544\uB2D9\uB2C8\uB2E4.`
|
|
649
649
|
);
|
|
650
650
|
}
|
|
651
651
|
const sourceTable = targetTable;
|
|
@@ -671,13 +671,13 @@ class Queryable {
|
|
|
671
671
|
return result;
|
|
672
672
|
}
|
|
673
673
|
//#endregion
|
|
674
|
-
//#region ==========
|
|
674
|
+
//#region ========== Subquery - WRAP / UNION ==========
|
|
675
675
|
/**
|
|
676
|
-
* 현재 Queryable을
|
|
676
|
+
* 현재 Queryable을 Subquery로 감싸기
|
|
677
677
|
*
|
|
678
678
|
* distinct() 또는 groupBy() 후 count() 사용 시 필요
|
|
679
679
|
*
|
|
680
|
-
* @returns
|
|
680
|
+
* @returns Subquery로 감싸진 Queryable
|
|
681
681
|
*
|
|
682
682
|
* @example
|
|
683
683
|
* ```typescript
|
|
@@ -699,11 +699,11 @@ class Queryable {
|
|
|
699
699
|
});
|
|
700
700
|
}
|
|
701
701
|
/**
|
|
702
|
-
*
|
|
702
|
+
* Combine multiple Queryables with UNION (remove duplicates)
|
|
703
703
|
*
|
|
704
|
-
* @param queries -
|
|
705
|
-
* @returns UNION
|
|
706
|
-
* @throws 2
|
|
704
|
+
* @param queries - Array of Queryables to UNION (minimum 2)
|
|
705
|
+
* @returns UNION-ed Queryable
|
|
706
|
+
* @throws If less than 2 queryables are passed
|
|
707
707
|
*
|
|
708
708
|
* @example
|
|
709
709
|
* ```typescript
|
|
@@ -715,7 +715,7 @@ class Queryable {
|
|
|
715
715
|
*/
|
|
716
716
|
static union(...queries) {
|
|
717
717
|
if (queries.length < 2) {
|
|
718
|
-
throw new ArgumentError("union
|
|
718
|
+
throw new ArgumentError("union requires at least 2 queryables.", {
|
|
719
719
|
provided: queries.length,
|
|
720
720
|
minimum: 2
|
|
721
721
|
});
|
|
@@ -725,20 +725,20 @@ class Queryable {
|
|
|
725
725
|
return new Queryable({
|
|
726
726
|
db: first.meta.db,
|
|
727
727
|
from: queries,
|
|
728
|
-
// Queryable[]
|
|
728
|
+
// stored as Queryable[] array
|
|
729
729
|
as: unionAlias,
|
|
730
730
|
columns: transformColumnsAlias(first.meta.columns, unionAlias, "")
|
|
731
731
|
});
|
|
732
732
|
}
|
|
733
733
|
//#endregion
|
|
734
|
-
//#region ==========
|
|
734
|
+
//#region ========== recursive - WITH RECURSIVE ==========
|
|
735
735
|
/**
|
|
736
|
-
*
|
|
736
|
+
* recursive CTE(Common Table Expression)를 Generate
|
|
737
737
|
*
|
|
738
|
-
* 계층
|
|
738
|
+
* 계층 structure data(조직도, 카테고리 트리 등)를 조회할 때 사용
|
|
739
739
|
*
|
|
740
|
-
* @param fwd -
|
|
741
|
-
* @returns
|
|
740
|
+
* @param fwd - recursive part을 정의하는 콜백 function
|
|
741
|
+
* @returns recursive CTE가 apply된 Queryable
|
|
742
742
|
*
|
|
743
743
|
* @example
|
|
744
744
|
* ```typescript
|
|
@@ -771,17 +771,17 @@ class Queryable {
|
|
|
771
771
|
with: {
|
|
772
772
|
name: cteName,
|
|
773
773
|
base: this,
|
|
774
|
-
//
|
|
774
|
+
// circular 참조 Type inference 차단
|
|
775
775
|
recursive: resultQr
|
|
776
776
|
}
|
|
777
777
|
});
|
|
778
778
|
}
|
|
779
779
|
//#endregion
|
|
780
|
-
//#region ========== [
|
|
780
|
+
//#region ========== [query] 조회 - SELECT ==========
|
|
781
781
|
/**
|
|
782
|
-
* SELECT
|
|
782
|
+
* SELECT query를 실행하고 result 배열을 return
|
|
783
783
|
*
|
|
784
|
-
* @returns
|
|
784
|
+
* @returns Query result array
|
|
785
785
|
*
|
|
786
786
|
* @example
|
|
787
787
|
* ```typescript
|
|
@@ -798,9 +798,9 @@ class Queryable {
|
|
|
798
798
|
return results[0];
|
|
799
799
|
}
|
|
800
800
|
/**
|
|
801
|
-
* 단일 결과를
|
|
801
|
+
* 단일 결과를 return (2개 이상이면 Error)
|
|
802
802
|
*
|
|
803
|
-
* @returns 단일
|
|
803
|
+
* @returns 단일 result 또는 undefined
|
|
804
804
|
* @throws 2개 이상의 결과가 반환된 경우
|
|
805
805
|
*
|
|
806
806
|
* @example
|
|
@@ -813,7 +813,7 @@ class Queryable {
|
|
|
813
813
|
async single() {
|
|
814
814
|
const result = await this.top(2).result();
|
|
815
815
|
if (result.length > 1) {
|
|
816
|
-
throw new ArgumentError("
|
|
816
|
+
throw new ArgumentError("Expected single result but multiple results returned.", {
|
|
817
817
|
table: this._getSourceName(),
|
|
818
818
|
resultCount: result.length
|
|
819
819
|
});
|
|
@@ -821,7 +821,7 @@ class Queryable {
|
|
|
821
821
|
return result[0];
|
|
822
822
|
}
|
|
823
823
|
/**
|
|
824
|
-
*
|
|
824
|
+
* query 소스 이름 return (error message용)
|
|
825
825
|
*/
|
|
826
826
|
_getSourceName() {
|
|
827
827
|
const from = this.meta.from;
|
|
@@ -834,9 +834,9 @@ class Queryable {
|
|
|
834
834
|
return this.meta.as;
|
|
835
835
|
}
|
|
836
836
|
/**
|
|
837
|
-
* 첫 번째 결과를
|
|
837
|
+
* 첫 번째 결과를 return (여러 개여도 첫 번째만)
|
|
838
838
|
*
|
|
839
|
-
* @returns 첫 번째
|
|
839
|
+
* @returns 첫 번째 result 또는 undefined
|
|
840
840
|
*
|
|
841
841
|
* @example
|
|
842
842
|
* ```typescript
|
|
@@ -850,10 +850,10 @@ class Queryable {
|
|
|
850
850
|
return results[0];
|
|
851
851
|
}
|
|
852
852
|
/**
|
|
853
|
-
*
|
|
853
|
+
* result row 수를 return
|
|
854
854
|
*
|
|
855
|
-
* @param fwd - 카운트할
|
|
856
|
-
* @returns
|
|
855
|
+
* @param fwd - 카운트할 column을 지정하는 function (Select)
|
|
856
|
+
* @returns row 수
|
|
857
857
|
* @throws distinct() 또는 groupBy() 후 직접 호출 시 에러 (wrap() 필요)
|
|
858
858
|
*
|
|
859
859
|
* @example
|
|
@@ -865,17 +865,17 @@ class Queryable {
|
|
|
865
865
|
*/
|
|
866
866
|
async count(fwd) {
|
|
867
867
|
if (this.meta.distinct) {
|
|
868
|
-
throw new Error("
|
|
868
|
+
throw new Error("Cannot use count() after distinct(). Use wrap() first.");
|
|
869
869
|
}
|
|
870
870
|
if (this.meta.groupBy) {
|
|
871
|
-
throw new Error("
|
|
871
|
+
throw new Error("Cannot use count() after groupBy(). Use wrap() first.");
|
|
872
872
|
}
|
|
873
873
|
const countQr = fwd ? this.select((c) => ({ cnt: expr.count(fwd(c)) })) : this.select(() => ({ cnt: expr.count() }));
|
|
874
874
|
const result = await countQr.single();
|
|
875
875
|
return (result == null ? void 0 : result.cnt) ?? 0;
|
|
876
876
|
}
|
|
877
877
|
/**
|
|
878
|
-
* 조건에 맞는
|
|
878
|
+
* 조건에 맞는 data 존재 여부를 확인
|
|
879
879
|
*
|
|
880
880
|
* @returns 존재하면 true, 없으면 false
|
|
881
881
|
*
|
|
@@ -1160,7 +1160,7 @@ class Queryable {
|
|
|
1160
1160
|
//#endregion
|
|
1161
1161
|
//#region ========== DDL Helper ==========
|
|
1162
1162
|
/**
|
|
1163
|
-
* FK
|
|
1163
|
+
* FK constraint on/off (transaction 내 사용 가능)
|
|
1164
1164
|
*/
|
|
1165
1165
|
async switchFk(switch_) {
|
|
1166
1166
|
const from = this.meta.from;
|
|
@@ -1177,7 +1177,7 @@ class Queryable {
|
|
|
1177
1177
|
const from = this.meta.from;
|
|
1178
1178
|
if (from instanceof TableBuilder) {
|
|
1179
1179
|
if (from.meta.columns == null) {
|
|
1180
|
-
throw new Error(
|
|
1180
|
+
throw new Error(`Table '${from.meta.name}' has no Column definition.`);
|
|
1181
1181
|
}
|
|
1182
1182
|
let aiColName;
|
|
1183
1183
|
for (const [key, col] of Object.entries(from.meta.columns)) {
|
|
@@ -1190,7 +1190,7 @@ class Queryable {
|
|
|
1190
1190
|
aiColName
|
|
1191
1191
|
};
|
|
1192
1192
|
}
|
|
1193
|
-
throw new Error("CUD
|
|
1193
|
+
throw new Error("CUD operations can only be used on TableBuilder-based queryables.");
|
|
1194
1194
|
}
|
|
1195
1195
|
//#endregion
|
|
1196
1196
|
}
|
|
@@ -1198,7 +1198,7 @@ function getMatchedPrimaryKeys(fkCols, targetTable) {
|
|
|
1198
1198
|
const pk = targetTable.meta.primaryKey;
|
|
1199
1199
|
if (pk == null || fkCols.length !== pk.length) {
|
|
1200
1200
|
throw new Error(
|
|
1201
|
-
`FK/PK
|
|
1201
|
+
`FK/PK column \uAC1C\uC218\uAC00 \uC77C\uCE58\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 (\uB300\uC0C1: ${targetTable.meta.name}, FK: ${fkCols.length}\uAC1C, PK: ${(pk == null ? void 0 : pk.length) ?? 0}\uAC1C)`
|
|
1202
1202
|
);
|
|
1203
1203
|
}
|
|
1204
1204
|
return pk;
|
|
@@ -1259,7 +1259,7 @@ function queryable(db, tableOrView, as) {
|
|
|
1259
1259
|
columns: transformColumnsAlias(baseQr.meta.columns, finalAs)
|
|
1260
1260
|
});
|
|
1261
1261
|
}
|
|
1262
|
-
throw new Error(
|
|
1262
|
+
throw new Error(`Invalid Table/View Metadata: ${tableOrView.meta.name}`);
|
|
1263
1263
|
};
|
|
1264
1264
|
}
|
|
1265
1265
|
export {
|