# API 文档 - SOQL 查询功能 (004-08) ## 元数据 - **需求编号**: 004-08 - **需求名称**: SOQL 查询功能 - **版本号**: v1.0.0 - **创建时间**: 2026-02-06 - **创建人**: AI Assistant - **模块**: datai-salesforce-tooling --- ## API 概述 SOQL 查询功能 API 提供了一组 RESTful 接口,用于执行 Salesforce Tooling API 的 SOQL 查询操作。支持执行任意 SOQL 查询、获取更多查询结果(queryMore)、查询所有结果(自动处理分页)、使用 SoqlBuilder 构建和执行查询,以及查询操作日志管理。 ### 核心功能 - 执行 SOQL 查询,返回查询结果和 queryLocator - 使用 queryLocator 获取更多查询结果 - 自动分页查询所有结果 - 使用 SoqlBuilder 构建和执行查询 - 查询操作日志管理 ### 技术架构 - **Controller**: ToolingSoqlQueryController - **Service**: IToolingSoqlQueryService / ToolingSoqlQueryServiceImpl - **Connection**: ToolingConnectionFactory (复用 004-01) - **Builder**: SoqlBuilder (复用现有工具类) --- ## 接口列表 ### 接口 1:执行 SOQL 查询 **功能描述**: 执行任意 SOQL 查询语句,返回查询结果和 queryLocator。支持所有 Tooling API 对象的查询。 **请求方式**: POST **请求路径**: `/salesforce/tooling/soql/query` **权限要求**: `tooling:soql:query` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | queryString | String | 是 | SOQL 查询语句,例如 "SELECT Id, Name FROM ApexClass LIMIT 100" | | source | String | 否 | 数据源标识,默认 "source" | **请求示例**: ```json { "queryString": "SELECT Id, Name, Body FROM ApexClass LIMIT 100", "source": "source" } ``` **响应参数**: | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码(200 成功,其他失败) | | msg | String | 提示信息 | | data | Object | 查询结果数据 | | data.success | Boolean | 查询是否成功 | | data.errorCode | String | 错误码(失败时返回) | | data.errorMessage | String | 错误信息(失败时返回) | | data.queryLocator | String | 查询定位器,用于获取更多结果 | | data.records | Array | 查询结果记录列表 | | data.totalSize | Integer | 总记录数 | | data.done | Boolean | 是否已获取所有结果 | **成功响应示例**: ```json { "code": 200, "msg": "查询成功", "data": { "success": true, "queryLocator": "01gXXXXXXXXXXXXXXX", "records": [ { "Id": "01pXXXXXXXXXXXXXXX", "Name": "MyApexClass", "Body": "public class MyApexClass { ... }" } ], "totalSize": 1, "done": false } } ``` **失败响应示例**: ```json { "code": 500, "msg": "查询失败", "data": { "success": false, "errorCode": "TOOLING_SOQL_002", "errorMessage": "查询失败:无效的查询语句" } } ``` --- ### 接口 2:获取更多查询结果 **功能描述**: 使用 queryLocator 获取更多查询结果(queryMore)。当一次查询无法返回所有结果时,使用此接口获取后续结果。 **请求方式**: POST **请求路径**: `/salesforce/tooling/soql/queryMore` **权限要求**: `tooling:soql:query` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | queryLocator | String | 是 | 查询定位器,从上一次查询结果中获取 | | source | String | 否 | 数据源标识,默认 "source" | **请求示例**: ```json { "queryLocator": "01gXXXXXXXXXXXXXXX", "source": "source" } ``` **响应参数**: | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码(200 成功,其他失败) | | msg | String | 提示信息 | | data | Object | 查询结果数据 | | data.success | Boolean | 查询是否成功 | | data.errorCode | String | 错误码(失败时返回) | | data.errorMessage | String | 错误信息(失败时返回) | | data.queryLocator | String | 查询定位器,用于获取更多结果 | | data.records | Array | 查询结果记录列表 | | data.totalSize | Integer | 总记录数 | | data.done | Boolean | 是否已获取所有结果 | **成功响应示例**: ```json { "code": 200, "msg": "查询成功", "data": { "success": true, "queryLocator": null, "records": [ { "Id": "01pXXXXXXXXXXXXXXX", "Name": "AnotherApexClass" } ], "totalSize": 1, "done": true } } ``` **失败响应示例**: ```json { "code": 500, "msg": "查询定位器无效", "data": { "success": false, "errorCode": "TOOLING_SOQL_005", "errorMessage": "查询定位器无效或已过期" } } ``` --- ### 接口 3:查询所有结果 **功能描述**: 自动分页查询所有结果,合并返回完整数据列表。适用于需要获取所有记录的场景,自动处理分页逻辑。 **注意**: Salesforce 限制最多返回 50000 条记录,超过限制将返回错误。 **请求方式**: POST **请求路径**: `/salesforce/tooling/soql/queryAll` **权限要求**: `tooling:soql:query` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | queryString | String | 是 | SOQL 查询语句 | | source | String | 否 | 数据源标识,默认 "source" | **请求示例**: ```json { "queryString": "SELECT Id, Name FROM ApexClass", "source": "source" } ``` **响应参数**: | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码(200 成功,其他失败) | | msg | String | 提示信息 | | data | Object | 查询结果数据 | | data.success | Boolean | 查询是否成功 | | data.errorCode | String | 错误码(失败时返回) | | data.errorMessage | String | 错误信息(失败时返回) | | data.records | Array | 所有查询结果记录列表 | | data.totalSize | Integer | 总记录数 | **成功响应示例**: ```json { "code": 200, "msg": "查询成功", "data": { "success": true, "records": [ { "Id": "01pXXXXXXXXXXXXXXX", "Name": "Class1" }, { "Id": "01pYYYYYYYYYYYYYYY", "Name": "Class2" } ], "totalSize": 2 } } ``` **失败响应示例** (超过 50000 条记录限制): ```json { "code": 500, "msg": "查询结果超出限制", "data": { "success": false, "errorCode": "TOOLING_SOQL_006", "errorMessage": "查询结果超出 50000 条记录限制,请使用分页查询" } } ``` --- ### 接口 4:使用 SoqlBuilder 执行查询 **功能描述**: 使用 SoqlBuilder 构建和执行查询。适用于需要动态构建查询条件的场景,提供更灵活的查询方式。 **请求方式**: POST **请求路径**: `/salesforce/tooling/soql/queryWithBuilder` **权限要求**: `tooling:soql:query` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | select | String | 是 | SELECT 子句,例如 "Id, Name, Body" | | from | String | 是 | FROM 子句,例如 "ApexClass" | | where | String | 否 | WHERE 子句,例如 "Name LIKE 'My%'" | | orderBy | String | 否 | ORDER BY 子句,例如 "Name ASC" | | limit | Integer | 否 | LIMIT 子句,例如 100 | | source | String | 否 | 数据源标识,默认 "source" | **请求示例**: ```json { "select": "Id, Name, Body", "from": "ApexClass", "where": "Name LIKE 'My%'", "orderBy": "Name ASC", "limit": 100, "source": "source" } ``` **响应参数**: | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码(200 成功,其他失败) | | msg | String | 提示信息 | | data | Object | 查询结果数据 | | data.success | Boolean | 查询是否成功 | | data.errorCode | String | 错误码(失败时返回) | | data.errorMessage | String | 错误信息(失败时返回) | | data.queryLocator | String | 查询定位器 | | data.records | Array | 查询结果记录列表 | | data.totalSize | Integer | 总记录数 | | data.done | Boolean | 是否已获取所有结果 | **成功响应示例**: ```json { "code": 200, "msg": "查询成功", "data": { "success": true, "queryLocator": null, "records": [ { "Id": "01pXXXXXXXXXXXXXXX", "Name": "MyApexClass", "Body": "public class MyApexClass { ... }" } ], "totalSize": 1, "done": true } } ``` --- ### 接口 5:获取查询日志列表 **功能描述**: 获取 SOQL 查询操作日志列表,支持分页查询。用于审计和监控查询操作。 **请求方式**: GET **请求路径**: `/salesforce/tooling/soql/logs` **权限要求**: `tooling:soql:log:query` **请求参数** (Query 参数): | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | pageNum | Integer | 否 | 页码,默认 1 | | pageSize | Integer | 否 | 每页大小,默认 10 | | queryType | String | 否 | 查询类型筛选,例如 "QUERY", "QUERY_MORE", "QUERY_ALL" | | success | Boolean | 否 | 是否成功筛选 | | startTime | String | 否 | 开始时间,格式:yyyy-MM-dd HH:mm:ss | | endTime | String | 否 | 结束时间,格式:yyyy-MM-dd HH:mm:ss | **请求示例**: ``` GET /salesforce/tooling/soql/logs?pageNum=1&pageSize=10&queryType=QUERY&success=true ``` **响应参数**: | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码(200 成功,其他失败) | | msg | String | 提示信息 | | data | Object | 分页数据 | | data.total | Long | 总记录数 | | data.rows | Array | 日志记录列表 | | data.rows[].id | Long | 日志 ID | | data.rows[].queryString | String | 查询字符串 | | data.rows[].queryType | String | 查询类型 | | data.rows[].executionTimeMs | Long | 执行时间(毫秒) | | data.rows[].resultCount | Integer | 结果数量 | | data.rows[].success | Boolean | 是否成功 | | data.rows[].errorMessage | String | 错误信息 | | data.rows[].createTime | String | 创建时间 | **成功响应示例**: ```json { "code": 200, "msg": "查询成功", "data": { "total": 100, "rows": [ { "id": 1, "queryString": "SELECT Id, Name FROM ApexClass LIMIT 100", "queryType": "QUERY", "executionTimeMs": 150, "resultCount": 100, "success": true, "errorMessage": null, "createTime": "2026-02-06 10:30:00" } ] } } ``` --- ## 错误码 | 错误码 | 错误信息 | 使用场景 | HTTP 状态码 | |-------|---------|---------|------------| | TOOLING_SOQL_001 | Session 无效或已过期 | 用户未登录或 Session 过期 | 401 | | TOOLING_SOQL_002 | 查询失败 | SOQL 查询执行失败(语法错误、对象不存在等) | 500 | | TOOLING_SOQL_003 | 权限不足 | 用户没有执行查询的权限 | 403 | | TOOLING_SOQL_004 | 用户未登录 | 用户未登录 | 401 | | TOOLING_SOQL_005 | 查询定位器无效 | queryLocator 无效或已过期 | 400 | | TOOLING_SOQL_006 | 查询结果超出限制 | 查询结果超过 50000 条记录限制 | 400 | --- ## SOQL 查询限制 ### Salesforce SOQL 限制 - **最大返回记录数**: 50000 条 - **OFFSET 上限**: 2000,且必须与 LIMIT 一起使用 - **不支持 SELECT ***: 必须明确指定字段或使用 FIELDS() - **不支持 BETWEEN**: 请使用 >= 和 <= 组合代替 - **不支持 JOIN**: 使用关系查询(Relationship Queries) - **不支持 UNION**: 无法合并两个不相关的结果集 ### 支持的运算符 `=`, `!=`, `>`, `>=`, `<`, `<=`, `LIKE`, `IN`, `NOT IN`, `= NULL`, `!= NULL` ### 支持的子句 `WHERE`, `GROUP BY`, `HAVING`, `ORDER BY`, `LIMIT`, `OFFSET` --- ## 使用示例 ### 示例 1:基本查询 ```bash curl -X POST "http://localhost:8080/salesforce/tooling/soql/query" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer {token}" \ -d '{ "queryString": "SELECT Id, Name FROM ApexClass LIMIT 10" }' ``` ### 示例 2:带条件的查询 ```bash curl -X POST "http://localhost:8080/salesforce/tooling/soql/query" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer {token}" \ -d '{ "queryString": "SELECT Id, Name, Body FROM ApexClass WHERE Name LIKE \"My%\" ORDER BY Name ASC LIMIT 50" }' ``` ### 示例 3:使用 SoqlBuilder ```bash curl -X POST "http://localhost:8080/salesforce/tooling/soql/queryWithBuilder" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer {token}" \ -d '{ "select": "Id, Name, Body", "from": "ApexClass", "where": "Name LIKE \"My%\"", "orderBy": "Name ASC", "limit": 50 }' ``` ### 示例 4:分页查询所有结果 ```bash curl -X POST "http://localhost:8080/salesforce/tooling/soql/queryAll" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer {token}" \ -d '{ "queryString": "SELECT Id, Name FROM ApexTrigger" }' ``` --- ## 相关文档 - [需求文档](../requirements/sub/2026-01-28-004-08-SOQL查询功能.md) - [设计文档](../design/2026-02-03-004-08-SOQL查询功能-设计.md) - [决策记录](../decisions/2026-02-03-004-08-ADR-SOQL查询功能技术选型.md) - [变更日志](../changelog/2026-02-06-004-08-changelog.md) - [复盘文档](../retros/2026-02-06-004-08-retro.md) --- ## 版本历史 ### v1.0.0 (2026-02-06) - 初始版本 - 实现 5 个 REST API 接口 - 支持执行 SOQL 查询、queryMore、queryAll、SoqlBuilder 查询、日志管理