@nextlyhq/adapter-mysql 0.0.2-alpha.72 → 0.0.2-alpha.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +231 -80
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +75 -4
- package/dist/index.d.ts +75 -4
- package/dist/index.mjs +232 -81
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -168,6 +168,16 @@ async function returnTransactionConnection(connection, rollbackFailed, restore)
|
|
|
168
168
|
else connection.destroy();
|
|
169
169
|
}
|
|
170
170
|
/**
|
|
171
|
+
* mysql2 accepts only `local`, `Z` and `±HH:MM` spellings for its driver
|
|
172
|
+
* zone, and the ones that resolve to UTC are exactly these. `local` resolves
|
|
173
|
+
* to the Node process's own zone, so it agrees with a UTC session only on a
|
|
174
|
+
* UTC host.
|
|
175
|
+
*/
|
|
176
|
+
function isUtcDriverZone(zone) {
|
|
177
|
+
if (zone === "local") return (/* @__PURE__ */ new Date()).getTimezoneOffset() === 0;
|
|
178
|
+
return zone === "Z" || zone === "+00:00" || zone === "-00:00";
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
171
181
|
* Package version
|
|
172
182
|
*/
|
|
173
183
|
const VERSION = "0.1.0";
|
|
@@ -214,11 +224,19 @@ const MYSQL_ERROR_CODES = {
|
|
|
214
224
|
1146: "query",
|
|
215
225
|
1054: "query"
|
|
216
226
|
};
|
|
227
|
+
/** ER_LOCK_DEADLOCK: the transaction lost a race, and running it again may succeed. */
|
|
228
|
+
const DEADLOCK = 1213;
|
|
217
229
|
/**
|
|
218
|
-
*
|
|
230
|
+
* The MySQL error number an error carries: its own, or that of the driver
|
|
231
|
+
* error it wraps, as a classified or a Drizzle query error does.
|
|
219
232
|
*/
|
|
220
|
-
function
|
|
221
|
-
|
|
233
|
+
function errnoOf(error) {
|
|
234
|
+
for (let at = error, hops = 0; hops < 4; hops++) {
|
|
235
|
+
if (typeof at !== "object" || at === null) return void 0;
|
|
236
|
+
const errno = Reflect.get(at, "errno");
|
|
237
|
+
if (typeof errno === "number") return errno;
|
|
238
|
+
at = Reflect.get(at, "cause");
|
|
239
|
+
}
|
|
222
240
|
}
|
|
223
241
|
/**
|
|
224
242
|
* MySQL database adapter for Nextly.
|
|
@@ -259,6 +277,8 @@ var MySqlAdapter = class extends _nextlyhq_adapter_drizzle.DrizzleAdapter {
|
|
|
259
277
|
* Connection pool instance.
|
|
260
278
|
*/
|
|
261
279
|
pool = null;
|
|
280
|
+
/** The `withSession` calls running, each on a connection of its own, for `disconnect` to wait for. */
|
|
281
|
+
sessions = /* @__PURE__ */ new Set();
|
|
262
282
|
/**
|
|
263
283
|
* Connection state flag.
|
|
264
284
|
*/
|
|
@@ -268,6 +288,7 @@ var MySqlAdapter = class extends _nextlyhq_adapter_drizzle.DrizzleAdapter {
|
|
|
268
288
|
* string at connect. Undefined until then, which callers treat as not known.
|
|
269
289
|
*/
|
|
270
290
|
sharedRowLock;
|
|
291
|
+
functionalIndexes;
|
|
271
292
|
/**
|
|
272
293
|
* Creates a new MySQL adapter instance.
|
|
273
294
|
*
|
|
@@ -291,15 +312,22 @@ var MySqlAdapter = class extends _nextlyhq_adapter_drizzle.DrizzleAdapter {
|
|
|
291
312
|
async connect() {
|
|
292
313
|
if (this.connected && this.pool) return;
|
|
293
314
|
try {
|
|
315
|
+
this.warnOnDriverZoneDisagreement();
|
|
294
316
|
const poolConfig = this.buildPoolConfig();
|
|
295
317
|
const pool = mysql2_promise.default.createPool(poolConfig);
|
|
318
|
+
pool.pool.on("connection", (connection) => {
|
|
319
|
+
connection.query("SET SESSION time_zone = '+00:00'", (error) => {
|
|
320
|
+
if (error) connection.destroy();
|
|
321
|
+
});
|
|
322
|
+
});
|
|
296
323
|
boundPoolWait(pool.pool, poolConfig.connectTimeout ?? 0);
|
|
297
324
|
this.pool = pool;
|
|
298
325
|
const connection = await this.pool.getConnection();
|
|
299
326
|
try {
|
|
300
327
|
await connection.query("SELECT 1");
|
|
301
|
-
const { variant } = await (0, _nextlyhq_adapter_drizzle_version_check.checkDialectVersion)(connection, "mysql", { onWarning: (msg) => this.config.logger?.warn?.(msg) });
|
|
328
|
+
const { variant, functionalIndexes } = await (0, _nextlyhq_adapter_drizzle_version_check.checkDialectVersion)(connection, "mysql", { onWarning: (msg) => this.config.logger?.warn?.(msg) });
|
|
302
329
|
this.sharedRowLock = (0, _nextlyhq_adapter_drizzle_version_check.acceptsForShare)(variant);
|
|
330
|
+
this.functionalIndexes = functionalIndexes;
|
|
303
331
|
this.connected = true;
|
|
304
332
|
if (this.config.logger?.info) this.config.logger.info("MySQL connection established", {
|
|
305
333
|
host: this.config.host ?? "from URL",
|
|
@@ -322,7 +350,8 @@ var MySqlAdapter = class extends _nextlyhq_adapter_drizzle.DrizzleAdapter {
|
|
|
322
350
|
*
|
|
323
351
|
* @remarks
|
|
324
352
|
* This method is idempotent - calling it multiple times is safe.
|
|
325
|
-
* It waits for all connections to be released before shutting down
|
|
353
|
+
* It waits for all connections to be released before shutting down,
|
|
354
|
+
* including each running `withSession`'s connection of its own.
|
|
326
355
|
*/
|
|
327
356
|
async disconnect() {
|
|
328
357
|
const pool = this.pool;
|
|
@@ -331,6 +360,7 @@ var MySqlAdapter = class extends _nextlyhq_adapter_drizzle.DrizzleAdapter {
|
|
|
331
360
|
this.drizzleByRelations = /* @__PURE__ */ new WeakMap();
|
|
332
361
|
if (!pool) return;
|
|
333
362
|
try {
|
|
363
|
+
await Promise.allSettled([...this.sessions]);
|
|
334
364
|
await pool.end();
|
|
335
365
|
if (this.config.logger?.info) this.config.logger.info("MySQL connection closed");
|
|
336
366
|
} finally {
|
|
@@ -408,54 +438,131 @@ var MySqlAdapter = class extends _nextlyhq_adapter_drizzle.DrizzleAdapter {
|
|
|
408
438
|
*
|
|
409
439
|
* Note: Savepoints are disabled in this adapter for safety due to
|
|
410
440
|
* MySQL's quirks with nested transactions.
|
|
441
|
+
*
|
|
442
|
+
* A call made inside another transaction's work therefore joins it flat,
|
|
443
|
+
* on its connection: its statements are the outer's. Its failure cannot be
|
|
444
|
+
* undone alone, so it fails the whole transaction, even when the outer
|
|
445
|
+
* catches it: the outer's COMMIT is refused, it rolls back, and it rejects
|
|
446
|
+
* with the error that failed the joined call; any later joined call fails
|
|
447
|
+
* with that error at once. A joined call keeps the outer's options and is
|
|
448
|
+
* never retried itself. `retryWhen` is asked first, of every error that
|
|
449
|
+
* ends an attempt, application ones included.
|
|
411
450
|
*/
|
|
412
|
-
|
|
413
|
-
return this.
|
|
451
|
+
transaction(work, options) {
|
|
452
|
+
return this.openOrJoin(work, options, {
|
|
453
|
+
run: (_attempt, openedAt) => this.runAttempt(work, options, openedAt),
|
|
454
|
+
retryable: (error) => errnoOf(error) === DEADLOCK,
|
|
455
|
+
describe: (error) => {
|
|
456
|
+
const errno = errnoOf(error);
|
|
457
|
+
return {
|
|
458
|
+
label: errno === DEADLOCK ? "deadlock" : "a retryable error",
|
|
459
|
+
detail: { errno }
|
|
460
|
+
};
|
|
461
|
+
},
|
|
462
|
+
logger: this.config.logger
|
|
463
|
+
});
|
|
414
464
|
}
|
|
415
|
-
/**
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
465
|
+
/**
|
|
466
|
+
* Runs `work` on a connection of its own, opened for it with the pool's
|
|
467
|
+
* connection settings, outside a transaction, each statement committing as
|
|
468
|
+
* it runs.
|
|
469
|
+
*
|
|
470
|
+
* @remarks
|
|
471
|
+
* Not a pooled connection: on a server whose sessions start with autocommit
|
|
472
|
+
* off, one can hold a transaction an earlier caller left open, and turning
|
|
473
|
+
* autocommit on would commit that caller's writes. A new connection holds
|
|
474
|
+
* nothing. It does not count against `pool.max`.
|
|
475
|
+
*
|
|
476
|
+
* Each statement commits as it runs, whatever the server's own autocommit
|
|
477
|
+
* default. With `strictSqlMode` the session runs in strict mode, as a
|
|
478
|
+
* transaction given the same option does, so a statement that would cut a
|
|
479
|
+
* value short fails and changes nothing. The connection is closed
|
|
480
|
+
* afterwards, whether `work` finished or threw, so whatever `work` set on
|
|
481
|
+
* its session (a temporary table, a session variable, a lock) ends with it.
|
|
482
|
+
*/
|
|
483
|
+
async withSession(work, options) {
|
|
484
|
+
this.refuseSessionInTransaction();
|
|
485
|
+
this.ensurePool();
|
|
486
|
+
const running = this.runSession(work, options);
|
|
487
|
+
this.sessions.add(running);
|
|
488
|
+
try {
|
|
489
|
+
return await running;
|
|
490
|
+
} finally {
|
|
491
|
+
this.sessions.delete(running);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
/** `withSession`'s work, on a connection it opens and closes. */
|
|
495
|
+
async runSession(work, options) {
|
|
496
|
+
let connection;
|
|
497
|
+
try {
|
|
498
|
+
connection = await mysql2_promise.default.createConnection(this.buildConnectionConfig());
|
|
499
|
+
} catch (error) {
|
|
500
|
+
throw this.classifyError(error);
|
|
501
|
+
}
|
|
502
|
+
try {
|
|
426
503
|
try {
|
|
427
|
-
await
|
|
428
|
-
|
|
429
|
-
await
|
|
430
|
-
if (this.config.logger?.debug) {
|
|
431
|
-
const durationMs = Date.now() - startTime;
|
|
432
|
-
this.config.logger.debug("Transaction committed", {
|
|
433
|
-
attempt,
|
|
434
|
-
durationMs
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
return result;
|
|
504
|
+
await connection.query("SET SESSION autocommit = 1");
|
|
505
|
+
await connection.query("SET SESSION time_zone = '+00:00'");
|
|
506
|
+
if (options?.strictSqlMode) await this.enterStrictMode(connection, {});
|
|
438
507
|
} catch (error) {
|
|
439
|
-
await connection.query("ROLLBACK").catch(() => {
|
|
440
|
-
rollbackFailed = true;
|
|
441
|
-
});
|
|
442
|
-
lastError = error;
|
|
443
|
-
if ((0, _nextlyhq_adapter_drizzle_types.isApplicationError)(error)) throw error;
|
|
444
|
-
const mysqlError = error;
|
|
445
|
-
if (mysqlError.errno === 1213 && attempt < maxAttempts) {
|
|
446
|
-
if (this.config.logger?.warn) this.config.logger.warn(`Transaction failed with deadlock, retrying (${attempt}/${maxAttempts})`, {
|
|
447
|
-
errno: mysqlError.errno,
|
|
448
|
-
attempt
|
|
449
|
-
});
|
|
450
|
-
await delay(retryDelayMs * attempt);
|
|
451
|
-
continue;
|
|
452
|
-
}
|
|
453
508
|
throw this.classifyError(error);
|
|
454
|
-
} finally {
|
|
455
|
-
await returnTransactionConnection(connection, rollbackFailed, restore);
|
|
456
509
|
}
|
|
510
|
+
return await work({ execute: async (statement, params = []) => {
|
|
511
|
+
const startTime = Date.now();
|
|
512
|
+
try {
|
|
513
|
+
const [rows] = await connection.query(statement, params);
|
|
514
|
+
if (this.config.logger?.query) this.config.logger.query(statement, params, Date.now() - startTime);
|
|
515
|
+
return rows;
|
|
516
|
+
} catch (error) {
|
|
517
|
+
throw this.classifyError(error, statement);
|
|
518
|
+
}
|
|
519
|
+
} });
|
|
520
|
+
} finally {
|
|
521
|
+
connection.destroy();
|
|
457
522
|
}
|
|
458
|
-
|
|
523
|
+
}
|
|
524
|
+
/** One attempt at an outermost transaction, on a connection of its own. */
|
|
525
|
+
async runAttempt(work, options, openedAt) {
|
|
526
|
+
const pool = this.ensurePool();
|
|
527
|
+
this.notePoolAccess();
|
|
528
|
+
const connection = await pool.getConnection();
|
|
529
|
+
let rollbackFailed = false;
|
|
530
|
+
const restore = {};
|
|
531
|
+
const settled = await this.settleOutermost({
|
|
532
|
+
context: this.createTransactionContext(connection),
|
|
533
|
+
join: this.joinSteps(connection),
|
|
534
|
+
openedAt,
|
|
535
|
+
begin: () => this.beginTransaction(connection, options, restore),
|
|
536
|
+
commit: async () => {
|
|
537
|
+
await connection.query("COMMIT");
|
|
538
|
+
},
|
|
539
|
+
rollback: async () => {
|
|
540
|
+
await connection.query("ROLLBACK").catch((rollbackError) => {
|
|
541
|
+
rollbackFailed = true;
|
|
542
|
+
throw rollbackError;
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
}, work, options);
|
|
546
|
+
await returnTransactionConnection(connection, rollbackFailed, restore);
|
|
547
|
+
return settled;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* How a call made inside a transaction on `connection` joins it: flat, on
|
|
551
|
+
* the same connection, with nothing to send. Any failure inside it fails
|
|
552
|
+
* the whole transaction, since no savepoint can undo the part alone.
|
|
553
|
+
*/
|
|
554
|
+
joinSteps(connection) {
|
|
555
|
+
const callbackConnection = connection.connection;
|
|
556
|
+
return this.joinStepsOn(() => this.createTransactionContext(connection), (relations) => relations ? (0, drizzle_orm_mysql2.drizzle)({
|
|
557
|
+
client: callbackConnection,
|
|
558
|
+
relations
|
|
559
|
+
}) : (0, drizzle_orm_mysql2.drizzle)({ client: callbackConnection }), (context) => ({
|
|
560
|
+
context,
|
|
561
|
+
begin() {},
|
|
562
|
+
commit() {},
|
|
563
|
+
rollback() {},
|
|
564
|
+
dooms: () => true
|
|
565
|
+
}));
|
|
459
566
|
}
|
|
460
567
|
/**
|
|
461
568
|
* Get MySQL database capabilities.
|
|
@@ -482,7 +589,8 @@ var MySqlAdapter = class extends _nextlyhq_adapter_drizzle.DrizzleAdapter {
|
|
|
482
589
|
supportsOnConflict: true,
|
|
483
590
|
maxParamsPerQuery: 65535,
|
|
484
591
|
maxIdentifierLength: 64,
|
|
485
|
-
sharedRowLock: this.sharedRowLock
|
|
592
|
+
sharedRowLock: this.sharedRowLock,
|
|
593
|
+
functionalIndexes: this.functionalIndexes
|
|
486
594
|
};
|
|
487
595
|
}
|
|
488
596
|
/**
|
|
@@ -565,51 +673,86 @@ var MySqlAdapter = class extends _nextlyhq_adapter_drizzle.DrizzleAdapter {
|
|
|
565
673
|
"execute",
|
|
566
674
|
"getConnection"
|
|
567
675
|
]);
|
|
568
|
-
return this.
|
|
569
|
-
const connection = await
|
|
676
|
+
return this.joiningHandle(onClient(callbackPool), async () => {
|
|
677
|
+
const connection = await pool.getConnection();
|
|
570
678
|
return {
|
|
571
679
|
drizzle: onClient(connection.connection),
|
|
572
680
|
rollback: () => connection.query("ROLLBACK"),
|
|
573
681
|
release: (dirty) => {
|
|
574
682
|
if (dirty) connection.destroy();
|
|
575
683
|
else connection.release();
|
|
576
|
-
}
|
|
684
|
+
},
|
|
685
|
+
join: this.joinSteps(connection)
|
|
577
686
|
};
|
|
578
|
-
})
|
|
687
|
+
}, relations);
|
|
688
|
+
}
|
|
689
|
+
/**
|
|
690
|
+
* Warns when a caller's configured driver zone does not agree with the
|
|
691
|
+
* pinned UTC session.
|
|
692
|
+
*
|
|
693
|
+
* mysql2's driver-level `timezone` decides how it parses the date strings
|
|
694
|
+
* the pinned session answers with and how it binds raw Date parameters, so
|
|
695
|
+
* a non-UTC spelling there would shift values a round-trip fails to
|
|
696
|
+
* cancel. The configuration is aligned to the pin (`buildConnectionConfig`
|
|
697
|
+
* sets UTC unconditionally, for pooled and standalone connections alike),
|
|
698
|
+
* never rewritten silently: the caller configured a reading, and this is
|
|
699
|
+
* where that reading is named as lost. Runs from `connect`, once per pool
|
|
700
|
+
* build — the configuration cannot change between calls.
|
|
701
|
+
*/
|
|
702
|
+
warnOnDriverZoneDisagreement() {
|
|
703
|
+
const requestedZone = this.config.timezone ?? "local";
|
|
704
|
+
if (isUtcDriverZone(requestedZone)) return;
|
|
705
|
+
this.config.logger?.warn?.(`Driver timezone "${requestedZone}" is not UTC; it is aligned to the pinned UTC session and no longer shifts reads or writes.`);
|
|
579
706
|
}
|
|
580
707
|
/**
|
|
581
708
|
* Builds mysql2 Pool configuration from adapter config.
|
|
582
709
|
*/
|
|
583
710
|
buildPoolConfig() {
|
|
584
|
-
const config =
|
|
585
|
-
if (this.config.url) config.uri = this.config.url;
|
|
586
|
-
else {
|
|
587
|
-
if (this.config.host) config.host = this.config.host;
|
|
588
|
-
if (this.config.port) config.port = this.config.port;
|
|
589
|
-
if (this.config.database) config.database = this.config.database;
|
|
590
|
-
if (this.config.user) config.user = this.config.user;
|
|
591
|
-
if (this.config.password) config.password = this.config.password;
|
|
592
|
-
}
|
|
711
|
+
const config = this.buildConnectionConfig();
|
|
593
712
|
config.connectionLimit = this.config.pool?.max ?? DEFAULT_POOL_CONFIG.max;
|
|
594
713
|
config.idleTimeout = this.config.pool?.idleTimeoutMs ?? DEFAULT_POOL_CONFIG.idleTimeoutMs;
|
|
595
|
-
config.connectTimeout = this.config.pool?.connectionTimeoutMs ?? DEFAULT_POOL_CONFIG.connectionTimeoutMs;
|
|
596
714
|
config.waitForConnections = true;
|
|
597
715
|
config.queueLimit = 0;
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
if (this.config.
|
|
716
|
+
return config;
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Builds the settings every connection opens with, pooled or not, from
|
|
720
|
+
* adapter config.
|
|
721
|
+
*/
|
|
722
|
+
buildConnectionConfig() {
|
|
723
|
+
const config = this.buildAddressConfig();
|
|
724
|
+
config.connectTimeout = this.config.pool?.connectionTimeoutMs ?? DEFAULT_POOL_CONFIG.connectionTimeoutMs;
|
|
725
|
+
if (this.config.ssl) config.ssl = this.buildSslConfig(this.config.ssl);
|
|
726
|
+
config.timezone = "Z";
|
|
608
727
|
if (this.config.charset) config.charset = this.config.charset;
|
|
609
728
|
config.multipleStatements = false;
|
|
610
729
|
config.dateStrings = false;
|
|
611
730
|
return config;
|
|
612
731
|
}
|
|
732
|
+
/** Where to connect: the connection string, or the explicit options. */
|
|
733
|
+
buildAddressConfig() {
|
|
734
|
+
if (this.config.url) return { uri: this.config.url };
|
|
735
|
+
const { host, port, database, user, password } = this.config;
|
|
736
|
+
const config = {
|
|
737
|
+
host,
|
|
738
|
+
port,
|
|
739
|
+
database,
|
|
740
|
+
user,
|
|
741
|
+
password
|
|
742
|
+
};
|
|
743
|
+
for (const key of Object.keys(config)) if (!config[key]) delete config[key];
|
|
744
|
+
return config;
|
|
745
|
+
}
|
|
746
|
+
/** mysql2's `ssl` option for the adapter's `ssl` setting. */
|
|
747
|
+
buildSslConfig(ssl) {
|
|
748
|
+
if (typeof ssl === "boolean") return ssl ? {} : void 0;
|
|
749
|
+
return {
|
|
750
|
+
rejectUnauthorized: ssl.rejectUnauthorized,
|
|
751
|
+
ca: ssl.ca,
|
|
752
|
+
cert: ssl.cert,
|
|
753
|
+
key: ssl.key
|
|
754
|
+
};
|
|
755
|
+
}
|
|
613
756
|
/**
|
|
614
757
|
* Begins a transaction with the specified options, recording in `changed`
|
|
615
758
|
* each session setting it changes, as it changes it, for `restoreSession`
|
|
@@ -634,12 +777,20 @@ var MySqlAdapter = class extends _nextlyhq_adapter_drizzle.DrizzleAdapter {
|
|
|
634
777
|
await connection.query(`SET SESSION innodb_lock_wait_timeout = ${timeoutSeconds}`);
|
|
635
778
|
changed.lockWaitTimeout = Number.isInteger(previous) ? previous : null;
|
|
636
779
|
}
|
|
637
|
-
if (options?.strictSqlMode)
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
780
|
+
if (options?.strictSqlMode) await this.enterStrictMode(connection, changed);
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Strict mode for the rest of this connection's session: an INSERT, UPDATE
|
|
784
|
+
* or ALTER that would cut a string to its column's length, or clamp a
|
|
785
|
+
* number to its range, fails instead of applying with a warning. Added to
|
|
786
|
+
* the session's own mode, so every other flag it had still holds, and
|
|
787
|
+
* recorded in `changed` for `restoreSession` to put back.
|
|
788
|
+
*/
|
|
789
|
+
async enterStrictMode(connection, changed) {
|
|
790
|
+
const [rows] = await connection.query("SELECT @@SESSION.sql_mode AS mode");
|
|
791
|
+
const previous = rows[0]?.mode;
|
|
792
|
+
changed.sqlMode = typeof previous === "string" ? previous : null;
|
|
793
|
+
await connection.query("SET SESSION sql_mode = TRIM(BOTH ',' FROM CONCAT(@@SESSION.sql_mode, ',STRICT_ALL_TABLES'))");
|
|
643
794
|
}
|
|
644
795
|
/**
|
|
645
796
|
* Creates a TransactionContext for the given connection.
|
|
@@ -835,7 +986,8 @@ var MySqlAdapter = class extends _nextlyhq_adapter_drizzle.DrizzleAdapter {
|
|
|
835
986
|
await connection.query(`SELECT ${idColumn} FROM ${this.escapeIdentifier(table)} WHERE ${idColumn} = ? FOR UPDATE`, [id]);
|
|
836
987
|
},
|
|
837
988
|
insert: async (table, data, options) => {
|
|
838
|
-
const
|
|
989
|
+
const insertTableObj = this.resolvedTableObject(table);
|
|
990
|
+
const mapped = this.mapRowToRawSql(insertTableObj, data);
|
|
839
991
|
const columns = Object.keys(mapped);
|
|
840
992
|
const values = Object.values(mapped);
|
|
841
993
|
const placeholders = this.buildPlaceholders(values.length, 0);
|
|
@@ -843,7 +995,6 @@ var MySqlAdapter = class extends _nextlyhq_adapter_drizzle.DrizzleAdapter {
|
|
|
843
995
|
const [result] = await connection.query(sql, values);
|
|
844
996
|
const ret = options?.returning;
|
|
845
997
|
if (Array.isArray(ret) && ret.length === 0) return;
|
|
846
|
-
const insertTableObj = this.getTableObject(table);
|
|
847
998
|
const aliases = this.dateWallClockAliases(insertTableObj, ret ?? "*");
|
|
848
999
|
const spelled = aliases.map((a) => `DATE_FORMAT(${this.escapeIdentifier(a.sqlName)}, '%Y-%m-%dT%H:%i:%s.%f') AS ${this.escapeIdentifier(a.alias)}`).join(", ");
|
|
849
1000
|
const projected = !ret || ret === "*" ? "*" : this.mapColumnNamesToSql(insertTableObj, ret).map((c) => this.escapeIdentifier(c)).join(", ");
|
|
@@ -861,7 +1012,7 @@ var MySqlAdapter = class extends _nextlyhq_adapter_drizzle.DrizzleAdapter {
|
|
|
861
1012
|
if (data.length === 0) return [];
|
|
862
1013
|
const retMany = options?.returning;
|
|
863
1014
|
const skipReread = Array.isArray(retMany) && retMany.length === 0;
|
|
864
|
-
const tableObj = this.
|
|
1015
|
+
const tableObj = this.resolvedTableObject(table);
|
|
865
1016
|
const mappedRecords = data.map((r) => this.mapRowToRawSql(tableObj, r));
|
|
866
1017
|
const columns = Object.keys(mappedRecords[0]);
|
|
867
1018
|
const allValues = [];
|