Fixes #1520 [plsql] Missing PL/SQL language constructs in parser: Is Of Type, Using

This commit is contained in:
Andreas Dangel
2016-11-04 16:10:07 +01:00
parent a9d0de9450
commit 4ab1d0cbee
7 changed files with 83 additions and 2 deletions

View File

@ -27,6 +27,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/**
* Added ASTIsOfTypeCondition node, added support for USING IN|OUT|IN_OUT
* See PMD Bug #1520
*
* Andreas Dangel 11/2016
*====================================================================
* Adjusted ProgramUnit() to allow Pragma(), even though this is not
* valid syntax. See PMD Bug #1527.
*
@ -1368,7 +1373,7 @@ ASTOpenStatement OpenStatement() :
{
<OPEN> [Expression()]
//[LOOKAHEAD(functionCall()) functionCall() | QualifiedName()]
[<FOR> Expression() [<USING> Expression() ("," Expression())*]]
[<FOR> Expression() [<USING> (<IN> | <OUT> | <IN_OUT>)? Expression() ("," (<IN> | <OUT> | <IN_OUT>)? Expression())*]]
{ return jjtThis ; }
}
@ -1966,6 +1971,21 @@ ASTUnaryExpressionNotPlusMinus UnaryExpressionNotPlusMinus() :
(
(<NOT>) {sb.append(" NOT "); }
(simpleNode = UnaryExpression(false) ) { sb.append(simpleNode.getImage()); }
|
(simpleNode = IsOfTypeCondition() ) {sb.append(simpleNode.getImage()); }
)
{
jjtThis.setImage(sb.toString()); return jjtThis;
}
}
ASTIsOfTypeCondition IsOfTypeCondition() :
{ PLSQLNode simpleNode = null; PLSQLNode name = null; StringBuilder sb = new StringBuilder(); }
{
(
LOOKAHEAD(<IDENTIFIER> <IS>)
((name = Name()) {sb.append(name.getImage());} <IS> {sb.append(" IS");} [<NOT> {sb.append(" NOT");}] <OF> {sb.append(" OF");} [<TYPE>]
"(" [<ONLY>] Name() ("," [<ONLY>] Name() )* ")")
|
(simpleNode = PrimaryExpression() ) { sb.append(simpleNode.getImage()); }
)
@ -3248,6 +3268,7 @@ TOKEN [IGNORE_CASE]:
* Added: <MERGE: "MERGE">, <AFTER: "AFTER">, <BEFORE: "BEFORE">,
* <INSTEADOF: "INSTEAD OF">, <FOREACHROW: "FOR EACH ROW">, <REFERENCING: "REFERENCING">,
* <OLD: "OLD">, <PARENT: "PARENT">
* 2016-11-04 - Andreas Dangel - Added <ONLY: "ONLY">, <IN_OUT: "IN_OUT">
*/
TOKEN [IGNORE_CASE]:
@ -3347,6 +3368,7 @@ TOKEN [IGNORE_CASE]:
<IF: "IF"> |
<IMMEDIATE: "IMMEDIATE"> |
<IN: "IN"> |
<IN_OUT: "IN_OUT"> |
<INDEX: "INDEX"> |
<INDICES: "INDICES"> |
<INCLUDING: "INCLUDING"> |
@ -3408,6 +3430,7 @@ TOKEN [IGNORE_CASE]:
<OF: "OF"> |
<OID: "OID"> |
<ON: "ON"> |
<ONLY: "ONLY"> |
<OPAQUE: "OPAQUE"> |
<OPEN: "OPEN"> |
<OPERATOR: "OPERATOR"> |

View File

@ -690,4 +690,8 @@ public class PLSQLParserVisitorAdapter implements PLSQLParserVisitor {
return visit((PLSQLNode) node, data);
}
@Override
public Object visit(ASTIsOfTypeCondition node, Object data) {
return visit((PLSQLNode) node, data);
}
}

View File

@ -784,6 +784,10 @@ public abstract class AbstractPLSQLRule extends AbstractRule implements PLSQLPar
public Object visit(ASTAccessibleByClause node, Object data) {
return visit((PLSQLNode) node, data);
}
@Override
public Object visit(ASTIsOfTypeCondition node, Object data) {
return visit((PLSQLNode) node, data);
}
/*
* Treat all Executable Code

View File

@ -50,4 +50,14 @@ public class PLSQLParserTest extends AbstractPLSQLParserTst {
public void testBug1527() throws Exception {
parsePLSQL(IOUtils.toString(PLSQLParserTest.class.getResourceAsStream("ast/InlinePragmaProcError.pls")));
}
@Test
public void testBug1520IsOfType() throws Exception {
parsePLSQL(IOUtils.toString(PLSQLParserTest.class.getResourceAsStream("ast/IsOfType.pls")));
}
@Test
public void testBug1520Using() throws Exception {
parsePLSQL(IOUtils.toString(PLSQLParserTest.class.getResourceAsStream("ast/Using.pls")));
}
}

View File

@ -0,0 +1,23 @@
PROCEDURE IsOfType (
inChannelID IN number,
inOperID IN number,
inClientId IN number,
ioFPOobj IN FPO_OBJ,
inPackageIDout IN number,
inStatusId IN number)
is
loFPOGE_OBJ FPOGE_OBJ;
BEGIN
IF ioFPOobj IS OF (FPOGE_OBJ) THEN
loFPOGE_OBJ:=treat(ioFPOobj AS FPOGE_OBJ);
end if;
IF ioFPOobj IS NOT OF TYPE (ONLY FPOGE_OBJ) THEN
loFPOGE_OBJ:=treat(ioFPOobj AS FPOGE_OBJ);
end if;
loFPOGE_OBJ:=SELECT A FROM persons p WHERE IS OF TYPE (employee_t);
loFPOGE_OBJ:=SELECT A FROM persons p WHERE IS NOT OF TYPE (ONLY employee_t, other_t);
end;

View File

@ -0,0 +1,16 @@
/*
* From: https://docs.oracle.com/cd/B13789_01/appdev.101/b10807/13_elems034.htm
*/
DECLARE
TYPE EmpCurTyp IS REF CURSOR; -- define weak REF CURSOR type
emp_cv EmpCurTyp; -- declare cursor variable
my_ename VARCHAR2(15);
my_sal NUMBER := 1000;
BEGIN
OPEN emp_cv FOR -- open cursor variable
'SELECT ename, sal FROM emp WHERE sal > :s' USING my_sal;
open cursor for 'query' USING variable;
open cursor for 'query' USING IN variable;
open cursor for 'query' USING OUT variable, IN othervariable;
open cursor for 'query' USING IN_OUT variable;
END;

View File

@ -41,6 +41,7 @@
* java-unusedcode/UnusedModifier
* [#1480](https://sourceforge.net/p/pmd/bugs/1480/): false positive on public modifier used with inner interface in enum
* PLSQL
* [#1520](https://sourceforge.net/p/pmd/bugs/1520/): \[plsql] Missing PL/SQL language constructs in parser: Is Of Type, Using
* [#1527](https://sourceforge.net/p/pmd/bugs/1527/): \[plsql] PRAGMA AUTONOMOUS_TRANSACTION gives processing errors
* [#1531](https://sourceforge.net/p/pmd/bugs/1531/): \[plsql] OOM/Endless loop while parsing (PL)SQL
* General