8.5 KiB
SQL 数据源处理器技术文档
概述
SQLDataSourceProcessor 是一个基于 DataSourceProcessor 的子类,用于处理以 .sqlds 格式定义的 SQL 数据源。它允许通过配置文件描述 SQL 查询、参数和数据库连接,并动态执行查询获取数据。
该模块主要用于从数据库中提取结构化数据,支持普通查询、分页查询以及自动推导返回字段结构(datadesc),并能将推导结果持久化回源文件。
依赖模块
import codecs
from .dsProcessor import DataSourceProcessor
from appPublic.jsonConfig import getConfig
from sqlor.dbpools import DBPools
import json
codecs: 用于安全地读写带编码的文件(如 UTF-8)。DataSourceProcessor: 抽象基类,定义了数据源处理器的标准接口。getConfig(fromappPublic.jsonConfig): 获取全局配置对象。DBPools(fromsqlor.dbpools): 提供异步数据库连接池及 SQL 执行装饰器。json: 用于序列化/反序列化 JSON 数据。
配置文件格式(.sqlds)
.sqlds 文件是标准的 JSON 格式,描述了一个 SQL 查询的数据源信息:
{
"sqldesc": {
"sql_string": "select * from dbo.stock_daily_hist where stock_num=${stock_num}$ order by trade_date desc",
"db": "mydb",
"sortfield": "trade_date"
},
"arguments": [
{
"name": "stock_num",
"type": "str",
"iotype": "text",
"default": "600804"
}
],
"datadesc": []
}
字段说明
| 字段 | 类型 | 必需 | 描述 |
|---|---|---|---|
sqldesc.sql_string |
string | 是 | 实际执行的 SQL 查询语句,支持 ${param}$ 形式的参数占位符。 |
sqldesc.db |
string | 是 | 数据库连接名称(在 DBPools 中注册过的别名)。 |
sqldesc.sortfield |
string | 否 | 排序字段,可用于前端排序或分页逻辑参考。 |
arguments |
array | 否 | 定义传入 SQL 的参数列表,每个参数包含:name, type, iotype, default。 |
datadesc |
array | 否 | 描述查询结果字段结构的数组。若为空,则首次访问时自动推导并写回文件。 |
⚠️ 注意:
${param}$是模板语法,运行时会被ns上下文中的对应值替换。
类定义
class SQLDataSourceProcessor(DataSourceProcessor):
继承自 DataSourceProcessor,实现针对 .sqlds 类型数据源的具体行为。
方法说明
isMe(name) -> bool
判断当前处理器是否适用于指定类型的数据源。
参数
name(str):数据源类型名。
返回值
True当且仅当name == 'sqlds'。
示例
if SQLDataSourceProcessor.isMe('sqlds'):
processor = SQLDataSourceProcessor(...)
getArgumentsDesc(dict_data, ns, request) -> list or None
获取数据源所需的输入参数描述。
参数
dict_data(dict):解析后的.sqlds文件内容。ns(dict):命名空间(通常为请求参数)。request(Request):HTTP 请求对象(可选用途扩展)。
返回值
list:参数描述数组(来自arguments字段)。None:若未定义arguments。
示例返回
[
{
"name": "stock_num",
"type": "str",
"iotype": "text",
"default": "600804"
}
]
async getDataDesc(dict_data, ns, request) -> list
异步获取查询结果的字段元信息(即 datadesc)。如果尚未生成,则自动从数据库中推导并保存到原文件。
参数
dict_data(dict):原始数据源配置。ns(dict):参数上下文,用于填充 SQL 占位符。request(Request):请求对象。
行为流程
- 若
datadesc已存在且非空,直接返回。 - 否则:
- 调用
runSQLResultFields获取 SQL 查询的实际返回字段(不含_row_id)。 - 将推导出的字段结构写入
dict_data['datadesc']。 - 序列化整个
dict_data回源文件(路径为self.src_file),保持缩进与中文不转义。
- 调用
使用的装饰器
@pool.runSQLResultFields:执行 SQL 并返回字段元信息(列名、类型等)。
返回值
list:字段描述列表,每项为字段元数据字典(如{ "name": "trade_date", "type": "datetime" })。
示例输出
[
{"name": "stock_num", "type": "string"},
{"name": "trade_date", "type": "date"},
{"name": "close_price", "type": "float"}
]
✅ 自动持久化:一旦推导完成,会更新
.sqlds文件以避免重复分析。
async getData(dict_data, ns, request) -> list
执行完整 SQL 查询并返回所有结果记录。
参数
dict_data(dict):数据源定义。ns(dict):参数上下文。request(Request):请求对象。
行为
- 使用
@pool.runSQL执行sqldesc.sql_string。 - 替换
${}中的参数。 - 返回所有行组成的列表。
使用的装饰器
@pool.runSQL:执行查询并返回异步迭代器,转换为列表。
返回值
list[dict]:每条记录为一个字典。
示例返回
[
{"stock_num": "600804", "trade_date": "2023-09-01", "close_price": 12.5},
{"stock_num": "600804", "trade_date": "2023-08-31", "close_price": 12.3}
]
async getPagingData(dict_data, ns, request) -> dict
执行分页查询,返回带分页信息的结果集。
参数
dict_data(dict)ns(dict):必须包含分页参数,如page,pageSize或等效字段。request(Request)
行为
- 使用
@pool.runSQLPaging执行分页 SQL。 - 自动处理偏移量和限制数量。
- 返回结构化分页响应。
使用的装饰器
@pool.runSQLPaging:支持分页的 SQL 执行器,返回包含data,total,page,pageSize的对象。
返回值(示例)
{
"data": [...],
"total": 100,
"page": 1,
"pageSize": 10
}
内部机制说明
SQL 模板替换
使用 ${param}$ 语法进行变量注入,例如:
select * from table where id = ${user_id}$
运行时由 DBPools 的装饰器根据 ns 字典替换为实际值。
自动字段推导与缓存
首次访问 getDataDesc 时,若 datadesc 为空,系统将:
- 执行 SQL 获取字段结构;
- 过滤掉内部字段
_row_id; - 写入本地
.sqlds文件以供后续使用。
这提高了性能并减少了对数据库元数据的频繁访问。
编码与文件写入
使用 codecs.open(..., encoding=config.website.coding) 确保文件按项目设定编码保存(通常是 UTF-8),并通过 ensure_ascii=False 保留中文字符。
使用场景
适合以下情况:
- 需要灵活配置 SQL 查询作为 API 输出。
- 前端需要知道返回字段结构(用于表格渲染)。
- 支持参数化查询和分页。
- 开发阶段快速原型设计,无需编写后端代码。
示例 .sqlds 文件应用
假设文件名为 stock_history.sqlds,配置如下:
{
"sqldesc": {
"sql_string": "SELECT stock_num, trade_date, open, high, low, close FROM stock_daily WHERE stock_num = ${code}$ ORDER BY trade_date DESC",
"db": "financial_db",
"sortfield": "trade_date"
},
"arguments": [
{
"name": "code",
"type": "str",
"iotype": "text",
"default": "600804"
}
],
"datadesc": []
}
调用 getDataDesc() 后,datadesc 将被自动填充为:
[
{"name": "stock_num", "type": "string"},
{"name": "trade_date", "type": "date"},
{"name": "open", "type": "float"},
{"name": "high", "type": "float"},
{"name": "low", "type": "float"},
{"name": "close", "type": "float"}
]
注意事项
- 安全性:确保
${}参数经过验证,防止 SQL 注入(建议配合白名单或类型校验)。 - 性能:大数据集应优先使用
getPagingData。 - 文件权限:写回
.sqlds文件时需保证进程有写权限。 - 缓存失效:修改 SQL 后建议手动清除
datadesc以触发重新推导。
总结
SQLDataSourceProcessor 提供了一种声明式的方式来定义基于 SQL 的数据接口,结合配置文件与异步数据库访问,实现了高效、可维护的数据服务层组件。特别适用于报表、配置化页面、低代码平台等场景。