API.md 42 KB

Database Metadata API(详细)

📋 API总览

🎯 功能概述

Database Metadata API 提供完整的数据库元数据管理功能,支持多数据库类型(MySQL、PostgreSQL等)的结构化数据访问。通过RESTful接口实现数据库对象的浏览、查询、创建和管理操作。

🗄️ 支持的数据库类型

  • MySQL 5.x/8.x:完整支持数据库、表、视图、索引、触发器等对象
  • PostgreSQL:支持数据库、Schema、表、视图等对象(计划中)
  • 其他数据库:通过插件架构可扩展支持

🚀 核心功能

  1. 结构化导航:支持从数据库→表→列的层级浏览
  2. 元数据查询:获取对象详情、列信息、索引定义等
  3. 对象管理:创建、修改、删除数据库对象
  4. 模板系统:提供创建/修改表单的动态模板
  5. 分页支持:大结果集的分页查询和浏览

📚 主要接口

接口 路径 功能描述
列出根对象 POST /database/metadata/root 获取数据库实例下的根级对象(如数据库列表)
列出子对象 POST /database/metadata/children 获取父对象下的子对象(如表、视图等)
获取对象详情 POST /database/metadata/object 获取单个对象的详细信息和子对象
创建对象模板 POST /database/metadata/create/template 获取创建对象的表单模板
更新对象模板 POST /database/metadata/update/template 获取更新现有对象的表单模板
删除对象模板 POST /database/metadata/delete/template 获取删除对象的确认模板
创建对象 POST /database/metadata/object/create 创建数据库对象(支持预览/执行)
更新对象 POST /database/metadata/object/update 更新数据库对象(支持预览/执行)
删除对象 POST /database/metadata/object/delete 删除数据库对象(支持预览/执行)
获取元信息 POST /database/metadata/info 获取数据库支持的关键字、字段类型和能力信息(用于自动完成/语法高亮/能力探测)
刷新元数据 POST /database/metadata/object/refresh 刷新对象的元数据缓存

🏗️ 设计原则

  • 结构化路径:使用 ObjectPath 数组表示对象层级,避免字符串解析
  • 类型安全:明确的字段类型和验证规则
  • 分页友好:支持大结果集的分页,减少内存占用
  • 预览模式:DDL操作支持预览SQL,保障安全性
  • 统一响应:所有接口使用统一的响应格式和错误处理

💡 使用建议

  • 导航流程:先用 fetch=false 获取结构,再按需加载详情
  • 分页处理:大对象列表建议使用分页,避免一次性加载过多数据
  • 错误处理:后端在遇到校验或执行错误时会通过 HTTP 非 200 状态码返回(常见为 400 参数/校验错误、500 服务器执行错误)。响应仍使用统一包装 service/internal/common/response.Response,错误的底层信息会放在 error 字段中(信息为中文、尽量详细)。客户端应优先根据 HTTP 状态码判断错误类型,并读取 code/msg/error 字段来呈现或定位问题。
  • 连接管理:通过 connId 指定数据库连接,确保连接池复用

本文档逐个接口列出请求字段、响应结构、示例和注意事项,方便前端和客户端对接与测试。

基本信息

  • 前缀:/database/metadata
  • 协议:HTTP POST,Content-Type: application/json
  • 公共响应包装:service/internal/common/response.Response

通用响应格式

{
  "code": 0,       // 0=成功,非0为失败
  "msg": "ok",   // 简短中文提示
  "data": {},      // 成功时的业务数据
  "error": ""    // 失败时的底层错误信息(便于排查)
}

注意:成功响应通常为 HTTP 200;当出现校验/参数错误或执行失败时,后端会返回相应的 HTTP 错误状态(例如 400/422/500),但仍会使用上述统一 JSON 结构携带 code/msg/error 信息。error 字段一般为中文的详细底层错误(便于前端展示或日志记录)。

通用字段说明(常见请求字段)

  • connId (string, required):连接池查找键,后端用此 key 调用 ConnectionPool.GetConnection(connId)。
  • connInfo (string, optional):展示/日志用的连接信息(可选),不会用于建立连接。
  • fetch (bool, optional):是否拉取具体条目;false 表示只返回类型/计数,true 表示返回具体条目(支持分页)。
  • page (int, optional):分页页码,默认 1(从 1 开始)。
  • pageSize (int, optional):每页大小,默认 50。
    • path (array of {type,name}, optional/required per endpoint):结构化路径,表示从根到目标对象的层级(见下文 ObjectPathEntry 说明)。例如数据库下的表 users 的 path 为 [{"type":"database","name":"mydb"},{"type":"table","name":"users"}]。

通用数据结构(摘录)

  • meta.GenericObject 简要字段:
    • ID string
    • Name string
    • Type string
    • ParentID string
    • DBType string
    • Attrs object
    • Children []GenericObject

1) 列出根对象 — POST /database/metadata/root

用途

  • 列出某个连接(connection)下的根级对象(例如 MySQL 的 databases/schemas)。

