@guandata/guanetl 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## @guandata/guanetl 0.1.15 - 2026-06-15
4
+
5
+ - `save` 增强输出数据集保护,保留级联相关配置,并对追加写入场景的行数据结构提前校验。
6
+ - 补充多输出数据集和追加写入保存流程说明,降低 ETL 保存时误改输出配置的风险。
7
+
8
+ ## @guandata/guanetl 0.1.14 - 2026-06-09
9
+
10
+ - 移除 `delete` 命令。ETL / 数据集删除属于高风险操作,后续不再通过 guanetl 暴露。
11
+ - 修复 `edit -> export -> save` 保存已绑定输出数据集时,导出空 `dataSource` 覆盖服务端绑定并触发保存保护的问题。
12
+ - `run --wait` 明确区分触发响应状态与最终执行结果,避免把触发任务的 `FINISHED` 误读为 ETL 执行成功。
13
+ - 修复 ETL 导出与 merge 过程中部分节点字段丢失问题,并补充相关测试覆盖。
14
+
3
15
  ## @guandata/guanetl 0.1.13 - 2026-06-04
4
16
 
5
17
  - `lint` 增加字段 raw name 与 alias/displayName 疑似误用诊断,帮助识别 SQL/算子字段引用风险。
package/README.md CHANGED
@@ -39,6 +39,18 @@ guanetl install-skill
39
39
 
40
40
  ## 版本更新
41
41
 
42
+ ### @guandata/guanetl 0.1.15
43
+
44
+ - `save` 增强输出数据集保护,保留级联相关配置,并对追加写入场景的行数据结构提前校验。
45
+ - 补充多输出数据集和追加写入保存流程说明,降低 ETL 保存时误改输出配置的风险。
46
+
47
+ ### @guandata/guanetl 0.1.14
48
+
49
+ - 移除 `delete` 命令。ETL / 数据集删除属于高风险操作,后续不再通过 guanetl 暴露。
50
+ - 修复 `edit -> export -> save` 保存已绑定输出数据集时,导出空 `dataSource` 覆盖服务端绑定并触发保存保护的问题。
51
+ - `run --wait` 明确区分触发响应状态与最终执行结果,避免把触发任务的 `FINISHED` 误读为 ETL 执行成功。
52
+ - 修复 ETL 导出与 merge 过程中部分节点字段丢失问题,并补充相关测试覆盖。
53
+
42
54
  ### @guandata/guanetl 0.1.13
43
55
 
