Conversation
SET 子句原按 split(",") 切分,假设逗号只用于分隔列,导致 replace(col,?,?)、
concat(a,b)、substr(s,1,2) 等函数调用的参数逗号被当作列分隔符,解析出 "?"、"?)"
等伪列名。脏列名经 latestSQL() 拼进前镜像/后镜像查询,产出非法 SQL:
SELECT short_name_tair,?,?),ID FROM BIZ_PBM_ORGANIZATION WHERE ID IN (...) AND 1=1
该 SQL 在达梦 DM8 上报 42000/-2007,且 dbstream 内部 SQL 不经过业务侧 SQL 日志,
调用方看到的却是自己那条合法 UPDATE 的失败,错误归因误导、排查成本高。
修复:
- 抽出 SQLUtils.splitTopLevel(),按括号深度 + 字符串状态切分,仅在顶层切分;
复用 parseInsertSQLValues() 已有的同类逻辑,避免第二份实现,不引入新依赖
- UpdateSQLParser.getColumnValues() 改用 splitTopLevel,且跳过无 "列名=表达式"
结构的片段
- UpdateDBEventParser.latestSQL() 不再拼出 "IN ()"(主键值为空时跳过该条件,
全部为空时退化为 1=0),字符串主键转义单引号,null 主键跳过
- 前镜像为空时不再进入后镜像查询
- 前镜像/后镜像查询失败时把内部 SQL 原文带进 SQLException,避免归因到业务 SQL
(Update/DeleteDBEventParser)
测试:UpdateSQLParserTest 由 5 例增至 14 例,覆盖 issue 原始 SQL、多函数调用、
字面量内逗号、无等号片段、别名 + substr。全量 59 个测试通过。
Fixes #9
Co-Authored-By: Claude Code <[email protected]>
pom.xml 版本号 1.0.19 → 1.0.20,包含 issue #9 的修复。 Co-Authored-By: Claude Code <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #9
问题
UPDATE的SET子句含函数调用时,dbstream 会生成非法 SQL 并抛给调用方。UpdateSQLParser.getColumnValues()取到 SET 子句后直接split(","),假设逗号只用于分隔列。但replace(col, ?, ?)/concat(a, b)/substr(s, 1, 2)这类函数调用的参数之间也有逗号,于是被当成列分隔符,解析出"?"、"?)"等伪列名。脏列名经
latestSQL()拼进内部查询,产出:达梦 DM8 上报
SQLState 42000 / -2007,第 1 行, 第 26 列[)]附近出现错误。为什么难排查
内部 SQL 不经过业务侧的 SQL 日志,调用方(Hibernate)看到的是自己那条合法 UPDATE 的失败:
一条合法 SQL 顶着另一条非法 SQL 的报错。
修复
SQLUtils.splitTopLevel()— 抽出按「括号深度 + 字符串状态」切分的原语,仅在顶层切分。复用parseInsertSQLValues()中已有的同类逻辑,不引入 jsqlparser,保持零运行时依赖UpdateSQLParser.getColumnValues()— 改用splitTopLevel,并跳过无列名=表达式结构的片段UpdateDBEventParser.latestSQL()— 主键值为空时不再拼出IN ()(全部为空退化为1=0,避免退化成全表扫描);字符串主键转义单引号;null 主键跳过SQLException(Update/Delete 两侧)验证
修复后渲染出的内部查询,与 issue §4 的「黄金对照」第 3 条逐字一致:
其他边界:前镜像为空 →
WHERE 1=0;字符串主键含引号 →IN ('o''brien')。./mvnw clean test— 59 个测试全部通过。UpdateSQLParserTest由 5 例增至 14 例,新增覆盖 issue 原始 SQL、多函数调用、字面量内逗号、无等号片段、别名 +substr。行为变化说明
SQLUtils.splitTopLevel原样保留字符串里的''(原parseInsertSQLValues会折叠成',丢失转义信息)。该变化已通过集成测试确认无影响。🤖 Generated with Claude Code