1

我尝试通过复制 xpath 规则在声纳(plsql)中编写自定义规则。此规则的任务是在缺少保存点语句的地方标记“回滚到保存点”语句。

对于 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 查询,因为缺少保存点 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 节点。我认为所有回滚的名称都会与第一个保存点的名称一致?

4

1 回答 1

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 Toolkit 运行您的第一个 XPath 查询时,选择了回滚到“spB”和“spA”,但没有选择回滚到“spX”。

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

在我看来,您只想选择“spX”之一,因为没有相应的保存点。

通过使用 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])]
于 2013-06-27T08:13:54.773 回答