请求字段 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | connId | string | 是 | 连接池查找键(必须) | | connInfo | string | 否 | 展示/日志用的连接备注 | | page | int | 否 | 分页页码,默认 1 | | pageSize | int | 否 | 每页大小,默认 50 | | fetch | bool | 否 | 是否拉取具体条目;false=只返回类型/计数 |

示例请求

{
  "connId": "conn-123",
  "connInfo": "mysql-prod-01",
  "page": 1,
  "pageSize": 50,
  "fetch": true
}

成功响应(fetch=true)

{
  "code": 0,
  "msg": "ok",
  "data": {
    "total": 3,
    "data": [
      {
        "ID": "conn-123.db-mydb",
        "Name": "mydb",
        "Type": "database",
        "ParentID": "conn-123",
        "DBType": "mysql",
        "Attrs": {"charset":"utf8mb4"},
        "Children": []
      }
    ]
  }
}

成功响应(fetch=false)

{
  "code": 0,
  "msg": "ok",
  "data": {
    "total": 3,
    "data": [ {"ID":"conn-123.type-database","Name":"database","Type":"database","ParentID":"conn-123","DBType":"mysql"} ]
  }
}

常见错误

  • code != 0 且 error 包含底层信息。例如连接不存在:code=2, error="connection not found"。

注意

  • 建议客户端初次请求使用 fetch=false 进行结构化导航,减少首次 IO。

2) 列出子对象 — POST /database/metadata/children

用途

  • 列出父对象下的子对象(例如数据库下的表/视图,或表下的索引/触发器)。

请求字段 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | connId | string | 是 | 连接池查找键 | | connInfo | string | 否 | 展示/日志 | | path | array | 是 | 结构化路径(ObjectPath),最后一项为父对象。例如:[{"type":"database","name":"mydb"}] | | type | string | 否 | 子对象类型(childType):table/view/index/procedure/trigger,默认 table | | page | int | 否 | 分页页码 | | pageSize | int | 否 | 每页大小 | | fetch | bool | 否 | 是否返回具体条目 |

示例请求

{
  "connId": "conn-123",
  "path": [{"type":"database","name":"mydb"}],
  "type": "table",
  "page": 1,
  "pageSize": 50,
  "fetch": true
}

成功响应(fetch=true) 见根对象的 data.pagination 格式(total + data 列表,data 为 GenericObject)。

注意

  • 不再兼容旧的 dotted parentID(如 conn-123.db-mydb.table-users)。表级详情请使用 /database/metadata/object

3) 获取对象详情 — POST /database/metadata/object

用途

  • 获取单个对象详情(例如表的列、索引、DDL 等)。

请求字段 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | connId | string | 是 | 连接池查找键 | | connInfo | string | 否 | 展示/日志 | | path | array | 是 | 结构化路径(ObjectPath),完整路径从根到目标对象。例如:[{"type":"database","name":"mydb"},{"type":"table","name":"users"}] | | fetch | bool | 否 | 是否展开子对象(列/索引) |

示例请求

{
  "connId": "conn-123",
  "path": [{"type":"database","name":"mydb"},{"type":"table","name":"users"}],
  "fetch": true
}

成功响应

  • datameta.GenericObject,详情下通常包含 Children 数组(列、索引等)。

  • datameta.GenericObject,详情下通常包含 Children 数组(列、索引等)。注意:GenericObject 中的 Description 字段包含类型说明/交互提示,Attrs 仅为属性集合(map[string]string),服务端不再在 Attrs 中返回 suggestedRequest。前端应使用结构化 pathtype(按需)进行按类型加载。

注意

  • fetch=false,接口仅返回对象的基础元信息,不会展开大量子对象。

示例成功响应(fetch=false,返回 Children 类型占位)

{
  "code": 0,
  "msg": "ok",
  "data": {
    "ID": "conn-123.db-mydb.table-users",
    "Name": "users",
    "Type": "table",
    "ParentID": "mydb",
    "DBType": "mysql",
    "Attrs": {"engine":"InnoDB","createTime":null},
    "Children": [
      {
        "ID": "conn-123.db-mydb.table-users.type-column",
        "Name": "column",
        "Type": "column",
        "ParentID": "conn-123.db-mydb.table-users",
        "DBType": "mysql",
        "Description": "列(column)类型占位;调用同一对象详情接口并设置 fetch=true 可获取列列表",
        "Attrs": {}
      },
      {
        "ID": "conn-123.db-mydb.table-users.type-index",
        "Name": "index",
        "Type": "index",
        "ParentID": "conn-123.db-mydb.table-users",
        "DBType": "mysql",
        "Description": "索引(index)类型占位;调用对象详情接口并设置 fetch=true 可获取索引信息",
        "Attrs": {}
      }
    ]
  }
}

说明:服务端现在不再在 Attrs 中返回 suggestedRequest 字段(路由建议)。前端请使用结构化 path(ObjectPath)和 type 参数来按类型请求具体数据(例如: POST /database/metadata/object 的 body 中包含 path),或解析 Description 字段显示类型说明并在 UI 中提供“按类型展开”操作。


