我尝试通过复制xpath规则在声纳(plsql)中编写自定义规则。此规则的任务是标记“rollback to savepoint”语句,其中缺少savepoint语句。
对于2个保存点和3个回滚语句,AST(抽象语法树)如下所示:
<PROCEDURE_DEFINITION>
...
<SAVEPOINT>
<IDENTIFIER tokenValue="SAVEPOINT" />
<IDENTIFIER tokenValue="spA" />
<SEMICOLON tokenValue=";" />
</SAVEPOINT>
...
<SAVEPOINT>
<IDENTIFIER tokenValue="SAVEPOINT" />
<IDENTIFIER tokenValue="spB" />
<SEMICOLON tokenValue=";" />
</SAVEPOINT>
...
<ROLLBACK>
<IDENTIFIER tokenValue="ROLLBACK" />
<TO />
<IDENTIFIER tokenValue="SAVEPOINT" />
<IDENTIFIER tokenValue="spB" />
<SEMICOLON tokenValue=";" />
</ROLLBACK>
...
<ROLLBACK>
<IDENTIFIER tokenValue="ROLLBACK" />
<TO />
<IDENTIFIER tokenValue="SAVEPOINT" />
<IDENTIFIER tokenValue="spA" />
<SEMICOLON tokenValue=";" />
</ROLLBACK>
...
<ROLLBACK>
<IDENTIFIER tokenValue="ROLLBACK" />
<TO />
<IDENTIFIER tokenValue="SAVEPOINT" />
<IDENTIFIER tokenValue="spX" />
<SEMICOLON tokenValue=";" />
</ROLLBACK>
...
</PROCEDURE_DEFINITION>
我搜索标记上次回滚的XPath查询,因为缺少savepoint spX。 但是这个xpath标记最后两个回滚
//PROCEDURE_DEFINITION//ROLLBACK[
IDENTIFIER[
@tokenValue =
./ancestor::PROCEDURE_DEFINITION
//SAVEPOINT/IDENTIFIER[2]/@tokenValue
]
]
有什么建议吗?
修改
我找到了这个次优的解决方案:
//PROCEDURE_DEFINITION//ROLLBACK
[
not(
./IDENTIFIER[3]/@tokenValue =
ancestor::PROCEDURE_DEFINITION//SAVEPOINT/IDENTIFIER[2]/@tokenValue
)
]
PLSQL不区分大小写。但是当我添加翻译功能时,我会被标记为第一个和最后一个ROLLBACK节点。我想所有回滚的名字都会同意第一个保存点的名字吗?
答案 0 :(得分:1)
首先,根据您显示的AST,在我看来,这是您要在其上运行XPath查询的PL / SQL代码:
DECLARE
PROCEDURE foo AS
BEGIN
SAVEPOINT spA;
SAVEPOINT spB;
ROLLBACK spB; -- Compliant
ROLLBACK spA; -- Compliant
ROLLBACK spX; -- Non-Compliant
END;
BEGIN
NULL;
END;
/
当我使用SSLR PL / SQL工具包运行您的第一个XPath查询时,回滚到&#39; spB&#39;和&#39; spA&#39;被选中,但不是“spX&#39;”。
您的第二个XPath查询会选择所有这些。
在我看来,你只想选择一个“spX&#39;”,因为没有相应的保存点。
对第一个查询进行微不足道的更改允许通过使用not()取消条件来反转所选节点:
//PROCEDURE_DEFINITION//ROLLBACK[
not(IDENTIFIER[
@tokenValue =
./ancestor::PROCEDURE_DEFINITION
//SAVEPOINT/IDENTIFIER[2]/@tokenValue
])
]
但我实际上建议您删除查询的PROCEDURE_DEFINITION部分,因为SAVEPOINT和ROLLBACK语句在函数或匿名块中也是有效的:
//ROLLBACK[not(IDENTIFIER[@tokenValue = //SAVEPOINT/IDENTIFIER[2]/@tokenValue])]