跳至正文
浏览文档
API 参考

API 参考

查询构造参数、方法签名、默认值与返回结构。

完成快速开始后,可以在这里查阅方法签名、输入与返回值。AVA 的数据和可视化方法均为异步方法。生命周期订阅见事件,引擎扩展点见自定义引擎。

API 速览

分类API功能
初始化new AVA(config)配置模型与执行引擎。
数据source(config)加载或替换数据源。
schema(options?, setter?)查看或设置数据结构。
profile(options?, setter?)计算或设置统计信息。
semantic(options?, setter?)读取或设置业务定义。
分析与查询analyze(query, config?)回答分析问题。
分步控制 translate(query)生成查询。
分步控制 query(dsl, options?)执行查询。
suggest(count?)推荐问题。
可视化visualize(analysisResult)推荐并渲染图表。
分步控制 recommend(analysisResult)推荐图表配置。
分步控制 viz(spec)渲染图表配置。
资源清理dispose()释放资源。

分步控制 这些 API 提供可独立调用的单步操作。

初始化

构造函数

new AVA(config: AVAConfig)

参数类型必填默认值与行为
configAVAConfig是配置对象。
config.llmLLMConfig是见下方模型字段。
config.engineEngineConfig否{ type: 'duckdb' },见下方引擎字段。

构造函数不加载数据,引擎会在 source() 时创建。

模型选项

以下字段位于 config.llm 中。

字段类型必填含义与默认值
provider'openai' | 'gateway'否默认使用兼容 OpenAI 的 Chat Completions;Gateway 可读取 AI_GATEWAY_API_KEY。
modelstring | LanguageModel是模型名称,或预先配置好的 AI SDK 模型实例。
apiKeystring否模型服务商的 API 密钥。
baseURLstring否可选的 API 基础地址。
maxRetriesnumber否模型 API 可重试错误的最大重试次数,默认 3。

以字符串传入模型名称时,默认使用兼容 OpenAI 的 Chat Completions ;传入模型对象时则直接使用该对象。用量回调并不完整覆盖每次模型请求,不能用来汇总全部用量。

引擎选项

提供 engine 时,config.engine.type 必填。支持 duckdb、python、javascript、supabase、clickhouse,以及通过 registerEngine() 注册的名称。省略 engine 时选择 DuckDB。JavaScript、Supabase、ClickHouse 没有其他引擎字段,连接凭证放在 source() 中。

DuckDB

将 engine.type 设为 duckdb。engine 接受的全部额外字段如下。

字段类型必填含义与默认值
memoryLimitstring否内存限制,例如 '512MB',默认 '512MB'。
threadsnumber否工作线程数,默认 1。
maxTempDirectorySizestring否临时溢写目录的大小上限,例如 '1GB';不设置则不限制。
queryTimeoutMsnumber否单次查询超时,单位毫秒,默认 30000。
allowCommunityExtensionsboolean否数据源加载明确需要社区扩展时,允许启用 DuckDB 社区扩展。
Python

将 engine.type 设为 python。engine 接受的全部额外字段如下。

字段类型必填含义与默认值
execute(code: string) => Promise<ExecutionResult>否用自定义环境替换本地 python3 执行。本地执行没有沙箱;请运行完整 Python 脚本,将其 JSON 输出作为 ExecutionResult 返回。脚本包含数据加载和结果限制,远程执行时限需另行配置。
queryTimeoutMsnumber否客户端等待上限及本地进程执行时限,默认 30000 毫秒。
已注册的引擎

将 engine.type 设为传给 registerEngine() 的名称。其余字段以 options 传给引擎构造函数。这是 SDK 能力,CLI 仅支持内置引擎名。

字段类型必填含义与默认值
typestring是已注册的引擎名称,例如 'sales'。
其他字段Engine-specific取决于引擎由注册的引擎负责验证。

数据

source

typescript
source(config: DataSourceConfig): Promise<void>

通过引擎加载数据源,没有返回值,也不会发现 schema。

typescript
await ava.source({ type: 'json', options: { data: [{ revenue: 120 }] } });
参数类型必填含义
configDataSourceConfig是待加载的数据源。
config.typeSourceType是数据源类型,例如 json 或 csv-file。
config.options数据源对应的对象是该类型的读取或连接设置。

加载数据源会释放旧引擎,清除保存的 schema、profile 和业务语义。加载失败后没有活动数据源。替换数据源前,请等待正在进行的操作完成。

