API.md 20 KB

Database Data Query API(详细)

本文档描述数据查询模块的 API 接口,用于执行数据库表/视图的数据查询操作。

概要

本文档详细描述数据查询模块的 API(前缀 /database/data),包括请求/响应格式、异步任务交互与可选的 WebSocket 推送方案。所有接口使用 JSON(Content-Type: application/json),并采用 service/internal/common/response.Response 作为统一响应包装。

通用响应格式

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

通用字段说明

  • connId (string, required):连接池查找键,后端用此 key 调用 ConnectionPool.GetConnection(connId)。
  • connInfo (string, optional):展示/日志用的连接信息(可选),不会用于建立连接。
  • path (array of {type,name}, required):结构化路径,表示从根到目标对象的层级。例如数据库下的表 users 的 path 为 [{"type":"database","name":"mydb"},{"type":"table","name":"users"}]。
  • query (object, required):查询参数对象,详见下文 DataQueryRequest。

通用数据结构

  • meta.DataMeta 字段:

    • name string:名称(列名、行标识等)
    • type string:类型("column"、"row"、"value"等)
    • fieldType string:表单类型(可选)
    • dbType string:数据库类型(如 "VARCHAR(255)"、"INT")
    • nullable bool:是否可空
    • omitted bool:当该字段的值在当前响应中被省略(通常因为数据为大对象如 BLOB/CLOB 或按策略隐藏)时为 true。 前端可据此展示占位、下载链接或按需请求完整内容;驱动可能在 meta 中包含 size(字节数)等辅助信息。
    • valueType string:值的类型(用于前端识别,如 "string"、"int"、"bool")
    • rowId string:行ID(仅对Type="row"有效,用于唯一标识数据行;MySQL等无内置ROWID的数据库为空字符串)
    • attrs object:额外属性
    • meta object:元数据
    • children []DataMeta:子项
  • DataOperationResponse 统一响应结构(用于查询和SQL执行):

    • success bool:操作是否成功
    • data QueryResult:查询结果数据(SELECT语句或数据查询)
    • sqlType string:SQL类型(ExecuteSQL独有:SELECT/INSERT/UPDATE/DELETE/CREATE/DROP等)
    • affectedRows int64:影响行数(ExecuteSQL独有:INSERT/UPDATE/DELETE)
    • lastInsertId interface{}:最后插入ID(ExecuteSQL独有:INSERT语句)
    • errorMessage string:错误信息(ExecuteSQL独有)
    • executionTime int64:执行时间(毫秒)。
    • 对于 ExecuteSQL:在 DataOperationResponse 顶层返回 SQL 执行耗时(示例中已包含)。
    • 对于 QueryData:执行时间由驱动写入 data.executionTimeQueryResult.ExecutionTime),处理器不会将其复制到响应顶层;前端应从 data.executionTime 读取查询耗时。
    • rowsReturned int:返回行数(ExecuteSQL独有,SELECT语句)
    • message string:提示信息

1) 数据查询 — POST /database/data/query

用途

  • 对指定路径的数据库对象(通常为表或视图)执行数据查询,支持列选择、过滤、排序、分页等。
  • 支持同步和异步执行模式。

请求字段 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | connId | string | 是 | 连接池查找键(必须) | | connInfo | string | 否 | 展示/日志用的连接备注 | | path | []ObjectPathEntry | 是 | 目标对象的结构化路径(见通用字段说明) | | query | DataQueryRequest | 是 | 查询参数对象 | | async | bool|string | 否 | 异步模式。支持布尔或字符串:false/"sync"=同步,true/"poll"=异步(轮询),"ws"=异步(WebSocket 推送) |