4) 获取创建/修改模板 — POST /database/metadata/create/template

用途

  • 驱动返回 ObjectTemplate,供前端渲染创建/修改表单。
  • 支持动态表单生成,根据对象类型和父上下文返回相应的字段定义、约束和示例。

请求字段 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | connId | string | 是 | 连接池查找键 | | connInfo | string | 否 | 展示/日志 | | objectType | string | 是 | 要创建/修改的对象类型(支持:database、table、index) | | parentName | string | 否 | 可选父上下文(创建表时为数据库名,创建索引时可为表名) |

示例请求

{ "connId":"conn-123", "objectType":"table", "parentName":"mydb" }

成功响应

  • datameta.ObjectTemplate,包含完整的表单模板信息。

ObjectTemplate 结构说明 | 字段 | 类型 | 说明 | |---|---|---| | objectType | string | 对象类型 | | parentHint | string | 父上下文提示信息 | | fields | []TemplateField | 表单字段定义数组 | | example | object | 示例数据(可选) | | notes | string | 附加说明(可选) |

TemplateField 字段详细说明 | 字段 | 类型 | 说明 | |---|---|---| | name | string | 字段标识符 | | label | string | 前端显示标签 | | type | FieldType | 字段类型(见下表) | | required | bool | 是否必填 | | default | string | 默认值(以字符串表示;前端应根据 field.type 做进一步解析,如 bool/int/JSON) | | help | string | 帮助提示 | | enumOptions | []string | 枚举选项(当type为enum时) | | nestedFields | []TemplateField | 嵌套字段(当type为list/object时) | | editable | bool | 是否可编辑(修改场景) | | current | string | 当前值(修改场景),以字符串表示;若字段为复杂类型,值为 JSON 字符串 | | allowedOps | []string | 允许的操作(修改场景) |

FieldType 可用值

  • string:字符串输入
  • int:整数输入
  • bool:布尔值
  • number:数值输入
  • enum:枚举选择
  • list:列表/数组
  • object:对象
  • textarea:多行文本

X) 获取元信息 — POST /database/metadata/info

用途

  • 返回数据库引擎层面的元信息,供前端的自动完成、语法高亮、类型提示与能力检测使用。

请求字段 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | connId | string | 是 | 连接池查找键(必须) | | connInfo | string | 否 | 展示/日志用的连接备注 |

示例请求

{
  "connId": "conn-123",
  "connInfo": "mysql-prod-01"
}

成功响应(示例)

{
  "code": 0,
  "msg": "ok",
  "data": {
    "keywords": ["ADD","ALTER","CREATE","SELECT","WHERE"],
    "fieldTypes": ["BIGINT","CHAR","DATE","DATETIME","DECIMAL","INT","VARCHAR"],
    "typeAliases": {"string":["VARCHAR","TEXT"]},
    "capabilities": {"supportsTransactions":true,"supportsDDLTransaction":false},
    "functions": ["COUNT","SUM","NOW"]
  }
}

说明与注意

  • 返回的数据结构对应 meta.MetadataCapabilities:包含 keywords(关键字/保留字)、fieldTypes(支持的数据类型,已规范化为大写)、typeAliases(可选的类型别名映射)、capabilities(布尔能力标记)、functions(可选函数列表)以及 extras(驱动或实现相关的额外信息)。
  • 该接口优先从连接池中指定连接获取信息;若驱动未实现或权限不足,服务可能返回错误(HTTP 500/400),并在 error 字段给出详细原因。
  • 关键字/类型列表在不同 MySQL 版本间存在差异;客户端应以返回值为准并可做缓存。若需要更实时或更丰富的数据(例如函数签名),建议后端扩展该接口并加入缓存策略或版本信息。

关于“当前值 (current)” 的获取与使用

为了让前端在修改/删除场景能够方便地渲染表单默认值或展示影响预览,服务端模板返回了两个层次的当前值:

  • ObjectTemplate.Current(对象级,map[string]string,可选)

    • 描述整个对象的关键当前属性,例如对于表:{"tableName":"users","engine":"InnoDB","charset":"utf8mb4"}。
    • 值均以字符串表示;对于复杂结构(如列列表),驱动会将其序列化为 JSON 字符串放入对应键中(例如 columns 的值可能为字符串形式的 JSON 数组)。
    • 前端可一次性使用该 map 填充表单,或用于显示“修改前/修改后”的差异比较。
  • TemplateField.Current(字段级,string,位于每个 TemplateField 中,optional)

    • 为每个字段提供更精细的当前值(例如字段 engine 的当前值为 "InnoDB")。
    • 值以字符串表示;前端在渲染单个控件时优先使用 TemplateField.Current,若该值缺失再回退到 ObjectTemplate.Current[fieldName]

优先级建议(前端)

  • 对每个表单字段,优先使用 field.Current(如果存在)。
  • 否则尝试使用 template.Current[field.Name] 作为回退值。

