You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by ji...@apache.org on 2022/11/24 12:13:18 UTC

[shardingsphere] branch master updated: Update Oracle SQL XMLTABLE function parse (#22363)

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

jianglongtao 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 f34552a9ad8 Update Oracle SQL XMLTABLE function parse (#22363)
f34552a9ad8 is described below

commit f34552a9ad8ba83a8dfaa53fe6239c56d36ecf06
Author: Zichao <57...@users.noreply.github.com>
AuthorDate: Fri Nov 25 01:13:10 2022 +1300

    Update Oracle SQL XMLTABLE function parse (#22363)
    
    * Update Oracle SQL XMLTABLE function parse
    
    * Update Oracle SQL XMLTABLE function parse
    
    * Update Oracle SQL XMLTABLE function parse
    
    * Update Oracle SQL XMLTABLE function parse
    
    * Update Oracle SQL XMLTABLE function parse
    
    * Update Oracle SQL XMLTABLE function parse
    
    * Update Oracle SQL XMLTABLE function parse
    
    * Update Oracle SQL XMLTABLE function parse
---
 .../src/main/antlr4/imports/oracle/BaseRule.g4     | 25 +++++++++
 .../src/main/antlr4/imports/oracle/DMLStatement.g4 |  9 ++++
 .../src/main/antlr4/imports/oracle/Keyword.g4      | 16 ++++++
 .../impl/OracleDMLStatementSQLVisitor.java         | 17 +++++-
 .../statement/impl/OracleStatementSQLVisitor.java  | 62 ++++++++++++++++++++--
 .../XmlNameSpaceStringAsIdentifierSegment.java     | 29 +++++-----
 .../dml/expr/XmlNameSpacesClauseSegment.java       | 30 ++++++-----
 .../segment/dml/expr/XmlTableColumnSegment.java    | 33 +++++++-----
 .../segment/dml/expr/XmlTableFunctionSegment.java  | 34 +++++++-----
 .../segment/dml/expr/XmlTableOptionsSegment.java   | 30 ++++++-----
 .../segment/generic/table/XmlTableSegment.java     | 58 ++++++++++++++++++++
 .../asserts/segment/table/TableAssert.java         | 36 ++++++++++++-
 .../ExpectedXmlTableFunction.java}                 | 21 ++++----
 .../domain/segment/impl/table/ExpectedTable.java   |  3 ++
 .../{ExpectedTable.java => ExpectedXmlTable.java}  | 21 +++++---
 test/parser/src/main/resources/case/dml/select.xml | 17 ++++++
 .../main/resources/sql/supported/dml/select.xml    |  1 +
 17 files changed, 347 insertions(+), 95 deletions(-)

diff --git a/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4 b/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4
index 7c222d79596..6f616e8144b 100644
--- a/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4
+++ b/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4
@@ -1624,6 +1624,7 @@ xmlFunction
     | xmlQueryFunction
     | xmlRootFunction
     | xmlSerializeFunction
+    | xmlTableFunction
     ;
 
 xmlAggFunction
@@ -1665,3 +1666,27 @@ xmlRootFunction
 xmlSerializeFunction
     : XMLSERIALIZE LP_ (DOCUMENT | CONTENT) expr (AS dataType)? (ENCODING STRING_)? (VERSION stringLiterals)? (NO IDENT | IDENT (SIZE EQ_ INTEGER_)?)? ((HIDE | SHOW) DEFAULT)? RP_
     ;
+
+xmlTableFunction
+    : XMLTABLE LP_ (xmlNameSpacesClause COMMA_)? STRING_ xmlTableOptions RP_
+    ;
+
+xmlNameSpacesClause
+    : XMLNAMESPACES LP_ (defaultString COMMA_)? (xmlNameSpaceStringAsIdentifier | defaultString) (COMMA_ (xmlNameSpaceStringAsIdentifier | defaultString))* RP_
+    ;
+
+xmlNameSpaceStringAsIdentifier
+    : STRING_ AS identifier
+    ;
+
+defaultString
+    : DEFAULT STRING_
+    ;
+
+xmlTableOptions
+    : xmlPassingClause? (RETURNING SEQUENCE BY REF)? (COLUMNS xmlTableColumn (COMMA_ xmlTableColumn)*)?
+    ;
+
+xmlTableColumn
+    : columnName (FOR ORDINALITY | (dataType | XMLTYPE (LP_ SEQUENCE RP_ BY REF)?) (PATH STRING_)? (DEFAULT expr)?)
+    ;
diff --git a/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/DMLStatement.g4 b/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/DMLStatement.g4
index 3741ff2ba9b..c8c2a4fd7ca 100644
--- a/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/DMLStatement.g4
+++ b/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/DMLStatement.g4
@@ -432,6 +432,15 @@ fromClauseOption
     | LP_ joinClause RP_
     | selectTableReference
     | inlineAnalyticView
+    | xmlTable
+    ;
+
+xmlTable
+    : tableName alias? COMMA_ xmlTableFunction xmlTableFunctionAlias
+    ;
+
+xmlTableFunctionAlias
+    : alias
     ;
 
 selectTableReference
diff --git a/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4 b/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
index 6a8bd228e15..bb0bc7a76b1 100644
--- a/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
+++ b/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
@@ -751,3 +751,19 @@ HIDE
 SHOW
     : S H O W
     ;
+
+XMLTABLE
+    : X M L T A B L E
+    ;
+
+XMLNAMESPACES
+    : X M L N A M E S P A C E S
+    ;
+
+ORDINALITY
+    : O R D I N A L I T Y
+    ;
+
+PATH
+    : P A T H
+    ;
diff --git a/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleDMLStatementSQLVisitor.java b/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleDMLStatementSQLVisitor.java
index bef92b029b9..e3df4d82a2d 100644
--- a/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleDMLStatementSQLVisitor.java
+++ b/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleDMLStatementSQLVisitor.java
@@ -103,6 +103,7 @@ import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.Update
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UsingClauseContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.WhereClauseContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.WithClauseContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlTableContext;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.JoinType;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.NullsOrderType;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.OrderDirection;
@@ -116,9 +117,10 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOp
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.DatetimeExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlQueryAndExistsFunctionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlPiFunctionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlQueryAndExistsFunctionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlSerializeFunctionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlTableFunctionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonTableExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
@@ -126,12 +128,12 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.DatetimeProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ShorthandProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.DatetimeProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.GroupBySegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.OrderBySegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
@@ -150,6 +152,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.Joi
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.XmlTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.util.SQLUtil;
 import org.apache.shardingsphere.sql.parser.sql.common.value.collection.CollectionValue;
 import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
@@ -799,12 +802,22 @@ public final class OracleDMLStatementSQLVisitor extends OracleStatementSQLVisito
     
     @Override
     public ASTNode visitFromClauseOption(final FromClauseOptionContext ctx) {
+        if (null != ctx.xmlTable()) {
+            return visit(ctx.xmlTable());
+        }
         if (null != ctx.joinClause()) {
             return visit(ctx.joinClause());
         }
         return visit(ctx.selectTableReference());
     }
     
+    @Override
+    public ASTNode visitXmlTable(final XmlTableContext ctx) {
+        String tableAlias = null == ctx.alias() ? null : ctx.alias().getText();
+        return new XmlTableSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.tableName().getText(),
+                tableAlias, (XmlTableFunctionSegment) visit(ctx.xmlTableFunction()), ctx.xmlTableFunctionAlias().alias().getText());
+    }
+    
     @Override
     public ASTNode visitJoinClause(final JoinClauseContext ctx) {
         TableSegment result;
diff --git a/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleStatementSQLVisitor.java b/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleStatementSQLVisitor.java
index 19f41dd26f1..135517a6e11 100644
--- a/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleStatementSQLVisitor.java
+++ b/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleStatementSQLVisitor.java
@@ -69,15 +69,20 @@ import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TypeNa
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UnreservedWordContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ViewNameContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlAggFunctionContext;
-import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlFunctionContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlColattvalFunctionContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlExistsFunctionContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlForestFunctionContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlFunctionContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlNameSpacesClauseContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlParseFunctionContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlPiFunctionContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlQueryFunctionContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlRootFunctionContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlSerializeFunctionContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlTableColumnContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlTableFunctionContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlTableOptionsContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlNameSpaceStringAsIdentifierContext;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.AggregationType;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.NullsOrderType;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.OrderDirection;
@@ -97,9 +102,14 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.Function
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.NotExpression;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlQueryAndExistsFunctionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlNameSpaceStringAsIdentifierSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlNameSpacesClauseSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlPiFunctionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlQueryAndExistsFunctionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlSerializeFunctionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlTableColumnSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlTableFunctionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlTableOptionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
@@ -580,7 +590,10 @@ public abstract class OracleStatementSQLVisitor extends OracleStatementBaseVisit
         if (null != ctx.xmlRootFunction()) {
             return visit(ctx.xmlRootFunction());
         }
-        return visit(ctx.xmlSerializeFunction());
+        if (null != ctx.xmlSerializeFunction()) {
+            return visit(ctx.xmlSerializeFunction());
+        }
+        return visit(ctx.xmlTableFunction());
     }
     
     @Override
@@ -655,6 +668,49 @@ public abstract class OracleStatementSQLVisitor extends OracleStatementBaseVisit
                 dataType, encoding, version, identSize, getOriginalText(ctx));
     }
     