DataQueryRequest 结构 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | columns | []string | 否 | 需要返回的列名列表;为空表示返回全部列 | | filters | object | 否 | 简单等值过滤:列名 -> 字符串值 | | order | []SortField | 否 | 排序字段列表 | | offset | int | 否 | 起始偏移(分页用) | | limit | int | 否 | 返回最大行数;0 表示使用默认 | | includeTotal | bool | 否 | 是否计算总行数(影响性能) | | stream | bool | 否 | 是否流式读取(暂未实现) | | args | []string | 否 | 参数化查询占位符参数 | | queryId | string | 否 | 查询唯一标识(用于跟踪) | | timeoutMs | int | 否 | 查询超时时间(毫秒) | | fetch | bool | 否 | 是否执行查询(false 只返回 SQL,不返回数据) |

SortField 结构 | 字段 | 类型 | 必需 | 说明 | |---|---:|:---:|---| | column | string | 是 | 排序列名 | | desc | bool | 否 | 是否降序(默认升序) |

示例请求

{
  "connId": "conn-123",
  "connInfo": "mysql-prod-01",
  "path": [
    {"type": "database", "name": "mydb"},
    {"type": "table", "name": "users"}
  ],
  "query": {
    "columns": ["id", "name", "email"],
    "filters": {"status": "active"},
    "order": [{"column": "id", "desc": false}],
    "offset": 0,
    "limit": 10,
    "includeTotal": true,
    "fetch": true
  },
  "async": false
}

异步查询示例

{
  "connId": "conn-123",
  "connInfo": "mysql-prod-01",
  "path": [
    {"type": "database", "name": "mydb"},
    {"type": "table", "name": "users"}
  ],
  "query": {
    "columns": ["id", "name", "email"],
    "filters": {"status": "active"},
    "order": [{"column": "id", "desc": false}],
    "offset": 0,
    "limit": 1000,
    "includeTotal": true,
    "fetch": true
  },
  "async": true
}

成功响应