示例(修改表的模板响应简化版,注意值均为字符串)

{
  "code": 0,
  "msg": "ok",
  "data": {
    "operation": "update",
    "objectType": "table",
    "parentHint": "database: demo",
  "current": { "tableName": "users", "engine": "InnoDB", "charset": "utf8mb4" },
    "fields": [
      { "name": "tableName", "label": "Table Name", "type": "string", "required": true, "current": "users", "editable": false },
      { "name": "engine", "label": "Engine", "type": "string", "current": "InnoDB" },
      { "name": "charset", "label": "Charset", "type": "string", "current": "utf8mb4" }
    ]
  }
}

行级(Record)编辑约定

  • 若要编辑单条记录(row),请在 path 中把行标识包含为最后一段(例如 {"type":"row","name":"<rowId或主键序列>"},或根据驱动约定传递主键值集合)。
  • 服务端(driver 或 DataReader)应根据 ObjectPath 中的主键信息执行 SELECT(仅限需要的列)并将结果放入 ObjectTemplate.Current 与对应 TemplateField.Current
  • 示例如下(path 显示包含 row 标识的概念):

    {
    "path": [{"type":"database","name":"mydb"},{"type":"table","name":"users"},{"type":"row","name":"id=123"}]
    }
    

性能与权限注意

  • 获取当前值通常需要执行额外的元数据查询或 SELECT,可能消耗 IO。若场景对性能敏感(例如列表分页),前端可以在不需要当前值时避免调用 update 模板或向后端请求 includeCurrent=false(如果后端支持该参数)。
  • 获取行级数据或 COUNT(*) 可能对大表造成压力,驱动可返回估算值或提示使用异步任务来计算准确统计。
  • 当前值的读取需要相应的权限(SELECT / metadata 读取权限)。当权限不足时,驱动可能返回部分信息或带有警告的模板,前端应处理这些情况并提示用户。

后端改进建议

  • 可选参数 includeCurrent(bool,默认 true):允许前端显式请求或跳过当前值填充,以降低延迟。
  • AllowedOps 字段:驱动可以在复杂对象上返回允许的细粒度操作(如 ["add","modify","drop","rename"]),前端据此决定显示哪些操作按钮或更高级的确认框。

安全与一致性

  • 当前值是请求时刻的快照。执行真正的修改(execute=true)前,服务端应再次校验或在事务中执行必要的检查以减少 TOCTOU 风险(对于不能回滚的 DDL 操作尤其重要)。

示例前端流程(更新对象)

  1. 前端调用 POST /database/metadata/update/template 获取模板(默认包含当前值)。
  2. 前端用 field.Currenttemplate.Current 填充表单初始值。用户修改表单。可在本地做字段级校验。
  3. 前端先以 execute=false 提交 POST /database/metadata/object/update 进行预览。
    • 预览成功:后端以 HTTP 200 返回统一包装的 JSON(code=0),预览生成的 SQL 放在 data.generatedSQL 字段中。
    • 预览失败(校验/参数错误):后端会返回 HTTP 400 或 422(具体取决于错误类型),并在统一响应的 error 字段中返回中文的详细错误信息,code/msg 也会反映失败状态。
    • 注意:服务端驱动层现在直接通过 Go 错误(error)返回校验或执行失败,处理层会将其映射为合适的 HTTP 状态码和响应体;客户端应优先以 HTTP 状态码判断错误类别并读取 error 字段以获取详细原因。
  4. 若预览无误,前端再次以 execute=true 提交执行。执行前后后端应记录审计日志并返回最终结果:成功返回 HTTP 200,失败返回相应的 HTTP 错误码并在 error 字段给出详细信息。

支持的对象类型及模板详情

1) 创建数据库 (objectType: "database")

{
  "code": 0,
  "msg": "ok",
  "data": {
    "objectType": "database",
    "fields": [
      {
        "name": "databaseName",
        "label": "Database Name",
        "type": "string",
        "required": true,
        "help": "要创建的数据库名称,不含前缀"
      },
      {
        "name": "charset",
        "label": "Character Set",
        "type": "enum",
        "required": false,
        "default": "utf8mb4",
        "enumOptions": ["utf8mb4", "utf8", "latin1", "ascii", "ucs2", "utf16", "utf32", "big5", "gbk"]
      },
      {
        "name": "collation",
        "label": "Collation",
        "type": "string",
        "required": false
      },
      {
        "name": "ifNotExists",
        "label": "If Not Exists",
        "type": "bool",
        "required": false,
        "default": "false"
      }
    ],
    "example": {
      "databaseName": "mydb",
      "charset": "utf8mb4",
      "ifNotExists": "true"
    }
  }
}

2) 创建表 (objectType: "table")

