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

Mryange 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 150157f1c29 [fix](be) Restore BOOLEAN support in linear_histogram 
(#68478)
150157f1c29 is described below

commit 150157f1c29b19682d6cec5bb44f190c62b869a5
Author: HappenLee <[email protected]>
AuthorDate: Wed Sep 30 14:51:21 2026 +0800

    [fix](be) Restore BOOLEAN support in linear_histogram (#68478)
    
    ### What problem does this PR solve?
    
    Issue Number: N/A
    
    Related PR: #54509, #56398
    
    `linear_histogram(boolean_column, 1.0)` passes FE analysis but fails on
    BE with `Agg Function linear_histogram(boolean, double) is not
    implemented`. The factory refactor in #54509 omitted the existing
    BOOLEAN case from the new type list.
    
    Restore BOOLEAN in the shared creator list, covering both the
    two-argument and offset variants. Reuse the existing histogram
    implementation and nullable adapter. Add BOOLEAN unit tests for empty
    inputs, bucket results, state serialization and merging, plus SQL
    regression coverage for nullable/non-nullable inputs, grouping,
    empty/all-null input and invalid bucket parameters.
    
    ### Release note
    
    Fix BOOLEAN inputs to `linear_histogram` failing with a
    function-not-implemented error.
    
    ### Check List (For Author)
    
    - Test:
    - [x] Regression test: `test_linear_histogram_boolean` on a local FE/BE
    ASAN build; generated output and result comparison.
    - [x] Unit Test: `./run-be-ut.sh -j 48 --run
    --filter=AggLinearHistogramTest.*` on ASAN; all 3 tests passed.
    - Behavior changed:
        - [x] Yes. Restore the previously supported BOOLEAN input type.
    - Does this need documentation?
        - [x] No. This restores existing behavior.
    
    Validation also includes BE/FE builds, header hygiene, formatting and
    `git diff --check`.
    Clang-tidy was attempted with the build compilation database; the
    baseline `be/src/core/types.h` contains an unmatched
    `NOLINTEND(readability-function-size)` directive, preventing a clean
    run.
    
    ### Check List (For Reviewer who merge this PR)
    
    - [ ] Confirm the release note
    - [ ] Confirm test cases
    - [ ] Confirm document
    - [ ] Add branch pick label
---
 .../aggregate_function_linear_histogram.cpp        |  7 +--
 .../exprs/aggregate/agg_linear_histogram_test.cpp  | 31 ++++++++++-
 .../test_linear_histogram_boolean.out              | 17 ++++++
 .../test_linear_histogram_boolean.groovy           | 63 ++++++++++++++++++++++
 4 files changed, 114 insertions(+), 4 deletions(-)

diff --git a/be/src/exprs/aggregate/aggregate_function_linear_histogram.cpp 
b/be/src/exprs/aggregate/aggregate_function_linear_histogram.cpp
index 3f14e238a22..8bfb9d3de96 100644
--- a/be/src/exprs/aggregate/aggregate_function_linear_histogram.cpp
+++ b/be/src/exprs/aggregate/aggregate_function_linear_histogram.cpp
@@ -34,9 +34,10 @@ AggregateFunctionPtr 
create_aggregate_function_linear_histogram(const std::strin
                                                                 const 
DataTypePtr& result_type,
                                                                 const bool 
result_is_nullable,
                                                                 const 
AggregateFunctionAttr& attr) {
-    using creator = creator_with_type_list<TYPE_TINYINT, TYPE_SMALLINT, 
TYPE_INT, TYPE_BIGINT,
-                                           TYPE_LARGEINT, TYPE_FLOAT, 
TYPE_DOUBLE, TYPE_DECIMAL32,
-                                           TYPE_DECIMAL64, TYPE_DECIMAL128I, 
TYPE_DECIMAL256>;
+    using creator =
+            creator_with_type_list<TYPE_BOOLEAN, TYPE_TINYINT, TYPE_SMALLINT, 
TYPE_INT, TYPE_BIGINT,
+                                   TYPE_LARGEINT, TYPE_FLOAT, TYPE_DOUBLE, 
TYPE_DECIMAL32,
+                                   TYPE_DECIMAL64, TYPE_DECIMAL128I, 
TYPE_DECIMAL256>;
     bool has_offset = (argument_types.size() == 3);
     if (has_offset) {
         return creator::create<HistogramWithInputParam, 
AggregateFunctionLinearHistogramData>(
diff --git a/be/test/exprs/aggregate/agg_linear_histogram_test.cpp 
b/be/test/exprs/aggregate/agg_linear_histogram_test.cpp
index 456868b0b52..5064150d660 100644
--- a/be/test/exprs/aggregate/agg_linear_histogram_test.cpp
+++ b/be/test/exprs/aggregate/agg_linear_histogram_test.cpp
@@ -206,7 +206,7 @@ public:
         AggregateFunctionSimpleFactory factory = 
AggregateFunctionSimpleFactory::instance();
         auto agg_function = factory.get("linear_histogram", data_types, 
nullptr, false, -1,
                                         {.column_names = {""}});
-        EXPECT_NE(agg_function, nullptr);
+        ASSERT_NE(agg_function, nullptr);
 
         std::unique_ptr<char[]> memory(new char[agg_function->size_of_data()]);
         AggregateDataPtr place = memory.get();
@@ -256,6 +256,28 @@ public:
             EXPECT_EQ(result2, expect_empty_result);
         }
 
+        if (input_rows == 2 && interval == 1 && offset == 0) {
+            EXPECT_EQ(result1,
+                      "{\"num_buckets\":2,\"buckets\":["
+                      
"{\"lower\":0.0,\"upper\":1.0,\"count\":2,\"acc_count\":2},"
+                      
"{\"lower\":1.0,\"upper\":2.0,\"count\":2,\"acc_count\":4}]}");
+            EXPECT_EQ(result2,
+                      "{\"num_buckets\":2,\"buckets\":["
+                      
"{\"lower\":0.0,\"upper\":1.0,\"count\":1,\"acc_count\":1},"
+                      
"{\"lower\":1.0,\"upper\":2.0,\"count\":1,\"acc_count\":2}]}");
+        }
+
+        if (input_rows == 2 && interval == 1 && offset == 0.5) {
+            EXPECT_EQ(result1,
+                      "{\"num_buckets\":2,\"buckets\":["
+                      
"{\"lower\":-0.5,\"upper\":0.5,\"count\":2,\"acc_count\":2},"
+                      
"{\"lower\":0.5,\"upper\":1.5,\"count\":2,\"acc_count\":4}]}");
+            EXPECT_EQ(result2,
+                      "{\"num_buckets\":2,\"buckets\":["
+                      
"{\"lower\":-0.5,\"upper\":0.5,\"count\":1,\"acc_count\":1},"
+                      
"{\"lower\":0.5,\"upper\":1.5,\"count\":1,\"acc_count\":2}]}");
+        }
+
         // test with data
         if (input_rows == 100 && interval == 10 && offset == 0) {
             std::string expect_result1 = s1;
@@ -290,6 +312,13 @@ private:
     Arena _agg_arena_pool;
 };
 
+TEST_F(AggLinearHistogramTest, test_boolean) {
+    test_agg_linear_histogram<DataTypeBool>(0, 1, 0);
+    test_agg_linear_histogram<DataTypeBool>(0, 1, 0.5);
+    test_agg_linear_histogram<DataTypeBool>(2, 1, 0);
+    test_agg_linear_histogram<DataTypeBool>(2, 1, 0.5);
+}
+
 TEST_F(AggLinearHistogramTest, test_empty) {
     test_agg_linear_histogram<DataTypeInt8>(0, 10, 0);
     test_agg_linear_histogram<DataTypeInt16>(0, 10, 0);
diff --git 
a/regression-test/data/query_p0/sql_functions/aggregate_functions/test_linear_histogram_boolean.out
 
b/regression-test/data/query_p0/sql_functions/aggregate_functions/test_linear_histogram_boolean.out
new file mode 100644
index 00000000000..b005daccc5e
--- /dev/null
+++ 
b/regression-test/data/query_p0/sql_functions/aggregate_functions/test_linear_histogram_boolean.out
@@ -0,0 +1,17 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !nullable --
+{"num_buckets":2,"buckets":[{"lower":0.0,"upper":1.0,"count":1,"acc_count":1},{"lower":1.0,"upper":2.0,"count":2,"acc_count":3}]}
      
{"num_buckets":2,"buckets":[{"lower":-0.5,"upper":0.5,"count":1,"acc_count":1},{"lower":0.5,"upper":1.5,"count":2,"acc_count":3}]}
+
+-- !not_nullable --
+{"num_buckets":2,"buckets":[{"lower":0.0,"upper":1.0,"count":2,"acc_count":2},{"lower":1.0,"upper":2.0,"count":2,"acc_count":4}]}
      
{"num_buckets":2,"buckets":[{"lower":-0.5,"upper":0.5,"count":2,"acc_count":2},{"lower":0.5,"upper":1.5,"count":2,"acc_count":4}]}
+
+-- !grouped --
+0      
{"num_buckets":1,"buckets":[{"lower":0.0,"upper":1.0,"count":1,"acc_count":1}]} 
{"num_buckets":1,"buckets":[{"lower":-0.5,"upper":0.5,"count":1,"acc_count":1}]}
+1      
{"num_buckets":1,"buckets":[{"lower":1.0,"upper":2.0,"count":2,"acc_count":2}]} 
{"num_buckets":1,"buckets":[{"lower":0.5,"upper":1.5,"count":2,"acc_count":2}]}
+
+-- !all_null --
+{"num_buckets":0,"buckets":[]} {"num_buckets":0,"buckets":[]}
+
+-- !empty --
+{"num_buckets":0,"buckets":[]} {"num_buckets":0,"buckets":[]}
+
diff --git 
a/regression-test/suites/query_p0/sql_functions/aggregate_functions/test_linear_histogram_boolean.groovy
 
b/regression-test/suites/query_p0/sql_functions/aggregate_functions/test_linear_histogram_boolean.groovy
new file mode 100644
index 00000000000..99a936b33e4
--- /dev/null
+++ 
b/regression-test/suites/query_p0/sql_functions/aggregate_functions/test_linear_histogram_boolean.groovy
@@ -0,0 +1,63 @@
+// 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_linear_histogram_boolean") {
+    sql "DROP TABLE IF EXISTS linear_histogram_boolean"
+    sql """
+        CREATE TABLE linear_histogram_boolean (
+            id INT NOT NULL,
+            b BOOLEAN NULL,
+            non_null_b BOOLEAN NOT NULL
+        )
+        DISTRIBUTED BY HASH(id) BUCKETS 3
+        PROPERTIES ("replication_num" = "1")
+    """
+    sql """
+        INSERT INTO linear_histogram_boolean VALUES
+            (1, TRUE, TRUE), (2, FALSE, FALSE), (3, TRUE, TRUE), (4, NULL, 
FALSE)
+    """
+
+    order_qt_nullable """
+        SELECT linear_histogram(b, 1.0), linear_histogram(b, 1.0, 0.5)
+        FROM linear_histogram_boolean
+    """
+    order_qt_not_nullable """
+        SELECT linear_histogram(non_null_b, 1.0), linear_histogram(non_null_b, 
1.0, 0.5)
+        FROM linear_histogram_boolean
+    """
+    order_qt_grouped """
+        SELECT id % 2, linear_histogram(b, 1.0), linear_histogram(b, 1.0, 0.5)
+        FROM linear_histogram_boolean GROUP BY id % 2
+    """
+    order_qt_all_null """
+        SELECT linear_histogram(b, 1.0), linear_histogram(b, 1.0, 0.5)
+        FROM linear_histogram_boolean WHERE b IS NULL
+    """
+    order_qt_empty """
+        SELECT linear_histogram(b, 1.0), linear_histogram(b, 1.0, 0.5)
+        FROM linear_histogram_boolean WHERE id < 0
+    """
+
+    test {
+        sql "SELECT linear_histogram(non_null_b, 0.0) FROM 
linear_histogram_boolean"
+        exception "interval should be larger than 0"
+    }
+    test {
+        sql "SELECT linear_histogram(non_null_b, 1.0, 1.0) FROM 
linear_histogram_boolean"
+        exception "offset should be in [0, interval)"
+    }
+}


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

Reply via email to