diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 6e612e8f5f..430b3960bf 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -83,6 +83,7 @@ This is a {{ site.pmd.release_type }} release. * [#1511](https://github.com/pmd/pmd/issues/1511): \[plsql] Parse Exception with IS NOT NULL * [#1583](https://github.com/pmd/pmd/issues/1583): \[plsql] Update Set Clause should allow multiple columns * [#1586](https://github.com/pmd/pmd/issues/1586): \[plsql] Parse Exception when functions are used with LIKE + * [#1588](https://github.com/pmd/pmd/issues/1588): \[plsql] Parse Exception with function calls in WHERE clause ### API Changes diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index 066a9eab8a..551393e182 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -1414,16 +1414,38 @@ ASTSqlExpression SqlExpression() : | LOOKAHEAD(2) | - LOOKAHEAD(2) AdditiveExpression() // this can be a literal or a simple expression, but no conditional + AdditiveExpression() // this can be a literal or a simple expression, but no conditional ) { return jjtThis; } } +/** + * See also https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/About-User-Defined-Functions.html#GUID-4EB3E236-8216-471C-BA44-23D87BDFEA67 + * + * A function reference might be: + * function_name + * package.function_name + * package.schema.function_name + * optional: @ dblink . + */ ASTFunctionCall FunctionCall() : -{ ASTID id; } { - id = ID() { jjtThis.setImage(id.getImage()); } Arguments() - { return jjtThis; } + ASTID id; + StringBuilder name = new StringBuilder(); +} +{ + id = ID() { name.append(id.getImage()); } + [ "." id = ID() { name.append('.').append(id.getImage()); } + [ "." id = ID() { name.append('.').append(id.getImage()); } ] + ] + [ "@" id = ID() { name.append('@').append(id.getImage()); } ] + + Arguments() + + { + jjtThis.setImage(name.toString()); + return jjtThis; + } } ASTColumn Column() : diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/WhereClauseTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/WhereClauseTest.java index 3ccfd30b0c..18d549472a 100644 --- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/WhereClauseTest.java +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/WhereClauseTest.java @@ -5,8 +5,10 @@ package net.sourceforge.pmd.lang.plsql.ast; import java.nio.charset.StandardCharsets; +import java.util.List; import org.apache.commons.io.IOUtils; +import org.junit.Assert; import org.junit.Test; import net.sourceforge.pmd.lang.plsql.AbstractPLSQLParserTst; @@ -18,6 +20,11 @@ public class WhereClauseTest extends AbstractPLSQLParserTst { String code = IOUtils.toString(this.getClass().getResourceAsStream("WhereClauseFunctionCall.pls"), StandardCharsets.UTF_8); ASTInput input = parsePLSQL(code); + List selectStatements = input.findDescendantsOfType(ASTSelectIntoStatement.class); + Assert.assertEquals(3, selectStatements.size()); + + ASTFunctionCall functionCall = selectStatements.get(2).getFirstDescendantOfType(ASTFunctionCall.class); + Assert.assertEquals("utils.get_colname", functionCall.getImage()); } @Test diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/WhereClauseFunctionCall.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/WhereClauseFunctionCall.pls index e2513cfe27..c777b1747c 100644 --- a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/WhereClauseFunctionCall.pls +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/WhereClauseFunctionCall.pls @@ -16,5 +16,10 @@ BEGIN OR rgn.cny_code = street_cny_code_in) AND UPPER(rgn.name) = UPPER(street_rgn_in); + SELECT value + INTO v_value + FROM table + WHERE colname = utils.get_colname('COLUMN_ID'); + END; /