44
56
  - `lint` 增加字段 raw name 与 alias/displayName 疑似误用诊断,帮助识别 SQL/算子字段引用风险。
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guandata/guanetl",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "观远 ETL 本地开发工具 - 拉取、编辑、导出、预览、保存 ETL",
5
5
  "bin": {
6
6
  "guanetl": "bin/run.js"
@@ -139,7 +139,9 @@ guanetl run <etl_id> --wait # 可选:保存后触发执行并等待
139
139
 
140
140
  **再次修改已 save 过的 ETL 时**:即使本地还保留着上次的工作目录,也必须重新执行 `guanetl edit <etl_id> --dir <新目录>` 拉取服务端最新版本,不要在旧工作目录上直接改了再 save。原因:服务端版本可能已经变化,直接复用旧 base 会导致合并冲突(如"输出数据集目录中存在同名文件")。
141
141
 
142
- 如果 `save` 在 direct-save 前提示输出数据集绑定风险,按提示处理,不要手动删除旧输出数据集。常见原因是本地改动把已有 `OUTPUT_DATASET` 节点的 dsId/dataSource 绑定丢掉、新建了同目录同名输出节点,或用 `guands dataset rename` 改了输出数据集名但 `etl.go` 的 `outputDsName` 没同步。修复优先级:重新 `edit` 到新目录、保持原输出节点 id、同步 `outputDsName`,确实要新输出时改 `outputDsName` 或 `parentDirId`。
142
+ 如果 `save` 在 direct-save 前提示输出数据集绑定风险,按提示处理,不要手动删除旧输出数据集。常见原因是本地改动把已有 `OUTPUT_DATASET` 节点的 dsId/dataSource 绑定丢掉、新建了同目录同名输出节点,或用 `guands dataset rename` 改了输出数据集名但 `etl.go` 的 `outputDsName` 没同步。修复优先级:重新 `edit` 到新目录、保持原输出节点 id、同步 `outputDsName`;确实要新建独立输出时,同时更换 `OUTPUT_DATASET` 节点 id,并设置新的 `outputDsName` 或 `parentDirId`。
143
+
144
+ 只追加输出列是安全例外:新增列、不改名、不删已有列、不改已有列类型,并保持原 `OUTPUT_DATASET` 节点 id 和 `outputDsName` 时,可以原地 `save`,保存前仍需 `preview` 目标输出确认结果。改列名、删列、改类型、换输入数据集、重接输出链路或更换输出节点 id 都按下游绑定风险处理。
143
145
 
144
146
  ### 新建 ETL
145
147
 
@@ -311,7 +313,7 @@ guanetl task cancel <t1> <t2> # 批量取消多个任务
311
313
  | 节点函数 | 用途 | 何时使用 | 关键约束 |
312
314
  |---|---|---|---|
313
315
  | `BasicInputDataset` | 引入数据集 | 每个 ETL 至少一个 | 必须提供 `[]Field` schema |
314
- | `BasicOutputDataset` | 输出数据集 | 每个 ETL 至少一个(叶子节点) | `DefineETL()` 返回值 |
316
+ | `BasicOutputDataset` | 输出数据集 | 每个 ETL 至少一个,可有多个(叶子节点) | `DefineETL()` 返回值;多输出共享一次 save/run/schedule |
315
317
  | `BasicSelectColumns` | 选列/重命名 | 只需要部分字段或改名 | - |
316
318
  | `BasicFilterRows` | 行筛选 | 按条件过滤数据 | combineType: `AND`/`OR` |
317
319
  | `BasicJoinData` | 等值 JOIN | 两表关联 | **优先用这个,不要写 SQL JOIN** |
@@ -112,7 +112,8 @@ BasicFilterRows(id, name string, source Node, combineType string, conditions []F
112
112
  ```
113
113
 
114
114
  - `combineType` 只能是 `AND` 或 `OR`
115
- - 高频操作符:`EQ` `NE` `LT` `LE` `GT` `GE` `IN` `BT` `IS_NULL` `NOT_NULL` `CONTAINS` `NOT_CONTAINS` `STARTSWITH` `NOT_STARTSWITH` `ENDSWITH` `NOT_ENDSWITH`
115
+ - 高频操作符:`EQ` `NE` `LT` `LE` `GT` `GE` `IN` `BT` `CONTAINS` `NOT_CONTAINS` `STARTSWITH` `NOT_STARTSWITH` `ENDSWITH` `NOT_ENDSWITH`
116
+ - 当前 `BasicFilterRows` 不支持 `IS_NULL` / `NOT_NULL`;null 过滤请改用 SQL 节点(如 ``WHERE `列名` IS NULL`` / ``IS NOT NULL``)。
116
117
 
117
118
  ### 等值 JOIN
118
119
 
@@ -211,7 +212,7 @@ node := BasicSqlScript(
211
212
  SQL 规则:
212
213
 
213
214
  - 上游节点在 SQL 中用 `input1`、`input2` 这类名字引用。
214
- - 特殊列名、中文列名、带空格列名,用反引号。
215
+ - 特殊列名、中文列名、带空格列名,以及 `AS` 输出别名中的非 ASCII 标识符,都必须用反引号。
215
216
  - 输入数据集字段存在 `alias` / `displayName` / `showName` 时,优先使用展示名而不是 raw name。
216
217
  - 新增 SQL 节点时,要同步新增 `.sql` 文件。
217
218
 
@@ -241,6 +242,52 @@ func DefineETL() []Node {
241
242
  }
242
243
  ```
243
244
 
245
+ ### 多输出 ETL
246
+
247
+ `DefineETL()` 可以返回多个叶子输出节点。适合从同一批输入派生多张下游表,例如同时产出明细表和汇总表。
248
+
249
+ ```go
250
+ package main
251
+
252
+ import . "guanetl/internal/framework"
253
+
254
+ func DefineETL() []Node {
255
+ orders := BasicInputDataset("id_1001", "订单", "ds_orders", []Field{
256
+ BasicField("门店", "STRING"),
257
+ BasicField("订单号", "STRING"),
258
+ BasicField("销售额", "DOUBLE"),
259
+ }, Position{X: 100, Y: 120})
260
+
261
+ detail := BasicSelectColumns("id_1002", "订单明细", orders, []ColumnSetting{
262
+ {Name: "门店"},
263
+ {Name: "订单号"},
264
+ {Name: "销售额"},
265
+ }, Position{X: 340, Y: 40})
266
+
267
+ summary := BasicGroupBy(
268
+ "id_1003",
269
+ "门店汇总",
270
+ orders,
271
+ []GroupByColumn{
272
+ BasicGroupByColumn("门店", "STRING"),
273
+ },
274
+ []AggregationColumn{
275
+ BasicAggregationColumnWithAlias("销售额", "DOUBLE", "SUM", "销售额合计"),
276
+ },
277
+ Position{X: 340, Y: 200},
278
+ )
279
+
280
+ outDetail := BasicOutputDatasetInDir("id_1004", "输出明细", detail, "订单明细表", "ds_dir_id", Position{X: 600, Y: 40})
281
+ outSummary := BasicOutputDatasetInDir("id_1005", "输出汇总", summary, "门店销售汇总表", "ds_dir_id", Position{X: 600, Y: 200})
282
+
283
+ return []Node{outDetail, outSummary}
284
+ }
285
+ ```
286
+
287
+ - 每个输出都要有独立的 `OUTPUT_DATASET` 节点 id 和独立的 `outputDsName`。
288
+ - 多输出共享同一个 ETL 的 `save`、`run` 和调度配置;任何一个输出分支变更后,都应重新验收本 ETL 的全部输出。
289
+ - 如果多个输出需要独立调度、独立发布、独立回滚,或希望隔离某个输出分支的变更影响,应拆成多个单输出 ETL。
290
+
244
291
  ## 每次改完都检查
245
292
 
246
293
  1. `DefineETL()` 返回的是叶子节点吗?
@@ -266,10 +313,11 @@ func DefineETL() []Node {
266
313
  `save` 会先拉取服务端当前 ETL,再把本地 `_exported.json` 合并进去。修改已保存 ETL 时,输出节点必须保留服务端已有输出数据集绑定,否则 direct-save 可能把它当成“创建新输出数据集”,触发“输出数据集目录中存在同名文件”。
267
314
 
268
315
  - 再次修改已保存 ETL,优先重新执行 `guanetl edit <etl_id> --dir <新目录>`,不要长期复用旧工作目录。
269
- - 修改已有输出 schema 时,保持原 `OUTPUT_DATASET` 节点 id
316
+ - 只追加输出列时,可以原地 `save`:新增列,不改名、不删已有列、不改已有列类型,并保持原 `OUTPUT_DATASET` 节点 id 和 `outputDsName`。
317
+ - 修改已有输出 schema 时,保持原 `OUTPUT_DATASET` 节点 id;改列名、删列、改已有列类型、换输入数据集或重接输出链路都可能影响下游绑定,保存前必须重新 `preview` 并评估下游。
270
318
  - 如果用 `guands dataset rename` 改过 ETL 输出数据集名称,必须同步 `etl.go` 中 `BasicOutputDataset(..., outputDsName, ...)` 或 `BasicOutputDatasetInDir(..., outputDsName, ...)` 的名称。
271
319
  - 不要为了绕过同名错误手动删除旧输出数据集;旧输出通常仍被 ETL 依赖。
272
- - 如果确实要创建新输出数据集,必须改 `outputDsName` 或 `parentDirId`,避免与旧输出同目录同名。
320
+ - 如果确实要创建新输出数据集,必须同时更换 `OUTPUT_DATASET` 节点 id,并设置新的 `outputDsName` 或 `parentDirId`;只改名称会被视为已有输出绑定风险。
273
321
  - `save` 如果在 direct-save 前提示输出绑定风险,先修本地 `etl.go` / `meta.json`,再重新 `export -> preview -> save`。
274
322
 
275
323
  ## Appendix: Framework Surface
@@ -354,11 +402,14 @@ type Formula struct {
354
402
  - `LT` `LE` `GT` `GE`
355
403
  - `IN`
356
404
  - `BT`
357
- - `IS_NULL` `NOT_NULL`
358
405
  - `CONTAINS` `NOT_CONTAINS`
359
406
  - `STARTSWITH` `NOT_STARTSWITH`
360
407
  - `ENDSWITH` `NOT_ENDSWITH`
361
408
 
409
+ 当前限制:
410
+
411
+ - `BasicFilterRows` 暂不支持 `IS_NULL` / `NOT_NULL`;null 过滤请使用 `BasicSqlScript`。
412
+
362
413
  JOIN 类型:
363
414
 
364
415
  - `INNER`
@@ -381,3 +432,5 @@ APPEND_ROWS unionType:
381
432
  - `INCLUDE_SHARED`
382
433
  - `INCLUDE_ALL`
383
434
  - `INCLUDE_FROM`
435
+
436
+ `BasicAppendRows` 会按列名对齐各输入源。参与拼接的同名列类型必须一致;例如一侧为 `DATE`、另一侧为 `LONG` 会在 `export` 阶段报错。遇到冲突时,先用 `BasicCalculator` / `BasicSelectColumns` 把各源字段统一类型或移除不用的冲突列,再执行行拼接。