This is an automated email from the ASF dual-hosted git repository.

FlyingZC 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 7eb84d44193 Support Oracle procedure parser and binder (#39231)
7eb84d44193 is described below

commit 7eb84d44193ec981090c22984c56340cd4197e40
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Fri Jul 24 16:53:45 2026 +0800

    Support Oracle procedure parser and binder (#39231)
    
    * Support Oracle procedure parser and binder
    
    * Allow CHILD as Oracle DML table alias
    
    * Preserve Oracle current of clause in DML AST
    
    * Update RELEASE-NOTES.md
---
 RELEASE-NOTES.md                                   |   1 +
 .../dml/expression/type/ColumnSegmentBinder.java   |  27 +++-
 .../expression/type/ColumnSegmentBinderTest.java   |  14 ++
 .../src/main/antlr4/imports/oracle/BaseRule.g4     |   7 +-
 .../src/main/antlr4/imports/oracle/DMLStatement.g4 |  78 ++++++++---
 .../main/antlr4/imports/oracle/OracleKeyword.g4    |   4 +
 .../oracle/src/main/antlr4/imports/oracle/PLSQL.g4 | 127 +++++++++++++-----
 .../statement/type/OracleDDLStatementVisitor.java  |  81 +++++++++---
 .../statement/type/OracleDMLStatementVisitor.java  | 142 +++++++++++++++++----
 .../ddl/procedure/AlterProcedureStatement.java     |  16 +++
 .../type/ddl/procedure/DropProcedureStatement.java |  16 +++
 .../core/statement/type/dml/CallStatement.java     |  18 +++
 .../binder/src/test/resources/cases/dml/insert.xml |  66 +++++++++-
 .../binder/src/test/resources/cases/dml/update.xml |  49 +++++++
 .../binder/src/test/resources/sqls/dml/insert.xml  |   1 +
 .../binder/src/test/resources/sqls/dml/update.xml  |   1 +
 .../it/parser/src/main/resources/case/dml/call.xml |  36 ++++--
 .../parser/src/main/resources/case/dml/delete.xml  |   9 ++
 .../parser/src/main/resources/case/dml/update.xml  |  19 +++
 .../src/main/resources/sql/supported/dml/call.xml  |   2 +
 .../main/resources/sql/supported/dml/delete.xml    |   1 +
 .../main/resources/sql/supported/dml/update.xml    |   1 +
 22 files changed, 605 insertions(+), 111 deletions(-)

diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 5b5576324ec..adfc1080407 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -69,6 +69,7 @@
 1. SQL Parser: Enhance Hive SQL parser to support CTE, lateral view, table 
sampling, transform and set operations - 
[#39008](https://github.com/apache/shardingsphere/pull/39008)
 1. SQL Parser: Add Hive CTAS and window function parsing - 
[#39188](https://github.com/apache/shardingsphere/pull/39188)
 1. SQL Parser: Support SQLServer table variable declaration parse - 
[#38904](https://github.com/apache/shardingsphere/pull/38904)
+1. SQL Parser: Support Oracle procedure parser and binder - 
[#39231](https://github.com/apache/shardingsphere/pull/39231)
 1. SQL Binder: Support select order by index bind metadata - 
[#38386](https://github.com/apache/shardingsphere/pull/38386)
 1. SQL Binder: Support SQL bind when with temp table name is same with 
physical table - [#38411](https://github.com/apache/shardingsphere/pull/38411)
 1. Metadata: Support Oracle dictionary views by adding SYS default system 
schema and YAML definitions - 
[#38388](https://github.com/apache/shardingsphere/pull/38388)
diff --git 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ColumnSegmentBinder.java
 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ColumnSegmentBinder.java
index e44a8bb3661..8966d60a4f9 100644
--- 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ColumnSegmentBinder.java
+++ 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ColumnSegmentBinder.java
@@ -204,7 +204,7 @@ public final class ColumnSegmentBinder {
             ColumnSegment inputColumnSegment = 
findInputColumnSegmentFromExternalTables(segment, 
binderContext.getExternalTableBinderContexts()).orElse(null);
             result = new ColumnSegmentInfo(inputColumnSegment, null == 
inputColumnSegment ? TableSourceType.TEMPORARY_TABLE : 
inputColumnSegment.getColumnBoundInfo().getTableSourceType());
         }
-        if (isNotFoundInputColumn(result, segment)) {
+        if (isNeedFindInputColumnByVariables(result, segment, 
binderContext.getSqlStatement().getVariableNames())) {
             result = new 
ColumnSegmentInfo(findInputColumnSegmentByVariables(segment, 
binderContext.getSqlStatement().getVariableNames()).orElse(null), 
TableSourceType.TEMPORARY_TABLE);
         }
         if (isNotFoundInputColumn(result, segment)) {
@@ -226,6 +226,10 @@ public final class ColumnSegmentBinder {
         return !segmentInfo.getInputColumnSegment().isPresent() && 
!segment.getOwner().isPresent();
     }
     
+    private static boolean isNeedFindInputColumnByVariables(final 
ColumnSegmentInfo segmentInfo, final ColumnSegment segment, final 
Collection<String> variableNames) {
+        return !segmentInfo.getInputColumnSegment().isPresent() && 
(!segment.getOwner().isPresent() || isVariableOwner(segment, variableNames));
+    }
+    
     private static ColumnSegmentInfo getInputInfoFromTableBinderContexts(final 
Collection<TableSegmentBinderContext> tableBinderContexts,
                                                                          final 
ColumnSegment segment, final SegmentType parentSegmentType) {
         ColumnSegment inputColumnSegment = null;
@@ -309,14 +313,27 @@ public final class ColumnSegmentBinder {
         if (variableNames.isEmpty()) {
             return Optional.empty();
         }
-        if (variableNames.contains(segment.getIdentifier().getValue())) {
-            ColumnSegment result = new ColumnSegment(0, 0, 
segment.getIdentifier());
-            result.setVariable(true);
-            return Optional.of(result);
+        if (!segment.getOwner().isPresent() && 
containsVariableName(variableNames, segment.getIdentifier().getValue()) || 
isVariableOwner(segment, variableNames)) {
+            return Optional.of(createVariableColumnSegment(segment));
         }
         return Optional.empty();
     }
     
+    private static boolean isVariableOwner(final ColumnSegment segment, final 
Collection<String> variableNames) {
+        return segment.getOwner().isPresent() && 
containsVariableName(variableNames, 
segment.getOwner().get().getIdentifier().getValue());
+    }
+    
+    private static boolean containsVariableName(final Collection<String> 
variableNames, final String variableName) {
+        return variableNames.stream().anyMatch(each -> 
each.equalsIgnoreCase(variableName));
+    }
+    
+    private static ColumnSegment createVariableColumnSegment(final 
ColumnSegment segment) {
+        ColumnSegment result = copy(segment);
+        segment.getOwner().ifPresent(result::setOwner);
+        result.setVariable(true);
+        return result;
+    }
+    
     private static boolean isSkipColumnBind(final 
Collection<TableSegmentBinderContext> tableBinderContexts, final 
Collection<TableSegmentBinderContext> outerBinderContexts) {
         for (TableSegmentBinderContext each : tableBinderContexts) {
             if (each instanceof FunctionTableSegmentBinderContext) {
diff --git 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ColumnSegmentBinderTest.java
 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ColumnSegmentBinderTest.java
index a8c6b3067ff..1a7d3c9466e 100644
--- 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ColumnSegmentBinderTest.java
+++ 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ColumnSegmentBinderTest.java
@@ -226,6 +226,20 @@ class ColumnSegmentBinderTest {
         assertThat(actual.getColumnBoundInfo().getOriginalColumn().getValue(), 
is("type_struct"));
     }
     
+    @Test
+    void assertBindProcedureRecordFieldVariable() {
+        SelectStatement selectStatement = 
SelectStatement.builder().databaseType(TypedSPILoader.getService(DatabaseType.class,
 "MySQL")).build();
+        selectStatement.getVariableNames().add("v_record");
+        SQLStatementBinderContext binderContext = new 
SQLStatementBinderContext(mock(ShardingSphereMetaData.class), "foo_db", new 
HintValueContext(), selectStatement);
+        ColumnSegment columnSegment = new ColumnSegment(0, 20, new 
IdentifierValue("sensitive_a"));
+        columnSegment.setOwner(new OwnerSegment(0, 7, new 
IdentifierValue("v_record")));
+        ColumnSegment actual = ColumnSegmentBinder.bind(columnSegment, 
SegmentType.PROJECTION, binderContext, LinkedHashMultimap.create(), 
LinkedHashMultimap.create());
+        assertTrue(actual.isVariable());
+        assertTrue(actual.getOwner().isPresent());
+        assertThat(actual.getExpression(), is("v_record.sensitive_a"));
+        assertThat(actual.getColumnBoundInfo().getTableSourceType(), 
is(TableSourceType.TEMPORARY_TABLE));
+    }
+    
     @Test
     void assertBindExcludedColumnInSetAssignment() {
         SelectStatement selectStatement = mock(SelectStatement.class);
diff --git 
a/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4 
b/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4
index 6c50ff334e8..6409b91e107 100644
--- 
a/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4
+++ 
b/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4
@@ -364,11 +364,13 @@ logGroupName
     ;
 
 columnNames
-    : LP_? columnName (COMMA_ columnName)* RP_?
+    : LP_ columnName (COMMA_ columnName)* RP_
+    | columnName (COMMA_ columnName)*
     ;
 
 tableNames
-    : LP_? tableName (COMMA_ tableName)* RP_?
+    : LP_ tableName (COMMA_ tableName)* RP_
+    | tableName (COMMA_ tableName)*
     ;
 
 oracleId
@@ -403,7 +405,6 @@ exprList
     : LP_ exprs RP_
     ;
 
-// TODO comb expr
 expr
     : expr andOperator expr
     | expr orOperator expr
diff --git 
a/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/DMLStatement.g4
 
b/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/DMLStatement.g4
index 8e556cce318..f4370934e42 100644
--- 
a/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/DMLStatement.g4
+++ 
b/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/DMLStatement.g4
@@ -28,11 +28,15 @@ insertSingleTable
     ;
 
 insertMultiTable
-    : (ALL multiTableElement+ | conditionalInsertClause) selectSubquery
+    : (ALL multiTableElements | conditionalInsertClause) selectSubquery
     ;
 
 multiTableElement
-    : insertIntoClause insertValuesClause? errorLoggingClause?
+    : multiTableInsertIntoClause insertValuesClause? errorLoggingClause?
+    ;
+
+multiTableElements
+    : multiTableElement+
     ;
 
 conditionalInsertClause
@@ -40,16 +44,19 @@ conditionalInsertClause
     ;
 
 conditionalInsertWhenPart
-    : WHEN expr THEN multiTableElement+
+    : WHEN expr THEN multiTableElements
     ;
 
 conditionalInsertElsePart
-    : ELSE multiTableElement+
+    : ELSE multiTableElements
     ;
 
 insertIntoClause
-    : INTO dmlTableExprClause
-    | INTO dmlTableExprClause columnNames?
+    : INTO dmlTableExprClause insertColumnNames?
+    ;
+
+multiTableInsertIntoClause
+    : INTO insertDmlTableExprClause insertColumnNames?
     ;
 
 insertValuesClause
@@ -65,8 +72,19 @@ returningIntoItem
     ;
 
 dmlTableExprClause
-    : dmlTableClause | dmlSubqueryClause | tableCollectionExpr
-    | (dmlTableClause | dmlSubqueryClause | tableCollectionExpr) alias
+    : dmlTableClause dmlTableAlias?
+    | dmlSubqueryClause dmlTableAlias?
+    | tableCollectionExpr dmlTableAlias?
+    ;
+
+insertDmlTableExprClause
+    : dmlTableClause
+    | dmlSubqueryClause
+    | tableCollectionExpr
+    ;
+
+insertColumnNames
+    : LP_ columnName (COMMA_ columnName)* RP_
     ;
 
 dmlTableClause
@@ -96,7 +114,7 @@ collectionExpr
     ;
 
 update
-    : UPDATE hint? updateSpecification (AS? alias)? updateSetClause 
whereClause? returningClause? errorLoggingClause?
+    : UPDATE hint? updateSpecification (AS? alias)? updateSetClause 
(whereClause | currentOfClause)? returningClause? errorLoggingClause?
     ;
 
 updateSpecification
@@ -129,7 +147,7 @@ assignmentValue
     ;
 
 delete
-    : DELETE hint? FROM? deleteSpecification alias? whereClause? 
returningClause? errorLoggingClause?
+    : DELETE hint? FROM? deleteSpecification alias? (whereClause | 
currentOfClause)? returningClause? errorLoggingClause?
     ;
 
 deleteSpecification
@@ -162,7 +180,17 @@ selectIntoClause
     ;
 
 variableNames
-    : variableName (COMMA_ variableName)*
+    : selectIntoTarget (COMMA_ selectIntoTarget)*
+    ;
+
+selectIntoTarget
+    : parameterMarker
+    | COLON_? variableName selectIntoTargetSuffix*
+    ;
+
+selectIntoTargetSuffix
+    : LP_ (expr (COMMA_ expr)*)? RP_
+    | DOT_ identifier
     ;
 
 variableName
@@ -182,7 +210,7 @@ functionDeclaration
     ;
 
 functionHeading
-    : FUNCTION functionName (LP_ parameterDeclaration (SQ_ 
parameterDeclaration)* RP_)? RETURN dataType
+    : FUNCTION functionName (LP_ parameterDeclaration (COMMA_ 
parameterDeclaration)* RP_)? RETURN dataType
     ;
 
 parameterDeclaration
@@ -194,7 +222,7 @@ procedureDeclaration
     ;
 
 procedureHeading
-    : PROCEDURE procedureName (LP_ parameterDeclaration (SQ_ 
parameterDeclaration)* RP_)?
+    : PROCEDURE procedureName (LP_ parameterDeclaration (COMMA_ 
parameterDeclaration)* RP_)?
     ;
 
 procedureProperties
@@ -453,11 +481,27 @@ fromClauseOption
     ;
 
 selectTableReference
-    : queryTableExprClause | containersClause | shardsClause
-    | (queryTableExprClause | containersClause | shardsClause) alias?
+    : (queryTableExprClause | containersClause | shardsClause) dmlTableAlias?
     | LP_ joinClause RP_
     ;
 
+dmlTableAlias
+    : IDENTIFIER_
+    | DOUBLE_QUOTED_TEXT
+    | STRING_
+    | SINGLE_C
+    | SINGLE_K
+    | SINGLE_M
+    | SINGLE_G
+    | SINGLE_T
+    | SINGLE_P
+    | SINGLE_E
+    | SINGLE_H
+    | V1
+    | LENGTH
+    | CHILD
+    ;
+
 queryTableExprClause
     : (ONLY LP_ queryTableExpr RP_ | queryTableExpr) flashbackQueryClause? 
(pivotClause | unpivotClause | rowPatternClause)?
     ;
@@ -614,6 +658,10 @@ whereClause
     : WHERE expr
     ;
 
+currentOfClause
+    : WHERE CURRENT OF cursorName
+    ;
+
 hierarchicalQueryClause
     : CONNECT BY NOCYCLE? expr (START WITH expr)?
     | START WITH expr CONNECT BY NOCYCLE? expr
diff --git 
a/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/OracleKeyword.g4
 
b/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/OracleKeyword.g4
index 94aa4557bd0..d3a0d54efa8 100644
--- 
a/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/OracleKeyword.g4
+++ 
b/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/OracleKeyword.g4
@@ -5960,6 +5960,10 @@ SERVERERROR
     :S E R V E R E R R O R
     ;
 
+SERIALLY_REUSABLE
+    :S E R I A L L Y UL_ R E U S A B L E
+    ;
+
 SESSIONS_PER_USER
     :S E S S I O N S UL_ P E R UL_ U S E R
     ;
diff --git 
a/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/PLSQL.g4 
b/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/PLSQL.g4
index 31f226bf60a..20694cf95eb 100644
--- a/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/PLSQL.g4
+++ b/parser/sql/engine/dialect/oracle/src/main/antlr4/imports/oracle/PLSQL.g4
@@ -19,8 +19,31 @@ grammar PLSQL;
 
 import Keyword, BaseRule, DDLStatement, DMLStatement, TCLStatement;
 
+@parser::members {
+    private boolean isNotPlsqlBlockTerminator() {
+        switch (_input.LA(1)) {
+            case END:
+            case ELSE:
+            case ELSIF:
+            case EXCEPTION:
+            case WHEN:
+                return false;
+            default:
+                return true;
+        }
+    }
+}
+
 call
-    : CALL
+    : CALL (schemaName DOT_)? procedureName (LP_ (callArgument (COMMA_ 
callArgument)*)? RP_)? callIntoClause?
+    ;
+
+callArgument
+    : expression
+    ;
+
+callIntoClause
+    : INTO (placeholder | variableName)
     ;
 
 alterProcedure
@@ -75,17 +98,21 @@ returnDateType
     ;
 
 body
-    : BEGIN statement+ (EXCEPTION (exceptionHandler)+)? END (identifier)? 
SEMI_?
+    : BEGIN plsqlStatements (EXCEPTION (exceptionHandler)+)? END (identifier)? 
SEMI_?
+    ;
+
+plsqlStatements
+    : {isNotPlsqlBlockTerminator()}? statement ({isNotPlsqlBlockTerminator()}? 
statement)*
     ;
 
-// 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_) *)?
+    : {isNotPlsqlBlockTerminator()}? (SIGNED_LEFT_SHIFT_ label 
SIGNED_RIGHT_SHIFT_ (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_) *)?
         (assignStatement
         | basicLoopStatement
         | caseStatement
         | closeStatement
         | continueStatement
+        | collectionMethodStatement
         | cursorForLoopStatement
         | executeImmediateStatement
         | exitStatement
@@ -94,6 +121,7 @@ statement
         | forallStatement
         | gotoStatement
         | ifStatement
+        | inlinePragma
         | modifyingStatement
         | nullStatement
         | openStatement
@@ -114,20 +142,24 @@ assignStatement
     ;
 
 assignStatementTarget
-    : collectionVariable=name (LP_ INTEGER_ RP_)?
-    // TODO cursor_variable, out_parameter, scalar_variable
-    | name
-    | placeholder
+    : placeholder
     | hostCursorVariable
-    // TODO object.attribute, record_variable.field
-    | attributeName
+    | plsqlVariableTarget
+    ;
+
+plsqlVariableTarget
+    : name plsqlTargetSuffix*
+    ;
+
+plsqlTargetSuffix
+    : LP_ (expression (COMMA_ expression)*)? RP_
+    | DOT_ identifier
     ;
 
 placeholder
     : COLON_ hostVariable=name (DOT_ columnName)? (COLON_ 
indicatorVariable=name)?
     ;
 
-// TODO PL/SQL grammar more than expr
 expression
     : expr
     ;
@@ -138,7 +170,7 @@ booleanExpression
 
 basicLoopStatement
     : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)?
-    LOOP statement+ END LOOP label? SEMI_
+    LOOP plsqlStatements END LOOP label? SEMI_
     ;
 
 caseStatement
@@ -148,16 +180,16 @@ caseStatement
 simpleCaseStatement
     : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)?
     CASE selector=expression
-    (WHEN booleanExpression THEN statement)+
-    (ELSE statement+)?
+    (WHEN booleanExpression THEN plsqlStatements)+
+    (ELSE plsqlStatements)?
     END CASE label? SEMI_
     ;
 
 searchedCaseStatement
     : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)?
     CASE
-    (WHEN booleanExpression THEN statement+)+
-    (ELSE statement+)?
+    (WHEN booleanExpression THEN plsqlStatements)+
+    (ELSE plsqlStatements)?
     END CASE label? SEMI_
     ;
 
@@ -174,7 +206,7 @@ cursorForLoopStatement
     (cursor (LP_ actualCursorParameter (COMMA_? actualCursorParameter)* RP_)?
     | LP_ select RP_
     )
-    LOOP statement+ END LOOP label? SEMI_
+    LOOP plsqlStatements END LOOP label? SEMI_
     ;
 
 executeImmediateStatement
@@ -201,7 +233,7 @@ fetchStatement
 forLoopStatement
     : (SIGNED_LEFT_SHIFT_ label SIGNED_RIGHT_SHIFT_)?
     FOR iterator
-        LOOP statement+
+        LOOP plsqlStatements
     END LOOP label? SEMI_
     ;
 
@@ -311,13 +343,13 @@ gotoStatement
     ;
 
 ifStatement
-    : (IF booleanExpression THEN statement+)*
-    (ELSIF booleanExpression THEN statement+)*
-    (ELSE statement+)?
-    (END IF SEMI_)+
+    : IF booleanExpression THEN plsqlStatements
+    (ELSIF booleanExpression THEN plsqlStatements)*
+    (ELSE plsqlStatements)?
+    END IF SEMI_
     ;
 
-modifyingStatement: IF modifyingExpression THEN statement+ (ELSIF 
modifyingExpression THEN statement+)* (ELSE statement+)? END IF SEMI_;
+modifyingStatement: IF modifyingExpression THEN plsqlStatements (ELSIF 
modifyingExpression THEN plsqlStatements)* (ELSE plsqlStatements)? END IF SEMI_;
 
 nullStatement
     : NULL SEMI_
@@ -331,6 +363,18 @@ cursor
     : variableName
     ;
 
+collectionMethodStatement
+    : collectionMethodCall SEMI_
+    ;
+
+collectionMethodCall
+    : name DOT_ collectionMethodName (LP_ (expression (COMMA_ expression)*)? 
RP_)?
+    ;
+
+collectionMethodName
+    : DELETE | EXISTS | COUNT | LIMIT | FIRST | LAST | PRIOR | NEXT | EXTEND | 
TRIM
+    ;
+
 openForStatement
     : OPEN (cursorVariable | hostCursorVariable) FOR (select | dynamicSqlStmt) 
plsqlUsingClause? SEMI_
     ;
@@ -356,7 +400,11 @@ plsqlBlock
     ;
 
 procedureCall
-    : (packageName DOT_)? procedureName (LP_ (parameter=expression (COMMA_ 
parameter=expression)*)? RP_)? SEMI_
+    : (packageName DOT_)? procedureName (LP_ (procedureCallParameter (COMMA_ 
procedureCallParameter)*)? RP_)? SEMI_
+    ;
+
+procedureCallParameter
+    : (identifier EQ_ GT_)? expression
     ;
 
 raiseStatement
@@ -371,9 +419,14 @@ 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)
+    : INTO plsqlIntoTarget (COMMA_ plsqlIntoTarget)*
+    ;
+
+plsqlIntoTarget
+    : plsqlVariableTarget
+    | placeholder
+    | hostArray
     ;
 
 record
@@ -381,7 +434,7 @@ record
     ;
 
 bulkCollectIntoClause
-    : BULK COLLECT INTO (collection=name | hostArray)
+    : BULK COLLECT INTO plsqlIntoTarget (COMMA_ plsqlIntoTarget)*
     ;
 
 hostArray
@@ -398,7 +451,6 @@ actualCursorParameter
 
 sqlStatementInPlsql
     : (commit
-    // TODO collection_method_call
     | delete
     | insert
     | lock
@@ -412,11 +464,11 @@ sqlStatementInPlsql
 
 whileLoopStatement
     : WHILE booleanExpression
-    LOOP statement+ END LOOP label? SEMI_
+    LOOP plsqlStatements END LOOP label? SEMI_
     ;
 
 exceptionHandler
-    : WHEN ((typeName (OR typeName)*)| OTHERS) THEN statement+
+    : WHEN ((typeName (OR typeName)*)| OTHERS) THEN plsqlStatements
     ;
 
 declareSection
@@ -440,7 +492,7 @@ cursorDefinition
     ;
 
 functionDefinition
-    : functionHeading (DETERMINISTIC | PIPELINED | PARALLEL_ENABLE | 
resultCacheClause)+  (IS | AS) (declareSection ? body | callSpec)
+    : functionHeading (DETERMINISTIC | PIPELINED | PARALLEL_ENABLE | 
resultCacheClause)*  (IS | AS) (declareSection ? body | callSpec)
     ;
 
 procedureDefinition
@@ -546,7 +598,7 @@ refCursorTypeDefinition
     ;
 
 subtypeDefinition
-    : SUBTYPE typeName IS dataType (constraint | characterSetClause)? (NOT 
NULL)?
+    : SUBTYPE typeName IS dataType (constraint | characterSetClause)? (NOT 
NULL)? SEMI_
     ;
 
 constraint
@@ -575,7 +627,8 @@ rowtypeAttribute
 
 pragma
     : autonomousTransPragma | restrictReferencesPragma | exceptionInitPragma
-    // TODO Support more pragma
+    | inlinePragma
+    | seriallyReusablePragma
     ;
 
 exceptionInitPragma
@@ -590,6 +643,14 @@ autonomousTransPragma
     : PRAGMA AUTONOMOUS_TRANSACTION SEMI_
     ;
 
+inlinePragma
+    : PRAGMA INLINE LP_ name COMMA_ stringLiterals RP_ SEMI_
+    ;
+
+seriallyReusablePragma
+    : PRAGMA SERIALLY_REUSABLE SEMI_
+    ;
+
 plsqlTriggerSource
     : (schemaName DOT_)? triggerName sharingClause? defaultCollationClause? 
(simpleDmlTrigger | systemTrigger)
     ;
diff --git 
a/parser/sql/engine/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/engine/oracle/visitor/statement/type/OracleDDLStatementVisitor.java
 
b/parser/sql/engine/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/engine/oracle/visitor/statement/type/OracleDDLStatementVisitor.java
index fe3f0aeae55..330beb87799 100644
--- 
a/parser/sql/engine/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/engine/oracle/visitor/statement/type/OracleDDLStatementVisitor.java
+++ 
b/parser/sql/engine/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/engine/oracle/visitor/statement/type/OracleDDLStatementVisitor.java
@@ -111,6 +111,7 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Create
 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.CursorParameterDecContext;
 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;
@@ -156,11 +157,14 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Dynami
 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.ForallStatementContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ForLoopStatementContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FunctionContext;
 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.IterandDeclContext;
 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;
@@ -182,7 +186,9 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Parame
 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.PlsqlStatementsContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ProcedureCallContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ProcedureNameContext;
 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;
@@ -1417,19 +1423,25 @@ public final class OracleDDLStatementVisitor extends 
OracleStatementVisitor impl
     }
     
     private FunctionNameSegment visitProcedureName(final 
PlsqlProcedureSourceContext ctx) {
-        SchemaNameContext schemaName = ctx.schemaName();
-        IdentifierValue procedureName = (IdentifierValue) 
visit(ctx.procedureName().identifier());
+        return createProcedureNameSegment(ctx.schemaName(), 
ctx.procedureName());
+    }
+    
+    private FunctionNameSegment createProcedureNameSegment(final 
SchemaNameContext schemaName, final ProcedureNameContext procedureNameContext) {
+        IdentifierValue procedureName = (IdentifierValue) 
visit(procedureNameContext.identifier());
         if (null == schemaName) {
-            return new 
FunctionNameSegment(ctx.procedureName().start.getStartIndex(), 
ctx.procedureName().stop.getStopIndex(), procedureName);
+            return new 
FunctionNameSegment(procedureNameContext.start.getStartIndex(), 
procedureNameContext.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);
+        FunctionNameSegment result = new 
FunctionNameSegment(schemaName.start.getStartIndex(), 
procedureNameContext.stop.getStopIndex(), procedureName);
         result.setOwner(owner);
         return result;
     }
     
     @Override
     public ASTNode visitCursorDefinition(final CursorDefinitionContext ctx) {
+        for (CursorParameterDecContext each : ctx.cursorParameterDec()) {
+            visit(each);
+        }
         SQLStatement sqlStatement = visitSelect0(ctx.select());
         getCursorStatements().put(null != ctx.variableName().identifier()
                 ? new IdentifierValue(ctx.variableName().getText()).getValue()
@@ -1437,15 +1449,17 @@ public final class OracleDDLStatementVisitor extends 
OracleStatementVisitor impl
         return defaultResult();
     }
     
+    @Override
+    public ASTNode visitCursorParameterDec(final CursorParameterDecContext 
ctx) {
+        getVariableSegment(ctx.variableName());
+        return defaultResult();
+    }
+    
     @Override
     public ASTNode visitBody(final BodyContext ctx) {
-        for (StatementContext each : ctx.statement()) {
-            visit(each);
-        }
+        visitPlsqlStatementList(ctx.plsqlStatements());
         for (ExceptionHandlerContext eachExceptionHandler : 
ctx.exceptionHandler()) {
-            for (StatementContext each : eachExceptionHandler.statement()) {
-                visit(each);
-            }
+            visitPlsqlStatementList(eachExceptionHandler.plsqlStatements());
         }
         if (null != ctx.identifier()) {
             getProcedureBodyEndNameSegments().add(
@@ -1454,6 +1468,12 @@ public final class OracleDDLStatementVisitor extends 
OracleStatementVisitor impl
         return defaultResult();
     }
     
+    private void visitPlsqlStatementList(final PlsqlStatementsContext ctx) {
+        for (StatementContext each : ctx.statement()) {
+            visit(each);
+        }
+    }
+    
     @Override
     public ASTNode visitProcedureCall(final ProcedureCallContext ctx) {
         int startIndex = ctx.procedureName().start.getStartIndex();
@@ -1481,9 +1501,7 @@ public final class OracleDDLStatementVisitor extends 
OracleStatementVisitor impl
             relatedCursorStatement = getCursorStatements().get(cursorName);
         }
         increaseCursorForLoopLevel();
-        for (StatementContext each : ctx.statement()) {
-            visit(each);
-        }
+        visitPlsqlStatementList(ctx.plsqlStatements());
         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);
@@ -1492,6 +1510,23 @@ public final class OracleDDLStatementVisitor extends 
OracleStatementVisitor impl
         return defaultResult();
     }
     
+    @Override
+    public ASTNode visitForLoopStatement(final ForLoopStatementContext ctx) {
+        for (IterandDeclContext each : ctx.iterator().iterandDecl()) {
+            IdentifierValue loopVariable = (IdentifierValue) 
visitIdentifier(each.identifier());
+            getVariableNames().add(loopVariable.getValue().toLowerCase());
+        }
+        visitPlsqlStatementList(ctx.plsqlStatements());
+        return defaultResult();
+    }
+    
+    @Override
+    public ASTNode visitForallStatement(final ForallStatementContext ctx) {
+        getVariableNames().add(new 
IdentifierValue(ctx.index.getText()).getValue().toLowerCase());
+        visit(ctx.dmlStatement());
+        return defaultResult();
+    }
+    
     @Override
     public ASTNode visitOpenForStatement(final OpenForStatementContext ctx) {
         if (null != ctx.select()) {
@@ -1540,7 +1575,7 @@ public final class OracleDDLStatementVisitor extends 
OracleStatementVisitor impl
             addToTempCursorForLoopStatements(result);
         }
         if (null != ctx.lock()) {
-            OracleStatementVisitor visitor = createOracleDMLStatementVisitor();
+            OracleStatementVisitor visitor = createOracleTCLStatementVisitor();
             SQLStatement result = (SQLStatement) visitor.visitLock(ctx.lock());
             getSqlStatementsInPlsql().add(new 
SQLStatementSegment(ctx.lock().start.getStartIndex(), 
ctx.lock().stop.getStopIndex(), result));
             addToTempCursorForLoopStatements(result);
@@ -1639,20 +1674,30 @@ public final class OracleDDLStatementVisitor extends 
OracleStatementVisitor impl
     
     @Override
     public ASTNode visitPlsqlBlock(final PlsqlBlockContext ctx) {
-        if (null != ctx.body() && null != ctx.body().statement()) {
-            ctx.body().statement().forEach(this::visit);
+        if (null != ctx.declareSection()) {
+            visit(ctx.declareSection());
+        }
+        if (null != ctx.body()) {
+            visitPlsqlStatementList(ctx.body().plsqlStatements());
+            for (ExceptionHandlerContext each : ctx.body().exceptionHandler()) 
{
+                visitPlsqlStatementList(each.plsqlStatements());
+            }
         }
         return new OraclePLSQLBlockStatement(getDatabaseType());
     }
     
     @Override
     public ASTNode visitAlterProcedure(final AlterProcedureContext ctx) {
-        return new AlterProcedureStatement(getDatabaseType());
+        AlterProcedureStatement result = new 
AlterProcedureStatement(getDatabaseType());
+        result.setProcedureName(createProcedureNameSegment(ctx.schemaName(), 
ctx.procedureName()));
+        return result;
     }
     
     @Override
     public ASTNode visitDropProcedure(final DropProcedureContext ctx) {
-        return new DropProcedureStatement(getDatabaseType());
+        DropProcedureStatement result = new 
DropProcedureStatement(getDatabaseType());
+        result.setProcedureName(createProcedureNameSegment(ctx.schemaName(), 
ctx.procedureName()));
+        return result;
     }
     
     @Override
diff --git 
a/parser/sql/engine/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/engine/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
 
b/parser/sql/engine/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/engine/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
index f9973d6a2b1..c329de1fa69 100644
--- 
a/parser/sql/engine/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/engine/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
+++ 
b/parser/sql/engine/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/engine/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
@@ -24,19 +24,22 @@ import 
org.apache.shardingsphere.sql.parser.api.visitor.statement.type.DMLStatem
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AliasContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AssignmentValueContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AssignmentValuesContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CallArgumentContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CallContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CellAssignmentContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CollectionExprContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ColumnNameContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ColumnNamesContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ConditionalInsertClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ConditionalInsertElsePartContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ConditionalInsertWhenPartContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ContainersClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CrossOuterApplyClauseContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CurrentOfClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DeleteContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DeleteSpecificationContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DeleteWhereClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DimensionColumnContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DmlTableAliasContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DmlSubqueryClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DmlTableClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DuplicateSpecificationContext;
@@ -55,6 +58,7 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Groupi
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.HavingClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InnerCrossJoinClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InsertContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InsertColumnNamesContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InsertIntoClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InsertMultiTableContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InsertSingleTableContext;
@@ -74,10 +78,12 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ModelC
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ModelColumnContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.MultiColumnForLoopContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.MultiTableElementContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.MultiTableInsertIntoClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OrderByClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OuterJoinClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ParenthesisSelectSubqueryContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.PivotClauseContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ProcedureNameContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.QueryBlockContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.QueryPartitionClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.QueryNameContext;
@@ -87,6 +93,7 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Refere
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ReturningClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ReturningIntoItemContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.RollupCubeClauseContext;
+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.SelectFromClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectIntoStatementContext;
@@ -120,6 +127,7 @@ import 
org.apache.shardingsphere.sql.parser.statement.core.enums.CombineType;
 import org.apache.shardingsphere.sql.parser.statement.core.enums.JoinType;
 import 
org.apache.shardingsphere.sql.parser.statement.core.enums.OrderDirection;
 import org.apache.shardingsphere.sql.parser.statement.core.enums.SubqueryType;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.routine.FunctionNameSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dal.VariableSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.ColumnAssignmentSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.InsertValuesSegment;
@@ -190,6 +198,7 @@ import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SubqueryTableSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableNameSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.CallStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.DeleteStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.InsertStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.MergeStatement;
@@ -217,6 +226,30 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
         super(databaseType);
     }
     
+    @Override
+    public ASTNode visitCall(final CallContext ctx) {
+        FunctionNameSegment procedureNameSegment = 
createCallProcedureNameSegment(ctx.schemaName(), ctx.procedureName());
+        String procedureName = procedureNameSegment.getOwner().map(optional -> 
optional.getIdentifier().getValue() + ".").orElse("") + 
procedureNameSegment.getIdentifier().getValue();
+        List<ExpressionSegment> params = ctx.callArgument().stream().map(each 
-> (ExpressionSegment) visit(each)).collect(Collectors.toList());
+        return new CallStatement(getDatabaseType(), procedureName, 
procedureNameSegment, params);
+    }
+    
+    private FunctionNameSegment createCallProcedureNameSegment(final 
SchemaNameContext schemaName, final ProcedureNameContext procedureNameContext) {
+        IdentifierValue procedureName = (IdentifierValue) 
visit(procedureNameContext.identifier());
+        if (null == schemaName) {
+            return new 
FunctionNameSegment(procedureNameContext.start.getStartIndex(), 
procedureNameContext.stop.getStopIndex(), procedureName);
+        }
+        OwnerSegment owner = new 
OwnerSegment(schemaName.start.getStartIndex(), schemaName.stop.getStopIndex(), 
(IdentifierValue) visit(schemaName.identifier()));
+        FunctionNameSegment result = new 
FunctionNameSegment(schemaName.start.getStartIndex(), 
procedureNameContext.stop.getStopIndex(), procedureName);
+        result.setOwner(owner);
+        return result;
+    }
+    
+    @Override
+    public ASTNode visitCallArgument(final CallArgumentContext ctx) {
+        return visit(ctx.expression());
+    }
+    
     @Override
     public ASTNode visitUpdate(final UpdateContext ctx) {
         TableSegment tableSegment = (TableSegment) 
visit(ctx.updateSpecification());
@@ -229,6 +262,12 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
                 .setAssignment((SetAssignmentSegment) 
visit(ctx.updateSetClause()));
         if (null != ctx.whereClause()) {
             result.where((WhereSegment) visit(ctx.whereClause()));
+        } else if (null != ctx.currentOfClause()) {
+            CurrentOfClauseContext currentOfClause = ctx.currentOfClause();
+            int startIndex = 
currentOfClause.CURRENT().getSymbol().getStartIndex();
+            int stopIndex = currentOfClause.cursorName().stop.getStopIndex();
+            result.where(new 
WhereSegment(currentOfClause.getStart().getStartIndex(), 
currentOfClause.getStop().getStopIndex(),
+                    new CommonExpressionSegment(startIndex, stopIndex, 
currentOfClause.start.getInputStream().getText(new Interval(startIndex, 
stopIndex)))));
         }
         if (null != ctx.returningClause()) {
             result.returning((ReturningSegment) visit(ctx.returningClause()));
@@ -242,16 +281,22 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
     @Override
     public ASTNode visitUpdateSpecification(final UpdateSpecificationContext 
ctx) {
         if (null != ctx.dmlTableExprClause().dmlTableClause()) {
-            return visit(ctx.dmlTableExprClause().dmlTableClause());
+            SimpleTableSegment result = (SimpleTableSegment) 
visit(ctx.dmlTableExprClause().dmlTableClause());
+            setDmlTableAlias(result, ctx.dmlTableExprClause().dmlTableAlias());
+            return result;
         }
         if (null != ctx.dmlTableExprClause().dmlSubqueryClause()) {
             SubquerySegment subquerySegment = (SubquerySegment) 
visit(ctx.dmlTableExprClause().dmlSubqueryClause());
             
subquerySegment.setSelect(subquerySegment.getSelect().withSubqueryType(SubqueryType.TABLE));
-            return new SubqueryTableSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), subquerySegment);
+            SubqueryTableSegment result = new 
SubqueryTableSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), 
subquerySegment);
+            setDmlTableAlias(result, ctx.dmlTableExprClause().dmlTableAlias());
+            return result;
         }
         SubquerySegment subquerySegment = (SubquerySegment) 
visit(ctx.dmlTableExprClause().tableCollectionExpr());
         
subquerySegment.setSelect(subquerySegment.getSelect().withSubqueryType(SubqueryType.TABLE));
-        return new SubqueryTableSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), subquerySegment);
+        SubqueryTableSegment result = new 
SubqueryTableSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), 
subquerySegment);
+        setDmlTableAlias(result, ctx.dmlTableExprClause().dmlTableAlias());
+        return result;
     }
     
     @Override
@@ -369,8 +414,8 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
         InsertStatement.InsertStatementBuilder result = 
InsertStatement.builder()
                 .databaseType(getDatabaseType())
                 .multiTableInsertType(null != ctx.conditionalInsertClause() && 
null != ctx.conditionalInsertClause().FIRST() ? MultiTableInsertType.FIRST : 
MultiTableInsertType.ALL);
-        List<MultiTableElementContext> multiTableElementContexts = 
ctx.multiTableElement();
-        if (null != multiTableElementContexts && 
!multiTableElementContexts.isEmpty()) {
+        List<MultiTableElementContext> multiTableElementContexts = null == 
ctx.multiTableElements() ? Collections.emptyList() : 
ctx.multiTableElements().multiTableElement();
+        if (!multiTableElementContexts.isEmpty()) {
             MultiTableInsertIntoSegment multiTableInsertIntoSegment = new 
MultiTableInsertIntoSegment(
                     
multiTableElementContexts.get(0).getStart().getStartIndex(), 
multiTableElementContexts.get(multiTableElementContexts.size() - 
1).getStop().getStopIndex());
             
multiTableInsertIntoSegment.getInsertStatements().addAll(createInsertIntoSegments(multiTableElementContexts));
@@ -409,31 +454,54 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
         return 
InsertStatement.builder().databaseType(getDatabaseType()).values(createInsertValuesSegments(ctx.assignmentValues())).build();
     }
     
-    @SuppressWarnings("unchecked")
     @Override
     public ASTNode visitInsertIntoClause(final InsertIntoClauseContext ctx) {
         InsertStatement.InsertStatementBuilder result = 
InsertStatement.builder().databaseType(getDatabaseType());
         if (null != ctx.dmlTableExprClause().dmlTableClause()) {
-            SimpleTableSegment simpleTableSegment = (SimpleTableSegment) 
visit(ctx.dmlTableExprClause().dmlTableClause());
-            if (null != ctx.dmlTableExprClause().alias()) {
-                simpleTableSegment.setAlias((AliasSegment) 
visit(ctx.dmlTableExprClause().alias()));
-            }
-            result.table(simpleTableSegment);
+            SimpleTableSegment tableSegment = (SimpleTableSegment) 
visit(ctx.dmlTableExprClause().dmlTableClause());
+            setDmlTableAlias(tableSegment, 
ctx.dmlTableExprClause().dmlTableAlias());
+            result.table(tableSegment);
         } else if (null != ctx.dmlTableExprClause().dmlSubqueryClause()) {
             result.insertSelect((SubquerySegment) 
visit(ctx.dmlTableExprClause().dmlSubqueryClause()));
         } else {
             result.insertSelect((SubquerySegment) 
visit(ctx.dmlTableExprClause().tableCollectionExpr()));
         }
-        if (null != ctx.columnNames()) {
-            ColumnNamesContext columnNames = ctx.columnNames();
-            CollectionValue<ColumnSegment> columnSegments = 
(CollectionValue<ColumnSegment>) visit(columnNames);
-            result.insertColumns(new 
InsertColumnsSegment(columnNames.start.getStartIndex(), 
columnNames.stop.getStopIndex(), columnSegments.getValue()));
+        if (null != ctx.insertColumnNames()) {
+            InsertColumnNamesContext columnNames = ctx.insertColumnNames();
+            result.insertColumns(new 
InsertColumnsSegment(columnNames.start.getStartIndex(), 
columnNames.stop.getStopIndex(), createInsertColumnSegments(columnNames)));
+        } else {
+            result.insertColumns(new 
InsertColumnsSegment(ctx.stop.getStopIndex() + 1, ctx.stop.getStopIndex() + 1, 
Collections.emptyList()));
+        }
+        return result.build();
+    }
+    
+    @Override
+    public ASTNode visitMultiTableInsertIntoClause(final 
MultiTableInsertIntoClauseContext ctx) {
+        InsertStatement.InsertStatementBuilder result = 
InsertStatement.builder().databaseType(getDatabaseType());
+        if (null != ctx.insertDmlTableExprClause().dmlTableClause()) {
+            result.table((SimpleTableSegment) 
visit(ctx.insertDmlTableExprClause().dmlTableClause()));
+        } else if (null != ctx.insertDmlTableExprClause().dmlSubqueryClause()) 
{
+            result.insertSelect((SubquerySegment) 
visit(ctx.insertDmlTableExprClause().dmlSubqueryClause()));
+        } else {
+            result.insertSelect((SubquerySegment) 
visit(ctx.insertDmlTableExprClause().tableCollectionExpr()));
+        }
+        if (null != ctx.insertColumnNames()) {
+            InsertColumnNamesContext columnNames = ctx.insertColumnNames();
+            result.insertColumns(new 
InsertColumnsSegment(columnNames.start.getStartIndex(), 
columnNames.stop.getStopIndex(), createInsertColumnSegments(columnNames)));
         } else {
             result.insertColumns(new 
InsertColumnsSegment(ctx.stop.getStopIndex() + 1, ctx.stop.getStopIndex() + 1, 
Collections.emptyList()));
         }
         return result.build();
     }
     
+    private Collection<ColumnSegment> createInsertColumnSegments(final 
InsertColumnNamesContext ctx) {
+        Collection<ColumnSegment> result = new LinkedList<>();
+        for (ColumnNameContext each : ctx.columnName()) {
+            result.add((ColumnSegment) visit(each));
+        }
+        return result;
+    }
+    
     @Override
     public ASTNode visitDelete(final DeleteContext ctx) {
         TableSegment tableSegment = (TableSegment) 
visit(ctx.deleteSpecification());
@@ -443,6 +511,12 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
         DeleteStatement.DeleteStatementBuilder result = 
DeleteStatement.builder().databaseType(getDatabaseType()).table(tableSegment);
         if (null != ctx.whereClause()) {
             result.where((WhereSegment) visit(ctx.whereClause()));
+        } else if (null != ctx.currentOfClause()) {
+            CurrentOfClauseContext currentOfClause = ctx.currentOfClause();
+            int startIndex = 
currentOfClause.CURRENT().getSymbol().getStartIndex();
+            int stopIndex = currentOfClause.cursorName().stop.getStopIndex();
+            result.where(new 
WhereSegment(currentOfClause.getStart().getStartIndex(), 
currentOfClause.getStop().getStopIndex(),
+                    new CommonExpressionSegment(startIndex, stopIndex, 
currentOfClause.start.getInputStream().getText(new Interval(startIndex, 
stopIndex)))));
         }
         if (null != ctx.returningClause()) {
             result.returning((ReturningSegment) visit(ctx.returningClause()));
@@ -456,14 +530,22 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
     @Override
     public ASTNode visitDeleteSpecification(final DeleteSpecificationContext 
ctx) {
         if (null != ctx.dmlTableExprClause().dmlTableClause()) {
-            return visit(ctx.dmlTableExprClause().dmlTableClause());
+            SimpleTableSegment result = (SimpleTableSegment) 
visit(ctx.dmlTableExprClause().dmlTableClause());
+            setDmlTableAlias(result, ctx.dmlTableExprClause().dmlTableAlias());
+            return result;
         }
         if (null != ctx.dmlTableExprClause().dmlSubqueryClause()) {
             SubquerySegment subquerySegment = (SubquerySegment) 
visit(ctx.dmlTableExprClause().dmlSubqueryClause());
-            return new 
SubqueryTableSegment(ctx.dmlTableExprClause().dmlSubqueryClause().start.getStartIndex(),
 ctx.dmlTableExprClause().dmlSubqueryClause().stop.getStopIndex(), 
subquerySegment);
+            SubqueryTableSegment result = new SubqueryTableSegment(
+                    
ctx.dmlTableExprClause().dmlSubqueryClause().start.getStartIndex(), 
ctx.dmlTableExprClause().dmlSubqueryClause().stop.getStopIndex(), 
subquerySegment);
+            setDmlTableAlias(result, ctx.dmlTableExprClause().dmlTableAlias());
+            return result;
         }
         SubquerySegment subquerySegment = (SubquerySegment) 
visit(ctx.dmlTableExprClause().tableCollectionExpr());
-        return new 
SubqueryTableSegment(ctx.dmlTableExprClause().tableCollectionExpr().start.getStartIndex(),
 ctx.dmlTableExprClause().tableCollectionExpr().stop.getStopIndex(), 
subquerySegment);
+        SubqueryTableSegment result = new SubqueryTableSegment(
+                
ctx.dmlTableExprClause().tableCollectionExpr().start.getStartIndex(), 
ctx.dmlTableExprClause().tableCollectionExpr().stop.getStopIndex(), 
subquerySegment);
+        setDmlTableAlias(result, ctx.dmlTableExprClause().dmlTableAlias());
+        return result;
     }
     
     @Override
@@ -496,11 +578,12 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
     
     @Override
     public ASTNode visitMultiTableElement(final MultiTableElementContext ctx) {
-        InsertStatement result = (InsertStatement) 
visit(ctx.insertIntoClause());
+        InsertStatement result = (InsertStatement) 
visit(ctx.multiTableInsertIntoClause());
         if (null != ctx.insertValuesClause()) {
             
result.getValues().addAll(createInsertValuesSegments(ctx.insertValuesClause().assignmentValues()));
         }
         result.addParameterMarkers(ctx.getParent() instanceof ExecuteContext ? 
getGlobalParameterMarkerSegments() : popAllStatementParameterMarkerSegments());
+        result.getVariableNames().addAll(getVariableNames());
         return result;
     }
     
@@ -611,7 +694,7 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
     
     @Override
     public ASTNode visitConditionalInsertWhenPart(final 
ConditionalInsertWhenPartContext ctx) {
-        List<MultiTableElementContext> multiTableElementContexts = 
ctx.multiTableElement();
+        List<MultiTableElementContext> multiTableElementContexts = 
ctx.multiTableElements().multiTableElement();
         MultiTableConditionalIntoThenSegment thenSegment = new 
MultiTableConditionalIntoThenSegment(multiTableElementContexts.get(0).start.getStartIndex(),
                 multiTableElementContexts.get(multiTableElementContexts.size() 
- 1).stop.getStopIndex(), createInsertIntoSegments(multiTableElementContexts));
         return new 
MultiTableConditionalIntoWhenThenSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.expr()), thenSegment);
@@ -619,7 +702,7 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
     
     @Override
     public ASTNode visitConditionalInsertElsePart(final 
ConditionalInsertElsePartContext ctx) {
-        return new 
MultiTableConditionalIntoElseSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), createInsertIntoSegments(ctx.multiTableElement()));
+        return new 
MultiTableConditionalIntoElseSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), 
createInsertIntoSegments(ctx.multiTableElements().multiTableElement()));
     }
     
     @Override
@@ -1002,6 +1085,11 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
         return new AliasSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), new IdentifierValue(ctx.STRING_().getText()));
     }
     
+    @Override
+    public ASTNode visitDmlTableAlias(final DmlTableAliasContext ctx) {
+        return new AliasSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), new IdentifierValue(ctx.getText()));
+    }
+    
     private ASTNode createProjection(final SelectProjectionExprClauseContext 
ctx) {
         AliasSegment alias = null == ctx.alias() ? null : (AliasSegment) 
visit(ctx.alias());
         ASTNode projection = visit(ctx.expr());
@@ -1316,12 +1404,16 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
         } else {
             result = (TableSegment) visit(ctx.queryTableExprClause());
         }
-        if (null != ctx.alias()) {
-            result.setAlias((AliasSegment) visit(ctx.alias()));
-        }
+        setDmlTableAlias(result, ctx.dmlTableAlias());
         return result;
     }
     
+    private void setDmlTableAlias(final TableSegment tableSegment, final 
DmlTableAliasContext dmlTableAlias) {
+        if (null != dmlTableAlias) {
+            tableSegment.setAlias((AliasSegment) visit(dmlTableAlias));
+        }
+    }
+    
     @Override
     public ASTNode visitContainersClause(final ContainersClauseContext ctx) {
         return visit(ctx.tableName());
diff --git 
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/type/ddl/procedure/AlterProcedureStatement.java
 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/type/ddl/procedure/AlterProcedureStatement.java
index 8a53f97cc76..16a4bb2e579 100644
--- 
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/type/ddl/procedure/AlterProcedureStatement.java
+++ 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/type/ddl/procedure/AlterProcedureStatement.java
@@ -17,15 +17,31 @@
 
 package 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.ddl.procedure;
 
+import lombok.Setter;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.routine.FunctionNameSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.ddl.DDLStatement;
 
+import java.util.Optional;
+
 /**
  * Alter procedure statement.
  */
+@Setter
 public final class AlterProcedureStatement extends DDLStatement {
     
+    private FunctionNameSegment procedureName;
+    
     public AlterProcedureStatement(final DatabaseType databaseType) {
         super(databaseType);
     }
+    
+    /**
+     * Get procedure name segment.
+     *
+     * @return procedure name segment
+     */
+    public Optional<FunctionNameSegment> getProcedureName() {
+        return Optional.ofNullable(procedureName);
+    }
 }
diff --git 
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/type/ddl/procedure/DropProcedureStatement.java
 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/type/ddl/procedure/DropProcedureStatement.java
index 22b33395750..2059b628d47 100644
--- 
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/type/ddl/procedure/DropProcedureStatement.java
+++ 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/type/ddl/procedure/DropProcedureStatement.java
@@ -17,15 +17,31 @@
 
 package 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.ddl.procedure;
 
+import lombok.Setter;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.routine.FunctionNameSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.ddl.DDLStatement;
 
+import java.util.Optional;
+
 /**
  * Drop procedure statement.
  */
+@Setter
 public final class DropProcedureStatement extends DDLStatement {
     
+    private FunctionNameSegment procedureName;
+    
     public DropProcedureStatement(final DatabaseType databaseType) {
         super(databaseType);
     }
+    
+    /**
+     * Get procedure name segment.
+     *
+     * @return procedure name segment
+     */
+    public Optional<FunctionNameSegment> getProcedureName() {
+        return Optional.ofNullable(procedureName);
+    }
 }
diff --git 
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/type/dml/CallStatement.java
 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/type/dml/CallStatement.java
index 0a4dc8997bf..8be47c25435 100644
--- 
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/type/dml/CallStatement.java
+++ 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/type/dml/CallStatement.java
@@ -19,9 +19,11 @@ package 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml;
 
 import lombok.Getter;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.routine.FunctionNameSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
 
 import java.util.List;
+import java.util.Optional;
 
 /**
  * Call statement.
@@ -31,11 +33,27 @@ public final class CallStatement extends DMLStatement {
     
     private final String procedureName;
     
+    private final FunctionNameSegment procedureNameSegment;
+    
     private final List<ExpressionSegment> parameters;
     
     public CallStatement(final DatabaseType databaseType, final String 
procedureName, final List<ExpressionSegment> parameters) {
+        this(databaseType, procedureName, null, parameters);
+    }
+    
+    public CallStatement(final DatabaseType databaseType, final String 
procedureName, final FunctionNameSegment procedureNameSegment, final 
List<ExpressionSegment> parameters) {
         super(databaseType);
         this.procedureName = procedureName;
+        this.procedureNameSegment = procedureNameSegment;
         this.parameters = parameters;
     }
+    
+    /**
+     * Get procedure name segment.
+     *
+     * @return procedure name segment
+     */
+    public Optional<FunctionNameSegment> getProcedureNameSegment() {
+        return Optional.ofNullable(procedureNameSegment);
+    }
 }
diff --git a/test/it/binder/src/test/resources/cases/dml/insert.xml 
b/test/it/binder/src/test/resources/cases/dml/insert.xml
index 7d490e004c7..6384acac183 100644
--- a/test/it/binder/src/test/resources/cases/dml/insert.xml
+++ b/test/it/binder/src/test/resources/cases/dml/insert.xml
@@ -298,7 +298,71 @@
             </assignment>
         </set>
     </insert>
-    
+
+    <insert sql-case-id="insert_select_with_target_table_alias_oracle">
+        <table name="t_order" start-index="12" stop-index="20" alias="o">
+            <table-bound>
+                <original-database name="foo_db_1" />
+                <original-schema name="FOO_DB_1" />
+            </table-bound>
+        </table>
+        <columns start-index="22" stop-index="31">
+            <column name="order_id" start-index="23" stop-index="30">
+                <column-bound>
+                    <original-database name="foo_db_1" />
+                    <original-schema name="FOO_DB_1" />
+                    <original-table name="t_order" />
+                    <original-column name="order_id" start-delimiter="&quot;" 
end-delimiter="&quot;" />
+                    <table-source-type name="PHYSICAL_TABLE"/>
+                </column-bound>
+            </column>
+        </columns>
+        <select>
+            <projections start-index="40" stop-index="49">
+                <column-projection name="order_id" start-index="40" 
stop-index="49">
+                    <owner name="i" start-index="40" stop-index="40" />
+                    <column-bound>
+                        <original-database name="foo_db_1" />
+                        <original-schema name="FOO_DB_1" />
+                        <original-table name="t_order_item" />
+                        <original-column name="order_id" 
start-delimiter="&quot;" end-delimiter="&quot;" />
+                        <table-source-type name="PHYSICAL_TABLE"/>
+                    </column-bound>
+                </column-projection>
+            </projections>
+            <from start-index="56" stop-index="69">
+                <simple-table name="t_order_item" start-index="56" 
stop-index="69" alias="i">
+                    <table-bound>
+                        <original-database name="foo_db_1" />
+                        <original-schema name="FOO_DB_1" />
+                    </table-bound>
+                </simple-table>
+            </from>
+            <where start-index="71" stop-index="89">
+                <expr>
+                    <binary-operation-expression start-index="77" 
stop-index="89">
+                        <left>
+                            <column name="item_id" start-index="77" 
stop-index="85">
+                                <owner name="i" start-index="77" 
stop-index="77" />
+                                <column-bound>
+                                    <original-database name="foo_db_1" />
+                                    <original-schema name="FOO_DB_1" />
+                                    <original-table name="t_order_item" />
+                                    <original-column name="item_id" 
start-delimiter="&quot;" end-delimiter="&quot;" />
+                                    <table-source-type name="PHYSICAL_TABLE"/>
+                                </column-bound>
+                            </column>
+                        </left>
+                        <operator>=</operator>
+                        <right>
+                            <literal-expression value="1" start-index="89" 
stop-index="89" />
+                        </right>
+                    </binary-operation-expression>
+                </expr>
+            </where>
+        </select>
+    </insert>
+
     <insert 
sql-case-id="insert_on_duplicate_key_update_with_excluded_postgres">
         <table name="t_order" start-index="12" stop-index="18">
             <table-bound>
diff --git a/test/it/binder/src/test/resources/cases/dml/update.xml 
b/test/it/binder/src/test/resources/cases/dml/update.xml
index 08e3f071d8c..772242f3535 100644
--- a/test/it/binder/src/test/resources/cases/dml/update.xml
+++ b/test/it/binder/src/test/resources/cases/dml/update.xml
@@ -149,4 +149,53 @@
             <parameter-marker-expression parameter-index="1" start-index="96" 
stop-index="96" />
         </parameters>
     </update>
+    <update sql-case-id="update_with_target_table_alias_oracle">
+        <table start-index="7" stop-index="15">
+            <simple-table name="t_order" start-index="7" stop-index="15" 
alias="o">
+                <table-bound>
+                    <original-database name="foo_db_1" />
+                    <original-schema name="FOO_DB_1" />
+                </table-bound>
+            </simple-table>
+        </table>
+        <set start-index="17" stop-index="35">
+            <assignment start-index="21" stop-index="35">
+                <column name="status" start-index="21" stop-index="28">
+                    <owner name="o" start-index="21" stop-index="21" />
+                    <column-bound>
+                        <original-database name="foo_db_1" />
+                        <original-schema name="FOO_DB_1" />
+                        <original-table name="t_order" />
+                        <original-column name="status" 
start-delimiter="&quot;" end-delimiter="&quot;" />
+                        <table-source-type name="PHYSICAL_TABLE"/>
+                    </column-bound>
+                </column>
+                <assignment-value>
+                    <literal-expression value="OK" start-index="32" 
stop-index="35" />
+                </assignment-value>
+            </assignment>
+        </set>
+        <where start-index="37" stop-index="56">
+            <expr>
+                <binary-operation-expression start-index="43" stop-index="56">
+                    <left>
+                        <column name="order_id" start-index="43" 
stop-index="52">
+                            <owner name="o" start-index="43" stop-index="43" />
+                            <column-bound>
+                                <original-database name="foo_db_1" />
+                                <original-schema name="FOO_DB_1" />
+                                <original-table name="t_order" />
+                                <original-column name="order_id" 
start-delimiter="&quot;" end-delimiter="&quot;" />
+                                <table-source-type name="PHYSICAL_TABLE"/>
+                            </column-bound>
+                        </column>
+                    </left>
+                    <operator>=</operator>
+                    <right>
+                        <literal-expression value="1" start-index="56" 
stop-index="56" />
+                    </right>
+                </binary-operation-expression>
+            </expr>
+        </where>
+    </update>
 </sql-parser-test-cases>
diff --git a/test/it/binder/src/test/resources/sqls/dml/insert.xml 
b/test/it/binder/src/test/resources/sqls/dml/insert.xml
index fb9ff84a023..a5cc22c1345 100644
--- a/test/it/binder/src/test/resources/sqls/dml/insert.xml
+++ b/test/it/binder/src/test/resources/sqls/dml/insert.xml
@@ -20,5 +20,6 @@
     <sql-case id="insert_with_columns" value="INSERT INTO t_order (order_id, 
user_id, status, merchant_id, remark, creation_date) VALUES (1, 1, 'OK', 1, 
'TEST', '2024-12-25')" db-types="MySQL"/>
     <sql-case id="insert_without_columns" value="INSERT INTO t_order VALUES 
(1, 1, 'OK', 1, 'TEST', '2024-12-25')" db-types="MySQL"/>
     <sql-case id="insert_with_assignments" value="INSERT INTO t_order set 
order_id=1, status='OK'" db-types="MySQL"/>
+    <sql-case id="insert_select_with_target_table_alias_oracle" value="INSERT 
INTO t_order o (order_id) SELECT i.order_id FROM t_order_item i WHERE i.item_id 
= 1" db-types="Oracle"/>
     <sql-case id="insert_on_duplicate_key_update_with_excluded_postgres" 
value="INSERT INTO t_order (order_id, user_id, status) VALUES (1, 1, 'init') ON 
CONFLICT (order_id) DO UPDATE SET status = EXCLUDED.status" 
db-types="PostgreSQL"/>
 </sql-cases>
diff --git a/test/it/binder/src/test/resources/sqls/dml/update.xml 
b/test/it/binder/src/test/resources/sqls/dml/update.xml
index 4aea98d9649..e1666281e17 100644
--- a/test/it/binder/src/test/resources/sqls/dml/update.xml
+++ b/test/it/binder/src/test/resources/sqls/dml/update.xml
@@ -19,4 +19,5 @@
 <sql-cases>
     <sql-case id="update_order_by" value="UPDATE t_order SET user_id = 1 WHERE 
order_id = 1 ORDER BY user_id LIMIT 1" db-types="MySQL"/>
     <sql-case id="update_with_timestampadd_microsecond" value="UPDATE t_order 
SET creation_date = TIMESTAMPADD(MICROSECOND, ?, creation_date) WHERE order_id 
= ?" db-types="MySQL" case-types="PLACEHOLDER"/>
+    <sql-case id="update_with_target_table_alias_oracle" value="UPDATE t_order 
o SET o.status = 'OK' WHERE o.order_id = 1" db-types="Oracle"/>
 </sql-cases>
diff --git a/test/it/parser/src/main/resources/case/dml/call.xml 
b/test/it/parser/src/main/resources/case/dml/call.xml
index 7f23541b70b..20f027cc8c1 100644
--- a/test/it/parser/src/main/resources/case/dml/call.xml
+++ b/test/it/parser/src/main/resources/case/dml/call.xml
@@ -21,7 +21,7 @@
     <call sql-case-id="call_without_parameters">
         <procedure-name name="p" start-index="5" stop-index="6" />
     </call>
-    
+
     <call sql-case-id="call_with_parameters_all_variable">
         <procedure-name name="p" start-index="5" stop-index="6" />
         <procedure-parameter>
@@ -31,7 +31,7 @@
             <common-expression literal-text="@user_id" start-index="18" 
stop-index="25" />
         </procedure-parameter>
     </call>
-    
+
     <call sql-case-id="call_with_parameters_all_placeholder">
         <procedure-name name="p" start-index="5" stop-index="6" />
         <procedure-parameter>
@@ -41,7 +41,7 @@
             <parameter-marker-expression parameter-index="1" start-index="10" 
stop-index="10" />
         </procedure-parameter>
     </call>
-    
+
     <call sql-case-id="call_with_parameters_all_expression">
         <procedure-name name="p" start-index="5" stop-index="6" />
         <procedure-parameter>
@@ -51,7 +51,7 @@
             <literal-expression value="order" start-index="15" stop-index="21" 
/>
         </procedure-parameter>
     </call>
-    
+
     <call sql-case-id="call_with_parameters_mix">
         <procedure-name name="p" start-index="5" stop-index="6" />
         <procedure-parameter>
@@ -64,7 +64,21 @@
             <parameter-marker-expression parameter-index="0" start-index="26" 
stop-index="26" />
         </procedure-parameter>
     </call>
-    
+
+    <call sql-case-id="call_without_parameters_oracle">
+        <procedure-name name="foo_proc" start-index="5" stop-index="12" />
+    </call>
+
+    <call sql-case-id="call_with_owner_oracle">
+        <procedure-name name="hr.foo_proc" start-index="5" stop-index="15" />
+        <procedure-parameter>
+            <parameter-marker-expression parameter-index="0" start-index="17" 
stop-index="17" />
+        </procedure-parameter>
+        <procedure-parameter>
+            <literal-expression value="order" start-index="20" stop-index="26" 
/>
+        </procedure-parameter>
+    </call>
+
     <call sql-case-id="call_with_named_notation_with_null">
         <procedure-name name="p" start-index="5" stop-index="6" />
         <procedure-parameter>
@@ -77,7 +91,7 @@
             <common-expression literal-text="c => 2" start-index="26" 
stop-index="31" />
         </procedure-parameter>
     </call>
-    
+
     <call sql-case-id="call_with_named_notation">
         <procedure-name name="p" start-index="5" stop-index="6" />
         <procedure-parameter>
@@ -90,7 +104,7 @@
             <common-expression literal-text="a => 0" start-index="23" 
stop-index="28" />
         </procedure-parameter>
     </call>
-    
+
     <call sql-case-id="call_with_mixed_notation">
         <procedure-name name="p" start-index="5" stop-index="6" />
         <procedure-parameter>
@@ -103,7 +117,7 @@
             <common-expression literal-text="c => 2" start-index="16" 
stop-index="21" />
         </procedure-parameter>
     </call>
-    
+
     <call sql-case-id="call_with_mixed_notation_with_null">
         <procedure-name name="p" start-index="5" stop-index="6" />
         <procedure-parameter>
@@ -116,7 +130,7 @@
             <common-expression literal-text="b => 11" start-index="21" 
stop-index="27" />
         </procedure-parameter>
     </call>
-    
+
     <call sql-case-id="call_with_mixed_notation_with_apos">
         <procedure-name name="p" start-index="5" stop-index="6" />
         <procedure-parameter>
@@ -126,7 +140,7 @@
             <common-expression literal-text="b => 'Hello'" start-index="11" 
stop-index="22" />
         </procedure-parameter>
     </call>
-    
+
     <call sql-case-id="call_with_named_notation_with_apos">
         <procedure-name name="p" start-index="5" stop-index="6" />
         <procedure-parameter>
@@ -136,7 +150,7 @@
             <common-expression literal-text="a => 10" start-index="21" 
stop-index="27" />
         </procedure-parameter>
     </call>
-    
+
     <call sql-case-id="call_with_positional_notation_with_expression">
         <procedure-name name="p" start-index="5" stop-index="6" />
         <procedure-parameter>
diff --git a/test/it/parser/src/main/resources/case/dml/delete.xml 
b/test/it/parser/src/main/resources/case/dml/delete.xml
index be7ecccd8fd..16d8d19e03e 100644
--- a/test/it/parser/src/main/resources/case/dml/delete.xml
+++ b/test/it/parser/src/main/resources/case/dml/delete.xml
@@ -820,6 +820,15 @@
         </where>
     </delete>
 
+    <delete sql-case-id="delete_with_current_of_oracle">
+        <table name="t_order" start-index="12" stop-index="18" />
+        <where start-index="20" stop-index="48">
+            <expr>
+                <common-expression text="CURRENT OF order_cursor" 
start-index="26" stop-index="48" />
+            </expr>
+        </where>
+    </delete>
+
     <delete sql-case-id="delete_with_schema">
         <table name="t_order" start-index="12" stop-index="22">
             <owner name="db1" start-index="12" stop-index="14" />
diff --git a/test/it/parser/src/main/resources/case/dml/update.xml 
b/test/it/parser/src/main/resources/case/dml/update.xml
index f0c20e4f43a..47a3cf0026d 100644
--- a/test/it/parser/src/main/resources/case/dml/update.xml
+++ b/test/it/parser/src/main/resources/case/dml/update.xml
@@ -154,6 +154,25 @@
         </set>
     </update>
 
+    <update sql-case-id="update_with_current_of_oracle">
+        <table start-index="7" stop-index="13">
+            <simple-table name="t_order" start-index="7" stop-index="13" />
+        </table>
+        <set start-index="15" stop-index="31">
+            <assignment start-index="19" stop-index="31">
+                <column name="status" start-index="19" stop-index="24" />
+                <assignment-value>
+                    <literal-expression value="OK" start-index="28" 
stop-index="31" />
+                </assignment-value>
+            </assignment>
+        </set>
+        <where start-index="33" stop-index="61">
+            <expr>
+                <common-expression text="CURRENT OF order_cursor" 
start-index="39" stop-index="61" />
+            </expr>
+        </where>
+    </update>
+
     <update sql-case-id="update_with_alias" parameters="'update', 1, 1">
         <table start-index="7" stop-index="18" >
             <simple-table name="t_order" alias="o" start-index="7" 
stop-index="18" />
diff --git a/test/it/parser/src/main/resources/sql/supported/dml/call.xml 
b/test/it/parser/src/main/resources/sql/supported/dml/call.xml
index 48801d76cfe..fefae166332 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/call.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/call.xml
@@ -24,6 +24,8 @@
     <sql-case id="call_with_parameters_mix" value="CALL p(@order_id, 'user', 
?)" db-types="MySQL,Doris" />
     <sql-case id="call_with_owner_mysql" value="CALL analytics.proc_demo(?, 
?)" db-types="MySQL" />
     <sql-case id="call_with_owner_doris" value="CALL analytics.proc_demo(?, 
?)" db-types="Doris" />
+    <sql-case id="call_without_parameters_oracle" value="CALL foo_proc()" 
db-types="Oracle" />
+    <sql-case id="call_with_owner_oracle" value="CALL hr.foo_proc(?, 'order')" 
db-types="Oracle" />
     <sql-case id="call_with_named_notation_with_null" value="CALL p(a =&gt; 
null, b =&gt; 8, c =&gt; 2);" db-types="PostgreSQL" />
     <sql-case id="call_with_named_notation" value="CALL p(b =&gt; 8, c =&gt; 
