XPath-1.0:标记缺少相对节点的节点

时间:2013-06-25 11:53:51

标签: sonarqube xpath-1.0

我尝试通过复制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节点。我想所有回滚的名字都会同意第一个保存点的名字吗?

1 个答案:

答案 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])]