schema

typescript
schema(options?: SchemaOptions, setter?: (options: SchemaOptions) => Schema): Promise<Schema>

返回已加载数据源的结构。不提供 setter 时,AVA 优先返回已保存的 schema;没有缓存则通过引擎发现并保存。

typescript
const schema = await ava.schema();

如需提供已有 schema,传入返回该对象的函数:

typescript
await ava.schema(undefined, () => savedSchema);
参数类型必填含义与默认值
optionsSchemaOptions否{},目前没有可配置字段。
setter(options: SchemaOptions) => Schema否返回要保存的 schema,替代引擎发现过程。

Setter 接收选项对象(默认 {}),同步返回 Schema。结果会替换已保存的 schema,并清空 profile。AVA 会验证并复制结果;结果无效或 setter 抛错时,调用失败,原有元数据保持不变。

需要先加载数据源。分析和统计会按需获取 schema,直接 query() 不要求提前发现结构。使用流程见了解数据结构。

Schema 结构

字段含义
models可用于查询的表或视图,必填。
models[].name模型名称。
models[].tableReference物理数据源标识,包含 table,以及可选的 catalog、schema。
models[].columns列定义,每列包含 name、type 和可选的 notNull。
models[].primaryKey单列名称,或代表复合主键的有序非空数组。
models[].uniqueKeys候选唯一键数组,每项为单列名称或复合键数组。
relationships可发现时返回的外键关系。
views可发现时返回的命名视图查询,包含 name 和 statement。

具体内容取决于数据源和引擎。查询结果中的 schema 描述输出列,并不是数据源的 Schema。

profile

typescript
profile(options?: ProfileOptions, setter?: (options: ProfileOptions) => Profile): Promise<Profile>

通过引擎计算并保存已加载数据源的统计信息。不传 setter 时,每次调用都会重新计算,需要引擎支持统计。

typescript
const profile = await ava.profile({ metrics: ['row_count', 'mean'] });

如需提供已有 profile,传入返回该对象的函数:

typescript
await ava.profile(undefined, () => savedProfile);
参数类型必填含义与默认值
optionsProfileOptions否{},使用下方默认指标。
options.metricsMetricConfig[]否交给引擎计算的指标列表;提供后替换默认列表。
setter(options: ProfileOptions) => Profile否返回要保存的 profile,替代引擎计算。

Setter 接收选项对象(默认 {}),同步返回 Profile,不要求引擎支持统计。AVA 会验证并复制结果;无效结果或 setter 抛错会让调用失败,并保留原有元数据。选项直接传给 setter,AVA 不会代替它计算或过滤指标。

需要先加载数据源。两条路径都会替换已保存的 profile,供分析、翻译和推荐问题复用。设置 profile 不会替换 schema。

Profile 格式

Profile 通过名称,将统计信息附加到已有的 schema 模型和列上:

字段含义
models[].name要补充统计信息的模型。
models[].metrics表级统计,例如 row_count。
models[].columns[].name该模型中要补充统计信息的列。
models[].columns[].metrics列级统计,例如 mean。
models[].columns[].properties.logicalType规范化分类:numeric、string、boolean、date 或 unknown。

指标缺失表示未计算,不代表零。设置 schema 会清空 profile,因此手动提供两者时应先设置 schema。加载新数据源或调用 dispose() 会清空 schema、profile、semantic;更新 schema 或 profile 会保留 semantic。

统计指标

默认指标为 row_count、null_count、distinct_count、top_values、min、max、mean。其他内置指标包括 duplicate_count、min_length、max_length、sum、stddev、median。

每项可以是指标名称,也可以是包含 id 和该指标专用选项的对象:

typescript
await ava.profile({
  metrics: ['row_count', { id: 'top_values', limit: 5 }],
});
字段类型默认值与行为
idstring对象形式必填,指标名称。
limitnumber仅用于 top_values,默认 3,必须是非负安全整数。
maxDistinctRationumber仅用于 top_values,默认 0.5,必须是 0—1 之间的有限数值。

其他内置指标没有额外选项。引擎计算 profile 时会拒绝未知指标与未知选项名。指标是否可用取决于引擎及字段类型。

metrics: [] 会生成空的指标对象。新 profile 替换旧统计信息,不会累加之前的指标。

semantic

