sqlmorpheus 0.2.1 → 0.2.3

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