@simplysm/orm-common 13.0.76 → 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.
Files changed (109) hide show
  1. package/README.md +575 -50
  2. package/dist/create-db-context.d.ts +1 -1
  3. package/dist/create-db-context.d.ts.map +1 -1
  4. package/dist/create-db-context.js +34 -27
  5. package/dist/create-db-context.js.map +1 -1
  6. package/dist/ddl/initialize.js +4 -4
  7. package/dist/ddl/initialize.js.map +1 -1
  8. package/dist/ddl/relation-ddl.d.ts +7 -7
  9. package/dist/ddl/relation-ddl.d.ts.map +1 -1
  10. package/dist/ddl/relation-ddl.js +18 -18
  11. package/dist/ddl/relation-ddl.js.map +1 -1
  12. package/dist/ddl/schema-ddl.d.ts +1 -1
  13. package/dist/ddl/schema-ddl.d.ts.map +1 -1
  14. package/dist/ddl/schema-ddl.js +2 -2
  15. package/dist/ddl/schema-ddl.js.map +1 -1
  16. package/dist/ddl/table-ddl.js +2 -2
  17. package/dist/ddl/table-ddl.js.map +1 -1
  18. package/dist/exec/queryable.d.ts +24 -24
  19. package/dist/exec/queryable.d.ts.map +1 -1
  20. package/dist/exec/queryable.js +37 -37
  21. package/dist/exec/queryable.js.map +1 -1
  22. package/dist/expr/expr-unit.js +1 -1
  23. package/dist/expr/expr-unit.js.map +1 -1
  24. package/dist/expr/expr.d.ts +9 -9
  25. package/dist/expr/expr.d.ts.map +1 -1
  26. package/dist/expr/expr.js +10 -10
  27. package/dist/expr/expr.js.map +1 -1
  28. package/dist/query-builder/base/expr-renderer-base.d.ts +2 -2
  29. package/dist/query-builder/base/expr-renderer-base.d.ts.map +1 -1
  30. package/dist/query-builder/base/query-builder-base.d.ts +7 -15
  31. package/dist/query-builder/base/query-builder-base.d.ts.map +1 -1
  32. package/dist/query-builder/base/query-builder-base.js +2 -2
  33. package/dist/query-builder/base/query-builder-base.js.map +1 -1
  34. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +4 -4
  35. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
  36. package/dist/query-builder/mssql/mssql-expr-renderer.js +8 -8
  37. package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
  38. package/dist/query-builder/mssql/mssql-query-builder.d.ts +7 -7
  39. package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
  40. package/dist/query-builder/mssql/mssql-query-builder.js +7 -7
  41. package/dist/query-builder/mssql/mssql-query-builder.js.map +1 -1
  42. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +4 -4
  43. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
  44. package/dist/query-builder/mysql/mysql-expr-renderer.js +9 -9
  45. package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
  46. package/dist/query-builder/mysql/mysql-query-builder.d.ts +7 -7
  47. package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
  48. package/dist/query-builder/mysql/mysql-query-builder.js +11 -11
  49. package/dist/query-builder/mysql/mysql-query-builder.js.map +1 -1
  50. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +4 -4
  51. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
  52. package/dist/query-builder/postgresql/postgresql-expr-renderer.js +8 -8
  53. package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
  54. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +7 -7
  55. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
  56. package/dist/query-builder/postgresql/postgresql-query-builder.js +7 -7
  57. package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
  58. package/dist/schema/procedure-builder.d.ts +1 -1
  59. package/dist/schema/table-builder.d.ts +1 -1
  60. package/dist/schema/table-builder.d.ts.map +1 -1
  61. package/dist/schema/table-builder.js +1 -1
  62. package/dist/schema/view-builder.d.ts +1 -1
  63. package/dist/schema/view-builder.d.ts.map +1 -1
  64. package/dist/schema/view-builder.js +1 -1
  65. package/dist/types/db-context-def.d.ts +18 -18
  66. package/dist/types/db-context-def.d.ts.map +1 -1
  67. package/dist/types/expr.d.ts +6 -6
  68. package/dist/types/expr.d.ts.map +1 -1
  69. package/dist/types/query-def.d.ts +15 -15
  70. package/dist/types/query-def.d.ts.map +1 -1
  71. package/dist/types/query-def.js +6 -6
  72. package/dist/utils/result-parser.d.ts.map +1 -1
  73. package/dist/utils/result-parser.js +44 -16
  74. package/dist/utils/result-parser.js.map +1 -1
  75. package/package.json +2 -2
  76. package/src/create-db-context.ts +36 -29
  77. package/src/ddl/initialize.ts +4 -4
  78. package/src/ddl/relation-ddl.ts +16 -16
  79. package/src/ddl/schema-ddl.ts +2 -2
  80. package/src/ddl/table-ddl.ts +2 -2
  81. package/src/exec/queryable.ts +58 -58
  82. package/src/expr/expr-unit.ts +1 -1
  83. package/src/expr/expr.ts +13 -13
  84. package/src/query-builder/base/expr-renderer-base.ts +2 -2
  85. package/src/query-builder/base/query-builder-base.ts +18 -14
  86. package/src/query-builder/mssql/mssql-expr-renderer.ts +11 -10
  87. package/src/query-builder/mssql/mssql-query-builder.ts +13 -13
  88. package/src/query-builder/mysql/mysql-expr-renderer.ts +12 -11
  89. package/src/query-builder/mysql/mysql-query-builder.ts +17 -17
  90. package/src/query-builder/postgresql/postgresql-expr-renderer.ts +11 -10
  91. package/src/query-builder/postgresql/postgresql-query-builder.ts +13 -13
  92. package/src/schema/procedure-builder.ts +1 -1
  93. package/src/schema/table-builder.ts +1 -1
  94. package/src/schema/view-builder.ts +1 -1
  95. package/src/types/db-context-def.ts +18 -18
  96. package/src/types/expr.ts +6 -6
  97. package/src/types/query-def.ts +31 -31
  98. package/src/utils/result-parser.ts +60 -16
  99. package/tests/db-context/create-db-context.spec.ts +6 -6
  100. package/tests/ddl/basic.expected.ts +8 -8
  101. package/tests/ddl/basic.spec.ts +24 -24
  102. package/tests/ddl/index-builder.spec.ts +10 -10
  103. package/tests/ddl/relation-builder.spec.ts +4 -4
  104. package/tests/dml/update.spec.ts +2 -2
  105. package/tests/expr/conditional.expected.ts +2 -2
  106. package/tests/expr/conditional.spec.ts +8 -8
  107. package/tests/expr/date.spec.ts +5 -5
  108. package/tests/select/basic.spec.ts +5 -5
  109. package/tests/utils/result-parser.spec.ts +4 -4