2, a =&gt; 0);" db-types="PostgreSQL" />
     <sql-case id="call_with_mixed_notation" value="CALL p(null, 7, c =&gt; 
2);" db-types="PostgreSQL" />
diff --git a/test/it/parser/src/main/resources/sql/supported/dml/delete.xml 
b/test/it/parser/src/main/resources/sql/supported/dml/delete.xml
index b444cfa86d9..bf3e5d1c217 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/delete.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/delete.xml
@@ -45,6 +45,7 @@
     <sql-case id="delete_with_partition" value="DELETE FROM sales PARTITION 
(sales_q1_1998) WHERE amount_sold > 1000" db-types="Oracle" />
     <sql-case id="delete_with_table" value="DELETE product_price_history" 
db-types="Oracle" />
     <sql-case id="delete_table_collection_oracle" value="DELETE FROM 
TABLE(SELECT nested_col FROM t_nested) WHERE nested_col = 1" db-types="Oracle" 
/>
+    <sql-case id="delete_with_current_of_oracle" value="DELETE FROM t_order 
WHERE CURRENT OF order_cursor" db-types="Oracle" />
     <sql-case id="delete_with_schema" value="DELETE FROM db1.t_order" />
     <sql-case id="delete_with_simple_condition" value="DELETE FROM 
