This is an automated email from the ASF dual-hosted git repository.
JackieTien97 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 96c905e8146 [SQL] Add STREAM and STREAMS as reserved keywords (#18458)
96c905e8146 is described below
commit 96c905e814665e1f8713a3f8925ba225ffa9fea1
Author: shizy <[email protected]>
AuthorDate: Thu Aug 13 11:23:03 2026 +0800
[SQL] Add STREAM and STREAMS as reserved keywords (#18458)
---
.../relational/sql/parser/StreamKeywordTest.java | 127 +++++++++++++++++++++
.../db/relational/grammar/sql/RelationalSql.g4 | 4 +-
2 files changed, 130 insertions(+), 1 deletion(-)
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/StreamKeywordTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/StreamKeywordTest.java
new file mode 100644
index 00000000000..765870b42b7
--- /dev/null
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/StreamKeywordTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.iotdb.db.queryengine.plan.relational.sql.parser;
+
+import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Statement;
+import org.apache.iotdb.db.protocol.session.IClientSession;
+import org.apache.iotdb.db.protocol.session.InternalClientSession;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDB;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateTable;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.time.ZoneId;
+
+public class StreamKeywordTest {
+
+ private SqlParser sqlParser;
+ private IClientSession clientSession;
+
+ @Before
+ public void setUp() {
+ sqlParser = new SqlParser();
+ clientSession = new InternalClientSession("testClient");
+ }
+
+ @Test
+ public void testStreamAsTableNameShouldFail() {
+ // STREAM cannot be used as table name without quoting
+ try {
+ sqlParser.createStatement(
+ "CREATE TABLE stream (col1 INT32 TAG, col2 INT32 FIELD)",
+ ZoneId.systemDefault(),
+ clientSession);
+ Assert.fail("Creating table with reserved keyword 'stream' should fail");
+ } catch (final Exception e) {
+ // Expected - stream is a reserved keyword
+ Assert.assertTrue(
+ "Expected parsing error for 'stream' keyword",
+ e.getMessage().contains("Encountered") ||
e.getMessage().contains("mismatched"));
+ }
+ }
+
+ @Test
+ public void testStreamAsColumnNameShouldFail() {
+ // STREAM cannot be used as column name without quoting
+ try {
+ sqlParser.createStatement(
+ "CREATE TABLE test_table (stream INT32 TAG, col2 INT32 FIELD)",
+ ZoneId.systemDefault(),
+ clientSession);
+ Assert.fail("Creating column with reserved keyword 'stream' should
fail");
+ } catch (final Exception e) {
+ // Expected - stream is a reserved keyword
+ Assert.assertTrue(
+ "Expected parsing error for 'stream' keyword",
+ e.getMessage().contains("Encountered") ||
e.getMessage().contains("mismatched"));
+ }
+ }
+
+ @Test
+ public void testStreamAsDatabaseNameShouldFail() {
+ // STREAM cannot be used as database name without quoting
+ try {
+ sqlParser.createStatement("CREATE DATABASE stream",
ZoneId.systemDefault(), clientSession);
+ Assert.fail("Creating database with reserved keyword 'stream' should
fail");
+ } catch (final Exception e) {
+ // Expected - stream is a reserved keyword
+ Assert.assertTrue(
+ "Expected parsing error for 'stream' keyword",
+ e.getMessage().contains("Encountered") ||
e.getMessage().contains("mismatched"));
+ }
+ }
+
+ @Test
+ public void testQuotedStreamShouldWork() {
+ // Quoted STREAM should work as identifier
+ Statement statement =
+ sqlParser.createStatement(
+ "CREATE DATABASE \"stream\"", ZoneId.systemDefault(),
clientSession);
+ CreateDB createDb = (CreateDB) statement;
+ Assert.assertEquals("stream", createDb.getDbName());
+
+ statement =
+ sqlParser.createStatement(
+ "CREATE TABLE \"stream\" (\"stream\" INT32 TAG, col2 INT32 FIELD)",
+ ZoneId.systemDefault(),
+ clientSession);
+ CreateTable createTable = (CreateTable) statement;
+ Assert.assertEquals("stream", createTable.getName().toString());
+ }
+
+ @Test
+ public void testStreamsAsNonReservedKeyword() {
+ // STREAMS is non-reserved and can be used as identifier
+ Statement statement =
+ sqlParser.createStatement("CREATE DATABASE streams",
ZoneId.systemDefault(), clientSession);
+ CreateDB createDb = (CreateDB) statement;
+ Assert.assertEquals("streams", createDb.getDbName());
+
+ statement =
+ sqlParser.createStatement(
+ "CREATE TABLE streams (streams INT32 TAG, col2 INT32 FIELD)",
+ ZoneId.systemDefault(),
+ clientSession);
+ CreateTable createTable = (CreateTable) statement;
+ Assert.assertEquals("streams", createTable.getName().toString());
+ }
+}
diff --git
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
index e8e3c1937a7..6ab05044dfb 100644
---
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
+++
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
@@ -1528,7 +1528,7 @@ nonReserved
| QUERIES | QUERY | QUOTES
| RANGE | READ | READONLY | RECONSTRUCT | REFRESH | REGION | REGIONID |
REGIONS | REMOVE | RENAME | REPAIR | REPEAT | REPEATABLE | REPLACE | RESET |
RESPECT | RESTRICT | RETURN | RETURNING | RETURNS | REVOKE | ROLE | ROLES |
ROLLBACK | ROOT | ROW | ROWS | RPR_FIRST | RPR_LAST | RUNNING
| SERIESSLOTID | SERVICE | SERVICES | SCALAR | SCHEMA | SCHEMAS | SECOND |
SECURITY | SEEK | SERIALIZABLE | SESSION | SET | SETS
- | SECURITY | SHOW | SINK | SOME | SOURCE | START | STATS | STOP |
SUBSCRIPTION | SUBSCRIPTIONS | SUBSET | SUBSTRING | SYSTEM
+ | SECURITY | SHOW | SINK | SOME | SOURCE | START | STATS | STOP | STREAMS
| SUBSCRIPTION | SUBSCRIPTIONS | SUBSET | SUBSTRING | SYSTEM
| TABLES | TABLESAMPLE | TAG | TAGS | TEXT | TEXT_STRING | TIES | TIME |
TIMEPARTITION | TIMER | TIMER_XL | TIMESERIES | TIMESLOTID | TIMESTAMP | TO |
TOPIC | TOPICS | TRAILING | TRANSACTION | TRUNCATE | TRY_CAST | TYPE
| UNBOUNDED | UNCOMMITTED | UNCONDITIONAL | UNIQUE | UNKNOWN | UNMATCHED |
UNTIL | UPDATE | URI | URLS | USE | USED | USER | UTF16 | UTF32 | UTF8
| VALIDATE | VALUE | VARIABLES | VARIATION | VERBOSE | VERSION | VIEW
@@ -1869,6 +1869,8 @@ SQL_DIALECT: 'SQL_DIALECT';
START: 'START';
STATS: 'STATS';
STOP: 'STOP';
+STREAM: 'STREAM';
+STREAMS: 'STREAMS';
SUBSCRIPTION: 'SUBSCRIPTION';
SUBSCRIPTIONS: 'SUBSCRIPTIONS';
SUBSET: 'SUBSET';