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

csun5285 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 886cb3ea48d [fix](struct) Preserve nested field comments in SHOW 
CREATE TABLE (#68307)
886cb3ea48d is described below

commit 886cb3ea48d7cf6cd3344edce0b1422ec5700634
Author: Chenyang Sun <[email protected]>
AuthorDate: Tue Oct 20 15:47:58 2026 +0800

    [fix](struct) Preserve nested field comments in SHOW CREATE TABLE (#68307)
    
    ### What problem does this PR solve?
    
    ```sql
    CREATE TABLE t (id INT, s STRUCT<a:INT COMMENT 'field doc'>)
    DUPLICATE KEY(id)
    DISTRIBUTED BY HASH(id) BUCKETS 1
    PROPERTIES ("replication_num" = "1");
    SHOW CREATE TABLE t;
    ```
    
    Before: `s` is shown as `struct<a:int>`.
    
    After: `s` is shown as `struct<a:int comment "field doc">`.
---
 .../main/java/org/apache/doris/catalog/Column.java |  2 +-
 .../java/org/apache/doris/catalog/TypeTest.java    | 38 +++++++++++++++
 .../ddl/test_struct_nested_comment_ddl.out         | 10 ++++
 .../ddl/test_struct_nested_comment_ddl.groovy      | 55 ++++++++++++++++++++++
 4 files changed, 104 insertions(+), 1 deletion(-)

diff --git a/fe/fe-catalog/src/main/java/org/apache/doris/catalog/Column.java 
b/fe/fe-catalog/src/main/java/org/apache/doris/catalog/Column.java
index 6272cfc0a3b..c4895ec5160 100644
--- a/fe/fe-catalog/src/main/java/org/apache/doris/catalog/Column.java
+++ b/fe/fe-catalog/src/main/java/org/apache/doris/catalog/Column.java
@@ -906,7 +906,7 @@ public class Column implements GsonPostProcessable {
 
         // show change datetimeV2/dateV2 to datetime/date
         if (isCompatible) {
-            sb.append(type.hideVersionForVersionColumn(true));
+            sb.append(type.hideVersionForVersionColumn(true, true));
         } else {
             sb.append(typeStr);
         }
diff --git a/fe/fe-core/src/test/java/org/apache/doris/catalog/TypeTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/catalog/TypeTest.java
index a4909a8aeed..7c66345fb6d 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/TypeTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/TypeTest.java
@@ -316,4 +316,42 @@ public class TypeTest {
         Assertions.assertFalse(dtv2s6.matchesType(timestampNs));
         Assertions.assertFalse(Type.matchExactType(timestampNs, 
wildcardDatetimeV2, false));
     }
+
+    // ===================== STRUCT nested comment in DDL =====================
+
+    /** SHOW CREATE TABLE has to print the comment of every nested field. */
+    @Test
+    public void testStructDdlKeepsNestedFieldComment() {
+        StructType structType = new StructType(
+                new StructField("a", Type.INT, null, true),
+                new StructField("b", Type.STRING, "field doc", true));
+        Column column = new Column("s", structType, false, null, true, null, 
"top-level");
+
+        Assertions.assertEquals(
+                "`s` struct<a:int,b:text comment \"field doc\"> NULL COMMENT 
\"top-level\"",
+                column.toSql(false, true));
+    }
+
+    /** A nested comment has to stay a readable literal, quotes and back 
slashes included. */
+    @Test
+    public void testStructDdlEscapesNestedFieldComment() {
+        StructType structType = new StructType(
+                new StructField("b", Type.STRING, "owner''s \\path and 
\"quotes\"", true));
+        Column column = new Column("s", structType, false, null, true, null, 
null);
+
+        Assertions.assertEquals(
+                "`s` struct<b:text comment \"owner''s \\\\path and 
\"\"quotes\"\"\"> NULL",
+                column.toSql(false, true));
+    }
+
+    /** Nested comments belong to DDL, but DESCRIBE only prints them when 
asked for. */
+    @Test
+    public void testStructDescribeHidesNestedCommentUnlessRequested() {
+        StructType structType = new StructType(
+                new StructField("b", Type.STRING, "field doc", true));
+        Assertions.assertEquals("struct<b:text>",
+                structType.hideVersionForVersionColumn(true, false));
+        Assertions.assertEquals("struct<b:text comment \"field doc\">",
+                structType.hideVersionForVersionColumn(true, true));
+    }
 }
diff --git 
a/regression-test/data/datatype_p0/nested_types/ddl/test_struct_nested_comment_ddl.out
 
b/regression-test/data/datatype_p0/nested_types/ddl/test_struct_nested_comment_ddl.out
new file mode 100644
index 00000000000..239892b5bf8
--- /dev/null
+++ 
b/regression-test/data/datatype_p0/nested_types/ddl/test_struct_nested_comment_ddl.out
@@ -0,0 +1,10 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !show_create --
+struct_nested_comment    `id` int NULL,\n  `s` struct<a:int,b:text comment 
"owner''s \\\\path",c:int> NULL COMMENT "top-level",\n  `n` 
struct<lvl1:struct<lvl2:int comment "deep doc">> NULL,\n  `arr` 
array<struct<inside:int comment "in array">> NULL
+
+-- !show_create_replay --
+struct_nested_comment_replay     `id` int NULL,\n  `s` struct<a:int,b:text 
comment "owner''s \\\\path",c:int> NULL COMMENT "top-level",\n  `n` 
struct<lvl1:struct<lvl2:int comment "deep doc">> NULL,\n  `arr` 
array<struct<inside:int comment "in array">> NULL
+
+-- !show_create_like --
+struct_nested_comment_like       `id` int NULL,\n  `s` struct<a:int,b:text 
comment "owner''s \\\\path",c:int> NULL COMMENT "top-level",\n  `n` 
struct<lvl1:struct<lvl2:int comment "deep doc">> NULL,\n  `arr` 
array<struct<inside:int comment "in array">> NULL
+
diff --git 
a/regression-test/suites/datatype_p0/nested_types/ddl/test_struct_nested_comment_ddl.groovy
 
b/regression-test/suites/datatype_p0/nested_types/ddl/test_struct_nested_comment_ddl.groovy
new file mode 100644
index 00000000000..035dcdf1c13
--- /dev/null
+++ 
b/regression-test/suites/datatype_p0/nested_types/ddl/test_struct_nested_comment_ddl.groovy
@@ -0,0 +1,55 @@
+// 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.
+
+suite("test_struct_nested_comment_ddl", "p0") {
+    sql "DROP TABLE IF EXISTS struct_nested_comment"
+    sql "DROP TABLE IF EXISTS struct_nested_comment_replay"
+    sql "DROP TABLE IF EXISTS struct_nested_comment_like"
+
+    // The comment on b carries a single quote and a back slash, both have to 
survive the DDL.
+    sql """
+        CREATE TABLE struct_nested_comment (
+            id INT,
+            s STRUCT<a:INT, b:TEXT COMMENT "owner''s \\\\path", c:INT> COMMENT 
"top-level",
+            n STRUCT<lvl1:STRUCT<lvl2:INT COMMENT "deep doc">>,
+            arr ARRAY<STRUCT<inside:INT COMMENT "in array">>
+        )
+        DUPLICATE KEY(id)
+        DISTRIBUTED BY HASH(id) BUCKETS 1
+        PROPERTIES ("replication_num" = "1")
+    """
+
+    // Only compare column definitions; table properties depend on the 
deployment and FE configuration.
+    def columnDefinitions = { row ->
+        def ddl = row[1].toString()
+        [row[0], ddl.substring(ddl.indexOf("(\n") + 2, ddl.indexOf("\n) 
ENGINE="))]
+    }
+
+    // SHOW CREATE TABLE used to drop every nested field comment.
+    quickRunTest("show_create", "SHOW CREATE TABLE struct_nested_comment", 
false, columnDefinitions)
+    def createStmt = (sql "SHOW CREATE TABLE 
struct_nested_comment")[0][1].toString()
+
+    // The printed DDL still has to parse back.
+    def replayStmt = createStmt.replace("`struct_nested_comment`", 
"`struct_nested_comment_replay`")
+    sql replayStmt
+    quickRunTest("show_create_replay", "SHOW CREATE TABLE 
struct_nested_comment_replay", false, columnDefinitions)
+
+    // CREATE TABLE LIKE re-parses the same generated DDL, so a dropped nested 
comment is
+    // gone from the new table for good, not just hidden from the user.
+    sql "CREATE TABLE struct_nested_comment_like LIKE struct_nested_comment"
+    quickRunTest("show_create_like", "SHOW CREATE TABLE 
struct_nested_comment_like", false, columnDefinitions)
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to