@simplysm/orm-common 13.0.75 → 13.0.77
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 +575 -50
- package/dist/create-db-context.d.ts +1 -1
- package/dist/create-db-context.d.ts.map +1 -1
- package/dist/create-db-context.js +34 -27
- package/dist/create-db-context.js.map +1 -1
- package/dist/ddl/initialize.js +4 -4
- package/dist/ddl/initialize.js.map +1 -1
- package/dist/ddl/relation-ddl.d.ts +7 -7
- package/dist/ddl/relation-ddl.d.ts.map +1 -1
- package/dist/ddl/relation-ddl.js +18 -18
- package/dist/ddl/relation-ddl.js.map +1 -1
- package/dist/ddl/schema-ddl.d.ts +1 -1
- package/dist/ddl/schema-ddl.d.ts.map +1 -1
- package/dist/ddl/schema-ddl.js +2 -2
- package/dist/ddl/schema-ddl.js.map +1 -1
- package/dist/ddl/table-ddl.js +2 -2
- package/dist/ddl/table-ddl.js.map +1 -1
- package/dist/exec/queryable.d.ts +24 -24
- package/dist/exec/queryable.d.ts.map +1 -1
- package/dist/exec/queryable.js +37 -37
- package/dist/exec/queryable.js.map +1 -1
- package/dist/expr/expr-unit.js +1 -1
- package/dist/expr/expr-unit.js.map +1 -1
- package/dist/expr/expr.d.ts +9 -9
- package/dist/expr/expr.d.ts.map +1 -1
- package/dist/expr/expr.js +10 -10
- package/dist/expr/expr.js.map +1 -1
- package/dist/query-builder/base/expr-renderer-base.d.ts +2 -2
- package/dist/query-builder/base/expr-renderer-base.d.ts.map +1 -1
- package/dist/query-builder/base/query-builder-base.d.ts +7 -15
- package/dist/query-builder/base/query-builder-base.d.ts.map +1 -1
- package/dist/query-builder/base/query-builder-base.js +2 -2
- 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 +8 -8
- package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.d.ts +7 -7
- package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.js +7 -7
- 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 +9 -9
- package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.d.ts +7 -7
- package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.js +11 -11
- 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 +8 -8
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +7 -7
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.js +7 -7
- package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
- package/dist/schema/procedure-builder.d.ts +1 -1
- package/dist/schema/table-builder.d.ts +1 -1
- package/dist/schema/table-builder.d.ts.map +1 -1
- package/dist/schema/table-builder.js +1 -1
- package/dist/schema/view-builder.d.ts +1 -1
- package/dist/schema/view-builder.d.ts.map +1 -1
- package/dist/schema/view-builder.js +1 -1
- package/dist/types/db-context-def.d.ts +18 -18
- package/dist/types/db-context-def.d.ts.map +1 -1
- package/dist/types/expr.d.ts +6 -6
- package/dist/types/expr.d.ts.map +1 -1
- package/dist/types/query-def.d.ts +15 -15
- package/dist/types/query-def.d.ts.map +1 -1
- package/dist/types/query-def.js +6 -6
- package/dist/utils/result-parser.d.ts.map +1 -1
- package/dist/utils/result-parser.js +44 -16
- package/dist/utils/result-parser.js.map +1 -1
- package/package.json +2 -2
- package/src/create-db-context.ts +36 -29
- package/src/ddl/initialize.ts +4 -4
- package/src/ddl/relation-ddl.ts +16 -16
- package/src/ddl/schema-ddl.ts +2 -2
- package/src/ddl/table-ddl.ts +2 -2
- package/src/exec/queryable.ts +58 -58
- package/src/expr/expr-unit.ts +1 -1
- package/src/expr/expr.ts +13 -13
- package/src/query-builder/base/expr-renderer-base.ts +2 -2
- package/src/query-builder/base/query-builder-base.ts +18 -14
- package/src/query-builder/mssql/mssql-expr-renderer.ts +11 -10
- package/src/query-builder/mssql/mssql-query-builder.ts +13 -13
- package/src/query-builder/mysql/mysql-expr-renderer.ts +12 -11
- package/src/query-builder/mysql/mysql-query-builder.ts +17 -17
- package/src/query-builder/postgresql/postgresql-expr-renderer.ts +11 -10
- package/src/query-builder/postgresql/postgresql-query-builder.ts +13 -13
- package/src/schema/procedure-builder.ts +1 -1
- package/src/schema/table-builder.ts +1 -1
- package/src/schema/view-builder.ts +1 -1
- package/src/types/db-context-def.ts +18 -18
- package/src/types/expr.ts +6 -6
- package/src/types/query-def.ts +31 -31
- package/src/utils/result-parser.ts +60 -16
- package/tests/db-context/create-db-context.spec.ts +6 -37
- package/tests/db-context/define-db-context.spec.ts +0 -51
- package/tests/ddl/basic.expected.ts +8 -8
- package/tests/ddl/basic.spec.ts +24 -181
- package/tests/ddl/column-builder.spec.ts +0 -112
- package/tests/ddl/index-builder.spec.ts +10 -64
- package/tests/ddl/procedure-builder.spec.ts +0 -106
- package/tests/ddl/relation-builder.spec.ts +4 -205
- package/tests/ddl/table-builder.spec.ts +0 -34
- package/tests/ddl/view-builder.spec.ts +0 -60
- package/tests/dml/delete.spec.ts +0 -33
- package/tests/dml/insert.spec.ts +0 -78
- package/tests/dml/update.spec.ts +2 -98
- package/tests/dml/upsert.spec.ts +0 -52
- package/tests/errors/queryable-errors.spec.ts +0 -51
- package/tests/escape.spec.ts +0 -41
- package/tests/examples/pivot.spec.ts +0 -333
- package/tests/examples/sampling.spec.ts +0 -63
- package/tests/examples/unpivot.spec.ts +0 -65
- package/tests/exec/search-parser.spec.ts +0 -16
- package/tests/expr/comparison.spec.ts +0 -66
- package/tests/expr/conditional.expected.ts +2 -2
- package/tests/expr/conditional.spec.ts +8 -35
- package/tests/expr/date.spec.ts +5 -72
- package/tests/expr/math.spec.ts +0 -47
- package/tests/expr/string.spec.ts +0 -56
- package/tests/expr/utility.spec.ts +0 -27
- package/tests/select/basic.spec.ts +5 -74
- package/tests/select/filter.spec.ts +0 -114
- package/tests/select/group.spec.ts +0 -85
- package/tests/select/join.spec.ts +0 -113
- package/tests/select/order.spec.ts +0 -49
- package/tests/select/subquery.spec.ts +0 -96
- package/tests/select/window.spec.ts +0 -185
- package/tests/types/nullable-queryable-record.spec.ts +0 -48
- package/tests/utils/result-parser-perf.spec.ts +0 -67
- package/tests/utils/result-parser.spec.ts +4 -38
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AddColumnQueryDef,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
AddForeignKeyQueryDef,
|
|
4
|
+
AddIndexQueryDef,
|
|
5
|
+
AddPrimaryKeyQueryDef,
|
|
6
6
|
ClearSchemaQueryDef,
|
|
7
7
|
CreateProcQueryDef,
|
|
8
8
|
CreateTableQueryDef,
|
|
@@ -10,9 +10,9 @@ import type {
|
|
|
10
10
|
SchemaExistsQueryDef,
|
|
11
11
|
DeleteQueryDef,
|
|
12
12
|
DropColumnQueryDef,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
DropForeignKeyQueryDef,
|
|
14
|
+
DropIndexQueryDef,
|
|
15
|
+
DropPrimaryKeyQueryDef,
|
|
16
16
|
DropProcQueryDef,
|
|
17
17
|
DropTableQueryDef,
|
|
18
18
|
DropViewQueryDef,
|
|
@@ -463,7 +463,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
|
|
|
463
463
|
|
|
464
464
|
//#region ========== DDL - Constraint ==========
|
|
465
465
|
|
|
466
|
-
protected
|
|
466
|
+
protected addPrimaryKey(def: AddPrimaryKeyQueryDef): QueryBuildResult {
|
|
467
467
|
const table = this.tableName(def.table);
|
|
468
468
|
const cols = def.columns.map((c) => this.expr.wrap(c)).join(", ");
|
|
469
469
|
const pkName = `PK_${def.table.name}`;
|
|
@@ -472,13 +472,13 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
|
|
|
472
472
|
};
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
-
protected
|
|
475
|
+
protected dropPrimaryKey(def: DropPrimaryKeyQueryDef): QueryBuildResult {
|
|
476
476
|
const table = this.tableName(def.table);
|
|
477
477
|
const pkName = `PK_${def.table.name}`;
|
|
478
478
|
return { sql: `ALTER TABLE ${table} DROP CONSTRAINT ${this.expr.wrap(pkName)}` };
|
|
479
479
|
}
|
|
480
480
|
|
|
481
|
-
protected
|
|
481
|
+
protected addForeignKey(def: AddForeignKeyQueryDef): QueryBuildResult {
|
|
482
482
|
const table = this.tableName(def.table);
|
|
483
483
|
const fk = def.foreignKey;
|
|
484
484
|
const fkCols = fk.fkColumns.map((c) => this.expr.wrap(c)).join(", ");
|
|
@@ -494,13 +494,13 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
|
|
|
494
494
|
return { sql };
|
|
495
495
|
}
|
|
496
496
|
|
|
497
|
-
protected
|
|
497
|
+
protected dropForeignKey(def: DropForeignKeyQueryDef): QueryBuildResult {
|
|
498
498
|
return {
|
|
499
499
|
sql: `ALTER TABLE ${this.tableName(def.table)} DROP CONSTRAINT ${this.expr.wrap(def.foreignKey)}`,
|
|
500
500
|
};
|
|
501
501
|
}
|
|
502
502
|
|
|
503
|
-
protected
|
|
503
|
+
protected addIndex(def: AddIndexQueryDef): QueryBuildResult {
|
|
504
504
|
const table = this.tableName(def.table);
|
|
505
505
|
const idx = def.index;
|
|
506
506
|
const cols = idx.columns.map((c) => `${this.expr.wrap(c.name)} ${c.orderBy}`).join(", ");
|
|
@@ -508,7 +508,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
|
|
|
508
508
|
return { sql: `CREATE ${unique}INDEX ${this.expr.wrap(idx.name)} ON ${table} (${cols})` };
|
|
509
509
|
}
|
|
510
510
|
|
|
511
|
-
protected
|
|
511
|
+
protected dropIndex(def: DropIndexQueryDef): QueryBuildResult {
|
|
512
512
|
return { sql: `DROP INDEX ${this.expr.wrap(def.index)} ON ${this.tableName(def.table)}` };
|
|
513
513
|
}
|
|
514
514
|
|
|
@@ -640,7 +640,7 @@ SELECT @result AS name WHERE @result IS NOT NULL`,
|
|
|
640
640
|
|
|
641
641
|
protected switchFk(def: SwitchFkQueryDef): QueryBuildResult {
|
|
642
642
|
const table = this.tableName(def.table);
|
|
643
|
-
if (def.
|
|
643
|
+
if (def.enabled) {
|
|
644
644
|
return { sql: `ALTER TABLE ${table} WITH CHECK CHECK CONSTRAINT ALL` };
|
|
645
645
|
}
|
|
646
646
|
return { sql: `ALTER TABLE ${table} NOCHECK CONSTRAINT ALL` };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DateOnly, DateTime, Time, Uuid
|
|
1
|
+
import { bytes, DateOnly, DateTime, Time, Uuid } from "@simplysm/core-common";
|
|
2
2
|
import type {
|
|
3
3
|
ExprColumn,
|
|
4
4
|
ExprValue,
|
|
@@ -46,7 +46,7 @@ import type {
|
|
|
46
46
|
ExprDateDiff,
|
|
47
47
|
ExprDateAdd,
|
|
48
48
|
ExprFormatDate,
|
|
49
|
-
|
|
49
|
+
ExprCoalesce,
|
|
50
50
|
ExprNullIf,
|
|
51
51
|
ExprIs,
|
|
52
52
|
ExprSwitch,
|
|
@@ -60,9 +60,10 @@ import type {
|
|
|
60
60
|
ExprLeast,
|
|
61
61
|
ExprRowNum,
|
|
62
62
|
ExprCast,
|
|
63
|
+
ExprRandom,
|
|
63
64
|
ExprWindow,
|
|
64
65
|
ExprSubquery,
|
|
65
|
-
|
|
66
|
+
DateUnit,
|
|
66
67
|
} from "../../types/expr";
|
|
67
68
|
import type { DataType } from "../../types/column";
|
|
68
69
|
import { ExprRendererBase } from "../base/expr-renderer-base";
|
|
@@ -113,10 +114,10 @@ export class MysqlExprRenderer extends ExprRendererBase {
|
|
|
113
114
|
return `'${value.toFormatString("HH:mm:ss")}'`;
|
|
114
115
|
}
|
|
115
116
|
if (value instanceof Uuid) {
|
|
116
|
-
return `0x${
|
|
117
|
+
return `0x${bytes.toHex(value.toBytes())}`;
|
|
117
118
|
}
|
|
118
119
|
if (value instanceof Uint8Array) {
|
|
119
|
-
return `0x${
|
|
120
|
+
return `0x${bytes.toHex(value)}`;
|
|
120
121
|
}
|
|
121
122
|
throw new Error(`Unknown value type: ${typeof value}`);
|
|
122
123
|
}
|
|
@@ -390,7 +391,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
|
|
|
390
391
|
protected dateDiff(expr: ExprDateDiff): string {
|
|
391
392
|
const from = this.render(expr.from);
|
|
392
393
|
const to = this.render(expr.to);
|
|
393
|
-
switch (expr.
|
|
394
|
+
switch (expr.unit) {
|
|
394
395
|
case "year":
|
|
395
396
|
return `TIMESTAMPDIFF(YEAR, ${from}, ${to})`;
|
|
396
397
|
case "month":
|
|
@@ -409,7 +410,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
|
|
|
409
410
|
protected dateAdd(expr: ExprDateAdd): string {
|
|
410
411
|
const source = this.render(expr.source);
|
|
411
412
|
const value = this.render(expr.value);
|
|
412
|
-
const unit = this.
|
|
413
|
+
const unit = this.dateUnitToSql(expr.unit);
|
|
413
414
|
return `DATE_ADD(${source}, INTERVAL ${value} ${unit})`;
|
|
414
415
|
}
|
|
415
416
|
|
|
@@ -419,8 +420,8 @@ export class MysqlExprRenderer extends ExprRendererBase {
|
|
|
419
420
|
return `DATE_FORMAT(${this.render(expr.source)}, '${mysqlFormat}')`;
|
|
420
421
|
}
|
|
421
422
|
|
|
422
|
-
private
|
|
423
|
-
switch (
|
|
423
|
+
private dateUnitToSql(unit: DateUnit): string {
|
|
424
|
+
switch (unit) {
|
|
424
425
|
case "year":
|
|
425
426
|
return "YEAR";
|
|
426
427
|
case "month":
|
|
@@ -451,7 +452,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
|
|
|
451
452
|
|
|
452
453
|
//#region ========== condition ==========
|
|
453
454
|
|
|
454
|
-
protected
|
|
455
|
+
protected coalesce(expr: ExprCoalesce): string {
|
|
455
456
|
if (expr.args.length === 0) return "NULL";
|
|
456
457
|
if (expr.args.length === 1) return this.render(expr.args[0]);
|
|
457
458
|
// COALESCE로 Render (여러 value 중 첫 번째 non-null)
|
|
@@ -526,7 +527,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
|
|
|
526
527
|
return "ROW_NUMBER() OVER ()";
|
|
527
528
|
}
|
|
528
529
|
|
|
529
|
-
protected random(): string {
|
|
530
|
+
protected random(_expr: ExprRandom): string {
|
|
530
531
|
return "RAND()";
|
|
531
532
|
}
|
|
532
533
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Uuid } from "@simplysm/core-common";
|
|
2
2
|
import type {
|
|
3
3
|
AddColumnQueryDef,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
AddForeignKeyQueryDef,
|
|
5
|
+
AddIndexQueryDef,
|
|
6
|
+
AddPrimaryKeyQueryDef,
|
|
7
7
|
ClearSchemaQueryDef,
|
|
8
8
|
CreateProcQueryDef,
|
|
9
9
|
CreateTableQueryDef,
|
|
@@ -11,9 +11,9 @@ import type {
|
|
|
11
11
|
SchemaExistsQueryDef,
|
|
12
12
|
DeleteQueryDef,
|
|
13
13
|
DropColumnQueryDef,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
DropForeignKeyQueryDef,
|
|
15
|
+
DropIndexQueryDef,
|
|
16
|
+
DropPrimaryKeyQueryDef,
|
|
17
17
|
DropProcQueryDef,
|
|
18
18
|
DropTableQueryDef,
|
|
19
19
|
DropViewQueryDef,
|
|
@@ -288,7 +288,7 @@ export class MysqlQueryBuilder extends QueryBuilderBase {
|
|
|
288
288
|
}
|
|
289
289
|
|
|
290
290
|
// PK가 AI 아님: 임시 Table로 PK 저장 후 조회
|
|
291
|
-
const tempTableName = this.expr.wrap("SD_TEMP_" + Uuid.
|
|
291
|
+
const tempTableName = this.expr.wrap("SD_TEMP_" + Uuid.generate().toString().replace(/-/g, ""));
|
|
292
292
|
|
|
293
293
|
// recordsSelectQuery에서 PK column만 추출한 SELECT Generate
|
|
294
294
|
const pkSelectDef: SelectQueryDef = {
|
|
@@ -343,7 +343,7 @@ export class MysqlQueryBuilder extends QueryBuilderBase {
|
|
|
343
343
|
|
|
344
344
|
// OUTPUT 필요: multi-statement (임시table에 PK 저장 + UPDATE + SELECT + DROP)
|
|
345
345
|
const outputCols = def.output.columns.map((c) => `${alias}.${this.expr.wrap(c)}`).join(", ");
|
|
346
|
-
const tempTableName = this.expr.wrap("SD_TEMP_" + Uuid.
|
|
346
|
+
const tempTableName = this.expr.wrap("SD_TEMP_" + Uuid.generate().toString().replace(/-/g, ""));
|
|
347
347
|
|
|
348
348
|
// UPDATE 대상 PK를 임시 Table에 저장 (UPDATE 후 WHERE condition이 달라질 수 있으므로)
|
|
349
349
|
const pkSelectCols = def.output.pkColNames
|
|
@@ -395,7 +395,7 @@ export class MysqlQueryBuilder extends QueryBuilderBase {
|
|
|
395
395
|
|
|
396
396
|
// OUTPUT 필요: multi-statement (Delete 전 임시table에 저장 + DELETE + SELECT + DROP)
|
|
397
397
|
const outputCols = def.output.columns.map((c) => `${alias}.${this.expr.wrap(c)}`).join(", ");
|
|
398
|
-
const tempTableName = this.expr.wrap("SD_TEMP_" + Uuid.
|
|
398
|
+
const tempTableName = this.expr.wrap("SD_TEMP_" + Uuid.generate().toString().replace(/-/g, ""));
|
|
399
399
|
|
|
400
400
|
// Delete 전 임시 Table에 저장
|
|
401
401
|
let createTempSql = `CREATE TEMPORARY TABLE ${tempTableName} AS SELECT ${outputCols} FROM ${table} AS ${alias}`;
|
|
@@ -456,7 +456,7 @@ export class MysqlQueryBuilder extends QueryBuilderBase {
|
|
|
456
456
|
|
|
457
457
|
// OUTPUT 필요: multi-statement (CREATE TEMP + UPDATE + INSERT + SELECT + DROP)
|
|
458
458
|
const outputCols = def.output.columns.map((c) => this.expr.wrap(c)).join(", ");
|
|
459
|
-
const tempTableName = this.expr.wrap("SD_TEMP_" + Uuid.
|
|
459
|
+
const tempTableName = this.expr.wrap("SD_TEMP_" + Uuid.generate().toString().replace(/-/g, ""));
|
|
460
460
|
|
|
461
461
|
// UPDATE 대상 PK를 임시 Table에 저장 (UPDATE 후 WHERE condition이 달라질 수 있으므로)
|
|
462
462
|
const pkSelectCols = def.output.pkColNames.map((pk) => this.expr.wrap(pk)).join(", ");
|
|
@@ -618,17 +618,17 @@ export class MysqlQueryBuilder extends QueryBuilderBase {
|
|
|
618
618
|
|
|
619
619
|
//#region ========== DDL - Constraint ==========
|
|
620
620
|
|
|
621
|
-
protected
|
|
621
|
+
protected addPrimaryKey(def: AddPrimaryKeyQueryDef): QueryBuildResult {
|
|
622
622
|
const table = this.tableName(def.table);
|
|
623
623
|
const cols = def.columns.map((c) => this.expr.wrap(c)).join(", ");
|
|
624
624
|
return { sql: `ALTER TABLE ${table} ADD PRIMARY KEY (${cols})` };
|
|
625
625
|
}
|
|
626
626
|
|
|
627
|
-
protected
|
|
627
|
+
protected dropPrimaryKey(def: DropPrimaryKeyQueryDef): QueryBuildResult {
|
|
628
628
|
return { sql: `ALTER TABLE ${this.tableName(def.table)} DROP PRIMARY KEY` };
|
|
629
629
|
}
|
|
630
630
|
|
|
631
|
-
protected
|
|
631
|
+
protected addForeignKey(def: AddForeignKeyQueryDef): QueryBuildResult {
|
|
632
632
|
const table = this.tableName(def.table);
|
|
633
633
|
const fk = def.foreignKey;
|
|
634
634
|
const fkCols = fk.fkColumns.map((c) => this.expr.wrap(c)).join(", ");
|
|
@@ -641,13 +641,13 @@ export class MysqlQueryBuilder extends QueryBuilderBase {
|
|
|
641
641
|
};
|
|
642
642
|
}
|
|
643
643
|
|
|
644
|
-
protected
|
|
644
|
+
protected dropForeignKey(def: DropForeignKeyQueryDef): QueryBuildResult {
|
|
645
645
|
return {
|
|
646
646
|
sql: `ALTER TABLE ${this.tableName(def.table)} DROP FOREIGN KEY ${this.expr.wrap(def.foreignKey)}`,
|
|
647
647
|
};
|
|
648
648
|
}
|
|
649
649
|
|
|
650
|
-
protected
|
|
650
|
+
protected addIndex(def: AddIndexQueryDef): QueryBuildResult {
|
|
651
651
|
const table = this.tableName(def.table);
|
|
652
652
|
const idx = def.index;
|
|
653
653
|
const cols = idx.columns.map((c) => `${this.expr.wrap(c.name)} ${c.orderBy}`).join(", ");
|
|
@@ -655,7 +655,7 @@ export class MysqlQueryBuilder extends QueryBuilderBase {
|
|
|
655
655
|
return { sql: `CREATE ${unique}INDEX ${this.expr.wrap(idx.name)} ON ${table} (${cols})` };
|
|
656
656
|
}
|
|
657
657
|
|
|
658
|
-
protected
|
|
658
|
+
protected dropIndex(def: DropIndexQueryDef): QueryBuildResult {
|
|
659
659
|
return { sql: `DROP INDEX ${this.expr.wrap(def.index)} ON ${this.tableName(def.table)}` };
|
|
660
660
|
}
|
|
661
661
|
|
|
@@ -750,7 +750,7 @@ SET FOREIGN_KEY_CHECKS = 1`,
|
|
|
750
750
|
|
|
751
751
|
/** MySQL은 전역 설정만 지원 (table 파라미터 무시됨) */
|
|
752
752
|
protected switchFk(def: SwitchFkQueryDef): QueryBuildResult {
|
|
753
|
-
return def.
|
|
753
|
+
return def.enabled
|
|
754
754
|
? { sql: "SET FOREIGN_KEY_CHECKS = 1" }
|
|
755
755
|
: { sql: "SET FOREIGN_KEY_CHECKS = 0" };
|
|
756
756
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DateOnly, DateTime, Time, Uuid
|
|
1
|
+
import { bytes, DateOnly, DateTime, Time, Uuid } from "@simplysm/core-common";
|
|
2
2
|
import type {
|
|
3
3
|
ExprColumn,
|
|
4
4
|
ExprValue,
|
|
@@ -46,7 +46,7 @@ import type {
|
|
|
46
46
|
ExprDateDiff,
|
|
47
47
|
ExprDateAdd,
|
|
48
48
|
ExprFormatDate,
|
|
49
|
-
|
|
49
|
+
ExprCoalesce,
|
|
50
50
|
ExprNullIf,
|
|
51
51
|
ExprIs,
|
|
52
52
|
ExprSwitch,
|
|
@@ -60,9 +60,10 @@ import type {
|
|
|
60
60
|
ExprLeast,
|
|
61
61
|
ExprRowNum,
|
|
62
62
|
ExprCast,
|
|
63
|
+
ExprRandom,
|
|
63
64
|
ExprWindow,
|
|
64
65
|
ExprSubquery,
|
|
65
|
-
|
|
66
|
+
DateUnit,
|
|
66
67
|
} from "../../types/expr";
|
|
67
68
|
import type { DataType } from "../../types/column";
|
|
68
69
|
import { ExprRendererBase } from "../base/expr-renderer-base";
|
|
@@ -110,7 +111,7 @@ export class PostgresqlExprRenderer extends ExprRendererBase {
|
|
|
110
111
|
return `'${value.toString()}'::uuid`;
|
|
111
112
|
}
|
|
112
113
|
if (value instanceof Uint8Array) {
|
|
113
|
-
return `'\\x${
|
|
114
|
+
return `'\\x${bytes.toHex(value)}'::bytea`;
|
|
114
115
|
}
|
|
115
116
|
throw new Error(`Unknown value type: ${typeof value}`);
|
|
116
117
|
}
|
|
@@ -388,7 +389,7 @@ export class PostgresqlExprRenderer extends ExprRendererBase {
|
|
|
388
389
|
protected dateDiff(expr: ExprDateDiff): string {
|
|
389
390
|
const from = this.render(expr.from);
|
|
390
391
|
const to = this.render(expr.to);
|
|
391
|
-
switch (expr.
|
|
392
|
+
switch (expr.unit) {
|
|
392
393
|
case "year":
|
|
393
394
|
return `EXTRACT(YEAR FROM AGE(${to}, ${from}))::INTEGER`;
|
|
394
395
|
case "month":
|
|
@@ -407,7 +408,7 @@ export class PostgresqlExprRenderer extends ExprRendererBase {
|
|
|
407
408
|
protected dateAdd(expr: ExprDateAdd): string {
|
|
408
409
|
const source = this.render(expr.source);
|
|
409
410
|
const value = this.render(expr.value);
|
|
410
|
-
const unit = this.
|
|
411
|
+
const unit = this.dateUnitToSql(expr.unit);
|
|
411
412
|
return `${source} + INTERVAL '1 ${unit}' * ${value}`;
|
|
412
413
|
}
|
|
413
414
|
|
|
@@ -417,8 +418,8 @@ export class PostgresqlExprRenderer extends ExprRendererBase {
|
|
|
417
418
|
return `TO_CHAR(${this.render(expr.source)}, '${pgFormat}')`;
|
|
418
419
|
}
|
|
419
420
|
|
|
420
|
-
private
|
|
421
|
-
switch (
|
|
421
|
+
private dateUnitToSql(unit: DateUnit): string {
|
|
422
|
+
switch (unit) {
|
|
422
423
|
case "year":
|
|
423
424
|
return "year";
|
|
424
425
|
case "month":
|
|
@@ -449,7 +450,7 @@ export class PostgresqlExprRenderer extends ExprRendererBase {
|
|
|
449
450
|
|
|
450
451
|
//#region ========== condition ==========
|
|
451
452
|
|
|
452
|
-
protected
|
|
453
|
+
protected coalesce(expr: ExprCoalesce): string {
|
|
453
454
|
if (expr.args.length === 0) return "NULL";
|
|
454
455
|
if (expr.args.length === 1) return this.render(expr.args[0]);
|
|
455
456
|
// PostgreSQL: COALESCE
|
|
@@ -524,7 +525,7 @@ export class PostgresqlExprRenderer extends ExprRendererBase {
|
|
|
524
525
|
return "ROW_NUMBER() OVER ()";
|
|
525
526
|
}
|
|
526
527
|
|
|
527
|
-
protected random(): string {
|
|
528
|
+
protected random(_expr: ExprRandom): string {
|
|
528
529
|
return "RANDOM()";
|
|
529
530
|
}
|
|
530
531
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AddColumnQueryDef,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
AddForeignKeyQueryDef,
|
|
4
|
+
AddIndexQueryDef,
|
|
5
|
+
AddPrimaryKeyQueryDef,
|
|
6
6
|
ClearSchemaQueryDef,
|
|
7
7
|
CreateProcQueryDef,
|
|
8
8
|
CreateTableQueryDef,
|
|
@@ -10,9 +10,9 @@ import type {
|
|
|
10
10
|
SchemaExistsQueryDef,
|
|
11
11
|
DeleteQueryDef,
|
|
12
12
|
DropColumnQueryDef,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
DropForeignKeyQueryDef,
|
|
14
|
+
DropIndexQueryDef,
|
|
15
|
+
DropPrimaryKeyQueryDef,
|
|
16
16
|
DropProcQueryDef,
|
|
17
17
|
DropTableQueryDef,
|
|
18
18
|
DropViewQueryDef,
|
|
@@ -502,7 +502,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
502
502
|
|
|
503
503
|
//#region ========== DDL - Constraint ==========
|
|
504
504
|
|
|
505
|
-
protected
|
|
505
|
+
protected addPrimaryKey(def: AddPrimaryKeyQueryDef): QueryBuildResult {
|
|
506
506
|
const table = this.tableName(def.table);
|
|
507
507
|
const cols = def.columns.map((c) => this.expr.wrap(c)).join(", ");
|
|
508
508
|
const pkName = `PK_${def.table.name}`;
|
|
@@ -511,13 +511,13 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
511
511
|
};
|
|
512
512
|
}
|
|
513
513
|
|
|
514
|
-
protected
|
|
514
|
+
protected dropPrimaryKey(def: DropPrimaryKeyQueryDef): QueryBuildResult {
|
|
515
515
|
const table = this.tableName(def.table);
|
|
516
516
|
const pkName = `PK_${def.table.name}`;
|
|
517
517
|
return { sql: `ALTER TABLE ${table} DROP CONSTRAINT ${this.expr.wrap(pkName)}` };
|
|
518
518
|
}
|
|
519
519
|
|
|
520
|
-
protected
|
|
520
|
+
protected addForeignKey(def: AddForeignKeyQueryDef): QueryBuildResult {
|
|
521
521
|
const table = this.tableName(def.table);
|
|
522
522
|
const fk = def.foreignKey;
|
|
523
523
|
const fkCols = fk.fkColumns.map((c) => this.expr.wrap(c)).join(", ");
|
|
@@ -533,13 +533,13 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
533
533
|
return { sql };
|
|
534
534
|
}
|
|
535
535
|
|
|
536
|
-
protected
|
|
536
|
+
protected dropForeignKey(def: DropForeignKeyQueryDef): QueryBuildResult {
|
|
537
537
|
return {
|
|
538
538
|
sql: `ALTER TABLE ${this.tableName(def.table)} DROP CONSTRAINT ${this.expr.wrap(def.foreignKey)}`,
|
|
539
539
|
};
|
|
540
540
|
}
|
|
541
541
|
|
|
542
|
-
protected
|
|
542
|
+
protected addIndex(def: AddIndexQueryDef): QueryBuildResult {
|
|
543
543
|
const table = this.tableName(def.table);
|
|
544
544
|
const idx = def.index;
|
|
545
545
|
const cols = idx.columns.map((c) => `${this.expr.wrap(c.name)} ${c.orderBy}`).join(", ");
|
|
@@ -547,7 +547,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
|
547
547
|
return { sql: `CREATE ${unique}INDEX ${this.expr.wrap(idx.name)} ON ${table} (${cols})` };
|
|
548
548
|
}
|
|
549
549
|
|
|
550
|
-
protected
|
|
550
|
+
protected dropIndex(def: DropIndexQueryDef): QueryBuildResult {
|
|
551
551
|
// PostgreSQL: Index는 schema 레벨에서 유니크하므로 Table명 불필요하지만 스키마는 명시 필요
|
|
552
552
|
const schema = def.table.schema ?? "public";
|
|
553
553
|
return { sql: `DROP INDEX ${this.expr.wrap(schema)}.${this.expr.wrap(def.index)}` };
|
|
@@ -674,7 +674,7 @@ END $$`,
|
|
|
674
674
|
|
|
675
675
|
protected switchFk(def: SwitchFkQueryDef): QueryBuildResult {
|
|
676
676
|
const table = this.tableName(def.table);
|
|
677
|
-
if (def.
|
|
677
|
+
if (def.enabled) {
|
|
678
678
|
// PostgreSQL: Table의 모든 FK 트리거 Enable
|
|
679
679
|
return { sql: `ALTER TABLE ${table} ENABLE TRIGGER ALL` };
|
|
680
680
|
}
|
|
@@ -34,7 +34,7 @@ import { type ColumnBuilderRecord, createColumnFactory } from "./factory/column-
|
|
|
34
34
|
* }
|
|
35
35
|
*
|
|
36
36
|
* // 호출
|
|
37
|
-
* const users = await db.getUserById({ userId: 1n }).
|
|
37
|
+
* const users = await db.getUserById({ userId: 1n }).execute();
|
|
38
38
|
* ```
|
|
39
39
|
*
|
|
40
40
|
* @see {@link Procedure} factory function
|
|
@@ -58,7 +58,7 @@ export class TableBuilder<
|
|
|
58
58
|
readonly $relations!: TRelations;
|
|
59
59
|
|
|
60
60
|
/** 전체 Type inference (column + relationship) */
|
|
61
|
-
readonly $
|
|
61
|
+
readonly $inferSelect!: InferColumns<TColumns> & InferDeepRelations<TRelations>;
|
|
62
62
|
/** column만 Type inference */
|
|
63
63
|
readonly $inferColumns!: InferColumns<TColumns>;
|
|
64
64
|
/** INSERT용 Type inference (autoIncrement exclude, nullable/default는 optional) */
|
|
@@ -27,7 +27,7 @@ export interface DbContextBase {
|
|
|
27
27
|
getQueryDefObjectName(
|
|
28
28
|
tableOrView: TableBuilder<any, any> | ViewBuilder<any, any, any>,
|
|
29
29
|
): QueryDefObjectName;
|
|
30
|
-
switchFk(table: QueryDefObjectName,
|
|
30
|
+
switchFk(table: QueryDefObjectName, enabled: boolean): Promise<void>;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export type DbContextStatus = "ready" | "connect" | "transact";
|
|
@@ -61,13 +61,13 @@ export type DbContextInstance<TDef extends DbContextDef<any, any, any>> = DbCont
|
|
|
61
61
|
DbContextDdlMethods & {
|
|
62
62
|
// Auto-mapped table queryable accessors
|
|
63
63
|
[K in keyof TDef["meta"]["tables"]]: () => import("../exec/queryable").Queryable<
|
|
64
|
-
TDef["meta"]["tables"][K]["$
|
|
64
|
+
TDef["meta"]["tables"][K]["$inferSelect"],
|
|
65
65
|
TDef["meta"]["tables"][K]
|
|
66
66
|
>;
|
|
67
67
|
} & {
|
|
68
68
|
// Auto-mapped view queryable accessors
|
|
69
69
|
[K in keyof TDef["meta"]["views"]]: () => import("../exec/queryable").Queryable<
|
|
70
|
-
TDef["meta"]["views"][K]["$
|
|
70
|
+
TDef["meta"]["views"][K]["$inferSelect"],
|
|
71
71
|
never
|
|
72
72
|
>;
|
|
73
73
|
} & {
|
|
@@ -86,7 +86,7 @@ export type DbContextInstance<TDef extends DbContextDef<any, any, any>> = DbCont
|
|
|
86
86
|
export interface DbContextConnectionMethods {
|
|
87
87
|
connect<TResult>(fn: () => Promise<TResult>, isolationLevel?: IsolationLevel): Promise<TResult>;
|
|
88
88
|
connectWithoutTransaction<TResult>(callback: () => Promise<TResult>): Promise<TResult>;
|
|
89
|
-
|
|
89
|
+
transaction<TResult>(fn: () => Promise<TResult>, isolationLevel?: IsolationLevel): Promise<TResult>;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
export interface DbContextDdlMethods {
|
|
@@ -109,20 +109,20 @@ export interface DbContextDdlMethods {
|
|
|
109
109
|
column: ColumnBuilder<any, any>,
|
|
110
110
|
): Promise<void>;
|
|
111
111
|
renameColumn(table: QueryDefObjectName, column: string, newName: string): Promise<void>;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
addPrimaryKey(table: QueryDefObjectName, columns: string[]): Promise<void>;
|
|
113
|
+
dropPrimaryKey(table: QueryDefObjectName): Promise<void>;
|
|
114
|
+
addForeignKey(
|
|
115
115
|
table: QueryDefObjectName,
|
|
116
116
|
relationName: string,
|
|
117
117
|
relationDef: ForeignKeyBuilder<any, any>,
|
|
118
118
|
): Promise<void>;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
119
|
+
addIndex(table: QueryDefObjectName, indexBuilder: IndexBuilder<string[]>): Promise<void>;
|
|
120
|
+
dropForeignKey(table: QueryDefObjectName, relationName: string): Promise<void>;
|
|
121
|
+
dropIndex(table: QueryDefObjectName, columns: string[]): Promise<void>;
|
|
122
122
|
clearSchema(params: { database: string; schema?: string }): Promise<void>;
|
|
123
123
|
schemaExists(database: string, schema?: string): Promise<boolean>;
|
|
124
124
|
truncate(table: QueryDefObjectName): Promise<void>;
|
|
125
|
-
switchFk(table: QueryDefObjectName,
|
|
125
|
+
switchFk(table: QueryDefObjectName, enabled: boolean): Promise<void>;
|
|
126
126
|
// QueryDef generators
|
|
127
127
|
getCreateTableQueryDef(table: TableBuilder<any, any>): QueryDef;
|
|
128
128
|
getCreateViewQueryDef(view: ViewBuilder<any, any, any>): QueryDef;
|
|
@@ -146,18 +146,18 @@ export interface DbContextDdlMethods {
|
|
|
146
146
|
column: ColumnBuilder<any, any>,
|
|
147
147
|
): QueryDef;
|
|
148
148
|
getRenameColumnQueryDef(table: QueryDefObjectName, column: string, newName: string): QueryDef;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
getAddPrimaryKeyQueryDef(table: QueryDefObjectName, columns: string[]): QueryDef;
|
|
150
|
+
getDropPrimaryKeyQueryDef(table: QueryDefObjectName): QueryDef;
|
|
151
|
+
getAddForeignKeyQueryDef(
|
|
152
152
|
table: QueryDefObjectName,
|
|
153
153
|
relationName: string,
|
|
154
154
|
relationDef: ForeignKeyBuilder<any, any>,
|
|
155
155
|
): QueryDef;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
getAddIndexQueryDef(table: QueryDefObjectName, indexBuilder: IndexBuilder<string[]>): QueryDef;
|
|
157
|
+
getDropForeignKeyQueryDef(table: QueryDefObjectName, relationName: string): QueryDef;
|
|
158
|
+
getDropIndexQueryDef(table: QueryDefObjectName, columns: string[]): QueryDef;
|
|
159
159
|
getClearSchemaQueryDef(params: { database: string; schema?: string }): QueryDef;
|
|
160
160
|
getSchemaExistsQueryDef(database: string, schema?: string): QueryDef;
|
|
161
161
|
getTruncateQueryDef(table: QueryDefObjectName): QueryDef;
|
|
162
|
-
getSwitchFkQueryDef(table: QueryDefObjectName,
|
|
162
|
+
getSwitchFkQueryDef(table: QueryDefObjectName, enabled: boolean): QueryDef;
|
|
163
163
|
}
|
package/src/types/expr.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type { SelectQueryDef } from "./query-def";
|
|
|
6
6
|
*
|
|
7
7
|
* dateDiff, dateAdd 등 Date functionused in
|
|
8
8
|
*/
|
|
9
|
-
export type
|
|
9
|
+
export type DateUnit = "year" | "month" | "day" | "hour" | "minute" | "second";
|
|
10
10
|
|
|
11
11
|
//#region ========== value expression ==========
|
|
12
12
|
|
|
@@ -326,7 +326,7 @@ export interface ExprIsoYearMonth {
|
|
|
326
326
|
/** Date 차이 (DATEDIFF) */
|
|
327
327
|
export interface ExprDateDiff {
|
|
328
328
|
type: "dateDiff";
|
|
329
|
-
|
|
329
|
+
unit: DateUnit;
|
|
330
330
|
from: Expr;
|
|
331
331
|
to: Expr;
|
|
332
332
|
}
|
|
@@ -334,7 +334,7 @@ export interface ExprDateDiff {
|
|
|
334
334
|
/** Date 연산 (DATEADD) */
|
|
335
335
|
export interface ExprDateAdd {
|
|
336
336
|
type: "dateAdd";
|
|
337
|
-
|
|
337
|
+
unit: DateUnit;
|
|
338
338
|
source: Expr;
|
|
339
339
|
value: Expr;
|
|
340
340
|
}
|
|
@@ -351,8 +351,8 @@ export interface ExprFormatDate {
|
|
|
351
351
|
//#region ========== condition ==========
|
|
352
352
|
|
|
353
353
|
/** NULL 대체 (COALESCE - 첫 번째 non-null return) */
|
|
354
|
-
export interface
|
|
355
|
-
type: "
|
|
354
|
+
export interface ExprCoalesce {
|
|
355
|
+
type: "coalesce";
|
|
356
356
|
args: Expr[];
|
|
357
357
|
}
|
|
358
358
|
|
|
@@ -668,7 +668,7 @@ export type Expr =
|
|
|
668
668
|
| ExprFormatDate
|
|
669
669
|
|
|
670
670
|
// Condition
|
|
671
|
-
|
|
|
671
|
+
| ExprCoalesce
|
|
672
672
|
| ExprNullIf
|
|
673
673
|
| ExprIs
|
|
674
674
|
| ExprSwitch
|