{
  "code": 0,
  "msg": "ok",
  "data": {
    "objectType": "table",
    "parentHint": "parentName should be the database name",
    "fields": [
      {
        "name": "tableName",
        "label": "Table Name",
        "type": "string",
        "required": true
      },
      {
        "name": "ifNotExists",
        "label": "If Not Exists",
        "type": "bool",
        "required": false,
        "default": "false"
      },
      {
        "name": "engine",
        "label": "Engine",
        "type": "enum",
        "required": false,
        "default": "InnoDB",
        "enumOptions": ["InnoDB", "MyISAM"]
      },
      {
        "name": "charset",
        "label": "Charset",
        "type": "enum",
        "required": false,
        "default": "utf8mb4",
        "enumOptions": ["utf8mb4", "utf8", "latin1", "ascii", "ucs2", "utf16", "utf32", "big5", "gbk"]
      },
      {
        "name": "columns",
        "label": "Columns",
        "type": "list",
        "required": true,
        "nestedFields": [
          {
            "name": "name",
            "label": "Column Name",
            "type": "string",
            "required": true
          },
          {
            "name": "type",
            "label": "Data Type",
            "type": "string",
            "required": true
          },
          {
            "name": "nullable",
            "label": "Nullable",
            "type": "bool",
            "required": false,
            "default": "false"
          },
          {
            "name": "default",
            "label": "Default",
            "type": "string",
            "required": false
          },
          {
            "name": "autoIncrement",
            "label": "Auto Increment",
            "type": "bool",
            "required": false,
            "default": "false"
          }
        ]
      }
    ],
    "example": {
      "tableName": "users",
      "columns": "[{\"name\":\"id\",\"type\":\"INT\",\"nullable\":false}]",
      "engine": "InnoDB"
    }
  }
}

3) 创建索引 (objectType: "index")

{
  "code": 0,
  "msg": "ok",
  "data": {
    "objectType": "index",
    "parentHint": "parentName can be table name",
    "fields": [
      {
        "name": "indexName",
        "label": "Index Name",
        "type": "string",
        "required": true
      },
      {
        "name": "columns",
        "label": "Columns (comma separated)",
        "type": "string",
        "required": true
      },
      {
        "name": "unique",
        "label": "Unique",
        "type": "bool",
        "required": false,
        "default": "false"
      }
    ],
    "example": {
      "indexName": "idx_users_email",
      "columns": "email",
      "unique": "true"
    }
  }
}

使用说明

  • 前端应根据 type 字段渲染相应的表单控件
  • enum 类型使用下拉选择框,list 类型使用动态添加的子表单
  • nestedFields 定义列表项的结构,支持复杂嵌套
  • required 字段在前端应添加必填验证
  • default 值可用于预填充表单
  • help 字段提供用户友好的提示信息

备注

  • TemplateField 包含 name, label, type, required, default, enumOptions, editable, current, allowedOps 等字段。详见附录。

4.1) 获取更新模板 — POST /database/metadata/update/template

用途

  • 获取现有数据库对象的更新表单模板,包含当前值和允许的修改操作。
  • 支持动态表单生成,根据对象类型和当前状态返回相应的字段定义、约束和修改选项。

请求字段 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | connId | string | 是 | 连接池查找键 | | connInfo | string | 否 | 展示/日志 | | path | []ObjectPathEntry | 是 | 目标对象的结构化路径 |

示例请求

{
  "connId": "conn-123",
  "connInfo": "MySQL Connection",
  "path": [
    {"type": "database", "name": "mydb"},
    {"type": "table", "name": "users"}
  ]
}

成功响应

  • datameta.ObjectTemplate,包含完整的更新表单模板信息。
  • 模板字段会包含 current(当前值)和 editable(是否可编辑)信息。

ObjectTemplate 更新场景特性

  • editable 字段指示哪些字段可以修改
  • current 字段提供当前值作为默认值
  • allowedOps 字段列出允许的操作(如 "ADD COLUMN", "DROP COLUMN" 等)

支持的对象类型及更新模板详情

1) 更新数据库 (objectType: "database")

{
  "code": 0,
  "msg": "ok",
  "data": {
    "objectType": "database",
    "parentHint": "Database: mydb",
    "fields": [
      {
        "name": "databaseName",
        "label": "Database Name",
        "type": "string",
        "required": true,
        "current": "mydb",
        "editable": false,
        "help": "数据库名称不可修改"
      },
      {
        "name": "charset",
        "label": "Character Set",
        "type": "enum",
        "required": false,
        "current": "utf8mb4",
        "editable": true,
        "enumOptions": ["utf8mb4", "utf8", "latin1", "ascii", "ucs2", "utf16", "utf32", "big5", "gbk"]
      },
      {
        "name": "collation",
        "label": "Collation",
        "type": "string",
        "required": false,
        "current": "utf8mb4_general_ci",
        "editable": true
      }
    ],
    "notes": "修改数据库属性将执行 ALTER DATABASE 语句"
  }
}

2) 更新表 (objectType: "table")

