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

CalvinKirs 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 fd4cc9cc144 [fix](fe) Quote unsafe view comments in exported DDL 
(#67708)
fd4cc9cc144 is described below

commit fd4cc9cc144f30574e80089fc549c3e2becb6b2c
Author: morrySnow <[email protected]>
AuthorDate: Thu Sep 10 12:13:34 2026 +0800

    [fix](fe) Quote unsafe view comments in exported DDL (#67708)
    
    ## Problem
    
    `SHOW CREATE VIEW` inserted view comments directly between single
    quotes. A comment containing an apostrophe produced invalid,
    non-replayable DDL.
    
    ## Root cause
    
    Both view DDL construction paths appended the stored comment text
    without applying SQL string-literal escaping. For example, the comment
    `O'Reilly` was emitted as `COMMENT 'O'Reilly'`, where the apostrophe
    prematurely ended the literal.
    
    ## How to reproduce
    
    ```sql
    CREATE VIEW v COMMENT "O'Reilly" AS SELECT 1 AS c;
    SHOW CREATE VIEW v;
    ```
    
    Before this change, replaying the returned `CREATE VIEW` statement
    failed because its comment literal was malformed.
    
    ## Fix
    
    Centralize view-comment rendering in a shared helper used by both DDL
    generation paths. Comments containing apostrophes or backslashes are
    passed to `SqlUtils.quoteStringLiteral` with the active
    `NO_BACKSLASH_ESCAPES` mode, so the resulting literal is valid for the
    current SQL mode. Comments that require no escaping keep the existing
    single-quoted output format.
    
    The unit test exports a view whose comment contains an apostrophe,
    replays the exported DDL under a new view name, and verifies that the
    comment is preserved exactly.
    
    ## Tests
    
    - `./run-fe-ut.sh --run CreateViewTest`: 10 tests passed, 0 failures
    - `./build.sh --fe`: all 73 FE modules built successfully
    - Manual sandbox validation confirmed that `SHOW CREATE VIEW` emits
    `COMMENT "O'Reilly"` and the exported statement is replayable
---
 .../main/java/org/apache/doris/catalog/Env.java    | 22 ++++++++++++++++------
 .../org/apache/doris/catalog/CreateViewTest.java   | 21 +++++++++++++++++++++
 2 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
index e1c24c4b98d..c8a6210415d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
@@ -257,6 +257,7 @@ import org.apache.doris.qe.GlobalVariable;
 import org.apache.doris.qe.JournalObservable;
 import org.apache.doris.qe.QueryCancelWorker;
 import org.apache.doris.qe.SessionVariable;
+import org.apache.doris.qe.SqlModeHelper;
 import org.apache.doris.qe.StmtExecutor;
 import org.apache.doris.qe.VariableMgr;
 import org.apache.doris.resource.AdmissionControl;
@@ -4295,9 +4296,7 @@ public class Env {
             View view = (View) table;
 
             sb.append("CREATE VIEW `").append(table.getName()).append("`");
-            if (StringUtils.isNotBlank(table.getComment())) {
-                sb.append(" COMMENT '").append(table.getComment()).append("'");
-            }
+            addViewComment(table, sb);
             sb.append(" AS ").append(view.getInlineViewDef());
             createTableStmt.add(sb + ";");
             return;
@@ -4625,9 +4624,7 @@ public class Env {
             sb.append("CREATE VIEW `").append(table.getName()).append("`");
             addColNameAndComment(view, sb);
             sb.append("\n");
-            if (StringUtils.isNotBlank(table.getComment())) {
-                sb.append(" COMMENT '").append(table.getComment()).append("'");
-            }
+            addViewComment(table, sb);
             sb.append(" AS ").append(view.getInlineViewDef());
             createTableStmt.add(sb + ";");
             return;
@@ -7580,6 +7577,19 @@ public class Env {
         }
     }
 
+    private static void addViewComment(TableIf table, StringBuilder sb) {
+        if (StringUtils.isNotBlank(table.getComment())) {
+            String comment = table.getComment();
+            sb.append(" COMMENT ");
+            // Keep the historical output unchanged when the comment is 
already safe in single quotes.
+            if (comment.indexOf('\'') >= 0 || comment.indexOf('\\') >= 0) {
+                sb.append(SqlUtils.quoteStringLiteral(comment, 
SqlModeHelper.hasNoBackSlashEscapes()));
+            } else {
+                sb.append('\'').append(comment).append('\'');
+            }
+        }
+    }
+
     public int getFollowerCount() {
         int count = 0;
         for (Frontend fe : frontends.values()) {
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateViewTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateViewTest.java
index f3eacbb51c5..e40a33f6387 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateViewTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateViewTest.java
@@ -27,7 +27,9 @@ import org.apache.doris.utframe.TestWithFeService;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 
 public class CreateViewTest extends TestWithFeService {
 
@@ -125,6 +127,25 @@ public class CreateViewTest extends TestWithFeService {
         Assertions.assertNotNull(view8.getColumn("c_array"));
     }
 
+    @Test
+    public void testViewCommentDdlRoundTrip() throws Exception {
+        createView("create view test.view_comment_round_trip comment 
\"O'Reilly\" as select 1 as c");
+
+        Database db = 
Env.getCurrentInternalCatalog().getDbOrDdlException("test");
+        View originalView = (View) 
db.getTableOrDdlException("view_comment_round_trip");
+        List<String> createViewStmts = new ArrayList<>();
+        Env.getDdlStmt(originalView, createViewStmts, null, null, false, true, 
-1L);
+
+        String exportedDdl = createViewStmts.get(0);
+        Assertions.assertTrue(exportedDdl.contains(" COMMENT \"O'Reilly\""));
+        String copiedDdl = exportedDdl.replace("CREATE VIEW 
`view_comment_round_trip`",
+                "CREATE VIEW test.`view_comment_round_trip_copy`");
+        createView(copiedDdl);
+
+        View copiedView = (View) 
db.getTableOrDdlException("view_comment_round_trip_copy");
+        Assertions.assertEquals(originalView.getComment(), 
copiedView.getComment());
+    }
+
     @Test
     public void testNestedViews() throws Exception {
         ExceptionChecker.expectThrowsNoException(


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

Reply via email to