+    @Override
+    public ASTNode visitXmlTableFunction(final XmlTableFunctionContext ctx) {
+        XmlNameSpacesClauseSegment xmlNameSpacesClause = null == ctx.xmlNameSpacesClause() ? null : (XmlNameSpacesClauseSegment) visit(ctx.xmlNameSpacesClause());
+        return new XmlTableFunctionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.XMLTABLE().getText(),
+                xmlNameSpacesClause, ctx.STRING_().getText(), (XmlTableOptionsSegment) visit(ctx.xmlTableOptions()), getOriginalText(ctx));
+    }
+    
+    @Override
+    public ASTNode visitXmlNameSpacesClause(final XmlNameSpacesClauseContext ctx) {
+        // TODO : throw exception if more than one defaultString exists in a xml name space clause
+        String defaultString = null == ctx.defaultString() ? null : ctx.defaultString(0).STRING_().getText();
+        Collection<XmlNameSpaceStringAsIdentifierSegment> xmlNameSpaceStringAsIdentifierSegments = null == ctx.xmlNameSpaceStringAsIdentifier() ? Collections.emptyList()
+                : ctx.xmlNameSpaceStringAsIdentifier().stream().map(each -> (XmlNameSpaceStringAsIdentifierSegment) visit(each)).collect(Collectors.toList());
+        XmlNameSpacesClauseSegment result = new XmlNameSpacesClauseSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), defaultString, getOriginalText(ctx));
+        result.getStringAsIdentifier().addAll(xmlNameSpaceStringAsIdentifierSegments);
+        return result;
+    }
+    
+    @Override
+    public ASTNode visitXmlNameSpaceStringAsIdentifier(final XmlNameSpaceStringAsIdentifierContext ctx) {
+        return new XmlNameSpaceStringAsIdentifierSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.STRING_().getText(), ctx.identifier().getText(), getOriginalText(ctx));
+    }
+    
+    @Override
+    public ASTNode visitXmlTableOptions(final XmlTableOptionsContext ctx) {
+        XmlTableOptionsSegment result = new XmlTableOptionsSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), getOriginalText(ctx));
+        Collection<ExpressionSegment> expressionSegments = null == ctx.xmlPassingClause().expr() ? Collections.emptyList()
+                : ctx.xmlPassingClause().expr().stream().map(each -> (ExpressionSegment) visit(each)).collect(Collectors.toList());
+        Collection<XmlTableColumnSegment> xmlTableColumnSegments = null == ctx.xmlTableColumn() ? Collections.emptyList()
+                : ctx.xmlTableColumn().stream().map(each -> (XmlTableColumnSegment) visit(each)).collect(Collectors.toList());
+        result.getParameters().addAll(expressionSegments);
+        result.getXmlTableColumnSegments().addAll(xmlTableColumnSegments);
+        return result;
+    }
+    
+    @Override
+    public ASTNode visitXmlTableColumn(final XmlTableColumnContext ctx) {
+        String dataType = null == ctx.dataType() ? null : ctx.dataType().getText();
+        String path = null == ctx.STRING_() ? null : ctx.STRING_().getText();
+        ExpressionSegment defaultExpr = null == ctx.expr() ? null : (ExpressionSegment) visit(ctx.expr());
+        return new XmlTableColumnSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.columnName().getText(), dataType, path, defaultExpr, getOriginalText(ctx));
+    }
+    
     private Collection<ExpressionSegment> getExpressions(final AggregationFunctionContext ctx) {
         return null == ctx.expr() ? Collections.emptyList() : ctx.expr().stream().map(each -> (ExpressionSegment) visit(each)).collect(Collectors.toList());
     }