{
  "code": 0,
  "msg": "ok",
  "data": {
    "objectType": "table",
    "parentHint": "Database: mydb, Table: users",
    "fields": [
      {
        "name": "tableName",
        "label": "Table Name",
        "type": "string",
        "required": true,
        "current": "users",
        "editable": false,
        "help": "表名不可直接修改,建议使用重命名操作"
      },
      {
        "name": "engine",
        "label": "Storage Engine",
        "type": "enum",
        "required": false,
        "current": "InnoDB",
        "editable": true,
        "enumOptions": ["InnoDB", "MyISAM", "MEMORY", "CSV", "ARCHIVE"]
      },
      {
        "name": "charset",
        "label": "Character Set",
        "type": "enum",
        "required": false,
        "current": "utf8mb4",
        "editable": true,
        "enumOptions": ["utf8mb4", "utf8", "latin1"]
      },
      {
        "name": "collation",
        "label": "Collation",
        "type": "string",
        "required": false,
        "current": "utf8mb4_general_ci",
        "editable": true
      },
      {
        "name": "comment",
        "label": "Comment",
        "type": "textarea",
        "required": false,
        "current": "User information table",
        "editable": true
      }
    ],
    "notes": "修改表属性将执行 ALTER TABLE 语句"
  }
}

3) 更新索引 (objectType: "index")

{
  "code": 0,
  "msg": "ok",
  "data": {
    "objectType": "index",
    "parentHint": "Table: users, Index: idx_email",
    "fields": [
      {
        "name": "indexName",
        "label": "Index Name",
        "type": "string",
        "required": true,
        "current": "idx_email",
        "editable": false,
        "help": "索引名不可修改,建议删除后重建"
      },
      {
        "name": "columns",
        "label": "Columns",
        "type": "string",
        "required": true,
        "current": "email",
        "editable": true,
        "help": "修改索引列将重建索引"
      },
      {
        "name": "unique",
        "label": "Unique",
        "type": "bool",
        "required": false,
        "current": "true",
        "editable": false,
        "help": "唯一性不可修改,建议删除后重建"
      }
    ],
    "notes": "索引修改将执行 DROP INDEX 和 CREATE INDEX 语句"
  }
}

4.2) 获取删除模板 — POST /database/metadata/delete/template

用途

  • 获取删除数据库对象的确认模板,显示将要删除的对象信息和依赖关系。
  • 帮助用户了解删除操作的影响范围,支持安全的删除确认流程。

请求字段 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | connId | string | 是 | 连接池查找键 | | connInfo | string | 否 | 展示/日志 | | path | []ObjectPathEntry | 是 | 目标对象的结构化路径 |

示例请求

{
  "connId": "conn-123",
  "connInfo": "MySQL Connection",
  "path": [
    {"type": "database", "name": "testdb"}
  ]
}

成功响应

  • datameta.ObjectTemplate,包含删除确认表单模板。
  • 模板通常包含确认字段和影响范围信息。

ObjectTemplate 删除场景特性

  • 主要用于显示删除影响和获取用户确认
  • 可能包含依赖对象列表和警告信息
  • editable 字段通常为 false,只显示信息

支持的对象类型及删除模板详情

1) 删除数据库 (objectType: "database")

{
  "code": 0,
  "msg": "ok",
  "data": {
    "objectType": "database",
    "parentHint": "Database: testdb",
    "fields": [
      {
        "name": "databaseName",
        "label": "Database Name",
        "type": "string",
        "required": true,
        "current": "testdb",
        "editable": false
      },
      {
        "name": "tableCount",
        "label": "Tables Count",
        "type": "int",
        "required": false,
        "current": "5",
        "editable": false,
        "help": "数据库中包含的表数量"
      },
      {
        "name": "confirmDelete",
        "label": "Confirm Delete",
        "type": "bool",
        "required": true,
        "default": "false",
        "help": "删除数据库将永久删除所有表、视图、索引等对象"
      }
    ],
    "notes": "警告:删除数据库将永久删除所有相关对象且不可恢复!"
  }
}

2) 删除表 (objectType: "table")

{
  "code": 0,
  "msg": "ok",
  "data": {
    "objectType": "table",
    "parentHint": "Database: mydb, Table: users",
    "fields": [
      {
        "name": "tableName",
        "label": "Table Name",
        "type": "string",
        "required": true,
        "current": "users",
        "editable": false
      },
      {
        "name": "rowCount",
        "label": "Estimated Row Count",
        "type": "int",
        "required": false,
        "current": "1000",
        "editable": false
      },
      {
        "name": "indexCount",
        "label": "Index Count",
        "type": "int",
        "required": false,
        "current": "3",
        "editable": false
      },
      {
        "name": "confirmDelete",
        "label": "Confirm Delete",
        "type": "bool",
        "required": true,
        "default": "false",
        "help": "删除表将永久删除所有数据和相关索引"
      }
    ],
    "notes": "删除表操作不可恢复,请确认已备份重要数据"
  }
}

3) 删除索引 (objectType: "index")

