📝 docs(tsl): restructure agent-facing reference

Rework TSL syntax, catalog, modules, and routing docs around deterministic agent lookup and generation.

Split large catalog pages into focused function fact pages, remove obsolete pending/verified/unavailable paths, and update consistency tests for the new structure.
This commit is contained in:
csh
2026-06-09 17:24:30 +08:00
parent 9c194170a1
commit 540b3c0a1b
192 changed files with 32929 additions and 13533 deletions
+338
View File
@@ -0,0 +1,338 @@
# TSL TS-SQL
文档类型:语法主线
是否可直接用于生成代码:是
是否含可直接照写示例:是
是否含不可照写反例:是
遇到不确定时:先按本页候选页继续判断;[13_resultset_and_filters.md](13_resultset_and_filters.md)、[12_matrix_and_collections.md](12_matrix_and_collections.md)、[23_fmarray.md](23_fmarray.md);仍不命中时回到语法路由中心 [index.md](index.md);如果问题已经超出语法层,回到 TSL 总入口 [../index.md](../index.md)
这一篇是 TS-SQL 的唯一语法入口:内存数组查询、返回形态、字段访问、`where` / `group by` / `order by`、一维数组查询、多表 `join``thisGroup``thisRowIndex``refMaxOf` / `refMinOf` 都在这里收拢。
## 本篇职责
回答“写 TS-SQL 查询时,怎样从最小 `select ... from ... end` 骨架开始,逐步处理筛选、分组、排序、多表联接、组内子查询和极值引用”。
## 智能体 TS-SQL 判断流程
1. 先判断要写 `select``sselect``vselect``mselect`,还是 `join` / `thisGroup` / 极值引用。
2. 内存数组查询优先从 `select ... from source_rows end` 最小骨架起手。
3. 二维结果集字段访问用 `["字段名"]`;多表查询字段访问用 `[表序号].["字段名"]`
4. 在一维数组上做 TS-SQL 时,优先使用 `thisRow``thisRowIndex`
5. 只想按已有结果集保留/排除行时跳到 [13_resultset_and_filters.md](13_resultset_and_filters.md);要做去重型集合关系时跳到 [12_matrix_and_collections.md](12_matrix_and_collections.md);要在 `FMArray` 上做查询或写回边界时跳到 [23_fmarray.md](23_fmarray.md)。
6. 没有对应代码块时不要发明 TS-SQL 写法。
## 核心规则
- TS-SQL 是 TSL 自带的类 SQL 查询语法,不是金融业务函数库。
- 基础查询文档骨架是:以 `select` / `sselect` / `vselect` / `mselect` 开始,以 `end` 收尾。
- `from` 后面可以直接跟内存数组结果集。
- 在内存二维结果集上,文档字段访问写法是 `["字段名"]`
- 在一维数组上做 TS-SQL 时,优先使用 `thisRow``thisRowIndex`
- `select` 返回二维结果,`sselect` 返回一维结果,`vselect` 返回单值,`mselect` 返回 `Matrix`
- `where``group by``order by` 可以直接接在 `from` 后面继续使用。
- 多表 `join` 时,字段访问应写成 `[表序号].["字段名"]`
- `thisGroup` 不是普通值,而是分组后的子结果集;要通过子 `select` / `vselect``from thisGroup` 来访问。
- `thisRowIndex``order by` 之后仍可返回原始行位置,而不是排序后的序号。
- `refMaxOf(...)``refMinOf(...)` 可与 `maxOf(...)` / `minOf(...)` 配合,取极值所在行的另一列值。
- 访问金融表、时间序列或业务数据源时,语法和业务语义要分开看;本页只讲语言层查询骨架。
## 可直接照写示例
### 最小查询骨架
代码块身份:可直接照写示例
```tsl
source_rows := array(
("A": 1, "B": 3),
("A": 2, "B": 1)
);
query_result := select * from source_rows end;
writeLn(length(query_result));
```
结果说明:
- `query_result` 的长度是 `2`
- 两行依次是 `(1,3)``(2,1)`
- 说明 TS-SQL 的最短可靠入口就是“准备结果集,然后 `select ... from source_rows end`
代码块身份:输出片段
```text
2
```
### 字段选择
代码块身份:可直接照写示例
```tsl
source_rows := array(
("A": 1, "B": 3),
("A": 2, "B": 1),
("A": 1, "B": 2)
);
query_result := select ["A"], ["B"] from source_rows end;
writeLn(length(query_result));
```
结果说明:
- `query_result` 的长度是 `3`
- 三行依次是 `(1,3)``(2,1)``(1,2)`
- 说明 `select ["A"], ["B"] from source_rows end` 会按原顺序返回二维结果集
### 四个查询入口怎样分工
代码块身份:可直接照写示例
```tsl
source_rows := array(
("A": 1, "B": 3),
("A": 2, "B": 1),
("A": 1, "B": 2)
);
selected_values := sselect ["A"] from source_rows end;
sum_value := vselect sumOf(["B"]) from source_rows end;
matrix_result := mselect * from source_rows end;
col_index := mcols(matrix_result, 1);
```
结果说明:
- `sselect ["A"] from source_rows end` 返回一维数组 `array(1, 2, 1)`
- `vselect sumOf(["B"]) from source_rows end` 返回单值 `6`
- `mselect * from source_rows end` 的行数是 `3`、列数是 `2`
- `mcols(matrix_result, 1)` 返回列索引 `array("A", "B")`
- 本页只把 `mselect` 的“返回 Matrix 且保留行列信息”写成文档主干;不要在本页发明直接单元格读取规则
### `where` 和 `order by`
代码块身份:可直接照写示例
```tsl
source_rows := array(
("A": 1, "B": 3),
("A": 2, "B": 1),
("A": 1, "B": 2)
);
query_result := select * from source_rows where ["B"] > 1 order by ["B"] end;
```
结果说明:
- `query_result` 的长度是 `2`
- 两行依次是 `(1,2)``(1,3)`
- 说明 `where ["B"] > 1` 会先筛选,再按 `order by ["B"]` 的升序返回
### `group by`
代码块身份:可直接照写示例
```tsl
source_rows := array(
("A": 1, "B": 3),
("A": 2, "B": 1),
("A": 1, "B": 2)
);
group_result := select ["A"], sumOf(["B"]) as "SumB"
from source_rows
group by ["A"]
order by ["A"]
end;
```
结果说明:
- `group_result` 的长度是 `2`
- 第一行是 `(1,5)`
- 第二行是 `(2,1)`
- 说明 `group by ["A"]` 后可以直接接聚集函数,并用 `as "SumB"` 指定返回列名
### 一维数组上的 `thisRow` 与 `thisRowIndex`
代码块身份:可直接照写示例
```tsl
values := array(10, 20, 30);
row_values := sselect thisRow from values end;
row_indexes := sselect thisRowIndex from values end;
query_result := select thisRow as "Value", thisRowIndex as "Idx"
from values
where thisRow > 15
order by thisRow
end;
```
结果说明:
- `sselect thisRow from values end` 返回 `array(10, 20, 30)`
- `sselect thisRowIndex from values end` 返回 `array(0, 1, 2)`
- 上面的 `select ... from values where thisRow > 15 order by thisRow end` 返回两行:第一行 `Value=20, Idx=1`,第二行 `Value=30, Idx=2`
### `join`
代码块身份:可直接照写示例
```tsl
left_rows := array(
("ID": 1, "V1": 10),
("ID": 2, "V1": 20)
);
right_rows := array(
("ID": 1, "V2": 100),
("ID": 3, "V2": 300)
);
join_result := select [1].["ID"], [1].["V1"], [2].["V2"]
from left_rows join right_rows on [1].["ID"] = [2].["ID"]
end;
writeLn(length(join_result));
writeLn(join_result[0]["ID"]);
writeLn(join_result[0]["V1"]);
writeLn(join_result[0]["V2"]);
```
结果说明:
- `join_result` 的长度是 `1`
- 唯一一行是 `(1,10,100)`
- 说明 `from left_rows join right_rows on ...``[1].["字段"]``[2].["字段"]` 这种多表字段访问属于文档明确写法
代码块身份:输出片段
```text
1
1
10
100
```
### `thisGroup`
代码块身份:可直接照写示例
```tsl
source_rows := array(
("A": 1, "B": 3, "Name": "x"),
("A": 2, "B": 1, "Name": "y"),
("A": 1, "B": 2, "Name": "z")
);
group_result := select ["A"], maxb := maxOf(["B"]) as "MaxB",
vselect ["Name"] from thisGroup where ["B"] = maxb end as "TopName"
from source_rows
group by ["A"]
order by ["A"]
end;
```
结果说明:
- `group_result` 的长度是 `2`
- 第一行是 `(1,3,"x")`
- 第二行是 `(2,1,"y")`
- 说明 `thisGroup` 可以在分组上下文里作为子结果集继续 `vselect`
### `thisRowIndex` 在排序后仍指向原始位置
代码块身份:可直接照写示例
```tsl
source_rows := array(
("A": 1, "B": 3),
("A": 2, "B": 1),
("A": 1, "B": 2)
);
query_result := select thisRowIndex as "Idx", ["B"]
from source_rows
order by ["B"]
end;
```
结果说明:
- `query_result` 的三行依次是 `(1,1)``(2,2)``(0,3)`
- 说明 `order by ["B"]` 之后,`thisRowIndex` 仍返回原表中的原始下标
### `refMaxOf` 与 `refMinOf`
代码块身份:可直接照写示例
```tsl
source_rows := array((6, 20), (5, 20), (9, 2), (2, 20), (7, 18));
max_ref_result := select maxOf([0]) as "MaxA", refMaxOf([1]) as "RefB" from source_rows end;
min_ref_result := select minOf([0]) as "MinA", refMinOf([1]) as "RefB" from source_rows end;
```
结果说明:
- `max_ref_result` 只有一行,结果是 `(9,2)`
- `min_ref_result` 只有一行,结果是 `(2,20)`
- 说明 `refMaxOf([1])` 取到了 `[0]` 最大值所在行的 `[1]``refMinOf([1])` 取到了 `[0]` 最小值所在行的 `[1]`
## 本页不生成的范围
- `with on`
- `left join` / `right join` / `full join`
- `RefsOf`
- `insert` / `update` / `delete`
- `TSQLInsert` / `TSQLSetValue` / `TSQLBatchInsert`
- `TSQLEdit` / `TSQLPost` / `TSQLFinal`
- 面向 SQL 表、业务表或时间序列的数据查询与写回
这些内容不作为本页可生成事实;业务数据源先查 [../reference/catalog/datawarehouse.md](../reference/catalog/datawarehouse.md)、[../modules/pytsl_api.md](../modules/pytsl_api.md) 或项目实际接口。
## 默认生成模板
TS-SQL 的最短默认骨架如下:
代码块身份:可直接照写示例
```tsl
query_result := select * from source_rows end;
```
## 禁止项
- 不要把数据库 SQL 方言直接迁移成 TS-SQL 代码。
- 不要把 `select` 当成普通函数调用,忘了以 `end` 收尾。
- 在二维结果集里直接写 `A` 而不是 `["A"]`
- 多表联接时继续写成 `["ID"]`,没有加表序号。
- 处理一维数组时直接把 `[0]` 当成稳定列访问。
-`thisGroup` 当成普通字段或普通变量。
- 把排序后的 `thisRowIndex` 误当成排序序号。
-`with on`、写回接口和时间序列缓存写进默认模板。
代码块身份:反例 / 不可照写
```text
query_result := select A from source_rows end;
```
上面这种写法不要当成本页可靠规则。二维结果集字段访问,本页只把 `["A"]` 这种写法写成文档主干。
代码块身份:反例 / 不可照写
```text
query_result := select [0] from values end;
```
这种对一维数组直接用 `[0]` 的写法虽然返回长度为 `3` 的结果,但取到的值是 `nil`,不能当成可靠入口。对一维数组应改用 `thisRow``thisRowIndex`
代码块身份:反例 / 不可照写
```text
query_result := select ["ID"], ["V1"], ["V2"]
from left_rows join right_rows on ["ID"] = ["ID"]
end;
```
上面这种写法不要当成本页可靠规则。多表查询里,本页只把 `[1].["字段"]``[2].["字段"]` 这种带表序号的访问方式写成文档主干。
代码块身份:反例 / 不可照写
```text
group_value := thisGroup;
```
不要把 `thisGroup` 当成普通值直接使用。可靠入口是 `select ... from thisGroup end``vselect ... from thisGroup end`