Q1_2000_sales WHERE amount_sold &lt; 0" db-types="Oracle" />
     <sql-case id="delete_with_output_clause_with_compress_function" 
value="DELETE FROM player OUTPUT deleted.id,deleted.name, 
deleted.surname,deleted.datemodifier,COMPRESS(deleted.info) INTO 
dbo.inactivePlayers WHERE datemodified &lt; @startOfYear" db-types="SQLServer" 
/>
diff --git a/test/it/parser/src/main/resources/sql/supported/dml/update.xml 
b/test/it/parser/src/main/resources/sql/supported/dml/update.xml
index 64d9c9b86e9..ca68ea8add2 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/update.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/update.xml
@@ -51,6 +51,7 @@
     <sql-case id="update_with_set_value_clause" value="UPDATE ot1 SET 
VALUE(ot1.x) = t1(20) WHERE VALUE(ot1.x) = t1(10);" db-types="Oracle" />
     <sql-case id="update_with_subquery_target_oracle" value="UPDATE (SELECT * 
FROM employees) SET salary = 1" db-types="Oracle" />
     <sql-case id="update_with_dblink_oracle" value="UPDATE employees@remote 
SET salary = salary" db-types="Oracle" />
+    <sql-case id="update_with_current_of_oracle" value="UPDATE t_order SET 
status = 'OK' WHERE CURRENT OF order_cursor" db-types="Oracle" />
     <sql-case id="update_with_open_row_set_function" value="UPDATE T SET 
XmlCol = ( SELECT * FROM OPENROWSET(BULK 'C:\SampleFolder\SampleData3.txt', 
SINGLE_BLOB) AS x) WHERE IntCol = 1" db-types="SQLServer"/>
     <sql-case id="update_with_point_type" value="UPDATE dbo.Cities SET 
Location.SetXY(23.5, 23.5) WHERE Name = 'Anchorage'" db-types="SQLServer"/>
     <sql-case id="update_with_table_hint" value="UPDATE Production.Product 
WITH (TABLOCK) SET ListPrice = ListPrice * 1.10 WHERE ProductNumber LIKE 
'BK-%'" db-types="SQLServer"/>

Reply via email to