typescript
semantic(options?: SemanticOptions, setter?: (options: SemanticOptions) => Semantic): Promise<Semantic>

读取或替换已加载数据源的语义定义。不传 setter 时返回已保存的定义,初始为 {}。这个调用不会发现 schema、计算 profile 或请求大模型。

typescript
await ava.semantic(undefined, () => ({
  description: 'Sales reporting; amounts are in USD.',
  cubes: [{
    name: 'revenue',
    baseObject: 'data',
    measures: [{ name: 'total', expression: 'SUM(revenue)', type: 'DOUBLE' }],
  }],
}));
 
const definitions = await ava.semantic();
await ava.semantic(undefined, () => ({})); // Clear the saved definitions.
参数类型必填含义与默认值
optionsSemanticOptions否{},目前没有可配置字段。
setter(options: SemanticOptions) => Semantic否返回要保存的业务语义,替换之前的完整定义。

Setter 接收选项对象,同步返回 Semantic。AVA 验证并复制结果;结果无效或 setter 抛错时保留之前的定义。需要先加载数据源。替换数据源或释放实例会清空语义;更新 schema、profile 会保留它。

Semantic 描述业务定义,不包含模型或列的 metrics;统计信息应通过 profile() 提供。引擎接收的组合上下文仍是 DataModel。

编写流程和销售示例见补充业务语义,详细字段见语义字段。

在 analyze()、translate()、suggest() 中,AVA 按名称将语义中的模型和列与 schema、profile 合并。未指定的模型、列及统计信息仍可使用;模型和列的属性按键合并,同名键以语义值为准。显式提供的关系或视图列表会整体替换发现的列表,包括空列表。每个语义模型都必须且只能声明一种来源:tableReference、refSql 或 baseObject。

这些定义为查询生成提供上下文。声明 cube、view 或计算列不会创建数据库对象,生成的查询仍须能在配置的引擎中执行。

分析与查询

analyze

analyze(query: string, config?: AnalysisConfig): Promise<AnalysisResponse>

参数类型必填默认值与行为
querystring是自然语言问题。
configAnalysisConfig否{}.
config.includeSummaryboolean否默认 true,设为 false 时返回空的 text。
config.maxRowsnumber否默认 200,见执行限制。
config.maxResultBytesnumber否默认 1048576,见执行限制。
config.strategyAnalysisStrategyConfig否默认直接分析。
config.strategy.type'direct' / 'loop'提供 strategy 时选择分析策略。
config.strategy.maxRetriesnumber否,仅 direct显式 type: 'direct' 时默认 2,省略策略时当前为 10;表示首次执行后的修正次数。
config.strategy.maxStepsnumber否,仅 loop默认 12,常规推理步数上限。

这些重试控制与 llm.maxRetries 不同,详见策略行为及使用要求。

需要先加载数据源。返回 ExecutionResult,并附加:

结果字段类型Presence含义
querystringAlways原始问题。
textstringAlways文字总结;关闭总结时为空。
markdownstring可选Markdown 内容。
sqlstring可选实际执行的查询或 DSL,非 SQL 引擎也沿用此字段名。

translate

translate(query: string): Promise<string>

参数类型必填含义
querystring是自然语言问题。

需要先加载数据源。只返回生成的 DSL,不执行;可用 query() 执行返回的字符串。

query

query(dsl: string, options?: ExecutionOptions): Promise<ExecutionResult>

参数类型必填默认值与行为
dslstring是使用所选引擎语言的可执行语句。
optionsExecutionOptions否使用下方默认执行限制。
options.maxRowsnumber否200.
options.maxResultBytesnumber否默认 1048576 字节。

需要先加载数据源,不会调用模型生成查询或总结结果。

ExecutionOptions

字段类型默认值可用值与行为
maxRowsnumber200向下取整后限制在 1—1000000 之间;取整后超出安全整数范围时使用默认值。
maxResultBytesnumber1048576 (1 MiB)有限值向下取整后最小为 1,非有限值使用默认值。

这些选项限制返回数据,与引擎执行超时相互独立。

ExecutionResult

字段类型Presence含义
schemaQueryColumn[]Always返回列的元数据。
schema[].namestringAlways列名。
schema[].typestring可选引擎提供的原生类型名,可选。
dataT[]Always返回的数据行。
truncatedtrue截断时结果已被限制截断。
truncatedBy'maxRows' / 'maxResultBytes'截断时触发截断的限制项。
rowCountnumber已知时执行读到结果末尾时返回的行数。

