@berthojoris/mcp-mysql-server 1.10.3 → 1.10.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -7
- package/DOCUMENTATIONS.md +2 -2
- package/dist/index.d.ts +0 -99
- package/dist/mcp-server.js +0 -21
- package/dist/tools/backupRestoreTools.d.ts +1 -6
- package/dist/tools/backupRestoreTools.js +99 -97
- package/dist/tools/constraintTools.d.ts +4 -11
- package/dist/tools/constraintTools.js +114 -115
- package/dist/tools/crudTools.d.ts +2 -6
- package/dist/tools/crudTools.js +186 -189
- package/dist/tools/dataExportTools.d.ts +0 -7
- package/dist/tools/dataExportTools.js +0 -15
- package/dist/tools/databaseTools.d.ts +1 -4
- package/dist/tools/databaseTools.js +29 -33
- package/dist/tools/ddlTools.d.ts +1 -5
- package/dist/tools/ddlTools.js +68 -53
- package/dist/tools/functionTools.d.ts +3 -9
- package/dist/tools/functionTools.js +111 -104
- package/dist/tools/indexTools.d.ts +3 -8
- package/dist/tools/indexTools.js +99 -95
- package/dist/tools/maintenanceTools.d.ts +2 -10
- package/dist/tools/maintenanceTools.js +66 -80
- package/dist/tools/migrationTools.d.ts +0 -5
- package/dist/tools/migrationTools.js +56 -24
- package/dist/tools/performanceTools.d.ts +1 -11
- package/dist/tools/performanceTools.js +278 -267
- package/dist/tools/processTools.d.ts +4 -13
- package/dist/tools/processTools.js +78 -80
- package/dist/tools/queryTools.d.ts +0 -2
- package/dist/tools/queryTools.js +0 -4
- package/dist/tools/schemaVersioningTools.d.ts +0 -9
- package/dist/tools/schemaVersioningTools.js +167 -166
- package/dist/tools/storedProcedureTools.d.ts +2 -4
- package/dist/tools/storedProcedureTools.js +143 -134
- package/dist/tools/transactionTools.d.ts +2 -3
- package/dist/tools/transactionTools.js +28 -29
- package/dist/tools/triggerTools.d.ts +3 -8
- package/dist/tools/triggerTools.js +98 -85
- package/dist/tools/utilityTools.d.ts +0 -1
- package/dist/tools/utilityTools.js +0 -2
- package/dist/tools/viewTools.d.ts +7 -13
- package/dist/tools/viewTools.js +100 -93
- package/package.json +1 -1
|
@@ -45,7 +45,10 @@ class SchemaVersioningTools {
|
|
|
45
45
|
*/
|
|
46
46
|
generateVersion() {
|
|
47
47
|
const now = new Date();
|
|
48
|
-
return now
|
|
48
|
+
return now
|
|
49
|
+
.toISOString()
|
|
50
|
+
.replace(/[-:T.Z]/g, "")
|
|
51
|
+
.slice(0, 14);
|
|
49
52
|
}
|
|
50
53
|
/**
|
|
51
54
|
* Escape string value for SQL
|
|
@@ -82,25 +85,25 @@ class SchemaVersioningTools {
|
|
|
82
85
|
if (!dbValidation.valid) {
|
|
83
86
|
return { status: "error", error: dbValidation.error };
|
|
84
87
|
}
|
|
85
|
-
const createTableQuery = `
|
|
86
|
-
CREATE TABLE IF NOT EXISTS ${this.migrationsTable} (
|
|
87
|
-
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
88
|
-
version VARCHAR(14) NOT NULL UNIQUE,
|
|
89
|
-
name VARCHAR(255) NOT NULL,
|
|
90
|
-
description TEXT,
|
|
91
|
-
up_sql LONGTEXT NOT NULL,
|
|
92
|
-
down_sql LONGTEXT,
|
|
93
|
-
checksum VARCHAR(64),
|
|
94
|
-
applied_at TIMESTAMP NULL DEFAULT NULL,
|
|
95
|
-
applied_by VARCHAR(255),
|
|
96
|
-
execution_time_ms INT,
|
|
97
|
-
status ENUM('pending', 'applied', 'failed', 'rolled_back') DEFAULT 'pending',
|
|
98
|
-
error_message TEXT,
|
|
99
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
100
|
-
INDEX idx_version (version),
|
|
101
|
-
INDEX idx_status (status),
|
|
102
|
-
INDEX idx_applied_at (applied_at)
|
|
103
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
88
|
+
const createTableQuery = `
|
|
89
|
+
CREATE TABLE IF NOT EXISTS ${this.migrationsTable} (
|
|
90
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
91
|
+
version VARCHAR(14) NOT NULL UNIQUE,
|
|
92
|
+
name VARCHAR(255) NOT NULL,
|
|
93
|
+
description TEXT,
|
|
94
|
+
up_sql LONGTEXT NOT NULL,
|
|
95
|
+
down_sql LONGTEXT,
|
|
96
|
+
checksum VARCHAR(64),
|
|
97
|
+
applied_at TIMESTAMP NULL DEFAULT NULL,
|
|
98
|
+
applied_by VARCHAR(255),
|
|
99
|
+
execution_time_ms INT,
|
|
100
|
+
status ENUM('pending', 'applied', 'failed', 'rolled_back') DEFAULT 'pending',
|
|
101
|
+
error_message TEXT,
|
|
102
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
103
|
+
INDEX idx_version (version),
|
|
104
|
+
INDEX idx_status (status),
|
|
105
|
+
INDEX idx_applied_at (applied_at)
|
|
106
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
104
107
|
`;
|
|
105
108
|
await this.db.query(createTableQuery);
|
|
106
109
|
return {
|
|
@@ -109,14 +112,12 @@ class SchemaVersioningTools {
|
|
|
109
112
|
message: `Migrations table '${this.migrationsTable}' initialized successfully`,
|
|
110
113
|
table_name: this.migrationsTable,
|
|
111
114
|
},
|
|
112
|
-
queryLog: this.db.getFormattedQueryLogs(1),
|
|
113
115
|
};
|
|
114
116
|
}
|
|
115
117
|
catch (error) {
|
|
116
118
|
return {
|
|
117
119
|
status: "error",
|
|
118
120
|
error: error.message,
|
|
119
|
-
queryLog: this.db.getFormattedQueryLogs(1),
|
|
120
121
|
};
|
|
121
122
|
}
|
|
122
123
|
}
|
|
@@ -125,7 +126,7 @@ class SchemaVersioningTools {
|
|
|
125
126
|
*/
|
|
126
127
|
async createMigration(params) {
|
|
127
128
|
try {
|
|
128
|
-
const { name, up_sql, down_sql, description, version, database
|
|
129
|
+
const { name, up_sql, down_sql, description, version, database } = params;
|
|
129
130
|
// Validate database access
|
|
130
131
|
const dbValidation = this.validateDatabaseAccess(database);
|
|
131
132
|
if (!dbValidation.valid) {
|
|
@@ -146,7 +147,9 @@ class SchemaVersioningTools {
|
|
|
146
147
|
const checksum = this.generateChecksum(up_sql);
|
|
147
148
|
// Check if version already exists
|
|
148
149
|
const existingQuery = `SELECT id FROM ${this.migrationsTable} WHERE version = ?`;
|
|
149
|
-
const existing = await this.db.query(existingQuery, [
|
|
150
|
+
const existing = await this.db.query(existingQuery, [
|
|
151
|
+
migrationVersion,
|
|
152
|
+
]);
|
|
150
153
|
if (existing.length > 0) {
|
|
151
154
|
return {
|
|
152
155
|
status: "error",
|
|
@@ -154,10 +157,10 @@ class SchemaVersioningTools {
|
|
|
154
157
|
};
|
|
155
158
|
}
|
|
156
159
|
// Insert the migration
|
|
157
|
-
const insertQuery = `
|
|
158
|
-
INSERT INTO ${this.migrationsTable}
|
|
159
|
-
(version, name, description, up_sql, down_sql, checksum, status)
|
|
160
|
-
VALUES (?, ?, ?, ?, ?, ?, 'pending')
|
|
160
|
+
const insertQuery = `
|
|
161
|
+
INSERT INTO ${this.migrationsTable}
|
|
162
|
+
(version, name, description, up_sql, down_sql, checksum, status)
|
|
163
|
+
VALUES (?, ?, ?, ?, ?, ?, 'pending')
|
|
161
164
|
`;
|
|
162
165
|
await this.db.query(insertQuery, [
|
|
163
166
|
migrationVersion,
|
|
@@ -176,14 +179,12 @@ class SchemaVersioningTools {
|
|
|
176
179
|
checksum,
|
|
177
180
|
status: "pending",
|
|
178
181
|
},
|
|
179
|
-
queryLog: this.db.getFormattedQueryLogs(3),
|
|
180
182
|
};
|
|
181
183
|
}
|
|
182
184
|
catch (error) {
|
|
183
185
|
return {
|
|
184
186
|
status: "error",
|
|
185
187
|
error: error.message,
|
|
186
|
-
queryLog: this.db.getFormattedQueryLogs(1),
|
|
187
188
|
};
|
|
188
189
|
}
|
|
189
190
|
}
|
|
@@ -195,10 +196,10 @@ class SchemaVersioningTools {
|
|
|
195
196
|
const str = sql.trim();
|
|
196
197
|
for (let i = 0; i < str.length; i++) {
|
|
197
198
|
const char = str.charCodeAt(i);
|
|
198
|
-
hash = (
|
|
199
|
+
hash = (hash << 5) - hash + char;
|
|
199
200
|
hash = hash & hash; // Convert to 32bit integer
|
|
200
201
|
}
|
|
201
|
-
return Math.abs(hash).toString(16).padStart(8,
|
|
202
|
+
return Math.abs(hash).toString(16).padStart(8, "0");
|
|
202
203
|
}
|
|
203
204
|
/**
|
|
204
205
|
* Apply pending migrations
|
|
@@ -215,10 +216,10 @@ class SchemaVersioningTools {
|
|
|
215
216
|
await this.initMigrationsTable({ database });
|
|
216
217
|
let queryCount = 1;
|
|
217
218
|
// Get pending migrations
|
|
218
|
-
let pendingQuery = `
|
|
219
|
-
SELECT id, version, name, up_sql, checksum
|
|
220
|
-
FROM ${this.migrationsTable}
|
|
221
|
-
WHERE status = 'pending'
|
|
219
|
+
let pendingQuery = `
|
|
220
|
+
SELECT id, version, name, up_sql, checksum
|
|
221
|
+
FROM ${this.migrationsTable}
|
|
222
|
+
WHERE status = 'pending'
|
|
222
223
|
`;
|
|
223
224
|
if (target_version) {
|
|
224
225
|
pendingQuery += ` AND version <= ?`;
|
|
@@ -236,7 +237,6 @@ class SchemaVersioningTools {
|
|
|
236
237
|
applied_count: 0,
|
|
237
238
|
migrations: [],
|
|
238
239
|
},
|
|
239
|
-
queryLog: this.db.getFormattedQueryLogs(queryCount),
|
|
240
240
|
};
|
|
241
241
|
}
|
|
242
242
|
if (dry_run) {
|
|
@@ -248,10 +248,10 @@ class SchemaVersioningTools {
|
|
|
248
248
|
migrations: pendingMigrations.map((m) => ({
|
|
249
249
|
version: m.version,
|
|
250
250
|
name: m.name,
|
|
251
|
-
up_sql_preview: m.up_sql.substring(0, 200) +
|
|
251
|
+
up_sql_preview: m.up_sql.substring(0, 200) +
|
|
252
|
+
(m.up_sql.length > 200 ? "..." : ""),
|
|
252
253
|
})),
|
|
253
254
|
},
|
|
254
|
-
queryLog: this.db.getFormattedQueryLogs(queryCount),
|
|
255
255
|
};
|
|
256
256
|
}
|
|
257
257
|
const appliedMigrations = [];
|
|
@@ -270,16 +270,20 @@ class SchemaVersioningTools {
|
|
|
270
270
|
}
|
|
271
271
|
const executionTime = Date.now() - startTime;
|
|
272
272
|
// Update migration status to applied
|
|
273
|
-
const updateQuery = `
|
|
274
|
-
UPDATE ${this.migrationsTable}
|
|
275
|
-
SET status = 'applied',
|
|
276
|
-
applied_at = NOW(),
|
|
277
|
-
applied_by = ?,
|
|
278
|
-
execution_time_ms = ?,
|
|
279
|
-
error_message = NULL
|
|
280
|
-
WHERE id = ?
|
|
273
|
+
const updateQuery = `
|
|
274
|
+
UPDATE ${this.migrationsTable}
|
|
275
|
+
SET status = 'applied',
|
|
276
|
+
applied_at = NOW(),
|
|
277
|
+
applied_by = ?,
|
|
278
|
+
execution_time_ms = ?,
|
|
279
|
+
error_message = NULL
|
|
280
|
+
WHERE id = ?
|
|
281
281
|
`;
|
|
282
|
-
await this.db.query(updateQuery, [
|
|
282
|
+
await this.db.query(updateQuery, [
|
|
283
|
+
currentUser,
|
|
284
|
+
executionTime,
|
|
285
|
+
migration.id,
|
|
286
|
+
]);
|
|
283
287
|
queryCount++;
|
|
284
288
|
appliedMigrations.push({
|
|
285
289
|
version: migration.version,
|
|
@@ -290,12 +294,12 @@ class SchemaVersioningTools {
|
|
|
290
294
|
catch (error) {
|
|
291
295
|
const executionTime = Date.now() - startTime;
|
|
292
296
|
// Update migration status to failed
|
|
293
|
-
const updateQuery = `
|
|
294
|
-
UPDATE ${this.migrationsTable}
|
|
295
|
-
SET status = 'failed',
|
|
296
|
-
execution_time_ms = ?,
|
|
297
|
-
error_message = ?
|
|
298
|
-
WHERE id = ?
|
|
297
|
+
const updateQuery = `
|
|
298
|
+
UPDATE ${this.migrationsTable}
|
|
299
|
+
SET status = 'failed',
|
|
300
|
+
execution_time_ms = ?,
|
|
301
|
+
error_message = ?
|
|
302
|
+
WHERE id = ?
|
|
299
303
|
`;
|
|
300
304
|
await this.db.query(updateQuery, [
|
|
301
305
|
executionTime,
|
|
@@ -324,14 +328,12 @@ class SchemaVersioningTools {
|
|
|
324
328
|
applied_migrations: appliedMigrations,
|
|
325
329
|
failed_migrations: failedMigrations,
|
|
326
330
|
},
|
|
327
|
-
queryLog: this.db.getFormattedQueryLogs(queryCount),
|
|
328
331
|
};
|
|
329
332
|
}
|
|
330
333
|
catch (error) {
|
|
331
334
|
return {
|
|
332
335
|
status: "error",
|
|
333
336
|
error: error.message,
|
|
334
|
-
queryLog: this.db.getFormattedQueryLogs(1),
|
|
335
337
|
};
|
|
336
338
|
}
|
|
337
339
|
}
|
|
@@ -424,21 +426,21 @@ class SchemaVersioningTools {
|
|
|
424
426
|
let rollbackQuery;
|
|
425
427
|
let queryParams = [];
|
|
426
428
|
if (target_version) {
|
|
427
|
-
rollbackQuery = `
|
|
428
|
-
SELECT id, version, name, down_sql
|
|
429
|
-
FROM ${this.migrationsTable}
|
|
430
|
-
WHERE status = 'applied' AND version > ?
|
|
431
|
-
ORDER BY version DESC
|
|
429
|
+
rollbackQuery = `
|
|
430
|
+
SELECT id, version, name, down_sql
|
|
431
|
+
FROM ${this.migrationsTable}
|
|
432
|
+
WHERE status = 'applied' AND version > ?
|
|
433
|
+
ORDER BY version DESC
|
|
432
434
|
`;
|
|
433
435
|
queryParams = [target_version];
|
|
434
436
|
}
|
|
435
437
|
else {
|
|
436
|
-
rollbackQuery = `
|
|
437
|
-
SELECT id, version, name, down_sql
|
|
438
|
-
FROM ${this.migrationsTable}
|
|
439
|
-
WHERE status = 'applied'
|
|
440
|
-
ORDER BY version DESC
|
|
441
|
-
LIMIT ?
|
|
438
|
+
rollbackQuery = `
|
|
439
|
+
SELECT id, version, name, down_sql
|
|
440
|
+
FROM ${this.migrationsTable}
|
|
441
|
+
WHERE status = 'applied'
|
|
442
|
+
ORDER BY version DESC
|
|
443
|
+
LIMIT ?
|
|
442
444
|
`;
|
|
443
445
|
queryParams = [steps];
|
|
444
446
|
}
|
|
@@ -452,7 +454,6 @@ class SchemaVersioningTools {
|
|
|
452
454
|
rolled_back_count: 0,
|
|
453
455
|
migrations: [],
|
|
454
456
|
},
|
|
455
|
-
queryLog: this.db.getFormattedQueryLogs(queryCount),
|
|
456
457
|
};
|
|
457
458
|
}
|
|
458
459
|
// Check if all migrations have down_sql
|
|
@@ -474,11 +475,11 @@ class SchemaVersioningTools {
|
|
|
474
475
|
name: m.name,
|
|
475
476
|
has_down_sql: !!m.down_sql,
|
|
476
477
|
down_sql_preview: m.down_sql
|
|
477
|
-
? m.down_sql.substring(0, 200) +
|
|
478
|
+
? m.down_sql.substring(0, 200) +
|
|
479
|
+
(m.down_sql.length > 200 ? "..." : "")
|
|
478
480
|
: null,
|
|
479
481
|
})),
|
|
480
482
|
},
|
|
481
|
-
queryLog: this.db.getFormattedQueryLogs(queryCount),
|
|
482
483
|
};
|
|
483
484
|
}
|
|
484
485
|
const rolledBackMigrations = [];
|
|
@@ -496,14 +497,14 @@ class SchemaVersioningTools {
|
|
|
496
497
|
}
|
|
497
498
|
const executionTime = Date.now() - startTime;
|
|
498
499
|
// Update migration status to rolled_back
|
|
499
|
-
const updateQuery = `
|
|
500
|
-
UPDATE ${this.migrationsTable}
|
|
501
|
-
SET status = 'rolled_back',
|
|
502
|
-
applied_at = NULL,
|
|
503
|
-
applied_by = NULL,
|
|
504
|
-
execution_time_ms = ?,
|
|
505
|
-
error_message = NULL
|
|
506
|
-
WHERE id = ?
|
|
500
|
+
const updateQuery = `
|
|
501
|
+
UPDATE ${this.migrationsTable}
|
|
502
|
+
SET status = 'rolled_back',
|
|
503
|
+
applied_at = NULL,
|
|
504
|
+
applied_by = NULL,
|
|
505
|
+
execution_time_ms = ?,
|
|
506
|
+
error_message = NULL
|
|
507
|
+
WHERE id = ?
|
|
507
508
|
`;
|
|
508
509
|
await this.db.query(updateQuery, [executionTime, migration.id]);
|
|
509
510
|
queryCount++;
|
|
@@ -536,14 +537,12 @@ class SchemaVersioningTools {
|
|
|
536
537
|
rolled_back_migrations: rolledBackMigrations,
|
|
537
538
|
failed_rollbacks: failedRollbacks,
|
|
538
539
|
},
|
|
539
|
-
queryLog: this.db.getFormattedQueryLogs(queryCount),
|
|
540
540
|
};
|
|
541
541
|
}
|
|
542
542
|
catch (error) {
|
|
543
543
|
return {
|
|
544
544
|
status: "error",
|
|
545
545
|
error: error.message,
|
|
546
|
-
queryLog: this.db.getFormattedQueryLogs(1),
|
|
547
546
|
};
|
|
548
547
|
}
|
|
549
548
|
}
|
|
@@ -562,21 +561,21 @@ class SchemaVersioningTools {
|
|
|
562
561
|
await this.initMigrationsTable({ database });
|
|
563
562
|
let queryCount = 1;
|
|
564
563
|
// Build query
|
|
565
|
-
let query = `
|
|
566
|
-
SELECT
|
|
567
|
-
id,
|
|
568
|
-
version,
|
|
569
|
-
name,
|
|
570
|
-
description,
|
|
571
|
-
checksum,
|
|
572
|
-
status,
|
|
573
|
-
applied_at,
|
|
574
|
-
applied_by,
|
|
575
|
-
execution_time_ms,
|
|
576
|
-
error_message,
|
|
577
|
-
created_at
|
|
578
|
-
FROM ${this.migrationsTable}
|
|
579
|
-
WHERE 1=1
|
|
564
|
+
let query = `
|
|
565
|
+
SELECT
|
|
566
|
+
id,
|
|
567
|
+
version,
|
|
568
|
+
name,
|
|
569
|
+
description,
|
|
570
|
+
checksum,
|
|
571
|
+
status,
|
|
572
|
+
applied_at,
|
|
573
|
+
applied_by,
|
|
574
|
+
execution_time_ms,
|
|
575
|
+
error_message,
|
|
576
|
+
created_at
|
|
577
|
+
FROM ${this.migrationsTable}
|
|
578
|
+
WHERE 1=1
|
|
580
579
|
`;
|
|
581
580
|
const queryParams = [];
|
|
582
581
|
if (version) {
|
|
@@ -592,12 +591,12 @@ class SchemaVersioningTools {
|
|
|
592
591
|
const migrations = await this.db.query(query, queryParams);
|
|
593
592
|
queryCount++;
|
|
594
593
|
// Get summary statistics
|
|
595
|
-
const summaryQuery = `
|
|
596
|
-
SELECT
|
|
597
|
-
status,
|
|
598
|
-
COUNT(*) as count
|
|
599
|
-
FROM ${this.migrationsTable}
|
|
600
|
-
GROUP BY status
|
|
594
|
+
const summaryQuery = `
|
|
595
|
+
SELECT
|
|
596
|
+
status,
|
|
597
|
+
COUNT(*) as count
|
|
598
|
+
FROM ${this.migrationsTable}
|
|
599
|
+
GROUP BY status
|
|
601
600
|
`;
|
|
602
601
|
const summary = await this.db.query(summaryQuery);
|
|
603
602
|
queryCount++;
|
|
@@ -606,12 +605,12 @@ class SchemaVersioningTools {
|
|
|
606
605
|
summaryMap[row.status] = row.count;
|
|
607
606
|
}
|
|
608
607
|
// Get current schema version
|
|
609
|
-
const currentVersionQuery = `
|
|
610
|
-
SELECT version
|
|
611
|
-
FROM ${this.migrationsTable}
|
|
612
|
-
WHERE status = 'applied'
|
|
613
|
-
ORDER BY version DESC
|
|
614
|
-
LIMIT 1
|
|
608
|
+
const currentVersionQuery = `
|
|
609
|
+
SELECT version
|
|
610
|
+
FROM ${this.migrationsTable}
|
|
611
|
+
WHERE status = 'applied'
|
|
612
|
+
ORDER BY version DESC
|
|
613
|
+
LIMIT 1
|
|
615
614
|
`;
|
|
616
615
|
const currentVersionResult = await this.db.query(currentVersionQuery);
|
|
617
616
|
queryCount++;
|
|
@@ -635,14 +634,12 @@ class SchemaVersioningTools {
|
|
|
635
634
|
created_at: m.created_at ? m.created_at.toISOString() : null,
|
|
636
635
|
})),
|
|
637
636
|
},
|
|
638
|
-
queryLog: this.db.getFormattedQueryLogs(queryCount),
|
|
639
637
|
};
|
|
640
638
|
}
|
|
641
639
|
catch (error) {
|
|
642
640
|
return {
|
|
643
641
|
status: "error",
|
|
644
642
|
error: error.message,
|
|
645
|
-
queryLog: this.db.getFormattedQueryLogs(1),
|
|
646
643
|
};
|
|
647
644
|
}
|
|
648
645
|
}
|
|
@@ -658,13 +655,15 @@ class SchemaVersioningTools {
|
|
|
658
655
|
return { status: "error", error: dbValidation.error };
|
|
659
656
|
}
|
|
660
657
|
// Check if migrations table exists
|
|
661
|
-
const tableExistsQuery = `
|
|
662
|
-
SELECT COUNT(*) as cnt
|
|
663
|
-
FROM information_schema.tables
|
|
664
|
-
WHERE table_schema = DATABASE()
|
|
665
|
-
AND table_name = ?
|
|
658
|
+
const tableExistsQuery = `
|
|
659
|
+
SELECT COUNT(*) as cnt
|
|
660
|
+
FROM information_schema.tables
|
|
661
|
+
WHERE table_schema = DATABASE()
|
|
662
|
+
AND table_name = ?
|
|
666
663
|
`;
|
|
667
|
-
const tableExists = await this.db.query(tableExistsQuery, [
|
|
664
|
+
const tableExists = await this.db.query(tableExistsQuery, [
|
|
665
|
+
this.migrationsTable,
|
|
666
|
+
]);
|
|
668
667
|
if (tableExists[0].cnt === 0) {
|
|
669
668
|
return {
|
|
670
669
|
status: "success",
|
|
@@ -673,19 +672,18 @@ class SchemaVersioningTools {
|
|
|
673
672
|
message: "No migrations have been tracked yet",
|
|
674
673
|
migrations_table_exists: false,
|
|
675
674
|
},
|
|
676
|
-
queryLog: this.db.getFormattedQueryLogs(1),
|
|
677
675
|
};
|
|
678
676
|
}
|
|
679
677
|
// Get current version
|
|
680
|
-
const versionQuery = `
|
|
681
|
-
SELECT
|
|
682
|
-
version,
|
|
683
|
-
name,
|
|
684
|
-
applied_at
|
|
685
|
-
FROM ${this.migrationsTable}
|
|
686
|
-
WHERE status = 'applied'
|
|
687
|
-
ORDER BY version DESC
|
|
688
|
-
LIMIT 1
|
|
678
|
+
const versionQuery = `
|
|
679
|
+
SELECT
|
|
680
|
+
version,
|
|
681
|
+
name,
|
|
682
|
+
applied_at
|
|
683
|
+
FROM ${this.migrationsTable}
|
|
684
|
+
WHERE status = 'applied'
|
|
685
|
+
ORDER BY version DESC
|
|
686
|
+
LIMIT 1
|
|
689
687
|
`;
|
|
690
688
|
const versionResult = await this.db.query(versionQuery);
|
|
691
689
|
if (versionResult.length === 0) {
|
|
@@ -696,15 +694,14 @@ class SchemaVersioningTools {
|
|
|
696
694
|
message: "No migrations have been applied yet",
|
|
697
695
|
migrations_table_exists: true,
|
|
698
696
|
},
|
|
699
|
-
queryLog: this.db.getFormattedQueryLogs(2),
|
|
700
697
|
};
|
|
701
698
|
}
|
|
702
699
|
const current = versionResult[0];
|
|
703
700
|
// Count pending migrations
|
|
704
|
-
const pendingQuery = `
|
|
705
|
-
SELECT COUNT(*) as cnt
|
|
706
|
-
FROM ${this.migrationsTable}
|
|
707
|
-
WHERE status = 'pending'
|
|
701
|
+
const pendingQuery = `
|
|
702
|
+
SELECT COUNT(*) as cnt
|
|
703
|
+
FROM ${this.migrationsTable}
|
|
704
|
+
WHERE status = 'pending'
|
|
708
705
|
`;
|
|
709
706
|
const pendingResult = await this.db.query(pendingQuery);
|
|
710
707
|
return {
|
|
@@ -712,18 +709,18 @@ class SchemaVersioningTools {
|
|
|
712
709
|
data: {
|
|
713
710
|
current_version: current.version,
|
|
714
711
|
current_migration_name: current.name,
|
|
715
|
-
applied_at: current.applied_at
|
|
712
|
+
applied_at: current.applied_at
|
|
713
|
+
? current.applied_at.toISOString()
|
|
714
|
+
: null,
|
|
716
715
|
pending_migrations: pendingResult[0].cnt,
|
|
717
716
|
migrations_table_exists: true,
|
|
718
717
|
},
|
|
719
|
-
queryLog: this.db.getFormattedQueryLogs(3),
|
|
720
718
|
};
|
|
721
719
|
}
|
|
722
720
|
catch (error) {
|
|
723
721
|
return {
|
|
724
722
|
status: "error",
|
|
725
723
|
error: error.message,
|
|
726
|
-
queryLog: this.db.getFormattedQueryLogs(1),
|
|
727
724
|
};
|
|
728
725
|
}
|
|
729
726
|
}
|
|
@@ -742,17 +739,17 @@ class SchemaVersioningTools {
|
|
|
742
739
|
await this.initMigrationsTable({ database });
|
|
743
740
|
let queryCount = 1;
|
|
744
741
|
// Get all migrations
|
|
745
|
-
const migrationsQuery = `
|
|
746
|
-
SELECT
|
|
747
|
-
id,
|
|
748
|
-
version,
|
|
749
|
-
name,
|
|
750
|
-
up_sql,
|
|
751
|
-
down_sql,
|
|
752
|
-
checksum,
|
|
753
|
-
status
|
|
754
|
-
FROM ${this.migrationsTable}
|
|
755
|
-
ORDER BY version ASC
|
|
742
|
+
const migrationsQuery = `
|
|
743
|
+
SELECT
|
|
744
|
+
id,
|
|
745
|
+
version,
|
|
746
|
+
name,
|
|
747
|
+
up_sql,
|
|
748
|
+
down_sql,
|
|
749
|
+
checksum,
|
|
750
|
+
status
|
|
751
|
+
FROM ${this.migrationsTable}
|
|
752
|
+
ORDER BY version ASC
|
|
756
753
|
`;
|
|
757
754
|
const migrations = await this.db.query(migrationsQuery);
|
|
758
755
|
queryCount++;
|
|
@@ -826,17 +823,16 @@ class SchemaVersioningTools {
|
|
|
826
823
|
pending: migrations.filter((m) => m.status === "pending").length,
|
|
827
824
|
applied: migrations.filter((m) => m.status === "applied").length,
|
|
828
825
|
failed: migrations.filter((m) => m.status === "failed").length,
|
|
829
|
-
rolled_back: migrations.filter((m) => m.status === "rolled_back")
|
|
826
|
+
rolled_back: migrations.filter((m) => m.status === "rolled_back")
|
|
827
|
+
.length,
|
|
830
828
|
},
|
|
831
829
|
},
|
|
832
|
-
queryLog: this.db.getFormattedQueryLogs(queryCount),
|
|
833
830
|
};
|
|
834
831
|
}
|
|
835
832
|
catch (error) {
|
|
836
833
|
return {
|
|
837
834
|
status: "error",
|
|
838
835
|
error: error.message,
|
|
839
|
-
queryLog: this.db.getFormattedQueryLogs(1),
|
|
840
836
|
};
|
|
841
837
|
}
|
|
842
838
|
}
|
|
@@ -852,10 +848,10 @@ class SchemaVersioningTools {
|
|
|
852
848
|
return { status: "error", error: dbValidation.error };
|
|
853
849
|
}
|
|
854
850
|
// Check if migration exists and is failed
|
|
855
|
-
const checkQuery = `
|
|
856
|
-
SELECT id, name, status
|
|
857
|
-
FROM ${this.migrationsTable}
|
|
858
|
-
WHERE version = ?
|
|
851
|
+
const checkQuery = `
|
|
852
|
+
SELECT id, name, status
|
|
853
|
+
FROM ${this.migrationsTable}
|
|
854
|
+
WHERE version = ?
|
|
859
855
|
`;
|
|
860
856
|
const migration = await this.db.query(checkQuery, [version]);
|
|
861
857
|
if (migration.length === 0) {
|
|
@@ -871,12 +867,12 @@ class SchemaVersioningTools {
|
|
|
871
867
|
};
|
|
872
868
|
}
|
|
873
869
|
// Reset to pending
|
|
874
|
-
const updateQuery = `
|
|
875
|
-
UPDATE ${this.migrationsTable}
|
|
876
|
-
SET status = 'pending',
|
|
877
|
-
error_message = NULL,
|
|
878
|
-
execution_time_ms = NULL
|
|
879
|
-
WHERE version = ?
|
|
870
|
+
const updateQuery = `
|
|
871
|
+
UPDATE ${this.migrationsTable}
|
|
872
|
+
SET status = 'pending',
|
|
873
|
+
error_message = NULL,
|
|
874
|
+
execution_time_ms = NULL
|
|
875
|
+
WHERE version = ?
|
|
880
876
|
`;
|
|
881
877
|
await this.db.query(updateQuery, [version]);
|
|
882
878
|
return {
|
|
@@ -888,14 +884,12 @@ class SchemaVersioningTools {
|
|
|
888
884
|
previous_status: "failed",
|
|
889
885
|
new_status: "pending",
|
|
890
886
|
},
|
|
891
|
-
queryLog: this.db.getFormattedQueryLogs(2),
|
|
892
887
|
};
|
|
893
888
|
}
|
|
894
889
|
catch (error) {
|
|
895
890
|
return {
|
|
896
891
|
status: "error",
|
|
897
892
|
error: error.message,
|
|
898
|
-
queryLog: this.db.getFormattedQueryLogs(1),
|
|
899
893
|
};
|
|
900
894
|
}
|
|
901
895
|
}
|
|
@@ -913,11 +907,17 @@ class SchemaVersioningTools {
|
|
|
913
907
|
// Validate table names
|
|
914
908
|
const table1Validation = this.security.validateIdentifier(table1);
|
|
915
909
|
if (!table1Validation.valid) {
|
|
916
|
-
return {
|
|
910
|
+
return {
|
|
911
|
+
status: "error",
|
|
912
|
+
error: `Invalid table1 name: ${table1Validation.error}`,
|
|
913
|
+
};
|
|
917
914
|
}
|
|
918
915
|
const table2Validation = this.security.validateIdentifier(table2);
|
|
919
916
|
if (!table2Validation.valid) {
|
|
920
|
-
return {
|
|
917
|
+
return {
|
|
918
|
+
status: "error",
|
|
919
|
+
error: `Invalid table2 name: ${table2Validation.error}`,
|
|
920
|
+
};
|
|
921
921
|
}
|
|
922
922
|
const escapedTable1 = this.security.escapeIdentifier(table1);
|
|
923
923
|
const escapedTable2 = this.security.escapeIdentifier(table2);
|
|
@@ -932,7 +932,9 @@ class SchemaVersioningTools {
|
|
|
932
932
|
for (const [name, col] of columns1) {
|
|
933
933
|
if (!columns2.has(name)) {
|
|
934
934
|
const nullable = col.Null === "YES" ? "NULL" : "NOT NULL";
|
|
935
|
-
const defaultVal = col.Default !== null
|
|
935
|
+
const defaultVal = col.Default !== null
|
|
936
|
+
? ` DEFAULT ${this.escapeValue(col.Default)}`
|
|
937
|
+
: "";
|
|
936
938
|
upStatements.push(`ALTER TABLE ${escapedTable2} ADD COLUMN \`${name}\` ${col.Type} ${nullable}${defaultVal};`);
|
|
937
939
|
downStatements.push(`ALTER TABLE ${escapedTable2} DROP COLUMN \`${name}\`;`);
|
|
938
940
|
}
|
|
@@ -942,7 +944,9 @@ class SchemaVersioningTools {
|
|
|
942
944
|
if (!columns1.has(name)) {
|
|
943
945
|
upStatements.push(`ALTER TABLE ${escapedTable2} DROP COLUMN \`${name}\`;`);
|
|
944
946
|
const nullable = col.Null === "YES" ? "NULL" : "NOT NULL";
|
|
945
|
-
const defaultVal = col.Default !== null
|
|
947
|
+
const defaultVal = col.Default !== null
|
|
948
|
+
? ` DEFAULT ${this.escapeValue(col.Default)}`
|
|
949
|
+
: "";
|
|
946
950
|
downStatements.push(`ALTER TABLE ${escapedTable2} ADD COLUMN \`${name}\` ${col.Type} ${nullable}${defaultVal};`);
|
|
947
951
|
}
|
|
948
952
|
}
|
|
@@ -965,7 +969,6 @@ class SchemaVersioningTools {
|
|
|
965
969
|
table2,
|
|
966
970
|
differences: 0,
|
|
967
971
|
},
|
|
968
|
-
queryLog: this.db.getFormattedQueryLogs(2),
|
|
969
972
|
};
|
|
970
973
|
}
|
|
971
974
|
const upSql = upStatements.join("\n");
|
|
@@ -992,14 +995,12 @@ class SchemaVersioningTools {
|
|
|
992
995
|
source_table: table1,
|
|
993
996
|
target_table: table2,
|
|
994
997
|
},
|
|
995
|
-
queryLog: this.db.getFormattedQueryLogs(4),
|
|
996
998
|
};
|
|
997
999
|
}
|
|
998
1000
|
catch (error) {
|
|
999
1001
|
return {
|
|
1000
1002
|
status: "error",
|
|
1001
1003
|
error: error.message,
|
|
1002
|
-
queryLog: this.db.getFormattedQueryLogs(1),
|
|
1003
1004
|
};
|
|
1004
1005
|
}
|
|
1005
1006
|
}
|