178 lines
5 KiB
Go
178 lines
5 KiB
Go
package db
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"log"
|
|
|
|
_ "modernc.org/sqlite"
|
|
//_ "github.com/mattn/go-sqlite3"
|
|
)
|
|
|
|
// TemplateEntry 对应 templates 表
|
|
type TemplateEntry struct {
|
|
Filename string `json:"filename"`
|
|
TemplateType string `json:"template_type"`
|
|
Content []byte `json:"content"`
|
|
CreatedAt int64 `json:"created_at"`
|
|
UpdatedAt int64 `json:"updated_at"`
|
|
}
|
|
|
|
// ParamsEntry 对应 config_params 表
|
|
type ParamsEntry struct {
|
|
Filename string `json:"filename"`
|
|
TemplateType string `json:"template_type"`
|
|
ParamsGOB []byte `json:"params_gob"`
|
|
ParamsOrigin []byte `json:"params_origin"`
|
|
CreatedAt int64 `json:"created_at"`
|
|
UpdatedAt int64 `json:"updated_at"`
|
|
}
|
|
|
|
// RenderedConfigEntry 对应 rendered_configs 表
|
|
type RenderedConfigEntry struct {
|
|
Filename string `json:"filename"`
|
|
RenderedContent []byte `json:"rendered_content"`
|
|
RenderedAt int64 `json:"rendered_at"`
|
|
UpdatedAt int64 `json:"updated_at"`
|
|
}
|
|
|
|
// UsersTable
|
|
type UsersTable struct {
|
|
UserName string `json:"username"`
|
|
Password string `json:"password"`
|
|
CreatedAt int64 `json:"created_at"`
|
|
UpdatedAt int64 `json:"updated_at"`
|
|
}
|
|
|
|
// GlobalConfig 全局CaddyFile配置专用table
|
|
type GlobalConfig struct {
|
|
Filename string `json:"filename"`
|
|
Params []byte `json:"params"`
|
|
TmplContent []byte `json:"tmpl_content"`
|
|
RenderedContent []byte `json:"rendered_content"`
|
|
UpdatedAt int64 `json:"updated_at"`
|
|
}
|
|
|
|
// ConfigDB
|
|
type ConfigDB struct {
|
|
DB *sql.DB
|
|
}
|
|
|
|
func InitDB(filepath string) (*ConfigDB, error) {
|
|
db, err := loadDB(filepath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cdb := &ConfigDB{DB: db}
|
|
// 尝试 Ping 数据库以验证连接是否成功
|
|
if err = db.Ping(); err != nil {
|
|
db.Close() // 如果连接失败,确保关闭数据库句柄
|
|
return nil, fmt.Errorf("db: failed to connect to database: %w", err)
|
|
}
|
|
err = cdb.createTables()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return cdb, nil
|
|
}
|
|
|
|
func loadDB(filepath string) (*sql.DB, error) {
|
|
db, err := sql.Open("sqlite", fmt.Sprintf("file:%s?cache=shared&_journal=WAL", filepath))
|
|
if err != nil {
|
|
log.Fatalf("Can not connect to database: %v", err)
|
|
return nil, err
|
|
}
|
|
return db, nil
|
|
}
|
|
|
|
func (cdb *ConfigDB) createTables() error {
|
|
tx, err := cdb.DB.Begin()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to begin transaction for table creation: %w", err)
|
|
}
|
|
defer tx.Rollback() // 确保在出错时回滚事务
|
|
|
|
// 创建 templates 表
|
|
_, err = tx.Exec(`
|
|
CREATE TABLE IF NOT EXISTS templates (
|
|
filename TEXT PRIMARY KEY,
|
|
template_type TEXT NOT NULL,
|
|
content BLOB NOT NULL,
|
|
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
|
|
);`)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create 'templates' table: %w", err)
|
|
}
|
|
|
|
// 2. 创建 config_params 表
|
|
_, err = tx.Exec(`
|
|
CREATE TABLE IF NOT EXISTS config_params (
|
|
filename TEXT PRIMARY KEY,
|
|
template_type TEXT NOT NULL,
|
|
params_gob BLOB NOT NULL,
|
|
params_origin BLOB NOT NULL,
|
|
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
|
|
-- FOREIGN KEY(filename) REFERENCES templates(filename) ON DELETE CASCADE -- 已移除
|
|
);`)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create 'config_params' table: %w", err)
|
|
}
|
|
|
|
// 3. 创建 rendered_configs 表 (外键指向 config_params 表)
|
|
_, err = tx.Exec(`
|
|
CREATE TABLE IF NOT EXISTS rendered_configs (
|
|
filename TEXT PRIMARY KEY,
|
|
rendered_content BLOB NOT NULL,
|
|
rendered_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
FOREIGN KEY(filename) REFERENCES config_params(filename) ON DELETE CASCADE -- 修改外键引用
|
|
);`)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create 'rendered_configs' table: %w", err)
|
|
}
|
|
|
|
// 4. 创建 users 表
|
|
_, err = tx.Exec(`
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
username TEXT PRIMARY KEY,
|
|
password TEXT NOT NULL,
|
|
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
|
|
);`)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create 'users' table: %w", err)
|
|
}
|
|
|
|
// 5. 创建 global_configs 表
|
|
_, err = tx.Exec(`
|
|
CREATE TABLE IF NOT EXISTS global_configs (
|
|
filename TEXT PRIMARY KEY,
|
|
params BLOB NOT NULL DEFAULT '',
|
|
tmpl_content BLOB NOT NULL DEFAULT '',
|
|
rendered_content BLOB NOT NULL DEFAULT '',
|
|
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
|
|
);`)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create 'global_configs' table: %w", err)
|
|
}
|
|
|
|
// 提交事务
|
|
if err := tx.Commit(); err != nil {
|
|
return fmt.Errorf("failed to commit transaction for table creation: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (cdb *ConfigDB) CloseDB() error {
|
|
if cdb.DB == nil {
|
|
return nil // 数据库未打开或已关闭
|
|
}
|
|
err := cdb.DB.Close()
|
|
if err != nil {
|
|
return fmt.Errorf("db: failed to close database: %w", err)
|
|
}
|
|
return nil
|
|
}
|