-
Notifications
You must be signed in to change notification settings - Fork 800
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: new database migration strategy (#219)
* formula overflow * fix: new database migration strategy * ci: add more error message * fix: change typ to 'local' | 'remote' --------- Co-authored-by: hzy <[email protected]>
- Loading branch information
1 parent
c827475
commit aacb021
Showing
6 changed files
with
119 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,53 @@ | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
import {execSync} from 'child_process'; | ||
import { execSync } from 'child_process'; | ||
import { fixTopField, getMigrationVersion, isInfoExist, updateMigrationVersion } from './fix-top-field'; | ||
|
||
const DB_NAME = "rin"; | ||
const SQL_DIR = path.join(__dirname, '..', 'server', 'sql'); | ||
|
||
// Change to the server/sql directory | ||
process.chdir(SQL_DIR); | ||
|
||
const typ = 'local'; | ||
const migrationVersion = await getMigrationVersion(typ, DB_NAME); | ||
const isInfoExistResult = await isInfoExist(typ, DB_NAME); | ||
// List all SQL files and sort them | ||
const sqlFiles = fs | ||
.readdirSync(SQL_DIR, {withFileTypes: true}) | ||
.readdirSync(SQL_DIR, { withFileTypes: true }) | ||
.filter(dirent => dirent.isFile() && dirent.name.endsWith('.sql')) | ||
.map(dirent => dirent.name) | ||
.filter(file => { | ||
const version = parseInt(file.split('-')[0]); | ||
return version > migrationVersion; | ||
}) | ||
.sort(); | ||
|
||
console.log("migration_version:", migrationVersion, "Migration SQL List: ", sqlFiles) | ||
|
||
// For each file in the sorted list | ||
for (const file of sqlFiles) { | ||
const filePath = path.join(SQL_DIR, file); | ||
// Run the migration | ||
try { | ||
execSync(`bunx wrangler d1 execute ${DB_NAME} --local --file "${filePath}"`, {stdio: 'inherit'}); | ||
execSync(`bunx wrangler d1 execute ${DB_NAME} --local --file "${filePath}"`, { stdio: 'inherit' }); | ||
console.log(`Executed ${file}`); | ||
} catch (error) { | ||
console.error(`Failed to execute ${file}: ${error}`); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
if (sqlFiles.length === 0) { | ||
console.log("No migration needed.") | ||
} else { | ||
const lastVersion = parseInt(sqlFiles[sqlFiles.length - 1].split('-')[0]); | ||
if (lastVersion > migrationVersion) { | ||
// Update the migration version | ||
await updateMigrationVersion(typ, DB_NAME, lastVersion); | ||
} | ||
} | ||
|
||
await fixTopField(typ, DB_NAME, isInfoExistResult); | ||
|
||
// Back to the root directory (optional, as the script ends) | ||
process.chdir(__dirname); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { $ } from "bun" | ||
|
||
export async function fixTopField(typ: 'local' | 'remote', db: string, isInfoExistResult: boolean) { | ||
if (!isInfoExistResult) { | ||
console.log("Legacy database, check top field") | ||
const result = await $`bunx wrangler d1 execute ${db} --${typ} --json --command "SELECT name FROM pragma_table_info('feeds') WHERE name='top'"`.quiet().json() | ||
if (result[0].results.length === 0) { | ||
console.log("Adding top field to feeds table") | ||
await $`bunx wrangler d1 execute ${db} --${typ} --json --command "ALTER TABLE feeds ADD COLUMN top INTEGER DEFAULT 0"`.quiet() | ||
} else { | ||
console.log("Top field already exists in feeds table") | ||
} | ||
} else { | ||
console.log("New database, skip top field check") | ||
} | ||
} | ||
|
||
export async function isInfoExist(typ: 'local' | 'remote', db: string) { | ||
const result = await $`bunx wrangler d1 execute ${db} --${typ} --json --command "SELECT name FROM sqlite_master WHERE type='table' AND name='info'"`.quiet().json() | ||
if (result[0].results.length === 0) { | ||
console.log("info table not exists") | ||
return false | ||
} else { | ||
console.log("info table already exists") | ||
return true | ||
} | ||
} | ||
|
||
export async function getMigrationVersion(typ: 'local' | 'remote', db: string) { | ||
const isInfoExistResult = await isInfoExist(typ, db) | ||
if (!isInfoExistResult) { | ||
console.log("Legacy database, migration_version not exists") | ||
return -1 | ||
} | ||
const result = await $`bunx wrangler d1 execute ${db} --${typ} --json --command "SELECT value FROM info WHERE key='migration_version'"`.quiet().json() | ||
if (result[0].results.length === 0) { | ||
console.log("migration_version not exists") | ||
return -1 | ||
} else { | ||
console.log("migration_version:", result[0].results[0].value) | ||
return parseInt(result[0].results[0].value) | ||
} | ||
} | ||
|
||
export async function updateMigrationVersion(typ: 'local' | 'remote', db: string, version: number) { | ||
const exists = await isInfoExist(typ, db) | ||
if (!exists) { | ||
console.log("info table not exists, skip update migration_version") | ||
throw new Error("info table not exists") | ||
} | ||
await $`bunx wrangler d1 execute ${db} --${typ} --json --command "UPDATE info SET value='${version}' WHERE key='migration_version'"`.quiet() | ||
console.log("Updated migration_version to", version) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,8 @@ | ||
PRAGMA foreign_keys=off; | ||
--> statement-breakpoint | ||
CREATE TABLE IF NOT EXISTS `feeds_new` ( | ||
`id` integer PRIMARY KEY NOT NULL, | ||
`alias` text, | ||
`title` text, | ||
`content` text NOT NULL, | ||
`summary` text DEFAULT '' NOT NULL, | ||
`listed` integer DEFAULT 1 NOT NULL, | ||
`draft` integer DEFAULT 1 NOT NULL, | ||
`uid` integer NOT NULL, | ||
`top` integer DEFAULT 0 NOT NULL, | ||
`created_at` integer DEFAULT (unixepoch()) NOT NULL, | ||
`updated_at` integer DEFAULT (unixepoch()) NOT NULL, | ||
FOREIGN KEY (`uid`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action | ||
CREATE TABLE IF NOT EXISTS `info` ( | ||
`key` text NOT NULL, | ||
`value` text NOT NULL | ||
); | ||
--> statement-breakpoint | ||
INSERT INTO `feeds_new` (`id`, `alias`, `title`, `content`, `summary`, `listed`, `draft`, `uid`, `created_at`, `updated_at`) | ||
SELECT `id`, `alias`, `title`, `content`, `summary`, `listed`, `draft`, `uid`, `created_at`, `updated_at` | ||
FROM `feeds`; | ||
--> statement-breakpoint | ||
DROP TABLE `feeds`; | ||
--> statement-breakpoint | ||
ALTER TABLE `feeds_new` RENAME TO `feeds`; | ||
CREATE UNIQUE INDEX `info_key_unique` ON `info` (`key`); | ||
--> statement-breakpoint | ||
PRAGMA foreign_keys=on; | ||
INSERT INTO `info` (`key`, `value`) VALUES ('migration_version', '2'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters