sqlmorpheus 0.2.1 → 0.2.2

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.mjs CHANGED
@@ -21,42 +21,65 @@ var LoggerClass = class {
21
21
  };
22
22
  var Logger = new LoggerClass();
23
23
 
24
- // src/lib/tableInfo/TableInfo.ts
25
- var TABLE_INFO_PROPERTY_NAME = Symbol("tableInfo");
26
- function getTableInfo(table) {
27
- let metadata = table[Symbol.metadata] ?? table.prototype?.[Symbol.metadata];
28
- if (!metadata) {
29
- metadata = {};
30
- table[Symbol.metadata] = metadata;
31
- }
32
- return getTableInfoFromMetadata(metadata);
33
- }
34
- function getTableInfoFromMetadata(metadata) {
35
- if (!metadata[TABLE_INFO_PROPERTY_NAME])
36
- metadata[TABLE_INFO_PROPERTY_NAME] = { primaryKey: "", foreignKeys: [] };
37
- return metadata[TABLE_INFO_PROPERTY_NAME];
38
- }
39
-
40
24
  // src/lib/tableInfo/TableObj.ts
41
25
  var TableObj = class _TableObj {
42
26
  IS_TABLE_OBJ = true;
43
27
  tableName;
44
- columns;
45
- tableInfo = {
28
+ tableStructure = {
29
+ table: "",
46
30
  primaryKey: void 0,
47
- foreignKeys: [],
48
- dataTypes: {}
31
+ columns: {},
32
+ foreignKeys: []
49
33
  };
50
- constructor(tableName, columns) {
34
+ static getEmptyColumnEntry(key) {
35
+ return {
36
+ name: key,
37
+ type: "",
38
+ defaultValue: "",
39
+ isPrimaryKey: false
40
+ };
41
+ }
42
+ static getColumnEntry(key, value) {
43
+ let dataType = typeof value;
44
+ switch (typeof value) {
45
+ case "function":
46
+ return null;
47
+ case "object":
48
+ if (value instanceof Date) {
49
+ dataType = "date";
50
+ break;
51
+ } else {
52
+ Logger.warn(`${key} was skipped because its type (${typeof value}) is not supported`);
53
+ return null;
54
+ }
55
+ case "undefined":
56
+ case "symbol":
57
+ Logger.warn(`${key} was skipped because its type (${typeof value}) is not supported`);
58
+ return null;
59
+ }
60
+ return {
61
+ ..._TableObj.getEmptyColumnEntry(key),
62
+ inputType: dataType,
63
+ inputDefaultValue: value
64
+ };
65
+ }
66
+ constructor(tableName, defaultValues) {
51
67
  this.tableName = tableName;
52
- this.columns = columns;
68
+ for (const key in defaultValues) {
69
+ const value = defaultValues[key];
70
+ const columnEntry = _TableObj.getColumnEntry(key, value);
71
+ if (!columnEntry)
72
+ continue;
73
+ this.tableStructure.columns[key] = columnEntry;
74
+ }
53
75
  }
54
76
  primaryKey(key) {
55
- this.tableInfo.primaryKey = key.toString();
77
+ this.tableStructure.primaryKey = key.toString();
78
+ this.tableStructure.columns[key.toString()].isPrimaryKey = true;
56
79
  return this;
57
80
  }
58
81
  foreignKey(fromColumn, toTable, toColumn, options) {
59
- this.tableInfo.foreignKeys.push({
82
+ this.tableStructure.foreignKeys.push({
60
83
  fromTable: this.tableName,
61
84
  fromColumn: fromColumn.toString(),
62
85
  toTable: toTable.tableName,
@@ -67,17 +90,44 @@ var TableObj = class _TableObj {
67
90
  return this;
68
91
  }
69
92
  dataType(column, type) {
70
- this.tableInfo.dataTypes[column.toString()] = type;
93
+ this.tableStructure.columns[column.toString()].type = type;
94
+ return this;
95
+ }
96
+ maxCharacterLength(column, max) {
97
+ this.tableStructure.columns[column.toString()].maxLength = max;
71
98
  return this;
72
99
  }
73
100
  static create(tableName, columns) {
74
101
  return new _TableObj(tableName, columns);
75
102
  }
76
- static isDbTable(obj) {
103
+ static isTableObj(obj) {
77
104
  return !!obj?.IS_TABLE_OBJ;
78
105
  }
79
106
  };
80
107
 
108
+ // src/lib/tableInfo/getTableStructure.ts
109
+ var TABLE_INFO_PROPERTY_NAME = Symbol("tableInfo");
110
+ function getInputColumnInfo(table, context) {
111
+ const metadata = context?.metadata ? getTableStructureFromMetadata(context.metadata) : getTableStructure(table);
112
+ const key = context.name ?? context;
113
+ if (!metadata.columns.hasOwnProperty(key))
114
+ metadata.columns[key] = TableObj.getEmptyColumnEntry(key);
115
+ return metadata.columns[key];
116
+ }
117
+ function getTableStructure(table) {
118
+ let metadata = table[Symbol.metadata] ?? table.prototype?.[Symbol.metadata];
119
+ if (!metadata) {
120
+ metadata = {};
121
+ table[Symbol.metadata] = metadata;
122
+ }
123
+ return getTableStructureFromMetadata(metadata);
124
+ }
125
+ function getTableStructureFromMetadata(metadata) {
126
+ if (!metadata[TABLE_INFO_PROPERTY_NAME])
127
+ metadata[TABLE_INFO_PROPERTY_NAME] = { table: "", primaryKey: "", foreignKeys: [], columns: {} };
128
+ return metadata[TABLE_INFO_PROPERTY_NAME];
129
+ }
130
+
81
131
  // src/lib/TableStructureGenerator.ts
82
132
  var TableStructureGenerator = class {
83
133
  dialect;
@@ -92,75 +142,29 @@ var TableStructureGenerator = class {
92
142
  * @return An object where keys are table names, and values are their corresponding table structures.
93
143
  */
94
144
  generateTableStructure() {
95
- const tableObjects = {};
145
+ const tables = {};
96
146
  for (const table of this.dbInstructions.tables) {
97
- if (TableObj.isDbTable(table))
98
- tableObjects[table.tableName] = table;
99
- else {
147
+ if (TableObj.isTableObj(table)) {
148
+ tables[table.tableName] = table.tableStructure;
149
+ } else {
100
150
  const classTable = table;
101
- tableObjects[classTable.name] = { columns: new classTable(), tableInfo: getTableInfo(classTable) };
151
+ const structure = getTableStructure(classTable);
152
+ tables[classTable.name] = structure;
153
+ for (const key in structure.columns) {
154
+ const entry = structure.columns[key];
155
+ entry.defaultValue = entry.defaultValue === null ? this.dialect.types.null : this.dialect.formatValueToSql(entry.inputDefaultValue, entry.inputType);
156
+ entry.type = this.dialect.getSqlType(entry.inputType, entry);
157
+ }
102
158
  }
103
159
  }
104
- const tables = {};
105
- for (const tableName in tableObjects) {
106
- const obj = tableObjects[tableName];
107
- const tableInfo = obj.tableInfo;
108
- tables[tableName] = {
109
- table: tableName,
110
- primaryKey: tableInfo?.primaryKey,
111
- columns: this.getColumns(obj.columns, tableInfo),
112
- foreignKeys: tableInfo?.foreignKeys
113
- };
114
- }
115
160
  return tables;
116
161
  }
117
- /**
118
- * Retrieves the columns for a table
119
- *
120
- * @param obj - The table class interface object containing properties that represent the table's fields.
121
- * @param tableInfo - Optional metadata about the table. Can be undefined.
122
- * @return An array of {@link ColumnInfo} representing the detailed column information.
123
- */
124
- getColumns(obj, tableInfo) {
125
- const columns = [];
126
- for (const property in obj) {
127
- const propertyKey = property;
128
- const value = obj[propertyKey];
129
- const columnData = {
130
- name: property,
131
- isPrimaryKey: property == tableInfo?.primaryKey,
132
- type: this.dialect.types.string,
133
- defaultValue: this.dialect.types.null
134
- };
135
- let dataType = tableInfo?.dataTypes?.[property] ?? typeof value;
136
- switch (dataType) {
137
- case "function":
138
- continue;
139
- case "object":
140
- if (value instanceof Date) {
141
- dataType = "date";
142
- break;
143
- } else {
144
- Logger.warn(`${property} was skipped because its type (${typeof value}) is not supported`);
145
- continue;
146
- }
147
- case "undefined":
148
- case "symbol":
149
- Logger.warn(`${property} was skipped because its type (${typeof value}) is not supported`);
150
- continue;
151
- }
152
- columnData.defaultValue = value === null ? this.dialect.types.null : this.dialect.formatValueToSql(value, dataType);
153
- columnData.type = this.dialect.types[dataType];
154
- columns.push(columnData);
155
- }
156
- return columns;
157
- }
158
162
  };
159
163
 
160
164
  // src/lib/exceptions/NotAllowedException.ts
161
165
  var NotAllowedException = class extends Error {
162
166
  constructor(entries) {
163
- let message = "Some destructive changes need to be confirmed. In preMigration() run:\n";
167
+ let message = "Some destructive changes need to be confirmed. To confirm, add to preMigration():\n";
164
168
  for (const entry of entries) {
165
169
  message += ` migrations.allowMigration(${entry.version}, ${entry.tableName}, "${entry.type}");
166
170
  `;
@@ -178,6 +182,13 @@ var Migrations = class {
178
182
  migrationDataForOldTableNames = {};
179
183
  alwaysAllowed = {};
180
184
  notAllowedChanges = [];
185
+ /**
186
+ * Resets the migration state to its initial values.
187
+ * Only used internally.
188
+ *
189
+ * @param dbInstructions - The instructions containing database metadata and migration details.
190
+ * @param fromVersion - The version of the actual database.
191
+ */
181
192
  reset(dbInstructions, fromVersion) {
182
193
  this.fromVersion = fromVersion;
183
194
  this.toVersion = dbInstructions.version;
@@ -186,10 +197,23 @@ var Migrations = class {
186
197
  this.alwaysAllowed = dbInstructions.alwaysAllowedMigrations ?? {};
187
198
  this.notAllowedChanges = [];
188
199
  }
200
+ /**
201
+ * Retrieves the migration instructions for the specified table.
202
+ * @see getEntryFromTableName
203
+ *
204
+ * @param table - The {@link TableInput} object from which the table name will be retrieved.
205
+ * @return The migration instructions corresponding to the given table input.
206
+ */
189
207
  getEntry(table) {
190
208
  const tableName = this.getTableName(table);
191
209
  return this.getEntryFromTableName(tableName);
192
210
  }
211
+ /**
212
+ * Retrieves the migration instructions for the specified table.
213
+ *
214
+ * @param tableName - The name of the table for which the entry is to be retrieved or created.
215
+ * @return The migration instructions corresponding to the given table input.
216
+ */
193
217
  getEntryFromTableName(tableName) {
194
218
  if (!this.migrationData.hasOwnProperty(tableName)) {
195
219
  this.migrationData[tableName] = {
@@ -201,17 +225,39 @@ var Migrations = class {
201
225
  }
202
226
  return this.migrationData[tableName];
203
227
  }
228
+ /**
229
+ * Retrieves the table name from the given table input.
230
+ *
231
+ * @param table - The {@link TableInput} object.
232
+ * @return The name of the table derived from either {@link TableObj} or a class.
233
+ */
204
234
  getTableName(table) {
205
- return TableObj.isDbTable(table) ? table.tableName : table.name;
235
+ return TableObj.isTableObj(table) ? table.tableName : table.name;
206
236
  }
237
+ /**
238
+ * Checks whether a provided version is relevant based on database version ({@link fromVersion}) and target version ({@link toVersion}).
239
+ * Also makes sure that version checks happen in order.
240
+ *
241
+ * @param version - The version to check for relevance.
242
+ * @return Returns true if the version is relevant, otherwise false.
243
+ * @throws Error if versions are not properly ordered
244
+ */
207
245
  versionIsRelevant(version) {
208
- if (version < this.fromVersion || version > this.toVersion)
246
+ if (version <= this.fromVersion || version > this.toVersion)
209
247
  return false;
210
248
  if (version < this.lastUsedVersion)
211
249
  throw new Error("Migrations in preMigration() have to be ordered by version (beginning with the lowest version).");
212
250
  this.lastUsedVersion = version;
213
251
  return true;
214
252
  }
253
+ /**
254
+ * Verifies the renaming tasks specified in {@link DatabaseInstructions.preMigration} that were considered are valid.
255
+ * Called after all SQL queries have been generated.
256
+ * Only used internally.
257
+ *
258
+ * @param newTables - The table structures extracted from {@link DatabaseInstructions.tables}.
259
+ * @throws Error if a renaming task is invalid.
260
+ */
215
261
  verifyRenamingTasks(newTables) {
216
262
  for (const tableName in this.migrationData) {
217
263
  const migrationEntry = this.migrationData[tableName];
@@ -228,11 +274,18 @@ var Migrations = class {
228
274
  const newColumnName = renamingData.newName;
229
275
  if (oldColumnName == newColumnName)
230
276
  return new Error(`You set column ${tableName}.${oldColumnName} to be renamed to itself!`);
231
- else if (!newTables[tableName]?.columns.find((column) => column.name == newColumnName))
277
+ else if (!newTables[tableName]?.columns[newColumnName])
232
278
  return new Error(`You set column ${tableName}.${oldColumnName} to be renamed to ${tableName}.${newColumnName}. But ${tableName}.${newColumnName} does not exist in your structure.`);
233
279
  }
234
280
  }
235
281
  }
282
+ /**
283
+ * Making sure all considered calls to {@link allowMigration()} where necessary to prevent input mistakes.
284
+ * Called after all SQL queries have been generated.
285
+ * Only used internally.
286
+ *
287
+ * @throws Error if unnecessary calls were discovered. All discovered calls are collected and thrown as one Error.
288
+ */
236
289
  verifyAllowedMigrations() {
237
290
  if (this.notAllowedChanges.length)
238
291
  return new NotAllowedException(this.notAllowedChanges);
@@ -248,6 +301,14 @@ var Migrations = class {
248
301
  if (errorMsg)
249
302
  return new Error(errorMsg);
250
303
  }
304
+ /**
305
+ * Called by {@link MigrationManager} to check if a specific destructive query is allowed.
306
+ * Only used internally.
307
+ *
308
+ * @see allowMigration()
309
+ * @param tableName - The name of the table to check the migration against.
310
+ * @param type - The type of destructive migration being checked.
311
+ */
251
312
  compareWithAllowedMigration(tableName, type) {
252
313
  const migrationEntry = this.migrationData[tableName];
253
314
  if (!migrationEntry?.allowedMigrations[type]) {
@@ -256,41 +317,114 @@ var Migrations = class {
256
317
  } else if (migrationEntry)
257
318
  migrationEntry.usedMigrations[type] = true;
258
319
  }
320
+ /**
321
+ * Retrieves the migration data containing instructions for data migration.
322
+ * Only used internally.
323
+ *
324
+ * @return An object where each key corresponds to the table name,
325
+ * and the value is the associated migration instructions.
326
+ */
259
327
  getMigrationData() {
260
328
  return this.migrationData;
261
329
  }
330
+ /**
331
+ * Iterates over renamed columns for the specified table and executes a callback for each pair of old and new column names.
332
+ * Only used internally.
333
+ *
334
+ * @param tableName - Name of the table whose renamed columns should be processed.
335
+ * @param callback - A function to execute for each renamed column, receiving the old and new column names as arguments.
336
+ */
262
337
  loopRenamedColumns(tableName, callback) {
263
338
  const migrationEntry = this.migrationData[tableName];
264
339
  for (const renamingData of migrationEntry.renamedColumns) {
265
340
  callback(renamingData.oldName, renamingData.newName);
266
341
  }
267
342
  }
343
+ /**
344
+ * Considers the renaming of a table and returns its (newest) name after the migration or
345
+ * the original name if no renaming is queued.
346
+ * Only used internally.
347
+ *
348
+ * @see getOldTableName()
349
+ * @param tableName - The current table name in the database.
350
+ * @return The newest table name if available, otherwise the current table name.
351
+ */
268
352
  getNewestTableName(tableName) {
269
353
  return this.migrationDataForOldTableNames[tableName]?.tableRenaming?.newName ?? tableName;
270
354
  }
355
+ /**
356
+ * Retrieves the current table name in the database.
357
+ * Only used internally.
358
+ *
359
+ * @see getNewestTableName()
360
+ * @param tableName - The name of the newest table name.
361
+ * @return The current table name in the database.
362
+ */
271
363
  getOldTableName(tableName) {
272
364
  return this.migrationData[tableName]?.tableRenaming?.oldName ?? tableName;
273
365
  }
366
+ /**
367
+ * Considers the renaming of a column in a table and returns its (newest) name after the migration or
368
+ * the original name if no renaming is queued.
369
+ * Only used internally.
370
+ *
371
+ * @param tableName - The name of the table containing the column.
372
+ * @param oldColumnName - The current name of the column in the database.
373
+ * @return The newest column name if available, otherwise the original column name.
374
+ */
274
375
  getNewestColumnName(tableName, oldColumnName) {
275
376
  const columnNames = this.migrationData[tableName]?.renamedColumns.find((columns) => columns.oldName == oldColumnName);
276
377
  return columnNames ? columnNames.newName : oldColumnName;
277
378
  }
379
+ /**
380
+ * Determines if the specified table is marked to be recreated.
381
+ * Only used internally.
382
+ *
383
+ * @param tableName The name of the table to check.
384
+ * @return Returns true if the table will be recreated, false otherwise.
385
+ */
278
386
  willBeRecreated(tableName) {
279
387
  return this.migrationData[tableName]?.recreate;
280
388
  }
389
+ /**
390
+ * Marks a table to be recreated and logs the recreation reason for the user.
391
+ * Only used internally.
392
+ *
393
+ * @param tableName - The name of the table to be marked for recreation.
394
+ * @param reason - The reason why the table is being marked for recreation.
395
+ */
281
396
  internalRecreate(tableName, reason) {
282
397
  const entry = this.getEntryFromTableName(tableName);
283
398
  entry.recreate = true;
284
399
  Logger.log(`Table ${tableName} will be recreated(${reason})!`);
285
400
  }
401
+ /**
402
+ * SqlMorpheus only allows destructive statements if it was specifically allowed in {@link DatabaseInstructions.preMigration()}.
403
+ * Use this method to allow a destructive statement for a specific version.
404
+ * This method will be ignored if {@link version} is smaller than the current database version or higher than the target version of {@link DatabaseInstructions}.
405
+ *
406
+ * @param version - The target version for which the specific migration is allowed. Must be provided to make sure this method will only have an effect when specified.
407
+ * @param table - Either a {@link TableObj} or a class decorated with @TableClass.
408
+ * @param allowedMigrations - The keys representing the migrations to be allowed. Multiple migrations can be provided
409
+ */
286
410
  allowMigration(version, table, ...allowedMigrations) {
287
- if (version < this.fromVersion || version > this.toVersion)
411
+ if (!this.versionIsRelevant(version))
288
412
  return;
289
413
  const entry = this.getEntry(table);
290
414
  for (const key of allowedMigrations) {
291
415
  entry.allowedMigrations[key] = true;
292
416
  }
293
417
  }
418
+ /**
419
+ * When you change the name of a table, SqlMorpheus will assume the original table was meant to be dropped
420
+ * and the new table was meant to be added, which would lead to data loss.
421
+ * Use this method to mark a table to be renamed instead.
422
+ * This method will be ignored if {@link version} is smaller than the current database version or higher than the target version of {@link DatabaseInstructions}.
423
+ *
424
+ * @param version - The target version for which the table should be renamed. Must be provided to make sure this method will only have an effect when specified.
425
+ * @param oldTableName - The current name in the database at the time of the migration.
426
+ * @param newTableName - The new table name or its equivalent input format.
427
+ */
294
428
  renameTable(version, oldTableName, newTableName) {
295
429
  if (!this.versionIsRelevant(version))
296
430
  return;
@@ -302,6 +436,17 @@ var Migrations = class {
302
436
  else
303
437
  entry.tableRenaming.newName = newTableNameString;
304
438
  }
439
+ /**
440
+ * When you change the name of a column, SqlMorpheus will assume the original column was meant to be removed
441
+ * and the new column was meant to be added, which would lead to data loss.
442
+ * Use this method to mark a column to be renamed instead.
443
+ * This method will be ignored if {@link version} is smaller than the current database version or higher than the target version of {@link DatabaseInstructions}.
444
+ *
445
+ * @param version - The target version for which the table should be renamed. Must be provided to make sure this method will only have an effect when specified.
446
+ * @param table Either a {@link TableObj} or a class decorated with @TableClass containing the column to be renamed.
447
+ * @param oldColumn The current name in the database at the time of the migration.
448
+ * @param newColumn The new name to assign to the column.
449
+ */
305
450
  renameColumn(version, table, oldColumn, newColumn) {
306
451
  if (!this.versionIsRelevant(version))
307
452
  return;
@@ -312,6 +457,15 @@ var Migrations = class {
312
457
  else
313
458
  entry.renamedColumns.push({ oldName: oldColumn, newName: newColumn });
314
459
  }
460
+ /**
461
+ * Should not be needed most of the time.
462
+ * Marks a table to be recreated
463
+ * (a copy of the table will be created, all data will be moved over, the original table will be dropped and the new table will be renamed to the original name).
464
+ * This method will be ignored if {@link version} is smaller than the current database version or higher than the target version of {@link DatabaseInstructions}.
465
+ *
466
+ * @param version - The target version for which the table should be renamed. Must be provided to make sure this method will only have an effect when specified.
467
+ * @param table Either a {@link TableObj} or a class decorated with @TableClass.
468
+ */
315
469
  recreateTable(version, table) {
316
470
  if (!this.versionIsRelevant(version))
317
471
  return;
@@ -500,8 +654,9 @@ ${changes.up}
500
654
  */
501
655
  createTableSql(tableName, columns, foreignKeys) {
502
656
  const queryLines = [];
503
- for (const columnInfo of columns) {
504
- queryLines.push(this.dialect.columnDefinition(columnInfo.name, columnInfo.type, columnInfo.defaultValue, columnInfo.isPrimaryKey));
657
+ for (const key in columns) {
658
+ const columnInfo = columns[key];
659
+ queryLines.push(this.dialect.columnDefinition(columnInfo.name, columnInfo.type, columnInfo.isPrimaryKey, columnInfo.defaultValue));
505
660
  }
506
661
  if (foreignKeys) {
507
662
  for (const foreignKeyInfo of foreignKeys) {
@@ -539,7 +694,11 @@ ${changes.up}
539
694
  this.migrations.compareWithAllowedMigration(tableName, "continueWithoutRollback");
540
695
  const oldColumnList = await this.dialect.getColumnInformation(this.migrations.getOldTableName(tableName));
541
696
  const newColumnList = this.newTables[tableName].columns;
542
- const moveableColumns = newColumnList.filter((entry) => oldColumnList.find((oldEntry) => oldEntry.name == entry.name) != void 0).map((entry) => entry.name);
697
+ const moveableColumns = [];
698
+ for (const key in newColumnList) {
699
+ if (oldColumnList.hasOwnProperty(key))
700
+ moveableColumns.push(newColumnList[key].name);
701
+ }
543
702
  const backupTableName = `${tableName}__backup`;
544
703
  const insertQuery = this.dialect.insert(
545
704
  backupTableName,
@@ -547,7 +706,7 @@ ${changes.up}
547
706
  );
548
707
  const moveDataQuery = insertQuery + "\n" + this.dialect.dropTable(tableName) + "\n" + this.dialect.renameTable(backupTableName, tableName);
549
708
  const structure = this.newTables[tableName];
550
- changes.up += this.createTableSql(backupTableName, structure.columns, structure.foreignKeys) + "\n" + moveDataQuery + "\n";
709
+ changes.up += this.createTableSql(backupTableName, structure.columns, structure.foreignKeys) + "\n" + moveDataQuery + "\n\n";
551
710
  const dbTableName = this.migrations.getOldTableName(tableName);
552
711
  changes.down += this.dialect.canInspectForeignKeys && this.dialect.canInspectPrimaryKey ? this.createTableSql(backupTableName, await this.dialect.getColumnInformation(dbTableName), await this.dialect.getForeignKeys(dbTableName)) + "\n" + moveDataQuery : "\n\n-- Cannot recreate foreign keys or load primary keys with this database! Table will not be recreated!\n";
553
712
  }
@@ -639,6 +798,10 @@ ${changes.up}
639
798
  const newTableDefinition = this.newTables[tableName];
640
799
  const oldColumnList = await this.dialect.getColumnInformation(this.migrations.getOldTableName(tableName));
641
800
  const oldPrimaryKey = this.dialect.canInspectPrimaryKey ? this.getPrimaryKeyColumn(oldColumnList) : false;
801
+ const oldColumnNewNameIndex = {};
802
+ for (const key in oldColumnList) {
803
+ oldColumnNewNameIndex[this.migrations.getNewestColumnName(tableName, key)] = oldColumnList[key];
804
+ }
642
805
  const newColumnList = newTableDefinition.columns;
643
806
  const newPrimaryKey = newTableDefinition.primaryKey;
644
807
  if (this.dialect.canInspectPrimaryKey && oldPrimaryKey != newPrimaryKey) {
@@ -657,25 +820,23 @@ ${changes.up}
657
820
  this.migrations.internalRecreate(newTableDefinition.table, "Dialect does not support altering primary keys");
658
821
  continue;
659
822
  }
660
- for (const newColumn of newColumnList) {
661
- const oldColumn = oldColumnList.find(
662
- (entry) => this.migrations.getNewestColumnName(tableName, entry.name) == newColumn.name
663
- );
823
+ for (const key in newColumnList) {
824
+ const newColumn = newColumnList[key];
825
+ const oldColumn = oldColumnNewNameIndex[newColumn.name];
664
826
  if (oldColumn == void 0) {
665
- changes.up += this.dialect.createColumn(tableName, this.dialect.columnDefinition(newColumn.name, newColumn.type, newColumn.defaultValue, newColumn.isPrimaryKey)) + "\n";
827
+ changes.up += this.dialect.createColumn(tableName, this.dialect.columnDefinition(newColumn.name, newColumn.type, newColumn.isPrimaryKey, newColumn.defaultValue)) + "\n";
666
828
  changes.down += this.dialect.dropColumn(tableName, newColumn.name) + "\n";
667
829
  } else if (newColumn.type != oldColumn.type || newColumn.defaultValue != oldColumn.defaultValue) {
668
830
  this.migrations.internalRecreate(newTableDefinition.table, "Table structure was changed");
669
831
  }
670
832
  }
671
- for (const oldColumn of oldColumnList) {
672
- const newColumn = newColumnList.find(
673
- (entry) => entry.name == this.migrations.getNewestColumnName(tableName, oldColumn.name)
674
- );
833
+ for (const key in oldColumnList) {
834
+ const oldColumn = oldColumnList[key];
835
+ const newColumn = newColumnList[this.migrations.getNewestColumnName(tableName, oldColumn.name)];
675
836
  if (newColumn == void 0) {
676
837
  this.migrations.compareWithAllowedMigration(tableName, "dropColumn");
677
838
  changes.up += this.dialect.dropColumn(tableName, oldColumn.name) + "\n";
678
- changes.down += this.dialect.createColumn(tableName, this.dialect.columnDefinition(oldColumn.name, oldColumn.type, oldColumn.defaultValue, oldColumn.isPrimaryKey)) + "\n";
839
+ changes.down += this.dialect.createColumn(tableName, this.dialect.columnDefinition(oldColumn.name, oldColumn.type, oldColumn.isPrimaryKey, oldColumn.defaultValue)) + "\n";
679
840
  }
680
841
  }
681
842
  }
@@ -684,11 +845,12 @@ ${changes.up}
684
845
  /**
685
846
  * Retrieves the name of the primary key column from a list of column information.
686
847
  *
687
- * @param columnInfoList - An array of ColumnInfo objects containing details about each column.
848
+ * @param columnInfoEntries - An array of ColumnInfo objects containing details about each column.
688
849
  * @return The name of the primary key column if found; otherwise, undefined.
689
850
  */
690
- getPrimaryKeyColumn(columnInfoList) {
691
- for (const columnInfo of columnInfoList) {
851
+ getPrimaryKeyColumn(columnInfoEntries) {
852
+ for (const key in columnInfoEntries) {
853
+ const columnInfo = columnInfoEntries[key];
692
854
  if (columnInfo.isPrimaryKey)
693
855
  return columnInfo.name;
694
856
  }
@@ -778,15 +940,27 @@ ${changes.down}`, { encoding: "utf-8" });
778
940
  import "polyfill-symbol-metadata";
779
941
  function TableClass(tableName, primaryKey) {
780
942
  return (table, context) => {
781
- const tableInfo = context?.metadata ? getTableInfoFromMetadata(context.metadata) : getTableInfo(table);
782
- tableInfo.primaryKey = primaryKey?.toString();
783
- if (tableInfo.foreignKeys) {
784
- for (const foreignKey of tableInfo.foreignKeys) {
943
+ const tableStructure = context?.metadata ? getTableStructureFromMetadata(context.metadata) : getTableStructure(table);
944
+ tableStructure.primaryKey = primaryKey?.toString();
945
+ tableStructure.table = tableName;
946
+ if (tableStructure.foreignKeys) {
947
+ for (const foreignKey of tableStructure.foreignKeys) {
785
948
  foreignKey.fromTable = tableName;
786
949
  if (foreignKey.toTable == table.name)
787
950
  foreignKey.toTable = tableName;
788
951
  }
789
952
  }
953
+ for (const key in table) {
954
+ const value = table[key];
955
+ const existingEntry = tableStructure.columns[key];
956
+ const defaultEntry = TableObj.getColumnEntry(key, value);
957
+ if (!defaultEntry)
958
+ continue;
959
+ tableStructure.columns[key] = {
960
+ ...defaultEntry,
961
+ ...existingEntry
962
+ };
963
+ }
790
964
  Object.defineProperty(table, "name", { value: tableName, writable: false });
791
965
  };
792
966
  }
@@ -795,10 +969,8 @@ function TableClass(tableName, primaryKey) {
795
969
  import "polyfill-symbol-metadata";
796
970
  function DataType(type) {
797
971
  return (table, context) => {
798
- const metadata = context?.metadata ? getTableInfoFromMetadata(context.metadata) : getTableInfo(table);
799
- if (!metadata.dataTypes)
800
- metadata.dataTypes = {};
801
- metadata.dataTypes[context.name ?? context] = type;
972
+ const entry = getInputColumnInfo(table, context);
973
+ entry.inputType = type;
802
974
  };
803
975
  }
804
976
 
@@ -806,7 +978,7 @@ function DataType(type) {
806
978
  import "polyfill-symbol-metadata";
807
979
  function ForeignKey(toTable, toColumn, options) {
808
980
  return (table, context) => {
809
- const metadata = context?.metadata ? getTableInfoFromMetadata(context.metadata) : getTableInfo(table);
981
+ const metadata = context?.metadata ? getTableStructureFromMetadata(context.metadata) : getTableStructure(table);
810
982
  if (!metadata.foreignKeys)
811
983
  metadata.foreignKeys = [];
812
984
  metadata.foreignKeys.push({
@@ -846,7 +1018,7 @@ var DefaultSql = class {
846
1018
  * Formats a given value to a SQL-equivalent string based on the provided data type.
847
1019
  *
848
1020
  * @param value - The value to be formatted.
849
- * @param type - The data type of the value. Either determined through typeof or {@link TableInfo} setting
1021
+ * @param type - The data type of the value. Either determined through typeof or {@link TableStructure} setting
850
1022
  * @return A string representation of the value formatted for SQL.
851
1023
  */
852
1024
  formatValueToSql(value, type) {
@@ -857,65 +1029,68 @@ var DefaultSql = class {
857
1029
  case "string":
858
1030
  return `"${value}"`;
859
1031
  case "time":
860
- return toDate(value).toISOString().slice(11, 19);
1032
+ return `"${toDate(value).toISOString().slice(11, 19)}"`;
861
1033
  case "date":
862
- return toDate(value).toISOString().slice(0, 10);
1034
+ return `"${toDate(value).toISOString().slice(0, 10)}"`;
863
1035
  case "dateTime":
864
- return toDate(value).toISOString().slice(0, 19).replace("T", " ");
1036
+ return `"${toDate(value).toISOString().slice(0, 19).replace("T", " ")}"`;
865
1037
  default:
866
1038
  return value.toString();
867
1039
  }
868
1040
  }
1041
+ getSqlType(dataType, _) {
1042
+ return this.types[dataType];
1043
+ }
869
1044
  /**
870
- * Query to enable / disable foreign keys in the database.
1045
+ * Statement to enable / disable foreign keys in the database.
871
1046
  * Is dialect specific.
872
1047
  *
873
1048
  * @param enabled - A boolean indicating whether to enable or disable foreign key constraints.
874
- * @return The query
1049
+ * @return The SQL statement as a string.
875
1050
  */
876
1051
  changeForeignKeysState(enabled) {
877
1052
  return "";
878
1053
  }
879
1054
  /**
880
- * Query to add a foreign key to a specified table.
1055
+ * Statement to add a foreign key to a specified table.
881
1056
  * Is only used if {@link canAlterForeignKeys} is true.
882
1057
  *
883
1058
  * @param fromTableName - The name of the table to which the foreign key will be added.
884
1059
  * @param foreignKey - The foreign key definition to be added, see {@link foreignKey()}.
885
- * @return The SQL statement that adds the foreign key to the specified table.
1060
+ * @return The SQL statement as a string.
886
1061
  */
887
1062
  addForeignKey(fromTableName, foreignKey) {
888
1063
  throw new Error("Adding foreign keys is not supported!");
889
1064
  }
890
1065
  /**
891
- * Query to remove a foreign key from a specified table.
1066
+ * Statement to remove a foreign key from a specified table.
892
1067
  * Is only used if {@link canAlterForeignKeys} is true.
893
1068
  *
894
1069
  * @param tableName - The name of the table to which the foreign key will be added.
895
1070
  * @param foreignKeyName - The name of the foreign key definition.
896
- * @return The SQL statement that removes the foreign key from the specified table.
1071
+ * @return The SQL statement as a string.
897
1072
  */
898
1073
  removeForeignKey(tableName, foreignKeyName) {
899
1074
  throw new Error("Foreign key removal is not supported!");
900
1075
  }
901
1076
  /**
902
- * Query to add a primary key to the specified table.
1077
+ * Statement to add a primary key to the specified table.
903
1078
  * Is only used if {@link canAlterPrimaryKey} is true.
904
1079
  *
905
1080
  * @param tableName - The name of the table to which the primary key will be added.
906
1081
  * @param columnName - The name of the column that will be set as the primary key.
907
- * @return A SQL statement to add a primary key to the specified table and column.
1082
+ * @return The SQL statement as a string.
908
1083
  */
909
1084
  addPrimaryKey(tableName, columnName) {
910
1085
  throw new Error("Adding foreign keys is not supported!");
911
1086
  }
912
1087
  /**
913
- * Query to remove a primary key from the specified table.
1088
+ * Statement to remove a primary key from the specified table.
914
1089
  * Is only used if {@link canAlterPrimaryKey} is true.
915
1090
  *
916
1091
  * @param tableName - The name of the table to which the primary key will be added.
917
1092
  * @param columnName - The name of the column that will be set as the primary key.
918
- * @return A SQL statement to remove a primary key from the specified table and column.
1093
+ * @return The SQL statement as a string.
919
1094
  */
920
1095
  removePrimaryKey(tableName, columnName) {
921
1096
  throw new Error("Foreign key removal is not supported!");
@@ -939,64 +1114,164 @@ var DefaultSql = class {
939
1114
  query += ` ON DELETE ${onDelete}`;
940
1115
  return query;
941
1116
  }
1117
+ /**
1118
+ * Statement to create a table if it does not already exist.
1119
+ *
1120
+ * @param tableName - The name of the table to be created.
1121
+ * @param entries - An array containing the column definitions for the table.
1122
+ * @return The SQL statement as a string.
1123
+ */
942
1124
  createTable(tableName, entries) {
943
1125
  return `CREATE TABLE IF NOT EXISTS ${tableName} (
944
1126
  ${entries.join(",\n ")}
945
1127
  );`;
946
1128
  }
1129
+ /**
1130
+ * Statement to rename a table.
1131
+ *
1132
+ * @param tableName - The name of the existing table to be renamed.
1133
+ * @param newTableName - The new name for the table.
1134
+ * @return The SQL statement as a string.
1135
+ */
947
1136
  renameTable(tableName, newTableName) {
948
1137
  return `ALTER TABLE ${tableName} RENAME TO ${newTableName};`;
949
1138
  }
1139
+ /**
1140
+ * Statement to drop a table if it exists.
1141
+ *
1142
+ * @param tableName - The name of the table to be dropped.
1143
+ * @return The SQL statement as a string.
1144
+ */
950
1145
  dropTable(tableName) {
951
1146
  return `DROP TABLE IF EXISTS ${tableName};`;
952
1147
  }
953
- columnDefinition(columnName, type, defaultValue, isPrimaryKey) {
954
- const query = `${columnName} ${type} DEFAULT ${defaultValue}`;
1148
+ /**
1149
+ * Constructs a SQL column definition based on the provided parameters.
1150
+ *
1151
+ * @param columnName - The name of the column.
1152
+ * @param type - The data type of the column.
1153
+ * @param defaultValue - The default value for the column.
1154
+ * @param isPrimaryKey - Indicates whether the column is a primary key.
1155
+ * @return The constructed SQL column definition string.
1156
+ */
1157
+ columnDefinition(columnName, type, isPrimaryKey, defaultValue) {
1158
+ const query = `${columnName} ${type}${defaultValue ? ` DEFAULT ${defaultValue}` : ""}`;
955
1159
  return isPrimaryKey ? `${query} PRIMARY KEY` : query;
956
1160
  }
1161
+ /**
1162
+ * Statement to add a new column to a specified table.
1163
+ *
1164
+ * @param columnTable - The name of the table to which the column will be added.
1165
+ * @param entry - The column definition including the column name and its data type. See {@link columnDefinition()}
1166
+ * @return The SQL statement as a string.
1167
+ */
957
1168
  createColumn(columnTable, entry) {
958
1169
  return `ALTER TABLE ${columnTable} ADD ${entry};`;
959
1170
  }
1171
+ /**
1172
+ * Statement to rename a column in an existing table.
1173
+ *
1174
+ * @param tableName - The name of the table containing the column to rename.
1175
+ * @param oldColumnName - The current name of the column to be renamed.
1176
+ * @param newColumnName - The new name for the column.
1177
+ * @return The SQL statement as a string.
1178
+ */
960
1179
  renameColumn(tableName, oldColumnName, newColumnName) {
961
1180
  return `ALTER TABLE ${tableName} RENAME COLUMN ${oldColumnName} TO ${newColumnName};`;
962
1181
  }
963
- copyColumn(tableName, oldColumnName, newColumnName) {
964
- return `UPDATE ${tableName} SET ${newColumnName} = ${oldColumnName};`;
965
- }
1182
+ /**
1183
+ * Statement to drop a column from a specified table.
1184
+ *
1185
+ * @param tableName - The name of the table from which the column will be dropped.
1186
+ * @param columnName - The name of the column to be dropped.
1187
+ * @return The SQL statement as a string.
1188
+ */
966
1189
  dropColumn(tableName, columnName) {
967
1190
  return `ALTER TABLE ${tableName} DROP COLUMN ${columnName};`;
968
1191
  }
1192
+ /**
1193
+ * Statement to return data from a table.
1194
+ *
1195
+ * @param tableName - The name of the database table to select data from.
1196
+ * @param select - An array of column names to include in the SELECT clause.
1197
+ * @param where - An optional condition.
1198
+ * @return The SQL statement as a string.
1199
+ */
969
1200
  select(tableName, select, where) {
970
1201
  let query = `SELECT ${select.join(",")} FROM ${tableName}`;
971
1202
  if (where)
972
1203
  query += ` WHERE ${where}`;
973
1204
  return `${query};`;
974
1205
  }
1206
+ /**
1207
+ * Statement to insert data into a table.
1208
+ *
1209
+ * @param tableName - The name of the table where the data will be inserted.
1210
+ * @param content - The value query. See {@link insertValues()}.
1211
+ * @return The SQL statement as a string.
1212
+ */
975
1213
  insert(tableName, content) {
976
1214
  return `INSERT INTO ${tableName} ${content};`;
977
1215
  }
1216
+ /**
1217
+ * A SQL insert query string. See {@link insert()}.
1218
+ *
1219
+ * @param keys - An array of column names to be used in the query.
1220
+ * @param [valueString] - An optional preformatted value string to be included in the query.
1221
+ * If not provided, the method generates a default placeholder string with "?" for each key.
1222
+ * @return The SQL statement as a string.
1223
+ */
978
1224
  insertValues(keys, valueString) {
979
1225
  return `(${keys}) ${valueString ?? `VALUES (${keys.map(() => "?").join(",")})`}`;
980
1226
  }
1227
+ /**
1228
+ * Returns a SQL query string to create a migration table.
1229
+ * The table is used to store migration data, specifically the version of the migration.
1230
+ *
1231
+ * @return The SQL query string for creating the migration table.
1232
+ */
981
1233
  migrationTableQuery() {
982
1234
  return this.createTable(MIGRATION_DATA_TABLE_NAME, [
983
- this.columnDefinition("version", this.types.number, "0", false)
1235
+ this.columnDefinition("version", this.types.number, false, "0")
984
1236
  ]);
985
1237
  }
1238
+ /**
1239
+ * Fetches the foreign keys for the specified table.
1240
+ * This method is only used if {@link canInspectForeignKeys} is true
1241
+ *
1242
+ * @param tableName - The name of the table for which to retrieve foreign key information.
1243
+ * @return {Promise<ForeignKeyInfo[]>} A promise that resolves to an array of {@link ForeignKeyInfo}.
1244
+ */
986
1245
  async getForeignKeys(tableName) {
987
1246
  throw new Error("Inspecting foreign keys is not supported!");
988
1247
  }
1248
+ /**
1249
+ * Ensures that the migration table exists in the database.
1250
+ * If the table does not exist, it creates the table using the defined migration table query.
1251
+ *
1252
+ * @return A promise that resolves when the migration table is created successfully.
1253
+ */
989
1254
  async createMigrationTableIfNeeded() {
990
1255
  await this.db.runMultipleWriteStatements(this.migrationTableQuery());
991
1256
  }
992
- //TODO: untested
1257
+ /**
1258
+ * Retrieves the current version from the migration data table.
1259
+ *
1260
+ * @return A promise that resolves to the current version number. Returns 0 if no version is found.
1261
+ */
993
1262
  async getVersion() {
994
1263
  await this.createMigrationTableIfNeeded();
995
1264
  const query = this.select(MIGRATION_DATA_TABLE_NAME, ["version"]);
996
1265
  const data = await this.db.runGetStatement(query);
997
1266
  return data.length ? data[0].version : 0;
998
1267
  }
999
- //TODO: untested
1268
+ /**
1269
+ * Updates the migration version in the database. If the version entry does not exist, it inserts a new one;
1270
+ * if it exists, it updates the version to the specified value.
1271
+ *
1272
+ * @param newVersion - The new migration version to set in the database.
1273
+ * @return A promise that resolves when the operation is complete.
1274
+ */
1000
1275
  async setVersion(newVersion) {
1001
1276
  const query = `${this.migrationTableQuery()};
1002
1277
  INSERT INTO ${MIGRATION_DATA_TABLE_NAME} (version) VALUES ${newVersion} WHERE NOT EXISTS (SELECT 1 FROM ${MIGRATION_DATA_TABLE_NAME})
@@ -1014,9 +1289,9 @@ var SqliteDialect = class extends DefaultSql {
1014
1289
  number: "INTEGER",
1015
1290
  bigint: "INTEGER",
1016
1291
  boolean: "INTEGER",
1017
- date: "DATE",
1018
- time: "TIME",
1019
- dateTime: "DATETIME",
1292
+ date: "INTEGER",
1293
+ time: "INTEGER",
1294
+ dateTime: "INTEGER",
1020
1295
  null: "NULL"
1021
1296
  };
1022
1297
  canAlterForeignKeys = false;
@@ -1031,14 +1306,16 @@ var SqliteDialect = class extends DefaultSql {
1031
1306
  }
1032
1307
  async getColumnInformation(tableName) {
1033
1308
  const data = await this.db.runGetStatement(`PRAGMA table_info(${tableName})`);
1034
- return data.map((entry) => {
1035
- return {
1309
+ const output = {};
1310
+ for (const entry of data) {
1311
+ output[entry["name"]] = {
1036
1312
  name: entry["name"],
1037
1313
  type: entry["type"],
1038
1314
  defaultValue: entry["dflt_value"],
1039
1315
  isPrimaryKey: entry["pk"] == "1"
1040
1316
  };
1041
- });
1317
+ }
1318
+ return output;
1042
1319
  }
1043
1320
  formatValueToSql(value, type) {
1044
1321
  function toDate(value2) {
@@ -1063,8 +1340,8 @@ var SqliteDialect = class extends DefaultSql {
1063
1340
  fromColumn: entry["from"],
1064
1341
  toTable: entry["table"],
1065
1342
  toColumn: entry["to"],
1066
- on_update: entry["on_update"],
1067
- on_delete: entry["on_delete"]
1343
+ onUpdate: entry["on_update"] ?? "NO ACTION",
1344
+ onDelete: entry["on_delete"] ?? "NO ACTION"
1068
1345
  };
1069
1346
  });
1070
1347
  }
@@ -1097,14 +1374,17 @@ var PostgresDialect = class extends DefaultSql {
1097
1374
  }
1098
1375
  async getColumnInformation(tableName) {
1099
1376
  const data = await this.db.runGetStatement(`SELECT column_name, data_type, column_default FROM information_schema.columns WHERE table_schema = 'public' AND table_name = '${tableName}';`);
1100
- return data.map((entry) => {
1101
- return {
1377
+ const output = {};
1378
+ for (const entry of data) {
1379
+ output[entry["name"]] = {
1102
1380
  name: entry["column_name"],
1103
1381
  type: entry["data_type"],
1382
+ maxLength: 0,
1104
1383
  defaultValue: entry["column_default"],
1105
1384
  isPrimaryKey: false
1106
1385
  };
1107
- });
1386
+ }
1387
+ return output;
1108
1388
  }
1109
1389
  addPrimaryKey(tableName, columnName) {
1110
1390
  return `ALTER TABLE ${tableName} ADD PRIMARY KEY (${columnName});
@@ -1149,18 +1429,21 @@ var MsSqlDialect = class extends DefaultSql {
1149
1429
  });
1150
1430
  }
1151
1431
  async getTableNames() {
1152
- return await this.db.runGetStatement("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'");
1432
+ return (await this.db.runGetStatement("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'")).map((entry) => entry.name);
1153
1433
  }
1154
1434
  async getColumnInformation(tableName) {
1155
1435
  const data = await this.db.runGetStatement(`SELECT COLUMN_NAME, DATA_TYPE, COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = N'${tableName};'`);
1156
- return data.map((entry) => {
1157
- return {
1158
- name: entry["COLUMN_NAME"],
1436
+ const output = {};
1437
+ for (const entry of data) {
1438
+ output[entry["name"]] = {
1439
+ name: entry["name"],
1159
1440
  type: entry["DATA_TYPE"],
1441
+ maxLength: 0,
1160
1442
  defaultValue: entry["COLUMN_DEFAULT"],
1161
- isPrimaryKey: false
1443
+ isPrimaryKey: entry["pk"] == "1"
1162
1444
  };
1163
- });
1445
+ }
1446
+ return output;
1164
1447
  }
1165
1448
  };
1166
1449
 
@@ -1170,9 +1453,26 @@ var MySqlDialect = class extends DefaultSql {
1170
1453
  canAlterPrimaryKey = true;
1171
1454
  canInspectForeignKeys = true;
1172
1455
  canInspectPrimaryKey = true;
1456
+ types = {
1457
+ string: "VARCHAR",
1458
+ number: "INT",
1459
+ bigint: "BIGINT",
1460
+ boolean: "BOOLEAN",
1461
+ date: "DATE",
1462
+ time: "TIME",
1463
+ dateTime: "DATETIME",
1464
+ null: "NULL"
1465
+ };
1466
+ getSqlType(dataType, columnInfo) {
1467
+ switch (dataType) {
1468
+ case "string":
1469
+ return this.types[dataType] + `(${columnInfo?.maxLength})`;
1470
+ default:
1471
+ return super.getSqlType(dataType, columnInfo);
1472
+ }
1473
+ }
1173
1474
  changeForeignKeysState(enabled) {
1174
- return `SET FOREIGN_KEY_CHECKS ${enabled ? "1" : "0"}
1175
- ;`;
1475
+ return `SET FOREIGN_KEY_CHECKS ${enabled ? "1" : "0"};`;
1176
1476
  }
1177
1477
  addForeignKey(fromTableName, foreignKey) {
1178
1478
  return `ALTER TABLE ${fromTableName} ADD ${foreignKey};`;
@@ -1198,18 +1498,22 @@ var MySqlDialect = class extends DefaultSql {
1198
1498
  });
1199
1499
  }
1200
1500
  async getTableNames() {
1201
- return await this.db.runGetStatement("SHOW TABLES;");
1501
+ const t = await this.db.runGetStatement("SELECT table_name FROM information_schema.tables;");
1502
+ return (await this.db.runGetStatement("SELECT table_name FROM information_schema.tables;")).map((entry) => entry.name);
1202
1503
  }
1203
1504
  async getColumnInformation(tableName) {
1204
1505
  const data = await this.db.runGetStatement(`SHOW COLUMNS FROM ${tableName};`);
1205
- return data.map((entry) => {
1206
- return {
1207
- name: entry["Field"],
1208
- type: entry["Type"],
1209
- defaultValue: entry["Default"],
1210
- isPrimaryKey: entry["Key"] == "PRI"
1506
+ const output = {};
1507
+ for (const entry of data) {
1508
+ output[entry["name"]] = {
1509
+ name: entry["name"],
1510
+ type: entry["type"],
1511
+ maxLength: 0,
1512
+ defaultValue: entry["dflt_value"],
1513
+ isPrimaryKey: entry["pk"] == "1"
1211
1514
  };
1212
- });
1515
+ }
1516
+ return output;
1213
1517
  }
1214
1518
  };
1215
1519