# 存储管理器 这个包提供了两种存储方式来管理数据库连接、文件夹和脚本(Script): ## 存储方式 ### 1. 文件存储 (file_storage) - 使用TOML文件存储配置信息 - 脚本内容存储在文件系统中(`sql_base_dir`) - 适合单用户、小型应用 ### 2. 数据库存储 (db_storage) - 使用SQLite数据库存储所有数据 - 所有信息(配置、脚本内容)都存储在数据库中 - 适合多用户、需要并发访问的应用 ## 接口定义 所有存储实现都遵循 `StorageInterface` 接口,确保两种存储方式具有相同的API: ```go 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配置文件和本地文件系统来存储数据,适合单用户或小型应用。 ```go 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数据库来存储所有数据,适合多用户或需要并发访问的应用。 ```go 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) } ``` ### 工厂方法 工厂方法提供了统一的存储管理器创建接口,可以根据配置动态选择存储类型。 ```go 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 - 数据库连接 数据库连接结构体定义了连接到数据库所需的所有信息: ```go 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 - 文件夹 文件夹结构体用于组织数据库连接的层次结构: ```go 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 片段: ```go 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)。确保所有实体(连接、文件夹、文件)在系统中具有唯一标识。 ## 安装依赖 在使用此包之前,需要安装所需的依赖包: ```bash # 安装TOML配置文件处理库 (文件存储必需) go get github.com/pelletier/go-toml/v2 # 安装SQLite驱动 (数据库存储必需) go get modernc.org/sqlite # 安装UUID生成库 (通用必需) go get github.com/google/uuid ``` **注意**: - 文件存储只需要 `go-toml` 和 `google/uuid` - 数据库存储需要 `sqlite` 和 `google/uuid` - 建议在项目初始化时就安装所有依赖,以避免运行时错误