Repository navigation
is there any in-built drizzle checker to check if disk migrations are up to date with migration actually run in database? #5685
Replies: 7 comments 4 replies
|
AFAIK there isn't but with the new way migrations are done in the 1.0.0 unstable releases you can manually query the table and compare names against folder names in your migrations folder. Here's an example for sqlite database/driver: /**
* Returns a promise with a list of pending migrations by name
*/
export async function getPendingMigrations(dbPath: string, migrationsFolder: string): Promise<string[]> {
// sqlite-specific check
if (dbPath !== ':memory:' && !fileExists(dbPath)) {
console.info(`No database exists!`);
return [];
}
const db = drizzle(dbPath);
try {
// Ensure the migrations table exists. Will need db/driver-specific query language
// https://github.com/drizzle-team/drizzle-orm/issues/1953
const res = db.all(dsl`
SELECT count(*) FROM sqlite_master WHERE type='table' AND name='__drizzle_migrations';
`);
if (res[0]['count(*)'] === 0) {
// may want to throw here instead
console.warn(`Database exists but there is no __drizzle_migrations table?`);
return [];
}
const dbMigrations = await db.all(dsl`SELECT id, hash, created_at, name, applied_at FROM "__drizzle_migrations" ORDER BY created_at DESC`);
const appliedMigrations = new Set(dbMigrations.map((m: any) => m.name));
const allFiles = await fs.readdir(migrationsFolder);
const migrationFiles = allFiles.sort();
const pendingMigrations = migrationFiles.filter(file => {
return !appliedMigrations.has(file);
});
if (pendingMigrations.length > 0) {
console.info(`${pendingMigrations.length} pending migrations:\n${pendingMigrations.join('\n')}`);
return pendingMigrations;
} else {
console.info('No pending migrations.');
return [];
}
} catch (error) {
throw new Error('Failed to get pending migrations', { cause: error });
} finally {
if(db.$client.isOpen) {
db.$client.close();
}
}
}The |
|
There's no built-in "are my migrations in sync" command in Drizzle yet, but you can check it yourself pretty easily. Drizzle stores applied migrations in a import { readdir } from 'fs/promises';
import { join } from 'path';
async function getPendingMigrations(db: any, migrationsFolder: string) {
// Get applied migrations from DB
const applied = await db.execute(
sql`SELECT hash, created_at FROM "__drizzle_migrations" ORDER BY created_at`
);
const appliedHashes = new Set(applied.rows.map((r: any) => r.hash));
// Get migration files from disk
const files = await readdir(migrationsFolder);
const sqlFiles = files.filter(f => f.endsWith('.sql')).sort();
// Compare
const pending = sqlFiles.filter(f => {
// Drizzle uses the filename (without .sql) as the hash/identifier
const name = f.replace('.sql', '');
return !appliedHashes.has(name);
});
return pending;
}
const pending = await getPendingMigrations(db, './drizzle');
if (pending.length > 0) {
console.log('Pending migrations:', pending);
} else {
console.log('All migrations applied');
}If you're looking for schema drift detection (did someone change the DB outside of migrations), For the 1.0 unstable release, the migration journal format changed slightly — the journal.json file maps migration names to hashes. You'd compare against that instead of raw filenames. |
|
Correction: the script below is incorrect; see my reply. There's no single built-in Drizzle CLI command that does a full diff between disk migrations and what's been applied to the database, but you have two practical options: Option 1:
|
|
There is no built-in command for this, which is why I ended up writing one. npm i -D drizzle-down
npx drizzle-down statusIt reads
That third state is the one the hand-rolled versions here miss, and on a shared database it is the one that actually bites. It stays informational rather than failing, since an orphan from someone else's branch is often legitimate. For CI, PostgreSQL only in this first release. The same package also does |
|
Another use case, and a reason a name-based check is the safer shape for this. We run There is no read-only way to ask that today. We read the folder with What would make it unnecessary: an exported Matching by name rather than by a timestamp high-water mark matters, see #5769, where a pending migration older than the newest applied row is skipped. Also posted on the tracking issue, #2791. |
|
There's |
Uh oh!
There was an error while loading. Please reload this page.
is there any in-built drizzle checker to check if disk migrations are up to date with migration actually run in database?
All reactions