diff --git a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlNameSpaceStringAsIdentifierSegment.java
similarity index 56%
copy from test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
copy to sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlNameSpaceStringAsIdentifierSegment.java
index 4f24cfec264..3b5e7ab3572 100644
--- a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlNameSpaceStringAsIdentifierSegment.java
@@ -15,27 +15,28 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.table;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr;
 
 import lombok.Getter;
-import lombok.Setter;
-import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.AbstractExpectedDelimiterSQLSegment;
-
-import javax.xml.bind.annotation.XmlElement;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.ComplexExpressionSegment;
 
 /**
- * Expected tables.
+ * Xml name spaces string as identifier segment.
  */
+@RequiredArgsConstructor
 @Getter
-@Setter
-public final class ExpectedTable extends AbstractExpectedDelimiterSQLSegment {
+@ToString
+public final class XmlNameSpaceStringAsIdentifierSegment implements ComplexExpressionSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
     
-    @XmlElement(name = "simple-table")
-    private ExpectedSimpleTable simpleTable;
+    private final String xmlNameSpaceString;
     
-    @XmlElement(name = "subquery-table")
-    private ExpectedSubqueryTable subqueryTable;
+    private final String xmlNameSpaceIdentifier;
     
-    @XmlElement(name = "join-table")
-    private ExpectedJoinTable joinTable;
+    private final String text;
 }
