fix: skip comment-only migration SQL
This commit is contained in:
@@ -51,6 +51,50 @@ function section(content: string, which: "up" | "down"): string {
|
||||
return (next ? rest.slice(0, next.index) : rest).trim();
|
||||
}
|
||||
|
||||
function hasExecutableSql(sql: string): boolean {
|
||||
let quote = "";
|
||||
let lineComment = false;
|
||||
let blockComment = false;
|
||||
for (let index = 0; index < sql.length; index++) {
|
||||
const char = sql[index]!;
|
||||
const next = sql[index + 1] ?? "";
|
||||
if (lineComment) {
|
||||
if (char === "\n" || char === "\r") lineComment = false;
|
||||
continue;
|
||||
}
|
||||
if (blockComment) {
|
||||
if (char === "*" && next === "/") {
|
||||
blockComment = false;
|
||||
index++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (quote) {
|
||||
if (char === quote) {
|
||||
if (next === quote) index++;
|
||||
else quote = "";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (char === "-" && next === "-") {
|
||||
lineComment = true;
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
if (char === "/" && next === "*") {
|
||||
blockComment = true;
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
if (char === "'" || char === '"' || char === "`") {
|
||||
quote = char;
|
||||
return true;
|
||||
}
|
||||
if (!/\s|;/.test(char)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Load and parse all migration files in a directory, sorted by filename. */
|
||||
export function loadMigrations(dir: string): Migration[] {
|
||||
if (!existsSync(dir)) return [];
|
||||
@@ -136,7 +180,7 @@ export async function applyMigrations(
|
||||
for (const migration of pending.filter(({ name }) => !current.has(name))) {
|
||||
throwIfAborted(options.signal);
|
||||
await db.tx(async (tx) => {
|
||||
if (migration.up) await tx.exec(migration.up);
|
||||
if (hasExecutableSql(migration.up)) await tx.exec(migration.up);
|
||||
await tx.exec(`INSERT INTO ${MIGRATIONS_TABLE} (name) VALUES (?)`, [migration.name]);
|
||||
});
|
||||
done.push(migration.name);
|
||||
@@ -175,7 +219,7 @@ export async function rollback(
|
||||
try {
|
||||
throwIfAborted(options.signal);
|
||||
await db.tx(async (tx) => {
|
||||
if (migration?.down) await tx.exec(migration.down);
|
||||
if (migration && hasExecutableSql(migration.down)) await tx.exec(migration.down);
|
||||
await tx.exec(`DELETE FROM ${MIGRATIONS_TABLE} WHERE name = ?`, [last]);
|
||||
});
|
||||
return last;
|
||||
|
||||
Reference in New Issue
Block a user