Launcher 0.1.26 中,QM v2 为嵌套维度 ID/caption 列显式配置 name + alias,模型校验、登记和刷新均成功,但实时 JSON/Markdown 仍公开 TM 原字段名;以 QM 配置的新名称构造 DSL 时,query.validate 返回 FIELD_NOT_FOUND。同一个 QM 改用原字段名即可通过校验并正确执行。
此问题影响通过 QM 为 AI 提供稳定业务字段名;不是把 TM 的维度 alias 当成 QM alias 使用,也不是只测试整个维度 ref 的前缀展开。
8c8e461b73224d8faddbc7573e550cb549901f05;内部 Java project version: 9.3.0-SNAPSHOT051639bf738633cc63c2e4acfb5a4e91f0a3782c45bdcf767876abd465c7ff40http://127.0.0.1:18068,Namespace chinook,named datasource chinook-sqlite,none-dev-test-only,Console/FAP 关闭foggy-runtime-api/v1, schema 2026-06-06bdf635be69850bd3be09c9a2dbeef7ddfb80036bd3ef3381383cd03b61e4a61a./start-foggy-runtime.ps1 -Port 18068 -WorkDir ./work。chinook-sqlite,绑定 chinook,连接测试成功。不是内置 demo 数据源。models/model/、models/query/,保存后面的 DSL 到 alias-payload.json。--base-url http://127.0.0.1:18068 --namespace chinook):foggy-runtime models validate --models-dir ./models
foggy-runtime bundles add --name qm-alias-repro --path ./models
foggy-runtime models refresh
foggy-runtime models describe MinimalArtistAliasQueryModel
foggy-runtime models describe MinimalArtistAliasQueryModel --format markdown
foggy-runtime query validate MinimalArtistAliasQueryModel --payload ./alias-payload.json
最后一条退出码为 2;被校验拒绝的请求没有继续执行。
export const model = {
name: 'MinimalArtistAliasLineModel', caption: '账单明细别名复现', tableName: 'InvoiceLine', idColumn: 'InvoiceLineId',
properties: [{ column: 'InvoiceLineId', name: 'invoiceLineId', caption: '明细 ID', type: 'INTEGER' }],
dimensions: [
{ name: 'invoice', caption: '账单', tableName: 'Invoice', foreignKey: 'InvoiceId', primaryKey: 'InvoiceId', captionColumn: 'InvoiceId',
properties: [{ column: 'InvoiceDate', name: 'invoiceDate', caption: '账单日期', type: 'DATETIME' }] },
{ name: 'track', caption: '曲目', tableName: 'Track', foreignKey: 'TrackId', primaryKey: 'TrackId', captionColumn: 'Name',
dimensions: [
{ name: 'album', caption: '专辑', tableName: 'Album', foreignKey: 'AlbumId', primaryKey: 'AlbumId', captionColumn: 'Title',
dimensions: [
{ name: 'artist', caption: '艺术家', tableName: 'Artist', foreignKey: 'ArtistId', primaryKey: 'ArtistId', captionColumn: 'Name' }
] }
] }
],
measures: [{ column: 'UnitPrice', name: 'lineAmount', caption: '明细金额', type: 'MONEY', aggregation: 'sum',
formulaDef: { builder: (alias) => `${alias}.UnitPrice * ${alias}.Quantity` } }]
};
const line = loadTableModel('MinimalArtistAliasLineModel');
export const queryModel = {
name: 'MinimalArtistAliasQueryModel', caption: '艺术家别名复现', loader: 'v2', model: line,
columnGroups: [{ caption: '复现字段', items: [
{ ref: line.invoiceLineId },
{ ref: line.invoice$invoiceDate },
{ ref: line.track.album.artist$id, name: 'albumArtistId', alias: 'albumArtistId' },
{ ref: line.track.album.artist$caption, name: 'albumArtistName', alias: 'albumArtistName' },
{ ref: line.lineAmount }
] }],
accesses: []
};
{
"columns": [
"albumArtistId",
"albumArtistName",
"count(invoiceLineId) as lineCount",
"sum(lineAmount) as totalAmount"
],
"slice": [
{
"field": "invoice$invoiceDate",
"op": "[)",
"value": [
"2012-01-01",
"2013-01-01"
]
},
{
"field": "albumArtistId",
"op": "=",
"value": 90
}
],
"groupBy": [
"albumArtistId",
"albumArtistName"
],
"orderBy": [
"albumArtistId"
],
"limit": 5
}
name/alias,实时 JSON、Markdown、字段解析和 DSL 校验遵循同一份公开字段约定。albumArtistId、albumArtistName 可用于选择、筛选、分组和排序。models validate,0 invalid;Bundle 登记及刷新成功。artist$id、artist$caption,没有 albumArtistId / albumArtistName。query.validate 返回:{
"code": "FIELD_NOT_FOUND",
"message": "Field 'albumArtistId' not found in model 'MinimalArtistAliasQueryModel'. Did you mean 'track.album.artist$id'?",
"model": "MinimalArtistAliasQueryModel",
"phase": "query.validate",
"safeToAutoRepair": true,
"suggestedNextAction": "Call model describe and retry with an existing field."
}
albumArtistId 替换为 artist$id、albumArtistName 替换为 artist$caption(columns/slice/groupBy/orderBy 一并替换),再次 validate 后 execute,均成功:[
{
"artist$caption": "Iron Maiden",
"artist$id": 90,
"lineCount": 34,
"totalAmount": 33.66
}
]
| QM 写法 | 模型校验/加载 | JSON/Markdown 新名称 | 新名称 DSL 校验 | 同 QM 原名称对照 |
|---|---|---|---|---|
整维度 ref: line.track.album.artist, alias: 'albumArtist' |
通过 | 未出现 | FIELD_NOT_FOUND | 通过,34 条 / 33.66 |
| ID/caption 各自配置 alias | 通过 | 未出现 | FIELD_NOT_FOUND | 通过,34 条 / 33.66 |
| ID/caption 各自配置相同 name + alias | 通过 | 未出现 | FIELD_NOT_FOUND | 通过,34 条 / 33.66 |
三个 DSL 与此前 0.1.25 复现请求保持不变。整维度 ref 的 alias 是否应作为展开前缀,可以另行明确合同;即使该写法不支持,最小复现中对具体 ID/caption 列显式设置 name/alias 的问题仍存在。
在该 Release commit 中,SelectColumnDef 描述了 QM name/alias,DbQueryColumnImpl 也保存这些值;而 SemanticServiceV3Impl 的维度字段元数据构建使用 dimension.getEffectiveName() 生成 ID/caption 名称。推测 QM 列覆盖名未完整传到语义字段注册链路,尚未把这一点当作已确定的根因。
建议回归覆盖:QM 具体嵌套 ID/caption 的 name/alias、JSON/Markdown 一致性、columns/slice/groupBy/orderBy、执行结果输出键,以及两个同名嵌套维度通过 QM 别名消歧。整维度 alias 不支持时也应有明确诊断。