Skip to content

Enhance OML knowledge SQL handling and prefer local sqlite authority#97

Open
zwk4zhendeC wants to merge 2 commits into
wp-labs:hotfix/1.22from
zwk4zhendeC:feature/knowdb-sqlite-priority
Open

Enhance OML knowledge SQL handling and prefer local sqlite authority#97
zwk4zhendeC wants to merge 2 commits into
wp-labs:hotfix/1.22from
zwk4zhendeC:feature/knowdb-sqlite-priority

Conversation

@zwk4zhendeC
Copy link
Copy Markdown
Contributor

@zwk4zhendeC zwk4zhendeC commented May 15, 2026

支持 KnowDB provider 与本地 tables 共存时优先命中 sqlite authority

背景

当前 KnowDB 在 knowdb.toml 同时包含:

  • 外部 provider(如 PostgreSQL / MySQL)
  • 本地 [[tables]](CSV -> authority.sqlite)

时,运行时只会激活外部 provider,导致:

  • 本地 authority 虽然已配置,但查询不会优先命中 sqlite
  • OML SQL 中查询本地表时,仍然发往 PostgreSQL / MySQL
  • 如果外部库中没有该表,会直接报错
  • .run/authority.sqlite 在部分路径下还会被误删

这会让本地静态知识表无法在共存场景下发挥作用。


问题表现

以示例 tmp/knowdb_pg_sqlite 为例:

knowdb.toml 同时包含:

  • [provider] kind = "postgres"
  • [[tables]] name = "local_asset_data"

对应 OML:

pg_asset_name: chars = select asset from asset_data where ip = @src_ip;
sqlite_asset_name: chars = select asset from local_asset_data where ip = @src_ip;
sqlite_asset_list = select group_concat(distinct asset) from local_asset_data where ip in (@sip, @dip);

期望行为:

  • asset_data 继续走 PostgreSQL
  • local_asset_data 优先走本地 sqlite authority

旧行为:

  • local_asset_data 仍然发往 PostgreSQL
  • 典型报错为:
postgres query_named_fields failed: relation "local_asset_data" does not exist

解决方案

本次改动分为两层:

1. 启动阶段:即使存在 provider,也先构建本地 authority

在引擎初始化时:

  • 如果 knowdb.toml 中存在本地 [[tables]]
  • 无论是否配置了 [provider]
  • 都先构建 .run/authority.sqlite

同时:

  • provider 为 postgres/mysql 时,不再无条件删除 authority.sqlite
  • 只有真正需要重建本地 authority 时才清理旧文件

这保证了本地表在运行时始终有可用的 authority 数据源。

2. 运行阶段:按表名路由,本地表优先走 sqlite

在 OML SQL evaluator 中增加本地 sqlite 优先路由:

  • 启动时收集 knowdb.toml[[tables]] 的本地表名单
  • SQL 执行时解析 FROM <table>
  • 如果命中本地表名单:
    • 直接走 thread-cloned sqlite authority
  • 如果未命中:
    • 继续走当前活动 provider(如 PostgreSQL)

因此实现了:

  • 本地表优先 sqlite
  • 其他表继续走外部 provider

同时包含的改动(截至 1234c99,包含)

1. 增强 OML SQL 表达能力

  • 支持 group_concat(distinct ...)
  • 支持 where field in (...)
  • 支持 in(...)in (...)
  • 支持 SQL 条件中使用 @ref 引用前序 OML 字段

2. 空值处理优化

  • SQL 聚合无命中返回 NULL 时,不再把 field: null 写入最终结果
  • 如果所有 SQL 动态参数都为 null,则直接跳过查询,避免无意义请求和报错

3. take(...) 语义修复

  • take 现在可以消费前序 OML 已经写入 dst 的字段
  • read 的上下文可见性保持一致

主要改动点

引擎 / rescue 初始化

  • src/facade/engine.rs
  • src/facade/rescue.rs

职责:

  • 判断本地 [[tables]] 是否存在
  • 共存场景下优先构建 authority.sqlite
  • 避免 provider 场景误删 authority 文件
  • 注册本地 sqlite 优先路由

KnowDB handler

  • src/knowledge/mod.rs

职责:

  • 记录 authority URI
  • 收集本地表名单
  • 为运行时 sqlite 优先路由提供上下文

OML SQL evaluator

  • crates/wp-oml/src/core/evaluator/query/sql.rs

职责:

  • 本地表优先 sqlite 路由
  • SQL 全空参数短路
  • 保持普通 provider 查询路径不变

OML 最终结果写入

  • crates/wp-oml/src/core/evaluator/extract/operations/other.rs

职责:

  • 跳过 Value::Null,避免输出 field: null

SQL parser

  • crates/wp-oml/src/parser/sql_prm.rs

职责:

  • 支持 group_concat(distinct ...)
  • 支持 IN (...)
  • 支持 @ref

验证

已完成验证包括:

编译验证

cargo check -p wp-engine -p wp-oml

示例验证

