gtong 77ba2d1c54 11.24 1 vecka sedan
..
db_storage 77ba2d1c54 11.24 1 vecka sedan
types 77ba2d1c54 11.24 1 vecka sedan
README.md 77ba2d1c54 11.24 1 vecka sedan
factory.go af431d199e 9.19 2 månader sedan
interface.go 77ba2d1c54 11.24 1 vecka sedan

README.md

存储管理器

这个包提供了两种存储方式来管理数据库连接、文件夹和脚本(Script):

存储方式

1. 文件存储 (file_storage)

  • 使用TOML文件存储配置信息
  • 脚本内容存储在文件系统中(sql_base_dir
  • 适合单用户、小型应用

2. 数据库存储 (db_storage)

  • 使用SQLite数据库存储所有数据
  • 所有信息(配置、脚本内容)都存储在数据库中
  • 适合多用户、需要并发访问的应用

接口定义

所有存储实现都遵循 StorageInterface 接口,确保两种存储方式具有相同的API:

type StorageInterface interface {
    // ========== 连接管理方法 ==========
    
    // CreateConnection 在指定文件夹下创建新的连接(支持多种连接类型)
    // 参数:
    //   - folderPath: 连接存放的文件夹路径
    //   - name: 连接名称
    //   - description: 连接描述
    //   - kind: 连接类别,示例值为 `database` / `server` / `other`
    //   - type: 具体类型或子类型,例如针对数据库为 `mysql`/`postgres`,针对服务器可能为 `ssh`
    //   - version: 版本号或次级信息(例如 `8.0`)
    //   - host: 数据库/服务器主机地址
    //   - port: 网络端口
    //   - username: 用户名
    //   - password: 密码
    //   - database: 数据库名(当 kind=="database" 时适用)
    //   - connStr: 自定义连接字符串 (可选)
    //   - tags: 标签列表
    // 返回: 创建的连接对象或错误
    // CreateConnection: 使用 `type`/`version`(已移除旧字段 `db_type`/`db_version`)
    CreateConnection(folderPath, name, description, typ, version, host string, port int, username, password, database, connStr string, tags []string) (*types.ConnectionWithDetails, error)
    
    // GetConnection 根据连接ID获取连接详细信息
    // 参数: connID - 连接的唯一标识符
    // 返回: 连接对象或错误 (如果连接不存在)
    GetConnection(connID string) (*types.ConnectionWithDetails, error)
    
    // UpdateConnection 更新现有连接的信息
    // 参数: connID - 要更新的连接ID, 其他参数同CreateConnection
    // 返回: 更新后的连接对象或错误
    UpdateConnection(connID, name, description, typ, version, host string, port int, username, password, database, connStr string, tags []string) (*types.ConnectionWithDetails, error)
    
    // DeleteConnection 删除指定文件夹下的连接
    // 参数:
    //   - folderPath: 连接所在的文件夹路径
    //   - connID: 要删除的连接ID
    // 返回: 错误 (如果删除失败)
    DeleteConnection(folderPath, connID string) error
    
    // MoveConnection 将连接移动到其他文件夹
    // 参数:
    //   - connID: 要移动的连接ID
    //   - targetPath: 目标文件夹路径
    // 返回: 移动后的连接对象或错误
    MoveConnection(connID, targetPath string) (*types.ConnectionWithDetails, error)
    
    // GetRootConnections 获取根目录 ("/") 下的所有连接
    // 返回: 根目录连接列表或错误
    GetRootConnections() ([]types.ConnectionWithDetails, error)
    
    // GetAllConnections 获取所有连接 (包括子文件夹中的)
    // 返回: 所有连接的完整列表或错误
    GetAllConnections() ([]types.ConnectionWithDetails, error)

    // ========== 文件夹管理方法 ==========
    
    // CreateFolder 在指定路径下创建新文件夹
    // 参数:
    //   - path: 父文件夹路径
    //   - name: 文件夹名称
    //   - description: 文件夹描述
    //   - tags: 标签列表
    // 返回: 创建的文件夹对象或错误
    CreateFolder(path, name, description string, tags []string) (*types.Folder, error)
    
    // GetFolder 获取指定路径的文件夹信息
    // 参数: path - 文件夹路径
    // 返回: 文件夹对象或错误 (如果文件夹不存在)
    GetFolder(path string) (*types.Folder, error)
    
    // UpdateFolder 更新文件夹信息
    // 参数: path - 文件夹路径, 其他参数同CreateFolder
    // 返回: 更新后的文件夹对象或错误
    UpdateFolder(path, name, description string, tags []string) (*types.Folder, error)
    
    // DeleteFolder 删除指定路径的文件夹
    // 参数: path - 要删除的文件夹路径
    // 返回: 错误 (如果删除失败或文件夹不存在)
    DeleteFolder(path string) error
    
    // ListFolders 列出指定路径下的文件夹
    // 参数:
    //   - path: 要列出的文件夹路径
    //   - recursive: 是否递归列出子文件夹 (true=递归, false=仅直接子文件夹)
    //   - includeConnections: 是否在结果中包含每个文件夹的连接信息
    // 返回: 文件夹列表或错误
    ListFolders(path string, recursive, includeConnections bool) ([]types.Folder, error)
    
    // FolderExists 检查文件夹是否存在
    // 参数: path - 要检查的文件夹路径
    // 返回: 存在(true)/不存在(false) 和可能的错误
    FolderExists(path string) (bool, error)

    // ========== 脚本 (Script) 管理方法 ==========
    
    // CreateScript 为指定连接创建脚本记录
    // 参数:
    //   - connID: 关联的数据库连接ID
    //   - name: 脚本名称
    //   - description: 脚本描述
    //   - tags: 标签列表
    //   - content: 脚本内容 (SQL 或其它语言取决于 `language` 字段)
    // 返回: 创建的 Script 对象或错误
    CreateScript(connID, name, description string, tags []string, content string) (*types.Script, error)
    
    // GetScript 获取脚本信息
    // 参数: scriptID - 脚本的唯一标识符
    // 返回: Script 对象或错误
    GetScript(scriptID string) (*types.Script, error)
    
    // UpdateScript 更新脚本信息 (不包含内容)
    // 参数: scriptID - 脚本ID, 其他参数同CreateScript (除content外)
    // 返回: 更新后的 Script 对象或错误
    UpdateScript(scriptID, name, description string, tags []string) (*types.Script, error)
    
    // DeleteScript 删除脚本
    // 参数: scriptID - 要删除的脚本ID
    // 返回: 错误 (如果删除失败)
    DeleteScript(scriptID string) error
    
    // ReadScriptContent 读取脚本内容
    // 参数: scriptID - 脚本ID
    // 返回: 脚本内容字符串或错误
    ReadScriptContent(scriptID string) (string, error)
    
    // WriteScriptContent 写入脚本内容
    // 参数:
    //   - scriptID: 脚本ID
    //   - content: 要写入的内容
    // 返回: 错误 (如果写入失败)
    WriteScriptContent(scriptID, content string) error
    
    // ListScripts 列出指定连接的所有脚本
    // 参数: connID - 数据库连接ID
    // 返回: Script 列表或错误
    ListScripts(connID string) ([]types.Script, error)

    // ========== 配置管理方法 ==========
    
    // CreateDefaultConfig 创建默认配置文件
    // 返回: 错误 (如果创建失败)
    CreateDefaultConfig() error
    
    // SaveConnection 保存连接配置
    // 参数: conn - 要保存的连接对象
    // 返回: 错误 (如果保存失败)
    SaveConnection(conn *types.ConnectionWithDetails) error
}

使用方法

文件存储

文件存储使用TOML配置文件和本地文件系统来存储数据,适合单用户或小型应用。

import "dbview/service/internal/common/manager/storage"

// 创建文件存储管理器
// 参数:
//   - configPath: TOML配置文件路径 (如 "data.toml")
//   - sqlBaseDir: 脚本存储的基础目录 (如 "sql_files")
manager, err := storage.NewFileStorage("data.toml", "scripts")
if err != nil {
    log.Fatal(err) // 创建失败时程序退出
}

// 使用manager进行操作
// CreateConnection 的参数说明:
// - folderPath: 连接存放的文件夹路径 (如 "/")
// - name: 连接名称 (如 "MyDB")
// - description: 连接描述 (如 "My Database")
// - type: 具体类型或子类型,例如针对数据库为 `mysql`/`postgres`,针对服务器可能为 `ssh`
// - version: 版本号或次级信息(例如 `8.0`)
// - host: 数据库/服务器主机地址 (如 "localhost")
// - port: 网络端口 (如 3306)
// - username: 用户名
// - password: 密码
// - database: 数据库名
// - connStr: 自定义连接字符串 (可为空字符串)
// - tags: 标签数组 (如 []string{"dev", "test"})
conn, err := manager.CreateConnection("/", "MyDB", "My Database", "mysql", "8.0", "localhost", 3306, "user", "pass", "mydb", "", []string{"dev"})
if err != nil {
    log.Printf("创建连接失败: %v", err)
}

数据库存储

数据库存储使用SQLite数据库来存储所有数据,适合多用户或需要并发访问的应用。

import "dbview/service/internal/common/manager/storage"

// 创建数据库存储管理器
// 参数: dbPath - SQLite数据库文件路径 (如 "storage.db")
manager, err := storage.NewDBStorage("storage.db")
if err != nil {
    log.Fatal(err) // 创建失败时程序退出
}

// 使用manager进行操作(接口相同)
// 所有方法的使用方式与文件存储完全相同
// 注意:接口参数使用 `type`/`version` 表示连接类型与次级版本信息
conn, err := manager.CreateConnection("/", "MyDB", "My Database", "mysql", "8.0", "localhost", 3306, "user", "pass", "mydb", "", []string{"dev"})
if err != nil {
    log.Printf("创建连接失败: %v", err)
}

工厂方法

工厂方法提供了统一的存储管理器创建接口,可以根据配置动态选择存储类型。

import "dbview/service/internal/common/manager/storage"

// 使用工厂方法创建存储管理器
// GetStorage的参数:
//   - storageType: 存储类型 (storage.FileStorage 或 storage.DBStorage)
//   - configPath: 配置文件路径 (文件存储) 或 空字符串 (数据库存储)
//   - dbPath: 数据库路径 (数据库存储) 或 脚本目录 (文件存储)
manager, err := storage.GetStorage(storage.FileStorage, "data.toml", "scripts")
if err != nil {
    log.Fatal("创建文件存储管理器失败:", err)
}

// 或者创建数据库存储管理器
manager, err := storage.GetStorage(storage.DBStorage, "", "storage.db")
if err != nil {
    log.Fatal("创建数据库存储管理器失败:", err)
}

存储类型常量

  • storage.FileStorage - 文件存储类型:使用TOML文件和本地文件系统
  • storage.DBStorage - 数据库存储类型:使用SQLite数据库存储所有数据

主要功能

连接管理

数据库连接管理提供了完整的CRUD操作,以及连接的组织和移动功能。

  • CreateConnection(folderPath, name, description, type, version, host, port, username, password, database, connStr, tags)

    • 功能: 在指定文件夹下创建新的数据库连接配置
    • 参数: 文件夹路径、连接基本信息、数据库连接参数、标签
    • 返回值: 创建成功的连接对象,包含自动生成的ID和时间戳
    • 错误: 文件夹不存在、连接名称冲突、参数验证失败等
  • GetConnection(connID)

    • 功能: 根据唯一ID获取完整的连接信息
    • 参数: 连接的唯一标识符
    • 返回值: 包含所有连接详情的对象
    • 错误: 连接不存在
  • UpdateConnection(connID, name, description, type, version, host, port, username, password, database, connStr, tags)

    • 功能: 更新现有连接的配置信息
    • 参数: 连接ID和新配置信息
    • 返回值: 更新后的连接对象
    • 错误: 连接不存在、参数验证失败
  • DeleteConnection(folderPath, connID)

    • 功能: 删除指定文件夹下的连接及其关联的脚本(scripts)
    • 参数: 文件夹路径和连接ID
    • 返回值: 无
    • 错误: 连接不存在、文件夹路径不匹配
  • MoveConnection(connID, targetPath)

    • 功能: 将连接移动到其他文件夹
    • 参数: 连接ID和目标文件夹路径
    • 返回值: 移动后的连接对象
    • 错误: 连接不存在、目标文件夹不存在
  • GetRootConnections()

    • 功能: 获取根目录("/")下所有直接连接
    • 参数: 无
    • 返回值: 根目录连接列表
    • 错误: 存储访问错误
  • GetAllConnections()

    • 功能: 获取所有连接,包括子文件夹中的连接
    • 参数: 无
    • 返回值: 完整的连接列表
    • 错误: 存储访问错误

文件夹管理

文件夹管理支持层次结构的管理,用于组织数据库连接。

  • CreateFolder(path, name, description, tags)

    • 功能: 在指定路径下创建新的文件夹
    • 参数: 父文件夹路径、文件夹名称、描述、标签
    • 返回值: 创建成功的文件夹对象
    • 错误: 父文件夹不存在、文件夹名称冲突
  • GetFolder(path)

    • 功能: 获取指定路径文件夹的详细信息
    • 参数: 文件夹路径
    • 返回值: 文件夹对象,包含子文件夹和连接信息
    • 错误: 文件夹不存在
  • UpdateFolder(path, name, description, tags)

    • 功能: 更新文件夹的基本信息
    • 参数: 文件夹路径和新信息
    • 返回值: 更新后的文件夹对象
    • 错误: 文件夹不存在
  • DeleteFolder(path, name)

    • 功能: 删除文件夹及其所有子文件夹、数据库连接和关联的脚本(级联删除)
    • 参数:
    • path: 文件夹路径
    • name: 文件夹名称(用于验证)
    • 返回值: 无
    • 错误: 文件夹不存在、名称不匹配
  • ListFolders(path, recursive, includeConnections)

    • 功能: 列出指定路径下的文件夹列表
    • 参数:
    • path: 起始文件夹路径
    • recursive: 是否递归列出所有子文件夹
    • includeConnections: 是否在结果中包含每个文件夹的连接信息
    • 返回值: 文件夹对象数组
    • 错误: 路径不存在
  • FolderExists(path)

    • 功能: 检查指定路径的文件夹是否存在
    • 参数: 文件夹路径
    • 返回值: 布尔值表示是否存在
    • 错误: 存储访问错误

脚本 (Script) 管理

脚本管理允许为每个数据库连接存储和管理可执行或保存的脚本(例如 SQL 语句片段)。

  • CreateScript(connID, name, description, tags, content)

    • 功能: 为指定连接创建新的脚本记录
    • 参数: 连接ID、脚本名、描述、标签、脚本内容
    • 返回值: 创建成功的 Script 对象
    • 错误: 连接不存在、名称冲突
  • GetScript(scriptID)

    • 功能: 获取脚本的详细信息(不含内容)
    • 参数: 脚本ID
    • 返回值: Script 对象
    • 错误: 脚本不存在
  • UpdateScript(scriptID, name, description, tags)

    • 功能: 更新脚本的基本信息(不含内容)
    • 参数: 脚本ID和新信息
    • 返回值: 更新后的对象
    • 错误: 脚本不存在
  • DeleteScript(scriptID)

    • 功能: 删除指定的脚本记录
    • 参数: 脚本ID
    • 返回值: 无
    • 错误: 脚本不存在
  • ReadScriptContent(scriptID)

    • 功能: 读取脚本的内容
    • 参数: 脚本ID
    • 返回值: 脚本内容字符串
    • 错误: 脚本不存在、读取失败
  • WriteScriptContent(scriptID, content)

    • 功能: 更新脚本的内容
    • 参数: 脚本ID和新内容
    • 返回值: 无
    • 错误: 脚本不存在、写入失败
  • ListScripts(connID)

    • 功能: 列出指定连接的所有脚本
    • 参数: 连接ID
    • 返回值: Script 列表
    • 错误: 连接不存在

配置管理

配置管理处理存储系统的初始化和持久化。

  • CreateDefaultConfig()

    • 功能: 创建默认的配置文件或数据库结构
    • 参数: 无
    • 返回值: 无
    • 错误: 创建失败
  • SaveConnection(conn)

    • 功能: 将连接对象保存到存储中
    • 参数: 连接对象
    • 返回值: 无
    • 错误: 保存失败

数据结构

DBConnection - 数据库连接

数据库连接结构体定义了连接到数据库所需的所有信息:

type DBConnection struct {
    ID          string    `json:"id" db:"id"`          // 连接的唯一标识符 (UUID)
    Name        string    `json:"name" db:"name"`        // 连接显示名称
    Description string    `json:"description" db:"description"` // 连接描述信息
    Type        string    `json:"type" db:"db_type"` // 数据库类型: mysql, postgresql, sqlite等
    Version     string    `json:"version" db:"db_version"` // 数据库版本号
    Host        string    `json:"host" db:"host"`        // 数据库服务器主机地址
    Port        int       `json:"port" db:"port"`        // 数据库服务器端口号
    Username    string    `json:"username" db:"username"` // 数据库用户名
    Password    string    `json:"password" db:"password"` // 数据库密码
    Database    string    `json:"database" db:"database"` // 数据库名称
    ConnStr     string    `json:"conn_str" db:"conn_str"` // 自定义连接字符串 (可选)
    FolderPath  string    `json:"folder_path" db:"folder_path"` // 连接所在的文件夹路径
    LastUsed    time.Time `json:"last_used" db:"last_used"` // 最后使用时间
    CreatedTime time.Time `json:"created_time" db:"created_time"` // 创建时间
    Tags        []string  `json:"tags" db:"tags"`        // 标签列表,用于分类和搜索
    Scripts    []Script `json:"scripts" db:"scripts"` // 关联的脚本列表
}

字段说明:

  • ID: 全局唯一标识符,用于在系统中唯一标识连接
  • Name: 用户友好的显示名称
  • Type/Version: 确定数据库驱动和兼容性 (以前称为 DBType/DBVersion)
  • Host/Port: 网络连接信息
  • Username/Password: 认证信息
  • ConnStr: 高级用户可自定义完整连接字符串
  • FolderPath: 支持层次化组织连接
  • Tags: 支持多维度分类,如"dev"、"prod"、"test"等
  • Scripts: 关联的脚本文件(Script),便于管理

Folder - 文件夹

文件夹结构体用于组织数据库连接的层次结构:

type Folder struct {
    ID          string         `json:"id" db:"id"`          // 文件夹的唯一标识符
    Name        string         `json:"name" db:"name"`        // 文件夹显示名称
    Description string         `json:"description" db:"description"` // 文件夹描述
    CreatedTime time.Time      `json:"created_time" db:"created_time"` // 创建时间
    Tags        []string       `json:"tags" db:"tags"`        // 标签列表
    FolderPath  string         `json:"folder_path" db:"folder_path"` // 文件夹完整路径
    Subfolders  []Folder       `json:"subfolders" db:"subfolders"` // 子文件夹列表
    Connections []DBConnection `json:"connections" db:"connections"` // 该文件夹下的连接列表
}

字段说明:

  • ID: 文件夹唯一标识符
  • Name: 文件夹显示名称
  • FolderPath: 完整路径,如"/project/dev"表示dev文件夹在project下
  • Subfolders: 支持无限层级的文件夹嵌套
  • Connections: 文件夹直接包含的连接(不含子文件夹的连接)
  • Tags: 文件夹级别的分类标签

Script - 脚本

脚本结构体示例,表示存储在系统中的可执行脚本或 SQL 片段:

type Script struct {
  ID           string    `json:"id" db:"id"`
  DBConnId     string    `json:"db_conn_id" db:"db_conn_id"` // 关联的数据库连接ID
  Name         string    `json:"name" db:"name"`
  Description  string    `json:"description" db:"description"`
  Language     string    `json:"language" db:"language"` // 脚本语言,例如 "sql"/"plpgsql"/"python"
  Tags         []string  `json:"tags" db:"tags"`
  LastModified time.Time `json:"last_modified" db:"last_modified"`
  CreatedTime  time.Time `json:"created_time" db:"created_time"`
  Content      string    `json:"content" db:"content"`
}

字段说明:

  • ID: 脚本唯一标识符
  • DBConnId: 关联的数据库连接,确保脚本与正确数据库匹配
  • Name: 脚本名称
  • Content: 实际的脚本内容
  • LastModified: 内容最后修改时间,用于版本控制
  • Tags: 脚本标签,如"ddl"、"dml"、"maintenance"等

依赖

该存储管理器依赖以下第三方Go包:

  • 文件存储依赖:

    • github.com/pelletier/go-toml/v2: 用于解析和生成TOML配置文件。TOML是一种易读的配置文件格式,用于存储连接和文件夹的元数据。
  • 数据库存储依赖:

    • modernc.org/sqlite: SQLite数据库驱动。提供了纯Go实现的SQLite支持,无需CGO依赖,适合跨平台部署。
  • 通用依赖:

    • github.com/google/uuid: 用于生成全局唯一标识符(UUID)。确保所有实体(连接、文件夹、文件)在系统中具有唯一标识。

安装依赖

在使用此包之前,需要安装所需的依赖包:

# 安装TOML配置文件处理库 (文件存储必需)
go get github.com/pelletier/go-toml/v2

# 安装SQLite驱动 (数据库存储必需)
go get modernc.org/sqlite

# 安装UUID生成库 (通用必需)
go get github.com/google/uuid

注意:

  • 文件存储只需要 go-tomlgoogle/uuid
  • 数据库存储需要 sqlitegoogle/uuid
  • 建议在项目初始化时就安装所有依赖,以避免运行时错误