@atscript/db-mysql 0.1.168 → 0.1.170

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.d.cts CHANGED
@@ -116,6 +116,7 @@ declare class MysqlAdapter extends BaseDbAdapter {
116
116
  private static readonly NATIVE_DEFAULT_FNS;
117
117
  private _engine;
118
118
  private _charset;
119
+ /** `@db.mysql.collate` on the table; none → the charset's default (see `mysqlDefaultCollation`). */
119
120
  private _collation;
120
121
  private _autoIncrementStart?;
121
122
  private _incrementFields;
@@ -132,6 +133,11 @@ declare class MysqlAdapter extends BaseDbAdapter {
132
133
  */
133
134
  private _epochAfterRekey;
134
135
  private _onUpdateFields;
136
+ /** Field path → `@db.mysql.charset` of the column. */
137
+ private _charsetFields;
138
+ private _space?;
139
+ /** Memo of {@link _keyTableCharsets} — it also makes its warning fire once. */
140
+ private _keyTableCharsetsMemo?;
135
141
  /** Whether the connected MySQL instance supports native VECTOR type (MySQL 9.0+). */
136
142
  private _supportsVector;
137
143
  /** Vector fields: physical field name → { dimensions, similarity, indexName }. */
@@ -141,6 +147,7 @@ declare class MysqlAdapter extends BaseDbAdapter {
141
147
  private _replaceColumnsMemo?;
142
148
  private _fulltextMemo?;
143
149
  private _searchIndexesMemo?;
150
+ private _incrementPkMemo?;
144
151
  /**
145
152
  * Schema name for INFORMATION_SCHEMA queries — `@db.schema` of the bound
146
153
  * table, or `null` (→ `DATABASE()`, the pool's database) when the table
@@ -260,6 +267,11 @@ declare class MysqlAdapter extends BaseDbAdapter {
260
267
  private _uniformIdGroup;
261
268
  /** Physical column of the single-column AUTO_INCREMENT primary key, if the table has one. */
262
269
  private _autoIncrementPk;
270
+ /**
271
+ * Physical column of the primary key's `@db.default.increment` part (if any)
272
+ * and whether the key is composite — computed once per table.
273
+ */
274
+ private _incrementPk;
263
275
  /**
264
276
  * Splits `rows` into runs that each map to ONE statement with a derivable
265
277
  * id sequence. MySQL reports only the first GENERATED id of a statement, and
@@ -298,6 +310,15 @@ declare class MysqlAdapter extends BaseDbAdapter {
298
310
  * count — mode 2, the 8.0 default), explicit rows keep their own value.
299
311
  */
300
312
  private _groupInsertedIds;
313
+ /**
314
+ * The inserted id of `row` (see `_resolveInsertedId`). For a COMPOSITE key
315
+ * with an AUTO_INCREMENT part, `partId` is what the statement generated for
316
+ * that part — pass it only when exact (a ONE-row INSERT); a row carrying the
317
+ * part keeps its own value. An explicit `0` in the part counts as absent:
318
+ * MySQL generates a value for it (unless `NO_AUTO_VALUE_ON_ZERO`), so only
319
+ * `partId` knows it — without that the id is `undefined`, never a wrong `0`.
320
+ */
321
+ private _insertedIdOf;
301
322
  supportsInsertIgnore(): boolean;
302
323
  /**
303
324
  * Standalone (no caller transaction): per chunk ONE optimistic multi-row
@@ -418,6 +439,22 @@ declare class MysqlAdapter extends BaseDbAdapter {
418
439
  deleteMany(filter: FilterExpr, opts?: TDbDeleteManyOptions): Promise<TDbDeleteResult>;
419
440
  prepareTypeMapper(): Promise<void>;
420
441
  ensureTable(opts?: TEnsureTableOptions): Promise<void>;
442
+ /** The table's collation: `@db.mysql.collate`, else the charset's default one (`utf8mb4_unicode_ci` for `utf8mb4`). */
443
+ private _tableCollation;
444
+ /**
445
+ * Foreign-key column path → the referenced table's character set and
446
+ * collation, where they differ from this table's (see
447
+ * `mysqlColumnCharset`). Warns about a foreign-key column whose own
448
+ * `@db.mysql.charset` / collation is replaced by the referenced column's.
449
+ */
450
+ private _keyTableCharsets;
451
+ private _buildKeyTableCharsets;
452
+ /**
453
+ * The key-length prefix an index needs on `field`'s column: a function of
454
+ * its MAPPED type and its character set (`mysqlColumnCharset`, else the
455
+ * table's).
456
+ */
457
+ private _indexPrefix;
421
458
  /** The CREATE TABLE options (engine/charset/collation/increment/ON UPDATE/type mapper). */
422
459
  private _tableOptions;
423
460
  /** The shared column-definition context for ADD/MODIFY statements. */
@@ -453,6 +490,58 @@ declare class MysqlAdapter extends BaseDbAdapter {
453
490
  /** Live columns of `tableName`, read through `exec` (a held connection, or the pool). */
454
491
  private _readColumns;
455
492
  syncColumns(diff: TColumnDiff): Promise<TSyncColumnResult>;
493
+ /**
494
+ * Runs `fn` (the MODIFYs of `fields`) with the live foreign keys over those
495
+ * columns dropped — this table's own and those of any table referencing
496
+ * them, its own included — and re-creates them, as they were, after: also
497
+ * when `fn` throws. Nothing is dropped when a constraint could not be
498
+ * re-created over the new types (see {@link _liftable}): MySQL then refuses
499
+ * the MODIFY as it always did. A constraint that cannot be re-created is
500
+ * named, with its DDL, in the error (after `fn`'s own).
501
+ */
502
+ private _withForeignKeysLifted;
503
+ /**
504
+ * Re-creates `fks` (dropped by {@link _withForeignKeysLifted}) — one
505
+ * `ALTER TABLE` per table, with `foreign_key_checks` off on this connection
506
+ * so MySQL adds them in place instead of rebuilding the table (the rows
507
+ * met them before the change). A table whose statement fails has its
508
+ * constraints re-tried one by one. Returns those that could not be
509
+ * re-created.
510
+ */
511
+ private _restoreForeignKeys;
512
+ /**
513
+ * Whether every constraint of `fks` can be re-created once `fields` have
514
+ * their new types: each column pair of a constraint that the change touches
515
+ * stays compatible — the new type against the other side's live column (or
516
+ * its new type, on this table): integers of the same type and signedness,
517
+ * `CHAR` / `VARCHAR` either way with the same collation, anything else the
518
+ * same type. Otherwise nothing is lifted (and MySQL refuses the change, as
519
+ * it did before foreign keys were lifted) — a dropped constraint must
520
+ * never be lost to a column outside this run.
521
+ */
522
+ private _liftable;
523
+ /**
524
+ * The collation each of `fields` (string columns) has after its MODIFY:
525
+ * the definition's own `COLLATE`, else the default of its `CHARACTER SET`,
526
+ * else the table's.
527
+ */
528
+ private _newCollations;
529
+ /**
530
+ * The live foreign keys over any of `columns` of this table: its own (by
531
+ * their columns) and those referencing them (by the referenced columns),
532
+ * each with every column, in key order.
533
+ */
534
+ private _foreignKeysOver;
535
+ /**
536
+ * Before `fields` are modified: drops the managed indexes that key more of
537
+ * a column than its new type allows — a full key on a column becoming
538
+ * TEXT (ER 1170), or on a VARCHAR growing past the key-part limit (ER
539
+ * 1071). Index sync re-creates them with the prefix the new type needs.
540
+ * Primary keys, FULLTEXT and unmanaged indexes are left alone.
541
+ */
542
+ private _dropIndexesOutgrown;
543
+ /** `DROP INDEX name` on this table (logged). */
544
+ private _dropIndex;
456
545
  recreateTable(): Promise<void>;
457
546
  dropTable(): Promise<void>;
458
547
  copyFromJsonColumn(source: string, targets: readonly TJsonCopyTarget[]): Promise<void>;
@@ -462,6 +551,8 @@ declare class MysqlAdapter extends BaseDbAdapter {
462
551
  dropTableByName(tableName: string): Promise<void>;
463
552
  dropViewByName(viewName: string): Promise<void>;
464
553
  renameTable(oldName: string): Promise<void>;
554
+ /** Keeps the space: {@link typeMapper} asks it which fields a foreign key references. */
555
+ registerSpace(space: DbSpace): void;
465
556
  typeMapper(field: TDbFieldMeta): string;
466
557
  protected _syncIndexes(dryRun: boolean): Promise<TIndexChange[]>;
467
558
  syncForeignKeys(): Promise<TForeignKeyChange[]>;
@@ -469,6 +560,13 @@ declare class MysqlAdapter extends BaseDbAdapter {
469
560
  planForeignKeys(): Promise<TForeignKeyChange[]>;
470
561
  private _syncForeignKeys;
471
562
  dropForeignKeys(fkFieldKeys: string[]): Promise<void>;
563
+ /**
564
+ * Drops a foreign-key constraint over `columns` (in key order), then the
565
+ * index InnoDB created for it: an unnamed constraint gets an index named
566
+ * after its first column, which outlives the constraint — and would block
567
+ * that column from becoming TEXT once it no longer references anything
568
+ * (ER 1170). An index another constraint still needs is kept (ER 1553).
569
+ */
472
570
  private _dropFkConstraint;
473
571
  /** Queries INFORMATION_SCHEMA for existing FK constraints, grouped by constraint name → column names. */
474
572
  private _getExistingFkConstraints;
package/dist/index.d.mts CHANGED
@@ -116,6 +116,7 @@ declare class MysqlAdapter extends BaseDbAdapter {
116
116
  private static readonly NATIVE_DEFAULT_FNS;
117
117
  private _engine;
118
118
  private _charset;
119
+ /** `@db.mysql.collate` on the table; none → the charset's default (see `mysqlDefaultCollation`). */
119
120
  private _collation;
120
121
  private _autoIncrementStart?;
121
122
  private _incrementFields;
@@ -132,6 +133,11 @@ declare class MysqlAdapter extends BaseDbAdapter {
132
133
  */
133
134
  private _epochAfterRekey;
134
135
  private _onUpdateFields;
136
+ /** Field path → `@db.mysql.charset` of the column. */
137
+ private _charsetFields;
138
+ private _space?;
139
+ /** Memo of {@link _keyTableCharsets} — it also makes its warning fire once. */
140
+ private _keyTableCharsetsMemo?;
135
141
  /** Whether the connected MySQL instance supports native VECTOR type (MySQL 9.0+). */
136
142
  private _supportsVector;
137
143
  /** Vector fields: physical field name → { dimensions, similarity, indexName }. */
@@ -141,6 +147,7 @@ declare class MysqlAdapter extends BaseDbAdapter {
141
147
  private _replaceColumnsMemo?;
142
148
  private _fulltextMemo?;
143
149
  private _searchIndexesMemo?;
150
+ private _incrementPkMemo?;
144
151
  /**
145
152
  * Schema name for INFORMATION_SCHEMA queries — `@db.schema` of the bound
146
153
  * table, or `null` (→ `DATABASE()`, the pool's database) when the table
@@ -260,6 +267,11 @@ declare class MysqlAdapter extends BaseDbAdapter {
260
267
  private _uniformIdGroup;
261
268
  /** Physical column of the single-column AUTO_INCREMENT primary key, if the table has one. */
262
269
  private _autoIncrementPk;
270
+ /**
271
+ * Physical column of the primary key's `@db.default.increment` part (if any)
272
+ * and whether the key is composite — computed once per table.
273
+ */
274
+ private _incrementPk;
263
275
  /**
264
276
  * Splits `rows` into runs that each map to ONE statement with a derivable
265
277
  * id sequence. MySQL reports only the first GENERATED id of a statement, and
@@ -298,6 +310,15 @@ declare class MysqlAdapter extends BaseDbAdapter {
298
310
  * count — mode 2, the 8.0 default), explicit rows keep their own value.
299
311
  */
300
312
  private _groupInsertedIds;
313
+ /**
314
+ * The inserted id of `row` (see `_resolveInsertedId`). For a COMPOSITE key
315
+ * with an AUTO_INCREMENT part, `partId` is what the statement generated for
316
+ * that part — pass it only when exact (a ONE-row INSERT); a row carrying the
317
+ * part keeps its own value. An explicit `0` in the part counts as absent:
318
+ * MySQL generates a value for it (unless `NO_AUTO_VALUE_ON_ZERO`), so only
319
+ * `partId` knows it — without that the id is `undefined`, never a wrong `0`.
320
+ */
321
+ private _insertedIdOf;
301
322
  supportsInsertIgnore(): boolean;
302
323
  /**
303
324
  * Standalone (no caller transaction): per chunk ONE optimistic multi-row
@@ -418,6 +439,22 @@ declare class MysqlAdapter extends BaseDbAdapter {
418
439
  deleteMany(filter: FilterExpr, opts?: TDbDeleteManyOptions): Promise<TDbDeleteResult>;
419
440
  prepareTypeMapper(): Promise<void>;
420
441
  ensureTable(opts?: TEnsureTableOptions): Promise<void>;
442
+ /** The table's collation: `@db.mysql.collate`, else the charset's default one (`utf8mb4_unicode_ci` for `utf8mb4`). */
443
+ private _tableCollation;
444
+ /**
445
+ * Foreign-key column path → the referenced table's character set and
446
+ * collation, where they differ from this table's (see
447
+ * `mysqlColumnCharset`). Warns about a foreign-key column whose own
448
+ * `@db.mysql.charset` / collation is replaced by the referenced column's.
449
+ */
450
+ private _keyTableCharsets;
451
+ private _buildKeyTableCharsets;
452
+ /**
453
+ * The key-length prefix an index needs on `field`'s column: a function of
454
+ * its MAPPED type and its character set (`mysqlColumnCharset`, else the
455
+ * table's).
456
+ */
457
+ private _indexPrefix;
421
458
  /** The CREATE TABLE options (engine/charset/collation/increment/ON UPDATE/type mapper). */
422
459
  private _tableOptions;
423
460
  /** The shared column-definition context for ADD/MODIFY statements. */
@@ -453,6 +490,58 @@ declare class MysqlAdapter extends BaseDbAdapter {
453
490
  /** Live columns of `tableName`, read through `exec` (a held connection, or the pool). */
454
491
  private _readColumns;
455
492
  syncColumns(diff: TColumnDiff): Promise<TSyncColumnResult>;
493
+ /**
494
+ * Runs `fn` (the MODIFYs of `fields`) with the live foreign keys over those
495
+ * columns dropped — this table's own and those of any table referencing
496
+ * them, its own included — and re-creates them, as they were, after: also
497
+ * when `fn` throws. Nothing is dropped when a constraint could not be
498
+ * re-created over the new types (see {@link _liftable}): MySQL then refuses
499
+ * the MODIFY as it always did. A constraint that cannot be re-created is
500
+ * named, with its DDL, in the error (after `fn`'s own).
501
+ */
502
+ private _withForeignKeysLifted;
503
+ /**
504
+ * Re-creates `fks` (dropped by {@link _withForeignKeysLifted}) — one
505
+ * `ALTER TABLE` per table, with `foreign_key_checks` off on this connection
506
+ * so MySQL adds them in place instead of rebuilding the table (the rows
507
+ * met them before the change). A table whose statement fails has its
508
+ * constraints re-tried one by one. Returns those that could not be
509
+ * re-created.
510
+ */
511
+ private _restoreForeignKeys;
512
+ /**
513
+ * Whether every constraint of `fks` can be re-created once `fields` have
514
+ * their new types: each column pair of a constraint that the change touches
515
+ * stays compatible — the new type against the other side's live column (or
516
+ * its new type, on this table): integers of the same type and signedness,
517
+ * `CHAR` / `VARCHAR` either way with the same collation, anything else the
518
+ * same type. Otherwise nothing is lifted (and MySQL refuses the change, as
519
+ * it did before foreign keys were lifted) — a dropped constraint must
520
+ * never be lost to a column outside this run.
521
+ */
522
+ private _liftable;
523
+ /**
524
+ * The collation each of `fields` (string columns) has after its MODIFY:
525
+ * the definition's own `COLLATE`, else the default of its `CHARACTER SET`,
526
+ * else the table's.
527
+ */
528
+ private _newCollations;
529
+ /**
530
+ * The live foreign keys over any of `columns` of this table: its own (by
531
+ * their columns) and those referencing them (by the referenced columns),
532
+ * each with every column, in key order.
533
+ */
534
+ private _foreignKeysOver;
535
+ /**
536
+ * Before `fields` are modified: drops the managed indexes that key more of
537
+ * a column than its new type allows — a full key on a column becoming
538
+ * TEXT (ER 1170), or on a VARCHAR growing past the key-part limit (ER
539
+ * 1071). Index sync re-creates them with the prefix the new type needs.
540
+ * Primary keys, FULLTEXT and unmanaged indexes are left alone.
541
+ */
542
+ private _dropIndexesOutgrown;
543
+ /** `DROP INDEX name` on this table (logged). */
544
+ private _dropIndex;
456
545
  recreateTable(): Promise<void>;
457
546
  dropTable(): Promise<void>;
458
547
  copyFromJsonColumn(source: string, targets: readonly TJsonCopyTarget[]): Promise<void>;
@@ -462,6 +551,8 @@ declare class MysqlAdapter extends BaseDbAdapter {
462
551
  dropTableByName(tableName: string): Promise<void>;
463
552
  dropViewByName(viewName: string): Promise<void>;
464
553
  renameTable(oldName: string): Promise<void>;
554
+ /** Keeps the space: {@link typeMapper} asks it which fields a foreign key references. */
555
+ registerSpace(space: DbSpace): void;
465
556
  typeMapper(field: TDbFieldMeta): string;
466
557
  protected _syncIndexes(dryRun: boolean): Promise<TIndexChange[]>;
467
558
  syncForeignKeys(): Promise<TForeignKeyChange[]>;
@@ -469,6 +560,13 @@ declare class MysqlAdapter extends BaseDbAdapter {
469
560
  planForeignKeys(): Promise<TForeignKeyChange[]>;
470
561
  private _syncForeignKeys;
471
562
  dropForeignKeys(fkFieldKeys: string[]): Promise<void>;
563
+ /**
564
+ * Drops a foreign-key constraint over `columns` (in key order), then the
565
+ * index InnoDB created for it: an unnamed constraint gets an index named
566
+ * after its first column, which outlives the constraint — and would block
567
+ * that column from becoming TEXT once it no longer references anything
568
+ * (ER 1170). An index another constraint still needs is kept (ER 1553).
569
+ */
472
570
  private _dropFkConstraint;
473
571
  /** Queries INFORMATION_SCHEMA for existing FK constraints, grouped by constraint name → column names. */
474
572
  private _getExistingFkConstraints;