在:

  • /Users/zwk/src_code/wp-labs/warp-parse

执行:

cargo run --bin wparse --all-features deamon --stat 2 -p --work-root /Users/zwk/src_code/wp-labs/wp-examples_bak/tmp/knowdb_pg_sqlite

验证结果:

  • asset_data 继续走 PostgreSQL
  • local_asset_data 已优先命中 sqlite authority

输出文件中已出现:

{
  "src_ip":"10.0.220.200",
  "dist_ip":"10.0.220.201",
  "pg_asset_name":"香港监控服务主机",
  "sqlite_asset_name":"1香港监控服务主机",
  "sqlite_asset_list":"1香港监控服务主机,1广东监控服务主机"
}

关联 Issue

@codecov
Copy link
Copy Markdown

codecov Bot commented May 15, 2026

Codecov Report

❌ Patch coverage is 43.63636% with 93 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/facade/rescue.rs 0.00% 37 Missing ⚠️
src/facade/engine.rs 50.90% 27 Missing ⚠️
crates/wp-oml/src/core/evaluator/query/sql.rs 63.26% 18 Missing ⚠️
src/knowledge/mod.rs 54.16% 11 Missing ⚠️

📢 Thoughts on this report? Let us know!

@zwk4zhendeC zwk4zhendeC changed the base branch from main to hotfix/1.22 May 15, 2026 12:15
Copy link
Copy Markdown
Contributor

@seeker-zuo seeker-zuo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

整体评价

方向正确,功能上能解决 #96 的问题。但代码质量和性能有几处需要改进后再合并。


主要问题

1. 代码重复:KnowdbProbe 等结构体在三处重复定义

KnowdbProviderProbeKnowdbProbeKnowdbTableProbe 在以下三个文件中几乎完全重复:

  • src/facade/engine.rs:71-87
  • src/facade/rescue.rs:23-44
  • src/knowledge/mod.rs:44-58

应该提取到 src/knowledge/mod.rspub(crate) 导出,让调用方复用。

2. KnowdbHandler 新增方法未被使用

authority_uri()local_tables()has_local_tables() 已添加,但 engine.rsrescue.rs 各自独立调用 load_local_table_names() 重新解析 toml,导致 knowdb.toml 被解析两次。应该通过 KnowdbHandler 获取这些信息。

3. first_table_name() SQL 解析过于脆弱 (sql.rs:45-55)

用字符串匹配 from 提取表名,以下场景会出错:

  • 子查询:SELECT * FROM (SELECT * FROM real_table) → 匹配到内层 FROM
  • JOIN:SELECT * FROM t1 JOIN t2 → 只拿到 t1
  • 字符串中含 "from":SELECT 'from' AS x FROM my_table → 匹配错误

建议至少对子查询和 JOIN 场景做防御性处理,或在匹配失败时 warn 日志。

4. 性能:每次查询都做 to_ascii_lowercase() 堆分配

first_table_name() 中对每条 SQL 执行 sql.to_ascii_lowercase(),这是热路径(每条 event 可能触发多次),会造成不必要的堆分配。建议改为逐字节遍历做 case-insensitive 匹配。

5. 性能:热路径上的 RwLock::read()

local_sqlite_for_table() 每次调用都获取 RwLock::read()。99% 的查询来自外部 provider 不会命中本地表,但每条 SQL 仍需走一遍原子操作。建议初始化时把 HashSet<String> 放到 Arc 里,查询路径只做 Arc::clone + 无锁查找。

6. 性能:ThreadClonedMDB 每次查询创建新连接

每次命中本地表都调用 ThreadClonedMDB::from_authority() 创建新连接,高频场景下开销较大。建议缓存连接或复用。


次要问题

7. should_rebuild_local_authority 命名误导

PG/MySQL 时返回 false(不重建),但调用方通过 || !local_tables.is_empty() 覆盖了结果,实际语义是 "是否应该保留旧 authority 文件"。建议改名或反转返回值。

8. engine.rsrescue.rs 的 authority URI 读写模式不一致

  • engine.rs:492readonly_authority_uri() — 只读
  • rescue.rs:128authority_uri.clone() — 读写

如果是有意为之,需要注释说明原因;如果是遗漏,应该统一。

9. 缺少自动化测试

first_table_name()、路由逻辑、should_rebuild_local_authority() 等关键函数均无单元测试。手动验证能证明本次正确,但后续重构容易引入回归。


建议处理顺序

优先级 事项
🔴 消除三处结构体重复,提取到 knowledge/mod.rs
🔴 调用方改用 KnowdbHandler 获取 local_tables,避免重复解析
🔴 去掉 to_ascii_lowercase() 每查询一次堆分配
🔴 去掉热路径 RwLock::read(),改用 Arc<HashSet> 无锁查找
🟡 缓存 ThreadClonedMDB 连接或将创建移到调用方
🟡 改进 first_table_name() 的 SQL 解析鲁棒性
🟢 添加关键路径单元测试
🟢 统一 URI 读写模式 / 改进函数命名

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants