diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 9b5dad4ce2..1a127710aa 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -31,6 +31,7 @@ This is a minor release. * plsql * [#980](https://github.com/pmd/pmd/issues/980): \[plsql] ParseException for CREATE TABLE * [#981](https://github.com/pmd/pmd/issues/981): \[plsql] ParseException when parsing VIEW + * [#1047](https://github.com/pmd/pmd/issues/1047): \[plsql] ParseException when parsing EXECUTE IMMEDIATE * ui * [#1233](https://github.com/pmd/pmd/issues/1233): \[ui] XPath autocomplete arrows on first and last items diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index 3a3fba733e..0d162e6bec 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -943,7 +943,7 @@ void Skip2NextTerminator(String initiator,String terminator) : t = getToken(1); if(t.image.equals(initiator)) count++; if(t.image.equals(terminator)) count--; - if((null != t.specialToken && beginToken.kind != SELECT && beginToken.kind != INSERT && beginToken.kind != UPDATE && beginToken.kind != DELETE && beginToken.kind != MERGE) || t.kind == EOF) + if((null != t.specialToken && beginToken.kind != SELECT && beginToken.kind != INSERT && beginToken.kind != UPDATE && beginToken.kind != DELETE && beginToken.kind != MERGE && beginToken.kind != EXECUTE) || t.kind == EOF) return; if (t.specialToken != null && "/".equals(t.image)) return; diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/ExecuteImmediateTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/ExecuteImmediateTest.java new file mode 100644 index 0000000000..73f05f107d --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/ExecuteImmediateTest.java @@ -0,0 +1,28 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.ast; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Test; + +import net.sourceforge.pmd.lang.plsql.AbstractPLSQLParserTst; + +public class ExecuteImmediateTest extends AbstractPLSQLParserTst { + + @Test + public void parseExecuteImmediate1047a() throws Exception { + String code = IOUtils.toString(this.getClass().getResourceAsStream("ExecuteImmediate1047a.pls")); + ASTInput input = parsePLSQL(code); + Assert.assertNotNull(input); + } + + @Test + public void parseExecuteImmediate1047b() throws Exception { + String code = IOUtils.toString(this.getClass().getResourceAsStream("ExecuteImmediate1047b.pls")); + ASTInput input = parsePLSQL(code); + Assert.assertNotNull(input); + } +} diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExecuteImmediate1047a.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExecuteImmediate1047a.pls new file mode 100644 index 0000000000..e296bbfe8a --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExecuteImmediate1047a.pls @@ -0,0 +1,14 @@ +-- +-- BSD-style license; for more info see http://pmd.sourceforge.net/license.html +-- + +CREATE OR REPLACE PROCEDURE test ( p_num_reg OUT number ) +AS + v_query clob; +BEGIN + v_query:='select count(1) from test_tbl where id =:param'; + + -- Note: execute immediate statement on multiple lines! + execute immediate v_query into p_num_reg + USING 'P'; +END test; diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExecuteImmediate1047b.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExecuteImmediate1047b.pls new file mode 100644 index 0000000000..ab8e6f2c0e --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExecuteImmediate1047b.pls @@ -0,0 +1,12 @@ +-- +-- BSD-style license; for more info see http://pmd.sourceforge.net/license.html +-- + +CREATE OR REPLACE PROCEDURE test ( p_num_reg OUT number ) +AS + v_query clob; +BEGIN + v_query:='select count(1) from test_tbl where id =:param'; + + execute immediate v_query into p_num_reg USING 'P'; +END test;