suggest

suggest(count?: number): Promise<SuggestResult[]>

参数类型必填默认值与行为
countnumber否默认 3,期望推荐的问题数量。

需要先加载数据源。按评分降序返回推荐问题,每项包含 query: string、score: number(0—1)、reason: string。

可视化

visualize 与 recommend

visualize(analysisResult): Promise<VisualizeResponse | null>

recommend(analysisResult): Promise<ChartSpec | null>

两种方法接受相同的输入:

参数类型必填含义
analysisResultPick<AnalysisResponse, 'query' | 'data'>是分析结果,或包含下面两个字段的对象。
analysisResult.querystring是问题或可视化意图。
analysisResult.dataRecord<string, unknown>[]是待可视化的数据行。

两种方法都不要求加载数据源,均调用模型;数据为空或没有推荐出图表时返回 null,生成错误则直接抛出。recommend() 返回 ChartSpec;visualize() 还返回 html: string,包含独立的图表页面。

viz

viz(spec: ChartSpec): Promise<string>

参数类型必填含义
specChartSpec是图表描述对象。
spec.chartTypeChartType是下方图表类型之一,属于共享描述对象;当前渲染器直接使用 config。
spec.configChartConfig是嵌入 HTML 的 GPT-Vis JSON 配置,config.type 与 chartType 一致。

ChartType 可选值:line、column、bar、pie、area、scatter、dual-axes、histogram、boxplot、radar、funnel、waterfall、liquid、word-cloud、violin、venn、treemap、sankey、table、summary。

返回独立 HTML 字符串,无需加载数据源,也不会调用模型。参见图表配置。

资源清理

dispose

dispose(): Promise<void> 没有参数,释放当前引擎并清空 schema、profile 与业务语义。应在 finally 中等待它执行完成。

语义模型参考

语义字段

六个顶层字段均可选,按应用需要提供即可。名称和必填表达式必须是非空字符串。properties 包含 JSON 值,其中的数值必须有限;description、unit、synonyms、owner 等键是应用约定,不代表 SDK 内置行为。

字段Shape用途
descriptionstring共享业务背景、术语、记录范围与时间口径。
propertiesRecord<string, JsonValue>共享注释。
models下方的模型定义物理及逻辑数据集、列含义与来源映射。
relationships下方的关系定义命名模型之间的连接关系。
views下方的视图定义可复用的命名 SQL 查询。
cubes下方的 Cube 定义指标、分组表达式与下钻路径。

语义模型

字段必填含义
name是逻辑模型名;按名称匹配已有 schema 模型,或添加新模型。
tableReference三种来源选择器之一{ table, schema?, catalog? },独立于逻辑名称的物理标识;额外的来源属性必须是 JSON 值。
refSql三种来源选择器之一列映射与计算之前,用于定义源数据行的 SQL。
baseObject三种来源选择器之一提供数据行的另一个模型或视图名称。
columns否列定义见下方;未列出的已有列仍保留。
primaryKey否单列名称,或代表复合主键的有序非空数组。
uniqueKeys否唯一键数组,每项是单列名称或非空复合键数组。
dialect否refSql 的 SQL 方言;省略时使用执行上下文。
properties否模型注释,尤其是行粒度和业务用途。

主键、唯一键是声明,不是统计结论,需要对照数据源验证。primaryKey: ['tenant_id', 'order_id'] 表示一个复合键;uniqueKeys: ['email', ['tenant_id', 'external_id']] 则声明两个候选唯一键。

语义列

字段必填含义
name是所属模型内的名称,用于匹配已有列。
type是声明的类型;关系导航列则填写目标模型名称。
properties否列的上下文,例如描述、单位、枚举含义或空值约定。
expression否针对来源的 SQL 映射或计算;null 或省略表示不提供表达式。
isCalculated否标记派生列的布尔值,本身不会执行计算。
isPrimaryKey否标记是否属于已声明主键的布尔值。
notNull否声明的非空约束,省略表示未指定。
relationship否用于导航的关系标识,不是外键列名。

语义关系与视图

字段必填含义
relationships[].name是关系标识,也用于列导航。
relationships[].models是恰好两个模型名,顺序为第一模型、第二模型。
relationships[].joinType是ONE_TO_ONE、ONE_TO_MANY、MANY_TO_ONE 或 MANY_TO_MANY。
relationships[].condition是使用限定列名的 SQL 连接条件。
relationships[].properties否关系的业务背景。
views[].name是查询的逻辑名称。
views[].statement是定义结果的 SQL;保存不会执行它。
views[].dialect否SQL 方言,省略时使用执行上下文。
views[].properties否用途与业务口径。

关系和视图允许额外的 JSON 属性,由应用及其使用方约定含义。

语义 Cube 与表达式

字段必填含义
name是Cube 标识。
baseObject是提供聚合数据行的模型或视图。
measures是非空的聚合定义数组。
dimensions否分组定义。
timeDimensions否日期、时间分组定义,粒度在查询时选择。
hierarchies否名称到非空维度名数组的映射,从粗粒度到细粒度排列。
properties否Cube 注释。

measures、dimensions 和 timeDimensions 的每一项都使用以下字段:

字段必填含义
name是Cube 内的表达式标识。
expression是指标使用 SQL 聚合表达式,维度使用分组表达式。
type是声明的结果类型。
description否表达式的业务含义。
properties否单位、同义词等注释。

例如,按日历下钻时,先定义 year、month、order_date 的维度表达式,再声明 hierarchies: { calendar: ['year', 'month', 'order_date'] }。层级只描述路径,不会自动生成这些字段。

模型、列、Cube 和表达式对象会拒绝未知字段;需要应用注释时,放在支持的 properties 中。

语义模型来源

编写映射前,先调用 schema() 检查模型名称、来源引用与列类型。名称必须在所属模型内准确匹配。销售示例的内存 JSON 暴露为 data;其他数据源可能使用不同名称,并带有 catalog 或 schema 限定信息。

models 中的每一项都需要 name,并且 只能选择一种 来源,即使只是想给已有模型补充描述:

来源选择器适用情况示例
tableReference模型映射到物理表或数据库视图,保留发现的来源限定信息。{ tableReference: { schema: 'public', table: 'orders' } }
refSql用 SQL 定义逻辑模型的源数据行。{ refSql: "SELECT * FROM orders WHERE status = 'paid'" }
baseObject由另一个模型或已声明视图提供源数据行。{ baseObject: 'paid_orders' }

使用已有 schema 模型的 name 可以补充该模型。换用其他名称会新增逻辑模型,不会重命名底层表。列即使只补充描述,也必须提供 name 和 type;物理列沿用发现的类型,计算列声明结果类型。

baseObject、refSql 和列的 expression 为查询生成器描述映射。逻辑名称不代表能直接交给 query() 执行。例如,查询计算列 net_amount 时,需要展开其表达式,或通过子查询、CTE 定义。

语义关系与视图示例

跨模型分析时添加关系;可复用 SQL 有助于表达业务逻辑时添加视图。以下片段假定已有数据源提供 orders、customers,与前面的单表销售示例相互独立。

关系示例

typescript
import type { Semantic } from '@antv/ava';
 
const semantic = {
  relationships: [{
    name: 'order_customer',
    models: ['orders', 'customers'],
    joinType: 'MANY_TO_ONE',
    condition: 'orders.customer_id = customers.id',
    properties: { description: 'Each order belongs to one customer.' },
  }],
} satisfies Semantic;

models 是有序模型对。MANY_TO_ONE 表示第一模型的多行可以匹配第二模型的一行。joinType 描述基数,不决定使用 LEFT JOIN 还是 INNER JOIN。复合键的连接条件需要包含所有键字段。

如果暴露关系导航列,应将 relationship 设为关系的 名称 ,将 type 设为目标模型名,例如 { name: 'customer', type: 'customers', relationship: 'order_customer' }。物理外键列仍是 customer_id。

跨表聚合前先检查行粒度。一笔订单连接多条明细时,订单金额可能被重复计算。基数声明只提供上下文,AVA 不会验证唯一性,也不会自动避免重复计数。

视图与派生模型示例

typescript
import type { Semantic } from '@antv/ava';
 
const semantic = {
  views: [{
    name: 'paid_orders',
    statement: "SELECT * FROM orders WHERE status = 'paid'",
    dialect: 'duckdb',
    properties: { description: 'Paid orders only; this excludes fully refunded orders.' },
  }],
  models: [{
    name: 'paid_sales',
    baseObject: 'paid_orders',
    properties: { description: 'One row per paid order.' },
  }],
} satisfies Semantic;