diff --git a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlNameSpacesClauseSegment.java
similarity index 54%
copy from test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
copy to sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlNameSpacesClauseSegment.java
index 4f24cfec264..0d120c3e529 100644
--- a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlNameSpacesClauseSegment.java
@@ -15,27 +15,31 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.table;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr;
 
 import lombok.Getter;
-import lombok.Setter;
-import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.AbstractExpectedDelimiterSQLSegment;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.ComplexExpressionSegment;
 
-import javax.xml.bind.annotation.XmlElement;
+import java.util.Collection;
+import java.util.LinkedList;
 
 /**
- * Expected tables.
+ * Xml name spaces segment.
  */
+@RequiredArgsConstructor
 @Getter
-@Setter
-public final class ExpectedTable extends AbstractExpectedDelimiterSQLSegment {
+@ToString
+public final class XmlNameSpacesClauseSegment implements ComplexExpressionSegment {
     
-    @XmlElement(name = "simple-table")
-    private ExpectedSimpleTable simpleTable;
+    private final int startIndex;
     
-    @XmlElement(name = "subquery-table")
-    private ExpectedSubqueryTable subqueryTable;
+    private final int stopIndex;
     
-    @XmlElement(name = "join-table")
-    private ExpectedJoinTable joinTable;
+    private final String defaultString;
+    
+    private final Collection<XmlNameSpaceStringAsIdentifierSegment> stringAsIdentifier = new LinkedList<>();
+    
+    private final String text;
 }
diff --git a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlTableColumnSegment.java
similarity index 56%
copy from test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
copy to sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlTableColumnSegment.java
index 4f24cfec264..9d65c0d053a 100644
--- a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlTableColumnSegment.java
@@ -15,27 +15,32 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.table;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr;
 
 import lombok.Getter;
-import lombok.Setter;
-import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.AbstractExpectedDelimiterSQLSegment;
-
-import javax.xml.bind.annotation.XmlElement;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.ComplexExpressionSegment;
 
 /**
- * Expected tables.
+ * Xml table column segment.
  */
+@RequiredArgsConstructor
 @Getter
-@Setter
-public final class ExpectedTable extends AbstractExpectedDelimiterSQLSegment {
+@ToString
+public final class XmlTableColumnSegment implements ComplexExpressionSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final String columnName;
+    
+    private final String dataType;
     
-    @XmlElement(name = "simple-table")
-    private ExpectedSimpleTable simpleTable;
+    private final String path;
     
-    @XmlElement(name = "subquery-table")
-    private ExpectedSubqueryTable subqueryTable;
+    private final ExpressionSegment defaultExpr;
     
-    @XmlElement(name = "join-table")
-    private ExpectedJoinTable joinTable;
+    private final String text;
 }
diff --git a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlTableFunctionSegment.java
similarity index 51%
copy from test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
copy to sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlTableFunctionSegment.java
index 4f24cfec264..d6e1e487c37 100644
--- a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlTableFunctionSegment.java
@@ -15,27 +15,33 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.table;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr;
 
 import lombok.Getter;
-import lombok.Setter;
-import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.AbstractExpectedDelimiterSQLSegment;
-
-import javax.xml.bind.annotation.XmlElement;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.ComplexExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 
 /**
- * Expected tables.
+ * Xml table function segment.
  */
+@RequiredArgsConstructor
 @Getter
-@Setter
-public final class ExpectedTable extends AbstractExpectedDelimiterSQLSegment {
+@ToString
+public final class XmlTableFunctionSegment implements ComplexExpressionSegment, ProjectionSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final String functionName;
+    
+    private final XmlNameSpacesClauseSegment xmlNameSpacesClause;
     
-    @XmlElement(name = "simple-table")
-    private ExpectedSimpleTable simpleTable;
+    private final String xQueryString;
     
-    @XmlElement(name = "subquery-table")
-    private ExpectedSubqueryTable subqueryTable;
+    private final XmlTableOptionsSegment xmlTableOption;
     
-    @XmlElement(name = "join-table")
-    private ExpectedJoinTable joinTable;
+    private final String text;
 }
diff --git a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlTableOptionsSegment.java
similarity index 54%
copy from test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
copy to sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlTableOptionsSegment.java
index 4f24cfec264..38b7f8864fd 100644
--- a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlTableOptionsSegment.java
@@ -15,27 +15,31 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.table;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr;
 
 import lombok.Getter;
-import lombok.Setter;
-import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.AbstractExpectedDelimiterSQLSegment;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.ComplexExpressionSegment;
 
-import javax.xml.bind.annotation.XmlElement;
+import java.util.Collection;
+import java.util.LinkedList;
 
 /**
- * Expected tables.
+ * Xml table options segment.
  */
+@RequiredArgsConstructor
 @Getter
-@Setter
-public final class ExpectedTable extends AbstractExpectedDelimiterSQLSegment {
+@ToString
+public final class XmlTableOptionsSegment implements ComplexExpressionSegment {
     
-    @XmlElement(name = "simple-table")
-    private ExpectedSimpleTable simpleTable;
+    private final int startIndex;
     
-    @XmlElement(name = "subquery-table")
-    private ExpectedSubqueryTable subqueryTable;
+    private final int stopIndex;
     
-    @XmlElement(name = "join-table")
-    private ExpectedJoinTable joinTable;
+    private final Collection<ExpressionSegment> parameters = new LinkedList<>();
+    
+    private final Collection<XmlTableColumnSegment> xmlTableColumnSegments = new LinkedList<>();
+    
+    private final String text;
 }
diff --git a/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/XmlTableSegment.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/XmlTableSegment.java
new file mode 100644
index 00000000000..7448c2ab1fd
--- /dev/null
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/XmlTableSegment.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlTableFunctionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.Optional;
+
+/**
+ * XML table segment.
+ */
+@RequiredArgsConstructor
+@Getter
+@Setter
+@ToString
+public final class XmlTableSegment implements TableSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final String tableName;
+    
+    private final String tableNameAlias;
+    
+    private final XmlTableFunctionSegment xmlTableFunction;
+    
+    private final String xmlTableFunctionAlias;
+    
+    @Override
+    public Optional<String> getAlias() {
+        return Optional.empty();
+    }
+    
+    @Override
+    public void setAlias(final AliasSegment alias) {
+    }
+}
diff --git a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/asserts/segment/table/TableAssert.java b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/asserts/segment/table/TableAssert.java
index 74bfeccd74e..67f8bc467e4 100644
--- a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/asserts/segment/table/TableAssert.java
+++ b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/asserts/segment/table/TableAssert.java
@@ -20,29 +20,33 @@ package org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.table
 import com.google.common.base.Strings;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlTableFunctionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.XmlTableSegment;
 import org.apache.shardingsphere.test.sql.parser.internal.asserts.SQLCaseAssertContext;
 import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.SQLSegmentAssert;
 import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.column.ColumnAssert;
 import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.expression.ExpressionAssert;
+import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.identifier.IdentifierValueAssert;
 import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.owner.OwnerAssert;
 import org.apache.shardingsphere.test.sql.parser.internal.asserts.statement.dml.impl.SelectStatementAssert;
-import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.identifier.IdentifierValueAssert;
 import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.column.ExpectedColumn;
+import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.expr.ExpectedXmlTableFunction;
 import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.table.ExpectedJoinTable;
 import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.table.ExpectedSimpleTable;
 import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.table.ExpectedSubqueryTable;
 import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.table.ExpectedTable;
+import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.table.ExpectedXmlTable;
 
 import java.util.Collection;
 import java.util.List;
 
 import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertFalse;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -65,12 +69,28 @@ public final class TableAssert {
             assertIs(assertContext, (SimpleTableSegment) actual, expected.getSimpleTable());
         } else if (actual instanceof SubqueryTableSegment) {
             assertIs(assertContext, (SubqueryTableSegment) actual, expected.getSubqueryTable());
+        } else if (actual instanceof XmlTableSegment) {
+            assertIs(assertContext, (XmlTableSegment) actual, expected.getXmlTable());
         } else {
             throw new UnsupportedOperationException(
                     String.format("Unsupported table segment type `%s`.", actual.getClass()));
         }
     }
     
