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="""
end-delimiter=""" />
+ <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=""" end-delimiter=""" />
+ <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=""" end-delimiter=""" />
+ <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=""" end-delimiter=""" />
+ <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=""" end-delimiter=""" />
+ <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 =>
null, b => 8, c => 2);" db-types="PostgreSQL" />
<sql-case id="call_with_named_notation" value="CALL p(b => 8, c =>
2, a => 0);" db-types="PostgreSQL" />
<sql-case id="call_with_mixed_notation" value="CALL p(null, 7, c =>
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 < 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 < @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"/>