{
  "code": 0,
  "msg": "ok",
  "data": {
    "objectType": "index",
    "parentHint": "Table: users, Index: idx_email",
    "fields": [
      {
        "name": "indexName",
        "label": "Index Name",
        "type": "string",
        "required": true,
        "current": "idx_email",
        "editable": false
      },
      {
        "name": "isUnique",
        "label": "Is Unique Index",
        "type": "bool",
        "required": false,
        "current": "true",
        "editable": false
      },
      {
        "name": "confirmDelete",
        "label": "Confirm Delete",
        "type": "bool",
        "required": true,
        "default": "false",
        "help": "删除索引可能影响查询性能"
      }
    ],
    "notes": "删除索引后相关查询可能变慢,建议观察一段时间后再决定是否重建"
  }
}

5) 创建对象(preview/execute) — POST /database/metadata/object/create

用途

  • 接收前端创建或修改请求,支持预览(preview)与实际执行(execute)。

请求字段 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | connId | string | 是 | 连接池查找键 | | connInfo | string | 否 | 展示/日志 | | objectType | string | 是 | 要创建的对象类型 | | parentName | string | 否 | 父上下文 | | properties | object | 是 | 表单数据(结构依赖于 ObjectTemplate) | | execute | bool | 否 | false=preview(返回 SQL),true=执行 |

示例请求(preview)

{
  "connId":"conn-123",
  "objectType":"table",
  "parentName":"mydb",
  "properties": { "name":"users","columns":[/*...*/] },
  "execute": false
}

成功响应

  • datameta.CreateObjectResponse,包含 generatedSQL(字符串数组)与可选的 objectID。当 execute=true 时返回执行后的结果(例如 objectID / 影响信息),错误通过 HTTP 非200 返回并在 error 字段给出详细信息。

安全提示

  • execute=true 会在目标数据库执行 DDL,务必在有审计与权限控制的情况下使用。

5.1) 更新对象(preview/execute) — POST /database/metadata/object/update

用途

  • 接收前端更新现有对象的请求,支持预览(preview)与实际执行(execute)。
  • 根据更新模板获取的表单数据执行相应的 ALTER 语句。

请求字段 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | connId | string | 是 | 连接池查找键 | | connInfo | string | 否 | 展示/日志 | | updateRequest | meta.UpdateObjectRequest | 是 | 更新请求,包含路径和属性 | | execute | bool | 否 | false=preview(返回 SQL),true=执行 |

UpdateObjectRequest 结构 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | path | []ObjectPathEntry | 是 | 目标对象的结构化路径 | | properties | object | 是 | 更新后的属性数据 |

示例请求(preview)

{
  "connId": "conn-123",
  "connInfo": "MySQL Connection",
  "updateRequest": {
    "path": [
      {"type": "database", "name": "mydb"},
      {"type": "table", "name": "users"}
    ],
    "properties": {
      "engine": "MyISAM",
      "charset": "utf8",
      "comment": "Updated user table"
    }
  },
  "execute": false
}

成功响应

  • datameta.UpdateObjectResponse,包含 generatedSQL(字符串数组)和可选的 objectID;当 execute=true 时返回执行后的结果或错误(错误通过 HTTP 非200 返回并在 error 字段给出详细信息)。

UpdateObjectResponse 结构 | 字段 | 类型 | 说明 | |---|---|---| | generatedSQL | []string | 预览时生成的 SQL 语句列表 | | objectID | string | 若操作创建/影响到新对象则返回其 ID(可选) |

安全提示

  • 更新操作会修改现有对象结构,建议先预览 SQL 语句
  • 某些更新操作(如修改存储引擎)可能需要表锁定,影响并发访问
  • 建议在维护窗口或低峰期执行更新操作

6) 刷新对象元数据 — POST /database/metadata/object/refresh

用途

  • 触发驱动层对指定对象的元数据刷新(驱动可能为占位实现)。

请求字段 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | objectID | string | 是 | 对象唯一 ID(例如 conn-123.db-mydb.table-users) |

示例请求

{ "objectID": "conn-123.db-mydb.table-users" }

成功响应

  • {code:0, msg:"ok"} 或按驱动实现返回其他信息。多数驱动当前为占位实现。

7) 删除对象(preview/execute) — POST /database/metadata/object/delete

用途

  • 按匹配规则查找要删除的对象并返回匹配结果;默认 preview(不执行),可用 execute=true 执行(谨慎)。

请求字段 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | connId | string | 否 | 建议提供,用于记录/执行操作的目标连接 | | execute | bool | 否 | false=preview,true=执行 | | object | object | 是 | 匹配规则,包含 parentIdname(支持通配符)、type 等 |

示例请求(preview)

{
  "connId":"conn-123",
  "execute": false,
  "object": { "parentId":"conn-123.db-mydb","name":"user_%","type":"table" }
}

成功响应

  • dataObjectOperationResponse,包含 affected (int64)、objectID (string,可选) 与 sql (string)。部分实现会把匹配对象的 JSON 放在 sql 字段以便前端解析或调试;当发生错误时,服务端会返回 HTTP 非200 并在 error 字段给出详细信息。

注意

  • 删除操作默认不执行真实 DROP,请在执行前确认并做好备份与审计。

