2013-06-25 124 views
1

我尝试通过复制xpath规则在声纳(plsql)中编写自定义规则。这条规则的任务是在保存点语句丢失的地方标记“回退到保存点”语句。XPath-1.0:标记相对节点丢失的节点

对于2保存点和3条ROLLBACK语句的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查询,因为保存点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

首先,根据您展示AST,在我看来,这是您要运行在你的XPath查询的PL/SQL代码:当我运行你的第一个XPath查询

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 Toolkit,选择“spB”和“spA”的回滚,但不是“spX”的回滚。

您的第二个XPath查询选择所有这些查询。

在我看来,你只想选择'spX',因为没有相应的保存点。

你的第一个查询琐碎的变化允许逆向选择的节点,通过使用不()否定条件:

//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])] 
+0

谢谢Dinesh。你猜猜PL/SQL代码是否正确(程序是程序包的一部分)。无论如何,你的XPath查询手段很好。但是它并没有在这个“保存点SpA;回滚spA;”上运行,因为与XPath相比,PL/SQL是大案例。 – MintiSE

+0

你是对的@MintiSE,虽然这是可以在纯XPath 1.0中解决的,但我们在SSLR上有一张票,以使它更容易:[SSLR-310](http://jira.sonarsource.com/browse/SSLR-310 ) –

+0

此外,这个规则将被包含在下一个PL/SQL插件版本中,因为它对每个人都是有价值的(不仅仅是你):[PLSQL-443](http://jira.sonarsource.com/browse/) PLSQL-443) –