From 6458f95c4d51d8f3791e0b5a94e299ddca23e20b Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 23 Sep 2021 19:57:56 +0200 Subject: [PATCH] [plsql] Parsing exception SELECT...INTO on Associative Arrays Types Fixes #3515 --- docs/pages/release_notes.md | 1 + pmd-plsql/etc/grammar/PldocAST.jjt | 5 +- .../pmd/lang/plsql/ast/PlsqlTreeDumpTest.java | 5 + .../pmd/lang/plsql/ast/SelectIntoArray.pls | 22 ++++ .../pmd/lang/plsql/ast/SelectIntoArray.txt | 103 ++++++++++++++++++ 5 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoArray.pls create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoArray.txt diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index cfd61f8fb5..a1589b09ed 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -29,6 +29,7 @@ See [credits](https://pmd.github.io/latest/pmd_projectdocs_credits.html) for our * [#3493](https://github.com/pmd/pmd/pull/3493): \[java] AvoidAccessibilityAlteration: add tests and fix rule * plsql * [#3487](https://github.com/pmd/pmd/issues/3487): \[plsql] Parsing exception OPEN ref_cursor_name FOR statement + * [#3515](https://github.com/pmd/pmd/issues/3515): \[plsql] Parsing exception SELECT...INTO on Associative Arrays Types ### API Changes diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index f6ceeaa92e..3c5656c028 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -2028,10 +2028,13 @@ ASTIntoClause IntoClause() : { return jjtThis; } } +// This might also be a associative array dereference... +// see https://github.com/pmd/pmd/issues/3515 ASTVariableName VariableName() : -{ ASTID id; StringBuilder name = new StringBuilder(); } +{ ASTID id; ASTLiteral lit; StringBuilder name = new StringBuilder(); } { id = ID() { name.append(id.getImage()); } + [ "(" lit = Literal() ")" { name.append('(').append(lit.getImage()).append(')'); } ] [ "." id = ID() { name.append('.').append(id.getImage()); } ] [ "." id = ID() { name.append('.').append(id.getImage()); } ] { diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/PlsqlTreeDumpTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/PlsqlTreeDumpTest.java index 089c16f76a..3a4c1cc8f8 100644 --- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/PlsqlTreeDumpTest.java +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/PlsqlTreeDumpTest.java @@ -36,4 +36,9 @@ public class PlsqlTreeDumpTest extends BaseTreeDumpTest { public void parseOpenForStatement() { doTest("OpenForStatement"); } + + @Test + public void parseSelectIntoAssociativeArrayType() { + doTest("SelectIntoArray"); + } } diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoArray.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoArray.pls new file mode 100644 index 0000000000..b8698f8422 --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoArray.pls @@ -0,0 +1,22 @@ +-- +-- See https://github.com/pmd/pmd/issues/3515 +-- + +CREATE OR REPLACE PROCEDURE EXAMPLE_PROCEDURE IS + -- + TYPE example_data_rt IS RECORD( + field_one PLS_INTEGER, + field_two PLS_INTEGER, + field_three PLS_INTEGER); + -- + TYPE example_data_aat IS TABLE OF example_data_rt INDEX BY BINARY_INTEGER; + -- + l_example_data example_data_aat; + -- +BEGIN + -- + SELECT 1 field_value_one, 2 field_value_two, 3 field_value_three + INTO l_example_data(1).field_one,l_example_data(1).field_two,l_example_data(1).field_three + FROM DUAL; + -- +END EXAMPLE_PROCEDURE; diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoArray.txt b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoArray.txt new file mode 100644 index 0000000000..2709539e5e --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoArray.txt @@ -0,0 +1,103 @@ ++- Input[@CanonicalImage = null, @ExcludedLinesCount = 0, @ExcludedRangesCount = 0, @Sourcecode = "-- +-- See https://github.com/pmd/pmd/issues/3515 +-- + +CREATE OR REPLACE PROCEDURE EXAMPLE_PROCEDURE IS + -- + TYPE example_data_rt IS RECORD( + field_one PLS_INTEGER, + field_two PLS_INTEGER, + field_three PLS_INTEGER); + -- + TYPE example_data_aat IS TABLE OF example_data_rt INDEX BY BINARY_INTEGER; + -- + l_example_data example_data_aat; + -- +BEGIN + -- + SELECT 1 field_value_one, 2 field_value_two, 3 field_value_three + INTO l_example_data(1).field_one,l_example_data(1).field_two,l_example_data(1).field_three + FROM DUAL; + -- +END EXAMPLE_PROCEDURE; +"] + +- Global[@CanonicalImage = null] + +- ProgramUnit[@CanonicalImage = null, @MethodName = "EXAMPLE_PROCEDURE", @Name = "EXAMPLE_PROCEDURE", @ObjectName = null] + +- MethodDeclarator[@CanonicalImage = "EXAMPLE_PROCEDURE", @Image = "EXAMPLE_PROCEDURE", @ParameterCount = 1] + | +- ObjectNameDeclaration[@CanonicalImage = "EXAMPLE_PROCEDURE", @Image = "EXAMPLE_PROCEDURE"] + | +- ID[@CanonicalImage = "EXAMPLE_PROCEDURE", @Image = "EXAMPLE_PROCEDURE"] + +- DeclarativeSection[@CanonicalImage = null] + | +- DeclarativeUnit[@CanonicalImage = null] + | | +- SubTypeDefinition[@CanonicalImage = "EXAMPLE_DATA_RT", @Image = "example_data_rt"] + | | +- QualifiedID[@CanonicalImage = "EXAMPLE_DATA_RT", @Image = "example_data_rt"] + | | +- FieldDeclaration[@CanonicalImage = "FIELD_ONE", @Image = "field_one"] + | | | +- ID[@CanonicalImage = "FIELD_ONE", @Image = "field_one"] + | | | +- Datatype[@CanonicalImage = "PLS_INTEGER", @Image = "PLS_INTEGER", @TypeImage = "PLS_INTEGER"] + | | | +- ScalarDataTypeName[@CanonicalImage = "PLS_INTEGER", @Image = "PLS_INTEGER"] + | | +- FieldDeclaration[@CanonicalImage = "FIELD_TWO", @Image = "field_two"] + | | | +- ID[@CanonicalImage = "FIELD_TWO", @Image = "field_two"] + | | | +- Datatype[@CanonicalImage = "PLS_INTEGER", @Image = "PLS_INTEGER", @TypeImage = "PLS_INTEGER"] + | | | +- ScalarDataTypeName[@CanonicalImage = "PLS_INTEGER", @Image = "PLS_INTEGER"] + | | +- FieldDeclaration[@CanonicalImage = "FIELD_THREE", @Image = "field_three"] + | | +- ID[@CanonicalImage = "FIELD_THREE", @Image = "field_three"] + | | +- Datatype[@CanonicalImage = "PLS_INTEGER", @Image = "PLS_INTEGER", @TypeImage = "PLS_INTEGER"] + | | +- ScalarDataTypeName[@CanonicalImage = "PLS_INTEGER", @Image = "PLS_INTEGER"] + | +- DeclarativeUnit[@CanonicalImage = null] + | | +- SubTypeDefinition[@CanonicalImage = "EXAMPLE_DATA_AAT", @Image = "example_data_aat"] + | | +- QualifiedID[@CanonicalImage = "EXAMPLE_DATA_AAT", @Image = "example_data_aat"] + | | +- Datatype[@CanonicalImage = "EXAMPLE_DATA_RT", @Image = "example_data_rt", @TypeImage = "example_data_rt"] + | | | +- QualifiedName[@CanonicalImage = "EXAMPLE_DATA_RT", @Image = "example_data_rt"] + | | | +- UnqualifiedID[@CanonicalImage = "EXAMPLE_DATA_RT", @Image = "example_data_rt"] + | | +- Datatype[@CanonicalImage = "BINARY_INTEGER", @Image = "BINARY_INTEGER", @TypeImage = "BINARY_INTEGER"] + | | +- ScalarDataTypeName[@CanonicalImage = "BINARY_INTEGER", @Image = "BINARY_INTEGER"] + | +- DeclarativeUnit[@CanonicalImage = null] + | +- VariableOrConstantDeclaration[@CanonicalImage = null] + | +- VariableOrConstantDeclarator[@CanonicalImage = "L_EXAMPLE_DATA EXAMPLE_DATA_AAT", @Image = "l_example_data example_data_aat"] + | +- VariableOrConstantDeclaratorId[@Array = false, @ArrayDepth = 0, @CanonicalImage = "L_EXAMPLE_DATA", @Image = "l_example_data"] + | | +- ID[@CanonicalImage = "L_EXAMPLE_DATA", @Image = "l_example_data"] + | +- Datatype[@CanonicalImage = "EXAMPLE_DATA_AAT", @Image = "example_data_aat", @TypeImage = "example_data_aat"] + | +- QualifiedName[@CanonicalImage = "EXAMPLE_DATA_AAT", @Image = "example_data_aat"] + | +- UnqualifiedID[@CanonicalImage = "EXAMPLE_DATA_AAT", @Image = "example_data_aat"] + +- Statement[@CanonicalImage = null] + | +- UnlabelledStatement[@CanonicalImage = null] + | +- SelectIntoStatement[@All = false, @CanonicalImage = null, @Distinct = false, @Unique = false] + | +- SelectList[@CanonicalImage = null] + | | +- SqlExpression[@CanonicalImage = "1", @Image = "1"] + | | | +- PrimaryPrefix[@CanonicalImage = "1", @Image = "1", @SelfModifier = false] + | | | +- Literal[@CanonicalImage = "1", @Image = "1"] + | | | +- NumericLiteral[@CanonicalImage = "1", @Image = "1"] + | | +- ColumnAlias[@CanonicalImage = "FIELD_VALUE_ONE", @Image = "field_value_one"] + | | | +- ID[@CanonicalImage = "FIELD_VALUE_ONE", @Image = "field_value_one"] + | | +- SqlExpression[@CanonicalImage = "2", @Image = "2"] + | | | +- PrimaryPrefix[@CanonicalImage = "2", @Image = "2", @SelfModifier = false] + | | | +- Literal[@CanonicalImage = "2", @Image = "2"] + | | | +- NumericLiteral[@CanonicalImage = "2", @Image = "2"] + | | +- ColumnAlias[@CanonicalImage = "FIELD_VALUE_TWO", @Image = "field_value_two"] + | | | +- ID[@CanonicalImage = "FIELD_VALUE_TWO", @Image = "field_value_two"] + | | +- SqlExpression[@CanonicalImage = "3", @Image = "3"] + | | | +- PrimaryPrefix[@CanonicalImage = "3", @Image = "3", @SelfModifier = false] + | | | +- Literal[@CanonicalImage = "3", @Image = "3"] + | | | +- NumericLiteral[@CanonicalImage = "3", @Image = "3"] + | | +- ColumnAlias[@CanonicalImage = "FIELD_VALUE_THREE", @Image = "field_value_three"] + | | +- ID[@CanonicalImage = "FIELD_VALUE_THREE", @Image = "field_value_three"] + | +- IntoClause[@CanonicalImage = null] + | | +- VariableName[@CanonicalImage = "L_EXAMPLE_DATA(1).FIELD_ONE", @Image = "l_example_data(1).field_one"] + | | | +- ID[@CanonicalImage = "L_EXAMPLE_DATA", @Image = "l_example_data"] + | | | +- Literal[@CanonicalImage = "1", @Image = "1"] + | | | | +- NumericLiteral[@CanonicalImage = "1", @Image = "1"] + | | | +- ID[@CanonicalImage = "FIELD_ONE", @Image = "field_one"] + | | +- VariableName[@CanonicalImage = "L_EXAMPLE_DATA(1).FIELD_TWO", @Image = "l_example_data(1).field_two"] + | | | +- ID[@CanonicalImage = "L_EXAMPLE_DATA", @Image = "l_example_data"] + | | | +- Literal[@CanonicalImage = "1", @Image = "1"] + | | | | +- NumericLiteral[@CanonicalImage = "1", @Image = "1"] + | | | +- ID[@CanonicalImage = "FIELD_TWO", @Image = "field_two"] + | | +- VariableName[@CanonicalImage = "L_EXAMPLE_DATA(1).FIELD_THREE", @Image = "l_example_data(1).field_three"] + | | +- ID[@CanonicalImage = "L_EXAMPLE_DATA", @Image = "l_example_data"] + | | +- Literal[@CanonicalImage = "1", @Image = "1"] + | | | +- NumericLiteral[@CanonicalImage = "1", @Image = "1"] + | | +- ID[@CanonicalImage = "FIELD_THREE", @Image = "field_three"] + | +- FromClause[@CanonicalImage = null] + | +- TableReference[@CanonicalImage = null] + | +- TableName[@CanonicalImage = "DUAL", @Image = "DUAL"] + | +- ID[@CanonicalImage = "DUAL", @Image = "DUAL"] + +- ID[@CanonicalImage = "EXAMPLE_PROCEDURE", @Image = "EXAMPLE_PROCEDURE"]