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

jt2594838 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 ad1bd47951f Fix tree path quoting in SHOW CREATE VIEW (#18911)
ad1bd47951f is described below

commit ad1bd47951f76ff5d3c174b10aaf3f5b8a89c8c9
Author: Caideyipi <[email protected]>
AuthorDate: Mon Oct 19 14:16:21 2026 +0800

    Fix tree path quoting in SHOW CREATE VIEW (#18911)
---
 .../iotdb/relational/it/schema/IoTDBTableIT.java   | 56 ++++++++++++-
 .../metadata/relational/ShowCreateViewTask.java    |  3 +-
 .../relational/ShowCreateViewTaskTest.java         | 91 ++++++++++++++++++++++
 3 files changed, 147 insertions(+), 3 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java
index 25f4cdc66cf..f7a5bc4581c 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java
@@ -912,6 +912,58 @@ public class IoTDBTableIT {
     }
   }
 
+  @Test
+  public void testShowCreateViewPreservesQuotedTreePath() throws Exception {
+    final String[][] pathNodes = {
+      {"`a``b`", "\"`a``b`\""},
+      {"`a b`", "\"`a b`\""},
+      {"`a\"b`", "\"`a\"\"b`\""}
+    };
+    try (final Connection connection = EnvFactory.getEnv().getConnection();
+        final Statement statement = connection.createStatement()) {
+      statement.execute("CREATE DATABASE root.show_create_view_source");
+      for (int i = 0; i < pathNodes.length; i++) {
+        final String device = "root.show_create_view_source." + 
pathNodes[i][0] + ".d1";
+        statement.execute("CREATE TIMESERIES " + device + ".s1 INT32");
+        statement.execute("INSERT INTO " + device + "(time,s1) VALUES (1," + 
(10 + i) + ")");
+      }
+      statement.execute("CREATE TIMESERIES 
root.show_create_view_source.ab.d1.s1 INT32");
+      statement.execute("INSERT INTO 
root.show_create_view_source.ab.d1(time,s1) VALUES (1,999)");
+    }
+
+    try (final Connection connection =
+            EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        final Statement statement = connection.createStatement()) {
+      statement.execute("CREATE DATABASE show_create_view_db");
+      statement.execute("USE show_create_view_db");
+      for (int i = 0; i < pathNodes.length; i++) {
+        final String viewName = "v" + i;
+        final String prefixPath = "root.\"show_create_view_source\"." + 
pathNodes[i][1] + ".**";
+        statement.execute(
+            "CREATE VIEW "
+                + viewName
+                + " (device STRING TAG, value INT32 FIELD FROM s1) AS "
+                + prefixPath);
+        for (final String command : new String[] {"SHOW CREATE VIEW ", "SHOW 
CREATE TABLE "}) {
+          final String createSql;
+          try (final ResultSet resultSet = statement.executeQuery(command + 
viewName)) {
+            assertTrue(resultSet.next());
+            assertEquals(viewName, resultSet.getString(1));
+            createSql = resultSet.getString(2);
+            assertTrue(createSql.endsWith(" AS " + prefixPath));
+            assertFalse(resultSet.next());
+          }
+          statement.execute("DROP VIEW " + viewName);
+          statement.execute(createSql);
+          TestUtils.assertResultSetEqual(
+              statement.executeQuery("SELECT value FROM " + viewName + " ORDER 
BY time"),
+              "value,",
+              Collections.singleton((10 + i) + ","));
+        }
+      }
+    }
+  }
+
   @Test
   public void testTreeViewTable() throws Exception {
     try (final Connection connection = EnvFactory.getEnv().getConnection();
@@ -1219,14 +1271,14 @@ public class IoTDBTableIT {
           statement.executeQuery("show create view view_table"),
           "View,Create View,",
           Collections.singleton(
-              "view_table,CREATE VIEW \"view_table\" (\"time\" TIMESTAMP 
TIME,\"tag1\" STRING TAG,\"tag2\" STRING TAG,\"s11\" INT32 FIELD,\"s3\" STRING 
FIELD FROM \"s2\") RESTRICT WITH (ttl=100) AS root.\"重庆\".\"1\".**,"));
+              "view_table,CREATE VIEW \"view_table\" (\"time\" TIMESTAMP 
TIME,\"tag1\" STRING TAG,\"tag2\" STRING TAG,\"s11\" INT32 FIELD,\"s3\" STRING 
FIELD FROM \"s2\") RESTRICT WITH (ttl=100) AS root.\"重庆\".\"`1`\".**,"));
 
       // Can also use "show create table"
       TestUtils.assertResultSetEqual(
           statement.executeQuery("show create table view_table"),
           "View,Create View,",
           Collections.singleton(
-              "view_table,CREATE VIEW \"view_table\" (\"time\" TIMESTAMP 
TIME,\"tag1\" STRING TAG,\"tag2\" STRING TAG,\"s11\" INT32 FIELD,\"s3\" STRING 
FIELD FROM \"s2\") RESTRICT WITH (ttl=100) AS root.\"重庆\".\"1\".**,"));
+              "view_table,CREATE VIEW \"view_table\" (\"time\" TIMESTAMP 
TIME,\"tag1\" STRING TAG,\"tag2\" STRING TAG,\"s11\" INT32 FIELD,\"s3\" STRING 
FIELD FROM \"s2\") RESTRICT WITH (ttl=100) AS root.\"重庆\".\"`1`\".**,"));
 
       statement.execute("create table a ()");
       try {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateViewTask.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateViewTask.java
index d46f3e7774d..a616282e7c4 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateViewTask.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateViewTask.java
@@ -154,7 +154,8 @@ public class ShowCreateViewTask extends AbstractTableTask {
     final String[] pathNodes = 
TreeViewSchema.getPrefixPattern(table).getNodes();
     builder.append(pathNodes[0]);
     for (int i = 1; i < pathNodes.length - 1; ++i) {
-      builder.append(".\"").append(pathNodes[i].replace("`", "")).append("\"");
+      // Preserve tree-model quoting inside the table-model identifier for 
round-trip parsing.
+      builder.append(".").append(getIdentifier(pathNodes[i]));
     }
     builder.append(".").append(pathNodes[pathNodes.length - 1]);
 
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateViewTaskTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateViewTaskTest.java
new file mode 100644
index 00000000000..9ea96d4a448
--- /dev/null
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowCreateViewTaskTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.execution.config.metadata.relational;
+
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.schema.table.TreeViewSchema;
+import org.apache.iotdb.commons.schema.table.TsTable;
+import org.apache.iotdb.commons.schema.table.column.FieldColumnSchema;
+import org.apache.iotdb.commons.schema.table.column.TagColumnSchema;
+import org.apache.iotdb.commons.schema.table.column.TimeColumnSchema;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateView;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.parser.SqlParser;
+
+import org.apache.tsfile.enums.TSDataType;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.time.ZoneId;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+@RunWith(Parameterized.class)
+public class ShowCreateViewTaskTest {
+
+  @Parameterized.Parameters(name = "{0}")
+  public static Collection<Object[]> paths() {
+    return Arrays.asList(
+        new Object[][] {
+          {"root.demo_tick.ab.**", "root.\"demo_tick\".\"ab\".**"},
+          {"root.demo_tick.`a``b`.**", "root.\"demo_tick\".\"`a``b`\".**"},
+          {"root.`demo``tick`.`a````b`.**", 
"root.\"`demo``tick`\".\"`a````b`\".**"},
+          {"root.demo_tick.`a b`.**", "root.\"demo_tick\".\"`a b`\".**"},
+          {"root.demo_tick.`a.b`.**", "root.\"demo_tick\".\"`a.b`\".**"},
+          {"root.demo_tick.`a\"b`.**", "root.\"demo_tick\".\"`a\"\"b`\".**"},
+          {"root.demo_tick.`a``\"b`.**", 
"root.\"demo_tick\".\"`a``\"\"b`\".**"},
+          {"root.demo_tick.`*`.**", "root.\"demo_tick\".\"`*`\".**"},
+          {"root.demo_tick.`1`.**", "root.\"demo_tick\".\"`1`\".**"}
+        });
+  }
+
+  private final String treePath;
+  private final String sqlPath;
+
+  public ShowCreateViewTaskTest(final String treePath, final String sqlPath) {
+    this.treePath = treePath;
+    this.sqlPath = sqlPath;
+  }
+
+  @Test
+  public void testShowCreateViewPreservesPrefixPath() throws Exception {
+    final PartialPath prefixPath = new PartialPath(treePath);
+    final TsTable table = new TsTable("v");
+    table.addColumnSchema(new TimeColumnSchema("time", TSDataType.TIMESTAMP));
+    table.addColumnSchema(new TagColumnSchema("device", TSDataType.STRING));
+    final FieldColumnSchema field = new FieldColumnSchema("value", 
TSDataType.INT32);
+    TreeViewSchema.setOriginalName(field, "s1");
+    table.addColumnSchema(field);
+    assertNull(TreeViewSchema.setPathPattern(table, prefixPath));
+
+    final String sql = ShowCreateViewTask.getShowCreateViewSQL(table);
+    assertEquals(
+        "CREATE VIEW \"v\" (\"time\" TIMESTAMP TIME,\"device\" STRING TAG,"
+            + "\"value\" INT32 FIELD FROM \"s1\") WITH (ttl='INF') AS "
+            + sqlPath,
+        sql);
+    final CreateView recreatedView =
+        (CreateView) new SqlParser().createStatement(sql, 
ZoneId.systemDefault(), null);
+    assertEquals(prefixPath, recreatedView.getPrefixPath());
+  }
+}

Reply via email to