{
  "code": 0,
  "msg": "ok",
  "data": {
    "success": true,
    "data": {
      "columns": [
        {
          "name": "id",
          "type": "column",
          "dbType": "INT",
          "nullable": false
        },
        {
          "name": "name",
          "type": "column",
          "dbType": "VARCHAR(100)",
          "nullable": true
        },
        {
          "name": "email",
          "type": "column",
          "dbType": "VARCHAR(255)",
          "nullable": true
        }
      ],
      "rows": [
        {
          "type": "row",
          "rowId": "",
          "children": [
            {"name": "id", "type": "value", "value": 1, "valueType": "int"},
            {"name": "name", "type": "value", "value": "Alice", "valueType": "string"},
            {"name": "email", "type": "value", "value": "alice@example.com", "valueType": "string"}
          ]
        },
        {
          "type": "row",
          "rowId": "",
          "children": [
            {"name": "id", "type": "value", "value": 2, "valueType": "int"},
            {"name": "name", "type": "value", "value": "Bob", "valueType": "string"},
            {"name": "email", "type": "value", "value": "bob@example.com", "valueType": "string"}
          ]
        }
      ],
      "total": 100,
      "returned": 2,
      "truncated": false,
      "executionTime": 12
    },
    "message": "查询完成"
  }
异步查询成功响应

json { "code": 0, "msg": "ok", "data": {

"success": true,
"data": {
  "taskId": "task-abc-123-def-456",
  "status": "running",
  "message": "异步查询已提交,正在执行中",
  "wsUrl": "{scheme}://{host}/database/data/tasks/ws"  
}

} }

json { "connId": "conn-123", "path": [

{"type": "database", "name": "mydb"},
{"type": "table", "name": "users"}

], "query": {

"fetch": false

} }


响应:

json { "code": 0, "msg": "ok", "data": {

"success": true,
"data": {
  "columns": [
    {
      "name": "id",
      "type": "column",
      "dbType": "INT",
      "nullable": false
    },
    {
      "name": "name",
      "type": "column",
      "dbType": "VARCHAR(100)",
      "nullable": true
    }
  ],
  "rows": [],
  "total": 100,
  "returned": 100,
  "truncated": false,
  "stats": {
    "sql": "SELECT * FROM `users`"
  },
  "executionTime": 5
},
"message": "查询完成"

} }


Async=true 示例(异步执行查询)

json { "connId": "conn-123", "path": [

{"type": "database", "name": "mydb"},
{"type": "table", "name": "users"}

], "query": {}, "async": true }


响应:

json { "code": 0, "msg": "ok", "data": {

"success": true,
"taskId": "abc123def456",
"message": "查询已提交到任务队列"

} }


常见错误
- code != 0 且 `error` 包含底层信息。例如路径无效:code=2, error="invalid path: need at least database and table"。
- 连接不存在:code=2, error="从连接池获取连接失败"。
- 查询失败:code=2, error="failed to execute query"。

注意事项
- 路径必须至少包含数据库和表两级。
- 过滤条件当前使用简单等值,复杂条件可后续扩展。
- 值类型根据数据库列类型自动映射(string/int/float/bool/[]byte/nil),前端可直接使用 JSON 原生类型。
- includeTotal=true 时会额外执行 COUNT 查询,可能影响性能。
- fetch=false 时只构建并返回 SQL,不执行查询(适合预览)。
- async=true 时查询将通过任务队列异步执行,返回任务ID;需通过任务接口获取结果。
- 当前实现未使用参数化查询,生产环境建议升级以防 SQL 注入。
-------------------------------------------------------------------------------

## 2) 获取异步任务结果 — POST /database/data/task/result

用途
- 获取异步数据查询任务的执行结果和状态。

请求字段
| 字段 | 类型 | 必需 | 说明 |
|---|---:|:---:|---|
| taskId | string | 是 | 异步查询任务的ID |

示例请求

json { "taskId": "abc123def4" }


成功响应(任务完成)

json { "code": 0, "msg": "ok", "data": {

"success": true,
"data": {
  "columns": [
    {
      "name": "id",
      "type": "column",
      "dbType": "INT",
      "nullable": false
    }
  ],
  "rows": [
    {
      "type": "row",
      "rowId": "",
      "children": [
        {"name": "id", "type": "value", "value": 1, "valueType": "int"}
      ]
    }
  ],
  "total": 1,
  "returned": 1,
  "truncated": false,
  "stats": {
    "query": "SELECT * FROM `users`"
  }
},
"status": "completed",
"message": "获取任务结果成功"

} }


成功响应(任务进行中)

json { "code": 0, "msg": "ok", "data": {

"success": true,
"status": "running",
"message": "获取任务结果成功"

} }


常见错误
- code != 0 且 `error` 包含底层信息。例如任务不存在:code=2, error="获取任务状态失败: 任务不存在"。
- 任务管理器未配置:code=2, error="任务管理器未配置"。

注意事项
- 任务状态包括:pending(等待中)、running(运行中)、completed(已完成)、failed(失败)、cancelled(已取消)。
- 只有 completed 状态才会返回查询数据。
- 建议轮询获取任务结果,失败或取消状态会返回错误信息。

WebSocket 推送(可选)
- 端点:`GET /database/data/tasks/ws`(WebSocket upgrade)
- 用途:客户端可通过 WebSocket 订阅指定 `taskId` 的实时状态与进度更新,以减少轮询频率并获得即时通知。
- 连接后订阅格式(客户端发送 JSON):
  - 订阅:`{"action":"subscribe","taskId":"<taskId>"}`
  - 退订:`{"action":"unsubscribe","taskId":"<taskId>"}`
- 服务器推送格式(示例,JSON):

json {"taskId":"", "status":"running|success|failed|cancelled", "progress": 42, "result": {...}, "error": "..."}

- 使用说明:
  - 在发起异步请求时,如果希望使用 WebSocket 推送,请将 `async` 设置为字符串 `"ws"`;服务端在接受后会在异步响应中返回 `wsUrl`,客户端据此建立 WebSocket 连接并发送订阅消息。
  - 若 WebSocket 不可用或连接失败,请继续使用传统的轮询接口 `POST /database/data/task/result` 或 `POST /database/data/execute/task/result` 获取任务状态。
  - WebSocket 连接断开时,服务端将自动清理对应订阅;客户端应在断开后重新订阅或回退到轮询。

前端使用示例
----------------
下面给出简短示例,帮助前端团队如何使用 `async` 字段、如何建立 WebSocket 连接并订阅任务,以及在连接不可用时如何回退到轮询。

1) 使用 `async` 字段的示例请求

 - 同步执行(等同于立即返回结果):

