@simplysm/orm-common 14.0.1 → 14.0.5

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 (59) hide show
  1. package/README.md +163 -0
  2. package/dist/exec/queryable.js +18 -18
  3. package/dist/exec/queryable.js.map +1 -1
  4. package/dist/expr/expr.d.ts +102 -102
  5. package/dist/expr/expr.js +105 -105
  6. package/dist/expr/expr.js.map +1 -1
  7. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +1 -1
  8. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
  9. package/dist/query-builder/mssql/mssql-expr-renderer.js +17 -17
  10. package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
  11. package/dist/query-builder/mssql/mssql-query-builder.d.ts +2 -2
  12. package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
  13. package/dist/query-builder/mssql/mssql-query-builder.js +26 -26
  14. package/dist/query-builder/mssql/mssql-query-builder.js.map +1 -1
  15. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +1 -1
  16. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
  17. package/dist/query-builder/mysql/mysql-expr-renderer.js +14 -14
  18. package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
  19. package/dist/query-builder/mysql/mysql-query-builder.d.ts +10 -10
  20. package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
  21. package/dist/query-builder/mysql/mysql-query-builder.js +67 -67
  22. package/dist/query-builder/mysql/mysql-query-builder.js.map +1 -1
  23. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +1 -1
  24. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
  25. package/dist/query-builder/postgresql/postgresql-expr-renderer.js +13 -13
  26. package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
  27. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +8 -8
  28. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
  29. package/dist/query-builder/postgresql/postgresql-query-builder.js +47 -47
  30. package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
  31. package/dist/schema/factory/relation-builder.d.ts +8 -8
  32. package/dist/schema/factory/relation-builder.js +9 -9
  33. package/dist/schema/factory/relation-builder.js.map +1 -1
  34. package/dist/schema/view-builder.js +2 -2
  35. package/dist/schema/view-builder.js.map +1 -1
  36. package/dist/types/column.d.ts +21 -21
  37. package/dist/types/column.js +5 -5
  38. package/dist/utils/result-parser.d.ts +11 -11
  39. package/dist/utils/result-parser.js +48 -48
  40. package/dist/utils/result-parser.js.map +1 -1
  41. package/docs/core.md +157 -0
  42. package/docs/expression.md +220 -0
  43. package/docs/query-builder.md +150 -0
  44. package/docs/queryable.md +261 -0
  45. package/docs/schema-builders.md +294 -0
  46. package/docs/types.md +520 -0
  47. package/package.json +7 -3
  48. package/src/exec/queryable.ts +18 -18
  49. package/src/expr/expr.ts +105 -105
  50. package/src/query-builder/mssql/mssql-expr-renderer.ts +17 -17
  51. package/src/query-builder/mssql/mssql-query-builder.ts +26 -26
  52. package/src/query-builder/mysql/mysql-expr-renderer.ts +14 -14
  53. package/src/query-builder/mysql/mysql-query-builder.ts +67 -67
  54. package/src/query-builder/postgresql/postgresql-expr-renderer.ts +13 -13
  55. package/src/query-builder/postgresql/postgresql-query-builder.ts +47 -47
  56. package/src/schema/factory/relation-builder.ts +9 -9
  57. package/src/schema/view-builder.ts +2 -2
  58. package/src/types/column.ts +23 -23
  59. package/src/utils/result-parser.ts +49 -49
@@ -38,25 +38,25 @@ import { PostgresqlExprRenderer } from "./postgresql-expr-renderer";
38
38
  /**
39
39
  * PostgreSQL QueryBuilder
40
40
  *
41
- * PostgreSQL specifics:
42
- * - OUTPUT: uses RETURNING clause (native support)
43
- * - TRUNCATE: RESTART IDENTITY option required
44
- * - UPSERT: CTE approach (INSERT ... ON CONFLICT only supports single unique constraint)
45
- * - AUTO_INCREMENT: GENERATED BY DEFAULT AS IDENTITY (allows explicit value assignment)
46
- * - Separate index generation needed when adding FK (unlike MySQL)
41
+ * PostgreSQL 고유 사항:
42
+ * - OUTPUT: RETURNING 사용 (네이티브 지원)
43
+ * - TRUNCATE: RESTART IDENTITY 옵션 필요
44
+ * - UPSERT: CTE 방식 (INSERT ... ON CONFLICT 단일 유니크 제약조건만 지원)
45
+ * - AUTO_INCREMENT: GENERATED BY DEFAULT AS IDENTITY (명시적 할당 가능)
46
+ * - FK 추가 별도 인덱스 생성 필요 (MySQL과 다름)
47
47
  */