错误处理与常见状态

  • 通用:code 非0 表示失败,msg 为简短提示,error 包含底层错误堆栈/信息(仅供调试)。
  • 推荐前端在遇到 code != 0 时,显示 msg 给用户,并在开发/调试模式下查看 error

示例失败响应

{
  "code": 2,
  "msg": "连接不存在",
  "data": null,
  "error": "connection not found: conn-999"
}

附录:ObjectTemplate / TemplateField 详细说明

ObjectTemplate 结构

字段 类型 必需 说明
objectType string 对象类型(如 "database", "table", "index")
parentHint string 父上下文提示信息
fields []TemplateField 表单字段定义数组
example object 示例数据,用于前端预览
notes string 附加说明和注意事项

TemplateField 结构

字段 类型 必需 说明
name string 字段唯一标识符,用于表单提交
label string 前端显示的字段标签
type FieldType 字段类型,决定前端渲染方式
required bool 是否为必填字段
default any 默认值
help string 帮助提示文本
enumOptions []string 枚举选项(仅当type="enum"时有效)
nestedFields []TemplateField 嵌套字段定义(用于list/object类型)
editable bool 是否可编辑(修改场景使用)
current any 当前值(修改场景使用)
allowedOps []string 允许的操作(修改场景使用)

FieldType 枚举值详解

类型值 说明 前端控件建议
string 单行文本输入 <input type="text">
int 整数输入 <input type="number">
bool 布尔值 <input type="checkbox"> 或开关组件
number 数值输入(支持小数) <input type="number" step="any">
enum 枚举选择 <select> 下拉框
list 数组/列表 动态添加的子表单组
object 对象 嵌套表单
textarea 多行文本 <textarea>

创建场景 vs 修改场景

创建场景(新建对象):

  • 主要使用:name, label, type, required, default, help, enumOptions, nestedFields
  • 忽略:editable, current, allowedOps

修改场景(编辑现有对象):

  • 额外使用:editable, current, allowedOps
  • editable: 控制字段是否可编辑
  • current: 显示当前值
  • allowedOps: 支持的操作,如 ["modify", "drop", "rename"]

实际使用示例

简单字段(字符串输入)

{
  "name": "tableName",
  "label": "Table Name",
  "type": "string",
  "required": true,
  "help": "请输入表名,只能包含字母、数字和下划线"
}

枚举字段(下拉选择)

{
  "name": "engine",
  "label": "Storage Engine",
  "type": "enum",
  "required": false,
  "default": "InnoDB",
  "enumOptions": ["InnoDB", "MyISAM", "MEMORY", "CSV"],
  "help": "选择表的存储引擎"
}

列表字段(动态数组)

{
  "name": "columns",
  "label": "Table Columns",
  "type": "list",
  "required": true,
  "nestedFields": [
    {
      "name": "name",
      "label": "Column Name",
      "type": "string",
      "required": true
    },
    {
      "name": "type",
      "label": "Data Type",
      "type": "string",
      "required": true
    }
  ]
}

修改场景字段

{
  "name": "email",
  "label": "Email Address",
  "type": "string",
  "current": "user@example.com",
  "editable": true,
  "allowedOps": ["modify", "drop"],
  "help": "修改邮箱地址或选择删除此字段"
}

前端实现建议

  1. 动态表单渲染:根据 type 字段选择合适的控件
  2. 必填验证:对 required=true 的字段添加前端验证
  3. 默认值处理:使用 default 值预填充表单
  4. 嵌套结构listobject 类型需要递归渲染
  5. 条件显示:某些字段可能基于其他字段的值显示/隐藏
  6. 操作按钮:修改场景下根据 allowedOps 显示相应按钮

注意事项

  • 所有字段名应使用驼峰命名法(camelCase)
  • 枚举选项应按逻辑顺序排列,常用选项在前
  • 帮助文本应简洁明了,控制在50字符以内
  • 嵌套字段的深度不宜超过3层
  • 修改场景的 current 值应与后端实际值保持同步

本地运行与调试建议

  1. 设置 MySQL 连接字符串(环境变量 MYSQL_DSN):

    $env:MYSQL_DSN = "user:password@tcp(127.0.0.1:3306)/?parseTime=true"
    go run .\main.go
    
  2. curl 快速测试示例:

    curl -X POST http://localhost:8080/database/metadata/root \
    -H "Content-Type: application/json" \
    -d '{"connId":"conn-123","page":1,"pageSize":20}'
    
  3. 如果出现数据库或连接错误,请检查 MYSQL_DSN、网络与权限,并查看服务日志(stdout/stderr)。


如需我继续:

  • 扫描并替换仓库中仍将 connInfo 用作 lookup key 的调用点为 connId,并运行 go build ./... 验证。
  • 或将此文档导出为 OpenAPI/Swagger 规范(需映射 Go DTO 到 OpenAPI schema)。

(文档由代码近照整理,若后续接口签名再次变更,请让我同步更新示例与字段说明。)