如何在ANTLR4中跳过指定SQL语句的解析及重写阶段
很抱歉这个问题此前已被关闭无法重新打开,我的英文水平有限,内容确实是通过网站翻译的。:)
@BartKiers 感谢您对这个问题感兴趣,我来举详细的示例说明。
现有大量SQL查询,例如select * from user、update user set field1 = 'value1' where condition = 'value'等,我们将其统称为原始SQL查询。
现有一个Java程序会通过ANTLR4拦截所有原始SQL查询,将其解析为Parse Tree节点后,依赖解析结果对查询进行重写,原始SQL经过解析重写后可能变为:
select field1, field1_encrypted, field1_digest, field2 from user
或者:
update user set field1 = value1, field1_encrypted = encrypt_algorithm(value1), field1_digest = digest_algorithm(value1) where condition_digest = digest_algorithm(values)
等形式。
重写完成后,这些SQL会作为SQLStatement执行,SELECT语句对应SelectSQLStatement执行,UPDATE语句对应UpdateSQLStatement执行。
现在我希望部分原始SQL可以跳过解析阶段,同时对应的重写阶段也一并跳过,直接执行原始SQL语句。
我打算用注释标记这类SQL,例如:
/* PARSE_PHASE_SKIPPED=TRUE */ originalSQL
或者加SKIP前缀:
SKIP originalSQL
我希望ANTLR4可以将标记后的完整原始SQL部分解析为Parse Tree节点,将其作为ParsePhaseSkippedSQLStatement执行。
请问ANTLR4是否支持这种场景,对应的语法应该怎么写?提前感谢。
感谢您的回复@Mike Cargal,您的理解基本正确。我再重新说明,举更详细的示例。
我们有一个名为X的Java系统,里面有大量开发人员编写的SQL查询,这些SQL已经确认可以通过Ibatis/JPA等正常执行,我们将其称为原始SQL查询。
举两个原始SQL查询的示例:
insert into user (username, id_no) values ('xyz', '123456')
select username, id_no from user u where u.id_no = '123456'
现在user表的id_no字段属于敏感数据,需要存储密文而非明文,因此原始SQL会经过ANTLR解析,再通过Java代码重写为如下形式,我们称之为重写后SQL,这些重写后的SQL同样可以通过Ibatis/JPA正常执行:
insert into user (username, id_no, id_no_cipher, id_no_digest) values ('xyz', '', 'encrypted_123456', 'digest_123456')
select username, id_no_cipher as id_no from user u where u.id_no_digest = 'digest_123456'
该场景下:
- 重写阶段依赖解析阶段的结果,原始SQL需要被正确解析后才能通过Java代码完成重写。
- 所有原始SQL都会被解析,但只有匹配敏感数据规则的部分会被重写为重写后SQL。
但有很多原始SQL我们明确知道不需要重写,也不需要解析,且部分复杂SQL在解析时还可能抛出异常,但这些SQL本身可以通过Ibatis/JPA正常执行。
因此我计划通过SQL注释、自定义关键字标记的方式“关闭”这类SQL的解析阶段,请问该需求在ANTLR4中如何实现,对应的语法规则应该怎么写?
内容的提问来源于stack exchange,提问作者bafony