json { "connId": "conn-123", "path": [...], "query": {}, "async": false }


 - 异步(轮询)模式:

json { "connId": "conn-123", "path": [...], "query": {}, "async": true }


 - 异步(WebSocket 推送)模式:

json { "connId": "conn-123", "path": [...], "query": {}, "async": "ws" }


2) 使用 Fetch 发起异步(ws)请求并读取返回的 `wsUrl`

js // 发起异步请求并请求 WebSocket 推送 const resp = await fetch('/database/data/query', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ connId: 'conn-123', path: [...], query: {}, async: 'ws' }) }); const body = await resp.json(); // 业务包装在 body.data const wsUrl = body.data?.wsUrl; // 例如: "{scheme}://{host}/database/data/tasks/ws" const taskId = body.data?.taskId;


3) 使用浏览器 WebSocket 建立连接并订阅任务(示例)

js // 在浏览器中构造实际的 ws 地址 const scheme = window.location.protocol === 'https:' ? 'wss' : 'ws'; const host = window.location.host; // host:port const wsEndpoint = ${scheme}://${host}/database/data/tasks/ws;

const ws = new WebSocket(wsEndpoint); ws.onopen = () => { // 订阅刚才创建的任务 ws.send(JSON.stringify({ action: 'subscribe', taskId })); }; ws.onmessage = (evt) => { try {

const msg = JSON.parse(evt.data);
// msg 结构示例: { taskId, status, progress, result, error }
console.log('task update', msg);
if (msg.status === 'success' || msg.status === 'failed' || msg.status === 'cancelled') {
  // 处理完成或失败
}

} catch (e) {

console.error('invalid ws message', e);

} }; ws.onclose = () => { // 可选:回退到轮询获取最终结果 // pollTaskResult(taskId) };

// 取消订阅示例 // ws.send(JSON.stringify({ action: 'unsubscribe', taskId }));


4) 如果 WebSocket 不可用,回退到轮询示例(简易):

js async function pollTaskResult(taskId){ while(true){

const r = await fetch('/database/data/task/result', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ taskId })
});
const j = await r.json();
if (j.data?.status === 'completed'){
  return j.data?.data; // 最终结果
}
if (j.data?.status === 'failed' || j.data?.status === 'cancelled'){
  throw new Error('task failed or cancelled');
}
await new Promise(res => setTimeout(res, 2000)); // 2秒轮询

} }


说明:`{scheme}://{host}` 应由前端运行环境替换为实际值(例如使用 `window.location` 相关属性),或由后端在异步响应中返回完整 `wsUrl`。

-------------------------------------------------------------------------------

## 3) SQL 执行 — POST /database/data/execute

用途
- 执行各种类型的 SQL 语句(SELECT、INSERT、UPDATE、DELETE、CREATE、DROP 等)。
- 支持同步和异步执行模式。

请求字段
| 字段 | 类型 | 必需 | 说明 |
|---|---:|:---:|---|
| connId | string | 是 | 连接池查找键(必须) |
| connInfo | string | 否 | 展示/日志用的连接备注 |
| path | []ObjectPathEntry | 是 | 目标对象的结构化路径(用于确定数据库连接) |
| sql | string | 是 | 要执行的 SQL 语句 |
| params | []interface{} | 否 | 参数化查询的参数列表 |
| async | bool|string | 否 | 异步模式。支持布尔或字符串:`false`/`"sync"`=同步,`true`/`"poll"`=异步(轮询),`"ws"`=异步(WebSocket 推送) |
| includeLarge | bool | 否 | 是否在响应中包含大对象字段(如 BLOB/CLOB)的完整值;默认 `false`,当为 `false` 时驱动可能省略大对象并在对应 `DataMeta` 中设置 `omitted: true` |

