添加启动时的数据库表及表结构完整性校验

This commit is contained in:
lyswhut
2023-02-06 17:33:21 +08:00
parent c8eac2690f
commit cf960e3695
5 changed files with 260 additions and 95 deletions
+10 -92
View File
@@ -1,108 +1,22 @@
import Database from 'better-sqlite3'
import path from 'path'
import tables from './tables'
import verifyDB from './verifyDB'
// import migrateData from './migrate'
let db: Database.Database
const initTables = (db: Database.Database) => {
const sql = `
CREATE TABLE "db_info" (
"id" INTEGER NOT NULL UNIQUE,
"field_name" TEXT,
"field_value" TEXT,
PRIMARY KEY("id" AUTOINCREMENT)
);
CREATE TABLE "my_list" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"source" TEXT,
"sourceListId" TEXT,
"position" INTEGER NOT NULL,
"locationUpdateTime" INTEGER,
PRIMARY KEY("id")
);
CREATE TABLE "my_list_music_info" (
"id" TEXT NOT NULL,
"listId" TEXT NOT NULL,
"name" TEXT NOT NULL,
"singer" TEXT NOT NULL,
"source" TEXT NOT NULL,
"interval" TEXT,
"meta" TEXT NOT NULL,
UNIQUE("id","listId")
);
CREATE INDEX "index_my_list_music_info" ON "my_list_music_info" (
"id",
"listId"
);
CREATE TABLE "my_list_music_info_order" (
"listId" TEXT NOT NULL,
"musicInfoId" TEXT NOT NULL,
"order" INTEGER NOT NULL
);
CREATE INDEX "index_my_list_music_info_order" ON "my_list_music_info_order" (
"listId",
"musicInfoId"
);
CREATE TABLE "music_info_other_source" (
"source_id" TEXT NOT NULL,
"id" TEXT NOT NULL,
"source" TEXT NOT NULL,
"name" TEXT NOT NULL,
"singer" TEXT NOT NULL,
"meta" TEXT NOT NULL,
"order" INTEGER NOT NULL,
UNIQUE("source_id","id")
);
CREATE INDEX "index_music_info_other_source" ON "music_info_other_source" (
"source_id",
"id"
);
-- TODO "meta" TEXT NOT NULL,
CREATE TABLE "lyric" (
"id" TEXT NOT NULL,
"source" TEXT NOT NULL,
"type" TEXT NOT NULL,
"text" TEXT NOT NULL
);
CREATE TABLE "music_url" (
"id" TEXT NOT NULL,
"url" TEXT NOT NULL
);
CREATE TABLE "download_list" (
"id" TEXT NOT NULL,
"isComplate" INTEGER NOT NULL,
"status" TEXT NOT NULL,
"statusText" TEXT NOT NULL,
"progress_downloaded" INTEGER NOT NULL,
"progress_total" INTEGER NOT NULL,
"url" TEXT,
"quality" TEXT NOT NULL,
"ext" TEXT NOT NULL,
"fileName" TEXT NOT NULL,
"filePath" TEXT NOT NULL,
"musicInfo" TEXT NOT NULL,
"position" INTEGER NOT NULL,
PRIMARY KEY("id")
);
db.exec(`
${Array.from(tables.values()).join('\n')}
INSERT INTO "main"."db_info" ("field_name", "field_value") VALUES ('version', '1');
`
db.exec(sql)
`)
}
// 打开、初始化数据库
export const init = (lxDataPath: string): boolean => {
export const init = (lxDataPath: string): boolean | null => {
const databasePath = path.join(lxDataPath, 'lx.data.db')
const nativeBinding = path.join(__dirname, '../node_modules/better-sqlite3/build/Release/better_sqlite3.node')
let dbFileExists = true
@@ -127,6 +41,10 @@ export const init = (lxDataPath: string): boolean => {
// https://www.sqlite.org/pragma.html#pragma_optimize
if (dbFileExists) db.exec('PRAGMA optimize;')
if (!verifyDB(db)) {
db.close()
return null
}
// https://www.sqlite.org/lang_vacuum.html
// db.exec('VACUUM "main"')
+209
View File
@@ -0,0 +1,209 @@
// export const sql = `
// CREATE TABLE "db_info" (
// "id" INTEGER NOT NULL UNIQUE,
// "field_name" TEXT,
// "field_value" TEXT,
// PRIMARY KEY("id" AUTOINCREMENT)
// );
// CREATE TABLE "my_list" (
// "id" TEXT NOT NULL,
// "name" TEXT NOT NULL,
// "source" TEXT,
// "sourceListId" TEXT,
// "position" INTEGER NOT NULL,
// "locationUpdateTime" INTEGER,
// PRIMARY KEY("id")
// );
// CREATE TABLE "my_list_music_info" (
// "id" TEXT NOT NULL,
// "listId" TEXT NOT NULL,
// "name" TEXT NOT NULL,
// "singer" TEXT NOT NULL,
// "source" TEXT NOT NULL,
// "interval" TEXT,
// "meta" TEXT NOT NULL,
// UNIQUE("id","listId")
// );
// CREATE INDEX "index_my_list_music_info" ON "my_list_music_info" (
// "id",
// "listId"
// );
// CREATE TABLE "my_list_music_info_order" (
// "listId" TEXT NOT NULL,
// "musicInfoId" TEXT NOT NULL,
// "order" INTEGER NOT NULL
// );
// CREATE INDEX "index_my_list_music_info_order" ON "my_list_music_info_order" (
// "listId",
// "musicInfoId"
// );
// CREATE TABLE "music_info_other_source" (
// "source_id" TEXT NOT NULL,
// "id" TEXT NOT NULL,
// "source" TEXT NOT NULL,
// "name" TEXT NOT NULL,
// "singer" TEXT NOT NULL,
// "meta" TEXT NOT NULL,
// "order" INTEGER NOT NULL,
// UNIQUE("source_id","id")
// );
// CREATE INDEX "index_music_info_other_source" ON "music_info_other_source" (
// "source_id",
// "id"
// );
// -- TODO "meta" TEXT NOT NULL,
// CREATE TABLE "lyric" (
// "id" TEXT NOT NULL,
// "source" TEXT NOT NULL,
// "type" TEXT NOT NULL,
// "text" TEXT NOT NULL
// );
// CREATE TABLE "music_url" (
// "id" TEXT NOT NULL,
// "url" TEXT NOT NULL
// );
// CREATE TABLE "download_list" (
// "id" TEXT NOT NULL,
// "isComplate" INTEGER NOT NULL,
// "status" TEXT NOT NULL,
// "statusText" TEXT NOT NULL,
// "progress_downloaded" INTEGER NOT NULL,
// "progress_total" INTEGER NOT NULL,
// "url" TEXT,
// "quality" TEXT NOT NULL,
// "ext" TEXT NOT NULL,
// "fileName" TEXT NOT NULL,
// "filePath" TEXT NOT NULL,
// "musicInfo" TEXT NOT NULL,
// "position" INTEGER NOT NULL,
// PRIMARY KEY("id")
// );
// `
// export const tables = [
// 'table_db_info',
// 'table_my_list',
// 'table_my_list_music_info',
// 'index_index_my_list_music_info',
// 'table_my_list_music_info_order',
// 'index_index_my_list_music_info_order',
// 'table_music_info_other_source',
// 'index_index_music_info_other_source',
// 'table_lyric',
// 'table_music_url',
// 'table_download_list',
// ]
const tables = new Map<string, string>()
tables.set('db_info', `
CREATE TABLE "db_info" (
"id" INTEGER NOT NULL UNIQUE,
"field_name" TEXT,
"field_value" TEXT,
PRIMARY KEY("id" AUTOINCREMENT)
);
`)
tables.set('my_list', `
CREATE TABLE "my_list" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"source" TEXT,
"sourceListId" TEXT,
"position" INTEGER NOT NULL,
"locationUpdateTime" INTEGER,
PRIMARY KEY("id")
);
`)
tables.set('my_list_music_info', `
CREATE TABLE "my_list_music_info" (
"id" TEXT NOT NULL,
"listId" TEXT NOT NULL,
"name" TEXT NOT NULL,
"singer" TEXT NOT NULL,
"source" TEXT NOT NULL,
"interval" TEXT,
"meta" TEXT NOT NULL,
UNIQUE("id","listId")
);
`)
tables.set('index_my_list_music_info', `
CREATE INDEX "index_my_list_music_info" ON "my_list_music_info" (
"id",
"listId"
);
`)
tables.set('my_list_music_info_order', `
CREATE TABLE "my_list_music_info_order" (
"listId" TEXT NOT NULL,
"musicInfoId" TEXT NOT NULL,
"order" INTEGER NOT NULL
);
`)
tables.set('index_my_list_music_info_order', `
CREATE INDEX "index_my_list_music_info_order" ON "my_list_music_info_order" (
"listId",
"musicInfoId"
);
`)
tables.set('music_info_other_source', `
CREATE TABLE "music_info_other_source" (
"source_id" TEXT NOT NULL,
"id" TEXT NOT NULL,
"source" TEXT NOT NULL,
"name" TEXT NOT NULL,
"singer" TEXT NOT NULL,
"meta" TEXT NOT NULL,
"order" INTEGER NOT NULL,
UNIQUE("source_id","id")
);
`)
tables.set('index_music_info_other_source', `
CREATE INDEX "index_music_info_other_source" ON "music_info_other_source" (
"source_id",
"id"
);
`)
tables.set('lyric', `
-- TODO "meta" TEXT NOT NULL,
CREATE TABLE "lyric" (
"id" TEXT NOT NULL,
"source" TEXT NOT NULL,
"type" TEXT NOT NULL,
"text" TEXT NOT NULL
);
`)
tables.set('music_url', `
CREATE TABLE "music_url" (
"id" TEXT NOT NULL,
"url" TEXT NOT NULL
);
`)
tables.set('download_list', `
CREATE TABLE "download_list" (
"id" TEXT NOT NULL,
"isComplate" INTEGER NOT NULL,
"status" TEXT NOT NULL,
"statusText" TEXT NOT NULL,
"progress_downloaded" INTEGER NOT NULL,
"progress_total" INTEGER NOT NULL,
"url" TEXT,
"quality" TEXT NOT NULL,
"ext" TEXT NOT NULL,
"fileName" TEXT NOT NULL,
"filePath" TEXT NOT NULL,
"musicInfo" TEXT NOT NULL,
"position" INTEGER NOT NULL,
PRIMARY KEY("id")
);
`)
export default tables
+25
View File
@@ -0,0 +1,25 @@
import type Database from 'better-sqlite3'
import tables from './tables'
const rxp = /\n|\s|;|--.+/g
export default (db: Database.Database) => {
const result = db.prepare('SELECT type,name,tbl_name,sql FROM "main".sqlite_master WHERE sql NOT NULL;').all()
const dbTableMap = new Map<string, string>()
for (const info of result) dbTableMap.set(info.name, info.sql.replace(rxp, ''))
return Array.from(tables.entries()).every(([name, sql]) => {
const dbSql = dbTableMap.get(name)
return dbSql && dbSql == sql.replace(rxp, '')
})
// console.log(dbTableMap)
// for (const [name, sql] of tables.entries()) {
// const dbSql = dbTableMap.get(name)
// if (dbSql) {
// if (dbSql == sql.replace(rxp, '')) continue
// console.log(dbSql)
// console.log(sql.replace(rxp, ''))
// } else {
// console.log(name)
// }
// }
// if (result.every((info) => { tables.includes() }))
}