+    /**
+     * Assert actual xml table segment is correct with expected xml table.
+     *
+     * @param assertContext assert context
+     * @param actual actual xml table
+     * @param expected expected xml table
+     */
+    private static void assertIs(final SQLCaseAssertContext assertContext, final XmlTableSegment actual, final ExpectedXmlTable expected) {
+        assertThat(assertContext.getText("Table name assertion error"), actual.getTableName(), is(expected.getTableName()));
+        assertThat(assertContext.getText("Table name alias assertion error"), actual.getTableNameAlias(), is(expected.getTableAlias()));
+        assertXmlTableFunction(assertContext, actual.getXmlTableFunction(), expected.getXmlTableFunction());
+        assertThat(assertContext.getText("Xml table function alias assertion error"), actual.getXmlTableFunctionAlias(), is(expected.getXmlTableFunctionAlias()));
+    }
+    
     /**
      * Assert actual table segment is correct with expected table.
      *
@@ -160,4 +180,16 @@ public final class TableAssert {
             assertThat(assertContext.getText("Actual join-type should exist."), actual, is(expected));
         }
     }
+    
+    /**
+     * Assert actual xml table function segment is correct with expected xml table function.
+     *
+     * @param assertContext assert context
+     * @param actual actual xml table function
+     * @param expected expected xml table function
+     */
+    private static void assertXmlTableFunction(final SQLCaseAssertContext assertContext, final XmlTableFunctionSegment actual, final ExpectedXmlTableFunction expected) {
+        assertThat(assertContext.getText("Function name assertion error"), actual.getFunctionName(), is(expected.getFunctionName()));
+        assertThat(assertContext.getText("Function text assert error"), actual.getText(), is(expected.getText()));
+    }
 }
