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

morningman pushed a commit to branch branch-1.2-lts
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-1.2-lts by this push:
     new 7f5173d627 [Fix](planner) fix incorrect nullable in ctas. (#22770)
7f5173d627 is described below

commit 7f5173d6277d0b46b0eddc710a0f5e27c535df3c
Author: mch_ucchi <[email protected]>
AuthorDate: Mon Aug 21 11:46:27 2023 +0800

    [Fix](planner) fix incorrect nullable in ctas. (#22770)
    
    ctas with outer join like
    ```sql
    create table a (
            id int not null,
            name varchar(20) not null
    )
    distributed by hash(id) buckets 4
    properties (
            "replication_num"="1"
    );
    
    create table b (
            id int not null,
            age int not null
    )
    distributed by hash(id) buckets 4
    properties (
            "replication_num"="1"
    );
    
    insert into a values(1, 'ww'), (2, 'zs');
    insert into b values(1, 22);
    
    create table c properties("replication_num"="1") as select a.id, a.name, 
b.age from a left join b on a.id = b.id;
    ```
    the column 'age' in c is not null, but nullable is expected, we fix it by 
use the nullable mode of the outputs of root plan fragment.
---
 .../doris/analysis/CreateTableAsSelectStmt.java    | 16 +++++++++++
 .../apache/doris/planner/SingleNodePlanner.java    |  2 +-
 regression-test/suites/ddl_p0/test_ctas.groovy     | 33 ++++++++++++++++++++++
 3 files changed, 50 insertions(+), 1 deletion(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableAsSelectStmt.java
 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableAsSelectStmt.java
index 45bdb4bdbb..d3a0f39a8c 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableAsSelectStmt.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableAsSelectStmt.java
@@ -20,7 +20,11 @@ package org.apache.doris.analysis;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.UserException;
+import org.apache.doris.planner.OriginalPlanner;
+import org.apache.doris.planner.PlanFragment;
+import org.apache.doris.qe.ConnectContext;
 
+import com.google.common.base.Preconditions;
 import lombok.Getter;
 
 import java.util.ArrayList;
@@ -66,6 +70,18 @@ public class CreateTableAsSelectStmt extends DdlStmt {
         QueryStmt tmpStmt = queryStmt.clone();
         tmpStmt.analyze(dummyRootAnalyzer);
         this.queryStmt = tmpStmt;
+        // to adjust the nullable of the result expression, we have to create 
plan fragment from the query stmt.
+        OriginalPlanner planner = new OriginalPlanner(dummyRootAnalyzer);
+        planner.createPlanFragments(queryStmt, dummyRootAnalyzer, 
ConnectContext.get().getSessionVariable().toThrift());
+        PlanFragment root = planner.getFragments().get(0);
+        List<Expr> outputs = root.getOutputExprs();
+        Preconditions.checkArgument(outputs.size() == 
queryStmt.getResultExprs().size());
+        for (int i = 0; i < outputs.size(); ++i) {
+            if (queryStmt.getResultExprs().get(i).getSrcSlotRef() != null) {
+                queryStmt.getResultExprs().get(i).getSrcSlotRef().getColumn()
+                        .setIsAllowNull(outputs.get(i).isNullable());
+            }
+        }
         ArrayList<Expr> resultExprs = getQueryStmt().getResultExprs();
         if (columnNames != null && columnNames.size() != resultExprs.size()) {
             
ErrorReport.reportAnalysisException(ErrorCode.ERR_COL_NUMBER_NOT_MATCH);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java 
b/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
index 31c7c4d162..8acd269f0d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
@@ -1053,7 +1053,7 @@ public class SingleNodePlanner {
                 // reset assigned conjuncts of analyzer in every compare
                 analyzer.setAssignedConjuncts(root.getAssignedConjuncts());
                 PlanNode candidate = createJoinNode(analyzer, root, 
rootPlanNodeOfCandidate, tblRefOfCandidate);
-                // (ML): 这里还需要吗?应该不会返回null吧
+                // it may not return null, but protect.
                 if (candidate == null) {
                     continue;
                 }
diff --git a/regression-test/suites/ddl_p0/test_ctas.groovy 
b/regression-test/suites/ddl_p0/test_ctas.groovy
index f18691efcf..b77a25829e 100644
--- a/regression-test/suites/ddl_p0/test_ctas.groovy
+++ b/regression-test/suites/ddl_p0/test_ctas.groovy
@@ -203,6 +203,39 @@ suite("test_ctas") {
             DROP TABLE IF EXISTS ctas_113815
         """
     }
+    
+    try {
+        sql '''create table a (
+                id int not null,
+                        name varchar(20) not null
+        )
+        distributed by hash(id) buckets 4
+        properties (
+                "replication_num"="1"
+        );
+        '''
+
+        sql '''create table b (
+                id int not null,
+                        age int not null
+        )
+        distributed by hash(id) buckets 4
+        properties (
+                "replication_num"="1"
+        );
+        '''
+
+        sql 'insert into a values(1, \'ww\'), (2, \'zs\');'
+        sql 'insert into b values(1, 22);'
 
+        sql 'create table c properties("replication_num"="1") as select a.id, 
a.name, b.age from a left join b on a.id = b.id;'
+        
+        String desc = sql 'desc c'
+        assertTrue(desc.contains('Yes'))
+    } finally {
+        sql 'drop table a'
+        sql 'drop table b'
+        sql 'drop table c'
+    }
 }
 


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

Reply via email to