ExecuteSQLRequest 结构
| 字段 | 类型 | 必需 | 说明 |
|---|---:|:---:|---|
| connId | string | 是 | 连接池查找键 |
| connInfo | string | 否 | 展示/日志用的连接备注 |
| path | []ObjectPathEntry | 是 | 目标对象的结构化路径 |
| sql | string | 是 | SQL 语句 |
| params | []interface{} | 否 | 参数列表 |
| async | bool | 否 | 是否异步执行 |
| includeLarge | bool | 否 | 是否在响应中包含大对象字段的完整值;默认 `false`。当为 `false` 时,驱动可能将大对象省略并在 `data.columns`/`data.rows.children` 中的 `DataMeta` 设置 `omitted: true`,并在 `meta.size` 中提供字节长度说明。 |

示例请求

json { "connId": "conn-123", "connInfo": "mysql-prod-01", "path": [

{"type": "database", "name": "mydb"}

], "sql": "CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(100))", "params": [], "async": false }


异步执行示例

json { "connId": "conn-123", "connInfo": "mysql-prod-01", "path": [

{"type": "database", "name": "mydb"}

], "sql": "INSERT INTO users (name) SELECT name FROM temp_users", "async": true }


成功响应

json { "code": 0, "msg": "ok", "data": {

"success": true,
"sqlType": "CREATE TABLE",
"affectedRows": 0,
"executionTime": 15,
"message": "SQL执行完成"

} }

"message": "SQL执行完成"

} }


异步响应

json { "code": 0, "msg": "ok", "data": {

"success": true,
"taskId": "task-abc-123",
"message": "SQL已提交到任务队列",
"wsUrl": "{scheme}://{host}/database/data/tasks/ws"

} }


ExecuteResult 结构(已合并为 DataOperationResponse)
| 字段 | 类型 | 说明 |
|---|---|---|
| success | bool | 执行是否成功 |
| sqlType | string | SQL 类型(SELECT/INSERT/UPDATE/DELETE/CREATE/DROP 等) |
| affectedRows | int64 | 影响行数(INSERT/UPDATE/DELETE) |
| lastInsertId | interface{} | 最后插入 ID(INSERT 语句) |
| data | QueryResult | 查询结果(SELECT 语句) |
| errorMessage | string | 错误信息 |
| executionTime | int64 | 执行时间(毫秒) |
| rowsReturned | int | 返回的行数(SELECT 语句) |

**注意**:API 响应现在统一使用 `DataOperationResponse` 结构,包含了所有执行相关的字段。

-------------------------------------------------------------------------------

## 4) 获取 SQL 执行任务结果 — POST /database/data/execute/task/result

用途
- 获取异步 SQL 执行任务的执行结果。

请求字段
| 字段 | 类型 | 必需 | 说明 |
|---|---:|:---:|---|
| taskId | string | 是 | 异步任务 ID |

示例请求

json { "taskId": "task-abc-123" }


成功响应

json { "code": 0, "msg": "ok", "data": {

"success": true,
"status": "completed",
"data": {
  "success": true,
  "sqlType": "INSERT",
  "affectedRows": 1000,
  "executionTime": 250,
  "message": "SQL执行完成"
},
"message": "获取任务结果成功"

} }


运行中响应

json { "code": 0, "msg": "ok", "data": {

"success": true,
"status": "running",
"message": "获取任务结果成功"

} } ```

常见错误

  • code != 0 且 error 包含底层信息。例如任务不存在:code=2, error="获取任务状态失败: 任务不存在"。
  • 任务管理器未配置:code=2, error="任务管理器未配置"。

注意事项

  • 任务状态包括:pending(等待中)、running(运行中)、completed(已完成)、failed(失败)、cancelled(已取消)。
  • 只有 completed 状态才会返回执行结果。
  • 建议轮询获取任务结果,失败或取消状态会返回错误信息。