@simplysm/orm-common 13.0.28 → 13.0.30
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 +210 -3
- package/dist/create-db-context.d.ts.map +1 -1
- package/dist/create-db-context.js +7 -2
- package/dist/create-db-context.js.map +1 -1
- package/dist/ddl/column-ddl.d.ts.map +1 -1
- package/dist/ddl/column-ddl.js.map +1 -1
- package/dist/ddl/initialize.d.ts.map +1 -1
- package/dist/ddl/initialize.js.map +1 -1
- package/dist/ddl/relation-ddl.d.ts.map +1 -1
- package/dist/ddl/relation-ddl.js.map +1 -1
- package/dist/ddl/schema-ddl.d.ts.map +1 -1
- package/dist/ddl/schema-ddl.js.map +1 -1
- package/dist/ddl/table-ddl.d.ts.map +1 -1
- package/dist/ddl/table-ddl.js.map +1 -1
- package/dist/define-db-context.d.ts.map +1 -1
- package/dist/define-db-context.js.map +1 -1
- package/dist/exec/executable.d.ts.map +1 -1
- package/dist/exec/executable.js.map +1 -1
- package/dist/exec/queryable.d.ts.map +1 -1
- package/dist/exec/queryable.js +19 -6
- package/dist/exec/queryable.js.map +1 -1
- package/dist/exec/search-parser.js.map +1 -1
- package/dist/expr/expr.d.ts.map +1 -1
- package/dist/expr/expr.js.map +1 -1
- package/dist/query-builder/base/query-builder-base.d.ts.map +1 -1
- package/dist/query-builder/base/query-builder-base.js +3 -1
- package/dist/query-builder/base/query-builder-base.js.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.js +3 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.js +9 -3
- package/dist/query-builder/mssql/mssql-query-builder.js.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.js +3 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.js +12 -4
- package/dist/query-builder/mysql/mysql-query-builder.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js +3 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.js +21 -7
- package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
- package/dist/schema/factory/column-builder.d.ts.map +1 -1
- package/dist/schema/factory/column-builder.js.map +1 -1
- package/dist/schema/factory/relation-builder.d.ts.map +1 -1
- package/dist/schema/factory/relation-builder.js.map +1 -1
- package/dist/schema/procedure-builder.d.ts.map +1 -1
- package/dist/schema/procedure-builder.js.map +1 -1
- package/dist/schema/table-builder.d.ts.map +1 -1
- package/dist/schema/table-builder.js +3 -1
- package/dist/schema/table-builder.js.map +1 -1
- package/dist/schema/view-builder.d.ts.map +1 -1
- package/dist/schema/view-builder.js +3 -1
- package/dist/schema/view-builder.js.map +1 -1
- package/dist/types/db-context-def.d.ts.map +1 -1
- package/dist/types/db.d.ts.map +1 -1
- package/dist/utils/result-parser.js +3 -1
- package/dist/utils/result-parser.js.map +1 -1
- package/docs/queries.md +89 -5
- package/docs/schema.md +12 -20
- package/package.json +2 -2
- package/src/create-db-context.ts +53 -15
- package/src/ddl/column-ddl.ts +4 -1
- package/src/ddl/initialize.ts +13 -3
- package/src/ddl/relation-ddl.ts +4 -1
- package/src/ddl/schema-ddl.ts +8 -2
- package/src/ddl/table-ddl.ts +12 -3
- package/src/define-db-context.ts +3 -1
- package/src/exec/executable.ts +4 -1
- package/src/exec/queryable.ts +91 -26
- package/src/exec/search-parser.ts +5 -1
- package/src/expr/expr.ts +56 -15
- package/src/query-builder/base/query-builder-base.ts +3 -1
- package/src/query-builder/mssql/mssql-expr-renderer.ts +6 -2
- package/src/query-builder/mssql/mssql-query-builder.ts +15 -5
- package/src/query-builder/mysql/mysql-expr-renderer.ts +6 -2
- package/src/query-builder/mysql/mysql-query-builder.ts +19 -6
- package/src/query-builder/postgresql/postgresql-expr-renderer.ts +6 -2
- package/src/query-builder/postgresql/postgresql-query-builder.ts +35 -13
- package/src/schema/factory/column-builder.ts +16 -5
- package/src/schema/factory/relation-builder.ts +14 -4
- package/src/schema/procedure-builder.ts +4 -1
- package/src/schema/table-builder.ts +14 -3
- package/src/schema/view-builder.ts +5 -1
- package/src/types/db-context-def.ts +37 -8
- package/src/types/db.ts +9 -2
- package/src/utils/result-parser.ts +10 -3
|
@@ -465,7 +465,9 @@ export class PostgresqlExprRenderer extends ExprRendererBase {
|
|
|
465
465
|
}
|
|
466
466
|
|
|
467
467
|
protected switch(expr: ExprSwitch): string {
|
|
468
|
-
const cases = expr.cases
|
|
468
|
+
const cases = expr.cases
|
|
469
|
+
.map((c) => `WHEN ${this.render(c.when)} THEN ${this.render(c.then)}`)
|
|
470
|
+
.join(" ");
|
|
469
471
|
return `CASE ${cases} ELSE ${this.render(expr.else)} END`;
|
|
470
472
|
}
|
|
471
473
|
|
|
@@ -589,7 +591,9 @@ export class PostgresqlExprRenderer extends ExprRendererBase {
|
|
|
589
591
|
parts.push(`PARTITION BY ${spec.partitionBy.map((p) => this.render(p)).join(", ")}`);
|
|
590
592
|
}
|
|
591
593
|
if (spec.orderBy != null && spec.orderBy.length > 0) {
|
|
592
|
-
const orderParts = spec.orderBy.map(
|
|
594
|
+
const orderParts = spec.orderBy.map(
|
|
595
|
+
([expr, dir]) => `${this.render(expr)}${dir != null ? ` ${dir}` : ""}`,
|
|
596
|
+
);
|
|
593
597
|
parts.push(`ORDER BY ${orderParts.join(", ")}`);
|
|
594
598
|
}
|
|
595
599
|
return parts.join(" ");
|
|
@@ -71,7 +71,10 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
71
71
|
protected renderJoin(join: SelectQueryDefJoin): string {
|
|
72
72
|
const from = this.renderFrom(join.from);
|
|
73
73
|
const alias = this.expr.wrap(join.as);
|
|
74
|
-
const where =
|
|
74
|
+
const where =
|
|
75
|
+
join.where != null && join.where.length > 0
|
|
76
|
+
? ` ON ${this.expr.renderWhere(join.where)}`
|
|
77
|
+
: " ON TRUE";
|
|
75
78
|
|
|
76
79
|
// LATERAL JOIN 필요 여부 감지
|
|
77
80
|
if (this.needsLateral(join)) {
|
|
@@ -236,7 +239,9 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
236
239
|
const alias = this.expr.wrap(def.as);
|
|
237
240
|
|
|
238
241
|
// SET
|
|
239
|
-
const setParts = Object.entries(def.record).map(
|
|
242
|
+
const setParts = Object.entries(def.record).map(
|
|
243
|
+
([col, e]) => `${this.expr.wrap(col)} = ${this.expr.render(e)}`,
|
|
244
|
+
);
|
|
240
245
|
|
|
241
246
|
let sql = `UPDATE ${table} AS ${alias} SET ${setParts.join(", ")}`;
|
|
242
247
|
|
|
@@ -253,8 +258,10 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
253
258
|
.filter((j) => j.where != null && j.where.length > 0)
|
|
254
259
|
.map((j) => this.expr.renderWhere(j.where!));
|
|
255
260
|
if (joinConditions.length > 0) {
|
|
256
|
-
const whereCondition =
|
|
257
|
-
|
|
261
|
+
const whereCondition =
|
|
262
|
+
def.where != null && def.where.length > 0 ? this.expr.renderWhere(def.where) : null;
|
|
263
|
+
const allConditions =
|
|
264
|
+
whereCondition != null ? [whereCondition, ...joinConditions] : joinConditions;
|
|
258
265
|
sql += ` WHERE ${allConditions.join(" AND ")}`;
|
|
259
266
|
} else {
|
|
260
267
|
sql += this.renderWhere(def.where);
|
|
@@ -295,8 +302,10 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
295
302
|
.filter((j) => j.where != null && j.where.length > 0)
|
|
296
303
|
.map((j) => this.expr.renderWhere(j.where!));
|
|
297
304
|
if (joinConditions.length > 0) {
|
|
298
|
-
const whereCondition =
|
|
299
|
-
|
|
305
|
+
const whereCondition =
|
|
306
|
+
def.where != null && def.where.length > 0 ? this.expr.renderWhere(def.where) : null;
|
|
307
|
+
const allConditions =
|
|
308
|
+
whereCondition != null ? [whereCondition, ...joinConditions] : joinConditions;
|
|
300
309
|
sql += ` WHERE ${allConditions.join(" AND ")}`;
|
|
301
310
|
} else {
|
|
302
311
|
sql += this.renderWhere(def.where);
|
|
@@ -340,7 +349,8 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
340
349
|
: "TRUE";
|
|
341
350
|
|
|
342
351
|
// OUTPUT 컬럼
|
|
343
|
-
const outputCols =
|
|
352
|
+
const outputCols =
|
|
353
|
+
def.output != null ? def.output.columns.map((c) => this.expr.wrap(c)).join(", ") : "*";
|
|
344
354
|
|
|
345
355
|
// CTE 방식 UPSERT
|
|
346
356
|
let sql = `WITH matched AS (\n`;
|
|
@@ -405,7 +415,9 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
405
415
|
}
|
|
406
416
|
|
|
407
417
|
protected renameTable(def: RenameTableQueryDef): QueryBuildResult {
|
|
408
|
-
return {
|
|
418
|
+
return {
|
|
419
|
+
sql: `ALTER TABLE ${this.tableName(def.table)} RENAME TO ${this.expr.wrap(def.newName)}`,
|
|
420
|
+
};
|
|
409
421
|
}
|
|
410
422
|
|
|
411
423
|
protected truncate(def: TruncateQueryDef): QueryBuildResult {
|
|
@@ -442,7 +454,9 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
442
454
|
}
|
|
443
455
|
|
|
444
456
|
protected dropColumn(def: DropColumnQueryDef): QueryBuildResult {
|
|
445
|
-
return {
|
|
457
|
+
return {
|
|
458
|
+
sql: `ALTER TABLE ${this.tableName(def.table)} DROP COLUMN ${this.expr.wrap(def.column)}`,
|
|
459
|
+
};
|
|
446
460
|
}
|
|
447
461
|
|
|
448
462
|
protected modifyColumn(def: ModifyColumnQueryDef): QueryBuildResult {
|
|
@@ -453,7 +467,9 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
453
467
|
const parts: string[] = [];
|
|
454
468
|
|
|
455
469
|
// TYPE 변경
|
|
456
|
-
parts.push(
|
|
470
|
+
parts.push(
|
|
471
|
+
`ALTER COLUMN ${this.expr.wrap(col.name)} TYPE ${this.expr.renderDataType(col.dataType)}`,
|
|
472
|
+
);
|
|
457
473
|
|
|
458
474
|
// NULL 변경
|
|
459
475
|
if (col.nullable === false) {
|
|
@@ -464,7 +480,9 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
464
480
|
|
|
465
481
|
// DEFAULT 변경
|
|
466
482
|
if (col.default !== undefined) {
|
|
467
|
-
parts.push(
|
|
483
|
+
parts.push(
|
|
484
|
+
`ALTER COLUMN ${this.expr.wrap(col.name)} SET DEFAULT ${this.expr.escapeValue(col.default)}`,
|
|
485
|
+
);
|
|
468
486
|
}
|
|
469
487
|
|
|
470
488
|
return { sql: `ALTER TABLE ${table} ${parts.join(", ")}` };
|
|
@@ -485,7 +503,9 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
485
503
|
const table = this.tableName(def.table);
|
|
486
504
|
const cols = def.columns.map((c) => this.expr.wrap(c)).join(", ");
|
|
487
505
|
const pkName = `PK_${def.table.name}`;
|
|
488
|
-
return {
|
|
506
|
+
return {
|
|
507
|
+
sql: `ALTER TABLE ${table} ADD CONSTRAINT ${this.expr.wrap(pkName)} PRIMARY KEY (${cols})`,
|
|
508
|
+
};
|
|
489
509
|
}
|
|
490
510
|
|
|
491
511
|
protected dropPk(def: DropPkQueryDef): QueryBuildResult {
|
|
@@ -511,7 +531,9 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
511
531
|
}
|
|
512
532
|
|
|
513
533
|
protected dropFk(def: DropFkQueryDef): QueryBuildResult {
|
|
514
|
-
return {
|
|
534
|
+
return {
|
|
535
|
+
sql: `ALTER TABLE ${this.tableName(def.table)} DROP CONSTRAINT ${this.expr.wrap(def.foreignKey)}`,
|
|
536
|
+
};
|
|
515
537
|
}
|
|
516
538
|
|
|
517
539
|
protected addIdx(def: AddIdxQueryDef): QueryBuildResult {
|
|
@@ -83,7 +83,9 @@ export class ColumnBuilder<TValue extends ColumnPrimitive, TMeta extends ColumnM
|
|
|
83
83
|
* createdAt: c.datetime().default("CURRENT_TIMESTAMP")
|
|
84
84
|
* ```
|
|
85
85
|
*/
|
|
86
|
-
default(
|
|
86
|
+
default(
|
|
87
|
+
value: TValue,
|
|
88
|
+
): ColumnBuilder<TValue, Omit<TMeta, "default"> & { default: typeof value }> {
|
|
87
89
|
return new ColumnBuilder({ ...this.meta, default: value });
|
|
88
90
|
}
|
|
89
91
|
|
|
@@ -196,7 +198,10 @@ export function createColumnFactory() {
|
|
|
196
198
|
decimal(
|
|
197
199
|
precision: number,
|
|
198
200
|
scale?: number,
|
|
199
|
-
): ColumnBuilder<
|
|
201
|
+
): ColumnBuilder<
|
|
202
|
+
number,
|
|
203
|
+
{ type: "number"; dataType: { type: "decimal"; precision: number; scale?: number } }
|
|
204
|
+
> {
|
|
200
205
|
return new ColumnBuilder({ type: "number", dataType: { type: "decimal", precision, scale } });
|
|
201
206
|
},
|
|
202
207
|
|
|
@@ -211,7 +216,9 @@ export function createColumnFactory() {
|
|
|
211
216
|
* name: c.varchar(100) // VARCHAR(100)
|
|
212
217
|
* ```
|
|
213
218
|
*/
|
|
214
|
-
varchar(
|
|
219
|
+
varchar(
|
|
220
|
+
length: number,
|
|
221
|
+
): ColumnBuilder<string, { type: "string"; dataType: { type: "varchar"; length: number } }> {
|
|
215
222
|
return new ColumnBuilder({ type: "string", dataType: { type: "varchar", length } });
|
|
216
223
|
},
|
|
217
224
|
|
|
@@ -226,7 +233,9 @@ export function createColumnFactory() {
|
|
|
226
233
|
* countryCode: c.char(2) // CHAR(2)
|
|
227
234
|
* ```
|
|
228
235
|
*/
|
|
229
|
-
char(
|
|
236
|
+
char(
|
|
237
|
+
length: number,
|
|
238
|
+
): ColumnBuilder<string, { type: "string"; dataType: { type: "char"; length: number } }> {
|
|
230
239
|
return new ColumnBuilder({ type: "string", dataType: { type: "char" as const, length } });
|
|
231
240
|
},
|
|
232
241
|
|
|
@@ -397,7 +406,9 @@ export type InferInsertColumns<TBuilders extends ColumnBuilderRecord> = Pick<
|
|
|
397
406
|
*
|
|
398
407
|
* @template T - 컬럼 빌더 레코드 타입
|
|
399
408
|
*/
|
|
400
|
-
export type InferUpdateColumns<TBuilders extends ColumnBuilderRecord> = Partial<
|
|
409
|
+
export type InferUpdateColumns<TBuilders extends ColumnBuilderRecord> = Partial<
|
|
410
|
+
InferColumns<TBuilders>
|
|
411
|
+
>;
|
|
401
412
|
|
|
402
413
|
/**
|
|
403
414
|
* 데이터 레코드에서 컬럼 빌더 레코드로 변환
|
|
@@ -32,7 +32,10 @@ import type { ViewBuilder } from "../view-builder";
|
|
|
32
32
|
* @see {@link ForeignKeyTargetBuilder} 역참조 빌더
|
|
33
33
|
* @see {@link RelationKeyBuilder} DB FK 없는 관계
|
|
34
34
|
*/
|
|
35
|
-
export class ForeignKeyBuilder<
|
|
35
|
+
export class ForeignKeyBuilder<
|
|
36
|
+
TOwner extends TableBuilder<any, any>,
|
|
37
|
+
TTargetFn extends () => TableBuilder<any, any>,
|
|
38
|
+
> {
|
|
36
39
|
/**
|
|
37
40
|
* @param meta - FK 메타데이터
|
|
38
41
|
* @param meta.ownerFn - 소유 테이블 팩토리
|
|
@@ -88,7 +91,10 @@ export class ForeignKeyBuilder<TOwner extends TableBuilder<any, any>, TTargetFn
|
|
|
88
91
|
*
|
|
89
92
|
* @see {@link ForeignKeyBuilder} FK 빌더
|
|
90
93
|
*/
|
|
91
|
-
export class ForeignKeyTargetBuilder<
|
|
94
|
+
export class ForeignKeyTargetBuilder<
|
|
95
|
+
TTargetTableFn extends () => TableBuilder<any, any>,
|
|
96
|
+
TIsSingle extends boolean,
|
|
97
|
+
> {
|
|
92
98
|
/**
|
|
93
99
|
* @param meta - FK 역참조 메타데이터
|
|
94
100
|
* @param meta.targetTableFn - 참조하는 테이블 팩토리
|
|
@@ -294,7 +300,9 @@ type RelationRkFactory<
|
|
|
294
300
|
targetFn: TTargetFn,
|
|
295
301
|
): RelationKeyBuilder<TOwner, TTargetFn>;
|
|
296
302
|
/** 1:N 논리적 역참조 정의 */
|
|
297
|
-
relationKeyTarget<
|
|
303
|
+
relationKeyTarget<
|
|
304
|
+
TTargetTableFn extends () => TableBuilder<any, any> | ViewBuilder<any, any, any>,
|
|
305
|
+
>(
|
|
298
306
|
targetTableFn: TTargetTableFn,
|
|
299
307
|
relationName: string,
|
|
300
308
|
): RelationKeyTargetBuilder<TTargetTableFn, false>;
|
|
@@ -439,5 +447,7 @@ export type ExtractRelationTargetResult<TRelation> = TRelation extends
|
|
|
439
447
|
* ```
|
|
440
448
|
*/
|
|
441
449
|
export type InferDeepRelations<TRelations extends RelationBuilderRecord> = {
|
|
442
|
-
[K in keyof TRelations]?:
|
|
450
|
+
[K in keyof TRelations]?:
|
|
451
|
+
| ExtractRelationTarget<TRelations[K]>
|
|
452
|
+
| ExtractRelationTargetResult<TRelations[K]>;
|
|
443
453
|
};
|
|
@@ -40,7 +40,10 @@ import { type ColumnBuilderRecord, createColumnFactory } from "./factory/column-
|
|
|
40
40
|
* @see {@link Procedure} 팩토리 함수
|
|
41
41
|
* @see {@link executable} Executable 생성
|
|
42
42
|
*/
|
|
43
|
-
export class ProcedureBuilder<
|
|
43
|
+
export class ProcedureBuilder<
|
|
44
|
+
TParams extends ColumnBuilderRecord,
|
|
45
|
+
TReturns extends ColumnBuilderRecord,
|
|
46
|
+
> {
|
|
44
47
|
/** 파라미터 정의 (타입 추론용) */
|
|
45
48
|
readonly $params!: TParams;
|
|
46
49
|
/** 반환 타입 정의 (타입 추론용) */
|
|
@@ -6,7 +6,11 @@ import {
|
|
|
6
6
|
type InferUpdateColumns,
|
|
7
7
|
} from "./factory/column-builder";
|
|
8
8
|
import { createIndexFactory, type IndexBuilder } from "./factory/index-builder";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
createRelationFactory,
|
|
11
|
+
type InferDeepRelations,
|
|
12
|
+
type RelationBuilderRecord,
|
|
13
|
+
} from "./factory/relation-builder";
|
|
10
14
|
|
|
11
15
|
// ============================================
|
|
12
16
|
// TableBuilder
|
|
@@ -44,7 +48,10 @@ import { createRelationFactory, type InferDeepRelations, type RelationBuilderRec
|
|
|
44
48
|
* @see {@link Table} 팩토리 함수
|
|
45
49
|
* @see {@link queryable} Queryable 생성
|
|
46
50
|
*/
|
|
47
|
-
export class TableBuilder<
|
|
51
|
+
export class TableBuilder<
|
|
52
|
+
TColumns extends ColumnBuilderRecord,
|
|
53
|
+
TRelations extends RelationBuilderRecord,
|
|
54
|
+
> {
|
|
48
55
|
/** 컬럼 정의 (타입 추론용) */
|
|
49
56
|
readonly $columns!: TColumns;
|
|
50
57
|
/** 관계 정의 (타입 추론용) */
|
|
@@ -206,7 +213,11 @@ export class TableBuilder<TColumns extends ColumnBuilderRecord, TRelations exten
|
|
|
206
213
|
* ]);
|
|
207
214
|
* ```
|
|
208
215
|
*/
|
|
209
|
-
indexes(
|
|
216
|
+
indexes(
|
|
217
|
+
fn: (
|
|
218
|
+
i: ReturnType<typeof createIndexFactory<keyof TColumns & string>>,
|
|
219
|
+
) => IndexBuilder<string[]>[],
|
|
220
|
+
) {
|
|
210
221
|
return new TableBuilder({
|
|
211
222
|
...this.meta,
|
|
212
223
|
indexes: fn(createIndexFactory<keyof TColumns & string>()),
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { DbContextBase } from "../types/db-context-def";
|
|
2
2
|
import type { Queryable } from "../exec/queryable";
|
|
3
3
|
import type { DataRecord } from "../types/db";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
createRelationFactory,
|
|
6
|
+
type InferDeepRelations,
|
|
7
|
+
type RelationBuilderRecord,
|
|
8
|
+
} from "./factory/relation-builder";
|
|
5
9
|
|
|
6
10
|
// ============================================
|
|
7
11
|
// ViewBuilder
|
|
@@ -20,8 +20,13 @@ export interface DbContextBase {
|
|
|
20
20
|
readonly schema: string | undefined;
|
|
21
21
|
getNextAlias(): string;
|
|
22
22
|
resetAliasCounter(): void;
|
|
23
|
-
executeDefs<T = DataRecord>(
|
|
24
|
-
|
|
23
|
+
executeDefs<T = DataRecord>(
|
|
24
|
+
defs: QueryDef[],
|
|
25
|
+
resultMetas?: (ResultMeta | undefined)[],
|
|
26
|
+
): Promise<T[][]>;
|
|
27
|
+
getQueryDefObjectName(
|
|
28
|
+
tableOrView: TableBuilder<any, any> | ViewBuilder<any, any, any>,
|
|
29
|
+
): QueryDefObjectName;
|
|
25
30
|
switchFk(table: QueryDefObjectName, switch_: "on" | "off"): Promise<void>;
|
|
26
31
|
}
|
|
27
32
|
|
|
@@ -92,13 +97,25 @@ export interface DbContextDdlMethods {
|
|
|
92
97
|
dropView(view: QueryDefObjectName): Promise<void>;
|
|
93
98
|
createProc(procedure: ProcedureBuilder<any, any>): Promise<void>;
|
|
94
99
|
dropProc(procedure: QueryDefObjectName): Promise<void>;
|
|
95
|
-
addColumn(
|
|
100
|
+
addColumn(
|
|
101
|
+
table: QueryDefObjectName,
|
|
102
|
+
columnName: string,
|
|
103
|
+
column: ColumnBuilder<any, any>,
|
|
104
|
+
): Promise<void>;
|
|
96
105
|
dropColumn(table: QueryDefObjectName, column: string): Promise<void>;
|
|
97
|
-
modifyColumn(
|
|
106
|
+
modifyColumn(
|
|
107
|
+
table: QueryDefObjectName,
|
|
108
|
+
columnName: string,
|
|
109
|
+
column: ColumnBuilder<any, any>,
|
|
110
|
+
): Promise<void>;
|
|
98
111
|
renameColumn(table: QueryDefObjectName, column: string, newName: string): Promise<void>;
|
|
99
112
|
addPk(table: QueryDefObjectName, columns: string[]): Promise<void>;
|
|
100
113
|
dropPk(table: QueryDefObjectName): Promise<void>;
|
|
101
|
-
addFk(
|
|
114
|
+
addFk(
|
|
115
|
+
table: QueryDefObjectName,
|
|
116
|
+
relationName: string,
|
|
117
|
+
relationDef: ForeignKeyBuilder<any, any>,
|
|
118
|
+
): Promise<void>;
|
|
102
119
|
addIdx(table: QueryDefObjectName, indexBuilder: IndexBuilder<string[]>): Promise<void>;
|
|
103
120
|
dropFk(table: QueryDefObjectName, relationName: string): Promise<void>;
|
|
104
121
|
dropIdx(table: QueryDefObjectName, columns: string[]): Promise<void>;
|
|
@@ -117,13 +134,25 @@ export interface DbContextDdlMethods {
|
|
|
117
134
|
getRenameTableQueryDef(table: QueryDefObjectName, newName: string): QueryDef;
|
|
118
135
|
getDropViewQueryDef(view: QueryDefObjectName): QueryDef;
|
|
119
136
|
getDropProcQueryDef(procedure: QueryDefObjectName): QueryDef;
|
|
120
|
-
getAddColumnQueryDef(
|
|
137
|
+
getAddColumnQueryDef(
|
|
138
|
+
table: QueryDefObjectName,
|
|
139
|
+
columnName: string,
|
|
140
|
+
column: ColumnBuilder<any, any>,
|
|
141
|
+
): QueryDef;
|
|
121
142
|
getDropColumnQueryDef(table: QueryDefObjectName, column: string): QueryDef;
|
|
122
|
-
getModifyColumnQueryDef(
|
|
143
|
+
getModifyColumnQueryDef(
|
|
144
|
+
table: QueryDefObjectName,
|
|
145
|
+
columnName: string,
|
|
146
|
+
column: ColumnBuilder<any, any>,
|
|
147
|
+
): QueryDef;
|
|
123
148
|
getRenameColumnQueryDef(table: QueryDefObjectName, column: string, newName: string): QueryDef;
|
|
124
149
|
getAddPkQueryDef(table: QueryDefObjectName, columns: string[]): QueryDef;
|
|
125
150
|
getDropPkQueryDef(table: QueryDefObjectName): QueryDef;
|
|
126
|
-
getAddFkQueryDef(
|
|
151
|
+
getAddFkQueryDef(
|
|
152
|
+
table: QueryDefObjectName,
|
|
153
|
+
relationName: string,
|
|
154
|
+
relationDef: ForeignKeyBuilder<any, any>,
|
|
155
|
+
): QueryDef;
|
|
127
156
|
getAddIdxQueryDef(table: QueryDefObjectName, indexBuilder: IndexBuilder<string[]>): QueryDef;
|
|
128
157
|
getDropFkQueryDef(table: QueryDefObjectName, relationName: string): QueryDef;
|
|
129
158
|
getDropIdxQueryDef(table: QueryDefObjectName, columns: string[]): QueryDef;
|
package/src/types/db.ts
CHANGED
|
@@ -56,7 +56,11 @@ export interface QueryBuildResult {
|
|
|
56
56
|
* - `REPEATABLE_READ`: 트랜잭션 내 동일 쿼리 동일 결과 보장
|
|
57
57
|
* - `SERIALIZABLE`: 완전 직렬화 (가장 엄격)
|
|
58
58
|
*/
|
|
59
|
-
export type IsolationLevel =
|
|
59
|
+
export type IsolationLevel =
|
|
60
|
+
| "READ_UNCOMMITTED"
|
|
61
|
+
| "READ_COMMITTED"
|
|
62
|
+
| "REPEATABLE_READ"
|
|
63
|
+
| "SERIALIZABLE";
|
|
60
64
|
|
|
61
65
|
// ============================================
|
|
62
66
|
// DataRecord - 결과 데이터 타입 (재귀적, 중첩 허용)
|
|
@@ -144,7 +148,10 @@ export interface DbContextExecutor {
|
|
|
144
148
|
* @param resultMetas - 결과 변환을 위한 메타데이터 (선택)
|
|
145
149
|
* @returns 각 QueryDef별 결과 배열의 배열
|
|
146
150
|
*/
|
|
147
|
-
executeDefs<T = DataRecord>(
|
|
151
|
+
executeDefs<T = DataRecord>(
|
|
152
|
+
defs: QueryDef[],
|
|
153
|
+
resultMetas?: (ResultMeta | undefined)[],
|
|
154
|
+
): Promise<T[][]>;
|
|
148
155
|
}
|
|
149
156
|
|
|
150
157
|
/**
|
|
@@ -273,7 +273,9 @@ function groupRecordsRecursively(
|
|
|
273
273
|
return !key.includes(".");
|
|
274
274
|
} else {
|
|
275
275
|
// 하위 레벨: 현재 경로 + "." + 키
|
|
276
|
-
return
|
|
276
|
+
return (
|
|
277
|
+
key.startsWith(currentPath + ".") && key.slice(currentPath.length + 1).indexOf(".") === -1
|
|
278
|
+
);
|
|
277
279
|
}
|
|
278
280
|
});
|
|
279
281
|
|
|
@@ -375,7 +377,10 @@ function groupRecordsRecursively(
|
|
|
375
377
|
/**
|
|
376
378
|
* 레코드에서 JOIN 키를 제외한 그룹 키 추출
|
|
377
379
|
*/
|
|
378
|
-
function extractGroupKey(
|
|
380
|
+
function extractGroupKey(
|
|
381
|
+
record: Record<string, unknown>,
|
|
382
|
+
joinKeys: string[],
|
|
383
|
+
): Record<string, unknown> {
|
|
379
384
|
const result: Record<string, unknown> = {};
|
|
380
385
|
for (const [key, value] of Object.entries(record)) {
|
|
381
386
|
// JOIN 키가 아닌 것만 포함
|
|
@@ -433,7 +438,9 @@ function mergeJoinData(
|
|
|
433
438
|
}
|
|
434
439
|
} else {
|
|
435
440
|
// hashSet이 없으면 폴백 (기존 방식)
|
|
436
|
-
const isDuplicate = existingJoinData.some((item) =>
|
|
441
|
+
const isDuplicate = existingJoinData.some((item) =>
|
|
442
|
+
objEqual(item as Record<string, unknown>, newJoinData),
|
|
443
|
+
);
|
|
437
444
|
if (!isDuplicate) {
|
|
438
445
|
existingJoinData.push(newJoinData);
|
|
439
446
|
}
|