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

Gabriel39 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 a22aca4f6cf [fix](be) Normalize Iceberg Parquet decimal manifest 
bounds (#68548)
a22aca4f6cf is described below

commit a22aca4f6cf73ae78ad1aa7e1354b7c232e21b37
Author: Gabriel <[email protected]>
AuthorDate: Tue Sep 29 09:37:33 2026 +0800

    [fix](be) Normalize Iceberg Parquet decimal manifest bounds (#68548)
    
    ### What problem does this PR solve?
    
    Iceberg Parquet writes copy the encoded Parquet decimal min/max
    statistics directly into manifest bounds. For example, the unscaled
    value 128 can be written as `00000080` instead of `0080`. These padded
    bounds do not follow [Iceberg's single-value
    
serialization](https://iceberg.apache.org/spec/#appendix-d-single-value-serialization),
    which requires the minimal signed big-endian representation.
    
    Normalize DECIMAL bounds after merging row-group statistics. Preserve
    the necessary sign byte and convert integer physical representations
    from little endian. Other logical types retain their existing encoding.
    
    Add writer unit coverage for precisions 1–38 and sign boundaries, an
    Iceberg write regression for DECIMAL32/64/128 metadata and filtered
    reads, and refresh the existing Parquet statistics expectations.
    
    ### Release note
    
    Fix Iceberg Parquet DECIMAL manifest bounds to use the minimal signed
    big-endian encoding required by the Iceberg specification.
    
    Validation: clang-format 16, clang-tidy, and build hygiene checks passed
    after rebasing. C++ compilation completed, but the local writer
    unit-test executable could not link: the upstream CDC test now
    references `posix_spawn_file_actions_addclose`, which pulls in toolchain
    glibc compatibility definitions that conflict with Doris definitions. No
    unit tests executed in this post-rebase attempt. On the original PR
    commit, the ASAN BE/FE build, all 4 writer unit tests, and both Iceberg
    regression suites passed; the new unit test failed with the original
    implementation and passed with the fix.
    
    ### Check List (For Author)
    
    - Test:
    - [x] Regression test: `test_iceberg_write_decimal_bounds`,
    `test_iceberg_write_stats2`
      - [x] Unit Test: `VParquetWriterTest.*`
    - Behavior changed:
    - [x] Yes. Newly written Parquet DECIMAL bounds omit redundant
    sign-extension bytes while preserving their values.
    - Does this need documentation?
      - [x] No.
    
    ### Check List (For Reviewer who merge this PR)
    
    - [ ] Confirm the release note
    - [ ] Confirm test cases
    - [ ] Confirm document
    - [ ] Add branch pick label
---
 .../format/transformer/viceberg_parquet_writer.cpp | 30 +++++++-
 .../format/transformer/vparquet_writer_test.cpp    | 76 +++++++++++++++++++
 .../write/test_iceberg_write_decimal_bounds.out    | 55 ++++++++++++++
 .../iceberg/write/test_iceberg_write_stats2.out    |  6 +-
 .../write/test_iceberg_write_decimal_bounds.groovy | 88 ++++++++++++++++++++++
 5 files changed, 250 insertions(+), 5 deletions(-)

diff --git a/be/src/format/transformer/viceberg_parquet_writer.cpp 
b/be/src/format/transformer/viceberg_parquet_writer.cpp
index 10fde7aece3..57f329014d0 100644
--- a/be/src/format/transformer/viceberg_parquet_writer.cpp
+++ b/be/src/format/transformer/viceberg_parquet_writer.cpp
@@ -20,12 +20,38 @@
 #include <parquet/api/reader.h>
 #include <parquet/schema.h>
 
+#include <algorithm>
+
 #include "format/table/iceberg/iceberg_arrow_block_convertor.h"
 #include "format/table/parquet_utils.h"
 #include "runtime/runtime_state.h"
 
 namespace doris {
 
+static std::string encode_iceberg_bound(const ::parquet::Statistics& stats, 
std::string encoded) {
+    if (!stats.descr()->logical_type()->is_decimal()) {
+        return encoded;
+    }
+    // Parquet integer statistics are little-endian, while binary decimals 
already use big-endian.
+    // Iceberg bounds require the unscaled value's shortest signed big-endian 
representation.
+    if (stats.physical_type() == ::parquet::Type::INT32 ||
+        stats.physical_type() == ::parquet::Type::INT64) {
+        std::reverse(encoded.begin(), encoded.end());
+    }
+    size_t start = 0;
+    while (start + 1 < encoded.size()) {
+        const auto byte = static_cast<uint8_t>(encoded[start]);
+        const bool next_is_negative = (static_cast<uint8_t>(encoded[start + 
1]) & 0x80) != 0;
+        if ((byte == 0 && !next_is_negative) || (byte == 0xff && 
next_is_negative)) {
+            ++start;
+        } else {
+            break;
+        }
+    }
+    encoded.erase(0, start);
+    return encoded;
+}
+
 VIcebergParquetWriter::VIcebergParquetWriter(RuntimeState* state, 
io::FileWriter* file_writer,
                                              const VExprContextSPtrs& 
output_vexpr_ctxs,
                                              std::vector<std::string> 
column_names,
@@ -90,8 +116,8 @@ Status 
VIcebergParquetWriter::collect_file_statistics_after_close(TIcebergColumn
         }
         if (column_stat->HasMinMax()) {
             has_any_min_max = true;
-            lower_bounds[field_id] = column_stat->EncodeMin();
-            upper_bounds[field_id] = column_stat->EncodeMax();
+            lower_bounds[field_id] = encode_iceberg_bound(*column_stat, 
column_stat->EncodeMin());
+            upper_bounds[field_id] = encode_iceberg_bound(*column_stat, 
column_stat->EncodeMax());
         }
     }
 
diff --git a/be/test/format/transformer/vparquet_writer_test.cpp 
b/be/test/format/transformer/vparquet_writer_test.cpp
index f5a5b10c2b9..e7b446630f3 100644
--- a/be/test/format/transformer/vparquet_writer_test.cpp
+++ b/be/test/format/transformer/vparquet_writer_test.cpp
@@ -24,13 +24,16 @@
 #include <parquet/arrow/reader.h>
 #include <parquet/schema.h>
 
+#include <algorithm>
 #include <optional>
 #include <string_view>
 
 #include "core/block/block.h"
 #include "core/column/column_array.h"
+#include "core/column/column_decimal.h"
 #include "core/column/column_nullable.h"
 #include "core/data_type/data_type_array.h"
+#include "core/data_type/data_type_decimal.h"
 #include "core/data_type/data_type_factory.hpp"
 #include "core/data_type/data_type_nullable.h"
 #include "core/data_type/data_type_number.h"
@@ -64,6 +67,62 @@ protected:
         static_cast<void>(_fs->delete_file(_file_path));
     }
 
+    void check_decimal_bounds(int64_t unscaled, const std::string& expected) {
+        const int min_precision = unscaled > -10 && unscaled < 10 ? 1 : 3;
+        DataTypes types;
+        std::vector<std::string> names;
+        std::string json = R"({"type":"struct","fields":[)";
+        Block block;
+        for (int precision = min_precision; precision <= 38; ++precision) {
+            const auto name = "d" + std::to_string(precision);
+            const int scale = std::min(precision, 2);
+            auto type = make_nullable(create_decimal(precision, scale, false));
+            auto column = type->create_column();
+            if (precision <= 9) {
+                
column->insert(Field::create_field<TYPE_DECIMAL32>(Decimal32(unscaled)));
+            } else if (precision <= 18) {
+                
column->insert(Field::create_field<TYPE_DECIMAL64>(Decimal64(unscaled)));
+            } else {
+                
column->insert(Field::create_field<TYPE_DECIMAL128I>(Decimal128V3(unscaled)));
+            }
+            column->insert_default();
+            block.insert({std::move(column), type, name});
+            types.push_back(type);
+            names.push_back(name);
+            if (precision != min_precision) {
+                json += ",";
+            }
+            json += "{\"id\":" + std::to_string(precision) + ",\"name\":\"" + 
name +
+                    "\",\"required\":false,\"type\":\"decimal(" + 
std::to_string(precision) + "," +
+                    std::to_string(scale) + ")\"}";
+        }
+        json += "]}";
+        auto schema = iceberg::SchemaParser::from_json(json);
+        auto output_exprs = MockSlotRef::create_mock_contexts(types);
+        io::FileWriterPtr file_writer;
+        ASSERT_TRUE(_fs->create_file(_file_path, &file_writer).ok());
+        RuntimeState state;
+        state.set_timezone("UTC");
+        ParquetFileOptions options {.compression_type = 
TParquetCompressionType::UNCOMPRESSED,
+                                    .parquet_version = 
TParquetVersion::PARQUET_1_0,
+                                    .parquet_disable_dictionary = false,
+                                    .enable_int96_timestamps = false};
+        VIcebergParquetWriter writer(&state, file_writer.get(), output_exprs, 
names, false, options,
+                                     &json, *schema);
+        ASSERT_TRUE(writer.open().ok());
+        ASSERT_TRUE(writer.write(block).ok());
+        ASSERT_TRUE(writer.close().ok());
+        TIcebergColumnStats stats;
+        ASSERT_TRUE(writer.collect_file_statistics_after_close(&stats).ok());
+        for (int precision = min_precision; precision <= 38; ++precision) {
+            SCOPED_TRACE("precision=" + std::to_string(precision));
+            EXPECT_EQ(expected, stats.lower_bounds.at(precision));
+            EXPECT_EQ(expected, stats.upper_bounds.at(precision));
+            EXPECT_EQ(2, stats.value_counts.at(precision));
+            EXPECT_EQ(1, stats.null_value_counts.at(precision));
+        }
+    }
+
     arrow::MemoryPool* _previous_pool = nullptr;
     std::string _file_path;
     std::shared_ptr<io::FileSystem> _fs;
@@ -105,6 +164,23 @@ TEST_F(VParquetWriterTest, 
WritesIcebergPrimitiveAndCollectsMetrics) {
     EXPECT_EQ(std::string("\x03\x00\x00\x00", 4), stats.upper_bounds.at(7));
 }
 
+TEST_F(VParquetWriterTest, IcebergDecimalBoundsUseMinimalSignedBytes) {
+    for (const auto& [unscaled, expected] :
+         std::vector<std::pair<int64_t, std::string>> {{0, std::string("\x00", 
1)},
+                                                       {1, std::string("\x01", 
1)},
+                                                       {127, 
std::string("\x7f", 1)},
+                                                       {128, 
std::string("\x00\x80", 2)},
+                                                       {255, 
std::string("\x00\xff", 2)},
+                                                       {256, 
std::string("\x01\x00", 2)},
+                                                       {-1, 
std::string("\xff", 1)},
+                                                       {-128, 
std::string("\x80", 1)},
+                                                       {-129, 
std::string("\xff\x7f", 2)},
+                                                       {-256, 
std::string("\xff\x00", 2)}}) {
+        SCOPED_TRACE("unscaled=" + std::to_string(unscaled));
+        check_decimal_bounds(unscaled, expected);
+    }
+}
+
 // NOLINTNEXTLINE(readability-function-cognitive-complexity): keep schema and 
value assertions together.
 TEST_F(VParquetWriterTest, WritesInt64TimestampSemantics) {
     DataTypes types 
{DataTypeFactory::instance().create_data_type(TYPE_DATETIMEV2, false, 0, 6),
diff --git 
a/regression-test/data/external_table_p0/iceberg/write/test_iceberg_write_decimal_bounds.out
 
b/regression-test/data/external_table_p0/iceberg/write/test_iceberg_write_decimal_bounds.out
new file mode 100644
index 00000000000..1b7b03ea0a9
--- /dev/null
+++ 
b/regression-test/data/external_table_p0/iceberg/write/test_iceberg_write_decimal_bounds.out
@@ -0,0 +1,55 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !bounds --
+0      1       00      00      00      00      00      00
+1      1       01      01      01      01      01      01
+2      1       7F      7F      7F      7F      7F      7F
+3      1       0080    0080    0080    0080    0080    0080
+4      1       00FF    00FF    00FF    00FF    00FF    00FF
+5      1       0100    0100    0100    0100    0100    0100
+6      1       FF      FF      FF      FF      FF      FF
+7      1       80      80      80      80      80      80
+8      1       FF7F    FF7F    FF7F    FF7F    FF7F    FF7F
+9      1       FF00    FF00    FF00    FF00    FF00    FF00
+10     1       8000    8000    8000    8000    8000    8000
+11     1       FF7FFF  FF7FFF  FF7FFF  FF7FFF  FF7FFF  FF7FFF
+12     1       \N      \N      \N      \N      \N      \N
+13     1       3B9AC9FF        3B9AC9FF        0DE0B6B3A763FFFF        
0DE0B6B3A763FFFF        4B3B4CA85A86C47A098A223FFFFFFFFF        
4B3B4CA85A86C47A098A223FFFFFFFFF
+14     1       C4653601        C4653601        F21F494C589C0001        
F21F494C589C0001        B4C4B357A5793B85F675DDC000000001        
B4C4B357A5793B85F675DDC000000001
+15     2       FF      0080    FF      0080    FF      0080
+
+-- !values --
+0      0.00    0.00    0.00
+1      0.01    0.01    0.01
+2      1.27    1.27    1.27
+3      1.28    1.28    1.28
+4      2.55    2.55    2.55
+5      2.56    2.56    2.56
+6      -0.01   -0.01   -0.01
+7      -1.28   -1.28   -1.28
+8      -1.29   -1.29   -1.29
+9      -2.56   -2.56   -2.56
+10     -327.68 -327.68 -327.68
+11     -327.69 -327.69 -327.69
+12     \N      \N      \N
+13     9999999.99      9999999999999999.99     
999999999999999999999999999999999999.99
+14     -9999999.99     -9999999999999999.99    
-999999999999999999999999999999999999.99
+15     -0.01   -0.01   -0.01
+15     1.28    1.28    1.28
+
+-- !negative --
+6      -0.01   -0.01   -0.01
+7      -1.28   -1.28   -1.28
+8      -1.29   -1.29   -1.29
+9      -2.56   -2.56   -2.56
+10     -327.68 -327.68 -327.68
+11     -327.69 -327.69 -327.69
+14     -9999999.99     -9999999999999999.99    
-999999999999999999999999999999999999.99
+15     -0.01   -0.01   -0.01
+
+-- !positive --
+3      1.28    1.28    1.28
+4      2.55    2.55    2.55
+5      2.56    2.56    2.56
+13     9999999.99      9999999999999999.99     
999999999999999999999999999999999999.99
+15     1.28    1.28    1.28
+
diff --git 
a/regression-test/data/external_table_p0/iceberg/write/test_iceberg_write_stats2.out
 
b/regression-test/data/external_table_p0/iceberg/write/test_iceberg_write_stats2.out
index 0094b0f105f..56233ea9861 100644
--- 
a/regression-test/data/external_table_p0/iceberg/write/test_iceberg_write_stats2.out
+++ 
b/regression-test/data/external_table_p0/iceberg/write/test_iceberg_write_stats2.out
@@ -4,7 +4,7 @@ false   22      222     2.2     2.2     2222    8765.4321       
8765.432100     987654321098765432.987654321099
 true   11      111     1.1     1.1     1111    1234.5678       1234.567890     
123456789012345678.123456789012 aaa     2023-01-01      2023-01-01T12:34:56
 
 -- !sql_1 --
-0      PARQUET 2       {1:2, 2:2, 3:2, 4:2, 5:2, 6:2, 7:2, 8:2, 9:2, 10:2, 
11:2, 12:2} {1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0} 
{1:0x00, 2:0x0B000000, 3:0x6F00000000000000, 4:0xCDCC8C3F, 
5:0x9A9999999999F13F, 6:0x00000457, 7:0x00BC614E, 8:0x00000000499602D2, 
9:0x000000018EE90FF6C373E0393713FA14, 10:0x616161, 11:0x9E4B0000, 
12:0x005CE70F33F10500}     {1:0x01, 2:0x16000000, 3:0xDE00000000000000, 
4:0xCDCC0C40, 5:0x9A99999999990140, 6:0x000008AE, 7:0x05397FB1, 
8:0x000000020A75E124, 9 [...]
+0      PARQUET 2       {1:2, 2:2, 3:2, 4:2, 5:2, 6:2, 7:2, 8:2, 9:2, 10:2, 
11:2, 12:2} {1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0} 
{1:0x00, 2:0x0B000000, 3:0x6F00000000000000, 4:0xCDCC8C3F, 
5:0x9A9999999999F13F, 6:0x0457, 7:0x00BC614E, 8:0x499602D2, 
9:0x018EE90FF6C373E0393713FA14, 10:0x616161, 11:0x9E4B0000, 
12:0x005CE70F33F10500}       {1:0x01, 2:0x16000000, 3:0xDE00000000000000, 
4:0xCDCC0C40, 5:0x9A99999999990140, 6:0x08AE, 7:0x05397FB1, 8:0x020A75E124, 
9:0x0C7748819DFFB62505316873C [...]
 
 -- !sql_2 --
 {"bigint_col":{"column_size":74, "value_count":2, "null_value_count":0, 
"nan_value_count":null, "lower_bound":111, "upper_bound":222}, 
"boolean_col":{"column_size":33, "value_count":2, "null_value_count":0, 
"nan_value_count":null, "lower_bound":0, "upper_bound":1}, 
"date_col":{"column_size":66, "value_count":2, "null_value_count":0, 
"nan_value_count":null, "lower_bound":"2023-01-01", 
"upper_bound":"2023-06-15"}, "datetime_col1":{"column_size":74, 
"value_count":2, "null_value_count":0, "n [...]
@@ -20,13 +20,13 @@ true        11      111     1.1     1.1     1111    
1234.5678       1234.567890     123456789012345678.123456789012 a
 {"bigint_col":{"column_size":null, "value_count":2, "null_value_count":null, 
"nan_value_count":null, "lower_bound":111, "upper_bound":222}, 
"boolean_col":{"column_size":null, "value_count":2, "null_value_count":null, 
"nan_value_count":null, "lower_bound":0, "upper_bound":1}, 
"date_col":{"column_size":null, "value_count":2, "null_value_count":null, 
"nan_value_count":null, "lower_bound":"2023-01-01", 
"upper_bound":"2023-06-15"}, "datetime_col1":{"column_size":null, 
"value_count":2, "null_v [...]
 
 -- !sql_6 --
-{1:0x00, 2:0x0B000000, 3:0x6F00000000000000, 4:0xCDCC8C3F, 
5:0x9A9999999999F13F, 6:0x00000457, 7:0x00BC614E, 8:0x00000000499602D2, 
9:0x000000018EE90FF6C373E0393713FA14, 10:0x616161, 11:0x9E4B0000, 
12:0x005CE70F33F10500}
+{1:0x00, 2:0x0B000000, 3:0x6F00000000000000, 4:0xCDCC8C3F, 
5:0x9A9999999999F13F, 6:0x0457, 7:0x00BC614E, 8:0x499602D2, 
9:0x018EE90FF6C373E0393713FA14, 10:0x616161, 11:0x9E4B0000, 
12:0x005CE70F33F10500}
 
 -- !sql_7 --
 {1:0x00, 2:0x0B00000000000000, 3:0x6F00000000000000, 4:0xCDCC8C3F, 
5:0x9A9999999999F13F, 6:0x0457, 7:0x00BC614E, 8:0x075BCD15, 
9:0x018EE90FF6C373E0393713FA14, 10:0x616161, 11:0x9E4B0000, 
12:0x005CE70F33F10500}
 
 -- !sql_8 --
-{1:0x01, 2:0x16000000, 3:0xDE00000000000000, 4:0xCDCC0C40, 
5:0x9A99999999990140, 6:0x000008AE, 7:0x05397FB1, 8:0x000000020A75E124, 
9:0x0000000C7748819DFFB62505316873CB, 10:0x626262, 11:0x434C0000, 
12:0x40D91FA833FE0500}
+{1:0x01, 2:0x16000000, 3:0xDE00000000000000, 4:0xCDCC0C40, 
5:0x9A99999999990140, 6:0x08AE, 7:0x05397FB1, 8:0x020A75E124, 
9:0x0C7748819DFFB62505316873CB, 10:0x626262, 11:0x434C0000, 
12:0x40D91FA833FE0500}
 
 -- !sql_9 --
 {1:0x01, 2:0x1600000000000000, 3:0xDE00000000000000, 4:0xCDCC0C40, 
5:0x9A99999999990140, 6:0x08AE, 7:0x05397FB1, 8:0x05397FB1, 
9:0x0C7748819DFFB62505316873CB, 10:0x626262, 11:0x434C0000, 
12:0x40D91FA833FE0500}
diff --git 
a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_decimal_bounds.groovy
 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_decimal_bounds.groovy
new file mode 100644
index 00000000000..2b45de13ad6
--- /dev/null
+++ 
b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_decimal_bounds.groovy
@@ -0,0 +1,88 @@
+// 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_iceberg_write_decimal_bounds", "p0,external,iceberg") {
+    if 
(!context.config.otherConfigs.get("enableIcebergTest")?.equalsIgnoreCase("true"))
 {
+        logger.info("disable iceberg test.")
+        return
+    }
+
+    String catalogName = "test_iceberg_write_decimal_bounds"
+    String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
+    String restPort = context.config.otherConfigs.get("iceberg_rest_uri_port")
+    String minioPort = context.config.otherConfigs.get("iceberg_minio_port")
+    sql "DROP CATALOG IF EXISTS ${catalogName}"
+    sql """
+        CREATE CATALOG ${catalogName} PROPERTIES (
+            "type" = "iceberg",
+            "iceberg.catalog.type" = "rest",
+            "uri" = "http://${externalEnvIp}:${restPort}";,
+            "s3.access_key" = "admin",
+            "s3.secret_key" = "password",
+            "s3.endpoint" = "http://${externalEnvIp}:${minioPort}";,
+            "s3.region" = "us-east-1",
+            "enable.mapping.varbinary" = "true"
+        )
+    """
+    sql "SWITCH ${catalogName}"
+    sql "CREATE DATABASE IF NOT EXISTS test_decimal_bounds"
+    sql "USE test_decimal_bounds"
+    sql "DROP TABLE IF EXISTS decimal_bounds"
+    sql """
+        CREATE TABLE decimal_bounds (
+            case_id INT,
+            d32 DECIMAL(9,2),
+            d64 DECIMAL(18,2),
+            d128 DECIMAL(38,2)
+        )
+        PARTITION BY LIST (case_id) ()
+        PROPERTIES ("write-format" = "parquet")
+    """
+    // Separate partitions expose every sign boundary as a manifest bound, not 
just a data value.
+    sql """
+        INSERT INTO decimal_bounds VALUES
+            (0, 0.00, 0.00, 0.00),
+            (1, 0.01, 0.01, 0.01),
+            (2, 1.27, 1.27, 1.27),
+            (3, 1.28, 1.28, 1.28),
+            (4, 2.55, 2.55, 2.55),
+            (5, 2.56, 2.56, 2.56),
+            (6, -0.01, -0.01, -0.01),
+            (7, -1.28, -1.28, -1.28),
+            (8, -1.29, -1.29, -1.29),
+            (9, -2.56, -2.56, -2.56),
+            (10, -327.68, -327.68, -327.68),
+            (11, -327.69, -327.69, -327.69),
+            (12, NULL, NULL, NULL),
+            (13, 9999999.99, 9999999999999999.99, 
999999999999999999999999999999999999.99),
+            (14, -9999999.99, -9999999999999999.99, 
-999999999999999999999999999999999999.99),
+            (15, -0.01, -0.01, -0.01),
+            (15, 1.28, 1.28, 1.28)
+    """
+    // Reading the data alone would not detect redundant sign-extension bytes 
in metadata.
+    qt_bounds """
+        SELECT `partition`.case_id, record_count,
+               from_hex(lower_bounds[2]), from_hex(upper_bounds[2]),
+               from_hex(lower_bounds[3]), from_hex(upper_bounds[3]),
+               from_hex(lower_bounds[4]), from_hex(upper_bounds[4])
+        FROM decimal_bounds\$files
+        ORDER BY `partition`.case_id
+    """
+    qt_values "SELECT * FROM decimal_bounds ORDER BY case_id, d32"
+    qt_negative "SELECT * FROM decimal_bounds WHERE d128 < 0 ORDER BY case_id, 
d32"
+    qt_positive "SELECT * FROM decimal_bounds WHERE d32 >= 1.28 ORDER BY 
case_id, d32"
+}


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

Reply via email to