This commit is contained in:
seb
2026-10-29 03:39:07 +01:00
parent c7db2262b0
commit a5cef78d30
5 changed files with 34 additions and 7 deletions

View File

@@ -305,10 +305,16 @@ export class MssqlProvider {
}
}
async initialize() {
/**
* Initializes the MSSQL schema.
* @param {((message: string) => void) | { log?: (message: string) => void }} [options]
* @returns {Promise<void>}
*/
async initialize(options = {}) {
const pool = await this.ensurePool();
const log = typeof options === 'function' ? options : options?.log;
// Versioned upgrades first, so schema.js never meets an outdated table shape.
await upgradeSchema(this);
await upgradeSchema(this, log);
const { SCHEMA_SCRIPTS } = await import('./schema.js');
for (const script of SCHEMA_SCRIPTS) {

View File

@@ -81,9 +81,13 @@ function makeRunStep(provider) {
*/
export async function upgradeSchema(provider, log) {
const query = (sql, params) => provider.query(sql, params);
if (!(await hasAnyTable(query))) return 0;
if (!(await hasAnyTable(query))) {
log?.(`Fresh database detected; schema will initialize directly at version ${SCHEMA_VERSION}`);
return 0;
}
let current = await readSchemaVersion(query);
if (current === null) {
log?.(`Existing database has no version row; setting baseline version ${BASE_SCHEMA_VERSION}`);
await query(`
IF OBJECT_ID(N'dbo.meta', N'U') IS NULL
CREATE TABLE meta ([key] NVARCHAR(255) NOT NULL, value NVARCHAR(MAX) NOT NULL, CONSTRAINT PK_meta PRIMARY KEY ([key]));

View File

@@ -148,6 +148,11 @@ export async function migrateSchema({ direction, dirUrl, current, target, runSte
throw new Error(`Cannot ${direction} schema below version ${BASE_SCHEMA_VERSION}`);
}
if (current === target) {
log?.(`Schema version ${current} is up to date (no migrations needed)`);
return 0;
}
const byFrom = new Map(listSteps(dirUrl, direction).map((step) => [step.from, step]));
const plan = [];
for (let version = current; version !== target; ) {
@@ -160,14 +165,20 @@ export async function migrateSchema({ direction, dirUrl, current, target, runSte
version = step.to;
}
log?.(`Starting schema ${direction}: version ${current} -> ${target} (${plan.length} step(s) pending)`);
for (const step of plan) {
const start = performance.now();
const mod = await import(step.url.href);
if (typeof mod.default !== 'function') {
throw new Error(`Schema ${direction} step ${step.file} must default-export a function`);
}
await runStep(step, mod.default);
log(`schema ${direction} ${step.from} -> ${step.to} (${step.file})`);
const duration = Math.round(performance.now() - start);
log?.(`Applied schema ${direction} ${step.from} -> ${step.to} (${step.file}) [${duration}ms]`);
}
log?.(`Schema ${direction} completed successfully: database now at version ${target}`);
return plan.length;
}

View File

@@ -357,11 +357,13 @@ export class BetterSqlite3Provider extends BetterSqlite3Executor {
/**
* Initializes the native SQLite schema.
* @param {((message: string) => void) | { log?: (message: string) => void }} [options]
* @returns {Promise<void>}
*/
async initialize() {
async initialize(options = {}) {
const log = typeof options === 'function' ? options : options?.log;
// Versioned upgrades first, so schema.js never meets an outdated table shape.
await upgradeSchema(this.db);
await upgradeSchema(this.db, log);
for (const script of SCHEMA_SCRIPTS) {
if (script && script.trim()) {

View File

@@ -83,9 +83,13 @@ function makeRunStep(db) {
* @param {(message: string) => void} [log]
*/
export async function upgradeSchema(db, log) {
if (!hasAnyTable(db)) return 0;
if (!hasAnyTable(db)) {
log?.(`Fresh database detected; schema will initialize directly at version ${SCHEMA_VERSION}`);
return 0;
}
let current = readSchemaVersion(db);
if (current === null) {
log?.(`Existing database has no version row; setting baseline version ${BASE_SCHEMA_VERSION}`);
db.exec(`CREATE TABLE IF NOT EXISTS meta ("key" TEXT PRIMARY KEY, value TEXT NOT NULL)`);
writeSchemaVersion(db, BASE_SCHEMA_VERSION);
current = BASE_SCHEMA_VERSION;