@@ -22,7 +22,7 @@ import type { ColumnPrimitive, ColumnPrimitiveStr } from "../types/column";
22
22
  import type { WhereExprUnit, ExprInput } from "../expr/expr-unit";
23
23
  import { ExprUnit } from "../expr/expr-unit";
24
24
  import type { Expr } from "../types/expr";
25
- import { ArgumentError, objClearUndefined } from "@simplysm/core-common";
25
+ import { ArgumentError, obj } from "@simplysm/core-common";
26
26
  import {
27
27
  ForeignKeyBuilder,
28
28
  ForeignKeyTargetBuilder,
@@ -49,7 +49,7 @@ class JoinQueryable {
49
49
  * @param table - Table to join
50
50
  * @returns Joined Queryable
51
51
  */
52
- from<T extends TableBuilder<any, any>>(table: T): Queryable<T["$infer"], T> {
52
+ from<T extends TableBuilder<any, any>>(table: T): Queryable<T["$inferSelect"], T> {
53
53
  return queryable(this._db, table, this._joinAlias)();
54
54
  }
55
55
 
@@ -115,7 +115,7 @@ class RecursiveQueryable<TBaseData extends DataRecord> {
115
115
  */
116
116
  from<T extends TableBuilder<any, any>>(
117
117
  table: T,
118
- ): Queryable<T["$infer"] & { self?: TBaseData[] }, T> {
118
+ ): Queryable<T["$inferSelect"] & { self?: TBaseData[] }, T> {
119
119
  const selfAlias = `${this._cteName}.self`;
120
120
 
121
121
  return queryable(this._baseQr.meta.db, table, this._cteName)().join(
@@ -214,12 +214,12 @@ class RecursiveQueryable<TBaseData extends DataRecord> {
214
214
  * const users = await db.user()
215
215
  * .where((u) => [expr.eq(u.isActive, true)])
216
216
  * .orderBy((u) => u.name)
217
- * .result();
217
+ * .execute();
218
218
  *
219
219
  * // JOIN query
220
220
  * const posts = await db.post()
221
221
  * .include((p) => p.user)
222
- * .result();
222
+ * .execute();
223
223
  *
224
224
  * // INSERT
225
225
  * await db.user().insert([{ name: "Gildong Hong", email: "test@test.com" }]);
@@ -621,7 +621,7 @@ export class Queryable<
621
621
  * 1:N 관계의 LEFT OUTER JOIN을 수행 (배열로 result Add)
622
622
  *
623
623
  * @param as - Result에 추가할 property 이름
624
- * @param fwd - Join 조건을 정의하는 콜백 function
624
+ * @param fn - Join 조건을 정의하는 콜백 function
625
625
  * @returns join 결과가 배열로 추가된 Queryable
626
626
  *
627
627
  * @example
@@ -636,10 +636,10 @@ export class Queryable<
636
636
  */
637
637
  join<A extends string, R extends DataRecord>(
638
638
  as: A,
639
- fwd: (qr: JoinQueryable, cols: QueryableRecord<TData>) => Queryable<R, any>,
639
+ fn: (qr: JoinQueryable, cols: QueryableRecord<TData>) => Queryable<R, any>,
640
640
  ): Queryable<TData & { [K in A]?: R[] }, TFrom> {
641
641
  if (Array.isArray(this.meta.from)) {
642
- const newFroms = this.meta.from.map((from) => from.join(as, fwd));
642
+ const newFroms = this.meta.from.map((from) => from.join(as, fn));
643
643
  return new Queryable({
644
644
  ...this.meta,
645
645
  from: newFroms,
@@ -653,8 +653,8 @@ export class Queryable<
653
653
  // 2. target → Queryable Transform (alias 전달)
654
654
  const joinQr = new JoinQueryable(this.meta.db, joinAlias);
655
655
 
656
- // 3. fwd 실행 (where 등 condition 추가된 Queryable return)
657
- const resultQr = fwd(joinQr, this.meta.columns);
656
+ // 3. fn 실행 (where 등 condition 추가된 Queryable return)
657
+ const resultQr = fn(joinQr, this.meta.columns);
658
658
 
659
659
  // 4. 새 columns에 join result Add
660
660
  const joinColumns = transformColumnsAlias(resultQr.meta.columns, joinAlias);
@@ -674,7 +674,7 @@ export class Queryable<
674
674
  * N:1 또는 1:1 관계의 LEFT OUTER JOIN을 수행 (단일 객체로 result Add)
675
675
  *
676
676
  * @param as - Result에 추가할 property 이름
677
- * @param fwd - Join 조건을 정의하는 콜백 function
677
+ * @param fn - Join 조건을 정의하는 콜백 function
678
678
  * @returns join 결과가 단일 객체로 추가된 Queryable
679
679
  *
680
680
  * @example
@@ -689,13 +689,13 @@ export class Queryable<
689
689
  */
690
690
  joinSingle<A extends string, R extends DataRecord>(
691
691
  as: A,
692
- fwd: (qr: JoinQueryable, cols: QueryableRecord<TData>) => Queryable<R, any>,
692
+ fn: (qr: JoinQueryable, cols: QueryableRecord<TData>) => Queryable<R, any>,
693
693
  ): Queryable<
694
694
  { [K in keyof TData as K extends A ? never : K]: TData[K] } & { [K in A]?: R },
695
695
  TFrom
696
696
  > {
697
697
  if (Array.isArray(this.meta.from)) {
698
- const newFroms = this.meta.from.map((from) => from.joinSingle(as, fwd));
698
+ const newFroms = this.meta.from.map((from) => from.joinSingle(as, fn));
699
699
  return new Queryable({
700
700
  ...this.meta,
701
701
  from: newFroms,
@@ -709,8 +709,8 @@ export class Queryable<
709
709
  // 2. target → Queryable Transform (alias 전달)
710
710
  const joinQr = new JoinQueryable(this.meta.db, joinAlias);
711
711
 
712
- // 3. fwd 실행 (where 등 condition 추가된 Queryable return)
713
- const resultQr = fwd(joinQr, this.meta.columns);
712
+ // 3. fn 실행 (where 등 condition 추가된 Queryable return)
713
+ const resultQr = fn(joinQr, this.meta.columns);
714
714
 
715
715
  // 4. 새 columns에 join result Add
716
716
  const joinColumns = transformColumnsAlias(resultQr.meta.columns, joinAlias);
@@ -957,7 +957,7 @@ export class Queryable<
957
957
  *
958
958
  * 계층 structure data(조직도, 카테고리 트리 등)를 조회할 때 사용
959
959
  *
960
- * @param fwd - recursive part을 정의하는 콜백 function
960
+ * @param fn - recursive part을 정의하는 콜백 function
961
961
  * @returns recursive CTE가 apply된 Queryable
962
962
  *
963
963
  * @example
@@ -972,10 +972,10 @@ export class Queryable<
972
972
  * ```
973
973
  */
974
974
  recursive(
975
- fwd: (qr: RecursiveQueryable<TData>) => Queryable<TData, any>,
975
+ fn: (qr: RecursiveQueryable<TData>) => Queryable<TData, any>,
976
976
  ): Queryable<TData, never> {
977
977
  if (Array.isArray(this.meta.from)) {
978
- const newFroms = this.meta.from.map((from) => from.recursive(fwd));
978
+ const newFroms = this.meta.from.map((from) => from.recursive(fn));
979
979
  return new Queryable({
980
980
  ...this.meta,
981
981
  from: newFroms,
@@ -988,8 +988,8 @@ export class Queryable<
988
988
  // 2. target → Queryable Transform (CTE 이름 전달)
989
989
  const cteQr = new RecursiveQueryable(this, cteName);
990
990
 
991
- // 3. fwd 실행 (where 등 condition 추가된 Queryable return)
992
- const resultQr = fwd(cteQr);
991
+ // 3. fn 실행 (where 등 condition 추가된 Queryable return)
992
+ const resultQr = fn(cteQr);
993
993
 
994
994
  return new Queryable({
995
995
  db: this.meta.db,
@@ -1017,10 +1017,10 @@ export class Queryable<
1017
1017
  * ```typescript
1018
1018
  * const users = await db.user()
1019
1019
  * .where((u) => [expr.eq(u.isActive, true)])
1020
- * .result();
1020
+ * .execute();
1021
1021
  * ```
1022
1022
  */
1023
- async result(): Promise<TData[]> {
1023
+ async execute(): Promise<TData[]> {
1024
1024
  const results = await this.meta.db.executeDefs<TData>(
1025
1025
  [this.getSelectQueryDef()],
1026
1026
  [this.getResultMeta()],
@@ -1042,7 +1042,7 @@ export class Queryable<
1042
1042
  * ```
1043
1043
  */
1044
1044
  async single(): Promise<TData | undefined> {
1045
- const result = await this.top(2).result();
1045
+ const result = await this.top(2).execute();
1046
1046
  if (result.length > 1) {
1047
1047
  throw new ArgumentError("Expected single result but multiple results returned.", {
1048
1048
  table: this._getSourceName(),
@@ -1079,14 +1079,14 @@ export class Queryable<
1079
1079
  * ```
1080
1080
  */
1081
1081
  async first(): Promise<TData | undefined> {
1082
- const results = await this.top(1).result();
1082
+ const results = await this.top(1).execute();
1083
1083
  return results[0];
1084
1084
  }
1085
1085
 
1086
1086
  /**
1087
1087
  * result row 수를 return
1088
1088
  *
1089
- * @param fwd - 카운트할 column을 지정하는 function (Select)
1089
+ * @param fn - 카운트할 column을 지정하는 function (Select)
1090
1090
  * @returns row 수
1091
1091
  * @throws distinct() 또는 groupBy() 후 직접 호출 시 에러 (wrap() 필요)
1092
1092
  *
@@ -1097,7 +1097,7 @@ export class Queryable<
1097
1097
  * .count();
1098
1098
  * ```
1099
1099
  */
1100
- async count(fwd?: (cols: QueryableRecord<TData>) => ExprUnit<ColumnPrimitive>): Promise<number> {
1100
+ async count(fn?: (cols: QueryableRecord<TData>) => ExprUnit<ColumnPrimitive>): Promise<number> {
1101
1101
  if (this.meta.distinct) {
1102
1102
  throw new Error("Cannot use count() after distinct(). Use wrap() first.");
1103
1103
  }
@@ -1105,8 +1105,8 @@ export class Queryable<
1105
1105
  throw new Error("Cannot use count() after groupBy(). Use wrap() first.");
1106
1106
  }
1107
1107
 
1108
- const countQr = fwd
1109
- ? this.select((c) => ({ cnt: expr.count(fwd(c)) }))
1108
+ const countQr = fn
1109
+ ? this.select((c) => ({ cnt: expr.count(fn(c)) }))
1110
1110
  : this.select(() => ({ cnt: expr.count() }));
1111
1111
 
1112
1112
  const result = await countQr.single();
@@ -1132,7 +1132,7 @@ export class Queryable<
1132
1132
  }
1133
1133
 
1134
1134
  getSelectQueryDef(): SelectQueryDef {
1135
- return objClearUndefined({
1135
+ return obj.clearUndefined({
1136
1136
  type: "select",
1137
1137
  from: this._buildFromDef(),
1138
1138
  as: this.meta.as,
@@ -1394,7 +1394,7 @@ export class Queryable<
1394
1394
  outputDef.aiColName != null &&
1395
1395
  records.some((r) => (r as Record<string, unknown>)[outputDef.aiColName!] !== undefined);
1396
1396
 
1397
- return objClearUndefined({
1397
+ return obj.clearUndefined({
1398
1398
  type: "insert",
1399
1399
  table: this.meta.db.getQueryDefObjectName(from),
1400
1400
  records,
@@ -1418,7 +1418,7 @@ export class Queryable<
1418
1418
 
1419
1419
  const { select: _, ...existsSelectQuery } = this.getSelectQueryDef();
1420
1420
 
1421
- return objClearUndefined({
1421
+ return obj.clearUndefined({
1422
1422
  type: "insertIfNotExists",
1423
1423
  table: this.meta.db.getQueryDefObjectName(from),
1424
1424
  record,
@@ -1439,7 +1439,7 @@ export class Queryable<
1439
1439
  ): InsertIntoQueryDef {
1440
1440
  const outputDef = this._getCudOutputDef();
1441
1441
 
1442
- return objClearUndefined({
1442
+ return obj.clearUndefined({
1443
1443
  type: "insertInto",
1444
1444
  table: this.meta.db.getQueryDefObjectName(targetTable),
1445
1445
  recordsSelectQuery: this.getSelectQueryDef(),
@@ -1545,7 +1545,7 @@ export class Queryable<
1545
1545
  const from = this.meta.from as TableBuilder<any, any> | ViewBuilder<any, any, any>;
1546
1546
  const outputDef = this._getCudOutputDef();
1547
1547
 
1548
- return objClearUndefined({
1548
+ return obj.clearUndefined({
1549
1549
  type: "update",
1550
1550
  table: this.meta.db.getQueryDefObjectName(from),
1551
1551
  as: this.meta.as,
@@ -1568,7 +1568,7 @@ export class Queryable<
1568
1568
  const from = this.meta.from as TableBuilder<any, any> | ViewBuilder<any, any, any>;
1569
1569
  const outputDef = this._getCudOutputDef();
1570
1570
 
1571
- return objClearUndefined({
1571
+ return obj.clearUndefined({
1572
1572
  type: "delete",
1573
1573
  table: this.meta.db.getQueryDefObjectName(from),
1574
1574
  as: this.meta.as,
@@ -1595,8 +1595,8 @@ export class Queryable<
1595
1595
  *
1596
1596
  * WHERE condition에 맞는 data가 있으면 UPDATE, 없으면 INSERT
1597
1597
  *
1598
- * @param updateFwd - Update할 column과 값을 반환하는 function
1599
- * @param insertFwd - Insert할 레코드를 반환하는 function (selection, 미지정 시 updateFwd와 동일)
1598
+ * @param updateFn - Update할 column과 값을 반환하는 function
1599
+ * @param insertFn - Insert할 레코드를 반환하는 function (selection, 미지정 시 updateFn와 동일)
1600
1600
  * @param outputColumns - column name array to receive (Select)
1601
1601
  * @returns outputColumns 지정 시 영향받은 레코드 array return
1602
1602
  *
@@ -1620,47 +1620,47 @@ export class Queryable<
1620
1620
  * ```
1621
1621
  */
1622
1622
  async upsert(
1623
- updateFwd: (cols: QueryableRecord<TData>) => QueryableWriteRecord<TFrom["$inferUpdate"]>,
1623
+ updateFn: (cols: QueryableRecord<TData>) => QueryableWriteRecord<TFrom["$inferUpdate"]>,
1624
1624
  ): Promise<void>;
1625
1625
  async upsert<K extends keyof TFrom["$inferColumns"] & string>(
1626
- insertFwd: (cols: QueryableRecord<TData>) => QueryableWriteRecord<TFrom["$inferInsert"]>,
1626
+ insertFn: (cols: QueryableRecord<TData>) => QueryableWriteRecord<TFrom["$inferInsert"]>,
1627
1627
  outputColumns?: K[],
1628
1628
  ): Promise<Pick<TFrom["$inferColumns"], K>[]>;
1629
1629
  async upsert<U extends QueryableWriteRecord<TFrom["$inferUpdate"]>>(
1630
- updateFwd: (cols: QueryableRecord<TData>) => U,
1631
- insertFwd: (updateRecord: U) => QueryableWriteRecord<TFrom["$inferInsert"]>,
1630
+ updateFn: (cols: QueryableRecord<TData>) => U,
1631
+ insertFn: (updateRecord: U) => QueryableWriteRecord<TFrom["$inferInsert"]>,
1632
1632
  ): Promise<void>;
1633
1633
  async upsert<
1634
1634
  U extends QueryableWriteRecord<TFrom["$inferUpdate"]>,
1635
1635
  K extends keyof TFrom["$inferColumns"] & string,
1636
1636
  >(
1637
- updateFwd: (cols: QueryableRecord<TData>) => U,
1638
- insertFwd: (updateRecord: U) => QueryableWriteRecord<TFrom["$inferInsert"]>,
1637
+ updateFn: (cols: QueryableRecord<TData>) => U,
1638
+ insertFn: (updateRecord: U) => QueryableWriteRecord<TFrom["$inferInsert"]>,
1639
1639
  outputColumns?: K[],
1640
1640
  ): Promise<Pick<TFrom["$inferColumns"], K>[]>;
1641
1641
  async upsert<
1642
1642
  U extends QueryableWriteRecord<TFrom["$inferUpdate"]>,
1643
1643
  K extends keyof TFrom["$inferColumns"] & string,
1644
1644
  >(
1645
- updateFwdOrInsertFwd:
1645
+ updateFnOrInsertFn:
1646
1646
  | ((cols: QueryableRecord<TData>) => U)
1647
1647
  | ((cols: QueryableRecord<TData>) => QueryableWriteRecord<TFrom["$inferInsert"]>),
1648
- insertFwdOrOutputColumns?:
1648
+ insertFnOrOutputColumns?:
1649
1649
  | ((updateRecord: U) => QueryableWriteRecord<TFrom["$inferInsert"]>)
1650
1650
  | K[],
1651
1651
  outputColumns?: K[],
1652
1652
  ): Promise<Pick<TFrom["$inferColumns"], K>[] | void> {
1653
- const updateRecordFwd = updateFwdOrInsertFwd as (cols: QueryableRecord<TData>) => U;
1653
+ const updateRecordFn = updateFnOrInsertFn as (cols: QueryableRecord<TData>) => U;
1654
1654
 
1655
- const insertRecordFwd = (
1656
- insertFwdOrOutputColumns instanceof Function ? insertFwdOrOutputColumns : updateFwdOrInsertFwd
1655
+ const insertRecordFn = (
1656
+ insertFnOrOutputColumns instanceof Function ? insertFnOrOutputColumns : updateFnOrInsertFn
1657
1657
  ) as (updateRecord: U) => QueryableWriteRecord<TFrom["$inferInsert"]>;
1658
1658
 
1659
1659
  const realOutputColumns =
1660
- insertFwdOrOutputColumns instanceof Function ? outputColumns : insertFwdOrOutputColumns;
1660
+ insertFnOrOutputColumns instanceof Function ? outputColumns : insertFnOrOutputColumns;
1661
1661
 
1662
1662
  const results = await this.meta.db.executeDefs<Pick<TFrom["$inferColumns"], K>>(
1663
- [this.getUpsertQueryDef(updateRecordFwd, insertRecordFwd, realOutputColumns)],
1663
+ [this.getUpsertQueryDef(updateRecordFn, insertRecordFn, realOutputColumns)],
1664
1664
  [realOutputColumns ? this.getResultMeta(realOutputColumns) : undefined],
1665
1665
  );
1666
1666
 
@@ -1670,8 +1670,8 @@ export class Queryable<
1670
1670
  }
1671
1671
 
1672
1672
  getUpsertQueryDef<U extends QueryableWriteRecord<TFrom["$inferUpdate"]>>(
1673
- updateRecordFwd: (cols: QueryableRecord<TData>) => U,
1674
- insertRecordFwd: (updateRecord: U) => QueryableWriteRecord<TFrom["$inferInsert"]>,
1673
+ updateRecordFn: (cols: QueryableRecord<TData>) => U,
1674
+ insertRecordFn: (updateRecord: U) => QueryableWriteRecord<TFrom["$inferInsert"]>,
1675
1675
  outputColumns?: (keyof TFrom["$inferColumns"] & string)[],
1676
1676
  ): UpsertQueryDef {
1677
1677
  const from = this.meta.from as TableBuilder<any, any> | ViewBuilder<any, any, any>;
@@ -1680,19 +1680,19 @@ export class Queryable<
1680
1680
  const { select: _sel, ...existsSelectQuery } = this.getSelectQueryDef();
1681
1681
 
1682
1682
  // updateRecord Generate
1683
- const updateQrRecord = updateRecordFwd(this.meta.columns);
1683
+ const updateQrRecord = updateRecordFn(this.meta.columns);
1684
1684
  const updateRecord: Record<string, Expr> = {};
1685
1685
  for (const [key, value] of Object.entries(updateQrRecord)) {
1686
1686
  updateRecord[key] = expr.toExpr(value);
1687
1687
  }
1688
1688
 
1689
1689
  // insertRecord Generate (updateRecordRaw를 두 번째 인자로)
1690
- const insertRecordRaw = insertRecordFwd(updateQrRecord);
1690
+ const insertRecordRaw = insertRecordFn(updateQrRecord);
1691
1691
  const insertRecord = Object.fromEntries(
1692
1692
  Object.entries(insertRecordRaw).map(([key, value]) => [key, expr.toExpr(value)]),
1693
1693
  );
1694
1694
 
1695
- return objClearUndefined({
1695
+ return obj.clearUndefined({
1696
1696
  type: "upsert",
1697
1697
  table: this.meta.db.getQueryDefObjectName(from),
1698
1698
  existsSelectQuery,
@@ -1715,14 +1715,14 @@ export class Queryable<
1715
1715
  /**
1716
1716
  * FK constraint on/off (transaction 내 사용 가능)
1717
1717
  */
1718
- async switchFk(switch_: "on" | "off"): Promise<void> {
1718
+ async switchFk(enabled: boolean): Promise<void> {
1719
1719
  const from = this.meta.from;
1720
1720
  if (!(from instanceof TableBuilder) && !(from instanceof ViewBuilder)) {
1721
1721
  throw new Error(
1722
1722
  "switchFk는 TableBuilder 또는 ViewBuilder 기반 queryable에서만 사용할 수 있습니다.",
1723
1723
  );
1724
1724
  }
1725
- await this.meta.db.switchFk(this.meta.db.getQueryDefObjectName(from), switch_);
1725
+ await this.meta.db.switchFk(this.meta.db.getQueryDefObjectName(from), enabled);
1726
1726
  }
1727
1727
 
1728
1728
  //#endregion
@@ -1981,7 +1981,7 @@ function createPathProxy<TObject>(path: string[] = []): PathProxy<TObject> {
1981
1981
  * async getActiveUsers() {
1982
1982
  * return this.user()
1983
1983
  * .where((u) => [expr.eq(u.isActive, true)])
1984
- * .result();
1984
+ * .execute();
1985
1985
  * }
1986
1986
  * }
1987
1987
  * ```
@@ -1990,7 +1990,7 @@ export function queryable<TBuilder extends TableBuilder<any, any> | ViewBuilder<
1990
1990
  db: DbContextBase,
1991
1991
  tableOrView: TBuilder,
1992
1992
  as?: string,
1993
- ): () => Queryable<TBuilder["$infer"], TBuilder extends TableBuilder<any, any> ? TBuilder : never> {
1993
+ ): () => Queryable<TBuilder["$inferSelect"], TBuilder extends TableBuilder<any, any> ? TBuilder : never> {
1994
1994
  return () => {
1995
1995
  // as가 명시되지 않으면 db.getNextAlias() 사용 (카운터 증가)
1996
1996
  // as가 명시되면 그대로 사용 (카운터 증가 안함)
@@ -9,7 +9,7 @@ export class ExprUnit<TPrimitive extends ColumnPrimitive> {
9
9
  readonly $infer!: TPrimitive;
10
10
 
11
11
  get n(): ExprUnit<NonNullable<TPrimitive>> {
12
- return this as unknown as ExprUnit<NonNullable<TPrimitive>>;
12
+ return new ExprUnit<NonNullable<TPrimitive>>(this.dataType, this.expr);
13
13
  }
14
14
 
15
15
  constructor(
package/src/expr/expr.ts CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  } from "../types/column";
11
11
  import type { ExprInput } from "./expr-unit";
12
12
  import { ExprUnit, WhereExprUnit } from "./expr-unit";
13
- import type { Expr, DateSeparator, WhereExpr, WinSpec } from "../types/expr";
13
+ import type { Expr, DateUnit, WhereExpr, WinSpec } from "../types/expr";
14
14
  import type { SelectQueryDef } from "../types/query-def";
15
15
  import type { Queryable } from "../exec/queryable";
16
16
 
@@ -1163,7 +1163,7 @@ export const expr = {
1163
1163
  /**
1164
1164
  * Date 차이 계산 (DATEDIFF)
1165
1165
  *
1166
- * @param separator - 단위 ("year", "month", "day", "hour", "minute", "second")
1166
+ * @param unit - 단위 ("year", "month", "day", "hour", "minute", "second")
1167
1167
  * @param from - start Date
1168
1168
  * @param to - 끝 Date
1169
1169
  * @returns 차이 value (to - from)
@@ -1177,13 +1177,13 @@ export const expr = {
1177
1177
  * ```
1178
1178
  */
1179
1179
  dateDiff<T extends DateTime | DateOnly | Time | undefined>(
1180
- separator: DateSeparator,
1180
+ unit: DateUnit,
1181
1181
  from: ExprInput<T>,
1182
1182
  to: ExprInput<T>,
1183
1183
  ): ExprUnit<T extends undefined ? undefined : number> {
1184
1184
  return new ExprUnit("number", {
1185
1185
  type: "dateDiff",
1186
- separator,
1186
+ unit,
1187
1187
  from: toExpr(from),
1188
1188
  to: toExpr(to),
1189
1189
  });
@@ -1192,7 +1192,7 @@ export const expr = {
1192
1192
  /**
1193
1193
  * Date 더하기 (DATEADD)
1194
1194
  *
1195
- * @param separator - 단위 ("year", "month", "day", "hour", "minute", "second")
1195
+ * @param unit - 단위 ("year", "month", "day", "hour", "minute", "second")
1196
1196
  * @param source - 원본 Date
1197
1197
  * @param value - 더할 value (음수 가능)
1198
1198
  * @returns 계산된 Date
@@ -1206,13 +1206,13 @@ export const expr = {
1206
1206
  * ```
1207
1207
  */
1208
1208
  dateAdd<T extends DateTime | DateOnly | Time | undefined>(
1209
- separator: DateSeparator,
1209
+ unit: DateUnit,
1210
1210
  source: ExprUnit<T>,
1211
1211
  value: ExprInput<number>,
1212
1212
  ): ExprUnit<T> {
1213
1213
  return new ExprUnit(source.dataType, {
1214
1214
  type: "dateAdd",
1215
- separator,
1215
+ unit,
1216
1216
  source: toExpr(source),
1217
1217
  value: toExpr(value),
1218
1218
  });
@@ -1262,12 +1262,12 @@ export const expr = {
1262
1262
  * @example
1263
1263
  * ```typescript
1264
1264
  * db.user().select((u) => ({
1265
- * displayName: expr.ifNull(u.nickname, u.name, "Guest"),
1265
+ * displayName: expr.coalesce(u.nickname, u.name, "Guest"),
1266
1266
  * }))
1267
1267
  * // SELECT COALESCE(nickname, name, 'Guest') AS displayName
1268
1268
  * ```
1269
1269
  */
1270
- ifNull,
1270
+ coalesce,
1271
1271
 
1272
1272
  /**
1273
1273
  * 특정 값이면 NULL return (NULLIF)
@@ -2050,21 +2050,21 @@ export const expr = {
2050
2050
  //#region ========== Internal Helpers ==========
2051
2051
 
2052
2052
  // 여러 value 중 첫 번째 non-null return (COALESCE)
2053
- function ifNull<TPrimitive extends ColumnPrimitive>(
2053
+ function coalesce<TPrimitive extends ColumnPrimitive>(
2054
2054
  ...args: [
2055
2055
  ExprInput<TPrimitive | undefined>,
2056
2056
  ...ExprInput<TPrimitive | undefined>[],
2057
2057
  ExprInput<NonNullable<TPrimitive>>,
2058
2058
  ]
2059
2059
  ): ExprUnit<NonNullable<TPrimitive>>;
2060
- function ifNull<TPrimitive extends ColumnPrimitive>(
2060
+ function coalesce<TPrimitive extends ColumnPrimitive>(
2061
2061
  ...args: ExprInput<TPrimitive>[]
2062
2062
  ): ExprUnit<TPrimitive>;
2063
- function ifNull<TPrimitive extends ColumnPrimitive>(
2063
+ function coalesce<TPrimitive extends ColumnPrimitive>(
2064
2064
  ...args: ExprInput<TPrimitive>[]
2065
2065
  ): ExprUnit<TPrimitive> {
2066
2066
  return new ExprUnit(findDataType(args), {
2067
- type: "ifNull",
2067
+ type: "coalesce",
2068
2068
  args: args.map((a) => toExpr(a)),
2069
2069
  });
2070
2070
  }
@@ -47,7 +47,7 @@ import type {
47
47
  ExprDateDiff,
48
48
  ExprDateAdd,
49
49
  ExprFormatDate,
50
- ExprIfNull,
50
+ ExprCoalesce,
51
51
  ExprNullIf,
52
52
  ExprIs,
53
53
  ExprSwitch,
@@ -195,7 +195,7 @@ export abstract class ExprRendererBase {
195
195
 
196
196
  //#region ========== Abstract - Condition ==========
197
197
 
198
- protected abstract ifNull(expr: ExprIfNull): string;
198
+ protected abstract coalesce(expr: ExprCoalesce): string;
199
199
  protected abstract nullIf(expr: ExprNullIf): string;
200
200
  protected abstract is(expr: ExprIs): string;
201
201
  protected abstract switch(expr: ExprSwitch): string;
@@ -15,12 +15,12 @@ import type {
15
15
  DropColumnQueryDef,
16
16
  ModifyColumnQueryDef,
17
17
  RenameColumnQueryDef,
18
- AddPkQueryDef,
19
- DropPkQueryDef,
20
- AddFkQueryDef,
21
- DropFkQueryDef,
22
- AddIdxQueryDef,
23
- DropIdxQueryDef,
18
+ AddPrimaryKeyQueryDef,
19
+ DropPrimaryKeyQueryDef,
20
+ AddForeignKeyQueryDef,
21
+ DropForeignKeyQueryDef,
22
+ AddIndexQueryDef,
23
+ DropIndexQueryDef,
24
24
  CreateViewQueryDef,
25
25
  DropViewQueryDef,
26
26
  CreateProcQueryDef,
@@ -44,6 +44,11 @@ import type { ExprRendererBase } from "./expr-renderer-base";
44
44
  * - If different at all, make it abstract
45
45
  * - Method name identical to def.type (enables dynamic dispatch)
46
46
  */
47
+ /** Properties that are part of a basic (non-LATERAL) JOIN */
48
+ const BASIC_JOIN_PROPS: ReadonlySet<string> = new Set<
49
+ keyof Pick<SelectQueryDefJoin, "type" | "from" | "as" | "where" | "isSingle">
50
+ >(["type", "from", "as", "where", "isSingle"]);
51
+
47
52
  export abstract class QueryBuilderBase {
48
53
  protected abstract expr: ExprRendererBase;
49
54
 
@@ -129,8 +134,7 @@ export abstract class QueryBuilderBase {
129
134
  }
130
135
 
131
136
  // LATERAL needed if join has additional properties beyond basic JOIN properties
132
- const basicJoinProps = ["type", "from", "as", "where", "isSingle"];
133
- return Object.keys(join).some((key) => !basicJoinProps.includes(key));
137
+ return Object.keys(join).some((key) => !BASIC_JOIN_PROPS.has(key));
134
138
  }
135
139
 
136
140
  /** FROM clause source render */
@@ -184,12 +188,12 @@ export abstract class QueryBuilderBase {
184
188
 
185
189
  //#region ========== Abstract - DDL Constraint ==========
186
190
 
187
- protected abstract addPk(def: AddPkQueryDef): QueryBuildResult;
188
- protected abstract dropPk(def: DropPkQueryDef): QueryBuildResult;
189
- protected abstract addFk(def: AddFkQueryDef): QueryBuildResult;
190
- protected abstract dropFk(def: DropFkQueryDef): QueryBuildResult;
191
- protected abstract addIdx(def: AddIdxQueryDef): QueryBuildResult;
192
- protected abstract dropIdx(def: DropIdxQueryDef): QueryBuildResult;
191
+ protected abstract addPrimaryKey(def: AddPrimaryKeyQueryDef): QueryBuildResult;
192
+ protected abstract dropPrimaryKey(def: DropPrimaryKeyQueryDef): QueryBuildResult;
193
+ protected abstract addForeignKey(def: AddForeignKeyQueryDef): QueryBuildResult;
194
+ protected abstract dropForeignKey(def: DropForeignKeyQueryDef): QueryBuildResult;
195
+ protected abstract addIndex(def: AddIndexQueryDef): QueryBuildResult;
196
+ protected abstract dropIndex(def: DropIndexQueryDef): QueryBuildResult;
193
197
 
194
198
  //#endregion
195
199
 
@@ -1,4 +1,4 @@
1
- import { DateOnly, DateTime, Time, Uuid, bytesToHex } from "@simplysm/core-common";
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
- ExprIfNull,
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
- DateSeparator,
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 MssqlExprRenderer extends ExprRendererBase {
110
111
  return `'${value.toString()}'`;
111
112
  }
112
113
  if (value instanceof Uint8Array) {
113
- return `0x${bytesToHex(value)}`;
114
+ return `0x${bytes.toHex(value)}`;
114
115
  }
115
116
  throw new Error(`Unknown value type: ${typeof value}`);
116
117
  }
@@ -398,14 +399,14 @@ export class MssqlExprRenderer extends ExprRendererBase {
398
399
  protected dateDiff(expr: ExprDateDiff): string {
399
400
  const from = this.render(expr.from);
400
401
  const to = this.render(expr.to);
401
- const unit = this.dateSeparatorToUnit(expr.separator);
402
+ const unit = this.dateUnitToSql(expr.unit);
402
403
  return `DATEDIFF(${unit}, ${from}, ${to})`;
403
404
  }
404
405
 
405
406
  protected dateAdd(expr: ExprDateAdd): string {
406
407
  const source = this.render(expr.source);
407
408
  const value = this.render(expr.value);
408
- const unit = this.dateSeparatorToUnit(expr.separator);
409
+ const unit = this.dateUnitToSql(expr.unit);
409
410
  return `DATEADD(${unit}, ${value}, ${source})`;
410
411
  }
411
412
 
@@ -415,8 +416,8 @@ export class MssqlExprRenderer extends ExprRendererBase {
415
416
  return `FORMAT(${this.render(expr.source)}, '${mssqlFormat}')`;
416
417
  }
417
418
 
418
- private dateSeparatorToUnit(sep: DateSeparator): string {
419
- switch (sep) {
419
+ private dateUnitToSql(unit: DateUnit): string {
420
+ switch (unit) {
420
421
  case "year":
421
422
  return "YEAR";
422
423
  case "month":
@@ -441,7 +442,7 @@ export class MssqlExprRenderer extends ExprRendererBase {
441
442
 
442
443
  //#region ========== condition ==========
443
444
 
444
- protected ifNull(expr: ExprIfNull): string {
445
+ protected coalesce(expr: ExprCoalesce): string {
445
446
  if (expr.args.length === 0) return "NULL";
446
447
  if (expr.args.length === 1) return this.render(expr.args[0]);
447
448
  // MSSQL: COALESCE
@@ -520,7 +521,7 @@ export class MssqlExprRenderer extends ExprRendererBase {
520
521
  return "ROW_NUMBER() OVER (ORDER BY (SELECT NULL))";
521
522
  }
522
523
 
523
- protected random(): string {
524
+ protected random(_expr: ExprRandom): string {
524
525
  return "NEWID()";
525
526
  }
526
527