parent
28c6c8e121
commit
d47ca10029
@ -15,6 +15,8 @@ This is a {{ site.pmd.release_type }} release.
|
||||
### 🚀 New and noteworthy
|
||||
|
||||
### 🐛 Fixed Issues
|
||||
* plsql
|
||||
* [#2779](https://github.com/pmd/pmd/issues/2779): \[plsql] Error while parsing statement with (Oracle) DML Error Logging
|
||||
|
||||
### 🚨 API Changes
|
||||
|
||||
|
@ -27,6 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
/**
|
||||
* Add support Error Logging for INSERT, UPDATE, DELETE
|
||||
*
|
||||
* Andreas Dangel 06/2024
|
||||
*====================================================================
|
||||
* Add support for Select statement within OPEN FOR Statements
|
||||
*
|
||||
* Andreas Dangel 09/2021
|
||||
@ -2087,7 +2091,7 @@ ASTTableReference TableReference() :
|
||||
{
|
||||
QueryTableExpression()
|
||||
|
||||
[ LOOKAHEAD(2) TableAlias() ]
|
||||
[ LOOKAHEAD(2, {!getToken(1).getImage().equalsIgnoreCase("LOG")}) TableAlias() ]
|
||||
|
||||
{ return jjtThis; }
|
||||
}
|
||||
@ -2457,7 +2461,7 @@ ASTCursorForLoopStatement CursorForLoopStatement() :
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423
|
||||
* https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423
|
||||
*/
|
||||
ASTInsertStatement InsertStatement() :
|
||||
{}
|
||||
@ -2470,6 +2474,7 @@ ASTSingleTableInsert SingleTableInsert() :
|
||||
{}
|
||||
{
|
||||
InsertIntoClause() ( ValuesClause() [ ReturningClause() ] | Subquery() )
|
||||
[ ErrorLoggingClause() ]
|
||||
{ return jjtThis; }
|
||||
}
|
||||
|
||||
@ -2622,7 +2627,8 @@ ASTUpdateSetClause UpdateSetClause() :
|
||||
}
|
||||
|
||||
/**
|
||||
* https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/UPDATE.html#GUID-027A462D-379D-4E35-8611-410F3AC8FDA5__I2126358
|
||||
* https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/UPDATE.html#GUID-027A462D-379D-4E35-8611-410F3AC8FDA5__I2126358
|
||||
* https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/DELETE.html#GUID-156845A5-B626-412B-9F95-8869B988ABD7__I2122564
|
||||
*/
|
||||
ASTReturningClause ReturningClause() :
|
||||
{}
|
||||
@ -2632,7 +2638,9 @@ ASTReturningClause ReturningClause() :
|
||||
}
|
||||
|
||||
/**
|
||||
* https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/UPDATE.html#GUID-027A462D-379D-4E35-8611-410F3AC8FDA5__BCEEAAGC
|
||||
* https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__BGBDIGAH
|
||||
* https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/UPDATE.html#GUID-027A462D-379D-4E35-8611-410F3AC8FDA5__BCEEAAGC
|
||||
* https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/DELETE.html#GUID-156845A5-B626-412B-9F95-8869B988ABD7__CEGCHDJF
|
||||
*/
|
||||
ASTErrorLoggingClause ErrorLoggingClause() :
|
||||
{}
|
||||
@ -2645,12 +2653,17 @@ ASTErrorLoggingClause ErrorLoggingClause() :
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/DELETE.html#GUID-156845A5-B626-412B-9F95-8869B988ABD7
|
||||
*/
|
||||
ASTDeleteStatement DeleteStatement() :
|
||||
{}
|
||||
{
|
||||
<DELETE> [ <FROM> ]
|
||||
( TableReference() | <ONLY> "(" TableReference() ")" )
|
||||
[ WhereClause() ]
|
||||
[ ReturningClause() ]
|
||||
[ ErrorLoggingClause() ]
|
||||
{ return jjtThis; }
|
||||
}
|
||||
|
||||
|
@ -41,4 +41,9 @@ class PlsqlTreeDumpTest extends BaseTreeDumpTest {
|
||||
void parseSelectIntoAssociativeArrayType() {
|
||||
doTest("SelectIntoArray");
|
||||
}
|
||||
|
||||
@Test
|
||||
void errorLoggingClause() {
|
||||
doTest("ErrorLoggingClause2779");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
--
|
||||
-- BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
--
|
||||
|
||||
create or replace procedure test as
|
||||
begin
|
||||
|
||||
-- https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__BCEGDJDJ
|
||||
INSERT INTO raises
|
||||
SELECT employee_id, salary*1.1 FROM employees
|
||||
WHERE commission_pct > .2
|
||||
LOG ERRORS INTO errlog ('my_bad') REJECT LIMIT 10;
|
||||
|
||||
-- https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/UPDATE.html#GUID-027A462D-379D-4E35-8611-410F3AC8FDA5__I2135485
|
||||
UPDATE people_demo1 p SET VALUE(p) =
|
||||
(SELECT VALUE(q) FROM people_demo2 q
|
||||
WHERE p.department_id = q.department_id)
|
||||
WHERE p.department_id = 10
|
||||
LOG ERRORS INTO errlog ('my_bad') REJECT LIMIT 10;
|
||||
|
||||
-- https://github.com/pmd/pmd/issues/2779
|
||||
delete from test_table talias
|
||||
log errors into err$_test_table reject limit unlimited;
|
||||
|
||||
-- without a table alias
|
||||
delete from test_table
|
||||
log errors into err$_test_table reject limit unlimited;
|
||||
end;
|
||||
/
|
@ -0,0 +1,149 @@
|
||||
+- Input[@CanonicalImage = null, @ExcludedLinesCount = 0, @ExcludedRangesCount = 0]
|
||||
+- Global[@CanonicalImage = null]
|
||||
+- ProgramUnit[@CanonicalImage = null, @MethodName = "test", @Name = "test", @ObjectName = null]
|
||||
+- MethodDeclarator[@CanonicalImage = "TEST", @Image = "test", @ParameterCount = 1]
|
||||
| +- ObjectNameDeclaration[@CanonicalImage = "TEST", @Image = "test"]
|
||||
| +- ID[@CanonicalImage = "TEST", @Image = "test"]
|
||||
+- DeclarativeSection[@CanonicalImage = null]
|
||||
+- Statement[@CanonicalImage = null]
|
||||
| +- UnlabelledStatement[@CanonicalImage = null]
|
||||
| +- InsertStatement[@CanonicalImage = null]
|
||||
| +- SingleTableInsert[@CanonicalImage = null]
|
||||
| +- InsertIntoClause[@CanonicalImage = null]
|
||||
| | +- DMLTableExpressionClause[@CanonicalImage = null]
|
||||
| | +- TableName[@CanonicalImage = "RAISES", @Image = "raises"]
|
||||
| | +- ID[@CanonicalImage = "RAISES", @Image = "raises"]
|
||||
| +- QueryBlock[@All = false, @CanonicalImage = null, @Distinct = false, @Unique = false]
|
||||
| | +- SelectList[@CanonicalImage = null]
|
||||
| | | +- SqlExpression[@CanonicalImage = "EMPLOYEE_ID", @Image = "employee_id"]
|
||||
| | | | +- PrimaryPrefix[@CanonicalImage = "EMPLOYEE_ID", @Image = "employee_id", @SelfModifier = false]
|
||||
| | | | +- SimpleExpression[@CanonicalImage = "EMPLOYEE_ID", @Image = "employee_id"]
|
||||
| | | | +- Column[@CanonicalImage = "EMPLOYEE_ID", @Image = "employee_id"]
|
||||
| | | | +- ID[@CanonicalImage = "EMPLOYEE_ID", @Image = "employee_id"]
|
||||
| | | +- SqlExpression[@CanonicalImage = "SALARY * 1.1", @Image = "salary * 1.1"]
|
||||
| | | +- MultiplicativeExpression[@CanonicalImage = "SALARY * 1.1", @Image = "salary * 1.1"]
|
||||
| | | +- PrimaryPrefix[@CanonicalImage = "SALARY", @Image = "salary", @SelfModifier = false]
|
||||
| | | | +- SimpleExpression[@CanonicalImage = "SALARY", @Image = "salary"]
|
||||
| | | | +- Column[@CanonicalImage = "SALARY", @Image = "salary"]
|
||||
| | | | +- ID[@CanonicalImage = "SALARY", @Image = "salary"]
|
||||
| | | +- PrimaryPrefix[@CanonicalImage = "1.1", @Image = "1.1", @SelfModifier = false]
|
||||
| | | +- Literal[@CanonicalImage = "1.1", @Image = "1.1"]
|
||||
| | | +- NumericLiteral[@CanonicalImage = "1.1", @Image = "1.1"]
|
||||
| | +- FromClause[@CanonicalImage = null]
|
||||
| | | +- TableReference[@CanonicalImage = null]
|
||||
| | | +- TableName[@CanonicalImage = "EMPLOYEES", @Image = "employees"]
|
||||
| | | +- ID[@CanonicalImage = "EMPLOYEES", @Image = "employees"]
|
||||
| | +- WhereClause[@CanonicalImage = null]
|
||||
| | +- Condition[@CanonicalImage = null]
|
||||
| | +- CompoundCondition[@CanonicalImage = null, @Type = null]
|
||||
| | +- ComparisonCondition[@CanonicalImage = null, @Operator = ">"]
|
||||
| | +- SqlExpression[@CanonicalImage = "COMMISSION_PCT", @Image = "commission_pct"]
|
||||
| | | +- PrimaryPrefix[@CanonicalImage = "COMMISSION_PCT", @Image = "commission_pct", @SelfModifier = false]
|
||||
| | | +- SimpleExpression[@CanonicalImage = "COMMISSION_PCT", @Image = "commission_pct"]
|
||||
| | | +- Column[@CanonicalImage = "COMMISSION_PCT", @Image = "commission_pct"]
|
||||
| | | +- ID[@CanonicalImage = "COMMISSION_PCT", @Image = "commission_pct"]
|
||||
| | +- SqlExpression[@CanonicalImage = ".2", @Image = ".2"]
|
||||
| | +- PrimaryPrefix[@CanonicalImage = ".2", @Image = ".2", @SelfModifier = false]
|
||||
| | +- Literal[@CanonicalImage = ".2", @Image = ".2"]
|
||||
| | +- NumericLiteral[@CanonicalImage = ".2", @Image = ".2"]
|
||||
| +- ErrorLoggingClause[@CanonicalImage = null]
|
||||
| +- TableName[@CanonicalImage = "ERRLOG", @Image = "errlog"]
|
||||
| | +- ID[@CanonicalImage = "ERRLOG", @Image = "errlog"]
|
||||
| +- SqlExpression[@CanonicalImage = "\'MY_BAD\'", @Image = "\'my_bad\'"]
|
||||
| | +- PrimaryPrefix[@CanonicalImage = "\'MY_BAD\'", @Image = "\'my_bad\'", @SelfModifier = false]
|
||||
| | +- Literal[@CanonicalImage = "\'MY_BAD\'", @Image = "\'my_bad\'"]
|
||||
| | +- StringLiteral[@CanonicalImage = "\'MY_BAD\'", @Image = "\'my_bad\'", @String = "my_bad"]
|
||||
| +- NumericLiteral[@CanonicalImage = "10", @Image = "10"]
|
||||
+- Statement[@CanonicalImage = null]
|
||||
| +- UnlabelledStatement[@CanonicalImage = null]
|
||||
| +- UpdateStatement[@CanonicalImage = null]
|
||||
| +- DMLTableExpressionClause[@CanonicalImage = null]
|
||||
| | +- TableName[@CanonicalImage = "PEOPLE_DEMO1", @Image = "people_demo1"]
|
||||
| | +- ID[@CanonicalImage = "PEOPLE_DEMO1", @Image = "people_demo1"]
|
||||
| +- TableAlias[@CanonicalImage = "P", @Image = "p"]
|
||||
| | +- ID[@CanonicalImage = "P", @Image = "p"]
|
||||
| +- UpdateSetClause[@CanonicalImage = null]
|
||||
| | +- TableAlias[@CanonicalImage = "P", @Image = "p"]
|
||||
| | | +- ID[@CanonicalImage = "P", @Image = "p"]
|
||||
| | +- QueryBlock[@All = false, @CanonicalImage = null, @Distinct = false, @Unique = false]
|
||||
| | +- SelectList[@CanonicalImage = null]
|
||||
| | | +- SqlExpression[@CanonicalImage = "VALUE", @Image = "VALUE"]
|
||||
| | | +- PrimaryPrefix[@CanonicalImage = "VALUE", @Image = "VALUE", @SelfModifier = false]
|
||||
| | | +- FunctionCall[@CanonicalImage = "VALUE", @Image = "VALUE"]
|
||||
| | | +- FunctionName[@CanonicalImage = "VALUE", @Image = "VALUE"]
|
||||
| | | | +- ID[@CanonicalImage = "VALUE", @Image = "VALUE"]
|
||||
| | | +- Arguments[@ArgumentCount = 1, @CanonicalImage = null]
|
||||
| | | +- ArgumentList[@CanonicalImage = null]
|
||||
| | | +- Argument[@CanonicalImage = null]
|
||||
| | | +- Expression[@CanonicalImage = "Q", @Image = "q"]
|
||||
| | | +- PrimaryPrefix[@CanonicalImage = "Q", @Image = "q", @SelfModifier = false]
|
||||
| | | +- SimpleExpression[@CanonicalImage = "Q", @Image = "q"]
|
||||
| | | +- Column[@CanonicalImage = "Q", @Image = "q"]
|
||||
| | | +- ID[@CanonicalImage = "Q", @Image = "q"]
|
||||
| | +- FromClause[@CanonicalImage = null]
|
||||
| | | +- TableReference[@CanonicalImage = null]
|
||||
| | | +- TableName[@CanonicalImage = "PEOPLE_DEMO2", @Image = "people_demo2"]
|
||||
| | | | +- ID[@CanonicalImage = "PEOPLE_DEMO2", @Image = "people_demo2"]
|
||||
| | | +- TableAlias[@CanonicalImage = "Q", @Image = "q"]
|
||||
| | | +- ID[@CanonicalImage = "Q", @Image = "q"]
|
||||
| | +- WhereClause[@CanonicalImage = null]
|
||||
| | +- Condition[@CanonicalImage = null]
|
||||
| | +- CompoundCondition[@CanonicalImage = null, @Type = null]
|
||||
| | +- ComparisonCondition[@CanonicalImage = null, @Operator = "="]
|
||||
| | +- SqlExpression[@CanonicalImage = "P.DEPARTMENT_ID", @Image = "p.department_id"]
|
||||
| | | +- PrimaryPrefix[@CanonicalImage = "P.DEPARTMENT_ID", @Image = "p.department_id", @SelfModifier = false]
|
||||
| | | +- SimpleExpression[@CanonicalImage = "P.DEPARTMENT_ID", @Image = "p.department_id"]
|
||||
| | | +- TableName[@CanonicalImage = "P", @Image = "p"]
|
||||
| | | | +- ID[@CanonicalImage = "P", @Image = "p"]
|
||||
| | | +- Column[@CanonicalImage = "DEPARTMENT_ID", @Image = "department_id"]
|
||||
| | | +- ID[@CanonicalImage = "DEPARTMENT_ID", @Image = "department_id"]
|
||||
| | +- SqlExpression[@CanonicalImage = "Q.DEPARTMENT_ID", @Image = "q.department_id"]
|
||||
| | +- PrimaryPrefix[@CanonicalImage = "Q.DEPARTMENT_ID", @Image = "q.department_id", @SelfModifier = false]
|
||||
| | +- SimpleExpression[@CanonicalImage = "Q.DEPARTMENT_ID", @Image = "q.department_id"]
|
||||
| | +- TableName[@CanonicalImage = "Q", @Image = "q"]
|
||||
| | | +- ID[@CanonicalImage = "Q", @Image = "q"]
|
||||
| | +- Column[@CanonicalImage = "DEPARTMENT_ID", @Image = "department_id"]
|
||||
| | +- ID[@CanonicalImage = "DEPARTMENT_ID", @Image = "department_id"]
|
||||
| +- WhereClause[@CanonicalImage = null]
|
||||
| | +- Condition[@CanonicalImage = null]
|
||||
| | +- CompoundCondition[@CanonicalImage = null, @Type = null]
|
||||
| | +- ComparisonCondition[@CanonicalImage = null, @Operator = "="]
|
||||
| | +- SqlExpression[@CanonicalImage = "P.DEPARTMENT_ID", @Image = "p.department_id"]
|
||||
| | | +- PrimaryPrefix[@CanonicalImage = "P.DEPARTMENT_ID", @Image = "p.department_id", @SelfModifier = false]
|
||||
| | | +- SimpleExpression[@CanonicalImage = "P.DEPARTMENT_ID", @Image = "p.department_id"]
|
||||
| | | +- TableName[@CanonicalImage = "P", @Image = "p"]
|
||||
| | | | +- ID[@CanonicalImage = "P", @Image = "p"]
|
||||
| | | +- Column[@CanonicalImage = "DEPARTMENT_ID", @Image = "department_id"]
|
||||
| | | +- ID[@CanonicalImage = "DEPARTMENT_ID", @Image = "department_id"]
|
||||
| | +- SqlExpression[@CanonicalImage = "10", @Image = "10"]
|
||||
| | +- PrimaryPrefix[@CanonicalImage = "10", @Image = "10", @SelfModifier = false]
|
||||
| | +- Literal[@CanonicalImage = "10", @Image = "10"]
|
||||
| | +- NumericLiteral[@CanonicalImage = "10", @Image = "10"]
|
||||
| +- ErrorLoggingClause[@CanonicalImage = null]
|
||||
| +- TableName[@CanonicalImage = "ERRLOG", @Image = "errlog"]
|
||||
| | +- ID[@CanonicalImage = "ERRLOG", @Image = "errlog"]
|
||||
| +- SqlExpression[@CanonicalImage = "\'MY_BAD\'", @Image = "\'my_bad\'"]
|
||||
| | +- PrimaryPrefix[@CanonicalImage = "\'MY_BAD\'", @Image = "\'my_bad\'", @SelfModifier = false]
|
||||
| | +- Literal[@CanonicalImage = "\'MY_BAD\'", @Image = "\'my_bad\'"]
|
||||
| | +- StringLiteral[@CanonicalImage = "\'MY_BAD\'", @Image = "\'my_bad\'", @String = "my_bad"]
|
||||
| +- NumericLiteral[@CanonicalImage = "10", @Image = "10"]
|
||||
+- Statement[@CanonicalImage = null]
|
||||
| +- UnlabelledStatement[@CanonicalImage = null]
|
||||
| +- DeleteStatement[@CanonicalImage = null]
|
||||
| +- TableReference[@CanonicalImage = null]
|
||||
| | +- TableName[@CanonicalImage = "TEST_TABLE", @Image = "test_table"]
|
||||
| | | +- ID[@CanonicalImage = "TEST_TABLE", @Image = "test_table"]
|
||||
| | +- TableAlias[@CanonicalImage = "TALIAS", @Image = "talias"]
|
||||
| | +- ID[@CanonicalImage = "TALIAS", @Image = "talias"]
|
||||
| +- ErrorLoggingClause[@CanonicalImage = null]
|
||||
| +- TableName[@CanonicalImage = "ERR$_TEST_TABLE", @Image = "err$_test_table"]
|
||||
| +- ID[@CanonicalImage = "ERR$_TEST_TABLE", @Image = "err$_test_table"]
|
||||
+- Statement[@CanonicalImage = null]
|
||||
+- UnlabelledStatement[@CanonicalImage = null]
|
||||
+- DeleteStatement[@CanonicalImage = null]
|
||||
+- TableReference[@CanonicalImage = null]
|
||||
| +- TableName[@CanonicalImage = "TEST_TABLE", @Image = "test_table"]
|
||||
| +- ID[@CanonicalImage = "TEST_TABLE", @Image = "test_table"]
|
||||
+- ErrorLoggingClause[@CanonicalImage = null]
|
||||
+- TableName[@CanonicalImage = "ERR$_TEST_TABLE", @Image = "err$_test_table"]
|
||||
+- ID[@CanonicalImage = "ERR$_TEST_TABLE", @Image = "err$_test_table"]
|
Loading…
x
Reference in New Issue
Block a user