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

yiguolei pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-2.0 by this push:
     new c6d80452bac [refactor](mysql result format) use new serde framework to 
tuple conv… (#25526)
c6d80452bac is described below

commit c6d80452bac9acdd7913c1a308dcde658376428c
Author: zhiqiang <seuhezhiqi...@163.com>
AuthorDate: Wed Oct 18 00:10:50 2023 -0500

    [refactor](mysql result format) use new serde framework to tuple conv… 
(#25526)
    
    * [refactor](mysql result format) use new serde framework to tuple convert 
(#25006)
    
    * fix compile
    
    * Update mysql_tupleconvert.groovy
    
    ---------
    
    Co-authored-by: yiguolei <676222...@qq.com>
---
 be/cmake/thirdparty.cmake                          |  4 ++
 be/src/gutil/CMakeLists.txt                        |  2 +
 be/src/gutil/strings/numbers.cc                    | 13 ++++-
 be/src/gutil/strings/numbers.h                     |  4 +-
 be/src/runtime/runtime_state.h                     |  4 ++
 be/src/util/mysql_row_buffer.cpp                   | 10 ++--
 be/src/util/mysql_row_buffer.h                     |  4 ++
 be/src/vec/sink/vmysql_result_writer.cpp           |  3 ++
 be/src/vec/sink/vmysql_result_writer.h             |  2 +
 be/test/util/mysql_row_buffer_test.cpp             | 58 ++++++++++++++++++++++
 .../main/java/org/apache/doris/qe/Coordinator.java |  5 ++
 .../java/org/apache/doris/qe/SessionVariable.java  | 11 ++++
 gensrc/thrift/PaloInternalService.thrift           |  4 +-
 .../mysql_tupleconvert_p0/mysql_tupleconvert.out   | 10 ++++
 .../mysql_tupleconvert.groovy                      | 40 +++++++++++++++
 15 files changed, 164 insertions(+), 10 deletions(-)

diff --git a/be/cmake/thirdparty.cmake b/be/cmake/thirdparty.cmake
index bcb04cdf290..e8ea8c33308 100644
--- a/be/cmake/thirdparty.cmake
+++ b/be/cmake/thirdparty.cmake
@@ -283,6 +283,10 @@ set_target_properties(k5crypto PROPERTIES 
IMPORTED_LOCATION ${THIRDPARTY_DIR}/li
 add_library(gssapi_krb5 STATIC IMPORTED)
 set_target_properties(gssapi_krb5 PROPERTIES IMPORTED_LOCATION 
${THIRDPARTY_DIR}/lib/libgssapi_krb5.a)
 
+add_library(dragonbox_to_chars STATIC IMPORTED)
+set_target_properties(dragonbox_to_chars PROPERTIES IMPORTED_LOCATION 
${THIRDPARTY_DIR}/lib/libdragonbox_to_chars.a)
+target_include_directories(dragonbox_to_chars INTERFACE 
${THIRDPARTY_DIR}/include/dragonbox-1.1.3)
+
 find_program(THRIFT_COMPILER thrift ${CMAKE_SOURCE_DIR}/bin)
 
 if (OS_MACOSX)
diff --git a/be/src/gutil/CMakeLists.txt b/be/src/gutil/CMakeLists.txt
index bac9aec3037..12c2330884f 100644
--- a/be/src/gutil/CMakeLists.txt
+++ b/be/src/gutil/CMakeLists.txt
@@ -57,6 +57,8 @@ add_library(Gutil STATIC ${SOURCE_FILES})
 
 set_target_properties(Gutil PROPERTIES COMPILE_FLAGS "-funsigned-char 
-Wno-deprecated")
 target_compile_options(Gutil PRIVATE -Wno-char-subscripts 
-Wno-implicit-fallthrough)
+target_link_libraries(Gutil PRIVATE dragonbox_to_chars)
+
 # target_link_libraries(Gutil glog protobuf rt)
 
 #set(GUTIL_LIBS
diff --git a/be/src/gutil/strings/numbers.cc b/be/src/gutil/strings/numbers.cc
index 5550757d403..9aea10155f3 100644
--- a/be/src/gutil/strings/numbers.cc
+++ b/be/src/gutil/strings/numbers.cc
@@ -27,6 +27,7 @@ using std::string;
 #include "common/logging.h"
 #include <fmt/format.h>
 
+#include "dragonbox/dragonbox_to_chars.h"
 #include "gutil/gscoped_ptr.h"
 #include "gutil/int128.h"
 #include "gutil/integral_types.h"
@@ -1274,7 +1275,11 @@ int FloatToBuffer(float value, int width, char* buffer) {
     return snprintf_result;
 }
 
-int FastDoubleToBuffer(double value, char* buffer) {
+int FastDoubleToBuffer(double value, char* buffer, bool faster_float_convert) {
+    if (faster_float_convert) {
+        return jkj::dragonbox::to_chars_n(value, buffer) - buffer;
+    }
+ 
     auto end = fmt::format_to(buffer, "{:.15g}", value);
     *end = '\0';
     if (strtod(buffer, nullptr) != value) {
@@ -1283,7 +1288,11 @@ int FastDoubleToBuffer(double value, char* buffer) {
     return end - buffer;
 }
 
-int FastFloatToBuffer(float value, char* buffer) {
+int FastFloatToBuffer(float value, char* buffer, bool faster_float_convert) {
+    if (faster_float_convert) {
+        return jkj::dragonbox::to_chars_n(value, buffer) - buffer;
+    }
+
     auto end = fmt::format_to(buffer, "{:.6g}", value);
     *end = '\0';
 #ifdef _MSC_VER // has no strtof()
diff --git a/be/src/gutil/strings/numbers.h b/be/src/gutil/strings/numbers.h
index 8e2478794a0..e7c6f938267 100644
--- a/be/src/gutil/strings/numbers.h
+++ b/be/src/gutil/strings/numbers.h
@@ -443,8 +443,8 @@ int FloatToBuffer(float i, int width, char* buffer);
 char* DoubleToBuffer(double i, char* buffer);
 char* FloatToBuffer(float i, char* buffer);
 
-int FastDoubleToBuffer(double i, char* buffer);
-int FastFloatToBuffer(float i, char* buffer);
+int FastDoubleToBuffer(double i, char* buffer, bool faster_float_convert = 
false);
+int FastFloatToBuffer(float i, char* buffer, bool faster_float_convert = 
false);
 // In practice, doubles should never need more than 24 bytes and floats
 // should never need more than 14 (including null terminators), but we
 // overestimate to be safe.
diff --git a/be/src/runtime/runtime_state.h b/be/src/runtime/runtime_state.h
index 8c2d32b05a4..3c4ebb9feed 100644
--- a/be/src/runtime/runtime_state.h
+++ b/be/src/runtime/runtime_state.h
@@ -146,6 +146,10 @@ public:
         return _process_status;
     }
 
+    bool enable_faster_float_convert() const {
+        return _query_options.__isset.faster_float_convert && 
_query_options.faster_float_convert;
+    }
+
     // Appends error to the _error_log if there is space
     bool log_error(const std::string& error);
 
diff --git a/be/src/util/mysql_row_buffer.cpp b/be/src/util/mysql_row_buffer.cpp
index 00193481b71..e671ba2d012 100644
--- a/be/src/util/mysql_row_buffer.cpp
+++ b/be/src/util/mysql_row_buffer.cpp
@@ -174,12 +174,12 @@ static char* add_largeint(int128_t data, char* pos, bool 
dynamic_mode) {
 }
 
 template <typename T>
-char* add_float(T data, char* pos, bool dynamic_mode) {
+char* add_float(T data, char* pos, bool dynamic_mode, bool 
faster_float_convert = false) {
     int length = 0;
     if constexpr (std::is_same_v<T, float>) {
-        length = FastFloatToBuffer(data, pos + !dynamic_mode);
+        length = FastFloatToBuffer(data, pos + !dynamic_mode, 
faster_float_convert);
     } else if constexpr (std::is_same_v<T, double>) {
-        length = FastDoubleToBuffer(data, pos + !dynamic_mode);
+        length = FastDoubleToBuffer(data, pos + !dynamic_mode, 
faster_float_convert);
     }
     if (!dynamic_mode) {
         int1store(pos++, length);
@@ -385,7 +385,7 @@ int MysqlRowBuffer<is_binary_format>::push_float(float 
data) {
         return ret;
     }
 
-    _pos = add_float(data, _pos, _dynamic_mode);
+    _pos = add_float(data, _pos, _dynamic_mode, _faster_float_convert);
     return 0;
 }
 
@@ -405,7 +405,7 @@ int MysqlRowBuffer<is_binary_format>::push_double(double 
data) {
         return ret;
     }
 
-    _pos = add_float(data, _pos, _dynamic_mode);
+    _pos = add_float(data, _pos, _dynamic_mode, _faster_float_convert);
     return 0;
 }
 
diff --git a/be/src/util/mysql_row_buffer.h b/be/src/util/mysql_row_buffer.h
index 6a6c2b0ad0c..eec21feeadb 100644
--- a/be/src/util/mysql_row_buffer.h
+++ b/be/src/util/mysql_row_buffer.h
@@ -124,6 +124,8 @@ public:
      */
     void close_dynamic_mode();
 
+    void set_faster_float_convert(bool faster) { _faster_float_convert = 
faster; }
+
 private:
     int reserve(int64_t size);
 
@@ -142,6 +144,8 @@ private:
     uint64_t _len_pos;
     uint32_t _field_pos = 0;
     uint32_t _field_count = 0;
+
+    bool _faster_float_convert = false;
 };
 
 } // namespace doris
diff --git a/be/src/vec/sink/vmysql_result_writer.cpp 
b/be/src/vec/sink/vmysql_result_writer.cpp
index f1094673b0f..75d8606a3e8 100644
--- a/be/src/vec/sink/vmysql_result_writer.cpp
+++ b/be/src/vec/sink/vmysql_result_writer.cpp
@@ -90,6 +90,8 @@ Status 
VMysqlResultWriter<is_binary_format>::init(RuntimeState* state) {
     }
     set_output_object_data(state->return_object_data_as_binary());
     _is_dry_run = state->query_options().dry_run_query;
+    _enable_faster_float_convert = state->enable_faster_float_convert();
+
     return Status::OK();
 }
 
@@ -619,6 +621,7 @@ Status 
VMysqlResultWriter<is_binary_format>::append_block(Block& input_block) {
     {
         SCOPED_TIMER(_convert_tuple_timer);
         MysqlRowBuffer<is_binary_format> row_buffer;
+        row_buffer.set_faster_float_convert(_enable_faster_float_convert);
         if constexpr (is_binary_format) {
             row_buffer.start_binary_row(_output_vexpr_ctxs.size());
         }
diff --git a/be/src/vec/sink/vmysql_result_writer.h 
b/be/src/vec/sink/vmysql_result_writer.h
index b1954f2b019..1761a1a3bef 100644
--- a/be/src/vec/sink/vmysql_result_writer.h
+++ b/be/src/vec/sink/vmysql_result_writer.h
@@ -89,6 +89,8 @@ private:
     bool _is_dry_run = false;
 
     uint64_t _bytes_sent = 0;
+
+    bool _enable_faster_float_convert = false;
 };
 } // namespace vectorized
 } // namespace doris
diff --git a/be/test/util/mysql_row_buffer_test.cpp 
b/be/test/util/mysql_row_buffer_test.cpp
index cfe012fdcd5..3e2380b6c11 100644
--- a/be/test/util/mysql_row_buffer_test.cpp
+++ b/be/test/util/mysql_row_buffer_test.cpp
@@ -118,4 +118,62 @@ TEST(MysqlRowBufferTest, dynamic_mode) {
     EXPECT_EQ(0, strncmp(buf + 43, "test", 4));
 }
 
+TEST(MysqlRowBufferTest /*unused*/, faster_float_convert /*unused*/) {
+    MysqlRowBuffer mrb;
+    mrb.set_faster_float_convert(true);
+
+    mrb.push_float(0);
+    mrb.push_float(1.0);
+    mrb.push_float(-1.0);
+    mrb.push_float(56.45);
+    mrb.push_double(10.12);
+
+    const char* buf = mrb.buf();
+
+    // mem: size-data-size-data
+    // 3-'0E0'-3-'1E0'-4-'-1E0'-7-'5.645E1'-7-'1.012E1'
+    // 1b-3b---1b-3b---1b-4b----1b-7b-------1b-7b------
+    // 0  1    4  5    8  9     13 14       21 22
+
+    EXPECT_EQ(29, mrb.length());
+
+    EXPECT_EQ(3, *((int8_t*)(buf + 0)));
+    EXPECT_EQ(0, strncmp(buf + 1, "0E0", 3));
+
+    EXPECT_EQ(3, *((int8_t*)(buf + 4)));
+    EXPECT_EQ(0, strncmp(buf + 5, "1E0", 3));
+
+    EXPECT_EQ(4, *((int8_t*)(buf + 8)));
+    EXPECT_EQ(0, strncmp(buf + 9, "-1E0", 4));
+
+    EXPECT_EQ(7, *((int8_t*)(buf + 13)));
+    EXPECT_EQ(0, strncmp(buf + 14, "5.645E1", 7));
+
+    EXPECT_EQ(7, *((int8_t*)(buf + 21)));
+    EXPECT_EQ(0, strncmp(buf + 22, "1.012E1", 7));
+}
+
+TEST(MysqlRowBufferTest /*unused*/, faster_float_convert_dynamic /*unused*/) {
+    MysqlRowBuffer mrb;
+    mrb.set_faster_float_convert(true);
+    mrb.open_dynamic_mode();
+
+    mrb.push_float(0);
+    mrb.push_float(1.0);
+    mrb.push_float(-1.0);
+    mrb.push_float(56.45);
+    mrb.push_double(10.12);
+
+    const char* buf = mrb.buf();
+
+    EXPECT_EQ(33, mrb.length());
+    EXPECT_EQ(254, *((uint8_t*)(buf)));
+
+    EXPECT_EQ(0, strncmp(buf + 9, "0E0", 3));
+    EXPECT_EQ(0, strncmp(buf + 12, "1E0", 3));
+    EXPECT_EQ(0, strncmp(buf + 15, "-1E0", 4));
+    EXPECT_EQ(0, strncmp(buf + 19, "5.645E1", 7));
+    EXPECT_EQ(0, strncmp(buf + 26, "1.012E1", 7));
+}
+
 } // namespace doris
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/Coordinator.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/Coordinator.java
index 49afb6e6851..4ad725ae663 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/Coordinator.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/Coordinator.java
@@ -241,6 +241,8 @@ public class Coordinator implements CoordInterface {
 
     private boolean enablePipelineEngine = false;
 
+    private boolean fasterFloatConvert = false;
+
     // Runtime filter merge instance address and ID
     public TNetworkAddress runtimeFilterMergeAddr;
     public TUniqueId runtimeFilterMergeInstanceId;
@@ -291,6 +293,9 @@ public class Coordinator implements CoordInterface {
         // Only enable pipeline query engine in query, not load
         this.enablePipelineEngine = 
context.getSessionVariable().getEnablePipelineEngine()
                 && (fragments.size() > 0 && fragments.get(0).getSink() 
instanceof ResultSink);
+
+        this.fasterFloatConvert = 
context.getSessionVariable().fasterFloatConvert();
+
         initQueryOptions(context);
 
         setFromUserProperty(context);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
index f01e67a5107..65fbbf46026 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
@@ -408,6 +408,8 @@ public class SessionVariable implements Serializable, 
Writable {
 
     public static final String ENABLE_FULL_AUTO_ANALYZE = 
"enable_full_auto_analyze";
 
+    public static final String FASTER_FLOAT_CONVERT = "faster_float_convert";
+
     public static final List<String> DEBUG_VARIABLES = ImmutableList.of(
             SKIP_DELETE_PREDICATE,
             SKIP_DELETE_BITMAP,
@@ -1168,6 +1170,9 @@ public class SessionVariable implements Serializable, 
Writable {
             flag = VariableMgr.GLOBAL)
     public String fullAutoAnalyzeEndTime = "02:00:00";
 
+    @VariableMgr.VarAttr(name = FASTER_FLOAT_CONVERT,
+            description = {"是否启用更快的浮点数转换算法,注意会影响输出格式", "Set true to enable 
faster float pointer number convert"})
+    public boolean fasterFloatConvert = false;
 
     // If this fe is in fuzzy mode, then will use initFuzzyModeVariables to 
generate some variables,
     // not the default value set in the code.
@@ -2272,6 +2277,8 @@ public class SessionVariable implements Serializable, 
Writable {
 
         
tResult.setInvertedIndexConjunctionOptThreshold(invertedIndexConjunctionOptThreshold);
 
+        tResult.setFasterFloatConvert(fasterFloatConvert);
+
         return tResult;
     }
 
@@ -2580,6 +2587,10 @@ public class SessionVariable implements Serializable, 
Writable {
         return connectContext.getSessionVariable().enableAggState;
     }
 
+    public boolean fasterFloatConvert() {
+        return this.fasterFloatConvert;
+    }
+  
     public void checkAnalyzeTimeFormat(String time) {
         try {
             DateTimeFormatter timeFormatter = 
DateTimeFormatter.ofPattern("HH:mm:ss");
diff --git a/gensrc/thrift/PaloInternalService.thrift 
b/gensrc/thrift/PaloInternalService.thrift
index 818bc538b20..62eb5a0827b 100644
--- a/gensrc/thrift/PaloInternalService.thrift
+++ b/gensrc/thrift/PaloInternalService.thrift
@@ -246,7 +246,9 @@ struct TQueryOptions {
   // use is_report_success any more
   84: optional bool enable_profile = false;
   85: optional bool enable_page_cache = false;
-  86: optional i32 analyze_timeout = 43200
+  86: optional i32 analyze_timeout = 43200;
+
+  87: optional bool faster_float_convert = false;
 }
 
 
diff --git a/regression-test/data/mysql_tupleconvert_p0/mysql_tupleconvert.out 
b/regression-test/data/mysql_tupleconvert_p0/mysql_tupleconvert.out
new file mode 100644
index 00000000000..c27a9d00b53
--- /dev/null
+++ b/regression-test/data/mysql_tupleconvert_p0/mysql_tupleconvert.out
@@ -0,0 +1,10 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !select --
+1      0.33    3.1415925       [0.33, 0.67]    [3.1415926, 0.878787878]
+
+-- !select --
+1      0.33    3.1415925       [3.3E-1, 6.7E-1]        [3.1415926E0, 
8.78787878E-1]
+
+-- !select --
+1      0.33    3.1415925       [0.33, 0.67]    [3.1415926, 0.878787878]
+2      0.33    3.1415925       [0.33, 0.67]    [3.1415926, 0.878787878]
diff --git 
a/regression-test/suites/mysql_tupleconvert_p0/mysql_tupleconvert.groovy 
b/regression-test/suites/mysql_tupleconvert_p0/mysql_tupleconvert.groovy
new file mode 100644
index 00000000000..68dcd74f9d7
--- /dev/null
+++ b/regression-test/suites/mysql_tupleconvert_p0/mysql_tupleconvert.groovy
@@ -0,0 +1,40 @@
+// 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("mysql_tuple_convert_test") {
+    
+    testTable = "doule_faster_convert_test"
+    sql "DROP TABLE IF EXISTS ${testTable}"
+    sql """
+        CREATE TABLE IF NOT EXISTS ${testTable} (
+            `col_0` INT,
+            `col_1` DOUBLE,
+            `col_2` FLOAT,
+            `col_3` ARRAY<FLOAT>,
+            `col_4` ARRAY<DOUBLE>)
+        ENGINE=OLAP DUPLICATE KEY(`col_0`) DISTRIBUTED BY HASH(`col_0`) 
BUCKETS 1
+        PROPERTIES("replication_num" = "1");
+    """
+    sql """INSERT INTO ${testTable} VALUES (1, 0.33, 3.1415926, [0.33, 0.67], 
[3.1415926, 0.878787878]);"""
+    qt_select """SELECT /*+SET_VAR(faster_float_convert=false)*/ * FROM 
${testTable};"""
+    qt_select """SELECT /*+SET_VAR(faster_float_convert=true)*/ * FROM 
${testTable};"""
+    // make sure we can convert number from string to value
+    sql """INSERT INTO ${testTable} SELECT 2, col_1, col_2, col_3, col_4 from 
${testTable} where col_0 = 1;"""
+    qt_select """SELECT * FROM ${testTable} ORDER BY col_0;"""
+    sql """SET faster_float_convert=false;"""
+    sql "DROP TABLE IF EXISTS ${testTable}"
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to