diff --git a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/expr/ExpectedXmlTableFunction.java
similarity index 67%
copy from test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
copy to test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/expr/ExpectedXmlTableFunction.java
index 4f24cfec264..34fff8b81cc 100644
--- a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
+++ b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/expr/ExpectedXmlTableFunction.java
@@ -15,27 +15,24 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.table;
+package org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.expr;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.AbstractExpectedDelimiterSQLSegment;
+import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.AbstractExpectedSQLSegment;
 
-import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlAttribute;
 
 /**
- * Expected tables.
+ * Expected xml table function.
  */
 @Getter
 @Setter
-public final class ExpectedTable extends AbstractExpectedDelimiterSQLSegment {
+public final class ExpectedXmlTableFunction extends AbstractExpectedSQLSegment implements ExpectedExpressionSegment {
     
-    @XmlElement(name = "simple-table")
-    private ExpectedSimpleTable simpleTable;
+    @XmlAttribute(name = "function-name")
+    private String functionName;
     
-    @XmlElement(name = "subquery-table")
-    private ExpectedSubqueryTable subqueryTable;
-    
-    @XmlElement(name = "join-table")
-    private ExpectedJoinTable joinTable;
+    @XmlAttribute
+    private String text;
 }
diff --git a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
index 4f24cfec264..19d6a1049ab 100644
--- a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
+++ b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
@@ -38,4 +38,7 @@ public final class ExpectedTable extends AbstractExpectedDelimiterSQLSegment {
     
     @XmlElement(name = "join-table")
     private ExpectedJoinTable joinTable;
+    
+    @XmlElement(name = "xml-table")
+    private ExpectedXmlTable xmlTable;
 }
diff --git a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedXmlTable.java
similarity index 65%
copy from test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
copy to test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedXmlTable.java
index 4f24cfec264..930a3381319 100644
--- a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedTable.java
+++ b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/table/ExpectedXmlTable.java
@@ -20,22 +20,27 @@ package org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.s
 import lombok.Getter;
 import lombok.Setter;
 import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.AbstractExpectedDelimiterSQLSegment;
+import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.expr.ExpectedXmlTableFunction;
 
+import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
 
 /**
- * Expected tables.
+ * Expected xml table.
  */
 @Getter
 @Setter
-public final class ExpectedTable extends AbstractExpectedDelimiterSQLSegment {
+public final class ExpectedXmlTable extends AbstractExpectedDelimiterSQLSegment {
     
-    @XmlElement(name = "simple-table")
-    private ExpectedSimpleTable simpleTable;
+    @XmlAttribute(name = "table-name")
+    private String tableName;
     
-    @XmlElement(name = "subquery-table")
-    private ExpectedSubqueryTable subqueryTable;
+    @XmlAttribute(name = "table-alias")
+    private String tableAlias;
     
-    @XmlElement(name = "join-table")
-    private ExpectedJoinTable joinTable;
+    @XmlElement(name = "xml-table-function")
+    private ExpectedXmlTableFunction xmlTableFunction;
+    
+    @XmlAttribute(name = "xml-table-function-alias")
+    private String xmlTableFunctionAlias;
 }
diff --git a/test/parser/src/main/resources/case/dml/select.xml b/test/parser/src/main/resources/case/dml/select.xml
index 8ca0bc89015..71dd44bd0b0 100644
--- a/test/parser/src/main/resources/case/dml/select.xml
+++ b/test/parser/src/main/resources/case/dml/select.xml
@@ -4778,4 +4778,21 @@
             <simple-table name="b" start-index="103" stop-index="103" />
         </from>
     </select>
+
+    <select sql-case-id="select_from_xmltable_function">
+        <projections start-index="7" stop-index="65">
+            <column-projection name="warehouse_name" alias="warehouse" start-index="7" stop-index="30" />
+            <column-projection name="Water" start-index="33" stop-index="48">
+                <owner name="warehouse2" start-index="33" stop-index="42" />
+            </column-projection>
+            <column-projection name="Rail" start-index="51" stop-index="65">
+                <owner name="warehouse2" start-index="51" stop-index="60" />
+            </column-projection>
+        </projections>
+        <from>
+            <xml-table table-name="warehouses" xml-table-function-alias="warehouse2" start-index="76" stop-index="238">
+                <xml-table-function function-name="XMLTABLE" text="XMLTABLE('/Warehouse' PASSING warehouses.warehouse_spec COLUMNS &quot;Water&quot; varchar2(6) PATH 'WaterAccess',&quot;Rail&quot; varchar2(6) PATH 'RailAccess')" start-index="88" stop-index="227" />
+            </xml-table>
+        </from>
+    </select>
 </sql-parser-test-cases>
diff --git a/test/parser/src/main/resources/sql/supported/dml/select.xml b/test/parser/src/main/resources/sql/supported/dml/select.xml
index 973c59fe0c2..232235bafa8 100644
--- a/test/parser/src/main/resources/sql/supported/dml/select.xml
+++ b/test/parser/src/main/resources/sql/supported/dml/select.xml
@@ -154,4 +154,5 @@
     <sql-case id="select_xmlquery_function" value="SELECT XMLQUERY('//student[@age=20]' PASSING BY VALUE xcol AS x RETURNING CONTENT NULL ON EMPTY) FROM x_table;" db-types="Oracle" />
     <sql-case id="select_xmlroot_function" value="SELECT XMLROOT(XMLType('143598'), VERSION '1.0', STANDALONE YES) AS 'XMLROOT' FROM DUAL;" db-types="Oracle" />
     <sql-case id="select_xmlserialize_function" value="SELECT XMLSERIALIZE(DOCUMENT c2 AS BLOB ENCODING 'UTF-8' VERSION 'a' IDENT SIZE = 0 SHOW DEFAULT) FROM b;" db-types="Oracle" />
+    <sql-case id="select_from_xmltable_function" value="SELECT warehouse_name warehouse, warehouse2.Water, warehouse2.Rail FROM warehouses, XMLTABLE('/Warehouse' PASSING warehouses.warehouse_spec COLUMNS &quot;Water&quot; varchar2(6) PATH 'WaterAccess',&quot;Rail&quot; varchar2(6) PATH 'RailAccess') warehouse2;" db-types="Oracle" />
 </sql-cases>