真机侦察(S4T / NW 7.40)确认 data preview freestyle 解析器只接受窄 SQL 子集: - 选择列必须逗号分隔;WHERE 不支持 =,只支持 IN / LIKE - 现状 --where 'F=X' 会 400 并抛未捕获堆栈(非友好报错) 新增:错误速查 3 行 + 方言/元数据表对照小节(DD02T/DD40T/DD04T/DD01T + TADIR); sap-tool-constraints 规则 9 + 自检项 10。references/ 与 .claude/rules/ 已同步。 顺带记录:info 的传输请求恒为 (无法获取)——E071 查询用的 = 在该方言必 400,异常被吞。
6.9 KiB
6.9 KiB
sap-cli 使用约束
本文件定义使用 sap-cli 操作 SAP 系统时的 硬性约束。违反任何一条都会被 Hooks 拦截。
🚫 规则 1:只使用 sap-cli 命令操作 SAP 系统
操作 SAP 系统时,必须且只能使用 python main.py <命令> 的形式。
严禁以下行为:
| 禁止操作 | 原因 |
|---|---|
用 Python requests / urllib 直接调 ADT REST 端点 |
必须通过 sap-cli 命令 |
用 curl 直接调 ADT 端点(/sap/bc/adt/*) |
必须通过 sap-cli 命令 |
用 curl 调 SOAP RFC(/sap/bc/soap/rfc) |
必须通过 sap-cli 的 read-table 命令 |
编写 Python 脚本导入 sapcli.client.ADTClient 后直接调内部方法 |
sap-cli 的内部 API 不是公开接口 |
| 在 Python 脚本中手动构造 ADT XML body | 必须通过 sap-cli 命令处理 |
用 python -c 内联调用 requests 访问 SAP |
同上 |
唯一合法的 SAP 交互方式:
cd D:/Gitee/sap-cli-skill/assets && python main.py <command> [options]
本机唯一源目录为
D:/Gitee/sap-cli-skill,工具在其assets/下(原D:/Gitee/sap-cli已归档,勿再用)。通过--profile <名>切换目标系统,连接配置在assets/config.ini。
例外(仅在以下情况下允许)
run-program执行自定义 ABAP 报表 — 这是 sap-cli 的内置功能- 用户明确要求使用其他方式(如"请用 curl 测试这个端点")
- 开发 sap-cli 本身(作为项目开发而非使用工具时)
🚫 规则 2:禁止修改 SAP 标准开发对象
SAP 系统中的标准交付对象(CL_*、CX_*、IF_*、SAPL* 等)严禁修改。
| 禁止 | 说明 |
|---|---|
download 标准对象后修改再 sync 回去 |
破坏 SAP 系统一致性 |
对标准对象执行 delete |
不可逆操作 |
run-program 修改标准对象源码 |
同上 |
允许(只读):
- ✅
download/info/list/search/whereused - ✅
show-table/read-table— 查看结构和数据 - ✅
diff— 对比分析
判定标准:对象 original system 不是用户自己的开发系统,或对象名以 SAP 标准命名空间开头。不确定时先问用户。
🚫 规则 3:禁止操作系统表数据
SAP 系统表(存储元数据、运行时状态、内部配置的表)严禁直接操作。
| 禁止 | 典型表 |
|---|---|
| INSERT / UPDATE / DELETE / MODIFY 系统表 | TADIR, E071, SEOCLASS, REPOSRC, D010SINF, T000, TDEVC, TSTC |
允许(只读):
- ✅
read-table/show-table查看(SELECT)系统表数据用于诊断 - ✅
run-program报表中 SELECT 读取系统表
唯一例外:用户明确授权后才能操作系统表,且必须遵循 4 步授权流程(见 error-handling.md)。
🚫 规则 4:sync 命令必须带 --corr_nr
# ✅ 正确
python main.py sync --name ZMY_CLASS --type class --path ./src/zmy.abap --corr_nr DEVK901362
# ❌ 错误(缺少 --corr_nr,会触发交互式传输请求选择)
python main.py sync --name ZMY_CLASS --type class --path ./src/zmy.abap
🚫 规则 5:DDIC 对象的 NW 7.40 限制
在 NW 7.40 上,DDIC 对象(domain、dataelement、table)的 ADT Lock 返回 HTTP 406。
- 这是 SAP 系统限制,不是 sap-cli 的 bug
- sync DDIC 失败时,不要反复重试 — 报告给用户,让用户通过 SAP GUI SE09 处理
- 新建的 DDIC 对象(不存在于 SAP)可通过
create --definition创建
🚫 规则 6:查表数据用 read-table,查表结构用 show-table
sap-cli 已内置这些命令,不要自己写 HTTP 调用。
# 查看表结构
python main.py show-table --name ZSAPILOT_OBJ
# 查看表数据
python main.py read-table --name ZSAPILOT_OBJ --max-rows 50
🚫 规则 7:DDIC 未完成禁止开发引用它的代码(依赖顺序)
代码引用的每个 DDIC 对象(域/数据元素/表/结构/表类型)必须先完成「上传 → 语法检查通过 → 激活成功」三关,才能开始写引用它的代码。
- 落地顺序:
domain → dataelement → table/structure → tabletype → interface → class → function → report - 是否完成以实测为准:结构查
DD02L(AS4LOCAL = 'A')、表类型查DD40L、其余查info/TADIR;不采信会话自述 - 违反后果:后续每个引用对象语法检查报「类型/结构 XXX 未知」,整批返工
🚫 规则 8:强制开发闭环(不得跳步)
1. 本地编写/修改源码 → 2. 同步 SAP(upload/sync) → 3. 语法检查(syntax-check)
↑ │
└──────────────── 有错则回到第 1 步 ←───────────────────┘
4. 语法检查 0 错误 → 激活(activate) → 5. 激活成功后才允许执行测试(run-program/unit-test)
└── 测试不过 → 回到第 1 步
禁止:
- ❌ 跳过语法检查直接 activate
- ❌ 未激活就 run-program / unit-test(跑旧版本或报对象不存在)
- ❌ 把「语法检查通过」当「功能正常」—— syntax-check 不校验被调对象存在性与签名(见
abap-coding-rules.mdE04/E05) - ❌ 把「S4T 演示机通过」表述为「CEM/生产验证通过」
- ❌ 多会话并发操作同一批对象(派下一会话前先确认前一个已退出)
🚫 规则 9:read-table 的 --where 只能写 IN / LIKE
read-table 走 ADT Data Preview freestyle 解析器,只接受很窄的 SQL 子集。用 = 会返回 400,并以未捕获异常打印堆栈(不是友好报错)。
| 写法 | 实测结果 |
|---|---|
--where "TABNAME IN ('ZMM_BIP_001_HEADER')" |
✅ 200 |
--where "OBJ_NAME LIKE 'ZMM_BIP%'" |
✅ 200 |
--where "TABNAME='ZMM_BIP_001_HEADER'" |
❌ 400 A Boolean expression was expected |
--fields "A,B"(逗号分隔) |
✅ 200 |
--fields "A B"(空格分隔) |
❌ 400 要求逗号分隔 |
- 要按多个值过滤,一次
IN查完,不要循环单点查。 - 更多方言细节与元数据表对照见
error-handling.md「ADT Data Preview SQL 方言」。
自检清单
每次执行 SAP 操作前,确认:
- ✅ 我在用
python main.py <命令>吗? - ✅ 我没有直接调 ADT/SOAP/RFC 端点吗?
- ✅ 我操作的是 Z* 开头的自定义对象吗?
- ✅ 我没有 INSERT/UPDATE/DELETE 系统表吗?
- ✅ sync 命令带了
--corr_nr吗? - ✅ 我引用的 DDIC 对象都已激活(实测确认)了吗?
- ✅ 我按「本地改 → 同步 → 语法检查 → 循环至 0 错误 → 激活 → 测试」执行了吗?
- ✅ 我核实过被调函数/结构的存在性与签名了吗(E04/E05)?
- ✅ 同一任务只有一个开发者会话在跑吗?
- ✅
read-table的--where我用的是IN/LIKE而不是=吗?--fields是逗号分隔吗?