48
48
  export class PostgresqlQueryBuilder extends QueryBuilderBase {
49
49
  protected expr = new PostgresqlExprRenderer((def) => this.select(def).sql);
50
50
 
51
51
  //#region ========== Utilities ==========
52
52
 
53
- /** Render table name (PostgreSQL: database is handled by connection, uses schema.table only) */
53
+ /** 테이블명 렌더링 (PostgreSQL: database 연결에서 처리, schema.table 사용) */
54
54
  protected tableName(obj: QueryDefObjectName): string {
55
55
  const schema = obj.schema ?? "public";
56
56
  return `${this.expr.wrap(schema)}.${this.expr.wrap(obj.name)}`;
57
57
  }
58
58
 
59
- /** Render LIMIT...OFFSET clause */
59
+ /** LIMIT...OFFSET 렌더링 */
60
60
  protected renderLimit(limit: [number, number] | undefined, top: number | undefined): string {
61
61
  if (limit != null) {
62
62
  const [offset, count] = limit;
@@ -71,15 +71,15 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
71
71
  protected renderJoin(join: SelectQueryDefJoin): string {
72
72
  const alias = this.expr.wrap(join.as);
73
73
 
74
- // Detect if LATERAL JOIN is needed
74
+ // LATERAL JOIN 필요한지 감지
75
75
  if (this.needsLateral(join)) {
76
- // If from is an array (UNION ALL), use renderFrom(join.from),
77
- // otherwise (orderBy, top, select, etc.) use renderFrom(join) to generate subquery
76
+ // from 배열(UNION ALL)이면 renderFrom(join.from) 사용,
77
+ // (orderBy, top, select )이면 renderFrom(join)으로 서브쿼리 생성
78
78
  const from = Array.isArray(join.from) ? this.renderFrom(join.from) : this.renderFrom(join);
79
79
  return ` LEFT OUTER JOIN LATERAL ${from} AS ${alias} ON TRUE`;
80
80
  }
81
81
 
82
- // Normal JOIN
82
+ // 일반 JOIN
83
83
  const from = this.renderFrom(join.from);
84
84
  const where =
85
85
  join.where != null && join.where.length > 0
@@ -140,7 +140,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
140
140
  // LIMIT
141
141
  sql += this.renderLimit(def.limit, def.top);
142
142
 
143
- // LOCK (FOR UPDATE at end)
143
+ // LOCK (끝에 FOR UPDATE 추가)
144
144
  if (def.lock) {
145
145
  sql += " FOR UPDATE";
146
146
  }
@@ -169,14 +169,14 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
169
169
 
170
170
  let sql = `INSERT INTO ${table} (${colList})`;
171
171
 
172
- // GENERATED BY DEFAULT AS IDENTITY, so no additional clause needed for explicit value insertion
173
- // overrideIdentity parameter is kept for MSSQL (SET IDENTITY_INSERT) compatibility, but
174
- // PostgreSQL's GENERATED BY DEFAULT automatically allows explicit values
175
- // (note: OVERRIDING SYSTEM VALUE would be needed if GENERATED ALWAYS was used)
172
+ // GENERATED BY DEFAULT AS IDENTITY이므로 명시적 삽입에 추가 구문 불필요
173
+ // overrideIdentity 파라미터는 MSSQL (SET IDENTITY_INSERT) 호환성을 위해 유지하지만
174
+ // PostgreSQL GENERATED BY DEFAULT 자동으로 명시적 값을 허용
175
+ // (참고: GENERATED ALWAYS를 사용했다면 OVERRIDING SYSTEM VALUE 필요)
176
176
 
177
177
  sql += ` VALUES ${valuesList.join(", ")}`;
178
178
 
179
- // RETURNING (PostgreSQL native support)
179
+ // RETURNING (PostgreSQL 네이티브 지원)
180
180
  if (def.output != null) {
181
181
  const outputCols = def.output.columns.map((c) => this.expr.wrap(c)).join(", ");
182
182
  sql += ` RETURNING ${outputCols}`;
@@ -192,7 +192,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
192
192
  const colList = columns.map((c) => this.expr.wrap(c)).join(", ");
193
193
  const values = columns.map((c) => this.expr.escapeValue(def.record[c])).join(", ");
194
194
 
195
- // Render existsSelectQuery as SELECT 1 AS _
195
+ // existsSelectQuery SELECT 1 AS _로 렌더링
196
196
  const existsQuerySql = this.select({
197
197
  ...def.existsSelectQuery,
198
198
  select: { _: { type: "value", value: 1 } },
@@ -200,7 +200,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
200
200
 
201
201
  let sql = `INSERT INTO ${table} (${colList}) SELECT ${values} WHERE NOT EXISTS (${existsQuerySql})`;
202
202
 
203
- // RETURNING
203
+ // RETURNING
204
204
  if (def.output != null) {
205
205
  const outputCols = def.output.columns.map((c) => this.expr.wrap(c)).join(", ");
206
206
  sql += ` RETURNING ${outputCols}`;
@@ -213,7 +213,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
213
213
  const table = this.tableName(def.table);
214
214
  const selectSql = this.select(def.recordsSelectQuery).sql;
215
215
 
216
- // Extract columns from INSERT INTO SELECT
216
+ // INSERT INTO SELECT에서 column 추출
217
217
  const selectDef = def.recordsSelectQuery;
218
218
  const colList =
219
219
  selectDef.select != null
@@ -224,7 +224,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
224
224
 
225
225
  let sql = `INSERT INTO ${table} (${colList}) ${selectSql}`;
226
226
 
227
- // RETURNING
227
+ // RETURNING
228
228
  if (def.output != null) {
229
229
  const outputCols = def.output.columns.map((c) => this.expr.wrap(c)).join(", ");
230
230
  sql += ` RETURNING ${outputCols}`;
@@ -248,7 +248,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
248
248
 
249
249
  let sql = `UPDATE ${table} AS ${alias} SET ${setParts.join(", ")}`;
250
250
 
251
- // PostgreSQL: JOINs are handled via FROM clause
251
+ // PostgreSQL: JOIN은 FROM 절로 처리
252
252
  if (def.joins != null && def.joins.length > 0) {
253
253
  const joinTables = def.joins.map((j) => {
254
254
  const from = this.renderFrom(j.from);
@@ -256,7 +256,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
256
256
  });
257
257
  sql += ` FROM ${joinTables.join(", ")}`;
258
258
 
259
- // Add JOIN ON conditions to WHERE
259
+ // JOIN ON 조건을 WHERE에 추가
260
260
  const joinConditions = def.joins
261
261
  .filter((j) => j.where != null && j.where.length > 0)
262
262
  .map((j) => this.expr.renderWhere(j.where!));
@@ -273,7 +273,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
273
273
  sql += this.renderWhere(def.where);
274
274
  }
275
275
 
276
- // RETURNING
276
+ // RETURNING
277
277
  if (def.output != null) {
278
278
  const outputCols = def.output.columns.map((c) => `${alias}.${this.expr.wrap(c)}`).join(", ");
279
279
  sql += ` RETURNING ${outputCols}`;
@@ -292,7 +292,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
292
292
 
293
293
  let sql = `DELETE FROM ${table} AS ${alias}`;
294
294
 
295
- // PostgreSQL: JOINs are handled via USING clause
295
+ // PostgreSQL: JOIN은 USING 절로 처리
296
296
  if (def.joins != null && def.joins.length > 0) {
297
297
  const joinTables = def.joins.map((j) => {
298
298
  const from = this.renderFrom(j.from);
@@ -300,7 +300,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
300
300
  });
301
301
  sql += ` USING ${joinTables.join(", ")}`;
302
302
 
303
- // Add JOIN ON conditions to WHERE
303
+ // JOIN ON 조건을 WHERE에 추가
304
304
  const joinConditions = def.joins
305
305
  .filter((j) => j.where != null && j.where.length > 0)
306
306
  .map((j) => this.expr.renderWhere(j.where!));
@@ -317,7 +317,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
317
317
  sql += this.renderWhere(def.where);
318
318
  }
319
319
 
320
- // RETURNING (PostgreSQL: also supported for DELETE)
320
+ // RETURNING (PostgreSQL: DELETE에서도 지원)
321
321
  if (def.output != null) {
322
322
  const outputCols = def.output.columns.map((c) => this.expr.wrap(c)).join(", ");
323
323
  sql += ` RETURNING ${outputCols}`;
@@ -331,31 +331,31 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
331
331
  //#region ========== DML - UPSERT ==========
332
332
 
333
333
  protected upsert(def: UpsertQueryDef): QueryBuildResult {
334
- // PostgreSQL: CTE approach (uses CTE for generality since ON CONFLICT only supports single unique constraint)
334
+ // PostgreSQL: CTE 방식 (ON CONFLICT는 단일 유니크 제약조건만 지원하므로 범용성을 위해 CTE 사용)
335
335
  const table = this.tableName(def.table);
336
336
  const alias = this.expr.wrap(def.existsSelectQuery.as);
337
337
 
338
- // UPDATE SET part
338
+ // UPDATE SET 부분
339
339
  const updateSetParts = Object.entries(def.updateRecord).map(
340
340
  ([col, e]) => `${this.expr.wrap(col)} = ${this.expr.render(e)}`,
341
341
  );
342
342
 
343
- // INSERT part
343
+ // INSERT 부분
344
344
  const insertColumns = Object.keys(def.insertRecord);
345
345
  const insertColList = insertColumns.map((c) => this.expr.wrap(c)).join(", ");
346
346
  const insertValues = insertColumns.map((c) => this.expr.render(def.insertRecord[c])).join(", ");
347
347
 
348
- // WHERE condition
348
+ // WHERE 조건
349
349
  const whereCondition =
350
350
  def.existsSelectQuery.where != null && def.existsSelectQuery.where.length > 0
351
351
  ? this.expr.renderWhere(def.existsSelectQuery.where)
352
352
  : "TRUE";
353
353
 
354
- // OUTPUT column
354
+ // OUTPUT column 정의
355
355
  const outputCols =
356
356
  def.output != null ? def.output.columns.map((c) => this.expr.wrap(c)).join(", ") : "*";
357
357
 
358
- // CTE-based UPSERT
358
+ // CTE 기반 UPSERT
359
359
  let sql = `WITH matched AS (\n`;
360
360
  sql += ` SELECT ${alias}.* FROM ${table} AS ${alias} WHERE ${whereCondition}\n`;
361
361
  sql += `),\n`;
@@ -385,7 +385,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
385
385
  const colDefs = def.columns.map((col) => {
386
386
  let colSql = `${this.expr.wrap(col.name)} ${this.expr.renderDataType(col.dataType)}`;
387
387
 
388
- // nullable: true → NULL, else → NOT NULL
388
+ // nullable: true → NULL, 아니면 → NOT NULL
389
389
  if (col.nullable === true) {
390
390
  colSql += " NULL";
391
391
  } else {
@@ -403,7 +403,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
403
403
  return colSql;
404
404
  });
405
405
 
406
- // Primary Key with CONSTRAINT name
406
+ // CONSTRAINT 이름이 포함된 Primary Key
407
407
  if (def.primaryKey != null && def.primaryKey.length > 0) {
408
408
  const pkCols = def.primaryKey.map((c) => this.expr.wrap(c)).join(", ");
409
409
  const pkName = this.expr.wrap(`PK_${def.table.name}`);
@@ -424,7 +424,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
424
424
  }
425
425
 
426
426
  protected truncate(def: TruncateQueryDef): QueryBuildResult {
427
- // PostgreSQL: reset sequence with RESTART IDENTITY
427
+ // PostgreSQL: RESTART IDENTITY로 시퀀스 초기화
428
428
  return { sql: `TRUNCATE TABLE ${this.tableName(def.table)} RESTART IDENTITY` };
429
429
  }
430
430
 
@@ -466,22 +466,22 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
466
466
  const table = this.tableName(def.table);
467
467
  const col = def.column;
468
468
 
469
- // PostgreSQL: ALTER COLUMN requires multiple ALTER statements
469
+ // PostgreSQL: ALTER COLUMN 여러 ALTER 문이 필요
470
470
  const parts: string[] = [];
471
471
 
472
- // Change TYPE
472
+ // TYPE 변경
473
473
  parts.push(
474
474
  `ALTER COLUMN ${this.expr.wrap(col.name)} TYPE ${this.expr.renderDataType(col.dataType)}`,
475
475
  );
476
476
 
477
- // Change NULL constraint
477
+ // NULL 제약조건 변경
478
478
  if (col.nullable === false) {
479
479
  parts.push(`ALTER COLUMN ${this.expr.wrap(col.name)} SET NOT NULL`);
480
480
  } else {
481
481
  parts.push(`ALTER COLUMN ${this.expr.wrap(col.name)} DROP NOT NULL`);
482
482
  }
483
483
 
484
- // Change DEFAULT
484
+ // DEFAULT 변경
485
485
  if (col.default !== undefined) {
486
486
  parts.push(
487
487
  `ALTER COLUMN ${this.expr.wrap(col.name)} SET DEFAULT ${this.expr.escapeValue(col.default)}`,
@@ -526,7 +526,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
526
526
 
527
527
  let sql = `ALTER TABLE ${table} ADD CONSTRAINT ${this.expr.wrap(fk.name)} FOREIGN KEY (${fkCols}) REFERENCES ${targetTable} (${targetCols})`;
528
528
 
529
- // PostgreSQL: separate index generation needed for FK
529
+ // PostgreSQL: FK에 대한 별도 인덱스 생성 필요
530
530
  const idxName = `IDX_${def.table.name}_${fk.name.replace(/^FK_/, "")}`;
531
531
  sql += `;\nCREATE INDEX ${this.expr.wrap(idxName)} ON ${table} (${fkCols});`;
532
532
 
@@ -548,7 +548,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
548
548
  }
549
549
 
550
550
  protected dropIndex(def: DropIndexQueryDef): QueryBuildResult {
551
- // PostgreSQL: indexes are unique at schema level so table name is not needed, but schema must be specified
551
+ // PostgreSQL: 인덱스는 스키마 수준에서 고유하므로 테이블명은 불필요하지만 스키마 지정 필요
552
552
  const schema = def.table.schema ?? "public";
553
553
  return { sql: `DROP INDEX ${this.expr.wrap(schema)}.${this.expr.wrap(def.index)}` };
554
554
  }
@@ -570,7 +570,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
570
570
  protected createProc(def: CreateProcQueryDef): QueryBuildResult {
571
571
  const proc = this.tableName(def.procedure);
572
572
 
573
- // Process params
573
+ // 파라미터 처리
574
574
  const paramList =
575
575
  def.params
576
576
  ?.map((p) => {
@@ -582,7 +582,7 @@ export class PostgresqlQueryBuilder extends QueryBuilderBase {
582
582
  })
583
583
  .join(", ") ?? "";
584
584
 
585
- // Process returns
585
+ // 반환 타입 처리
586
586
  let returnClause = "VOID";
587
587
  if (def.returns && def.returns.length > 0) {
588
588
  const returnFields = def.returns
@@ -675,10 +675,10 @@ END $$`,
675
675
  protected switchFk(def: SwitchFkQueryDef): QueryBuildResult {
676
676
  const table = this.tableName(def.table);
677
677
  if (def.enabled) {
678
- // PostgreSQL: enable all FK triggers on the table
678
+ // PostgreSQL: 테이블의 모든 FK 트리거 활성화
679
679
  return { sql: `ALTER TABLE ${table} ENABLE TRIGGER ALL` };
680
680
  }
681
- // PostgreSQL: disable all FK triggers on the table
681
+ // PostgreSQL: 테이블의 모든 FK 트리거 비활성화
682
682
  return { sql: `ALTER TABLE ${table} DISABLE TRIGGER ALL` };
683
683
  }
684
684
 
@@ -139,7 +139,7 @@ export class ForeignKeyTargetBuilder<
139
139
  }
140
140
 
141
141
  // ============================================
142
- // RelationKeyBuilder (same as FK but does not register FK in DB)
142
+ // RelationKeyBuilder (FK 동일하지만 DB에 FK 등록하지 않음)
143
143
  // ============================================
144
144
 
145
145
  /**
@@ -153,15 +153,15 @@ export class ForeignKeyTargetBuilder<
153
153
  *
154
154
  * @example
155
155
  * ```typescript
156
- * // Relation definition from View to Table
156
+ * // View에서 Table로의 관계 정의
157
157
  * const UserSummary = View("UserSummary")
158
158
  * .query((db: MyDb) => db.user().select(...))
159
159
  * .relations((r) => ({
160
- * // View → Table (no FK creation)
160
+ * // View → Table (FK 미생성)
161
161
  * company: r.relationKey(["companyId"], () => Company),
162
162
  * }));
163
163
  *
164
- * // Relation definition from Table without FK
164
+ * // FK 없는 Table 관계 정의
165
165
  * const Report = Table("Report")
166
166
  * .columns((c) => ({ userId: c.bigint() }))
167
167
  * .relations((r) => ({
@@ -216,7 +216,7 @@ export class RelationKeyBuilder<
216
216
  * const Company = Table("Company")
217
217
  * .columns((c) => ({ id: c.bigint() }))
218
218
  * .relations((r) => ({
219
- * // Reverse-reference (no FK creation)
219
+ * // 역참조 (FK 미생성)
220
220
  * employees: r.relationKeyTarget(() => UserSummary, "company"),
221
221
  * }));
222
222
  * ```
@@ -321,21 +321,21 @@ type RelationRkFactory<
321
321
  *
322
322
  * @example
323
323
  * ```typescript
324
- * // Table - both FK and RelationKey available
324
+ * // Table - FK RelationKey 모두 사용 가능
325
325
  * const Post = Table("Post")
326
326
  * .columns((c) => ({
327
327
  * id: c.bigint(),
328
328
  * authorId: c.bigint(),
329
329
  * }))
330
330
  * .relations((r) => ({
331
- * author: r.foreignKey(["authorId"], () => User), // FK Generate
331
+ * author: r.foreignKey(["authorId"], () => User), // FK 생성
332
332
  * }));
333
333
  *
334
- * // View - only RelationKey available
334
+ * // View - RelationKey 사용 가능
335
335
  * const UserSummary = View("UserSummary")
336
336
  * .query(...)
337
337
  * .relations((r) => ({
338
- * posts: r.relationKeyTarget(() => Post, "author"), // No FK creation
338
+ * posts: r.relationKeyTarget(() => Post, "author"), // FK 미생성
339
339
  * }));
340
340
  * ```
341
341
  */
@@ -169,8 +169,8 @@ export class ViewBuilder<
169
169
  relations<T extends RelationBuilderRecord>(
170
170
  fn: (r: ReturnType<typeof createRelationFactory<this, keyof TData & string>>) => T,
171
171
  ): ViewBuilder<TDbContext, TData & InferDeepRelations<T>, TRelations> {
172
- // Casting is unavoidable due to TypeScript generic type inference limitations
173
- // Resolves type mismatch between TRelations type parameter and newly created relation type T
172
+ // TypeScript 제네릭 타입 추론 한계로 인해 캐스팅이 불가피
173
+ // TRelations 타입 파라미터와 새로 생성된 관계 타입 T 간의 타입 불일치 해결
174
174
  return new ViewBuilder({
175
175
  ...this.meta,
176
176
  relations: fn(createRelationFactory<this, keyof TData & string>(() => this)),
@@ -1,13 +1,13 @@
1
1
  import { DateOnly, DateTime, Time, Uuid, type Bytes } from "@simplysm/core-common";
2
2
 
3
3
  // ============================================
4
- // DataType (SQL type definition)
4
+ // DataType (SQL 타입 정의)
5
5
  // ============================================
6
6
 
7
7
  /**
8
- * SQL data type definition
8
+ * SQL 데이터 타입 정의
9
9
  *
10
- * DBMS Mapping:
10
+ * DBMS 매핑:
11
11
  * - `int`: INT (4 bytes)
12
12
  * - `bigint`: BIGINT (8 bytes)
13
13
  * - `float`: FLOAT/REAL (4 bytes)
@@ -47,13 +47,13 @@ export type DataType =
47
47
  | { type: "uuid" };
48
48
 
49
49
  // ============================================
50
- // ColumnPrimitive (TypeScript Type)
50
+ // ColumnPrimitive (TypeScript 타입)
51
51
  // ============================================
52
52
 
53
53
  /**
54
- * Column primitive type mapping
54
+ * Column 원시 타입 매핑
55
55
  *
56
- * TypeScript type name (string) → Actual TypeScript type mapping
56
+ * TypeScript 타입 이름 (문자열) → 실제 TypeScript 타입 매핑
57
57
  *
58
58
  * @example
59
59
  * ```typescript
@@ -73,7 +73,7 @@ export type ColumnPrimitiveMap = {
73
73
  };
74
74
 
75
75
  /**
76
- * Column primitive type name (string)
76
+ * Column 원시 타입 이름 (문자열)
77
77
  *
78
78
  * @example
79
79
  * ```typescript
@@ -84,9 +84,9 @@ export type ColumnPrimitiveMap = {
84
84
  export type ColumnPrimitiveStr = keyof ColumnPrimitiveMap;
85
85
 
86
86
  /**
87
- * All primitive types that can be stored in columns
87
+ * Column에 저장 가능한 모든 원시 타입
88
88
  *
89
- * undefined represents NULL
89
+ * undefined NULL을 나타냄
90
90
  */
91
91
  export type ColumnPrimitive = ColumnPrimitiveMap[ColumnPrimitiveStr] | undefined;
92
92
 
@@ -95,7 +95,7 @@ export type ColumnPrimitive = ColumnPrimitiveMap[ColumnPrimitiveStr] | undefined
95
95
  // ============================================
96
96
 
97
97
  /**
98
- * SQL DataType → TypeScript type name mapping
98
+ * SQL DataType → TypeScript 타입 이름 매핑
99
99
  *
100
100
  * @example
101
101
  * ```typescript
@@ -121,7 +121,7 @@ export const dataTypeStrToColumnPrimitiveStr = {
121
121
  };
122
122
 
123
123
  /**
124
- * TypeScript Type inference from DataType
124
+ * DataType으로부터 TypeScript 타입 추론
125
125
  *
126
126
  * @template T - DataType
127
127
  *
@@ -135,11 +135,11 @@ export type InferColumnPrimitiveFromDataType<TDataType extends DataType> =
135
135
  ColumnPrimitiveMap[(typeof dataTypeStrToColumnPrimitiveStr)[TDataType["type"]]];
136
136
 
137
137
  /**
138
- * Infer ColumnPrimitiveStr from runtime value
138
+ * 런타임 값에서 ColumnPrimitiveStr 추론
139
139
  *
140
- * @param value - Column value
141
- * @returns ColumnPrimitiveStr type name
142
- * @throws Error if value type is unknown
140
+ * @param value - Column
141
+ * @returns ColumnPrimitiveStr 타입 이름
142
+ * @throws 타입이 없을 때 Error
143
143
  *
144
144
  * @example
145
145
  * ```typescript
@@ -165,16 +165,16 @@ export function inferColumnPrimitiveStr(value: ColumnPrimitive): ColumnPrimitive
165
165
  // ============================================
166
166
 
167
167
  /**
168
- * Column metadata
168
+ * Column 메타데이터
169
169
  *
170
- * Generated by ColumnBuilder and passed to TableBuilder
170
+ * ColumnBuilder에서 생성되어 TableBuilder에 전달됨
171
171
  *
172
- * @property type - TypeScript type name (ColumnPrimitiveStr)
173
- * @property dataType - SQL data type
174
- * @property autoIncrement - Whether to auto-increment
175
- * @property nullable - Whether to allow NULL
176
- * @property default - Default value
177
- * @property description - Column description (DDL comment)
172
+ * @property type - TypeScript 타입 이름 (ColumnPrimitiveStr)
173
+ * @property dataType - SQL 데이터 타입
174
+ * @property autoIncrement - 자동 증가 여부
175
+ * @property nullable - NULL 허용 여부
176
+ * @property default - 기본값
177
+ * @property description - Column 설명 (DDL 코멘트)
178
178
  *
179
179
  * @see {@link ColumnBuilder} Column builder
180
180
  */