This is an automated email from the ASF dual-hosted git repository.
chengzhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 2b3814997f6 Support more plsql statement parse and add plsql parse
assert logic (#29648)
2b3814997f6 is described below
commit 2b3814997f60c13ba0c91728c66ca4e25fdb01da
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Thu Jan 4 15:12:36 2024 +0800
Support more plsql statement parse and add plsql parse assert logic (#29648)
* Support more plsql statement parse and add plsql parse assert logic
* fix checkstyle
---
.../src/main/antlr4/imports/oracle/Keyword.g4 | 68 ++++
.../oracle/src/main/antlr4/imports/oracle/PLSQL.g4 | 341 +++++++++++++++++--
.../src/main/antlr4/imports/oracle/Symbol.g4 | 2 +
.../visitor/statement/OracleStatementVisitor.java | 79 ++++-
.../statement/type/OracleDALStatementVisitor.java | 1 +
.../statement/type/OracleDDLStatementVisitor.java | 373 ++++++++++++++++++++-
.../statement/type/OracleDMLStatementVisitor.java | 48 ++-
.../parser/sql/common/enums/SequenceFunction.java | 30 +-
.../parser/sql/common/util/ColumnExtractor.java | 139 +++++++-
.../sql/common/util/ExpressionExtractUtils.java | 105 ++++++
.../parser/sql/common/util/WhereExtractUtils.java | 14 +
.../oracle/ddl/OracleCreateFunctionStatement.java | 15 +
.../oracle/ddl/OracleCreateProcedureStatement.java | 21 +-
.../CursorForLoopStatementSegment.java} | 28 +-
.../oracle/plsql/ProcedureCallNameSegment.java | 53 +++
.../SQLStatementSegment.java} | 20 +-
.../ddl/CreateFunctionStatementHandlerTest.java | 3 +-
.../ddl/CreateProcedureStatementHandlerTest.java | 3 +-
.../asserts/statement/SQLStatementAssert.java | 9 +-
.../statement/plsql/PLSQLStatementAssert.java | 131 ++++++++
...ectedDynamicSqlStatementExpressionSegment.java} | 8 +-
.../plsql/ExpectedProcedureCallNameSegment.java} | 17 +-
.../impl/plsql/ExpectedRoutineName.java} | 17 +-
.../impl/plsql/ExpectedSQLStatementSegment.java} | 17 +-
.../ddl/CreateFunctionStatementTestCase.java | 28 ++
.../ddl/CreateProcedureStatementTestCase.java | 28 ++
.../statement/plsql/CreateFunctionTestCase.java | 54 +++
.../statement/plsql/CreateProcedureTestCase.java | 54 +++
.../main/resources/case/plsql/create-function.xml | 21 ++
.../main/resources/case/plsql/create-procedure.xml | 34 ++
.../sql/supported/plsql/create-function.xml | 21 ++
.../sql/supported/plsql/create-procedure.xml | 21 ++
32 files changed, 1718 insertions(+), 85 deletions(-)
diff --git
a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
index 0580c89348a..377fbd3871f 100644
--- a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
+++ b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
@@ -839,3 +839,71 @@ AUTONOMOUS_TRANSACTION
WM_CONCAT
: W M UL_ C O N C A T
;
+
+DECLARE
+ : D E C L A R E
+ ;
+
+BULK
+ : B U L K
+ ;
+
+COLLECT
+ : C O L L E C T
+ ;
+
+INSERTING
+ : I N S E R T I N G
+ ;
+
+UPDATING
+ : U P D A T I N G
+ ;
+
+DELETING
+ : D E L E T I N G
+ ;
+
+ROWCOUNT
+ : R O W C O U N T
+ ;
+
+BULK_ROWCOUNT
+ : B U L K UL_ R O W C O U N T
+ ;
+
+RAISE
+ : R A I S E
+ ;
+
+WHILE
+ : W H I L E
+ ;
+
+GOTO
+ : G O T O
+ ;
+
+MUTABLE
+ : M U T A B L E
+ ;
+
+IMMUTABLE
+ : I M M U T A B L E
+ ;
+
+INDICES
+ : I N D I C E S
+ ;
+
+PAIRS
+ : P A I R S
+ ;
+
+PIPE
+ : P I P E
+ ;
+
+FORALL
+ : F O R A L L
+ ;
diff --git a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/PLSQL.g4
b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/PLSQL.g4
index 637ab4ee0e9..b9093f9eb94 100644
--- a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/PLSQL.g4
+++ b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/PLSQL.g4
@@ -17,7 +17,7 @@
grammar PLSQL;
-import Keyword, BaseRule, DDLStatement, DMLStatement;
+import Keyword, BaseRule, DDLStatement, DMLStatement, TCLStatement;
call
: CALL
@@ -48,10 +48,6 @@ plsqlProcedureSource
((defaultCollationClause | invokerRightsClause | accessibleByClause)*)?
(IS | AS) (callSpec | declareSection? body)
;
-plsqlBlock
- : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)* DECLARE declareSection
body
- ;
-
createFunction
: CREATE (OR REPLACE)? (EDITIONABLE | NONEDITIONABLE)? FUNCTION
plsqlFunctionSource
;
@@ -77,51 +73,336 @@ body
: BEGIN statement+ (EXCEPTION (exceptionHandler)+)? END (identifier)? SEMI_
;
-//need add more statement type according to the doc
+// TODO need add more statement type according to the doc
statement
: (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_ (SIGNED_LEFT_SHIFT_ label
SIGNED_RIGHT_SHIFT_) *)?
- (select
- | update
- | delete
- | insert
- | lockTable
- | merge
- | assignmentStatement
+ (assignStatement
| basicLoopStatement
+ | caseStatement
| closeStatement
+ | continueStatement
+ | cursorForLoopStatement
+ | executeImmediateStatement
+ | exitStatement
| fetchStatement
- | ifStatment
- | returnStatement
+ | forLoopStatement
+ | forallStatement
+ | gotoStatement
+ | ifStatement
| nullStatement
- ) SEMI_
+ | openStatement
+ | openForStatement
+ | pipeRowStatement
+ | plsqlBlock
+ | raiseStatement
+ | returnStatement
+ | selectIntoStatement
+ | sqlStatementInPlsql
+ | procedureCall
+ | whileLoopStatement
+ )
+ ;
+
+assignStatement
+ : assignStatementTarget ASSIGNMENT_OPERATOR_ expression SEMI_
+ ;
+
+assignStatementTarget
+ : collectionVariable=name (LP_ INTEGER_ RP_)?
+ // TODO cursor_variable, out_parameter, scalar_variable
+ | name
+ | placeholder
+ | hostCursorVariable
+ // TODO object.attribute, record_variable.field
+ | attributeName
+ ;
+
+placeholder
+ : COLON_ hostVariable=name (COLON_ indicatorVariable=name)?
+ ;
+
+// TODO PL/SQL grammar more than expr
+expression
+ : expr
+ ;
+
+booleanExpression
+ : NOT? booleanPrimary ((AND | OR) NOT? booleanPrimary)*
;
basicLoopStatement
- : LOOP (statement (EXIT label? (WHEN booleanPrimary)? SEMI_)?)+ END LOOP
label?
+ : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)?
+ LOOP statement+ END LOOP label? SEMI_
;
-assignmentStatement
- : variableName ASSIGNMENT_OPERATOR_ expr
+caseStatement
+ : simpleCaseStatement | searchedCaseStatement
+ ;
+
+simpleCaseStatement
+ : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)?
+ CASE selector=expression
+ (WHEN booleanExpression THEN statement)+
+ (ELSE statement+)?
+ END CASE label? SEMI_
+ ;
+
+searchedCaseStatement
+ : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)?
+ CASE
+ (WHEN booleanExpression THEN statement+)+
+ (ELSE statement+)?
+ END CASE label? SEMI_
;
closeStatement
- : CLOSE cursorName
+ : CLOSE (cursor | cursorVariable | hostCursorVariable) SEMI_
+ ;
+
+continueStatement
+ : CONTINUE label? (WHEN booleanExpression)? SEMI_
+ ;
+
+cursorForLoopStatement
+ : FOR record IN
+ (cursor (LP_ actualCursorParameter (COMMA_? actualCursorParameter)* RP_)?
+ | LP_ select RP_
+ )
+ LOOP statement+ END LOOP label? SEMI_
+ ;
+
+executeImmediateStatement
+ : EXECUTE IMMEDIATE dynamicSqlStmt
+ ((selectIntoClause | bulkCollectIntoClause) plsqlUsingClause?
+ | plsqlUsingClause dynamicReturningClause?
+ | dynamicReturningClause
+ )? SEMI_
+ ;
+
+dynamicReturningClause
+ : (RETURNING | RETURN) (selectIntoClause | bulkCollectIntoClause)
+ ;
+
+exitStatement
+ : EXIT label? (WHEN booleanExpression)? SEMI_
;
fetchStatement
- : FETCH cursorName INTO identifier
+ : FETCH (cursor | cursorVariable | hostCursorVariable)
+ (selectIntoClause | bulkCollectIntoClause (LIMIT expression)?) SEMI_
;
-ifStatment
- : IF booleanPrimary THEN statement+ (ELSIF booleanPrimary THEN
statement+)? (ELSE statement)? END IF
+forLoopStatement
+ : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)?
+ FOR iterator
+ LOOP statement+
+ END LOOP label? SEMI_
;
-returnStatement
- : RETURN expr
+iterator
+ : iterandDecl (COMMA_ iterandDecl)* IN iterationCtlSeq
+ ;
+
+iterandDecl
+ : plsIdentifier=identifier (MUTABLE | IMMUTABLE)? constrainedType=dataType?
+ ;
+
+iterationCtlSeq
+ : qualIterationCtl (COMMA_ qualIterationCtl)*
+ ;
+
+qualIterationCtl
+ : REVERSE? iterationCcontrol predClauseSeq
+ ;
+
+iterationCcontrol
+ : steppedControl
+ | singleExpressionControl
+ | valuesOfControl
+ | indicesOfControl
+ | pairsOfControl
+ | cursorIterationControl
+ ;
+
+predClauseSeq
+ : (WHILE booleanExpression)? (WHEN booleanExpression)?
+ ;
+
+steppedControl
+ : lowerBound RANGE_OPERATOR_ upperBound (BY step=expression)?
+ ;
+
+singleExpressionControl
+ : REPEAT? expression
+ ;
+
+valuesOfControl
+ : VALUES OF
+ (expression
+ | cursorVariable
+ | LP_ cursorObject | dynamicSql | sqlStatementInPlsql RP_
+ )
+ ;
+
+indicesOfControl
+ : INDICES OF
+ (expression
+ | cursorVariable
+ | LP_ cursorObject | cursorVariable | dynamicSql | sqlStatementInPlsql RP_
+ )
+ ;
+
+pairsOfControl
+ : PAIRS OF
+ (expression
+ | cursorVariable
+ | LP_ cursorObject | dynamicSql | sqlStatementInPlsql RP_
+ )
+ ;
+
+cursorIterationControl
+ : LP_ cursorObject | cursorVariable | dynamicSql | sqlStatementInPlsql RP_
+ ;
+
+dynamicSql
+ : EXECUTE IMMEDIATE dynamicSqlStmt (USING IN? (bindArgument COMMA_?)* )?
+ ;
+
+cursorObject
+ : variableName
+ ;
+
+forallStatement
+ : FORALL index=name IN boundsClause (SAVE EXCEPTIONS)? dmlStatement SEMI_
+ ;
+
+boundsClause
+ : lowerBound RANGE_OPERATOR_ upperBound
+ | INDICES OF collection=name (BETWEEN lowerBound AND upperBound)?
+ | VALUES OF indexCollection=name
+ ;
+
+lowerBound
+ : expression
+ ;
+
+upperBound
+ : expression
+ ;
+
+dmlStatement
+ : insert | update | delete | merge | dynamicSqlStmt
+ ;
+
+dynamicSqlStmt
+ : expression
+ ;
+
+gotoStatement
+ : GOTO label SEMI_
+ ;
+
+ifStatement
+ : IF booleanExpression THEN statement+
+ (ELSIF booleanExpression THEN statement+)*
+ (ELSE statement+)?
+ END IF SEMI_
;
nullStatement
- : NULL
+ : NULL SEMI_
+ ;
+
+openStatement
+ : OPEN cursor (LP_ actualCursorParameter (COMMA_? actualCursorParameter)*
RP_)? SEMI_
+ ;
+
+cursor
+ : variableName
+ ;
+
+openForStatement
+ : OPEN (cursorVariable | hostCursorVariable) FOR (select | dynamicSqlStmt)
plsqlUsingClause? SEMI_
+ ;
+
+cursorVariable
+ : variableName
+ ;
+
+plsqlUsingClause
+ : USING (IN | OUT | IN OUT)? bindArgument (COMMA_? (IN | OUT | IN OUT)?
bindArgument)*
+ ;
+
+bindArgument
+ : expression
+ ;
+
+pipeRowStatement
+ : PIPE ROW LP_ row=expression RP_ SEMI_
+ ;
+
+plsqlBlock
+ : ((SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)*)? (DECLARE
declareSection)? body
+ ;
+
+procedureCall
+ : (packageName DOT_)? procedureName (LP_ (parameter=expression (COMMA_
parameter=expression)*)? RP_)? SEMI_
+ ;
+
+raiseStatement
+ : RAISE name? SEMI_
+ ;
+
+returnStatement
+ : RETURN expression? SEMI_
+ ;
+
+selectIntoStatement
+ : SELECT (DISTINCT | UNIQUE | ALL)? selectList (selectIntoClause |
bulkCollectIntoClause) FROM fromClauseList whereClause?
hierarchicalQueryClause? groupByClause? modelClause? windowClause?
orderByClause? rowLimitingClause? SEMI_
+ ;
+
+// TODO into_clause of PL/SQL
+selectIntoClause
+ : INTO (variableName (COMMA_ variableName)* | record)
+ ;
+
+record
+ : name
+ ;
+
+bulkCollectIntoClause
+ : BULK COLLECT INTO (collection=name | hostArray)
+ ;
+
+hostArray
+ : COLON_ variableName
+ ;
+
+hostCursorVariable
+ : COLON_ variableName
+ ;
+
+actualCursorParameter
+ : expression
+ ;
+
+sqlStatementInPlsql
+ : (commit
+ // TODO collection_method_call
+ | delete
+ | insert
+ | lockTable
+ | merge
+ | rollback
+ | savepoint
+ | setTransaction
+ | update
+ ) SEMI_
+ ;
+
+whileLoopStatement
+ : WHILE booleanExpression
+ LOOP statement+ END LOOP label? SEMI_
;
exceptionHandler
@@ -276,7 +557,7 @@ rowtypeAttribute
pragma
: autonomousTransPragma | restrictReferencesPragma
-// TODO Support more pragma
+ // TODO Support more pragma
;
autonomousTransPragma
@@ -292,11 +573,11 @@ simpleDmlTrigger
;
dmlEventClause
- : dmlEventTrigger (OR dmlEventTrigger)* ON viewName
+ : dmlEventElement (OR dmlEventElement)* ON viewName
;
-dmlEventTrigger
- : DELETE | INSERT | UPDATE (OF columnName (COMMA_ columnName)*)?
+dmlEventElement
+ : (DELETE | INSERT | UPDATE) (OF LP_ columnName (COMMA_ columnName)* RP_)?
;
systemTrigger
diff --git a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Symbol.g4
b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Symbol.g4
index 8388c081011..dd8b3bc4f42 100644
--- a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Symbol.g4
+++ b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Symbol.g4
@@ -60,3 +60,5 @@ SEMI_: ';';
DOLLAR_: '$';
ASSIGNMENT_OPERATOR_:':=';
ARROW_: '=>';
+EXPONENT_: '**';
+RANGE_OPERATOR_: '..';
diff --git
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
index e13066d1237..4420a4e23ff 100644
---
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
+++
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
@@ -107,6 +107,7 @@ import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlTab
import org.apache.shardingsphere.sql.parser.sql.common.enums.AggregationType;
import org.apache.shardingsphere.sql.parser.sql.common.enums.OrderDirection;
import
org.apache.shardingsphere.sql.parser.sql.common.enums.ParameterMarkerType;
+import org.apache.shardingsphere.sql.parser.sql.common.enums.SequenceFunction;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.constraint.ConstraintSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexNameSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexSegment;
@@ -117,26 +118,12 @@ import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.Column
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenExpression;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CaseWhenExpression;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.datetime.DatetimeExpression;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.interval.IntervalDayToSecondExpression;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.interval.IntervalYearToMonthExpression;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.multiset.MultisetExpression;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.NotExpression;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlElementFunctionSegment;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlNamespaceStringAsIdentifierSegment;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlNamespacesClauseSegment;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlPiFunctionSegment;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlQueryAndExistsFunctionSegment;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlSerializeFunctionSegment;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlTableColumnSegment;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlTableFunctionSegment;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlTableOptionsSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.join.OuterJoinExpression;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
@@ -156,6 +143,7 @@ import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegm
import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ParameterMarkerSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import org.apache.shardingsphere.sql.parser.sql.common.util.SQLUtils;
import
org.apache.shardingsphere.sql.parser.sql.common.value.collection.CollectionValue;
import
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
@@ -167,13 +155,34 @@ import
org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.Number
import
org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.OtherLiteralValue;
import
org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.StringLiteralValue;
import
org.apache.shardingsphere.sql.parser.sql.common.value.parametermarker.ParameterMarkerValue;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.datetime.DatetimeExpression;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.interval.IntervalDayToSecondExpression;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.interval.IntervalYearToMonthExpression;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.join.OuterJoinExpression;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.multiset.MultisetExpression;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlElementFunctionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlNamespaceStringAsIdentifierSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlNamespacesClauseSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlPiFunctionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlQueryAndExistsFunctionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlSerializeFunctionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlTableColumnSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlTableFunctionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlTableOptionsSegment;
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.dml.OracleSelectStatement;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.CursorForLoopStatementSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.ProcedureCallNameSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.SQLStatementSegment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -186,6 +195,22 @@ public abstract class OracleStatementVisitor extends
OracleStatementBaseVisitor<
private final Collection<ParameterMarkerSegment>
statementParameterMarkerSegments = new LinkedList<>();
+ private final List<SQLStatementSegment> sqlStatementsInPlsql = new
ArrayList<>();
+
+ private final List<ProcedureCallNameSegment> procedureCallNames = new
ArrayList<>();
+
+ private final List<ExpressionSegment> dynamicSqlStatementExpressions = new
ArrayList<>();
+
+ private final Collection<String> variableNames = new HashSet<>();
+
+ private final Map<String, SQLStatement> cursorStatements = new HashMap<>();
+
+ private final List<CursorForLoopStatementSegment>
cursorForLoopStatementSegments = new ArrayList<>();
+
+ private final Map<Integer, Set<SQLStatement>> tempCursorForLoopStatements
= new HashMap<>();
+
+ private int cursorForLoopLevel;
+
@Override
public final ASTNode visitParameterMarker(final ParameterMarkerContext
ctx) {
return new ParameterMarkerValue(globalParameterMarkerSegments.size(),
ParameterMarkerType.QUESTION);
@@ -306,6 +331,9 @@ public abstract class OracleStatementVisitor extends
OracleStatementBaseVisitor<
@Override
public final ASTNode visitColumnName(final ColumnNameContext ctx) {
+ if (SequenceFunction.valueFrom(ctx.name().getText()).isPresent()) {
+ return createSequenceFunction(ctx);
+ }
ColumnSegment result = new
ColumnSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(),
(IdentifierValue) visit(ctx.name()));
OwnerContext owner = ctx.owner();
if (null != owner) {
@@ -317,6 +345,15 @@ public abstract class OracleStatementVisitor extends
OracleStatementBaseVisitor<
return result;
}
+ private FunctionSegment createSequenceFunction(final ColumnNameContext
ctx) {
+ FunctionSegment result = new
FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(),
ctx.name().getText(), getOriginalText(ctx));
+ OwnerContext owner = ctx.owner();
+ if (null != owner) {
+ result.setOwner(new OwnerSegment(owner.getStart().getStartIndex(),
owner.getStop().getStopIndex(), (IdentifierValue) visit(owner.identifier())));
+ }
+ return result;
+ }
+
@Override
public final ASTNode visitViewName(final ViewNameContext ctx) {
SimpleTableSegment result = new SimpleTableSegment(new
TableNameSegment(ctx.name().getStart().getStartIndex(),
@@ -1219,4 +1256,18 @@ public abstract class OracleStatementVisitor extends
OracleStatementBaseVisitor<
statementParameterMarkerSegments.clear();
return result;
}
+
+ /**
+ * Increase cursor for loop level.
+ */
+ protected void increaseCursorForLoopLevel() {
+ ++cursorForLoopLevel;
+ }
+
+ /**
+ * Decrease cursor for loop level.
+ */
+ protected void decreaseCursorForLoopLevel() {
+ --cursorForLoopLevel;
+ }
}
diff --git
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDALStatementVisitor.java
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDALStatementVisitor.java
index cf7ab2bc570..3eb8230958f 100644
---
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDALStatementVisitor.java
+++
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDALStatementVisitor.java
@@ -53,6 +53,7 @@ public final class OracleDALStatementVisitor extends
OracleStatementVisitor impl
result.setStatement((SQLStatement) visitor.visit(ctx.select()));
}
result.addParameterMarkerSegments(ctx.getParent() instanceof
ExecuteContext ? getGlobalParameterMarkerSegments() :
popAllStatementParameterMarkerSegments());
+ result.getVariableNames().addAll(getVariableNames());
return result;
}
}
diff --git
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDDLStatementVisitor.java
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDDLStatementVisitor.java
index 40319e4ccab..2577d9b45ed 100644
---
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDDLStatementVisitor.java
+++
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDDLStatementVisitor.java
@@ -64,6 +64,8 @@ import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Associ
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AuditContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AuditTraditionalContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AuditUnifiedContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.BodyContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CollectionVariableDeclContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ColumnClausesContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ColumnDefinitionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ColumnNameContext;
@@ -92,8 +94,8 @@ import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Create
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreatePFileContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateProcedureContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateProfileContext;
-import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateRestorePointContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateRelationalTableClauseContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateRestorePointContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateRollbackSegmentContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateSPFileContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateSequenceContext;
@@ -103,8 +105,11 @@ import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Create
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateTriggerContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateTypeContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CreateViewContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CursorDefinitionContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CursorForLoopStatementContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DataTypeDefinitionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DisassociateStatisticsContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DmlStatementContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropClusterContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropColumnClauseContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropColumnSpecificationContext;
@@ -141,15 +146,17 @@ import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropTa
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropTriggerContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropTypeContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DropViewContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DynamicSqlStmtContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ExceptionHandlerContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FlashbackDatabaseContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FlashbackTableContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FunctionContext;
-import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SwitchContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.IndexExpressionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.IndexExpressionsContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.IndexNameContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.IndexTypeNameContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InlineConstraintContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ItemDeclarationContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ModifyColPropertiesContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ModifyCollectionRetrievalContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ModifyColumnSpecificationContext;
@@ -159,20 +166,34 @@ import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.NoAudi
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ObjectBaseTypeDefContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ObjectSubTypeDefContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ObjectTypeDefContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OpenForStatementContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OperateColumnClauseContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OutOfLineConstraintContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OutOfLineRefConstraintContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OwnerContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.PackageNameContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ParameterDeclarationContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.PlsqlBlockContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.PlsqlFunctionSourceContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.PlsqlProcedureSourceContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ProcedureCallContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.PurgeContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.RelationalPropertyContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.RenameContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SchemaNameContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectIntoStatementContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SqlStatementInPlsqlContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.StatementContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SwitchContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SystemActionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TableNameContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TruncateTableContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TypeNameContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.VariableNameContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.VarrayTypeSpecContext;
import
org.apache.shardingsphere.sql.parser.oracle.visitor.statement.OracleStatementVisitor;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dal.VariableSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.AlterDefinitionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.CreateDefinitionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.column.ColumnDefinitionSegment;
@@ -188,16 +209,21 @@ import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.constraint.al
import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexTypeSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.packages.PackageSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.routine.FunctionNameSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.tablespace.TablespaceSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.type.TypeDefinitionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.type.TypeSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.DataTypeSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.value.collection.CollectionValue;
import
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
+import
org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.StringLiteralValue;
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleAlterAnalyticViewStatement;
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleAlterAttributeDimensionStatement;
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleAlterAuditPolicyStatement;
@@ -316,10 +342,18 @@ import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.Ora
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleSwitchStatement;
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleSystemActionStatement;
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleTruncateStatement;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.dml.OracleSelectStatement;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.CursorForLoopStatementSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.ProcedureCallNameSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.SQLStatementSegment;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedHashSet;
import java.util.LinkedList;
+import java.util.Optional;
+import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -1032,7 +1066,34 @@ public final class OracleDDLStatementVisitor extends
OracleStatementVisitor impl
@Override
public ASTNode visitCreateFunction(final CreateFunctionContext ctx) {
- return new OracleCreateFunctionStatement();
+ return visitCreateFunction0(ctx);
+ }
+
+ private ASTNode visitCreateFunction0(final CreateFunctionContext ctx) {
+ if (null != ctx.plsqlFunctionSource().declareSection()) {
+ visit(ctx.plsqlFunctionSource().declareSection());
+ }
+ if (null != ctx.plsqlFunctionSource().body()) {
+ visit(ctx.plsqlFunctionSource().body());
+ }
+
getSqlStatementsInPlsql().sort(Comparator.comparingInt(SQLStatementSegment::getStartIndex));
+
getProcedureCallNames().sort(Comparator.comparingInt(ProcedureCallNameSegment::getStartIndex));
+
getDynamicSqlStatementExpressions().sort(Comparator.comparingInt(ExpressionSegment::getStartIndex));
+ OracleCreateFunctionStatement result = new
OracleCreateFunctionStatement(getSqlStatementsInPlsql(),
getProcedureCallNames(), getDynamicSqlStatementExpressions());
+ result.setFunctionName(visitFunctionName(ctx.plsqlFunctionSource()));
+ return result;
+ }
+
+ private FunctionNameSegment visitFunctionName(final
PlsqlFunctionSourceContext ctx) {
+ OwnerContext schema = ctx.function().owner();
+ IdentifierValue functionName = (IdentifierValue)
visit(ctx.function().name().identifier());
+ if (null == schema) {
+ return new
FunctionNameSegment(ctx.function().name().start.getStartIndex(),
ctx.function().name().stop.getStopIndex(), functionName);
+ }
+ OwnerSegment owner = new OwnerSegment(schema.start.getStartIndex(),
schema.stop.getStopIndex(), (IdentifierValue) visit(schema.identifier()));
+ FunctionNameSegment result = new
FunctionNameSegment(ctx.function().start.getStartIndex(),
ctx.function().stop.getStopIndex(), functionName);
+ result.setOwner(owner);
+ return result;
}
@Override
@@ -1264,7 +1325,311 @@ public final class OracleDDLStatementVisitor extends
OracleStatementVisitor impl
@Override
public ASTNode visitCreateProcedure(final CreateProcedureContext ctx) {
- return new OracleCreateProcedureStatement();
+ return visitCreateProcedure0(ctx);
+ }
+
+ private ASTNode visitCreateProcedure0(final CreateProcedureContext ctx) {
+ if (null != ctx.plsqlProcedureSource().parameterDeclaration()) {
+ for (ParameterDeclarationContext each :
ctx.plsqlProcedureSource().parameterDeclaration()) {
+ visit(each);
+ }
+ }
+ if (null != ctx.plsqlProcedureSource().declareSection()) {
+ visit(ctx.plsqlProcedureSource().declareSection());
+ }
+ if (null != ctx.plsqlProcedureSource().body()) {
+ visit(ctx.plsqlProcedureSource().body());
+ }
+
getSqlStatementsInPlsql().sort(Comparator.comparingInt(SQLStatementSegment::getStartIndex));
+
getProcedureCallNames().sort(Comparator.comparingInt(ProcedureCallNameSegment::getStartIndex));
+
getDynamicSqlStatementExpressions().sort(Comparator.comparingInt(ExpressionSegment::getStartIndex));
+ OracleCreateProcedureStatement result = new
OracleCreateProcedureStatement(getSqlStatementsInPlsql(),
getProcedureCallNames(), getDynamicSqlStatementExpressions());
+
result.setProcedureName(visitProcedureName(ctx.plsqlProcedureSource()));
+ result.getVariableNames().addAll(getVariableNames());
+ getSqlStatementsInPlsql().forEach(each ->
each.getSqlStatement().getVariableNames().addAll(getVariableNames()));
+
result.getCursorForLoopStatements().addAll(getCursorForLoopStatementSegments());
+ return result;
+ }
+
+ @Override
+ public ASTNode visitParameterDeclaration(final ParameterDeclarationContext
ctx) {
+ if (null != ctx.parameterName()) {
+ IdentifierValue paramName = (IdentifierValue)
visit(ctx.parameterName().identifier());
+ getVariableNames().add(paramName.getValue().toLowerCase());
+ return new VariableSegment(ctx.start.getStartIndex(),
ctx.stop.getStopIndex(), paramName.getValue());
+ }
+ return super.visitParameterDeclaration(ctx);
+ }
+
+ @Override
+ public ASTNode visitItemDeclaration(final ItemDeclarationContext ctx) {
+ CollectionValue<VariableSegment> result = new CollectionValue<>();
+ if (null != ctx.collectionVariableDecl() && null !=
ctx.collectionVariableDecl().variableName()) {
+ for (VariableNameContext each :
ctx.collectionVariableDecl().variableName()) {
+ getVariableSegment(each).ifPresent(optional ->
result.getValue().add(optional));
+ }
+ }
+ if (null != ctx.constantDeclaration() && null !=
ctx.constantDeclaration().variableName()) {
+
getVariableSegment(ctx.constantDeclaration().variableName()).ifPresent(optional
-> result.getValue().add(optional));
+ }
+ if (null != ctx.cursorVariableDeclaration() && null !=
ctx.cursorVariableDeclaration().variableName()) {
+
getVariableSegment(ctx.cursorVariableDeclaration().variableName()).ifPresent(optional
-> result.getValue().add(optional));
+ }
+ if (null != ctx.exceptionDeclaration() && null !=
ctx.exceptionDeclaration().variableName()) {
+
getVariableSegment(ctx.exceptionDeclaration().variableName()).ifPresent(optional
-> result.getValue().add(optional));
+ }
+ if (null != ctx.recordVariableDeclaration() && null !=
ctx.recordVariableDeclaration().variableName()) {
+
getVariableSegment(ctx.recordVariableDeclaration().variableName()).ifPresent(optional
-> result.getValue().add(optional));
+ }
+ if (null != ctx.variableDeclaration() && null !=
ctx.variableDeclaration().variableName()) {
+
getVariableSegment(ctx.variableDeclaration().variableName()).ifPresent(optional
-> result.getValue().add(optional));
+ }
+ return result;
+ }
+
+ private Optional<VariableSegment> getVariableSegment(final
VariableNameContext variableNameContext) {
+ if (null == variableNameContext) {
+ return Optional.empty();
+ }
+ if (null != variableNameContext.identifier()) {
+ String variableName = ((IdentifierValue)
visitIdentifier(variableNameContext.identifier())).getValue().toLowerCase();
+ getVariableNames().add(variableName);
+ return Optional.of(new
VariableSegment(variableNameContext.start.getStartIndex(),
variableNameContext.stop.getStopIndex(), variableName));
+ }
+ if (null != variableNameContext.stringLiterals()) {
+ String variableName =
variableNameContext.stringLiterals().STRING_().getText().toLowerCase();
+ getVariableNames().add(variableName);
+ return Optional.of(new
VariableSegment(variableNameContext.start.getStartIndex(),
variableNameContext.stop.getStopIndex(), variableName));
+ }
+ return Optional.empty();
+ }
+
+ @Override
+ public ASTNode visitCollectionVariableDecl(final
CollectionVariableDeclContext ctx) {
+ CollectionValue<VariableSegment> result = new CollectionValue<>();
+ if (null == ctx.variableName()) {
+ return super.visitCollectionVariableDecl(ctx);
+ }
+ for (VariableNameContext each : ctx.variableName()) {
+ getVariableSegment(each).ifPresent(optional ->
result.getValue().add(optional));
+ }
+ return result;
+ }
+
+ private FunctionNameSegment visitProcedureName(final
PlsqlProcedureSourceContext ctx) {
+ SchemaNameContext schemaName = ctx.schemaName();
+ IdentifierValue procedureName = (IdentifierValue)
visit(ctx.procedureName().identifier());
+ if (null == schemaName) {
+ return new
FunctionNameSegment(ctx.procedureName().start.getStartIndex(),
ctx.procedureName().stop.getStopIndex(), procedureName);
+ }
+ OwnerSegment owner = new
OwnerSegment(schemaName.start.getStartIndex(), schemaName.stop.getStopIndex(),
(IdentifierValue) visit(schemaName.identifier()));
+ FunctionNameSegment result = new
FunctionNameSegment(schemaName.start.getStartIndex(),
ctx.procedureName().stop.getStopIndex(), procedureName);
+ result.setOwner(owner);
+ return result;
+ }
+
+ @Override
+ public ASTNode visitCursorDefinition(final CursorDefinitionContext ctx) {
+ SQLStatement statement = visitSelect0(ctx.select());
+ getCursorStatements().put(null != ctx.variableName().identifier() ?
new IdentifierValue(ctx.variableName().getText()).getValue()
+ : new
StringLiteralValue(ctx.variableName().getText()).getValue(), statement);
+ return defaultResult();
+ }
+
+ @Override
+ public ASTNode visitBody(final BodyContext ctx) {
+ for (StatementContext each : ctx.statement()) {
+ visit(each);
+ }
+ for (ExceptionHandlerContext eachExceptionHandler :
ctx.exceptionHandler()) {
+ for (StatementContext each : eachExceptionHandler.statement()) {
+ visit(each);
+ }
+ }
+ return defaultResult();
+ }
+
+ @Override
+ public ASTNode visitProcedureCall(final ProcedureCallContext ctx) {
+ int startIndex = ctx.procedureName().start.getStartIndex();
+ PackageSegment packageSegment = null;
+ if (null != ctx.packageName()) {
+ startIndex = ctx.packageName().start.getStartIndex();
+ packageSegment = (PackageSegment) visit(ctx.packageName());
+ }
+ ProcedureCallNameSegment result = new
ProcedureCallNameSegment(startIndex, ctx.procedureName().stop.getStopIndex(),
(IdentifierValue) visit(ctx.procedureName().identifier()));
+ result.setPackageSegment(packageSegment);
+ getProcedureCallNames().add(result);
+ return defaultResult();
+ }
+
+ @Override
+ public ASTNode visitCursorForLoopStatement(final
CursorForLoopStatementContext ctx) {
+ SQLStatement relatedCursorStatement;
+ String cursorName = null;
+ if (null != ctx.select()) {
+ relatedCursorStatement = visitSelect0(ctx.select());
+ } else {
+ cursorName = null == ctx.cursor().variableName().identifier()
+ ? new StringLiteralValue(ctx.cursor().getText()).getValue()
+ : new IdentifierValue(ctx.cursor().getText()).getValue();
+ relatedCursorStatement = getCursorStatements().get(cursorName);
+ }
+ increaseCursorForLoopLevel();
+ for (StatementContext each : ctx.statement()) {
+ visit(each);
+ }
+ Set<SQLStatement> sqlStatements =
getTempCursorForLoopStatements().remove(getCursorForLoopLevel());
+ CursorForLoopStatementSegment cursorForLoopStatementSegment = new
CursorForLoopStatementSegment(ctx.getStart().getStartIndex(),
ctx.getStop().getStopIndex(),
+ new IdentifierValue(ctx.record().getText()).getValue(),
cursorName, relatedCursorStatement, null == sqlStatements ?
Collections.emptyList() : sqlStatements);
+ getCursorForLoopStatementSegments().add(cursorForLoopStatementSegment);
+ decreaseCursorForLoopLevel();
+ return defaultResult();
+ }
+
+ @Override
+ public ASTNode visitOpenForStatement(final OpenForStatementContext ctx) {
+ if (null != ctx.select()) {
+ visitSelect0(ctx.select());
+ }
+ // TODO handle SQL in dynamicString
+ return defaultResult();
+ }
+
+ private SQLStatement visitSelect0(final SelectContext select) {
+ OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+ SQLStatement result = (SQLStatement) visitor.visitSelect(select);
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(select.start.getStartIndex(), select.stop.getStopIndex(),
result));
+ addToTempCursorForLoopStatements(result);
+ return result;
+ }
+
+ private void addToTempCursorForLoopStatements(final SQLStatement
sqlStatement) {
+ if (0 == getCursorForLoopLevel()) {
+ return;
+ }
+ for (int i = 1; i <= getCursorForLoopLevel(); i++) {
+ getTempCursorForLoopStatements().computeIfAbsent(i, key -> new
LinkedHashSet<>()).add(sqlStatement);
+ }
+ }
+
+ @Override
+ public ASTNode visitSqlStatementInPlsql(final SqlStatementInPlsqlContext
ctx) {
+ if (null != ctx.commit()) {
+ OracleStatementVisitor visitor = createOracleTCLStatementVisitor();
+ SQLStatement result = (SQLStatement)
visitor.visitCommit(ctx.commit());
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.commit().start.getStartIndex(),
ctx.commit().stop.getStopIndex(), result));
+ addToTempCursorForLoopStatements(result);
+ }
+ // TODO visit collection_method_call
+ if (null != ctx.delete()) {
+ OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+ SQLStatement result = (SQLStatement)
visitor.visitDelete(ctx.delete());
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.delete().start.getStartIndex(),
ctx.delete().stop.getStopIndex(), result));
+ addToTempCursorForLoopStatements(result);
+ }
+ if (null != ctx.insert()) {
+ OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+ SQLStatement result = (SQLStatement)
visitor.visitInsert(ctx.insert());
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.insert().start.getStartIndex(),
ctx.insert().stop.getStopIndex(), result));
+ addToTempCursorForLoopStatements(result);
+ }
+ if (null != ctx.lockTable()) {
+ OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+ SQLStatement result = (SQLStatement)
visitor.visitLockTable(ctx.lockTable());
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.lockTable().start.getStartIndex(),
ctx.lockTable().stop.getStopIndex(), result));
+ addToTempCursorForLoopStatements(result);
+ }
+ if (null != ctx.merge()) {
+ OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+ SQLStatement result = (SQLStatement)
visitor.visitMerge(ctx.merge());
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.merge().start.getStartIndex(),
ctx.merge().stop.getStopIndex(), result));
+ addToTempCursorForLoopStatements(result);
+ }
+ if (null != ctx.rollback()) {
+ OracleStatementVisitor visitor = createOracleTCLStatementVisitor();
+ SQLStatement result = (SQLStatement)
visitor.visitRollback(ctx.rollback());
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.rollback().start.getStartIndex(),
ctx.rollback().stop.getStopIndex(), result));
+ addToTempCursorForLoopStatements(result);
+ }
+ if (null != ctx.savepoint()) {
+ OracleStatementVisitor visitor = createOracleTCLStatementVisitor();
+ SQLStatement result = (SQLStatement)
visitor.visitSavepoint(ctx.savepoint());
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.savepoint().start.getStartIndex(),
ctx.savepoint().stop.getStopIndex(), result));
+ addToTempCursorForLoopStatements(result);
+ }
+ if (null != ctx.setTransaction()) {
+ OracleStatementVisitor visitor = createOracleTCLStatementVisitor();
+ SQLStatement result = (SQLStatement)
visitor.visitSetTransaction(ctx.setTransaction());
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.setTransaction().start.getStartIndex(),
ctx.setTransaction().stop.getStopIndex(), result));
+ addToTempCursorForLoopStatements(result);
+ }
+ if (null != ctx.update()) {
+ OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+ SQLStatement result = (SQLStatement)
visitor.visitUpdate(ctx.update());
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.update().start.getStartIndex(),
ctx.update().stop.getStopIndex(), result));
+ addToTempCursorForLoopStatements(result);
+ }
+ return defaultResult();
+ }
+
+ private OracleStatementVisitor createOracleTCLStatementVisitor() {
+ OracleStatementVisitor result = new OracleTCLStatementVisitor();
+ result.getVariableNames().addAll(getVariableNames());
+ return result;
+ }
+
+ private OracleStatementVisitor createOracleDMLStatementVisitor() {
+ OracleStatementVisitor result = new OracleDMLStatementVisitor();
+ result.getVariableNames().addAll(getVariableNames());
+ return result;
+ }
+
+ @Override
+ public ASTNode visitDmlStatement(final DmlStatementContext ctx) {
+ if (null != ctx.insert()) {
+ OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+ SQLStatement result = (SQLStatement)
visitor.visitInsert(ctx.insert());
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.insert().start.getStartIndex(),
ctx.insert().stop.getStopIndex(), result));
+ addToTempCursorForLoopStatements(result);
+ }
+ if (null != ctx.update()) {
+ OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+ SQLStatement result = (SQLStatement)
visitor.visitUpdate(ctx.update());
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.update().start.getStartIndex(),
ctx.update().stop.getStopIndex(), result));
+ addToTempCursorForLoopStatements(result);
+ }
+ if (null != ctx.delete()) {
+ OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+ SQLStatement result = (SQLStatement)
visitor.visitDelete(ctx.delete());
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.delete().start.getStartIndex(),
ctx.delete().stop.getStopIndex(), result));
+ addToTempCursorForLoopStatements(result);
+ }
+ if (null != ctx.merge()) {
+ OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+ SQLStatement result = (SQLStatement)
visitor.visitMerge(ctx.merge());
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.merge().start.getStartIndex(),
ctx.merge().stop.getStopIndex(), result));
+ addToTempCursorForLoopStatements(result);
+ }
+ // TODO Handling dynamicSqlStmt if we can
+ return defaultResult();
+ }
+
+ @Override
+ public ASTNode visitSelectIntoStatement(final SelectIntoStatementContext
ctx) {
+ // TODO Visit intoClause
+ OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+ OracleSelectStatement result = (OracleSelectStatement)
visitor.visitSelectIntoStatement(ctx);
+ getSqlStatementsInPlsql().add(new
SQLStatementSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(),
result));
+ addToTempCursorForLoopStatements(result);
+ return result;
+ }
+
+ @Override
+ public ASTNode visitDynamicSqlStmt(final DynamicSqlStmtContext ctx) {
+ ExpressionSegment result = (ExpressionSegment)
visit(ctx.expression().expr());
+ getDynamicSqlStatementExpressions().add(result);
+ return result;
}
@Override
diff --git
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
index 3d75b33cce8..989384bd03b 100644
---
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
+++
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
@@ -84,6 +84,7 @@ import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Refere
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.RollupCubeClauseContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectFromClauseContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectIntoStatementContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectJoinOptionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectJoinSpecificationContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectListContext;
@@ -153,6 +154,7 @@ import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvai
import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ModelSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ParameterMarkerSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.PivotSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.WithSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.CollectionTableSegment;
@@ -191,6 +193,7 @@ import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.dml.Ora
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
@@ -212,6 +215,7 @@ public final class OracleDMLStatementVisitor extends
OracleStatementVisitor impl
result.setWhere((WhereSegment) visit(ctx.whereClause()));
}
result.addParameterMarkerSegments(ctx.getParent() instanceof
ExecuteContext ? getGlobalParameterMarkerSegments() :
popAllStatementParameterMarkerSegments());
+ result.getVariableNames().addAll(getVariableNames());
return result;
}
@@ -319,6 +323,7 @@ public final class OracleDMLStatementVisitor extends
OracleStatementVisitor impl
getOriginalText(ctx.selectSubquery()));
result.setInsertSelect(subquerySegment);
}
+ result.getVariableNames().addAll(getVariableNames());
return result;
}
@@ -343,17 +348,29 @@ public final class OracleDMLStatementVisitor extends
OracleStatementVisitor impl
}
result.setInsertSelect(new
SubquerySegment(ctx.selectSubquery().start.getStartIndex(),
ctx.selectSubquery().stop.getStopIndex(), (OracleSelectStatement)
visit(ctx.selectSubquery()),
getOriginalText(ctx.selectSubquery())));
+ result.getVariableNames().addAll(getVariableNames());
return result;
}
private Collection<InsertStatement> createInsertIntoSegments(final
List<MultiTableElementContext> ctx) {
Collection<InsertStatement> result = new LinkedList<>();
+ Collection<ParameterMarkerSegment> addedSegments = new HashSet<>();
for (MultiTableElementContext each : ctx) {
- result.add((OracleInsertStatement) visit(each));
+ OracleInsertStatement oracleInsertStatement =
(OracleInsertStatement) visit(each);
+ addParameterMarkerSegments(addedSegments, oracleInsertStatement);
+ result.add(oracleInsertStatement);
}
return result;
}
+ private void addParameterMarkerSegments(final
Collection<ParameterMarkerSegment> addedSegments, final OracleInsertStatement
oracleInsertStatement) {
+ for (ParameterMarkerSegment parameterMarkerSegment :
popAllStatementParameterMarkerSegments()) {
+ if (addedSegments.add(parameterMarkerSegment)) {
+
oracleInsertStatement.addParameterMarkerSegments(Collections.singletonList(parameterMarkerSegment));
+ }
+ }
+ }
+
@Override
public ASTNode visitInsertValuesClause(final InsertValuesClauseContext
ctx) {
OracleInsertStatement result = new OracleInsertStatement();
@@ -393,6 +410,7 @@ public final class OracleDMLStatementVisitor extends
OracleStatementVisitor impl
result.setWhere((WhereSegment) visit(ctx.whereClause()));
}
result.addParameterMarkerSegments(ctx.getParent() instanceof
ExecuteContext ? getGlobalParameterMarkerSegments() :
popAllStatementParameterMarkerSegments());
+ result.getVariableNames().addAll(getVariableNames());
return result;
}
@@ -409,6 +427,32 @@ public final class OracleDMLStatementVisitor extends
OracleStatementVisitor impl
return new SubqueryTableSegment(subquerySegment);
}
+ @Override
+ public OracleSelectStatement visitSelectIntoStatement(final
SelectIntoStatementContext ctx) {
+ OracleSelectStatement result = new OracleSelectStatement();
+ result.setProjections((ProjectionsSegment) visit(ctx.selectList()));
+ // TODO Visit selectIntoClause, bulkCollectIntoClause
+ result.setFrom((TableSegment) visit(ctx.fromClauseList()));
+ if (null != ctx.whereClause()) {
+ result.setWhere((WhereSegment) visit(ctx.whereClause()));
+ }
+ if (null != ctx.groupByClause()) {
+ result.setGroupBy((GroupBySegment) visit(ctx.groupByClause()));
+ }
+ // TODO Visit hierarchicalQueryClause
+ if (null != ctx.modelClause()) {
+ result.setModelSegment((ModelSegment) visit(ctx.modelClause()));
+ }
+ // TODO Visit windowClause
+ if (null != ctx.orderByClause()) {
+ result.setOrderBy((OrderBySegment) visit(ctx.orderByClause()));
+ }
+ // TODO Visit rowLimitingClause
+ result.addParameterMarkerSegments(ctx.getParent() instanceof
ExecuteContext ? getGlobalParameterMarkerSegments() :
popAllStatementParameterMarkerSegments());
+ result.getVariableNames().addAll(getVariableNames());
+ return result;
+ }
+
@Override
public ASTNode visitMultiTableElement(final MultiTableElementContext ctx) {
OracleInsertStatement result = (OracleInsertStatement)
visit(ctx.insertIntoClause());
@@ -423,6 +467,7 @@ public final class OracleDMLStatementVisitor extends
OracleStatementVisitor impl
public ASTNode visitSelect(final SelectContext ctx) {
OracleSelectStatement result = (OracleSelectStatement)
visit(ctx.selectSubquery());
result.addParameterMarkerSegments(ctx.getParent() instanceof
ExecuteContext ? getGlobalParameterMarkerSegments() :
popAllStatementParameterMarkerSegments());
+ result.getVariableNames().addAll(getVariableNames());
if (null != ctx.forUpdateClause()) {
result.setLock((LockSegment) visit(ctx.forUpdateClause()));
}
@@ -555,6 +600,7 @@ public final class OracleDMLStatementVisitor extends
OracleStatementVisitor impl
result.setOrderBy((OrderBySegment) visit(ctx.orderByClause()));
}
result.addParameterMarkerSegments(ctx.getParent() instanceof
ExecuteContext ? getGlobalParameterMarkerSegments() :
popAllStatementParameterMarkerSegments());
+ result.getVariableNames().addAll(getVariableNames());
return result;
}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/SequenceFunction.java
similarity index 51%
copy from
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
copy to
parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/SequenceFunction.java
index 2cf7e238fac..d8d390994eb 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
+++
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/SequenceFunction.java
@@ -15,12 +15,34 @@
* limitations under the License.
*/
-package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
+package org.apache.shardingsphere.sql.parser.sql.common.enums;
-import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import com.cedarsoftware.util.CaseInsensitiveMap;
+
+import java.util.Map;
+import java.util.Optional;
/**
- * Create function statement test case.
+ * Sequence function.
*/
-public final class CreateFunctionStatementTestCase extends SQLParserTestCase {
+public enum SequenceFunction {
+
+ CURRVAL, NEXTVAL;
+
+ private static final Map<String, SequenceFunction> SEQUENCE_FUNCTIONS =
new CaseInsensitiveMap<>(2, 1F);
+
+ static {
+ SEQUENCE_FUNCTIONS.put("CURRVAL", CURRVAL);
+ SEQUENCE_FUNCTIONS.put("NEXTVAL", NEXTVAL);
+ }
+
+ /**
+ * Get sequence function value from text.
+ *
+ * @param text text
+ * @return sequence function value
+ */
+ public static Optional<SequenceFunction> valueFrom(final String text) {
+ return Optional.ofNullable(SEQUENCE_FUNCTIONS.get(text));
+ }
}
diff --git
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ColumnExtractor.java
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ColumnExtractor.java
index c3c6f68f665..20efbccffcc 100644
---
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ColumnExtractor.java
+++
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ColumnExtractor.java
@@ -24,9 +24,27 @@ import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenE
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.join.OuterJoinExpression;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.DatetimeProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.IntervalExpressionProjection;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.GroupBySegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.OrderBySegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ExpressionOrderByItemSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.HavingSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.CollectionTableSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.join.OuterJoinExpression;
import java.util.Collection;
import java.util.LinkedList;
@@ -87,4 +105,123 @@ public final class ColumnExtractor {
columnSegments.addAll(ColumnExtractor.extract(each));
}
}
+
+ /**
+ * Extract column segments.
+ *
+ * @param columnSegments column segments
+ * @param statement select statement
+ * @param containsSubQuery whether contains sub query
+ */
+ public static void extractFromSelectStatement(final
Collection<ColumnSegment> columnSegments, final SelectStatement statement,
final boolean containsSubQuery) {
+ extractFromProjections(columnSegments,
statement.getProjections().getProjections(), containsSubQuery);
+ extractFromSelectStatementWithoutProjection(columnSegments, statement,
containsSubQuery);
+ }
+
+ /**
+ * Extract from select statement without projection.
+ *
+ * @param columnSegments column segments
+ * @param statement select statement
+ * @param containsSubQuery whether contains sub query
+ */
+ public static void extractFromSelectStatementWithoutProjection(final
Collection<ColumnSegment> columnSegments, final SelectStatement statement,
final boolean containsSubQuery) {
+ extractFromTable(columnSegments, statement.getFrom(),
containsSubQuery);
+ statement.getWhere().ifPresent(optional ->
extractFromWhere(columnSegments, optional, containsSubQuery));
+ statement.getGroupBy().ifPresent(optional ->
extractFromGroupBy(columnSegments, optional, containsSubQuery));
+ statement.getHaving().ifPresent(optional ->
extractFromHaving(columnSegments, optional, containsSubQuery));
+ statement.getOrderBy().ifPresent(optional ->
extractFromOrderBy(columnSegments, optional, containsSubQuery));
+ statement.getCombine().ifPresent(optional ->
extractFromSelectStatement(columnSegments, optional.getRight(),
containsSubQuery));
+ }
+
+ /**
+ * Extract column segments.
+ *
+ * @param columnSegments column segments
+ * @param projections projection segments
+ * @param containsSubQuery contains sub query
+ */
+ public static void extractFromProjections(final Collection<ColumnSegment>
columnSegments, final Collection<ProjectionSegment> projections, final boolean
containsSubQuery) {
+ for (ProjectionSegment each : projections) {
+ if (each instanceof ColumnProjectionSegment) {
+ columnSegments.add(((ColumnProjectionSegment)
each).getColumn());
+ }
+ if (each instanceof AggregationProjectionSegment) {
+ for (ExpressionSegment parameter :
((AggregationProjectionSegment) each).getParameters()) {
+
columnSegments.addAll(ExpressionExtractUtils.extractColumns(parameter,
containsSubQuery));
+ }
+ }
+ if (each instanceof DatetimeProjectionSegment) {
+
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((DatetimeProjectionSegment)
each).getLeft(), containsSubQuery));
+
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((DatetimeProjectionSegment)
each).getRight(), containsSubQuery));
+ }
+ if (each instanceof ExpressionProjectionSegment) {
+
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((ExpressionProjectionSegment)
each).getExpr(), containsSubQuery));
+ }
+ if (each instanceof IntervalExpressionProjection) {
+
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((IntervalExpressionProjection)
each).getLeft(), containsSubQuery));
+
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((IntervalExpressionProjection)
each).getRight(), containsSubQuery));
+
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((IntervalExpressionProjection)
each).getMinus(), containsSubQuery));
+ }
+ if (each instanceof SubqueryProjectionSegment && containsSubQuery)
{
+ extractFromSelectStatement(columnSegments,
((SubqueryProjectionSegment) each).getSubquery().getSelect(), true);
+ }
+ }
+ }
+
+ private static void extractFromTable(final Collection<ColumnSegment>
columnSegments, final TableSegment tableSegment, final boolean
containsSubQuery) {
+ if (null == tableSegment) {
+ return;
+ }
+ if (tableSegment instanceof CollectionTableSegment) {
+
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((CollectionTableSegment)
tableSegment).getExpressionSegment(), containsSubQuery));
+ }
+ if (tableSegment instanceof JoinTableSegment) {
+ extractFromTable(columnSegments, ((JoinTableSegment)
tableSegment).getLeft(), containsSubQuery);
+ extractFromTable(columnSegments, ((JoinTableSegment)
tableSegment).getRight(), containsSubQuery);
+
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((JoinTableSegment)
tableSegment).getCondition(), containsSubQuery));
+ columnSegments.addAll(((JoinTableSegment)
tableSegment).getUsing());
+ columnSegments.addAll(((JoinTableSegment)
tableSegment).getDerivedUsing());
+ }
+ if (tableSegment instanceof SubqueryTableSegment && containsSubQuery) {
+ extractFromSelectStatement(columnSegments, ((SubqueryTableSegment)
tableSegment).getSubquery().getSelect(), true);
+ }
+ }
+
+ /**
+ * Extract column segments.
+ *
+ * @param columnSegments column segments
+ * @param whereSegment where segment
+ * @param containsSubQuery contains sub query
+ */
+ public static void extractFromWhere(final Collection<ColumnSegment>
columnSegments, final WhereSegment whereSegment, final boolean
containsSubQuery) {
+
columnSegments.addAll(ExpressionExtractUtils.extractColumns(whereSegment.getExpr(),
containsSubQuery));
+ }
+
+ private static void extractFromGroupBy(final Collection<ColumnSegment>
columnSegments, final GroupBySegment groupBySegment, final boolean
containsSubQuery) {
+ for (OrderByItemSegment each : groupBySegment.getGroupByItems()) {
+ if (each instanceof ColumnOrderByItemSegment) {
+ columnSegments.add(((ColumnOrderByItemSegment)
each).getColumn());
+ }
+ if (each instanceof ExpressionOrderByItemSegment) {
+
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((ExpressionOrderByItemSegment)
each).getExpr(), containsSubQuery));
+ }
+ }
+ }
+
+ private static void extractFromHaving(final Collection<ColumnSegment>
columnSegments, final HavingSegment havingSegment, final boolean
containsSubQuery) {
+
columnSegments.addAll(ExpressionExtractUtils.extractColumns(havingSegment.getExpr(),
containsSubQuery));
+ }
+
+ private static void extractFromOrderBy(final Collection<ColumnSegment>
columnSegments, final OrderBySegment orderBySegment, final boolean
containsSubQuery) {
+ for (OrderByItemSegment each : orderBySegment.getOrderByItems()) {
+ if (each instanceof ColumnOrderByItemSegment) {
+ columnSegments.add(((ColumnOrderByItemSegment)
each).getColumn());
+ }
+ if (each instanceof ExpressionOrderByItemSegment) {
+
columnSegments.addAll(ExpressionExtractUtils.extractColumns(((ExpressionOrderByItemSegment)
each).getExpr(), containsSubQuery));
+ }
+ }
+ }
}
diff --git
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtils.java
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtils.java
index 6d69c31ae75..1ba74ee51d9 100644
---
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtils.java
+++
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtils.java
@@ -20,15 +20,31 @@ package
org.apache.shardingsphere.sql.parser.sql.common.util;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.shardingsphere.sql.parser.sql.common.enums.LogicalOperator;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenExpression;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CaseWhenExpression;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.NotExpression;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.TypeCastExpression;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ValuesExpression;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonTableExpressionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.IntervalExpressionProjection;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.mysql.match.MatchAgainstExpression;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.datetime.DatetimeExpression;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.join.OuterJoinExpression;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.multiset.MultisetExpression;
import java.util.ArrayList;
import java.util.Collection;
@@ -138,4 +154,93 @@ public final class ExpressionExtractUtils {
}
}
}
+
+ /**
+ * Extract columns.
+ *
+ * @param expression expression
+ * @param containsSubQuery contains sub query or not
+ * @return columns
+ */
+ public static Collection<ColumnSegment> extractColumns(final
ExpressionSegment expression, final boolean containsSubQuery) {
+ if (expression instanceof ColumnSegment) {
+ return Collections.singletonList((ColumnSegment) expression);
+ }
+ Collection<ColumnSegment> result = new LinkedList<>();
+ if (expression instanceof AggregationProjectionSegment) {
+ for (ExpressionSegment each : ((AggregationProjectionSegment)
expression).getParameters()) {
+ result.addAll(extractColumns(each, containsSubQuery));
+ }
+ }
+ if (expression instanceof BetweenExpression) {
+ result.addAll(extractColumns(((BetweenExpression)
expression).getLeft(), containsSubQuery));
+ result.addAll(extractColumns(((BetweenExpression)
expression).getBetweenExpr(), containsSubQuery));
+ result.addAll(extractColumns(((BetweenExpression)
expression).getAndExpr(), containsSubQuery));
+ }
+ if (expression instanceof BinaryOperationExpression) {
+ result.addAll(extractColumns(((BinaryOperationExpression)
expression).getLeft(), containsSubQuery));
+ result.addAll(extractColumns(((BinaryOperationExpression)
expression).getRight(), containsSubQuery));
+ }
+ if (expression instanceof CaseWhenExpression) {
+ result.addAll(extractColumns(((CaseWhenExpression)
expression).getCaseExpr(), containsSubQuery));
+ result.addAll(extractColumns(((CaseWhenExpression)
expression).getElseExpr(), containsSubQuery));
+ ((CaseWhenExpression) expression).getWhenExprs().forEach(each ->
result.addAll(extractColumns(each, containsSubQuery)));
+ ((CaseWhenExpression) expression).getThenExprs().forEach(each ->
result.addAll(extractColumns(each, containsSubQuery)));
+ }
+ if (expression instanceof OuterJoinExpression) {
+ result.add(((OuterJoinExpression) expression).getColumnName());
+ }
+ if (expression instanceof CommonTableExpressionSegment) {
+ result.addAll(((CommonTableExpressionSegment)
expression).getColumns());
+ }
+ if (expression instanceof DatetimeExpression) {
+ result.addAll(extractColumns(((DatetimeExpression)
expression).getLeft(), containsSubQuery));
+ result.addAll(extractColumns(((DatetimeExpression)
expression).getRight(), containsSubQuery));
+ }
+ if (expression instanceof ExpressionProjectionSegment) {
+ result.addAll(extractColumns(((ExpressionProjectionSegment)
expression).getExpr(), containsSubQuery));
+ }
+ if (expression instanceof FunctionSegment) {
+ for (ExpressionSegment each : ((FunctionSegment)
expression).getParameters()) {
+ result.addAll(extractColumns(each, containsSubQuery));
+ }
+ }
+ if (expression instanceof InExpression) {
+ result.addAll(extractColumns(((InExpression)
expression).getLeft(), containsSubQuery));
+ result.addAll(extractColumns(((InExpression)
expression).getRight(), containsSubQuery));
+ }
+ if (expression instanceof IntervalExpressionProjection) {
+ result.addAll(extractColumns(((IntervalExpressionProjection)
expression).getLeft(), containsSubQuery));
+ result.addAll(extractColumns(((IntervalExpressionProjection)
expression).getRight(), containsSubQuery));
+ result.addAll(extractColumns(((IntervalExpressionProjection)
expression).getMinus(), containsSubQuery));
+ }
+ if (expression instanceof ListExpression) {
+ for (ExpressionSegment each : ((ListExpression)
expression).getItems()) {
+ result.addAll(extractColumns(each, containsSubQuery));
+ }
+ }
+ if (expression instanceof MatchAgainstExpression) {
+ result.add(((MatchAgainstExpression) expression).getColumnName());
+ result.addAll(extractColumns(((MatchAgainstExpression)
expression).getExpr(), containsSubQuery));
+ }
+ if (expression instanceof MultisetExpression) {
+ result.addAll(extractColumns(((MultisetExpression)
expression).getLeft(), containsSubQuery));
+ result.addAll(extractColumns(((MultisetExpression)
expression).getRight(), containsSubQuery));
+ }
+ if (expression instanceof NotExpression) {
+ result.addAll(extractColumns(((NotExpression)
expression).getExpression(), containsSubQuery));
+ }
+ if (expression instanceof ValuesExpression) {
+ for (InsertValuesSegment each : ((ValuesExpression)
expression).getRowConstructorList()) {
+ each.getValues().forEach(value ->
result.addAll(extractColumns(value, containsSubQuery)));
+ }
+ }
+ if (expression instanceof SubquerySegment && containsSubQuery) {
+ ColumnExtractor.extractFromSelectStatement(result,
((SubquerySegment) expression).getSelect(), true);
+ }
+ if (expression instanceof SubqueryExpressionSegment &&
containsSubQuery) {
+ ColumnExtractor.extractFromSelectStatement(result,
((SubqueryExpressionSegment) expression).getSubquery().getSelect(), true);
+ }
+ return result;
+ }
}
diff --git
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/WhereExtractUtils.java
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/WhereExtractUtils.java
index 964dab98f2d..9ff381a3d46 100644
---
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/WhereExtractUtils.java
+++
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/WhereExtractUtils.java
@@ -77,4 +77,18 @@ public final class WhereExtractUtils {
}
return result;
}
+
+ /**
+ * Get subquery where segment without join conditions from SelectStatement.
+ *
+ * @param selectStatement SelectStatement
+ * @return subquery where segment collection
+ */
+ public static Collection<WhereSegment>
getSubqueryWhereSegmentsWithoutJoinConditions(final SelectStatement
selectStatement) {
+ Collection<WhereSegment> result = new LinkedList<>();
+ for (SubquerySegment each :
SubqueryExtractUtils.getSubquerySegments(selectStatement)) {
+ each.getSelect().getWhere().ifPresent(result::add);
+ }
+ return result;
+ }
}
diff --git
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
index 83c66294cf9..797412d2711 100644
---
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
+++
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
@@ -17,11 +17,26 @@
package org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateFunctionStatement;
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.OracleStatement;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.ProcedureCallNameSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.SQLStatementSegment;
+
+import java.util.List;
/**
* Oracle create function statement.
*/
+@RequiredArgsConstructor
+@Getter
public final class OracleCreateFunctionStatement extends
CreateFunctionStatement implements OracleStatement {
+
+ private final List<SQLStatementSegment> sqlStatements;
+
+ private final List<ProcedureCallNameSegment> procedureCallNames;
+
+ private final List<ExpressionSegment> dynamicSqlStatementExpressions;
}
diff --git
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateProcedureStatement.java
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateProcedureStatement.java
index 010dee48262..69b28bde8be 100644
---
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateProcedureStatement.java
+++
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateProcedureStatement.java
@@ -17,13 +17,30 @@
package org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl;
-import lombok.Setter;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateProcedureStatement;
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.OracleStatement;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.CursorForLoopStatementSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.ProcedureCallNameSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.SQLStatementSegment;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* Oracle create procedure statement.
*/
-@Setter
+@RequiredArgsConstructor
+@Getter
public final class OracleCreateProcedureStatement extends
CreateProcedureStatement implements OracleStatement {
+
+ private final List<SQLStatementSegment> sqlStatements;
+
+ private final List<ProcedureCallNameSegment> procedureCallNames;
+
+ private final List<ExpressionSegment> dynamicSqlStatementExpressions;
+
+ private final List<CursorForLoopStatementSegment> cursorForLoopStatements
= new ArrayList<>();
}
diff --git
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/CursorForLoopStatementSegment.java
similarity index 60%
copy from
parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
copy to
parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/CursorForLoopStatementSegment.java
index 83c66294cf9..270bca13f33 100644
---
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
+++
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/CursorForLoopStatementSegment.java
@@ -15,13 +15,31 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl;
+package
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql;
-import
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateFunctionStatement;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.OracleStatement;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+
+import java.util.Collection;
/**
- * Oracle create function statement.
+ * Cursor for loop statement segment.
*/
-public final class OracleCreateFunctionStatement extends
CreateFunctionStatement implements OracleStatement {
+@RequiredArgsConstructor
+@Getter
+public final class CursorForLoopStatementSegment implements SQLSegment {
+
+ private final int startIndex;
+
+ private final int stopIndex;
+
+ private final String record;
+
+ private final String cursor;
+
+ private final SQLStatement cursorRelatedStatement;
+
+ private final Collection<SQLStatement> statements;
}
diff --git
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/ProcedureCallNameSegment.java
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/ProcedureCallNameSegment.java
new file mode 100644
index 00000000000..a38503a91a4
--- /dev/null
+++
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/ProcedureCallNameSegment.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.packages.PackageSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
+
+import java.util.Optional;
+
+/**
+ * PL/SQL procedure call name segment.
+ */
+@RequiredArgsConstructor
+@Getter
+@Setter
+public final class ProcedureCallNameSegment implements SQLSegment {
+
+ private final int startIndex;
+
+ private final int stopIndex;
+
+ private final IdentifierValue identifier;
+
+ private PackageSegment packageSegment;
+
+ public Optional<PackageSegment> getPackageSegment() {
+ return Optional.ofNullable(packageSegment);
+ }
+
+ @Override
+ public String toString() {
+ return getPackageSegment().map(s ->
s.getIdentifier().getValueWithQuoteCharacters() + ".").orElse("") +
identifier.getValueWithQuoteCharacters();
+ }
+}
diff --git
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/SQLStatementSegment.java
similarity index 69%
copy from
parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
copy to
parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/SQLStatementSegment.java
index 83c66294cf9..3a1fedb5ee6 100644
---
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/ddl/OracleCreateFunctionStatement.java
+++
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/oracle/plsql/SQLStatementSegment.java
@@ -15,13 +15,23 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl;
+package
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql;
-import
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateFunctionStatement;
-import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.OracleStatement;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
/**
- * Oracle create function statement.
+ * SQL statement segment.
*/
-public final class OracleCreateFunctionStatement extends
CreateFunctionStatement implements OracleStatement {
+@RequiredArgsConstructor
+@Getter
+public final class SQLStatementSegment implements SQLSegment {
+
+ private final int startIndex;
+
+ private final int stopIndex;
+
+ private final SQLStatement sqlStatement;
}
diff --git
a/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateFunctionStatementHandlerTest.java
b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateFunctionStatementHandlerTest.java
index a330216c29e..67e98e3e9a2 100644
---
a/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateFunctionStatementHandlerTest.java
+++
b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateFunctionStatementHandlerTest.java
@@ -25,6 +25,7 @@ import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.ddl
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.ddl.SQLServerCreateFunctionStatement;
import org.junit.jupiter.api.Test;
+import java.util.Collections;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -51,7 +52,7 @@ class CreateFunctionStatementHandlerTest {
@Test
void assertGetRoutineBodySegmentForOtherDatabases() {
assertFalse(CreateFunctionStatementHandler.getRoutineBodySegment(new
OpenGaussCreateFunctionStatement()).isPresent());
- assertFalse(CreateFunctionStatementHandler.getRoutineBodySegment(new
OracleCreateFunctionStatement()).isPresent());
+ assertFalse(CreateFunctionStatementHandler.getRoutineBodySegment(new
OracleCreateFunctionStatement(Collections.emptyList(), Collections.emptyList(),
Collections.emptyList())).isPresent());
assertFalse(CreateFunctionStatementHandler.getRoutineBodySegment(new
PostgreSQLCreateFunctionStatement()).isPresent());
assertFalse(CreateFunctionStatementHandler.getRoutineBodySegment(new
SQLServerCreateFunctionStatement()).isPresent());
}
diff --git
a/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateProcedureStatementHandlerTest.java
b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateProcedureStatementHandlerTest.java
index 009059e623c..d0eca72b025 100644
---
a/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateProcedureStatementHandlerTest.java
+++
b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/ddl/CreateProcedureStatementHandlerTest.java
@@ -25,6 +25,7 @@ import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.ddl
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.ddl.SQLServerCreateProcedureStatement;
import org.junit.jupiter.api.Test;
+import java.util.Collections;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -51,7 +52,7 @@ class CreateProcedureStatementHandlerTest {
@Test
void assertGetRoutineBodySegmentForOtherDatabases() {
assertFalse(CreateProcedureStatementHandler.getRoutineBodySegment(new
OpenGaussCreateProcedureStatement()).isPresent());
- assertFalse(CreateProcedureStatementHandler.getRoutineBodySegment(new
OracleCreateProcedureStatement()).isPresent());
+ assertFalse(CreateProcedureStatementHandler.getRoutineBodySegment(new
OracleCreateProcedureStatement(Collections.emptyList(),
Collections.emptyList(), Collections.emptyList())).isPresent());
assertFalse(CreateProcedureStatementHandler.getRoutineBodySegment(new
PostgreSQLCreateProcedureStatement()).isPresent());
assertFalse(CreateProcedureStatementHandler.getRoutineBodySegment(new
SQLServerCreateProcedureStatement()).isPresent());
}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/SQLStatementAssert.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/SQLStatementAssert.java
index 95a5018c5cc..29f5fb390bd 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/SQLStatementAssert.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/SQLStatementAssert.java
@@ -29,17 +29,20 @@ import
org.apache.shardingsphere.sql.parser.sql.common.statement.dcl.DCLStatemen
import
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DDLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.tcl.TCLStatement;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleCreateFunctionStatement;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleCreateProcedureStatement;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.parameter.ParameterMarkerAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.comment.CommentAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dal.DALStatementAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dcl.DCLStatementAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.ddl.DDLStatementAssert;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dml.DMLStatementAssert;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.plsql.PLSQLStatementAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.ral.RALStatementAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.rdl.RDLStatementAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.rql.RQLStatementAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.rul.RULStatementAssert;
-import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dml.DMLStatementAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.tcl.TCLStatementAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
@@ -57,6 +60,10 @@ public final class SQLStatementAssert {
* @param expected expected parser result
*/
public static void assertIs(final SQLCaseAssertContext assertContext,
final SQLStatement actual, final SQLParserTestCase expected) {
+ if (actual instanceof OracleCreateProcedureStatement || actual
instanceof OracleCreateFunctionStatement) {
+ PLSQLStatementAssert.assertIs(assertContext, actual, expected);
+ return;
+ }
ParameterMarkerAssert.assertCount(assertContext,
actual.getParameterCount(), expected.getParameters().size());
CommentAssert.assertComment(assertContext, actual, expected);
if (actual instanceof DMLStatement) {
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/plsql/PLSQLStatementAssert.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/plsql/PLSQLStatementAssert.java
new file mode 100644
index 00000000000..31795720692
--- /dev/null
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/plsql/PLSQLStatementAssert.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.plsql;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleCreateFunctionStatement;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.ddl.OracleCreateProcedureStatement;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.ProcedureCallNameSegment;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.plsql.SQLStatementSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedDynamicSqlStatementExpressionSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedProcedureCallNameSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedSQLStatementSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.plsql.CreateFunctionTestCase;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.plsql.CreateProcedureTestCase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * PL/SQL statement assert.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class PLSQLStatementAssert {
+
+ /**
+ * Assert PL/SQL statement is correct with expected parser result.
+ *
+ * @param assertContext assert context
+ * @param actual actual PL/SQL statement
+ * @param expected expected parser result
+ */
+ public static void assertIs(final SQLCaseAssertContext assertContext,
final SQLStatement actual, final SQLParserTestCase expected) {
+ if (actual instanceof OracleCreateProcedureStatement && expected
instanceof CreateProcedureTestCase) {
+ OracleCreateProcedureStatement actualStatement =
(OracleCreateProcedureStatement) actual;
+ CreateProcedureTestCase expectedTestCase =
(CreateProcedureTestCase) expected;
+ assertProcedureName(assertContext, actualStatement,
expectedTestCase);
+ assertSQLStatements(assertContext,
actualStatement.getSqlStatements(), expectedTestCase.getSqlStatements());
+ assertProcedureCallNames(assertContext,
actualStatement.getProcedureCallNames(), expectedTestCase.getProcedureCalls());
+ assertDynamicSqlStatementExpressions(assertContext,
actualStatement.getDynamicSqlStatementExpressions(),
expectedTestCase.getDynamicSqlStatementExpressions());
+ }
+ if (actual instanceof OracleCreateFunctionStatement && expected
instanceof CreateFunctionTestCase) {
+ OracleCreateFunctionStatement actualStatement =
(OracleCreateFunctionStatement) actual;
+ CreateFunctionTestCase expectedTestCase = (CreateFunctionTestCase)
expected;
+ assertFunctionName(assertContext, actualStatement,
expectedTestCase);
+ assertSQLStatements(assertContext,
actualStatement.getSqlStatements(), expectedTestCase.getSqlStatements());
+ assertProcedureCallNames(assertContext,
actualStatement.getProcedureCallNames(), expectedTestCase.getProcedureCalls());
+ assertDynamicSqlStatementExpressions(assertContext,
actualStatement.getDynamicSqlStatementExpressions(),
expectedTestCase.getDynamicSqlStatementExpressions());
+ }
+ }
+
+ private static void assertProcedureName(final SQLCaseAssertContext
assertContext, final OracleCreateProcedureStatement actual, final
CreateProcedureTestCase expected) {
+ if (null == expected.getProcedureName()) {
+ assertFalse(actual.getProcedureName().isPresent(),
assertContext.getText("Procedure name should not be exist."));
+ } else {
+ assertTrue(actual.getProcedureName().isPresent(),
assertContext.getText("Procedure name should be exist."));
+ assertThat(assertContext.getText("Procedure name mismatched:"),
actual.getProcedureName().get().getIdentifier().getValue(),
is(expected.getProcedureName().getName()));
+ }
+ }
+
+ private static void assertFunctionName(final SQLCaseAssertContext
assertContext, final OracleCreateFunctionStatement actual, final
CreateFunctionTestCase expected) {
+ if (null == expected.getFunctionName()) {
+ assertFalse(actual.getFunctionName().isPresent(),
assertContext.getText("Function name should not be exist."));
+ } else {
+ assertTrue(actual.getFunctionName().isPresent(),
assertContext.getText("Function name should be exist."));
+ assertThat(assertContext.getText("Function name mismatched:"),
actual.getFunctionName().get().getIdentifier().getValue(),
is(expected.getFunctionName().getName()));
+ }
+ }
+
+ private static void assertSQLStatements(final SQLCaseAssertContext
assertContext, final List<SQLStatementSegment> actual, final
List<ExpectedSQLStatementSegment> expectedSQLStatementSegments) {
+ assertThat(assertContext.getText("SQL statements size mismatched: "),
actual.size(), is(expectedSQLStatementSegments.size()));
+ List<SQLStatementSegment> actualSegments = new ArrayList<>(actual);
+ List<ExpectedSQLStatementSegment> expectedSegments = new
ArrayList<>(expectedSQLStatementSegments);
+ for (int i = 0; i < actualSegments.size(); i++) {
+ SQLStatementSegment actualSegment = actualSegments.get(i);
+ ExpectedSQLStatementSegment expectedSegment =
expectedSegments.get(i);
+ assertThat(assertContext.getText("Start index mismatched:"),
actualSegment.getStartIndex(), is(expectedSegment.getStartIndex()));
+ assertThat(assertContext.getText("End index mismatched:"),
actualSegment.getStopIndex(), is(expectedSegment.getStopIndex()));
+ assertThat(assertContext.getText("SQL statement mismatched:"),
actualSegment.getSqlStatement().getClass().getSimpleName(),
is(expectedSegment.getStatementClassSimpleName()));
+ }
+ }
+
+ private static void assertProcedureCallNames(final SQLCaseAssertContext
assertContext, final List<ProcedureCallNameSegment> actual,
+ final
List<ExpectedProcedureCallNameSegment> expectedProcedureCallSegments) {
+ assertThat(assertContext.getText("Procedure call names size
mismatched: "), actual.size(), is(expectedProcedureCallSegments.size()));
+ List<ProcedureCallNameSegment> actualSegments = new
ArrayList<>(actual);
+ List<ExpectedProcedureCallNameSegment> expectedSegments = new
ArrayList<>(expectedProcedureCallSegments);
+ for (int i = 0; i < actualSegments.size(); i++) {
+ ProcedureCallNameSegment actualSegment = actualSegments.get(i);
+ ExpectedProcedureCallNameSegment expectedSegment =
expectedSegments.get(i);
+ assertThat(assertContext.getText("Procedure call name
mismatched:"), actualSegment.toString(), is(expectedSegment.getName()));
+ }
+ }
+
+ private static void assertDynamicSqlStatementExpressions(final
SQLCaseAssertContext assertContext, final List<ExpressionSegment> actual,
+ final
List<ExpectedDynamicSqlStatementExpressionSegment> expectedExpressionSegments) {
+ assertThat(assertContext.getText("Dynamic SQL statement expressions
size mismatched: "), actual.size(), is(expectedExpressionSegments.size()));
+ List<ExpressionSegment> actualSegments = new ArrayList<>(actual);
+ List<ExpectedDynamicSqlStatementExpressionSegment> expectedSegments =
new ArrayList<>(expectedExpressionSegments);
+ for (int i = 0; i < actualSegments.size(); i++) {
+ ExpressionSegment actualSegment = actualSegments.get(i);
+ ExpectedDynamicSqlStatementExpressionSegment expectedSegment =
expectedSegments.get(i);
+ assertThat(assertContext.getText("Dynamic SQL statement start
index mismatched: "), actualSegment.getStartIndex(),
is(expectedSegment.getStartIndex()));
+ assertThat(assertContext.getText("Dynamic SQL statement stop index
mismatched: "), actualSegment.getStopIndex(),
is(expectedSegment.getStopIndex()));
+ }
+ }
+}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedDynamicSqlStatementExpressionSegment.java
similarity index 79%
copy from
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
copy to
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedDynamicSqlStatementExpressionSegment.java
index bb3c5853ed5..15ab6bc27db 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedDynamicSqlStatementExpressionSegment.java
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
+package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql;
-import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
/**
- * Create procedure statement test case.
+ * Expected dynamic SQL statement expression segment.
*/
-public final class CreateProcedureStatementTestCase extends SQLParserTestCase {
+public final class ExpectedDynamicSqlStatementExpressionSegment extends
AbstractExpectedSQLSegment {
}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedProcedureCallNameSegment.java
similarity index 71%
copy from
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
copy to
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedProcedureCallNameSegment.java
index bb3c5853ed5..3fd04480a03 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedProcedureCallNameSegment.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
+package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql;
-import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import lombok.Getter;
+import lombok.Setter;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+
+import javax.xml.bind.annotation.XmlAttribute;
/**
- * Create procedure statement test case.
+ * Expected procedure call name segment.
*/
-public final class CreateProcedureStatementTestCase extends SQLParserTestCase {
+@Getter
+@Setter
+public final class ExpectedProcedureCallNameSegment extends
AbstractExpectedSQLSegment {
+
+ @XmlAttribute
+ private String name;
}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedRoutineName.java
similarity index 73%
copy from
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
copy to
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedRoutineName.java
index bb3c5853ed5..0509d93cc15 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedRoutineName.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
+package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql;
-import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import lombok.Getter;
+import lombok.Setter;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+
+import javax.xml.bind.annotation.XmlAttribute;
/**
- * Create procedure statement test case.
+ * Expected routine name.
*/
-public final class CreateProcedureStatementTestCase extends SQLParserTestCase {
+@Getter
+@Setter
+public final class ExpectedRoutineName extends AbstractExpectedSQLSegment {
+
+ @XmlAttribute
+ private String name;
}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedSQLStatementSegment.java
similarity index 69%
copy from
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
copy to
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedSQLStatementSegment.java
index bb3c5853ed5..e2425bbcc87 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plsql/ExpectedSQLStatementSegment.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
+package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql;
-import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import lombok.Getter;
+import lombok.Setter;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+
+import javax.xml.bind.annotation.XmlAttribute;
/**
- * Create procedure statement test case.
+ * Expected SQL statement segment.
*/
-public final class CreateProcedureStatementTestCase extends SQLParserTestCase {
+@Getter
+@Setter
+public final class ExpectedSQLStatementSegment extends
AbstractExpectedSQLSegment {
+
+ @XmlAttribute(name = "statement-class-simple-name")
+ private String statementClassSimpleName;
}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
index 2cf7e238fac..b14876ea8ce 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateFunctionStatementTestCase.java
@@ -17,10 +17,38 @@
package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
+import lombok.Getter;
+import lombok.Setter;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedDynamicSqlStatementExpressionSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedProcedureCallNameSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedRoutineName;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedSQLStatementSegment;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import java.util.LinkedList;
+import java.util.List;
/**
* Create function statement test case.
*/
+@Getter
+@Setter
public final class CreateFunctionStatementTestCase extends SQLParserTestCase {
+
+ @XmlElement(name = "function-name")
+ private ExpectedRoutineName functionName;
+
+ @XmlElementWrapper(name = "sql-statements")
+ @XmlElement(name = "sql-statement")
+ private List<ExpectedSQLStatementSegment> sqlStatements = new
LinkedList<>();
+
+ @XmlElementWrapper(name = "procedure-calls")
+ @XmlElement(name = "procedure-call")
+ private List<ExpectedProcedureCallNameSegment> procedureCalls = new
LinkedList<>();
+
+ @XmlElementWrapper(name = "dynamic-sql-statement-expressions")
+ @XmlElement(name = "dynamic-sql-statement-expression")
+ private List<ExpectedDynamicSqlStatementExpressionSegment>
dynamicSqlStatementExpressions = new LinkedList<>();
}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
index bb3c5853ed5..d18d1ca17b0 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/CreateProcedureStatementTestCase.java
@@ -17,10 +17,38 @@
package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl;
+import lombok.Getter;
+import lombok.Setter;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedDynamicSqlStatementExpressionSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedProcedureCallNameSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedRoutineName;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedSQLStatementSegment;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import java.util.LinkedList;
+import java.util.List;
/**
* Create procedure statement test case.
*/
+@Getter
+@Setter
public final class CreateProcedureStatementTestCase extends SQLParserTestCase {
+
+ @XmlElement(name = "procedure-name")
+ private ExpectedRoutineName procedureName;
+
+ @XmlElementWrapper(name = "sql-statements")
+ @XmlElement(name = "sql-statement")
+ private List<ExpectedSQLStatementSegment> sqlStatements = new
LinkedList<>();
+
+ @XmlElementWrapper(name = "procedure-calls")
+ @XmlElement(name = "procedure-call")
+ private List<ExpectedProcedureCallNameSegment> procedureCalls = new
LinkedList<>();
+
+ @XmlElementWrapper(name = "dynamic-sql-statement-expressions")
+ @XmlElement(name = "dynamic-sql-statement-expression")
+ private List<ExpectedDynamicSqlStatementExpressionSegment>
dynamicSqlStatementExpressions = new LinkedList<>();
}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/plsql/CreateFunctionTestCase.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/plsql/CreateFunctionTestCase.java
new file mode 100644
index 00000000000..0788d2c5170
--- /dev/null
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/plsql/CreateFunctionTestCase.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.plsql;
+
+import lombok.Getter;
+import lombok.Setter;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedDynamicSqlStatementExpressionSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedProcedureCallNameSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedRoutineName;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedSQLStatementSegment;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Oracle create function test case.
+ */
+@Getter
+@Setter
+public final class CreateFunctionTestCase extends SQLParserTestCase {
+
+ @XmlElement(name = "function-name")
+ private ExpectedRoutineName functionName;
+
+ @XmlElementWrapper(name = "sql-statements")
+ @XmlElement(name = "sql-statement")
+ private List<ExpectedSQLStatementSegment> sqlStatements = new
LinkedList<>();
+
+ @XmlElementWrapper(name = "procedure-calls")
+ @XmlElement(name = "procedure-call")
+ private List<ExpectedProcedureCallNameSegment> procedureCalls = new
LinkedList<>();
+
+ @XmlElementWrapper(name = "dynamic-sql-statement-expressions")
+ @XmlElement(name = "dynamic-sql-statement-expression")
+ private List<ExpectedDynamicSqlStatementExpressionSegment>
dynamicSqlStatementExpressions = new LinkedList<>();
+}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/plsql/CreateProcedureTestCase.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/plsql/CreateProcedureTestCase.java
new file mode 100644
index 00000000000..fe02ef653ab
--- /dev/null
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/plsql/CreateProcedureTestCase.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.plsql;
+
+import lombok.Getter;
+import lombok.Setter;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedDynamicSqlStatementExpressionSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedProcedureCallNameSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedRoutineName;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plsql.ExpectedSQLStatementSegment;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Oracle create procedure test case.
+ */
+@Getter
+@Setter
+public final class CreateProcedureTestCase extends SQLParserTestCase {
+
+ @XmlElement(name = "procedure-name")
+ private ExpectedRoutineName procedureName;
+
+ @XmlElementWrapper(name = "sql-statements")
+ @XmlElement(name = "sql-statement")
+ private List<ExpectedSQLStatementSegment> sqlStatements = new
LinkedList<>();
+
+ @XmlElementWrapper(name = "procedure-calls")
+ @XmlElement(name = "procedure-call")
+ private List<ExpectedProcedureCallNameSegment> procedureCalls = new
LinkedList<>();
+
+ @XmlElementWrapper(name = "dynamic-sql-statement-expressions")
+ @XmlElement(name = "dynamic-sql-statement-expression")
+ private List<ExpectedDynamicSqlStatementExpressionSegment>
dynamicSqlStatementExpressions = new LinkedList<>();
+}
diff --git a/test/it/parser/src/main/resources/case/plsql/create-function.xml
b/test/it/parser/src/main/resources/case/plsql/create-function.xml
new file mode 100644
index 00000000000..25c85ada135
--- /dev/null
+++ b/test/it/parser/src/main/resources/case/plsql/create-function.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<sql-parser-test-cases>
+ <create-function sql-case-id="pl_sql_create_function" />
+</sql-parser-test-cases>
diff --git a/test/it/parser/src/main/resources/case/plsql/create-procedure.xml
b/test/it/parser/src/main/resources/case/plsql/create-procedure.xml
new file mode 100644
index 00000000000..44d0f76e012
--- /dev/null
+++ b/test/it/parser/src/main/resources/case/plsql/create-procedure.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<sql-parser-test-cases>
+ <create-procedure sql-case-id="pl_sql_create_procedure">
+ <procedure-name name="test_procedure" />
+ <sql-statements>
+ <sql-statement start-index="167" stop-index="192"
statement-class-simple-name="OracleSavepointStatement" />
+ <sql-statement start-index="210" stop-index="274"
statement-class-simple-name="OracleSelectStatement" />
+ <sql-statement start-index="1205" stop-index="1210"
statement-class-simple-name="OracleCommitStatement" />
+ <sql-statement start-index="1251" stop-index="1293"
statement-class-simple-name="OracleRollbackStatement" />
+ <sql-statement start-index="1408" stop-index="1450"
statement-class-simple-name="OracleRollbackStatement" />
+ </sql-statements>
+ <procedure-calls>
+ <procedure-call name="DBMS_OUTPUT.PUT_LINE" />
+ <procedure-call name="DBMS_OUTPUT.PUT_LINE" />
+ </procedure-calls>
+ </create-procedure>
+</sql-parser-test-cases>
diff --git
a/test/it/parser/src/main/resources/sql/supported/plsql/create-function.xml
b/test/it/parser/src/main/resources/sql/supported/plsql/create-function.xml
new file mode 100644
index 00000000000..6346f011538
--- /dev/null
+++ b/test/it/parser/src/main/resources/sql/supported/plsql/create-function.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<sql-cases>
+ <sql-case id="pl_sql_create_function" db-types="Oracle"
case-types="LITERAL" value="CREATE OR REPLACE EDITIONABLE FUNCTION
"TEST"."test_function" ( v_orgid IN NUMBER)
RETURN NUMBER AS v_partAmount NUMBER(9,2);--兼岗人数
v_factnums NUMBER(9,2);--实际人数 v_cnt NUMBER;
BEGIN v_factnums:=0;
v_partAmount:=0; BEGIN--1 --- 部门实际的兼岗人数
[...]
+</sql-cases>
diff --git
a/test/it/parser/src/main/resources/sql/supported/plsql/create-procedure.xml
b/test/it/parser/src/main/resources/sql/supported/plsql/create-procedure.xml
new file mode 100644
index 00000000000..747de6ebeca
--- /dev/null
+++ b/test/it/parser/src/main/resources/sql/supported/plsql/create-procedure.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<sql-cases>
+ <sql-case id="pl_sql_create_procedure" db-types="Oracle" value="create or
replace procedure test_procedure(P_RETVAL out varchar2) is E_EXCEPTION
EXCEPTION; v_bendate date; v_enddate date; v_day varchar2(30); begin
SAVEPOINT cp_SHOPBudget_Gy; P_RETVAL := 0; select upper(trim(to_char(sysdate,
'day'))) into v_day from dual; if v_day = 'MONDAY' then return; else
case when v_day = 'MONDAY' then v_bendate := TRUNC(SYSDATE) - 7;
v_enddate := TRUNC( [...]
+</sql-cases>