@simplysm/orm-node 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.
@@ -1,392 +1,379 @@
1
1
  import consola from "consola";
2
- import {
3
- DateOnly,
4
- DateTime,
5
- json,
6
- str,
7
- wait,
8
- SdError,
9
- EventEmitter,
10
- Time,
11
- Uuid
12
- } from "@simplysm/core-common";
13
- import {
14
- DB_CONN_CONNECT_TIMEOUT,
15
- DB_CONN_DEFAULT_TIMEOUT,
16
- DB_CONN_ERRORS
17
- } from "../types/db-conn.js";
2
+ import { DateOnly, DateTime, json, str, wait, SdError, EventEmitter, Time, Uuid, } from "@simplysm/core-common";
3
+ import { DB_CONN_CONNECT_TIMEOUT, DB_CONN_DEFAULT_TIMEOUT, DB_CONN_ERRORS, } from "../types/db-conn.js";
18
4
  const logger = consola.withTag("mssql-db-conn");
19
- class MssqlDbConn extends EventEmitter {
20
- constructor(_tedious, config) {
21
- super();
22
- this._tedious = _tedious;
23
- this.config = config;
24
- }
25
- _timeout = DB_CONN_DEFAULT_TIMEOUT;
26
- _conn;
27
- _connTimeout;
28
- _requests = [];
29
- isConnected = false;
30
- isInTransaction = false;
31
- async connect() {
32
- if (this.isConnected) {
33
- throw new SdError(DB_CONN_ERRORS.ALREADY_CONNECTED);
5
+ /**
6
+ * MSSQL 데이터베이스 연결 클래스
7
+ *
8
+ * tedious 라이브러리를 사용하여 MSSQL/Azure SQL 연결을 관리한다.
9
+ */
10
+ export class MssqlDbConn extends EventEmitter {
11
+ _tedious;
12
+ config;
13
+ _timeout = DB_CONN_DEFAULT_TIMEOUT;
14
+ _conn;
15
+ _connTimeout;
16
+ _requests = [];
17
+ isConnected = false;
18
+ isInTransaction = false;
19
+ constructor(_tedious, config) {
20
+ super();
21
+ this._tedious = _tedious;
22
+ this.config = config;
34
23
  }
35
- const conn = new this._tedious.Connection({
36
- server: this.config.host,
37
- authentication: {
38
- type: "default",
39
- options: {
40
- userName: this.config.username,
41
- password: this.config.password
24
+ async connect() {
25
+ if (this.isConnected) {
26
+ throw new SdError(DB_CONN_ERRORS.ALREADY_CONNECTED);
42
27
  }
43
- },
44
- options: {
45
- database: this.config.database,
46
- port: this.config.port,
47
- rowCollectionOnDone: true,
48
- useUTC: false,
49
- encrypt: this.config.dialect === "mssql-azure",
50
- requestTimeout: this._timeout,
51
- trustServerCertificate: true,
52
- connectTimeout: DB_CONN_CONNECT_TIMEOUT
53
- }
54
- });
55
- conn.on("infoMessage", (info) => {
56
- logger.debug("info", info.message);
57
- });
58
- conn.on("errorMessage", (error) => {
59
- logger.error("errorMessage", error.message);
60
- });
61
- conn.on("error", (error) => {
62
- logger.error("error", error.message);
63
- });
64
- conn.on("end", () => {
65
- this.emit("close");
66
- this._resetState();
67
- });
68
- await new Promise((resolve, reject) => {
69
- conn.connect((err) => {
70
- if (err != null) {
71
- reject(new SdError(err));
72
- return;
73
- }
74
- this._startTimeout();
75
- this.isConnected = true;
76
- this.isInTransaction = false;
77
- resolve();
78
- });
79
- });
80
- this._conn = conn;
81
- }
82
- async close() {
83
- this._stopTimeout();
84
- if (this._conn == null || !this.isConnected) {
85
- return;
28
+ const conn = new this._tedious.Connection({
29
+ server: this.config.host,
30
+ authentication: {
31
+ type: "default",
32
+ options: {
33
+ userName: this.config.username,
34
+ password: this.config.password,
35
+ },
36
+ },
37
+ options: {
38
+ database: this.config.database,
39
+ port: this.config.port,
40
+ rowCollectionOnDone: true,
41
+ useUTC: false,
42
+ encrypt: this.config.dialect === "mssql-azure",
43
+ requestTimeout: this._timeout,
44
+ trustServerCertificate: true,
45
+ connectTimeout: DB_CONN_CONNECT_TIMEOUT,
46
+ },
47
+ });
48
+ conn.on("infoMessage", (info) => {
49
+ logger.debug("정보", info.message);
50
+ });
51
+ conn.on("errorMessage", (error) => {
52
+ logger.error("오류 메시지", error.message);
53
+ });
54
+ conn.on("error", (error) => {
55
+ logger.error("오류", error.message);
56
+ });
57
+ conn.on("end", () => {
58
+ this.emit("close");
59
+ this._resetState();
60
+ });
61
+ await new Promise((resolve, reject) => {
62
+ conn.connect((err) => {
63
+ if (err != null) {
64
+ reject(new SdError(err));
65
+ return;
66
+ }
67
+ this._startTimeout();
68
+ this.isConnected = true;
69
+ this.isInTransaction = false;
70
+ resolve();
71
+ });
72
+ });
73
+ this._conn = conn;
86
74
  }
87
- const conn = this._conn;
88
- conn.cancel();
89
- await wait.until(() => this._requests.length < 1, 3e4, 100);
90
- await new Promise((resolve) => {
91
- conn.on("end", () => {
92
- wait.until(() => this._conn == null, 3e4, 100).then(() => resolve()).catch(() => resolve());
93
- });
94
- conn.close();
95
- });
96
- }
97
- async beginTransaction(isolationLevel) {
98
- this._assertConnected();
99
- this._startTimeout();
100
- const conn = this._conn;
101
- await new Promise((resolve, reject) => {
102
- conn.beginTransaction(
103
- (err) => {
104
- if (err != null) {
105
- reject(new SdError(err));
75
+ async close() {
76
+ this._stopTimeout();
77
+ if (this._conn == null || !this.isConnected) {
106
78
  return;
107
- }
108
- this.isInTransaction = true;
109
- resolve();
110
- },
111
- "",
112
- this._tedious.ISOLATION_LEVEL[isolationLevel ?? this.config.defaultIsolationLevel ?? "READ_UNCOMMITTED"]
113
- );
114
- });
115
- }
116
- async commitTransaction() {
117
- this._assertConnected();
118
- this._startTimeout();
119
- const conn = this._conn;
120
- await new Promise((resolve, reject) => {
121
- conn.commitTransaction((err) => {
122
- if (err != null) {
123
- reject(new SdError(err));
124
- return;
125
- }
126
- this.isInTransaction = false;
127
- resolve();
128
- });
129
- });
130
- }
131
- async rollbackTransaction() {
132
- this._assertConnected();
133
- this._startTimeout();
134
- const conn = this._conn;
135
- await new Promise((resolve, reject) => {
136
- conn.rollbackTransaction((err) => {
137
- if (err != null) {
138
- reject(new SdError(err));
139
- return;
140
79
  }
141
- this.isInTransaction = false;
142
- resolve();
143
- });
144
- });
145
- }
146
- async execute(queries) {
147
- const results = [];
148
- for (const query of queries.filter((item) => !str.isNullOrEmpty(item))) {
149
- const resultItems = await this.executeParametrized(query);
150
- results.push(...resultItems);
80
+ const conn = this._conn;
81
+ // 진행 중인 요청 취소
82
+ conn.cancel();
83
+ await wait.until(() => this._requests.length < 1, 30000, 100);
84
+ // 연결 종료 대기
85
+ await new Promise((resolve) => {
86
+ conn.on("end", () => {
87
+ wait.until(() => this._conn == null, 30000, 100)
88
+ .then(() => resolve())
89
+ .catch(() => resolve());
90
+ });
91
+ conn.close();
92
+ });
151
93
  }
152
- return results;
153
- }
154
- async executeParametrized(query, params) {
155
- this._assertConnected();
156
- this._startTimeout();
157
- const conn = this._conn;
158
- const results = [];
159
- logger.debug("Query execution", { queryLength: query.length, params });
160
- await new Promise((resolve, reject) => {
161
- let rejected = false;
162
- const queryRequest = new this._tedious.Request(query, (err) => {
163
- if (err != null) {
164
- rejected = true;
165
- this._requests = this._requests.filter((r) => r !== queryRequest);
166
- const errCode = "code" in err ? err.code : void 0;
167
- if (errCode === "ECANCEL") {
168
- reject(new SdError(err, "Query was cancelled."));
169
- } else {
170
- const lineNumber = "lineNumber" in err && typeof err.lineNumber === "number" ? err.lineNumber : void 0;
171
- if (lineNumber != null && lineNumber > 0) {
172
- const splitQuery = query.split("\n");
173
- splitQuery[lineNumber - 1] = "==> " + splitQuery[lineNumber - 1];
174
- reject(
175
- new SdError(err, `Error executing query
176
- -- query
177
- ${splitQuery.join("\n")}
178
- --`)
179
- );
180
- } else {
181
- reject(new SdError(err, `Error executing query
182
- -- query
183
- ${query}
184
- --`));
185
- }
186
- }
187
- }
188
- });
189
- queryRequest.on("done", (_rowCount, _more, rst) => {
94
+ async beginTransaction(isolationLevel) {
95
+ this._assertConnected();
190
96
  this._startTimeout();
191
- if (rejected) {
192
- return;
193
- }
194
- results.push(this._parseRowsToRecords(rst));
195
- }).on("doneInProc", (_rowCount, _more, rst) => {
97
+ const conn = this._conn;
98
+ await new Promise((resolve, reject) => {
99
+ conn.beginTransaction((err) => {
100
+ if (err != null) {
101
+ reject(new SdError(err));
102
+ return;
103
+ }
104
+ this.isInTransaction = true;
105
+ resolve();
106
+ }, "", this._tedious.ISOLATION_LEVEL[isolationLevel ?? this.config.defaultIsolationLevel ?? "READ_UNCOMMITTED"]);
107
+ });
108
+ }
109
+ async commitTransaction() {
110
+ this._assertConnected();
196
111
  this._startTimeout();
197
- if (rejected) {
198
- return;
199
- }
200
- results.push(this._parseRowsToRecords(rst));
201
- }).on("error", (err) => {
112
+ const conn = this._conn;
113
+ await new Promise((resolve, reject) => {
114
+ conn.commitTransaction((err) => {
115
+ if (err != null) {
116
+ reject(new SdError(err));
117
+ return;
118
+ }
119
+ this.isInTransaction = false;
120
+ resolve();
121
+ });
122
+ });
123
+ }
124
+ async rollbackTransaction() {
125
+ this._assertConnected();
202
126
  this._startTimeout();
203
- if (rejected) {
204
- return;
127
+ const conn = this._conn;
128
+ await new Promise((resolve, reject) => {
129
+ conn.rollbackTransaction((err) => {
130
+ if (err != null) {
131
+ reject(new SdError(err));
132
+ return;
133
+ }
134
+ this.isInTransaction = false;
135
+ resolve();
136
+ });
137
+ });
138
+ }
139
+ async execute(queries) {
140
+ const results = [];
141
+ for (const query of queries.filter((item) => !str.isNullOrEmpty(item))) {
142
+ const resultItems = await this.executeParametrized(query);
143
+ results.push(...resultItems);
205
144
  }
206
- rejected = true;
207
- this._requests = this._requests.filter((r) => r !== queryRequest);
208
- reject(new SdError(err, `Error executing query
209
- -- query
210
- ${query}
211
- --`));
212
- }).on("requestCompleted", () => {
145
+ return results;
146
+ }
147
+ async executeParametrized(query, params) {
148
+ this._assertConnected();
213
149
  this._startTimeout();
214
- if (rejected) {
215
- return;
216
- }
217
- this._requests = this._requests.filter((r) => r !== queryRequest);
218
- resolve();
219
- });
220
- this._requests.push(queryRequest);
221
- if (params != null) {
222
- for (let i = 0; i < params.length; i++) {
223
- const paramValue = params[i];
224
- const paramName = `p${i}`;
225
- const type = this._guessTediousType(paramValue);
226
- queryRequest.addParameter(paramName, type, paramValue);
150
+ const conn = this._conn;
151
+ const results = [];
152
+ logger.debug("쿼리 실행", { queryLength: query.length, params });
153
+ await new Promise((resolve, reject) => {
154
+ let rejected = false;
155
+ const queryRequest = new this._tedious.Request(query, (err) => {
156
+ if (err != null) {
157
+ rejected = true;
158
+ this._requests = this._requests.filter((r) => r !== queryRequest);
159
+ const errCode = "code" in err ? err.code : undefined;
160
+ if (errCode === "ECANCEL") {
161
+ reject(new SdError(err, "쿼리가 취소되었습니다."));
162
+ }
163
+ else {
164
+ const lineNumber = "lineNumber" in err && typeof err.lineNumber === "number" ? err.lineNumber : undefined;
165
+ if (lineNumber != null && lineNumber > 0) {
166
+ const splitQuery = query.split("\n");
167
+ splitQuery[lineNumber - 1] = "==> " + splitQuery[lineNumber - 1];
168
+ reject(new SdError(err, `쿼리 실행 오류\n-- query\n${splitQuery.join("\n")}\n--`));
169
+ }
170
+ else {
171
+ reject(new SdError(err, `쿼리 실행 오류\n-- query\n${query}\n--`));
172
+ }
173
+ }
174
+ }
175
+ });
176
+ queryRequest
177
+ .on("done", (_rowCount, _more, rst) => {
178
+ this._startTimeout();
179
+ if (rejected) {
180
+ return;
181
+ }
182
+ results.push(this._parseRowsToRecords(rst));
183
+ })
184
+ .on("doneInProc", (_rowCount, _more, rst) => {
185
+ this._startTimeout();
186
+ if (rejected) {
187
+ return;
188
+ }
189
+ results.push(this._parseRowsToRecords(rst));
190
+ })
191
+ .on("error", (err) => {
192
+ this._startTimeout();
193
+ if (rejected) {
194
+ return;
195
+ }
196
+ rejected = true;
197
+ this._requests = this._requests.filter((r) => r !== queryRequest);
198
+ reject(new SdError(err, `쿼리 실행 오류\n-- query\n${query}\n--`));
199
+ })
200
+ .on("requestCompleted", () => {
201
+ this._startTimeout();
202
+ if (rejected) {
203
+ return;
204
+ }
205
+ this._requests = this._requests.filter((r) => r !== queryRequest);
206
+ resolve();
207
+ });
208
+ this._requests.push(queryRequest);
209
+ if (params != null) {
210
+ for (let i = 0; i < params.length; i++) {
211
+ const paramValue = params[i];
212
+ const paramName = `p${i}`;
213
+ const type = this._guessTediousType(paramValue);
214
+ queryRequest.addParameter(paramName, type, paramValue);
215
+ }
216
+ conn.execSql(queryRequest);
217
+ }
218
+ else {
219
+ conn.execSqlBatch(queryRequest);
220
+ }
221
+ });
222
+ return results;
223
+ }
224
+ async bulkInsert(tableName, columnMetas, records) {
225
+ if (records.length === 0)
226
+ return;
227
+ this._assertConnected();
228
+ this._startTimeout();
229
+ const tediousColumnDefs = Object.entries(columnMetas).map(([name, meta]) => this._convertColumnMetaToTediousBulkColumnDef(name, meta));
230
+ await new Promise((resolve, reject) => {
231
+ const bulkLoad = this._conn.newBulkLoad(tableName, (err) => {
232
+ if (err != null) {
233
+ reject(new SdError(err, `Bulk Insert 오류\n${json.stringify(tediousColumnDefs)}\n-- data\n${json.stringify(records).substring(0, 10000)}...\n--`));
234
+ return;
235
+ }
236
+ resolve();
237
+ });
238
+ const colNames = Object.keys(columnMetas);
239
+ for (const tediousColumnDef of tediousColumnDefs) {
240
+ bulkLoad.addColumn(tediousColumnDef.name, tediousColumnDef.type, tediousColumnDef.options);
241
+ }
242
+ // 레코드를 행 배열로 변환 (컬럼 순서 유지, 값 변환 포함)
243
+ const rows = records.map((record) => colNames.map((colName) => {
244
+ const val = record[colName];
245
+ if (val instanceof Uuid)
246
+ return val.toString();
247
+ // eslint-disable-next-line no-restricted-globals -- tedious library requires Buffer
248
+ if (val instanceof Uint8Array)
249
+ return Buffer.from(val);
250
+ if (val instanceof DateTime)
251
+ return val.date;
252
+ if (val instanceof DateOnly)
253
+ return val.date;
254
+ if (val instanceof Time)
255
+ return val.toFormatString("HH:mm:ss");
256
+ return val;
257
+ }));
258
+ this._conn.execBulkLoad(bulkLoad, rows);
259
+ });
260
+ }
261
+ // ─────────────────────────────────────────────
262
+ // 내부 헬퍼
263
+ // ─────────────────────────────────────────────
264
+ _assertConnected() {
265
+ if (this._conn == null || !this.isConnected) {
266
+ throw new SdError(DB_CONN_ERRORS.NOT_CONNECTED);
227
267
  }
228
- conn.execSql(queryRequest);
229
- } else {
230
- conn.execSqlBatch(queryRequest);
231
- }
232
- });
233
- return results;
234
- }
235
- async bulkInsert(tableName, columnMetas, records) {
236
- if (records.length === 0) return;
237
- this._assertConnected();
238
- this._startTimeout();
239
- const tediousColumnDefs = Object.entries(columnMetas).map(
240
- ([name, meta]) => this._convertColumnMetaToTediousBulkColumnDef(name, meta)
241
- );
242
- await new Promise((resolve, reject) => {
243
- const bulkLoad = this._conn.newBulkLoad(tableName, (err) => {
244
- if (err != null) {
245
- reject(
246
- new SdError(
247
- err,
248
- `Bulk Insert error
249
- ${json.stringify(tediousColumnDefs)}
250
- -- data
251
- ${json.stringify(records).substring(0, 1e4)}...
252
- --`
253
- )
254
- );
255
- return;
268
+ }
269
+ _parseRowsToRecords(rows) {
270
+ return (rows ?? []).map((item) => {
271
+ const resultItem = {};
272
+ for (const col of item) {
273
+ resultItem[col.metadata.colName] = col.value;
274
+ }
275
+ return resultItem;
276
+ });
277
+ }
278
+ _resetState() {
279
+ this.isConnected = false;
280
+ this.isInTransaction = false;
281
+ this._conn = undefined;
282
+ this._requests = [];
283
+ }
284
+ _stopTimeout() {
285
+ if (this._connTimeout != null) {
286
+ clearTimeout(this._connTimeout);
256
287
  }
257
- resolve();
258
- });
259
- const colNames = Object.keys(columnMetas);
260
- for (const tediousColumnDef of tediousColumnDefs) {
261
- bulkLoad.addColumn(tediousColumnDef.name, tediousColumnDef.type, tediousColumnDef.options);
262
- }
263
- const rows = records.map(
264
- (record) => colNames.map((colName) => {
265
- const val = record[colName];
266
- if (val instanceof Uuid) return val.toString();
267
- if (val instanceof Uint8Array) return Buffer.from(val);
268
- if (val instanceof DateTime) return val.date;
269
- if (val instanceof DateOnly) return val.date;
270
- if (val instanceof Time) return val.toFormatString("HH:mm:ss");
271
- return val;
272
- })
273
- );
274
- this._conn.execBulkLoad(bulkLoad, rows);
275
- });
276
- }
277
- // ─────────────────────────────────────────────
278
- // Private helpers
279
- // ─────────────────────────────────────────────
280
- _assertConnected() {
281
- if (this._conn == null || !this.isConnected) {
282
- throw new SdError(DB_CONN_ERRORS.NOT_CONNECTED);
283
288
  }
284
- }
285
- _parseRowsToRecords(rows) {
286
- return (rows ?? []).map((item) => {
287
- const resultItem = {};
288
- for (const col of item) {
289
- resultItem[col.metadata.colName] = col.value;
290
- }
291
- return resultItem;
292
- });
293
- }
294
- _resetState() {
295
- this.isConnected = false;
296
- this.isInTransaction = false;
297
- this._conn = void 0;
298
- this._requests = [];
299
- }
300
- _stopTimeout() {
301
- if (this._connTimeout != null) {
302
- clearTimeout(this._connTimeout);
289
+ _startTimeout() {
290
+ this._stopTimeout();
291
+ this._connTimeout = setTimeout(() => {
292
+ this.close().catch((err) => {
293
+ logger.error("연결 종료 오류", err instanceof Error ? err.message : String(err));
294
+ });
295
+ }, this._timeout * 2);
303
296
  }
304
- }
305
- _startTimeout() {
306
- this._stopTimeout();
307
- this._connTimeout = setTimeout(() => {
308
- this.close().catch((err) => {
309
- logger.error("close error", err instanceof Error ? err.message : String(err));
310
- });
311
- }, this._timeout * 2);
312
- }
313
- _convertColumnMetaToTediousBulkColumnDef(name, meta) {
314
- const tediousDataType = this._convertDataTypeToTediousBulkColumnType(meta.dataType);
315
- return {
316
- name,
317
- type: tediousDataType.type,
318
- options: {
319
- length: tediousDataType.length,
320
- nullable: meta.nullable ?? false,
321
- precision: tediousDataType.precision,
322
- scale: tediousDataType.scale
323
- }
324
- };
325
- }
326
- _convertDataTypeToTediousBulkColumnType(dataType) {
327
- switch (dataType.type) {
328
- case "int":
329
- return { type: this._tedious.TYPES.Int };
330
- case "bigint":
331
- return { type: this._tedious.TYPES.BigInt };
332
- case "float":
333
- return { type: this._tedious.TYPES.Real };
334
- case "double":
335
- return { type: this._tedious.TYPES.Float };
336
- case "decimal":
297
+ _convertColumnMetaToTediousBulkColumnDef(name, meta) {
298
+ const tediousDataType = this._convertDataTypeToTediousBulkColumnType(meta.dataType);
337
299
  return {
338
- type: this._tedious.TYPES.Decimal,
339
- precision: dataType.precision,
340
- scale: dataType.scale
300
+ name,
301
+ type: tediousDataType.type,
302
+ options: {
303
+ length: tediousDataType.length,
304
+ nullable: meta.nullable ?? false,
305
+ precision: tediousDataType.precision,
306
+ scale: tediousDataType.scale,
307
+ },
341
308
  };
342
- case "varchar":
343
- return { type: this._tedious.TYPES.NVarChar, length: dataType.length };
344
- case "char":
345
- return { type: this._tedious.TYPES.NChar, length: dataType.length };
346
- case "text":
347
- return { type: this._tedious.TYPES.NText };
348
- case "binary":
349
- return { type: this._tedious.TYPES.VarBinary, length: Infinity };
350
- case "boolean":
351
- return { type: this._tedious.TYPES.Bit };
352
- case "datetime":
353
- return { type: this._tedious.TYPES.DateTime2 };
354
- case "date":
355
- return { type: this._tedious.TYPES.Date };
356
- case "time":
357
- return { type: this._tedious.TYPES.Time };
358
- case "uuid":
359
- return { type: this._tedious.TYPES.UniqueIdentifier };
360
- default:
361
- throw new SdError(`Unsupported DataType: ${JSON.stringify(dataType)}`);
362
- }
363
- }
364
- /**
365
- * Infer the type of a value and return Tedious data type
366
- *
367
- * @param value - Value whose type is to be inferred (error if null/undefined is passed)
368
- * @throws Error if null/undefined is passed
369
- */
370
- _guessTediousType(value) {
371
- if (value == null) {
372
- throw new SdError("_guessTediousType: null/undefined values are not supported.");
373
309
  }
374
- if (typeof value === "string") {
375
- return this._tedious.TYPES.NVarChar;
310
+ _convertDataTypeToTediousBulkColumnType(dataType) {
311
+ switch (dataType.type) {
312
+ case "int":
313
+ return { type: this._tedious.TYPES.Int };
314
+ case "bigint":
315
+ return { type: this._tedious.TYPES.BigInt };
316
+ case "float":
317
+ return { type: this._tedious.TYPES.Real };
318
+ case "double":
319
+ return { type: this._tedious.TYPES.Float };
320
+ case "decimal":
321
+ return {
322
+ type: this._tedious.TYPES.Decimal,
323
+ precision: dataType.precision,
324
+ scale: dataType.scale,
325
+ };
326
+ case "varchar":
327
+ return { type: this._tedious.TYPES.NVarChar, length: dataType.length };
328
+ case "char":
329
+ return { type: this._tedious.TYPES.NChar, length: dataType.length };
330
+ case "text":
331
+ return { type: this._tedious.TYPES.NText };
332
+ case "binary":
333
+ return { type: this._tedious.TYPES.VarBinary, length: Infinity };
334
+ case "boolean":
335
+ return { type: this._tedious.TYPES.Bit };
336
+ case "datetime":
337
+ return { type: this._tedious.TYPES.DateTime2 };
338
+ case "date":
339
+ return { type: this._tedious.TYPES.Date };
340
+ case "time":
341
+ return { type: this._tedious.TYPES.Time };
342
+ case "uuid":
343
+ return { type: this._tedious.TYPES.UniqueIdentifier };
344
+ default:
345
+ throw new SdError(`지원하지 않는 DataType: ${JSON.stringify(dataType)}`);
346
+ }
376
347
  }
377
- if (typeof value === "number") {
378
- return Number.isInteger(value) ? this._tedious.TYPES.BigInt : this._tedious.TYPES.Decimal;
348
+ /**
349
+ * 값의 타입을 추론하여 Tedious 데이터 타입을 반환한다
350
+ *
351
+ * @param value - 타입을 추론할 값 (null/undefined 전달 시 오류 발생)
352
+ * @throws null/undefined 전달 시 오류
353
+ */
354
+ _guessTediousType(value) {
355
+ if (value == null) {
356
+ throw new SdError("_guessTediousType: null/undefined 값은 지원하지 않습니다.");
357
+ }
358
+ if (typeof value === "string") {
359
+ return this._tedious.TYPES.NVarChar;
360
+ }
361
+ if (typeof value === "number") {
362
+ return Number.isInteger(value) ? this._tedious.TYPES.BigInt : this._tedious.TYPES.Decimal;
363
+ }
364
+ if (typeof value === "boolean")
365
+ return this._tedious.TYPES.Bit;
366
+ if (value instanceof DateTime)
367
+ return this._tedious.TYPES.DateTime2;
368
+ if (value instanceof DateOnly)
369
+ return this._tedious.TYPES.Date;
370
+ if (value instanceof Time)
371
+ return this._tedious.TYPES.Time;
372
+ if (value instanceof Uuid)
373
+ return this._tedious.TYPES.UniqueIdentifier;
374
+ if (value instanceof Uint8Array)
375
+ return this._tedious.TYPES.VarBinary;
376
+ throw new SdError(`알 수 없는 값 타입: ${typeof value}`);
379
377
  }
380
- if (typeof value === "boolean") return this._tedious.TYPES.Bit;
381
- if (value instanceof DateTime) return this._tedious.TYPES.DateTime2;
382
- if (value instanceof DateOnly) return this._tedious.TYPES.Date;
383
- if (value instanceof Time) return this._tedious.TYPES.Time;
384
- if (value instanceof Uuid) return this._tedious.TYPES.UniqueIdentifier;
385
- if (value instanceof Uint8Array) return this._tedious.TYPES.VarBinary;
386
- throw new SdError(`Unknown value type: ${typeof value}`);
387
- }
388
378
  }
389
- export {
390
- MssqlDbConn
391
- };
392
- //# sourceMappingURL=mssql-db-conn.js.map
379
+ //# sourceMappingURL=mssql-db-conn.js.map