@simplysm/orm-common 13.0.100 → 14.0.4

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 (246) hide show
  1. package/README.md +90 -147
  2. package/dist/create-db-context.d.ts +10 -10
  3. package/dist/create-db-context.js +312 -276
  4. package/dist/create-db-context.js.map +1 -6
  5. package/dist/ddl/column-ddl.d.ts +4 -4
  6. package/dist/ddl/column-ddl.js +41 -35
  7. package/dist/ddl/column-ddl.js.map +1 -6
  8. package/dist/ddl/initialize.d.ts +17 -17
  9. package/dist/ddl/initialize.js +200 -142
  10. package/dist/ddl/initialize.js.map +1 -6
  11. package/dist/ddl/relation-ddl.d.ts +6 -6
  12. package/dist/ddl/relation-ddl.js +55 -48
  13. package/dist/ddl/relation-ddl.js.map +1 -6
  14. package/dist/ddl/schema-ddl.d.ts +4 -4
  15. package/dist/ddl/schema-ddl.js +21 -15
  16. package/dist/ddl/schema-ddl.js.map +1 -6
  17. package/dist/ddl/table-ddl.d.ts +20 -20
  18. package/dist/ddl/table-ddl.js +139 -93
  19. package/dist/ddl/table-ddl.js.map +1 -6
  20. package/dist/define-db-context.js +10 -13
  21. package/dist/define-db-context.js.map +1 -6
  22. package/dist/errors/db-transaction-error.d.ts +15 -15
  23. package/dist/errors/db-transaction-error.d.ts.map +1 -1
  24. package/dist/errors/db-transaction-error.js +53 -19
  25. package/dist/errors/db-transaction-error.js.map +1 -6
  26. package/dist/exec/executable.d.ts +23 -23
  27. package/dist/exec/executable.js +94 -40
  28. package/dist/exec/executable.js.map +1 -6
  29. package/dist/exec/queryable.d.ts +97 -97
  30. package/dist/exec/queryable.js +1310 -1204
  31. package/dist/exec/queryable.js.map +1 -6
  32. package/dist/exec/search-parser.d.ts +31 -31
  33. package/dist/exec/search-parser.d.ts.map +1 -1
  34. package/dist/exec/search-parser.js +158 -59
  35. package/dist/exec/search-parser.js.map +1 -6
  36. package/dist/expr/expr-unit.d.ts +4 -4
  37. package/dist/expr/expr-unit.js +24 -18
  38. package/dist/expr/expr-unit.js.map +1 -6
  39. package/dist/expr/expr.d.ts +108 -108
  40. package/dist/expr/expr.js +1872 -1844
  41. package/dist/expr/expr.js.map +1 -6
  42. package/dist/index.js +23 -1
  43. package/dist/index.js.map +1 -6
  44. package/dist/models/system-migration.js +7 -7
  45. package/dist/models/system-migration.js.map +1 -6
  46. package/dist/query-builder/base/expr-renderer-base.d.ts +10 -10
  47. package/dist/query-builder/base/expr-renderer-base.js +27 -21
  48. package/dist/query-builder/base/expr-renderer-base.js.map +1 -6
  49. package/dist/query-builder/base/query-builder-base.d.ts +21 -21
  50. package/dist/query-builder/base/query-builder-base.d.ts.map +1 -1
  51. package/dist/query-builder/base/query-builder-base.js +90 -80
  52. package/dist/query-builder/base/query-builder-base.js.map +1 -6
  53. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +5 -5
  54. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
  55. package/dist/query-builder/mssql/mssql-expr-renderer.js +447 -420
  56. package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -6
  57. package/dist/query-builder/mssql/mssql-query-builder.d.ts +2 -2
  58. package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
  59. package/dist/query-builder/mssql/mssql-query-builder.js +483 -443
  60. package/dist/query-builder/mssql/mssql-query-builder.js.map +1 -6
  61. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +5 -5
  62. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
  63. package/dist/query-builder/mysql/mysql-expr-renderer.js +451 -419
  64. package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -6
  65. package/dist/query-builder/mysql/mysql-query-builder.d.ts +10 -10
  66. package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
  67. package/dist/query-builder/mysql/mysql-query-builder.js +570 -479
  68. package/dist/query-builder/mysql/mysql-query-builder.js.map +1 -6
  69. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +5 -5
  70. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
  71. package/dist/query-builder/postgresql/postgresql-expr-renderer.js +449 -422
  72. package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -6
  73. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +8 -8
  74. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
  75. package/dist/query-builder/postgresql/postgresql-query-builder.js +511 -460
  76. package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -6
  77. package/dist/query-builder/query-builder.d.ts +1 -1
  78. package/dist/query-builder/query-builder.js +13 -13
  79. package/dist/query-builder/query-builder.js.map +1 -6
  80. package/dist/schema/factory/column-builder.d.ts +84 -84
  81. package/dist/schema/factory/column-builder.js +248 -185
  82. package/dist/schema/factory/column-builder.js.map +1 -6
  83. package/dist/schema/factory/index-builder.d.ts +38 -38
  84. package/dist/schema/factory/index-builder.js +144 -85
  85. package/dist/schema/factory/index-builder.js.map +1 -6
  86. package/dist/schema/factory/relation-builder.d.ts +99 -99
  87. package/dist/schema/factory/relation-builder.d.ts.map +1 -1
  88. package/dist/schema/factory/relation-builder.js +274 -136
  89. package/dist/schema/factory/relation-builder.js.map +1 -6
  90. package/dist/schema/procedure-builder.d.ts +51 -51
  91. package/dist/schema/procedure-builder.d.ts.map +1 -1
  92. package/dist/schema/procedure-builder.js +205 -131
  93. package/dist/schema/procedure-builder.js.map +1 -6
  94. package/dist/schema/table-builder.d.ts +55 -55
  95. package/dist/schema/table-builder.d.ts.map +1 -1
  96. package/dist/schema/table-builder.js +274 -205
  97. package/dist/schema/table-builder.js.map +1 -6
  98. package/dist/schema/view-builder.d.ts +44 -44
  99. package/dist/schema/view-builder.d.ts.map +1 -1
  100. package/dist/schema/view-builder.js +189 -116
  101. package/dist/schema/view-builder.js.map +1 -6
  102. package/dist/types/column.d.ts +21 -21
  103. package/dist/types/column.js +60 -30
  104. package/dist/types/column.js.map +1 -6
  105. package/dist/types/db-context-def.d.ts +9 -9
  106. package/dist/types/db-context-def.js +2 -1
  107. package/dist/types/db-context-def.js.map +1 -6
  108. package/dist/types/db.d.ts +47 -47
  109. package/dist/types/db.js +15 -5
  110. package/dist/types/db.js.map +1 -6
  111. package/dist/types/expr.d.ts +81 -81
  112. package/dist/types/expr.d.ts.map +1 -1
  113. package/dist/types/expr.js +3 -1
  114. package/dist/types/expr.js.map +1 -6
  115. package/dist/types/query-def.d.ts +46 -46
  116. package/dist/types/query-def.d.ts.map +1 -1
  117. package/dist/types/query-def.js +31 -24
  118. package/dist/types/query-def.js.map +1 -6
  119. package/dist/utils/result-parser.d.ts +11 -11
  120. package/dist/utils/result-parser.js +362 -221
  121. package/dist/utils/result-parser.js.map +1 -6
  122. package/docs/core.md +117 -145
  123. package/docs/expression.md +186 -203
  124. package/docs/query-builder.md +75 -42
  125. package/docs/queryable.md +189 -151
  126. package/docs/schema-builders.md +172 -283
  127. package/docs/types.md +229 -173
  128. package/package.json +7 -5
  129. package/src/create-db-context.ts +31 -31
  130. package/src/ddl/column-ddl.ts +4 -4
  131. package/src/ddl/initialize.ts +38 -38
  132. package/src/ddl/relation-ddl.ts +6 -6
  133. package/src/ddl/schema-ddl.ts +4 -4
  134. package/src/ddl/table-ddl.ts +24 -24
  135. package/src/errors/db-transaction-error.ts +13 -13
  136. package/src/exec/executable.ts +25 -25
  137. package/src/exec/queryable.ts +152 -152
  138. package/src/exec/search-parser.ts +50 -50
  139. package/src/expr/expr-unit.ts +4 -4
  140. package/src/expr/expr.ts +118 -118
  141. package/src/index.ts +8 -8
  142. package/src/models/system-migration.ts +1 -1
  143. package/src/query-builder/base/expr-renderer-base.ts +21 -21
  144. package/src/query-builder/base/query-builder-base.ts +33 -33
  145. package/src/query-builder/mssql/mssql-expr-renderer.ts +28 -28
  146. package/src/query-builder/mssql/mssql-query-builder.ts +37 -37
  147. package/src/query-builder/mysql/mysql-expr-renderer.ts +29 -29
  148. package/src/query-builder/mysql/mysql-query-builder.ts +70 -70
  149. package/src/query-builder/postgresql/postgresql-expr-renderer.ts +22 -22
  150. package/src/query-builder/postgresql/postgresql-query-builder.ts +54 -54
  151. package/src/query-builder/query-builder.ts +1 -1
  152. package/src/schema/factory/column-builder.ts +86 -86
  153. package/src/schema/factory/index-builder.ts +38 -38
  154. package/src/schema/factory/relation-builder.ts +102 -102
  155. package/src/schema/procedure-builder.ts +52 -52
  156. package/src/schema/table-builder.ts +56 -56
  157. package/src/schema/view-builder.ts +47 -47
  158. package/src/types/column.ts +24 -24
  159. package/src/types/db-context-def.ts +15 -15
  160. package/src/types/db.ts +50 -50
  161. package/src/types/expr.ts +103 -103
  162. package/src/types/query-def.ts +50 -50
  163. package/src/utils/result-parser.ts +88 -88
  164. package/docs/utilities.md +0 -27
  165. package/tests/db-context/create-db-context.spec.ts +0 -193
  166. package/tests/db-context/define-db-context.spec.ts +0 -17
  167. package/tests/ddl/basic.expected.ts +0 -341
  168. package/tests/ddl/basic.spec.ts +0 -557
  169. package/tests/ddl/column-builder.expected.ts +0 -310
  170. package/tests/ddl/column-builder.spec.ts +0 -525
  171. package/tests/ddl/index-builder.expected.ts +0 -38
  172. package/tests/ddl/index-builder.spec.ts +0 -148
  173. package/tests/ddl/procedure-builder.expected.ts +0 -52
  174. package/tests/ddl/procedure-builder.spec.ts +0 -128
  175. package/tests/ddl/relation-builder.expected.ts +0 -36
  176. package/tests/ddl/relation-builder.spec.ts +0 -171
  177. package/tests/ddl/table-builder.expected.ts +0 -113
  178. package/tests/ddl/table-builder.spec.ts +0 -399
  179. package/tests/ddl/view-builder.expected.ts +0 -38
  180. package/tests/ddl/view-builder.spec.ts +0 -116
  181. package/tests/dml/delete.expected.ts +0 -96
  182. package/tests/dml/delete.spec.ts +0 -127
  183. package/tests/dml/insert.expected.ts +0 -192
  184. package/tests/dml/insert.spec.ts +0 -210
  185. package/tests/dml/update.expected.ts +0 -176
  186. package/tests/dml/update.spec.ts +0 -222
  187. package/tests/dml/upsert.expected.ts +0 -215
  188. package/tests/dml/upsert.spec.ts +0 -190
  189. package/tests/errors/queryable-errors.spec.ts +0 -126
  190. package/tests/escape.spec.ts +0 -59
  191. package/tests/examples/pivot.expected.ts +0 -211
  192. package/tests/examples/pivot.spec.ts +0 -200
  193. package/tests/examples/sampling.expected.ts +0 -69
  194. package/tests/examples/sampling.spec.ts +0 -42
  195. package/tests/examples/unpivot.expected.ts +0 -120
  196. package/tests/examples/unpivot.spec.ts +0 -161
  197. package/tests/exec/search-parser.spec.ts +0 -267
  198. package/tests/executable/basic.expected.ts +0 -18
  199. package/tests/executable/basic.spec.ts +0 -54
  200. package/tests/expr/comparison.expected.ts +0 -282
  201. package/tests/expr/comparison.spec.ts +0 -334
  202. package/tests/expr/conditional.expected.ts +0 -134
  203. package/tests/expr/conditional.spec.ts +0 -249
  204. package/tests/expr/date.expected.ts +0 -332
  205. package/tests/expr/date.spec.ts +0 -459
  206. package/tests/expr/math.expected.ts +0 -62
  207. package/tests/expr/math.spec.ts +0 -59
  208. package/tests/expr/string.expected.ts +0 -218
  209. package/tests/expr/string.spec.ts +0 -300
  210. package/tests/expr/utility.expected.ts +0 -147
  211. package/tests/expr/utility.spec.ts +0 -155
  212. package/tests/select/basic.expected.ts +0 -322
  213. package/tests/select/basic.spec.ts +0 -433
  214. package/tests/select/filter.expected.ts +0 -357
  215. package/tests/select/filter.spec.ts +0 -954
  216. package/tests/select/group.expected.ts +0 -169
  217. package/tests/select/group.spec.ts +0 -159
  218. package/tests/select/join.expected.ts +0 -582
  219. package/tests/select/join.spec.ts +0 -692
  220. package/tests/select/order.expected.ts +0 -150
  221. package/tests/select/order.spec.ts +0 -140
  222. package/tests/select/recursive-cte.expected.ts +0 -244
  223. package/tests/select/recursive-cte.spec.ts +0 -514
  224. package/tests/select/result-meta.spec.ts +0 -270
  225. package/tests/select/subquery.expected.ts +0 -363
  226. package/tests/select/subquery.spec.ts +0 -441
  227. package/tests/select/view.expected.ts +0 -155
  228. package/tests/select/view.spec.ts +0 -235
  229. package/tests/select/window.expected.ts +0 -345
  230. package/tests/select/window.spec.ts +0 -433
  231. package/tests/setup/MockExecutor.ts +0 -18
  232. package/tests/setup/TestDbContext.ts +0 -59
  233. package/tests/setup/models/Company.ts +0 -13
  234. package/tests/setup/models/Employee.ts +0 -10
  235. package/tests/setup/models/MonthlySales.ts +0 -11
  236. package/tests/setup/models/Post.ts +0 -16
  237. package/tests/setup/models/Sales.ts +0 -10
  238. package/tests/setup/models/User.ts +0 -19
  239. package/tests/setup/procedure/GetAllUsers.ts +0 -9
  240. package/tests/setup/procedure/GetUserById.ts +0 -12
  241. package/tests/setup/test-utils.ts +0 -72
  242. package/tests/setup/views/ActiveUsers.ts +0 -8
  243. package/tests/setup/views/UserSummary.ts +0 -11
  244. package/tests/types/nullable-queryable-record.spec.ts +0 -97
  245. package/tests/utils/result-parser-perf.spec.ts +0 -143
  246. package/tests/utils/result-parser.spec.ts +0 -667
