This is an automated email from the ASF dual-hosted git repository.
duanzhengqiang 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 943c256d83d fix:Support Hive CREATE VIEW statement parse (#36120)
943c256d83d is described below
commit 943c256d83da0a9c531aba1999dc8b9fb07a45ea
Author: Claire <[email protected]>
AuthorDate: Wed Jul 30 16:19:12 2025 +0800
fix:Support Hive CREATE VIEW statement parse (#36120)
* support hive create view statement
* update code
* update RELEASE-NOTES.md
---
RELEASE-NOTES.md | 1 +
.../src/main/antlr4/imports/hive/DDLStatement.g4 | 8 +
.../sql/parser/autogen/HiveStatement.g4 | 1 +
.../statement/type/HiveDDLStatementVisitor.java | 38 ++++
.../src/main/resources/case/ddl/create-view.xml | 203 +++++++++++++++++++++
.../resources/sql/supported/ddl/create-view.xml | 10 +
6 files changed, 261 insertions(+)
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index f50fb418d3b..dc24798204b 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -75,6 +75,7 @@
1. Encrypt: Add quotes to encrypt rewrite derived columns -
[#34950](https://github.com/apache/shardingsphere/pull/34950)
1. Encrypt: Add support for NOT LIKE operator in encryption -
[#35984](https://github.com/apache/shardingsphere/pull/35984)
1. SQL Parser: Support Hive ALTER COLUMN statement parse -
[#36096](https://github.com/apache/shardingsphere/pull/36096)
+1. SQL Parser: Support Hive CREATE VIEW statement parse -
[#36120](https://github.com/apache/shardingsphere/pull/36120)
### Bug Fixes
diff --git
a/parser/sql/dialect/hive/src/main/antlr4/imports/hive/DDLStatement.g4
b/parser/sql/dialect/hive/src/main/antlr4/imports/hive/DDLStatement.g4
index 6b70490bd50..f6cfa0731ce 100644
--- a/parser/sql/dialect/hive/src/main/antlr4/imports/hive/DDLStatement.g4
+++ b/parser/sql/dialect/hive/src/main/antlr4/imports/hive/DDLStatement.g4
@@ -40,6 +40,10 @@ createTable
| createTableCommonClause LIKE existingTableName storageLocation?
;
+createView
+ : CREATE VIEW ifNotExists? viewNameWithDb (LP_ columnName (COMMENT
string_)? (COMMA_ columnName (COMMENT string_)?)* RP_)? (COMMENT string_)?
tblProperties? AS select
+ ;
+
dropTable
: DROP TABLE ifExists? tableNameWithDb (PURGE)?
;
@@ -118,6 +122,10 @@ tableNameWithDb
: (identifier DOT_)? identifier
;
+viewNameWithDb
+ : (identifier DOT_)? identifier
+ ;
+
existingTableName
: (identifier DOT_)? identifier
;
diff --git
a/parser/sql/dialect/hive/src/main/antlr4/org/apache/shardingsphere/sql/parser/autogen/HiveStatement.g4
b/parser/sql/dialect/hive/src/main/antlr4/org/apache/shardingsphere/sql/parser/autogen/HiveStatement.g4
index fbd1cda5a75..389081c50a8 100644
---
a/parser/sql/dialect/hive/src/main/antlr4/org/apache/shardingsphere/sql/parser/autogen/HiveStatement.g4
+++
b/parser/sql/dialect/hive/src/main/antlr4/org/apache/shardingsphere/sql/parser/autogen/HiveStatement.g4
@@ -35,6 +35,7 @@ execute
| truncateTable
| msckStatement
| alterTable
+ | createView
) (SEMI_ EOF? | EOF)
| EOF
;
diff --git
a/parser/sql/dialect/hive/src/main/java/org/apache/shardingsphere/sql/parser/hive/visitor/statement/type/HiveDDLStatementVisitor.java
b/parser/sql/dialect/hive/src/main/java/org/apache/shardingsphere/sql/parser/hive/visitor/statement/type/HiveDDLStatementVisitor.java
index 6dc03106b4b..1fc6cd2dd3e 100644
---
a/parser/sql/dialect/hive/src/main/java/org/apache/shardingsphere/sql/parser/hive/visitor/statement/type/HiveDDLStatementVisitor.java
+++
b/parser/sql/dialect/hive/src/main/java/org/apache/shardingsphere/sql/parser/hive/visitor/statement/type/HiveDDLStatementVisitor.java
@@ -61,6 +61,10 @@ import
org.apache.shardingsphere.sql.parser.autogen.HiveStatementParser.AddColum
import
org.apache.shardingsphere.sql.parser.autogen.HiveStatementParser.ReplaceColumnsContext;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.column.alter.AddColumnDefinitionSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.column.alter.ReplaceColumnDefinitionSegment;
+import
org.apache.shardingsphere.sql.parser.autogen.HiveStatementParser.CreateViewContext;
+import
org.apache.shardingsphere.sql.parser.autogen.HiveStatementParser.ViewNameWithDbContext;
+import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.ddl.view.CreateViewStatement;
+import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
import java.util.Collections;
/**
@@ -267,4 +271,38 @@ public final class HiveDDLStatementVisitor extends
HiveStatementVisitor implemen
public ASTNode visitTableConstraint(final TableConstraintContext ctx) {
return new ConstraintDefinitionSegment(ctx.getStart().getStartIndex(),
ctx.getStop().getStopIndex());
}
+
+ @Override
+ public ASTNode visitCreateView(final CreateViewContext ctx) {
+ CreateViewStatement result = new
CreateViewStatement(getDatabaseType());
+ result.setView((SimpleTableSegment) visit(ctx.viewNameWithDb()));
+ if (null != ctx.COMMENT() && !ctx.string_().isEmpty()) {
+ result.setViewDefinition(ctx.string_(ctx.string_().size() -
1).getText().replace("'", ""));
+ }
+ if (null != ctx.tblProperties()) {
+ result.setViewDefinition(getText(ctx.tblProperties()));
+ }
+ HiveDMLStatementVisitor dmlVisitor = new
HiveDMLStatementVisitor(getDatabaseType());
+ ASTNode selectNode = dmlVisitor.visit(ctx.select());
+ if (selectNode instanceof SelectStatement) {
+ result.setSelect((SelectStatement) selectNode);
+ }
+ result.setViewDefinition(getText(ctx));
+ return result;
+ }
+
+ @Override
+ public ASTNode visitViewNameWithDb(final ViewNameWithDbContext ctx) {
+ if (1 == ctx.identifier().size()) {
+ return new SimpleTableSegment(new
TableNameSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(),
+ new IdentifierValue(ctx.identifier(0).getText())));
+ } else {
+ SimpleTableSegment result = new SimpleTableSegment(new
TableNameSegment(ctx.identifier(1).getStart().getStartIndex(),
+ ctx.identifier(1).getStop().getStopIndex(), new
IdentifierValue(ctx.identifier(1).getText())));
+ result.setOwner(new
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.OwnerSegment(
+ ctx.identifier(0).getStart().getStartIndex(),
ctx.identifier(0).getStop().getStopIndex(),
+ new IdentifierValue(ctx.identifier(0).getText())));
+ return result;
+ }
+ }
}
diff --git a/test/it/parser/src/main/resources/case/ddl/create-view.xml
b/test/it/parser/src/main/resources/case/ddl/create-view.xml
index a5b1279539a..69556758a17 100644
--- a/test/it/parser/src/main/resources/case/ddl/create-view.xml
+++ b/test/it/parser/src/main/resources/case/ddl/create-view.xml
@@ -2165,4 +2165,207 @@
</where>
</select>
</create-view>
+
+ <create-view sql-case-id="create_view_hive" view-definition="CREATE VIEW
onion_referrers(url COMMENT 'URL of Referring page') COMMENT 'Referrers to The
Onion website' AS SELECT DISTINCT referrer_url FROM page_view WHERE
page_url='http://www.theonion.com'">
+ <view name="onion_referrers" start-index="12" stop-index="26">
+ <column name="url" comment="URL of Referring page"
start-index="29" stop-index="31" />
+ </view>
+ <view-comment value="Referrers to The Onion website" start-index="34"
stop-index="70" />
+ <select>
+ <distinct start-index="84" stop-index="92" />
+ <projections start-index="125" stop-index="136"
distinct-row="true">
+ <column-projection name="referrer_url" start-index="125"
stop-index="136" />
+ </projections>
+ <from>
+ <simple-table name="page_view" start-index="143"
stop-index="151" />
+ </from>
+ <where start-index="153" stop-index="192">
+ <expr>
+ <binary-operation-expression start-index="159"
stop-index="192">
+ <left>
+ <column name="page_url" start-index="159"
stop-index="166" />
+ </left>
+ <right>
+ <literal-expression
value="http://www.theonion.com" start-index="168" stop-index="192" />
+ </right>
+ <operator>=</operator>
+ </binary-operation-expression>
+ </expr>
+ </where>
+ </select>
+ </create-view>
+
+ <create-view sql-case-id="create_view_basic" view-definition="CREATE VIEW
sales_summary AS SELECT order_id, total FROM sales">
+ <view name="sales_summary" start-index="12" stop-index="24" />
+ <select>
+ <projections start-index="36" stop-index="50">
+ <column-projection name="order_id" start-index="36"
stop-index="43" />
+ <column-projection name="total" start-index="46"
stop-index="50" />
+ </projections>
+ <from>
+ <simple-table name="sales" start-index="57" stop-index="61" />
+ </from>
+ </select>
+ </create-view>
+
+ <create-view sql-case-id="create_view_with_if_not_exists"
view-definition="CREATE VIEW IF NOT EXISTS sales_summary AS SELECT order_id,
total FROM sales">
+ <view name="sales_summary" start-index="26" stop-index="38" />
+ <select>
+ <projections start-index="50" stop-index="64">
+ <column-projection name="order_id" start-index="50"
stop-index="57" />
+ <column-projection name="total" start-index="60"
stop-index="64" />
+ </projections>
+ <from>
+ <simple-table name="sales" start-index="71" stop-index="75" />
+ </from>
+ </select>
+ </create-view>
+
+ <create-view sql-case-id="create_view_with_column_def"
view-definition="CREATE VIEW sales_summary (order_id COMMENT 'ID', total
COMMENT 'total') AS SELECT order_id, total FROM sales">
+ <view name="sales_summary" start-index="12" stop-index="24">
+ <column name="order_id" comment="ID" start-index="25"
stop-index="33" />
+ <column name="total" comment="total" start-index="44"
stop-index="49" />
+ </view>
+ <select>
+ <projections start-index="83" stop-index="97">
+ <column-projection name="order_id" start-index="83"
stop-index="90" />
+ <column-projection name="total" start-index="93"
stop-index="97" />
+ </projections>
+ <from>
+ <simple-table name="sales" start-index="104" stop-index="108"
/>
+ </from>
+ </select>
+ </create-view>
+
+ <create-view sql-case-id="create_view_with_comment"
view-definition="CREATE VIEW sales_summary COMMENT 'view' AS SELECT order_id,
total FROM sales">
+ <view name="sales_summary" start-index="12" stop-index="24" />
+ <view-comment value="view" start-index="25" stop-index="33" />
+ <select>
+ <projections start-index="51" stop-index="65">
+ <column-projection name="order_id" start-index="51"
stop-index="58" />
+ <column-projection name="total" start-index="61"
stop-index="65" />
+ </projections>
+ <from>
+ <simple-table name="sales" start-index="72" stop-index="76" />
+ </from>
+ </select>
+ </create-view>
+
+ <create-view sql-case-id="create_view_with_tblproperties"
view-definition="CREATE VIEW sales_summary TBLPROPERTIES ('creator' =
'data_team', 'version' = '1.0') AS SELECT order_id, total FROM sales">
+ <view name="sales_summary" start-index="12" stop-index="24" />
+ <tblproperties start-index="26" stop-index="91">
+ <property key="creator" value="data_team" start-index="40"
stop-index="60" />
+ <property key="version" value="1.0" start-index="63"
stop-index="83" />
+ </tblproperties>
+ <select>
+ <projections start-index="95" stop-index="109">
+ <column-projection name="order_id" start-index="95"
stop-index="102" />
+ <column-projection name="total" start-index="105"
stop-index="109" />
+ </projections>
+ <from>
+ <simple-table name="sales" start-index="116" stop-index="120"
/>
+ </from>
+ </select>
+ </create-view>
+
+ <create-view sql-case-id="create_view_with_order_by"
view-definition="CREATE VIEW top_sales AS SELECT order_id, total FROM sales
ORDER BY total DESC">
+ <view name="top_sales" start-index="12" stop-index="20" />
+ <select>
+ <projections start-index="32" stop-index="46">
+ <column-projection name="order_id" start-index="32"
stop-index="39" />
+ <column-projection name="total" start-index="42"
stop-index="46" />
+ </projections>
+ <from>
+ <simple-table name="sales" start-index="53" stop-index="57" />
+ </from>
+ <order-by start-index="65" stop-index="84">
+ <column-item name="total" order-direction="DESC"
start-index="68" stop-index="72" />
+ </order-by>
+ </select>
+ </create-view>
+
+ <create-view sql-case-id="create_view_with_limit" view-definition="CREATE
VIEW recent_orders AS SELECT order_id, order_date FROM sales LIMIT 100">
+ <view name="recent_orders" start-index="12" stop-index="24" />
+ <select>
+ <projections start-index="36" stop-index="55">
+ <column-projection name="order_id" start-index="36"
stop-index="43" />
+ <column-projection name="order_date" start-index="46"
stop-index="55" />
+ </projections>
+ <from>
+ <simple-table name="sales" start-index="62" stop-index="66" />
+ </from>
+ <limit start-index="68" stop-index="76">
+ <row-count value="100" start-index="74" stop-index="76" />
+ </limit>
+ </select>
+ </create-view>
+
+ <create-view sql-case-id="create_view_with_db_name"
view-definition="CREATE VIEW db1.sales_summary AS SELECT order_id, total FROM
db2.sales">
+ <view name="sales_summary" start-index="12" stop-index="28">
+ <owner name="db1" start-index="12" stop-index="14" />
+ </view>
+ <select>
+ <projections start-index="40" stop-index="54">
+ <column-projection name="order_id" start-index="40"
stop-index="47" />
+ <column-projection name="total" start-index="50"
stop-index="54" />
+ </projections>
+ <from>
+ <simple-table name="sales" start-index="61" stop-index="69">
+ <owner name="db2" start-index="61" stop-index="63" />
+ </simple-table>
+ </from>
+ </select>
+ </create-view>
+
+ <create-view sql-case-id="create_view_with_cte" view-definition="CREATE
VIEW user_orders AS WITH user_cte AS (SELECT id, name FROM users) SELECT
u.name, o.order_id FROM user_cte u JOIN orders o ON u.id = o.user_id">
+ <view name="user_orders" start-index="12" stop-index="22" />
+ <cte start-index="38" stop-index="76">
+ <cte-item name="user_cte" start-index="43" stop-index="51">
+ <select>
+ <projections start-index="63" stop-index="70">
+ <column-projection name="id" start-index="63"
stop-index="65" />
+ <column-projection name="name" start-index="68"
stop-index="70" />
+ </projections>
+ <from>
+ <simple-table name="users" start-index="77"
stop-index="82" />
+ </from>
+ </select>
+ </cte-item>
+ </cte>
+ <select>
+ <projections start-index="80" stop-index="97">
+ <column-projection name="name" start-index="80"
stop-index="85">
+ <owner name="u" start-index="80" stop-index="80" />
+ </column-projection>
+ <column-projection name="order_id" start-index="88"
stop-index="97">
+ <owner name="o" start-index="88" stop-index="88" />
+ </column-projection>
+ </projections>
+ <from>
+ <join-table join-type="INNER">
+ <left>
+ <simple-table name="user_cte" alias="u"
start-index="104" stop-index="113" />
+ </left>
+ <right>
+ <simple-table name="orders" alias="o"
start-index="120" stop-index="127" />
+ </right>
+ <on-condition>
+ <binary-operation-expression start-index="132"
stop-index="147">
+ <left>
+ <column name="id" start-index="132"
stop-index="135">
+ <owner name="u" start-index="132"
stop-index="132" />
+ </column>
+ </left>
+ <operator>=</operator>
+ <right>
+ <column name="user_id" start-index="139"
stop-index="147">
+ <owner name="o" start-index="139"
stop-index="139" />
+ </column>
+ </right>
+ </binary-operation-expression>
+ </on-condition>
+ </join-table>
+ </from>
+ </select>
+ </create-view>
</sql-parser-test-cases>
diff --git
a/test/it/parser/src/main/resources/sql/supported/ddl/create-view.xml
b/test/it/parser/src/main/resources/sql/supported/ddl/create-view.xml
index 2812513ed17..624a6aeacd3 100644
--- a/test/it/parser/src/main/resources/sql/supported/ddl/create-view.xml
+++ b/test/it/parser/src/main/resources/sql/supported/ddl/create-view.xml
@@ -96,4 +96,14 @@
<sql-case id="create_view_select_to_number_to_char" value="CREATE VIEW
time_view AS SELECT time_id, TO_NUMBER(TO_CHAR(time_id, 'ddd')) AS day_in_year
FROM times" db-types="Oracle" />
<sql-case id="create_view_select_subquery_with_union_all" value="CREATE
VIEW view_with_unionall AS (SELECT c.rowid crid, c.cust_id, 2 umarker FROM
customers c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid,
c.cust_id, 3 umarker FROM customers c WHERE c.cust_last_name = 'Jones')"
db-types="Oracle" />
<sql-case id="create_view_select_sys_XMLGen" value="CREATE OR REPLACE VIEW
employee_view OF XMLType WITH OBJECT ID (XMLCast(XMLQuery('/Emp/@empno' PASSING
OBJECT_VALUE RETURNING CONTENT) AS BINARY_DOUBLE)) AS SELECT
sys_XMLGen(emp_t(e.employee_id, e.first_name, e.last_name,
e.hire_date),XMLFormat('EMP')) FROM employees e WHERE salary > 15000;"
db-types="Oracle" />
+ <sql-case id="create_view_hive" value="CREATE VIEW onion_referrers(url
COMMENT 'URL of Referring page') COMMENT 'Referrers to The Onion website' AS
SELECT DISTINCT referrer_url FROM page_view WHERE
page_url='http://www.theonion.com';" db-types="Hive" />
+ <sql-case id="create_view_basic" value="CREATE VIEW sales_summary AS
SELECT order_id, total FROM sales" db-types="Hive" />
+ <sql-case id="create_view_with_if_not_exists" value="CREATE VIEW IF NOT
EXISTS sales_summary AS SELECT order_id, total FROM sales" db-types="Hive" />
+ <sql-case id="create_view_with_column_def" value="CREATE VIEW
sales_summary (order_id COMMENT 'ID', total COMMENT 'total') AS SELECT
order_id, total FROM sales" db-types="Hive" />
+ <sql-case id="create_view_with_comment" value="CREATE VIEW sales_summary
COMMENT 'view' AS SELECT order_id, total FROM sales" db-types="Hive" />
+ <sql-case id="create_view_with_tblproperties" value="CREATE VIEW
sales_summary TBLPROPERTIES ('creator' = 'data_team', 'version' = '1.0') AS
SELECT order_id, total FROM sales" db-types="Hive" />
+ <sql-case id="create_view_with_order_by" value="CREATE VIEW top_sales AS
SELECT order_id, total FROM sales ORDER BY total DESC" db-types="Hive" />
+ <sql-case id="create_view_with_limit" value="CREATE VIEW recent_orders AS
SELECT order_id, order_date FROM sales LIMIT 100" db-types="Hive" />
+ <sql-case id="create_view_with_db_name" value="CREATE VIEW
db1.sales_summary AS SELECT order_id, total FROM db2.sales" db-types="Hive" />
+ <sql-case id="create_view_with_cte" value="CREATE VIEW user_orders AS WITH
user_cte AS (SELECT id, name FROM users) SELECT u.name, o.order_id FROM
user_cte u JOIN orders o ON u.id = o.user_id" db-types="Hive" />
</sql-cases>