这里的逻辑模型引用一个命名查询,生成器可以将其展开为 CTE 或子查询。只有执行引擎中已存在 paid_orders 时,await ava.query('SELECT * FROM paid_orders') 才能执行;保存定义不会创建它。不需要单独命名视图时,也可以直接用模型的 refSql 描述来源查询。

保存并合并语义定义

在应用中保留一份完整定义,与对应数据源一起管理版本,并在 source() 之后传给 AVA。每次 setter 都替换已保存的整个语义对象,不会追加或局部修改旧定义。

typescript
await ava.semantic(undefined, () => completeDefinitions);
const saved = await ava.semantic();
await ava.semantic(undefined, () => ({})); // Clear all saved semantics.

定义可保存在代码或应用自己的 JSON 文件中。例如,Node.js 加载数据源后:

javascript
const { readFile } = require('node:fs/promises');
const definitions = JSON.parse(await readFile('./sales-semantic.json', 'utf8'));
await ava.semantic(undefined, () => definitions);

JSON 文件只包含定义对象,不带 JavaScript 变量声明或 setter。AVA 接受对象而非文件路径;如果保存为 YAML,请先在应用中解析,再调用 setter。读取和解析文件可以异步完成,setter 本身同步返回对象。

操作需要数据模型时,AVA 按以下顺序组合输入:

组合方式行为
先 schema,再 profile按名称将统计信息附加到已有模型和列。
语义模型同名模型补充已有内容,新名称添加逻辑模型;显式来源选择器优先。
语义列同名列补充已有列,新名称添加新列。未列出的模型、列及 profile 指标仍可使用;空列数组不会删除已发现的列。
模型与列的 properties按键合并,同名键以语义值为准;嵌套 JSON 值整体替换,不递归合并。
显式提供的其他模型与列字段语义值替换对应字段,包括类型与键声明。
顶层字段显式值替换对应内容。关系与视图数组整体替换;[] 会清空组合上下文中的相应列表。

省略某部分会保留对应的 schema 上下文。需要在已发现的外键之外新增关系时,应在传入列表中包含仍要保留的关系。读取 schema()、profile()、semantic() 返回的仍是各自输入,不是组合模型;目前没有公开方法读取合并后的 DataModel。

更新 schema 会清空 profile、保留语义;计算 profile 会替换统计信息、保留语义;加载新数据源或调用 dispose() 会清空三者。加载新数据源后应重新应用保存的定义,并在结构变化时复核映射。这些调用都需要活动数据源,替换数据源失败后则没有活动数据源。

Setter 验证并复制返回对象。验证失败或 setter 抛错时,之前的语义定义保持不变。

语义验证

结构验证检查字段形状、必填项、来源选择器的互斥性及非空指标列表,但 不能证明 SQL 有效、引用对象存在、键声明成立、单位一致或业务规则正确。重复的语义模型名、同一模型内的重复列名,会在分析、翻译或推荐问题组装组合模型时被拒绝,而非仅由 setter 拒绝。

为自己的数据定义口径时,可以沿用销售示例的验证流程:

  1. 查看 schema(),准确匹配名称与物理类型。远程数据源需保留 catalog 和 schema 限定信息。
  2. 请业务负责人复核行粒度、纳入统计的状态、空值处理、单位与时间口径。
  3. 用答案已知的小数据集逐一运行表达式,按需覆盖被排除记录、空值、退款及连接重复计数等情况。
  4. 针对同样的问题检查 translate() 输出,再将执行结果与已知答案对照。Setter 成功不等于端到端验证成功。
  5. 数据源结构或业务定义变化后,重新执行这些检查。
现象检查方向
Setter 拒绝模型必须且只能提供 tableReference、refSql、baseObject 之一;列需要 name 和 type。
Setter 拒绝 Cube需要 baseObject,以及至少一个包含 name、expression、type 的指标。
Setter 拒绝统计信息模型与列的 metrics 应传给 profile(),不要放进 semantic()。
查询提示逻辑名称不存在检查 SQL 是否将声明的表达式、视图或模型展开为可执行 SQL。
已发现的连接关系消失你提供的关系列表替换了发现的列表,请包含所有仍需要的关系。
数值偏大检查行粒度、连接基数、重复键、记录过滤和退款处理。
规则未生效检查生成的查询。必须遵守的访问规则应在数据层或执行层强制实施。