@@ -43,7 +43,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
43
43
 
44
44
  //#region ========== Utilities ==========
45
45
 
46
- /** Render table name */
46
+ /** 테이블명 렌더링 */
47
47
  protected tableName(obj: QueryDefObjectName): string {
48
48
  const parts: string[] = [];
49
49
  if (obj.database != null) {
@@ -58,7 +58,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
58
58
  return parts.join(".");
59
59
  }
60
60
 
61
- /** Render OFFSET...FETCH clause */
61
+ /** OFFSET...FETCH 렌더링 */
62
62
  protected renderLimit(limit: [number, number] | undefined): string {
63
63
  if (limit == null) return "";
64
64
  const [offset, count] = limit;
@@ -68,15 +68,15 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
68
68
  protected renderJoin(join: SelectQueryDefJoin): string {
69
69
  const alias = this.expr.wrap(join.as);
70
70
 
71
- // Detect if LATERAL JOIN is needed → MSSQL uses OUTER APPLY
71
+ // LATERAL JOIN 필요한지 감지 → MSSQL OUTER APPLY 사용
72
72
  if (this.needsLateral(join)) {
73
- // If from is an array (UNION ALL), use renderFrom(join.from),
74
- // otherwise (orderBy, top, select, etc.) use renderFrom(join) to generate subquery
73
+ // from 배열(UNION ALL)이면 renderFrom(join.from) 사용,
74
+ // (orderBy, top, select )이면 renderFrom(join)으로 서브쿼리 생성
75
75
  const from = Array.isArray(join.from) ? this.renderFrom(join.from) : this.renderFrom(join);
76
76
  return ` OUTER APPLY ${from} AS ${alias}`;
77
77
  }
78
78
 
79
- // Normal JOIN
79
+ // 일반 JOIN
80
80
  const from = this.renderFrom(join.from);
81
81
  const where =
82
82
  join.where != null && join.where.length > 0
@@ -122,7 +122,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
122
122
  const from = this.renderFrom(def.from);
123
123
  sql += ` FROM ${from} AS ${this.expr.wrap(def.as)}`;
124
124
 
125
- // LOCK (force row-level lock with ROWLOCK - same behavior as MySQL/PostgreSQL FOR UPDATE)
125
+ // LOCK (ROWLOCK으로 수준 잠금 강제 - MySQL/PostgreSQL FOR UPDATE와 동일 동작)
126
126
  if (def.lock) {
127
127
  sql += " WITH (UPDLOCK, ROWLOCK)";
128
128
  }
@@ -157,7 +157,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
157
157
  const table = this.tableName(def.table);
158
158
 
159
159
  if (def.records.length === 0) {
160
- throw new Error("INSERT requires at least one record.");
160
+ throw new Error("INSERT에는 최소 1개의 레코드가 필요합니다.");
161
161
  }
162
162
 
163
163
  const columns = Object.keys(def.records[0]);
@@ -165,14 +165,14 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
165
165
 
166
166
  let sql = "";
167
167
 
168
- // IDENTITY_INSERT ON (when inserting explicit values into AI column)
168
+ // IDENTITY_INSERT ON (AI column에 명시적 값을 삽입할 )
169
169
  if (def.overrideIdentity) {
170
170
  sql += `SET IDENTITY_INSERT ${table} ON;\n`;
171
171
  }
172
172
 
173
173
  sql += `INSERT INTO ${table} (${colList})`;
174
174
 
175
- // OUTPUT (MSSQL native support)
175
+ // OUTPUT (MSSQL 네이티브 지원)
176
176
  if (def.output != null) {
177
177
  const outputCols = def.output.columns.map((c) => `INSERTED.${this.expr.wrap(c)}`).join(", ");
178
178
  sql += ` OUTPUT ${outputCols}`;
@@ -191,7 +191,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
191
191
  sql += `;\nSET IDENTITY_INSERT ${table} OFF;`;
192
192
  }
193
193
 
194
- // With overrideIdentity: SET ON → results[0], INSERT → results[1], SET OFF → results[2]
194
+ // overrideIdentity 사용 시: SET ON → results[0], INSERT → results[1], SET OFF → results[2]
195
195
  return { sql, resultSetIndex: def.overrideIdentity ? 1 : undefined };
196
196
  }
197
197
 
@@ -202,7 +202,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
202
202
  const colList = columns.map((c) => this.expr.wrap(c)).join(", ");
203
203
  const values = columns.map((c) => this.expr.escapeValue(def.record[c])).join(", ");
204
204
 
205
- // Render existsSelectQuery as SELECT 1 AS _
205
+ // existsSelectQuery SELECT 1 AS _로 렌더링
206
206
  const existsQuerySql = this.select({
207
207
  ...def.existsSelectQuery,
208
208
  select: { _: { type: "value", value: 1 } },
@@ -210,7 +210,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
210
210
 
211
211
  let sql = `INSERT INTO ${table} (${colList})`;
212
212
 
213
- // OUTPUT (MSSQL: OUTPUT must be placed before SELECT)
213
+ // OUTPUT (MSSQL: OUTPUT SELECT 앞에 위치해야 )
214
214
  if (def.output != null) {
215
215
  const outputCols = def.output.columns.map((c) => `INSERTED.${this.expr.wrap(c)}`).join(", ");
216
216
  sql += ` OUTPUT ${outputCols}`;
@@ -225,7 +225,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
225
225
  const table = this.tableName(def.table);
226
226
  const selectSql = this.select(def.recordsSelectQuery).sql;
227
227
 
228
- // Extract columns from INSERT INTO SELECT
228
+ // INSERT INTO SELECT에서 column 추출
229
229
  const selectDef = def.recordsSelectQuery;
230
230
  const colList =
231
231
  selectDef.select != null
@@ -292,7 +292,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
292
292
  }
293
293
  sql += ` ${alias}`;
294
294
 
295
- // OUTPUT (MSSQL: DELETED for DELETE)
295
+ // OUTPUT (MSSQL: DELETE에는 DELETED 사용)
296
296
  if (def.output != null) {
297
297
  const outputCols = def.output.columns.map((c) => `DELETED.${this.expr.wrap(c)}`).join(", ");
298
298
  sql += ` OUTPUT ${outputCols}`;
@@ -310,17 +310,17 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
310
310
  //#region ========== DML - UPSERT ==========
311
311
 
312
312
  protected upsert(def: UpsertQueryDef): QueryBuildResult {
313
- // MSSQL: Use MERGE
313
+ // MSSQL: MERGE 사용
314
314
  const table = this.tableName(def.table);
315
315
  const alias = this.expr.wrap(def.existsSelectQuery.as);
316
316
  const existsWhere = def.existsSelectQuery.where;
317
317
 
318
- // UPDATE SET part
318
+ // UPDATE SET 부분
319
319
  const updateSetParts = Object.entries(def.updateRecord).map(
320
320
  ([col, e]) => `${this.expr.wrap(col)} = ${this.expr.render(e)}`,
321
321
  );
322
322
 
323
- // INSERT part
323
+ // INSERT 부분
324
324
  const insertColumns = Object.keys(def.insertRecord);
325
325
  const insertColList = insertColumns.map((c) => this.expr.wrap(c)).join(", ");
326
326
  const insertValues = insertColumns.map((c) => this.expr.render(def.insertRecord[c])).join(", ");
@@ -356,7 +356,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
356
356
  const colDefs = def.columns.map((col) => {
357
357
  let colSql = `${this.expr.wrap(col.name)} ${this.expr.renderDataType(col.dataType)}`;
358
358
 
359
- // nullable: true → NULL, else → NOT NULL
359
+ // nullable: true → NULL, 아니면 → NOT NULL
360
360
  if (col.nullable === true) {
361
361
  colSql += " NULL";
362
362
  } else {
@@ -374,7 +374,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
374
374
  return colSql;
375
375
  });
376
376
 
377
- // Primary Key with CONSTRAINT name
377
+ // CONSTRAINT 이름이 포함된 Primary Key
378
378
  if (def.primaryKey != null && def.primaryKey.length > 0) {
379
379
  const pkCols = def.primaryKey.map((c) => this.expr.wrap(c)).join(", ");
380
380
  const pkName = this.expr.wrap(`PK_${def.table.name}`);
@@ -396,7 +396,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
396
396
  }
397
397
 
398
398
  protected truncate(def: TruncateQueryDef): QueryBuildResult {
399
- // MSSQL: TRUNCATE automatically resets IDENTITY
399
+ // MSSQL: TRUNCATE IDENTITY를 자동으로 초기화
400
400
  return { sql: `TRUNCATE TABLE ${this.tableName(def.table)}` };
401
401
  }
402
402
 
@@ -447,13 +447,13 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
447
447
  colSql += " NOT NULL";
448
448
  }
449
449
 
450
- // MSSQL: ALTER COLUMN (IDENTITY and DEFAULT require separate handling)
450
+ // MSSQL: ALTER COLUMN (IDENTITY DEFAULT 별도 처리 필요)
451
451
  return { sql: `ALTER TABLE ${table} ALTER COLUMN ${colSql}` };
452
452
  }
453
453
 
454
454
  protected renameColumn(def: RenameColumnQueryDef): QueryBuildResult {
455
455
  const table = this.tableName(def.table);
456
- // MSSQL: Use sp_rename
456
+ // MSSQL: sp_rename 사용
457
457
  const tableCol = this.expr.escapeString(`${table}.${def.column}`);
458
458
  const newName = this.expr.escapeString(def.newName);
459
459
  return { sql: `EXEC sp_rename '${tableCol}', '${newName}', 'COLUMN'` };
@@ -487,7 +487,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
487
487
 
488
488
  let sql = `ALTER TABLE ${table} ADD CONSTRAINT ${this.expr.wrap(fk.name)} FOREIGN KEY (${fkCols}) REFERENCES ${targetTable} (${targetCols})`;
489
489
 
490
- // MSSQL/PostgreSQL: separate index generation needed for FK
490
+ // MSSQL/PostgreSQL: FK에 대한 별도 인덱스 생성 필요
491
491
  const idxName = `IDX_${def.table.name}_${fk.name.replace(/^FK_/, "")}`;
492
492
  sql += `;\nCREATE INDEX ${this.expr.wrap(idxName)} ON ${table} (${fkCols});`;
493
493
 
@@ -519,7 +519,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
519
519
  protected createView(def: CreateViewQueryDef): QueryBuildResult {
520
520
  const view = this.tableName(def.view);
521
521
  const selectSql = this.select(def.queryDef).sql;
522
- // MSSQL: CREATE OR ALTER VIEW (2016 SP1+)
522
+ // MSSQL: CREATE OR ALTER VIEW (2016 SP1 이상)
523
523
  return { sql: `CREATE OR ALTER VIEW ${view} AS ${selectSql}` };
524
524
  }
525
525
 
@@ -530,7 +530,7 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
530
530
  protected createProc(def: CreateProcQueryDef): QueryBuildResult {
531
531
  const proc = this.tableName(def.procedure);
532
532
 
533
- // Process params
533
+ // 파라미터 처리
534
534
  const paramList =
535
535
  def.params
536
536
  ?.map((p) => {
@@ -574,13 +574,13 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
574
574
  //#region ========== Utils ==========
575
575
 
576
576
  protected clearSchema(def: ClearSchemaQueryDef): QueryBuildResult {
577
- // SQL injection prevention: identifier validation
577
+ // SQL 인젝션 방지: 식별자 유효성 검사
578
578
  if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(def.database)) {
579
- throw new Error(`Invalid database name: ${def.database}`);
579
+ throw new Error(`잘못된 데이터베이스 이름: ${def.database}`);
580
580
  }
581
581
  const schemaName = def.schema ?? "dbo";
582
582
  if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(schemaName)) {
583
- throw new Error(`Invalid schema name: ${schemaName}`);
583
+ throw new Error(`잘못된 schema 이름: ${schemaName}`);
584
584
  }
585
585
 
586
586
  const db = this.expr.wrap(def.database);
@@ -590,22 +590,22 @@ export class MssqlQueryBuilder extends QueryBuilderBase {
590
590
  DECLARE @sql NVARCHAR(MAX);
591
591
  SET @sql = N'';
592
592
 
593
- -- Drop FK constraints
593
+ -- FK 제약조건 삭제
594
594
  SELECT @sql = @sql + N'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.' + QUOTENAME(OBJECT_NAME(parent_object_id)) + N' DROP CONSTRAINT ' + QUOTENAME(name) + N';' + CHAR(13)
595
595
  FROM ${db}.sys.foreign_keys
596
596
  WHERE OBJECT_SCHEMA_NAME(parent_object_id) = '${schema}';
597
597
 
598
- -- Drop tables
598
+ -- 테이블 삭제
599
599
  SELECT @sql = @sql + N'DROP TABLE ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name) + N';' + CHAR(13)
600
600
  FROM ${db}.sys.tables
601
601
  WHERE SCHEMA_NAME(schema_id) = '${schema}';
602
602
 
603
- -- Drop views
603
+ -- 삭제
604
604
  SELECT @sql = @sql + N'DROP VIEW ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name) + N';' + CHAR(13)
605
605
  FROM ${db}.sys.views
606
606
  WHERE schema_id = SCHEMA_ID('${schema}');
607
607
 
608
- -- Drop procedures
608
+ -- 프로시저 삭제
609
609
  SELECT @sql = @sql + N'DROP PROCEDURE ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name) + N';' + CHAR(13)
610
610
  FROM ${db}.sys.procedures
611
611
  WHERE SCHEMA_NAME(schema_id) = '${schema}';
@@ -615,18 +615,18 @@ EXEC sp_executesql @sql;`,
615
615
  }
616
616
 
617
617
  protected schemaExists(def: SchemaExistsQueryDef): QueryBuildResult {
618
- // SQL injection prevention: identifier validation
618
+ // SQL 인젝션 방지: 식별자 유효성 검사
619
619
  if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(def.database)) {
620
- throw new Error(`Invalid database name: ${def.database}`);
620
+ throw new Error(`잘못된 데이터베이스 이름: ${def.database}`);
621
621
  }
622
622
  const schemaName = def.schema ?? "dbo";
623
623
  if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(schemaName)) {
624
- throw new Error(`Invalid schema name: ${schemaName}`);
624
+ throw new Error(`잘못된 schema 이름: ${schemaName}`);
625
625
  }
626
626
 
627
627
  const dbName = this.expr.escapeString(def.database);
628
628
  const schema = this.expr.escapeString(schemaName);
629
- // MSSQL: check database existence then check schema (using dynamic SQL)
629
+ // MSSQL: 데이터베이스 존재 여부 확인 schema 확인 (동적 SQL 사용)
630
630
  return {
631
631
  sql: `DECLARE @result NVARCHAR(MAX) = NULL;
632
632
  IF EXISTS (SELECT 1 FROM sys.databases WHERE name = '${dbName}')
@@ -69,28 +69,28 @@ import type { DataType } from "../../types/column";
69
69
  import { ExprRendererBase } from "../base/expr-renderer-base";
70
70
 
71
71
  /**
72
- * MySQL expression renderer
72
+ * MySQL 표현식 렌더러
73
73
  */
74
74
  export class MysqlExprRenderer extends ExprRendererBase {
75
- //#region ========== Utilities (public - also used by QueryBuilder) ==========
75
+ //#region ========== 유틸리티 (public - QueryBuilder에서도 사용) ==========
76
76
 
77
- /** Wrap identifier */
77
+ /** 식별자 감싸기 */
78
78
  wrap(name: string): string {
79
79
  return `\`${name.replace(/`/g, "``")}\``;
80
80
  }
81
81
 
82
- /** Escape for SQL string literals (returns without quotes) */
82
+ /** SQL 문자열 리터럴용 이스케이프 (따옴표 제외) */
83
83
  escapeString(value: string): string {
84
84
  return value
85
- .replace(/\\/g, "\\\\") // backslash (highest priority)
86
- .replace(/'/g, "''") // single quote
87
- .replace(/\0/g, "\\0") // NULL byte
88
- .replace(/\n/g, "\\n") // newline
89
- .replace(/\r/g, "\\r") // carriage return
90
- .replace(/\t/g, "\\t"); // tab
85
+ .replace(/\\/g, "\\\\") // 백슬래시 (최우선)
86
+ .replace(/'/g, "''") // 작은따옴표
87
+ .replace(/\0/g, "\\0") // NULL 바이트
88
+ .replace(/\n/g, "\\n") // 줄바꿈
89
+ .replace(/\r/g, "\\r") // 캐리지 리턴
90
+ .replace(/\t/g, "\\t"); //
91
91
  }
92
92
 
93
- /** value escape */
93
+ /** 이스케이프 */
94
94
  escapeValue(value: unknown): string {
95
95
  if (value == null) {
96
96
  return "NULL";
@@ -119,10 +119,10 @@ export class MysqlExprRenderer extends ExprRendererBase {
119
119
  if (value instanceof Uint8Array) {
120
120
  return `0x${bytes.toHex(value)}`;
121
121
  }
122
- throw new Error(`Unknown value type: ${typeof value}`);
122
+ throw new Error(`알 없는 값 타입: ${typeof value}`);
123
123
  }
124
124
 
125
- /** DataType → SQL type */
125
+ /** DataType → SQL 타입 변환 */
126
126
  renderDataType(dataType: DataType): string {
127
127
  switch (dataType.type) {
128
128
  case "int":
@@ -182,7 +182,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
182
182
  //#region ========== comparison (null-safe) ==========
183
183
 
184
184
  protected eq(expr: ExprEq): string {
185
- // MySQL: <=> operator (null-safe equal)
185
+ // MySQL: <=> 연산자 (NULL 안전 동등 비교)
186
186
  return `${this.render(expr.source)} <=> ${this.render(expr.target)}`;
187
187
  }
188
188
 
@@ -221,7 +221,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
221
221
  }
222
222
 
223
223
  protected like(expr: ExprLike): string {
224
- // Always add ESCAPE '\'
224
+ // 항상 ESCAPE '\' 추가
225
225
  return `${this.render(expr.source)} LIKE ${this.render(expr.pattern)} ESCAPE '\\\\'`;
226
226
  }
227
227
 
@@ -231,7 +231,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
231
231
 
232
232
  protected in(expr: ExprIn): string {
233
233
  if (expr.values.length === 0) {
234
- return "1=0"; // empty IN is always false
234
+ return "1=0"; // IN 항상 false
235
235
  }
236
236
  const values = expr.values.map((v) => this.render(v)).join(", ");
237
237
  return `${this.render(expr.source)} IN (${values})`;
@@ -242,7 +242,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
242
242
  }
243
243
 
244
244
  protected exists(expr: ExprExists): string {
245
- // Render as SELECT 1
245
+ // SELECT 1로 렌더링
246
246
  const subquery = this.buildSelect({
247
247
  ...expr.query,
248
248
  select: { _: { type: "value", value: 1 } },
@@ -273,7 +273,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
273
273
  //#region ========== String (null handling) ==========
274
274
 
275
275
  protected concat(expr: ExprConcat): string {
276
- // null handling: IFNULL(arg, '')
276
+ // null 처리: IFNULL(arg, '')
277
277
  const args = expr.args.map((a) => `IFNULL(${this.render(a)}, '')`);
278
278
  return `CONCAT(${args.join(", ")})`;
279
279
  }
@@ -307,12 +307,12 @@ export class MysqlExprRenderer extends ExprRendererBase {
307
307
  }
308
308
 
309
309
  protected length(expr: ExprLength): string {
310
- // null handling: IFNULL(arg, '')
310
+ // null 처리: IFNULL(arg, '')
311
311
  return `CHAR_LENGTH(IFNULL(${this.render(expr.arg)}, ''))`;
312
312
  }
313
313
 
314
314
  protected byteLength(expr: ExprByteLength): string {
315
- // null handling: IFNULL(arg, '')
315
+ // null 처리: IFNULL(arg, '')
316
316
  return `LENGTH(IFNULL(${this.render(expr.arg)}, ''))`;
317
317
  }
318
318
 
@@ -380,7 +380,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
380
380
  }
381
381
 
382
382
  protected isoWeekStartDate(expr: ExprIsoWeekStartDate): string {
383
- // ISO week start date (Monday)
383
+ // ISO 시작일 (월요일)
384
384
  return `DATE_SUB(${this.render(expr.arg)}, INTERVAL (WEEKDAY(${this.render(expr.arg)})) DAY)`;
385
385
  }
386
386
 
@@ -415,7 +415,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
415
415
  }
416
416
 
417
417
  protected formatDate(expr: ExprFormatDate): string {
418
- // JS format → MySQL format
418
+ // JS 포맷 → MySQL 포맷
419
419
  const mysqlFormat = this.convertDateFormat(expr.format);
420
420
  return `DATE_FORMAT(${this.render(expr.source)}, '${mysqlFormat}')`;
421
421
  }
@@ -438,7 +438,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
438
438
  }
439
439
 
440
440
  private convertDateFormat(format: string): string {
441
- // Simple transform (yyyy-MM-dd HH:mm:ss format)
441
+ // 단순 변환 (yyyy-MM-dd HH:mm:ss 포맷)
442
442
  return format
443
443
  .replace(/yyyy/g, "%Y")
444
444
  .replace(/MM/g, "%m")
@@ -455,7 +455,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
455
455
  protected coalesce(expr: ExprCoalesce): string {
456
456
  if (expr.args.length === 0) return "NULL";
457
457
  if (expr.args.length === 1) return this.render(expr.args[0]);
458
- // Render as COALESCE (first non-null among multiple values)
458
+ // COALESCE로 렌더링 (여러 값 중 첫 번째 non-null 반환)
459
459
  return `COALESCE(${expr.args.map((a) => this.render(a)).join(", ")})`;
460
460
  }
461
461
 
@@ -512,18 +512,18 @@ export class MysqlExprRenderer extends ExprRendererBase {
512
512
  //#region ========== Other ==========
513
513
 
514
514
  protected greatest(expr: ExprGreatest): string {
515
- if (expr.args.length === 0) throw new Error("greatest requires at least one argument.");
515
+ if (expr.args.length === 0) throw new Error("greatest에는 최소 1개의 인수가 필요합니다.");
516
516
  return `GREATEST(${expr.args.map((a) => this.render(a)).join(", ")})`;
517
517
  }
518
518
 
519
519
  protected least(expr: ExprLeast): string {
520
- if (expr.args.length === 0) throw new Error("least requires at least one argument.");
520
+ if (expr.args.length === 0) throw new Error("least에는 최소 1개의 인수가 필요합니다.");
521
521
  return `LEAST(${expr.args.map((a) => this.render(a)).join(", ")})`;
522
522
  }
523
523
 
524
524
  protected rowNum(_expr: ExprRowNum): string {
525
- // MySQL: use variables or ROW_NUMBER() window function
526
- // Implemented with ROW_NUMBER() here (MySQL 8.0+)
525
+ // MySQL: 변수 또는 ROW_NUMBER() 윈도우 함수 사용
526
+ // 여기서는 ROW_NUMBER() 구현 (MySQL 8.0+)
527
527
  return "ROW_NUMBER() OVER ()";
528
528
  }
529
529
 
@@ -543,7 +543,7 @@ export class MysqlExprRenderer extends ExprRendererBase {
543
543
  const fn = this.renderWindowFn(expr.fn);
544
544
  let over = this.renderWindowSpec(expr.spec);
545
545
 
546
- // LAST_VALUE default frame only sees up to CURRENT ROW, so full frame must be specified
546
+ // LAST_VALUE 기본 프레임은 CURRENT ROW까지만 보므로 전체 프레임을 지정해야
547
547
  if (expr.fn.type === "lastValue" && over.length > 0) {
548
548
  over += " ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING";
549
549
  }