diff --git a/be/src/core/data_type_serde/data_type_serde.cpp b/be/src/core/data_type_serde/data_type_serde.cpp index 16526bc172b213..4dafca97aa3433 100644 --- a/be/src/core/data_type_serde/data_type_serde.cpp +++ b/be/src/core/data_type_serde/data_type_serde.cpp @@ -474,6 +474,24 @@ int64_t find_struct_child_index(const ::orc::Type& type, const std::string& fiel return -1; } +struct RoundedOrcTimestamp { + int64_t seconds; + uint64_t microseconds; +}; + +RoundedOrcTimestamp round_orc_timestamp_to_microseconds(int64_t seconds, int64_t nanoseconds) { + constexpr int64_t NANOS_PER_SECOND = 1000000000; + constexpr int64_t NANOS_PER_MICROSECOND = 1000; + constexpr int64_t MICROS_PER_SECOND = 1000000; + DORIS_CHECK(nanoseconds >= 0 && nanoseconds < NANOS_PER_SECOND); + // Doris stores six fractional digits, so use half-up rounding and carry 999999500ns into the + // next second instead of silently truncating the ORC value. + const auto rounded_microseconds = + (nanoseconds + NANOS_PER_MICROSECOND / 2) / NANOS_PER_MICROSECOND; + return {.seconds = seconds + rounded_microseconds / MICROS_PER_SECOND, + .microseconds = cast_set(rounded_microseconds % MICROS_PER_SECOND)}; +} + Status decode_timestamp_orc_values(IColumn& nested_column, const OrcDecodedColumnView& orc_view, const cctz::time_zone& timezone) { const auto* orc_batch = dynamic_cast(orc_view.batch); @@ -493,8 +511,10 @@ Status decode_timestamp_orc_values(IColumn& nested_column, const OrcDecodedColum } auto& value = reinterpret_cast&>(data[old_data_size + row]); - value.from_unixtime(orc_batch->data[source_row], timezone); - value.set_microsecond(cast_set(orc_batch->nanoseconds[source_row] / 1000)); + const auto timestamp = round_orc_timestamp_to_microseconds( + orc_batch->data[source_row], orc_batch->nanoseconds[source_row]); + value.from_unixtime(timestamp.seconds, timezone); + value.set_microsecond(timestamp.microseconds); } return Status::OK(); } @@ -518,8 +538,10 @@ Status decode_timestamp_tz_orc_values(IColumn& nested_column, continue; } auto& value = data[old_data_size + row]; - value.from_unixtime(orc_batch->data[source_row], utc_time_zone); - value.set_microsecond(cast_set(orc_batch->nanoseconds[source_row] / 1000)); + const auto timestamp = round_orc_timestamp_to_microseconds( + orc_batch->data[source_row], orc_batch->nanoseconds[source_row]); + value.from_unixtime(timestamp.seconds, utc_time_zone); + value.set_microsecond(timestamp.microseconds); } return Status::OK(); } diff --git a/be/src/format_v2/orc/orc_reader.cpp b/be/src/format_v2/orc/orc_reader.cpp index 9a2aeb538977dc..88462abbcdd03f 100644 --- a/be/src/format_v2/orc/orc_reader.cpp +++ b/be/src/format_v2/orc/orc_reader.cpp @@ -500,7 +500,15 @@ DateV2Value datetime_v2_from_orc_millis(int64_t millis, int millis_remainder += 1000; } const auto extra_nanos = std::max(nanos_tail, 0); - const auto microseconds = cast_set(millis_remainder * 1000 + extra_nanos / 1000); + constexpr int64_t NANOS_PER_MICROSECOND = 1000; + constexpr int64_t MICROS_PER_SECOND = 1000000; + // Stripe statistics split the timestamp into milliseconds and the remaining nanoseconds. Use + // the same half-up rule as row decoding so zone-map pruning observes identical values. + const auto rounded_extra_microseconds = + (extra_nanos + NANOS_PER_MICROSECOND / 2) / NANOS_PER_MICROSECOND; + const auto microseconds_with_carry = millis_remainder * 1000 + rounded_extra_microseconds; + seconds += microseconds_with_carry / MICROS_PER_SECOND; + const auto microseconds = cast_set(microseconds_with_carry % MICROS_PER_SECOND); DateV2Value value; value.from_unixtime(seconds, timezone); value.set_microsecond(microseconds); @@ -2111,6 +2119,16 @@ Status OrcReader::get_aggregate_result(const format::FileAggregateRequest& reque return Status::NotSupported( "ORC TIMESTAMP min/max statistics are unsafe before writer version ORC-135"); } + if (leaf_type->getKind() == ::orc::TypeKind::TIMESTAMP_INSTANT && + !_enable_mapping_timestamp_tz) { + // Raw timestamp order does not preserve local DATETIMEV2 order across a DST fold. + int32_t fixed_offset_seconds = 0; + if (!TimezoneUtils::try_get_fixed_offset_seconds(_state->timezone_obj, + &fixed_offset_seconds)) { + return Status::NotSupported( + "ORC timestamp min/max pushdown requires a fixed-offset timezone"); + } + } auto& aggregate_column = result->columns[column_idx]; aggregate_column.projection = request_column.projection; diff --git a/be/src/format_v2/orc/orc_search_argument.cpp b/be/src/format_v2/orc/orc_search_argument.cpp index 244109c12ce6e6..5cee9cf46c116c 100644 --- a/be/src/format_v2/orc/orc_search_argument.cpp +++ b/be/src/format_v2/orc/orc_search_argument.cpp @@ -50,6 +50,7 @@ #ifdef BE_TEST #include "util/debug_points.h" #endif +#include "util/timezone_utils.h" namespace doris::format::orc { namespace { @@ -722,6 +723,8 @@ std::optional<::orc::Literal> make_orc_literal(const OrcSargColumn& sarg_column, case ::orc::PredicateDataType::TIMESTAMP: { DORIS_CHECK(sarg_column.orc_type != nullptr); static const cctz::time_zone utc0 = cctz::utc_time_zone(); + // Plain TIMESTAMP statistics use UTC coordinates for wall-clock values. TIMESTAMP_INSTANT + // literals instead represent instants derived from the session-local DATETIMEV2 value. const auto& literal_timezone = sarg_column.orc_type->getKind() == ::orc::TypeKind::TIMESTAMP_INSTANT ? timezone : utc0; @@ -978,6 +981,15 @@ std::optional make_comparison_literal_for_sarg( if (!literal.has_value()) { return std::nullopt; } + if (column.predicate_type == ::orc::PredicateDataType::TIMESTAMP) { + const auto timestamp = literal->getTimestamp(); + // ORC reconstructs negative timestamp statistics with truncating division, which can + // produce a non-canonical nanos component. The exact epoch is unsafe too because its + // half-up lower bound is -500ns. Leave these predicates to Doris row filtering. + if (timestamp.second < 0 || (timestamp.second == 0 && timestamp.nanos == 0)) { + return std::nullopt; + } + } return OrcSargComparisonLiteral { .literal = *literal, .normalized_op = normalized_op, @@ -1052,6 +1064,12 @@ std::optional> make_in_literals_for_sarg( if (!literal.has_value()) { return std::nullopt; } + if (column.predicate_type == ::orc::PredicateDataType::TIMESTAMP) { + const auto timestamp = literal->getTimestamp(); + if (timestamp.second < 0 || (timestamp.second == 0 && timestamp.nanos == 0)) { + return std::nullopt; + } + } literals.push_back(*literal); } if (literals.empty()) { @@ -1177,6 +1195,145 @@ OrcSargNode make_not_node(OrcSargNode child) { }; } +OrcSargNode make_literal_node(OrcSargNodeKind kind, const OrcSargColumn& column, + ::orc::Literal literal) { + std::vector<::orc::Literal> literals; + literals.push_back(std::move(literal)); + return OrcSargNode { + .kind = kind, + .column = column, + .literals = std::move(literals), + .children = {}, + }; +} + +OrcSargNode make_and_node(std::vector children) { + DORIS_CHECK(!children.empty()); + return OrcSargNode { + .kind = OrcSargNodeKind::AND, + .column = std::nullopt, + .literals = {}, + .children = std::move(children), + }; +} + +::orc::Literal shift_timestamp_literal(const ::orc::Literal& literal, int32_t nanos_delta) { + constexpr int64_t NANOS_PER_SECOND = 1000000000; + const auto timestamp = literal.getTimestamp(); + int64_t seconds = timestamp.second; + int64_t nanos = timestamp.nanos + nanos_delta; + if (nanos < 0) { + --seconds; + nanos += NANOS_PER_SECOND; + } else if (nanos >= NANOS_PER_SECOND) { + ++seconds; + nanos -= NANOS_PER_SECOND; + } + return {seconds, cast_set(nanos)}; +} + +::orc::Literal floor_timestamp_literal_to_millis(const ::orc::Literal& literal) { + constexpr int32_t NANOS_PER_MILLISECOND = 1000000; + const auto timestamp = literal.getTimestamp(); + return {timestamp.second, timestamp.nanos / NANOS_PER_MILLISECOND * NANOS_PER_MILLISECOND}; +} + +::orc::Literal ceil_timestamp_literal_to_millis(const ::orc::Literal& literal) { + constexpr int32_t NANOS_PER_MILLISECOND = 1000000; + const auto timestamp = literal.getTimestamp(); + const auto remainder = timestamp.nanos % NANOS_PER_MILLISECOND; + if (remainder == 0) { + return literal; + } + return shift_timestamp_literal(literal, NANOS_PER_MILLISECOND - remainder); +} + +std::pair<::orc::Literal, ::orc::Literal> timestamp_rounding_bounds(const ::orc::Literal& literal) { + constexpr int32_t HALF_MICROSECOND_NANOS = 500; + // All raw ORC values in [lower, upper) round half-up to this Doris microsecond. Round these + // boundaries toward the side that enlarges the SARG match set because ORC statistics retain + // only millisecond precision. + return {shift_timestamp_literal(literal, -HALF_MICROSECOND_NANOS), + shift_timestamp_literal(literal, HALF_MICROSECOND_NANOS)}; +} + +OrcSargNode make_timestamp_equals_node(const OrcSargColumn& column, const ::orc::Literal& literal) { + const auto [lower_bound, upper_bound] = timestamp_rounding_bounds(literal); + std::vector children; + children.push_back(make_not_node(make_literal_node( + OrcSargNodeKind::LESS_THAN, column, floor_timestamp_literal_to_millis(lower_bound)))); + children.push_back(make_literal_node(OrcSargNodeKind::LESS_THAN, column, + ceil_timestamp_literal_to_millis(upper_bound))); + return make_and_node(std::move(children)); +} + +std::optional make_timestamp_comparison_node(const OrcSargComparison& comparison) { + const auto [lower_bound, upper_bound] = timestamp_rounding_bounds(comparison.literal); + switch (comparison.normalized_op) { + case TExprOpcode::GE: + return make_not_node(make_literal_node(OrcSargNodeKind::LESS_THAN, comparison.column, + floor_timestamp_literal_to_millis(lower_bound))); + case TExprOpcode::GT: + return make_not_node(make_literal_node(OrcSargNodeKind::LESS_THAN, comparison.column, + floor_timestamp_literal_to_millis(upper_bound))); + case TExprOpcode::LE: + return make_literal_node(OrcSargNodeKind::LESS_THAN, comparison.column, + ceil_timestamp_literal_to_millis(upper_bound)); + case TExprOpcode::LT: + return make_literal_node(OrcSargNodeKind::LESS_THAN, comparison.column, + ceil_timestamp_literal_to_millis(lower_bound)); + case TExprOpcode::EQ: + return make_timestamp_equals_node(comparison.column, comparison.literal); + case TExprOpcode::NE: + return std::nullopt; + default: + DORIS_CHECK(false) << "Unsupported normalized ORC timestamp SARG comparison op " + << comparison.normalized_op; + __builtin_unreachable(); + } +} + +OrcSargNode make_timestamp_in_node(const OrcSargColumn& column, + const std::vector<::orc::Literal>& literals) { + DORIS_CHECK(!literals.empty()); + if (literals.size() == 1) { + return make_timestamp_equals_node(column, literals.front()); + } + auto min_literal = literals.front(); + auto max_literal = literals.front(); + for (const auto& literal : literals) { + if (literal.getTimestamp() < min_literal.getTimestamp()) { + min_literal = literal; + } + if (max_literal.getTimestamp() < literal.getTimestamp()) { + max_literal = literal; + } + } + const auto lower_bound = + floor_timestamp_literal_to_millis(timestamp_rounding_bounds(min_literal).first); + const auto upper_bound = + ceil_timestamp_literal_to_millis(timestamp_rounding_bounds(max_literal).second); + std::vector children; + children.push_back( + make_not_node(make_literal_node(OrcSargNodeKind::LESS_THAN, column, lower_bound))); + children.push_back(make_literal_node(OrcSargNodeKind::LESS_THAN, column, upper_bound)); + return make_and_node(std::move(children)); +} + +bool can_emit_timestamp_sarg(const OrcSargColumn& column, const cctz::time_zone& timezone) { + if (column.predicate_type != ::orc::PredicateDataType::TIMESTAMP) { + return true; + } + DORIS_CHECK(column.orc_type != nullptr); + if (column.orc_type->getKind() == ::orc::TypeKind::TIMESTAMP) { + return true; + } + // An unmapped TIMESTAMP_INSTANT is decoded to a local DATETIMEV2. A named timezone may map + // that local timestamp to multiple instants during a DST fold. + int32_t offset_seconds = 0; + return TimezoneUtils::try_get_fixed_offset_seconds(timezone, &offset_seconds); +} + OrcSargNode make_comparison_node(OrcSargComparison comparison) { OrcSargNodeKind kind; bool negate = false; @@ -1208,14 +1365,7 @@ OrcSargNode make_comparison_node(OrcSargComparison comparison) { __builtin_unreachable(); } - std::vector<::orc::Literal> literals; - literals.push_back(std::move(comparison.literal)); - OrcSargNode node { - .kind = kind, - .column = comparison.column, - .literals = std::move(literals), - .children = {}, - }; + auto node = make_literal_node(kind, comparison.column, std::move(comparison.literal)); if (negate) { return make_not_node(std::move(node)); } @@ -1308,12 +1458,12 @@ class OrcSargCompiler { case TExprOpcode::LT: case TExprOpcode::EQ: case TExprOpcode::NE: - return compile_comparison(*normalized); + return compile_comparison(*normalized, is_negated); case TExprOpcode::EQ_FOR_NULL: return compile_null_safe_equal(*normalized); case TExprOpcode::FILTER_IN: case TExprOpcode::FILTER_NOT_IN: - return compile_in(*normalized); + return compile_in(*normalized, is_negated); case TExprOpcode::INVALID_OPCODE: return compile_is_null(*normalized); default: @@ -1383,7 +1533,7 @@ class OrcSargCompiler { return make_not_node(std::move(*child)); } - std::optional compile_comparison(const VExprSPtr& expr) const { + std::optional compile_comparison(const VExprSPtr& expr, bool is_negated) const { if (expr->node_type() == TExprNodeType::NULL_AWARE_BINARY_PRED) { return std::nullopt; } @@ -1391,6 +1541,14 @@ class OrcSargCompiler { if (!comparison.has_value()) { return std::nullopt; } + if (comparison->column.predicate_type == ::orc::PredicateDataType::TIMESTAMP) { + // Timestamp comparisons use a conservative millisecond envelope. Negating it turns + // false-positive margin into false negatives, so leave exact negation to Doris. + if (is_negated || !can_emit_timestamp_sarg(comparison->column, _timezone)) { + return std::nullopt; + } + return make_timestamp_comparison_node(*comparison); + } return make_comparison_node(std::move(*comparison)); } @@ -1404,10 +1562,16 @@ class OrcSargCompiler { if (!comparison.has_value()) { return std::nullopt; } + if (comparison->column.predicate_type == ::orc::PredicateDataType::TIMESTAMP) { + if (!can_emit_timestamp_sarg(comparison->column, _timezone)) { + return std::nullopt; + } + return make_timestamp_equals_node(comparison->column, comparison->literal); + } return make_comparison_node(std::move(*comparison)); } - std::optional compile_in(const VExprSPtr& expr) const { + std::optional compile_in(const VExprSPtr& expr, bool is_negated) const { if (expr->node_type() == TExprNodeType::NULL_AWARE_IN_PRED || expr->children().size() < 2) { return std::nullopt; } @@ -1421,6 +1585,14 @@ class OrcSargCompiler { if (!literals.has_value()) { return std::nullopt; } + if (column->predicate_type == ::orc::PredicateDataType::TIMESTAMP) { + // NOT IN negates the conservative equality envelopes and is unsafe for pruning. + if (is_negated || expr->op() == TExprOpcode::FILTER_NOT_IN || + !can_emit_timestamp_sarg(*column, _timezone)) { + return std::nullopt; + } + return make_timestamp_in_node(*column, *literals); + } auto node = make_in_node(*column, std::move(*literals)); if (expr->op() == TExprOpcode::FILTER_NOT_IN) { node = make_not_node(std::move(node)); diff --git a/be/src/format_v2/parquet/parquet_reader.cpp b/be/src/format_v2/parquet/parquet_reader.cpp index 753b3628bfa19b..0bcff2fc7e81d1 100644 --- a/be/src/format_v2/parquet/parquet_reader.cpp +++ b/be/src/format_v2/parquet/parquet_reader.cpp @@ -42,6 +42,7 @@ #include "format_v2/parquet/reader/column_reader.h" #include "io/io_common.h" #include "runtime/runtime_state.h" +#include "util/timezone_utils.h" namespace doris::format::parquet { @@ -52,6 +53,7 @@ struct ParquetReaderScanState { ParquetScanScheduler scheduler; const RuntimeState* runtime_state = nullptr; const cctz::time_zone* timezone = nullptr; + std::optional int96_timezone; bool enable_bloom_filter = false; bool enable_page_cache = false; bool enable_strict_mode = false; @@ -328,10 +330,11 @@ ParquetReader::ParquetReader(std::shared_ptr& system_p std::unique_ptr& file_description, std::shared_ptr io_ctx, RuntimeProfile* profile, std::optional global_rowid_context, - bool enable_mapping_timestamp_tz) + bool enable_mapping_timestamp_tz, std::string hive_parquet_time_zone) : FileReader(system_properties, file_description, io_ctx, profile), _global_rowid_context(global_rowid_context), - _enable_mapping_timestamp_tz(enable_mapping_timestamp_tz) {} + _enable_mapping_timestamp_tz(enable_mapping_timestamp_tz), + _hive_parquet_time_zone(std::move(hive_parquet_time_zone)) {} ParquetReader::~ParquetReader() = default; @@ -350,6 +353,15 @@ Status ParquetReader::init(RuntimeState* state) { state != nullptr && state->query_options().enable_parquet_filter_by_bloom_filter; _state->enable_page_cache = state != nullptr && state->query_options().enable_parquet_file_page_cache; + if (!_hive_parquet_time_zone.empty()) { + cctz::time_zone int96_timezone; + if (!TimezoneUtils::find_cctz_time_zone(_hive_parquet_time_zone, int96_timezone)) { + return Status::InvalidArgument("Invalid hive.parquet.time-zone: {}", + _hive_parquet_time_zone); + } + _state->int96_timezone = int96_timezone; + _state->scheduler.set_int96_timezone(&*_state->int96_timezone); + } if (state != nullptr) { _state->runtime_state = state; _state->timezone = &state->timezone_obj(); @@ -637,7 +649,8 @@ Status ParquetReader::get_aggregate_result(const format::FileAggregateRequest& r row_group, _state->file_context.schema->num_columns(), &row_group_plan.page_skip_plans, _parquet_profile.page_skip_profile(), _state->timezone, _state->enable_strict_mode, - _parquet_profile.scan_profile().column_reader_profile); + _parquet_profile.scan_profile().column_reader_profile, + _state->int96_timezone ? &*_state->int96_timezone : nullptr); std::unique_ptr shape_reader; RETURN_IF_ERROR(column_reader_factory.create_count_shape_reader( root_schema, &count_projection, &shape_reader)); diff --git a/be/src/format_v2/parquet/parquet_reader.h b/be/src/format_v2/parquet/parquet_reader.h index 6c8e88cc27a9b6..24794d80692763 100644 --- a/be/src/format_v2/parquet/parquet_reader.h +++ b/be/src/format_v2/parquet/parquet_reader.h @@ -17,6 +17,7 @@ #include #include +#include #include #include "common/status.h" @@ -46,7 +47,8 @@ class ParquetReader : public format::FileReader { std::unique_ptr& file_description, std::shared_ptr io_ctx, RuntimeProfile* profile, std::optional global_rowid_context = std::nullopt, - bool enable_mapping_timestamp_tz = false); + bool enable_mapping_timestamp_tz = false, + std::string hive_parquet_time_zone = ""); ~ParquetReader() override; Status init(RuntimeState* state) override; @@ -89,6 +91,7 @@ class ParquetReader : public format::FileReader { std::optional _global_rowid_context; // global RowId context size_t _batch_size = ParquetScanScheduler::DEFAULT_READ_BATCH_SIZE; bool _enable_mapping_timestamp_tz = false; // whether UTC timestamps are mapped to TIMESTAMPTZ + std::string _hive_parquet_time_zone; // explicit INT96 timezone; empty disables conversion }; } // namespace doris::format::parquet diff --git a/be/src/format_v2/parquet/parquet_scan.cpp b/be/src/format_v2/parquet/parquet_scan.cpp index 1abddc777aa442..0626faedce17fd 100644 --- a/be/src/format_v2/parquet/parquet_scan.cpp +++ b/be/src/format_v2/parquet/parquet_scan.cpp @@ -714,8 +714,8 @@ Status ParquetScanScheduler::open_next_row_group( ParquetColumnReaderFactory column_reader_factory( _current_row_group, file_context.schema->num_columns(), &row_group_plan.page_skip_plans, - _page_skip_profile, _timezone, _enable_strict_mode, - _scan_profile.column_reader_profile); + _page_skip_profile, _timezone, _enable_strict_mode, _scan_profile.column_reader_profile, + _int96_timezone); for (const auto& col : request.predicate_columns) { const auto local_id = col.local_id(); if (local_id == format::ROW_POSITION_COLUMN_ID) { diff --git a/be/src/format_v2/parquet/parquet_scan.h b/be/src/format_v2/parquet/parquet_scan.h index c656b146cefeaa..adcb8b174abe24 100644 --- a/be/src/format_v2/parquet/parquet_scan.h +++ b/be/src/format_v2/parquet/parquet_scan.h @@ -125,6 +125,7 @@ class ParquetScanScheduler { } void set_condition_cache_context(std::shared_ptr ctx); void set_timezone(const cctz::time_zone* timezone) { _timezone = timezone; } + void set_int96_timezone(const cctz::time_zone* timezone) { _int96_timezone = timezone; } void set_enable_strict_mode(bool enable_strict_mode) { _enable_strict_mode = enable_strict_mode; } @@ -218,6 +219,7 @@ class ParquetScanScheduler { int64_t _merge_read_slice_size = -1; std::optional _global_rowid_context; const cctz::time_zone* _timezone = nullptr; + const cctz::time_zone* _int96_timezone = nullptr; bool _enable_strict_mode = false; int64_t _batch_size = DEFAULT_READ_BATCH_SIZE; std::shared_ptr _condition_cache_ctx; diff --git a/be/src/format_v2/parquet/reader/column_reader.cpp b/be/src/format_v2/parquet/reader/column_reader.cpp index 352fbbd7c3d215..b88c9ebdf55514 100644 --- a/be/src/format_v2/parquet/reader/column_reader.cpp +++ b/be/src/format_v2/parquet/reader/column_reader.cpp @@ -210,13 +210,15 @@ ParquetColumnReaderFactory::ParquetColumnReaderFactory( std::shared_ptr<::parquet::RowGroupReader> row_group, int num_leaf_columns, const std::map* page_skip_plans, ParquetPageSkipProfile page_skip_profile, const cctz::time_zone* timezone, - bool enable_strict_mode, ParquetColumnReaderProfile column_reader_profile) + bool enable_strict_mode, ParquetColumnReaderProfile column_reader_profile, + const cctz::time_zone* int96_timezone) : _row_group(std::move(row_group)), _record_readers(static_cast(num_leaf_columns)), _dictionary_record_readers(static_cast(num_leaf_columns)), _page_skip_plans(page_skip_plans), _page_skip_profile(page_skip_profile), _timezone(timezone), + _int96_timezone(int96_timezone), _enable_strict_mode(enable_strict_mode), _column_reader_profile(column_reader_profile) {} @@ -243,7 +245,7 @@ Status ParquetColumnReaderFactory::make_scalar_column_reader( : nullptr; *reader = std::make_unique(column_schema, std::move(record_reader), page_skip_plan, _timezone, _enable_strict_mode, - _column_reader_profile); + _column_reader_profile, _int96_timezone); return Status::OK(); } diff --git a/be/src/format_v2/parquet/reader/column_reader.h b/be/src/format_v2/parquet/reader/column_reader.h index 51dbd44c11c226..ae56bfff1268c5 100644 --- a/be/src/format_v2/parquet/reader/column_reader.h +++ b/be/src/format_v2/parquet/reader/column_reader.h @@ -156,7 +156,8 @@ class ParquetColumnReaderFactory { ParquetPageSkipProfile page_skip_profile = {}, const cctz::time_zone* timezone = nullptr, bool enable_strict_mode = false, - ParquetColumnReaderProfile column_reader_profile = {}); + ParquetColumnReaderProfile column_reader_profile = {}, + const cctz::time_zone* int96_timezone = nullptr); Status create(const ParquetColumnSchema& column_schema, const format::LocalColumnIndex* projection, @@ -225,6 +226,7 @@ class ParquetColumnReaderFactory { nullptr; // page-index pruning result ParquetPageSkipProfile _page_skip_profile; // page skip profile const cctz::time_zone* _timezone = nullptr; // timezone + const cctz::time_zone* _int96_timezone = nullptr; // explicit timezone for legacy INT96 bool _enable_strict_mode = false; // strict mode ParquetColumnReaderProfile _column_reader_profile; // column reader profile }; diff --git a/be/src/format_v2/parquet/reader/parquet_leaf_reader.cpp b/be/src/format_v2/parquet/reader/parquet_leaf_reader.cpp index fd261ef5219d27..7c217fd7765a0e 100644 --- a/be/src/format_v2/parquet/reader/parquet_leaf_reader.cpp +++ b/be/src/format_v2/parquet/reader/parquet_leaf_reader.cpp @@ -376,7 +376,15 @@ Status ParquetLeafReader::append_values(const ParquetLeafBatch& batch, int64_t r view.decimal_scale = _type_descriptor.decimal_scale; view.fixed_length = _type_descriptor.fixed_length; view.timestamp_is_adjusted_to_utc = _type_descriptor.timestamp_is_adjusted_to_utc; - view.timezone = _timezone; + // INT96 has no timezone annotation, so the writer's convention cannot be inferred from the + // file. Match Trino's explicit hive.parquet.time-zone behavior instead of guessing from + // created_by or using the SQL session timezone: + // - With no catalog property, keep the raw wall clock. For example, raw 2021-01-01 10:11 in a + // Trino/UTC file stays 10:11 instead of becoming 18:11 in an Asia/Shanghai session. + // - With hive.parquet.time-zone=Asia/Shanghai, interpret a legacy Hive-normalized raw 02:11 as + // a UTC epoch and convert it back to the original local wall clock 10:11. + // TIMESTAMPTZ intentionally ignores this pointer in its SerDe and keeps the same UTC instant. + view.timezone = batch._value_kind == DecodedValueKind::INT96 ? _int96_timezone : _timezone; view.enable_strict_mode = _enable_strict_mode; view.null_map = null_map == nullptr || null_map->empty() ? nullptr : null_map->data(); const bool read_dense_for_nullable = batch._read_dense_for_nullable && view.null_map != nullptr; @@ -469,7 +477,8 @@ ParquetLeafReader::ParquetLeafReader( std::shared_ptr<::parquet::internal::RecordReader> record_reader, ParquetColumnReaderProfile profile, const cctz::time_zone* timezone, bool enable_strict_mode, - std::function decoded_value_appender) + std::function decoded_value_appender, + const cctz::time_zone* int96_timezone) : _descriptor(descriptor), _type_descriptor(type_descriptor), _type(std::move(type)), @@ -477,6 +486,7 @@ ParquetLeafReader::ParquetLeafReader( _record_reader(std::move(record_reader)), _profile(profile), _timezone(timezone), + _int96_timezone(int96_timezone), _enable_strict_mode(enable_strict_mode), _decoded_value_appender(std::move(decoded_value_appender)) {} @@ -736,7 +746,8 @@ Status ParquetLeafReader::build_nested_batch_from_leaf_batch( batch->values_column = value_type->create_column(); if (values_written > 0) { ParquetLeafReader value_reader(_descriptor, _type_descriptor, value_type, _name, - _record_reader, _profile, _timezone, _enable_strict_mode); + _record_reader, _profile, _timezone, _enable_strict_mode, + nullptr, _int96_timezone); RETURN_IF_ERROR(value_reader.append_values(leaf_batch, values_written, &value_nulls, batch->values_column)); } diff --git a/be/src/format_v2/parquet/reader/parquet_leaf_reader.h b/be/src/format_v2/parquet/reader/parquet_leaf_reader.h index b396b35fd1f32c..b54b04ada17ad7 100644 --- a/be/src/format_v2/parquet/reader/parquet_leaf_reader.h +++ b/be/src/format_v2/parquet/reader/parquet_leaf_reader.h @@ -103,7 +103,8 @@ class ParquetLeafReader { ParquetColumnReaderProfile profile = {}, const cctz::time_zone* timezone = nullptr, bool enable_strict_mode = false, std::function - decoded_value_appender = nullptr); + decoded_value_appender = nullptr, + const cctz::time_zone* int96_timezone = nullptr); Status read_batch(int64_t batch_rows, ParquetLeafBatch* batch, int64_t* rows_read) const; @@ -166,7 +167,8 @@ class ParquetLeafReader { _record_reader; // Arrow physical column reader (shared ownership) ParquetColumnReaderProfile _profile; // profile counters const cctz::time_zone* _timezone = nullptr; // timezone for timestamp conversion - bool _enable_strict_mode = false; // strict mode for type mismatch errors + const cctz::time_zone* _int96_timezone = nullptr; + bool _enable_strict_mode = false; // strict mode for type mismatch errors std::function _decoded_value_appender; }; diff --git a/be/src/format_v2/parquet/reader/scalar_column_reader.cpp b/be/src/format_v2/parquet/reader/scalar_column_reader.cpp index bdbd9ac8779e05..8ee1236a9e5401 100644 --- a/be/src/format_v2/parquet/reader/scalar_column_reader.cpp +++ b/be/src/format_v2/parquet/reader/scalar_column_reader.cpp @@ -121,13 +121,15 @@ ScalarColumnReader::ScalarColumnReader( const ParquetColumnSchema& column_schema, std::shared_ptr<::parquet::internal::RecordReader> record_reader, const ParquetPageSkipPlan* page_skip_plan, const cctz::time_zone* timezone, - bool enable_strict_mode, ParquetColumnReaderProfile profile) + bool enable_strict_mode, ParquetColumnReaderProfile profile, + const cctz::time_zone* int96_timezone) : ParquetColumnReader(column_schema, column_schema.type, profile), _descriptor(column_schema.descriptor), _type_descriptor(column_schema.type_descriptor), _record_reader(std::move(record_reader)), _page_skip_plan(page_skip_plan), _timezone(timezone), + _int96_timezone(int96_timezone), _enable_strict_mode(enable_strict_mode), _nested_batch(std::make_unique()) {} diff --git a/be/src/format_v2/parquet/reader/scalar_column_reader.h b/be/src/format_v2/parquet/reader/scalar_column_reader.h index 5342baa803eca0..1bac5e8c968769 100644 --- a/be/src/format_v2/parquet/reader/scalar_column_reader.h +++ b/be/src/format_v2/parquet/reader/scalar_column_reader.h @@ -50,7 +50,8 @@ class ScalarColumnReader final : public ParquetColumnReader { std::shared_ptr<::parquet::internal::RecordReader> record_reader, const ParquetPageSkipPlan* page_skip_plan = nullptr, const cctz::time_zone* timezone = nullptr, bool enable_strict_mode = false, - ParquetColumnReaderProfile profile = {}); + ParquetColumnReaderProfile profile = {}, + const cctz::time_zone* int96_timezone = nullptr); ~ScalarColumnReader() override; Status read(int64_t rows, MutableColumnPtr& column, int64_t* rows_read) override; @@ -88,7 +89,8 @@ class ScalarColumnReader final : public ParquetColumnReader { ParquetLeafReader leaf_reader() const { return ParquetLeafReader(_descriptor, _type_descriptor, _type, _name, _record_reader, - _profile, _timezone, _enable_strict_mode); + _profile, _timezone, _enable_strict_mode, nullptr, + _int96_timezone); } void advance_rows_read(int64_t rows); @@ -102,8 +104,9 @@ class ScalarColumnReader final : public ParquetColumnReader { const ParquetPageSkipPlan* _page_skip_plan = nullptr; // page-index pruning result (may be nullptr) const cctz::time_zone* _timezone = nullptr; // timezone - bool _enable_strict_mode = false; // strict mode - int64_t _row_group_rows_read = 0; // rows read in the current row group (cursor) + const cctz::time_zone* _int96_timezone = nullptr; + bool _enable_strict_mode = false; // strict mode + int64_t _row_group_rows_read = 0; // rows read in the current row group (cursor) std::unique_ptr _nested_batch; // intermediate result for nested reads }; diff --git a/be/src/format_v2/table_reader.cpp b/be/src/format_v2/table_reader.cpp index 5f37538c1f2639..e31a6f50bd8c27 100644 --- a/be/src/format_v2/table_reader.cpp +++ b/be/src/format_v2/table_reader.cpp @@ -753,10 +753,14 @@ Status TableReader::create_file_reader(std::unique_ptr* reader) { const bool enable_mapping_timestamp_tz = _scan_params != nullptr && _scan_params->__isset.enable_mapping_timestamp_tz && _scan_params->enable_mapping_timestamp_tz; + const std::string hive_parquet_time_zone = + _scan_params != nullptr && _scan_params->__isset.hive_parquet_time_zone + ? _scan_params->hive_parquet_time_zone + : ""; if (_format == FileFormat::PARQUET) { *reader = std::make_unique( _system_properties, _current_task->data_file, _io_ctx, _scanner_profile, - _global_rowid_context, enable_mapping_timestamp_tz); + _global_rowid_context, enable_mapping_timestamp_tz, hive_parquet_time_zone); return Status::OK(); } if (_format == FileFormat::ORC) { diff --git a/be/test/format_v2/orc/orc_reader_test.cpp b/be/test/format_v2/orc/orc_reader_test.cpp index 6809186f115b59..f572f260bc4659 100644 --- a/be/test/format_v2/orc/orc_reader_test.cpp +++ b/be/test/format_v2/orc/orc_reader_test.cpp @@ -275,6 +275,7 @@ class TableSlotRef : public VSlotRef { constexpr int64_t ROW_COUNT = 5; constexpr int64_t PRIMITIVE_ROW_COUNT = 3; +constexpr int64_t TIMESTAMP_ROUNDING_ROW_COUNT = 4; constexpr int64_t COMPLEX_ROW_COUNT = 3; constexpr int64_t DEEP_NESTED_ROW_COUNT = 4; constexpr int64_t DEEP_NESTED_BATCH_CAPACITY = 16; @@ -2475,13 +2476,20 @@ class NullableGreaterThanExpr final : public VExpr { using ValueType = typename PrimitiveTypeTraits::CppType; NullableGreaterThanExpr(int column_id, DataTypePtr type, const Field& value, - std::string column_name, bool literal_on_left = false) + std::string column_name, bool literal_on_left = false, + TExprOpcode::type comparison_op = TExprOpcode::GT) : VExpr(std::make_shared(), false), _column_id(column_id), _value(value.get()), + _comparison_op(comparison_op), _expr_name("NullableGreaterThanExpr") { _node_type = TExprNodeType::BINARY_PRED; - _opcode = literal_on_left ? TExprOpcode::LT : TExprOpcode::GT; + if (literal_on_left) { + DORIS_CHECK(comparison_op == TExprOpcode::GT); + _opcode = TExprOpcode::LT; + } else { + _opcode = comparison_op; + } auto slot = TableSlotRef::create_shared(column_id, column_id, -1, make_nullable(type), column_name); auto literal = TableLiteral::create_shared(std::move(type), value); @@ -2504,8 +2512,24 @@ class NullableGreaterThanExpr final : public VExpr { result_data.resize(count); for (size_t row = 0; row < count; ++row) { const size_t input_row = selector == nullptr ? row : (*selector)[row]; - result_data[row] = - !nullable_column.is_null_at(input_row) && input.get_element(input_row) > _value; + if (nullable_column.is_null_at(input_row)) { + result_data[row] = false; + continue; + } + const auto input_value = input.get_element(input_row); + switch (_comparison_op) { + case TExprOpcode::GT: + result_data[row] = input_value > _value; + break; + case TExprOpcode::LT: + result_data[row] = input_value < _value; + break; + case TExprOpcode::NE: + result_data[row] = input_value != _value; + break; + default: + DORIS_CHECK(false) << "Unsupported test comparison opcode " << _comparison_op; + } } result_column = std::move(result); return Status::OK(); @@ -2516,6 +2540,7 @@ class NullableGreaterThanExpr final : public VExpr { private: const int _column_id; const ValueType _value; + const TExprOpcode::type _comparison_op; const std::string _expr_name; }; @@ -3068,6 +3093,48 @@ void write_primitive_orc_file(const std::string& file_path) { out.write(memory_stream.getData(), static_cast(memory_stream.getLength())); } +void write_timestamp_rounding_orc_file(const std::string& file_path, + int64_t row_count = TIMESTAMP_ROUNDING_ROW_COUNT, + int64_t first_source_row = 0) { + auto type = std::unique_ptr<::orc::Type>(::orc::Type::buildTypeFromString( + "struct")); + + MemoryOutputStream memory_stream(1024 * 1024); + ::orc::WriterOptions options; + options.setCompression(::orc::CompressionKind_NONE); + options.setMemoryPool(::orc::getDefaultPool()); + // ORC treats GMT as its canonical zero-offset writer timezone. + options.setTimezoneName("GMT"); + auto writer = ::orc::createWriter(*type, &memory_stream, options); + auto batch = writer->createRowBatch(row_count); + auto& struct_batch = dynamic_cast<::orc::StructVectorBatch&>(*batch); + auto& timestamp_batch = dynamic_cast<::orc::TimestampVectorBatch&>(*struct_batch.fields[0]); + auto& timestamp_instant_batch = + dynamic_cast<::orc::TimestampVectorBatch&>(*struct_batch.fields[1]); + + static constexpr std::array seconds {1, 2, 1609459199, + -2}; + static constexpr std::array nanoseconds { + 111001900, 345678499, 999999999, 999998500}; + for (int64_t row = 0; row < row_count; ++row) { + const auto source_row = first_source_row + row; + timestamp_batch.data[row] = seconds[source_row]; + timestamp_batch.nanoseconds[row] = nanoseconds[source_row]; + timestamp_instant_batch.data[row] = seconds[source_row]; + timestamp_instant_batch.nanoseconds[row] = nanoseconds[source_row]; + } + struct_batch.numElements = row_count; + timestamp_batch.numElements = row_count; + timestamp_instant_batch.numElements = row_count; + + writer->add(*batch); + writer->close(); + + std::ofstream out(file_path, std::ios::binary); + out.write(memory_stream.getData(), static_cast(memory_stream.getLength())); +} + void fill_complex_struct_column(::orc::StructVectorBatch& struct_col) { auto& struct_a = dynamic_cast<::orc::LongVectorBatch&>(*struct_col.fields[0]); auto& struct_b = dynamic_cast<::orc::StringVectorBatch&>(*struct_col.fields[1]); @@ -4192,6 +4259,8 @@ void write_multi_stripe_orc_sarg_types_file(const std::string& file_path) { ::orc::WriterOptions options; options.setCompression(::orc::CompressionKind_NONE); options.setMemoryPool(::orc::getDefaultPool()); + // ORC treats GMT as its canonical zero-offset writer timezone. + options.setTimezoneName("GMT"); options.setStripeSize(1); options.setDictionaryKeySizeThreshold(0); auto writer = ::orc::createWriter(*type, &memory_stream, options); @@ -4316,7 +4385,8 @@ void write_two_stripe_constant_date_file(const std::string& file_path, int64_t f void write_two_stripe_constant_timestamp_file(const std::string& file_path, int64_t first_timestamp_second, int64_t second_timestamp_second, - std::string_view writer_timezone = "GMT") { + std::string_view writer_timezone = "GMT", + int64_t nanoseconds = 123000000) { auto type = std::unique_ptr<::orc::Type>( ::orc::Type::buildTypeFromString("struct")); @@ -4339,7 +4409,7 @@ void write_two_stripe_constant_timestamp_file(const std::string& file_path, payloads.reserve(ROWS_PER_STRIPE); for (int64_t row = 0; row < ROWS_PER_STRIPE; ++row) { timestamp_batch.data[row] = timestamp_second; - timestamp_batch.nanoseconds[row] = 123000000; + timestamp_batch.nanoseconds[row] = nanoseconds; payloads.push_back(std::string(2048, static_cast('a' + row % 26))); set_string_value(payload_batch, row, payloads.back()); } @@ -4470,6 +4540,8 @@ format::LocalColumnIndex struct_child_projection(int32_t root_field_id, int32_t class NewOrcReaderTest : public testing::Test { protected: + static void SetUpTestSuite() { TimezoneUtils::load_timezones_to_cache(); } + enum class DirectInPredicateShape { ROOT, AND, @@ -4957,6 +5029,61 @@ TEST_F(NewOrcReaderTest, AggregatePushdownTimestampMinMaxFallsBackForPreOrc135Wr EXPECT_EQ(fallback_values, baseline_values); } +TEST_F(NewOrcReaderTest, AggregatePushdownTimestampMinMaxMatchesNegativeRowDecoding) { + const auto file_path = (_test_dir / "aggregate_negative_timestamp.orc").string(); + // Unlike ORC SARG reconstruction, the aggregate path canonicalizes negative millisecond + // remainders before rounding. Its statistics result must match the decoded row value. + write_timestamp_rounding_orc_file(file_path, 1, 3); + + auto reader = create_reader_for_path(file_path); + RuntimeState state {TQueryOptions(), TQueryGlobals()}; + state.set_timezone("+00:00"); + ASSERT_TRUE(reader->init(&state).ok()); + + auto request = std::make_shared(); + request->non_predicate_columns = {field_projection(0)}; + ASSERT_TRUE(reader->open(request).ok()); + + format::FileAggregateRequest aggregate_request; + aggregate_request.agg_type = TPushAggOp::type::MINMAX; + aggregate_request.columns.push_back( + {.projection = format::LocalColumnIndex::top_level(format::LocalColumnId(0))}); + format::FileAggregateResult aggregate_result; + auto status = reader->get_aggregate_result(aggregate_request, &aggregate_result); + ASSERT_TRUE(status.ok()) << status; + ASSERT_EQ(aggregate_result.columns.size(), 1); + EXPECT_EQ(aggregate_result.count, 1); + EXPECT_TRUE(aggregate_result.columns[0].has_min); + EXPECT_TRUE(aggregate_result.columns[0].has_max); + const auto expected = make_datetime_v2(1969, 12, 31, 23, 59, 58, 999999); + EXPECT_EQ(aggregate_result.columns[0].min_value.get(), expected); + EXPECT_EQ(aggregate_result.columns[0].max_value.get(), expected); +} + +TEST_F(NewOrcReaderTest, AggregatePushdownTimestampMinMaxRejectsNamedTimezone) { + const auto multi_stripe_file_path = (_test_dir / "aggregate_timestamp_dst_fold.orc").string(); + // 2021-11-07 08:30Z and 09:00Z straddle the America/Los_Angeles fall-back transition. + write_multi_stripe_orc_timestamp_instant_sarg_file(multi_stripe_file_path, 1636273800, + 1636275600); + + auto reader = create_reader_for_path(multi_stripe_file_path); + RuntimeState state {TQueryOptions(), TQueryGlobals()}; + state.set_timezone("America/Los_Angeles"); + ASSERT_TRUE(reader->init(&state).ok()); + + auto request = std::make_shared(); + request->non_predicate_columns = {field_projection(0)}; + ASSERT_TRUE(reader->open(request).ok()); + + format::FileAggregateRequest aggregate_request; + aggregate_request.agg_type = TPushAggOp::type::MINMAX; + aggregate_request.columns.push_back( + {.projection = format::LocalColumnIndex::top_level(format::LocalColumnId(0))}); + format::FileAggregateResult aggregate_result; + auto status = reader->get_aggregate_result(aggregate_request, &aggregate_result); + EXPECT_TRUE(status.is()) << status; +} + TEST_F(NewOrcReaderTest, AggregatePushdownTimestampInstantMinMaxUsesTimestampTzWhenMapped) { const auto multi_stripe_file_path = (_test_dir / "aggregate_timestamp_instant_tz.orc").string(); write_multi_stripe_orc_timestamp_instant_sarg_file(multi_stripe_file_path); @@ -9215,6 +9342,47 @@ TEST_F(NewOrcReaderTest, SargTimestampConjunctPrunesStripes) { EXPECT_EQ(reader->reader_statistics().filtered_group_rows, 200); } +TEST_F(NewOrcReaderTest, SargPlainTimestampFixedOffsetUsesUtcWallClockLiteral) { + const auto multi_stripe_file_path = + (_test_dir / "sarg_timestamp_session_timezone.orc").string(); + // Plain TIMESTAMP uses UTC coordinates for wall-clock statistics even when writer and session + // timezones have a nonzero offset. + write_two_stripe_constant_timestamp_file(multi_stripe_file_path, 0, 3600, "Asia/Shanghai"); + ASSERT_EQ(get_orc_stripe_count(multi_stripe_file_path), 2); + + auto reader = create_reader_for_path(multi_stripe_file_path); + RuntimeState state {TQueryOptions(), TQueryGlobals()}; + state.set_timezone("+08:00"); + ASSERT_TRUE(reader->init(&state).ok()); + + std::vector schema; + ASSERT_TRUE(reader->get_schema(&schema).ok()); + ASSERT_EQ(schema.size(), 2); + + const auto literal = Field::create_field(make_datetime_v2(1970, 1, 1, 8, 30)); + auto request = std::make_shared(); + request->predicate_columns = {field_projection(0)}; + request->conjuncts.push_back( + VExprContext::create_shared(std::make_shared>( + 0, remove_nullable(schema[0].type), literal, "timestamp_col", false, + TExprOpcode::LT))); + ASSERT_TRUE(reader->open(request).ok()); + + bool eof = false; + size_t result_rows = 0; + while (!eof) { + Block block = build_file_block({schema[0]}); + size_t rows = 0; + ASSERT_TRUE(reader->get_block(&block, &rows, &eof).ok()); + result_rows += rows; + } + + EXPECT_EQ(result_rows, 200); + EXPECT_EQ(reader->reader_statistics().filtered_row_groups, 1); + EXPECT_EQ(reader->reader_statistics().filtered_row_groups_by_min_max, 1); + EXPECT_EQ(reader->reader_statistics().filtered_group_rows, 200); +} + TEST_F(NewOrcReaderTest, SargTimestampInstantConjunctUsesSessionTimezone) { const auto multi_stripe_file_path = (_test_dir / "sarg_timestamp_instant_timezone.orc").string(); @@ -9249,9 +9417,11 @@ TEST_F(NewOrcReaderTest, SargTimestampInstantConjunctUsesSessionTimezone) { } EXPECT_EQ(result_rows, 200); - EXPECT_EQ(reader->reader_statistics().filtered_row_groups, 1); - EXPECT_EQ(reader->reader_statistics().filtered_row_groups_by_min_max, 1); - EXPECT_EQ(reader->reader_statistics().filtered_group_rows, 200); + // Named timezones can map a local timestamp to multiple instants during a DST fold, so Doris + // must leave timestamp stripe pruning disabled and apply the predicate after decoding. + EXPECT_EQ(reader->reader_statistics().filtered_row_groups, 0); + EXPECT_EQ(reader->reader_statistics().filtered_row_groups_by_min_max, 0); + EXPECT_EQ(reader->reader_statistics().filtered_group_rows, 0); } TEST_F(NewOrcReaderTest, SargTimestampInstantRepeatedCivilTimeDoesNotPruneStripes) { @@ -9525,6 +9695,7 @@ TEST_F(NewOrcReaderTest, SargTimestampInListConjunctPrunesStripes) { auto reader = create_reader_for_path(multi_stripe_file_path); RuntimeState state {TQueryOptions(), TQueryGlobals()}; + state.set_timezone("+00:00"); ASSERT_TRUE(reader->init(&state).ok()); std::vector schema; @@ -9556,13 +9727,14 @@ TEST_F(NewOrcReaderTest, SargTimestampInListConjunctPrunesStripes) { EXPECT_EQ(reader->reader_statistics().filtered_group_rows, 200); } -TEST_F(NewOrcReaderTest, SargTimestampNotInListConjunctPrunesStripes) { +TEST_F(NewOrcReaderTest, SargTimestampNotInListConjunctDoesNotUseUnsafeEnvelope) { const auto multi_stripe_file_path = (_test_dir / "sarg_timestamp_not_in.orc").string(); write_two_stripe_constant_timestamp_file(multi_stripe_file_path, 0, 1609459200); ASSERT_EQ(get_orc_stripe_count(multi_stripe_file_path), 2); auto reader = create_reader_for_path(multi_stripe_file_path); RuntimeState state {TQueryOptions(), TQueryGlobals()}; + state.set_timezone("+00:00"); ASSERT_TRUE(reader->init(&state).ok()); std::vector schema; @@ -9589,9 +9761,52 @@ TEST_F(NewOrcReaderTest, SargTimestampNotInListConjunctPrunesStripes) { } EXPECT_EQ(result_rows, 200); - EXPECT_EQ(reader->reader_statistics().filtered_row_groups, 1); - EXPECT_EQ(reader->reader_statistics().filtered_row_groups_by_min_max, 1); - EXPECT_EQ(reader->reader_statistics().filtered_group_rows, 200); + EXPECT_EQ(reader->reader_statistics().filtered_row_groups, 0); + EXPECT_EQ(reader->reader_statistics().filtered_row_groups_by_min_max, 0); + EXPECT_EQ(reader->reader_statistics().filtered_group_rows, 0); +} + +TEST_F(NewOrcReaderTest, SargTimestampNamedTimezoneFoldDoesNotPruneMatches) { + const auto file_path = (_test_dir / "sarg_timestamp_dst_fold.orc").string(); + write_two_stripe_constant_timestamp_file(file_path, 1636273800, 1636277400, + "America/Los_Angeles"); + ASSERT_EQ(get_orc_stripe_count(file_path), 2); + + auto reader = create_reader_for_path(file_path); + RuntimeState state {TQueryOptions(), TQueryGlobals()}; + state.set_timezone("America/Los_Angeles"); + int32_t offset_seconds = 0; + ASSERT_FALSE( + TimezoneUtils::try_get_fixed_offset_seconds(state.timezone_obj(), &offset_seconds)); + ASSERT_TRUE(reader->init(&state).ok()); + + std::vector schema; + ASSERT_TRUE(reader->get_schema(&schema).ok()); + ASSERT_EQ(schema.size(), 2); + + auto request = std::make_shared(); + request->predicate_columns = {field_projection(0)}; + request->conjuncts.push_back( + VExprContext::create_shared(std::make_shared>( + 0, remove_nullable(schema[0].type), + std::vector {Field::create_field( + make_datetime_v2(2021, 11, 7, 1, 30, 0, 123000))}, + "timestamp_col"))); + ASSERT_TRUE(reader->open(request).ok()); + + bool eof = false; + size_t result_rows = 0; + while (!eof) { + Block block = build_file_block({schema[0]}); + size_t rows = 0; + ASSERT_TRUE(reader->get_block(&block, &rows, &eof).ok()); + result_rows += rows; + } + + EXPECT_EQ(result_rows, 400); + EXPECT_EQ(reader->reader_statistics().filtered_row_groups, 0); + EXPECT_EQ(reader->reader_statistics().filtered_row_groups_by_min_max, 0); + EXPECT_EQ(reader->reader_statistics().filtered_group_rows, 0); } TEST_F(NewOrcReaderTest, SargConjunctPruningPreservesRowPosition) { @@ -9927,6 +10142,194 @@ TEST_F(NewOrcReaderTest, ReadPrimitiveTypesWithNulls) { EXPECT_EQ(schema[15].type->to_string(*block.get_by_position(15).column, NULL_ROW), "NULL"); } +TEST_F(NewOrcReaderTest, ReadTimestampNanosecondsRoundsToMicroseconds) { + const auto file_path = (_test_dir / "timestamp_rounding.orc").string(); + write_timestamp_rounding_orc_file(file_path); + auto reader = create_reader_for_path(file_path); + RuntimeState state {TQueryOptions(), TQueryGlobals()}; + state.set_timezone("+00:00"); + ASSERT_TRUE(reader->init(&state).ok()); + + std::vector schema; + ASSERT_TRUE(reader->get_schema(&schema).ok()); + ASSERT_EQ(schema.size(), 2); + + Block block = build_file_block(schema); + auto request = std::make_shared(); + request->non_predicate_columns = {field_projection(0), field_projection(1)}; + ASSERT_TRUE(reader->open(request).ok()); + + size_t rows = 0; + bool eof = false; + ASSERT_TRUE(reader->get_block(&block, &rows, &eof).ok()); + EXPECT_FALSE(eof); + ASSERT_EQ(rows, TIMESTAMP_ROUNDING_ROW_COUNT); + + static constexpr std::array expected { + "1970-01-01 00:00:01.111002", "1970-01-01 00:00:02.345678", + "2021-01-01 00:00:00.000000", "1969-12-31 23:59:58.999999"}; + for (size_t column_id = 0; column_id < schema.size(); ++column_id) { + for (size_t row = 0; row < expected.size(); ++row) { + EXPECT_EQ(schema[column_id].type->to_string(*block.get_by_position(column_id).column, + row), + expected[row]); + } + } +} + +TEST_F(NewOrcReaderTest, TimestampSargMatchesRoundedMicroseconds) { + const auto file_path = (_test_dir / "timestamp_rounding_sarg.orc").string(); + write_timestamp_rounding_orc_file(file_path, 1); + auto reader = create_reader_for_path(file_path); + RuntimeState state {TQueryOptions(), TQueryGlobals()}; + state.set_timezone("+00:00"); + ASSERT_TRUE(reader->init(&state).ok()); + + std::vector schema; + ASSERT_TRUE(reader->get_schema(&schema).ok()); + ASSERT_EQ(schema.size(), 2); + + auto request = std::make_shared(); + request->predicate_columns = {field_projection(0)}; + request->conjuncts.push_back( + VExprContext::create_shared(std::make_shared>( + 0, remove_nullable(schema[0].type), + std::vector {Field::create_field( + make_datetime_v2(1970, 1, 1, 0, 0, 1, 111002))}, + "timestamp_col"))); + ASSERT_TRUE(reader->open(request).ok()); + + Block block = build_file_block({schema[0]}); + size_t rows = 0; + bool eof = false; + ASSERT_TRUE(reader->get_block(&block, &rows, &eof).ok()); + EXPECT_FALSE(eof); + ASSERT_EQ(rows, 1); + EXPECT_EQ(schema[0].type->to_string(*block.get_by_position(0).column, 0), + "1970-01-01 00:00:01.111002"); +} + +TEST_F(NewOrcReaderTest, TimestampSargMillisecondBoundsNeverPruneMatches) { + auto scan_rows = [&](std::string_view suffix, TExprOpcode::type comparison_op, + uint32_t literal_microseconds, bool not_in = false) { + const auto file_path = (_test_dir / fmt::format("timestamp_sarg_{}.orc", suffix)).string(); + // The first stripe rounds 1.111001900 to 1.111002, while the second rounds the same + // fractional part at second 10. Millisecond statistics must never make the SARG stricter + // than Doris's exact microsecond row comparison. + write_two_stripe_constant_timestamp_file(file_path, 1, 10, "GMT", 111001900); + auto reader = create_reader_for_path(file_path); + RuntimeState state {TQueryOptions(), TQueryGlobals()}; + state.set_timezone("+00:00"); + EXPECT_TRUE(reader->init(&state).ok()); + + std::vector schema; + EXPECT_TRUE(reader->get_schema(&schema).ok()); + EXPECT_EQ(schema.size(), 2); + + const auto literal = Field::create_field( + make_datetime_v2(1970, 1, 1, 0, 0, 1, literal_microseconds)); + auto request = std::make_shared(); + request->predicate_columns = {field_projection(0)}; + if (not_in) { + request->conjuncts.push_back( + VExprContext::create_shared(std::make_shared>( + 0, remove_nullable(schema[0].type), std::vector {literal}, + "timestamp_col", true))); + } else { + request->conjuncts.push_back(VExprContext::create_shared( + std::make_shared>( + 0, remove_nullable(schema[0].type), literal, "timestamp_col", false, + comparison_op))); + } + EXPECT_TRUE(reader->open(request).ok()); + + bool eof = false; + size_t result_rows = 0; + while (!eof) { + Block block = build_file_block({schema[0]}); + size_t rows = 0; + EXPECT_TRUE(reader->get_block(&block, &rows, &eof).ok()); + result_rows += rows; + } + return std::pair {result_rows, reader->reader_statistics().filtered_row_groups}; + }; + + EXPECT_EQ(scan_rows("gt", TExprOpcode::GT, 111001).first, 400); + EXPECT_EQ(scan_rows("lt", TExprOpcode::LT, 111003).first, 200); + const auto not_equal = scan_rows("ne", TExprOpcode::NE, 111001); + EXPECT_EQ(not_equal.first, 400); + EXPECT_EQ(not_equal.second, 0); + const auto not_in = scan_rows("not_in", TExprOpcode::INVALID_OPCODE, 111001, true); + EXPECT_EQ(not_in.first, 400); + EXPECT_EQ(not_in.second, 0); +} + +TEST_F(NewOrcReaderTest, NegativeTimestampRoundingBypassesUnsafeSarg) { + const auto file_path = (_test_dir / "negative_timestamp_rounding_sarg.orc").string(); + write_timestamp_rounding_orc_file(file_path, 1, 3); + auto reader = create_reader_for_path(file_path); + RuntimeState state {TQueryOptions(), TQueryGlobals()}; + state.set_timezone("+00:00"); + ASSERT_TRUE(reader->init(&state).ok()); + + std::vector schema; + ASSERT_TRUE(reader->get_schema(&schema).ok()); + ASSERT_EQ(schema.size(), 2); + + auto request = std::make_shared(); + request->predicate_columns = {field_projection(0)}; + request->conjuncts.push_back( + VExprContext::create_shared(std::make_shared>( + 0, remove_nullable(schema[0].type), + std::vector {Field::create_field( + make_datetime_v2(1969, 12, 31, 23, 59, 58, 999999))}, + "timestamp_col"))); + ASSERT_TRUE(reader->open(request).ok()); + + Block block = build_file_block({schema[0]}); + size_t rows = 0; + bool eof = false; + ASSERT_TRUE(reader->get_block(&block, &rows, &eof).ok()); + EXPECT_FALSE(eof); + ASSERT_EQ(rows, 1); + EXPECT_EQ(schema[0].type->to_string(*block.get_by_position(0).column, 0), + "1969-12-31 23:59:58.999999"); + EXPECT_EQ(reader->reader_statistics().filtered_row_groups, 0); +} + +TEST_F(NewOrcReaderTest, NegativeTimestampNotInEpochBypassesUnsafeSarg) { + const auto file_path = (_test_dir / "negative_timestamp_not_in_epoch.orc").string(); + write_timestamp_rounding_orc_file(file_path, 1, 3); + auto reader = create_reader_for_path(file_path); + RuntimeState state {TQueryOptions(), TQueryGlobals()}; + state.set_timezone("+00:00"); + ASSERT_TRUE(reader->init(&state).ok()); + + std::vector schema; + ASSERT_TRUE(reader->get_schema(&schema).ok()); + ASSERT_EQ(schema.size(), 2); + + auto request = std::make_shared(); + request->predicate_columns = {field_projection(0)}; + request->conjuncts.push_back( + VExprContext::create_shared(std::make_shared>( + 0, remove_nullable(schema[0].type), + std::vector { + Field::create_field(make_datetime_v2(1970, 1, 1))}, + "timestamp_col", true))); + ASSERT_TRUE(reader->open(request).ok()); + + Block block = build_file_block({schema[0]}); + size_t rows = 0; + bool eof = false; + ASSERT_TRUE(reader->get_block(&block, &rows, &eof).ok()); + EXPECT_FALSE(eof); + ASSERT_EQ(rows, 1); + EXPECT_EQ(schema[0].type->to_string(*block.get_by_position(0).column, 0), + "1969-12-31 23:59:58.999999"); + EXPECT_EQ(reader->reader_statistics().filtered_row_groups, 0); +} + TEST_F(NewOrcReaderTest, ReadHive11DecimalUsesBatchScale) { const auto file_path = find_repo_file( "contrib/apache-orc/java/core/src/test/resources/orc-file-11-format.orc"); diff --git a/be/test/format_v2/parquet/parquet_leaf_reader_test.cpp b/be/test/format_v2/parquet/parquet_leaf_reader_test.cpp index 0d0f9a2f8567cc..38c080b7624410 100644 --- a/be/test/format_v2/parquet/parquet_leaf_reader_test.cpp +++ b/be/test/format_v2/parquet/parquet_leaf_reader_test.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -76,7 +77,8 @@ struct CapturedDecodedView { ParquetLeafReader make_spy_leaf_reader(ParquetTypeDescriptor descriptor, DataTypePtr type, CapturedDecodedView* captured, const cctz::time_zone* timezone = nullptr, - bool enable_strict_mode = false) { + bool enable_strict_mode = false, + const cctz::time_zone* int96_timezone = nullptr) { auto appender = [captured](MutableColumnPtr&, const DecodedColumnView& view) { captured->value_kind = view.value_kind; captured->time_unit = view.time_unit; @@ -117,7 +119,7 @@ ParquetLeafReader make_spy_leaf_reader(ParquetTypeDescriptor descriptor, DataTyp return Status::OK(); }; return ParquetLeafReader(nullptr, descriptor, std::move(type), "leaf", nullptr, {}, timezone, - enable_strict_mode, std::move(appender)); + enable_strict_mode, std::move(appender), int96_timezone); } } // namespace @@ -354,6 +356,34 @@ TEST(ParquetLeafReaderTest, DecodedColumnViewCarriesDescriptorSessionAndNullMapF EXPECT_TRUE(captured.null_map_is_null); } +TEST(ParquetLeafReaderTest, Int96UsesOnlyExplicitHiveParquetTimezone) { + ParquetTypeDescriptor descriptor; + descriptor.physical_type = ::parquet::Type::INT96; + auto type = std::make_shared(); + cctz::time_zone session_timezone; + cctz::time_zone hive_parquet_timezone; + ASSERT_TRUE(cctz::load_time_zone("America/Los_Angeles", &session_timezone)); + ASSERT_TRUE(cctz::load_time_zone("Asia/Shanghai", &hive_parquet_timezone)); + + CapturedDecodedView captured; + auto reader = make_spy_leaf_reader(descriptor, type, &captured, &session_timezone, false, + &hive_parquet_timezone); + const std::array int96_value {}; + ParquetLeafBatch batch; + batch._value_kind = DecodedValueKind::INT96; + batch._fixed_values = int96_value.data(); + batch._values_written = 1; + auto column = type->create_column(); + + ASSERT_TRUE(reader.append_values(batch, 1, nullptr, column).ok()); + EXPECT_EQ(captured.timezone, &hive_parquet_timezone); + + captured.timezone = &session_timezone; + auto default_reader = make_spy_leaf_reader(descriptor, type, &captured, &session_timezone); + ASSERT_TRUE(default_reader.append_values(batch, 1, nullptr, column).ok()); + EXPECT_EQ(captured.timezone, nullptr); +} + TEST(ParquetLeafReaderTest, DecodedColumnViewCapturesBinaryFixedLengthAndFloat16Override) { ParquetTypeDescriptor binary_descriptor; binary_descriptor.physical_type = ::parquet::Type::FIXED_LEN_BYTE_ARRAY; diff --git a/be/test/format_v2/parquet/parquet_reader_test.cpp b/be/test/format_v2/parquet/parquet_reader_test.cpp index c5bf251c1553e2..67ab90a5cbc69d 100644 --- a/be/test/format_v2/parquet/parquet_reader_test.cpp +++ b/be/test/format_v2/parquet/parquet_reader_test.cpp @@ -37,10 +37,12 @@ #include "core/assert_cast.h" #include "core/block/block.h" +#include "core/column/column_array.h" #include "core/column/column_nullable.h" #include "core/column/column_string.h" #include "core/column/column_vector.h" #include "core/data_type/data_type_array.h" +#include "core/data_type/data_type_date_or_datetime_v2.h" #include "core/data_type/data_type_map.h" #include "core/data_type/data_type_nullable.h" #include "core/data_type/data_type_number.h" @@ -66,6 +68,7 @@ #include "storage/index/zone_map/zonemap_filter_result.h" #include "storage/segment/condition_cache.h" #include "storage/utils.h" +#include "util/timezone_utils.h" namespace doris { namespace { @@ -728,6 +731,37 @@ void write_int96_timestamp_parquet_file(const std::string& file_path) { arrow_builder.build())); } +void write_nested_int96_timestamp_parquet_file(const std::string& file_path) { + auto timestamp_type = arrow::timestamp(arrow::TimeUnit::MICRO); + auto value_builder = + std::make_shared(timestamp_type, arrow::default_memory_pool()); + arrow::ListBuilder list_builder(arrow::default_memory_pool(), value_builder, + arrow::list(arrow::field("element", timestamp_type, true))); + + ASSERT_TRUE(list_builder.Append().ok()); + ASSERT_TRUE(value_builder->Append(1735660800000000LL).ok()); + ASSERT_TRUE(value_builder->Append(1735660800123456LL).ok()); + ASSERT_TRUE(list_builder.Append().ok()); + ASSERT_TRUE(value_builder->Append(1735689600000000LL).ok()); + std::shared_ptr array; + ASSERT_TRUE(list_builder.Finish(&array).ok()); + auto table = arrow::Table::Make( + arrow::schema({arrow::field("timestamps", array->type(), true)}), {array}); + + auto file_result = arrow::io::FileOutputStream::Open(file_path); + ASSERT_TRUE(file_result.ok()) << file_result.status(); + std::shared_ptr out = *file_result; + ::parquet::WriterProperties::Builder writer_builder; + writer_builder.version(::parquet::ParquetVersion::PARQUET_2_6); + writer_builder.data_page_version(::parquet::ParquetDataPageVersion::V2); + writer_builder.compression(::parquet::Compression::UNCOMPRESSED); + ::parquet::ArrowWriterProperties::Builder arrow_builder; + arrow_builder.enable_force_write_int96_timestamps(); + PARQUET_THROW_NOT_OK(::parquet::arrow::WriteTable(*table, arrow::default_memory_pool(), out, + ROW_COUNT, writer_builder.build(), + arrow_builder.build())); +} + void write_int_pair_parquet_file(const std::string& file_path, int64_t row_group_size = ROW_COUNT) { auto schema = arrow::schema({ arrow::field("id", arrow::int32(), false), @@ -1136,7 +1170,7 @@ class NewParquetReaderTest : public testing::Test { RuntimeProfile* profile = nullptr, bool enable_mapping_timestamp_tz = false, std::shared_ptr io_ctx = nullptr, std::optional global_rowid_context = std::nullopt, - bool is_immutable = false) const { + bool is_immutable = false, std::string hive_parquet_time_zone = "") const { auto system_properties = std::make_shared(); system_properties->system_type = TFileType::FILE_LOCAL; auto file_description = std::make_unique(); @@ -1147,7 +1181,8 @@ class NewParquetReaderTest : public testing::Test { file_description->is_immutable = is_immutable; return std::make_unique( system_properties, file_description, std::move(io_ctx), profile, - global_rowid_context, enable_mapping_timestamp_tz); + global_rowid_context, enable_mapping_timestamp_tz, + std::move(hive_parquet_time_zone)); } std::filesystem::path _test_dir; @@ -1312,6 +1347,103 @@ TEST_F(NewParquetReaderTest, GetSchemaMapsInt96ToTimestampTzWhenTimestampTzMappi EXPECT_EQ(remove_nullable(schema[0].type)->get_scale(), 6); } +TEST_F(NewParquetReaderTest, Int96TimezoneUsesCatalogPropertyInsteadOfSessionTimezone) { + TimezoneUtils::load_timezones_to_cache(); + write_int96_timestamp_parquet_file(_file_path); + + auto read_first_value = [&](const std::string& hive_parquet_time_zone, + bool enable_mapping_timestamp_tz = false) { + auto reader = create_reader(0, -1, nullptr, enable_mapping_timestamp_tz, nullptr, + std::nullopt, false, hive_parquet_time_zone); + RuntimeState state {TQueryOptions(), TQueryGlobals()}; + // A session timezone must never implicitly opt an INT96 column into legacy conversion. + state.set_timezone("America/Los_Angeles"); + auto status = reader->init(&state); + if (!status.ok()) { + ADD_FAILURE() << status; + return std::string {}; + } + std::vector schema; + status = reader->get_schema(&schema); + if (!status.ok()) { + ADD_FAILURE() << status; + return std::string {}; + } + auto request = std::make_shared(); + request->non_predicate_columns = {field_projection(0)}; + status = reader->open(request); + if (!status.ok()) { + ADD_FAILURE() << status; + return std::string {}; + } + Block block = build_file_block(schema); + size_t rows = 0; + bool eof = false; + status = reader->get_block(&block, &rows, &eof); + if (!status.ok()) { + ADD_FAILURE() << status; + return std::string {}; + } + if (rows != 3) { + ADD_FAILURE() << "Expected 3 rows, got " << rows; + return std::string {}; + } + return block.get_by_position(0).type->to_string(*block.get_by_position(0).column, 0); + }; + + // A Trino/UTC-style file stores the wall clock 2024-12-31 16:00 directly. With the property + // absent, Doris preserves it even though the SQL session is America/Los_Angeles. + EXPECT_EQ(read_first_value(""), "2024-12-31 16:00:00.000000"); + // A legacy Hive writer configured for Asia/Shanghai can normalize local 2025-01-01 00:00 to + // raw INT96 2024-12-31 16:00. The matching catalog property reverses that normalization. + EXPECT_EQ(read_first_value("Asia/Shanghai"), "2025-01-01 00:00:00.000000"); + // TIMESTAMPTZ preserves the instant even when the INT96 compatibility timezone is configured. + EXPECT_EQ(read_first_value("Asia/Shanghai", true), "2024-12-31 16:00:00.000000+00:00"); +} + +TEST_F(NewParquetReaderTest, NestedInt96UsesHiveParquetTimezone) { + TimezoneUtils::load_timezones_to_cache(); + write_nested_int96_timestamp_parquet_file(_file_path); + auto reader = + create_reader(0, -1, nullptr, false, nullptr, std::nullopt, false, "Asia/Shanghai"); + RuntimeState state {TQueryOptions(), TQueryGlobals()}; + state.set_timezone("America/Los_Angeles"); + ASSERT_TRUE(reader->init(&state).ok()); + + std::vector schema; + ASSERT_TRUE(reader->get_schema(&schema).ok()); + ASSERT_EQ(schema.size(), 1); + auto request = std::make_shared(); + request->non_predicate_columns = {field_projection(0)}; + ASSERT_TRUE(reader->open(request).ok()); + + Block block = build_file_block(schema); + size_t rows = 0; + bool eof = false; + ASSERT_TRUE(reader->get_block(&block, &rows, &eof).ok()); + ASSERT_EQ(rows, 2); + const auto& arrays = nullable_nested_column(block, 0); + ASSERT_EQ(arrays.get_offsets(), ColumnArray::Offsets64({2, 3})); + const auto& nullable_elements = assert_cast(arrays.get_data()); + const auto& timestamps = + assert_cast(nullable_elements.get_nested_column()); + const auto* array_type = + assert_cast(remove_nullable(schema[0].type).get()); + const auto element_type = remove_nullable(array_type->get_nested_type()); + EXPECT_EQ(element_type->to_string(timestamps, 0), "2025-01-01 00:00:00.000000"); + EXPECT_EQ(element_type->to_string(timestamps, 1), "2025-01-01 00:00:00.123456"); + EXPECT_EQ(element_type->to_string(timestamps, 2), "2025-01-01 08:00:00.000000"); +} + +TEST_F(NewParquetReaderTest, RejectsInvalidHiveParquetTimezone) { + auto reader = + create_reader(0, -1, nullptr, false, nullptr, std::nullopt, false, "Not/A_Timezone"); + RuntimeState state {TQueryOptions(), TQueryGlobals()}; + auto status = reader->init(&state); + EXPECT_FALSE(status.ok()); + EXPECT_NE(status.to_string().find("Invalid hive.parquet.time-zone"), std::string::npos); +} + TEST_F(NewParquetReaderTest, ReadSingleRowGroupThenEof) { auto reader = create_reader(); RuntimeState state {TQueryOptions(), TQueryGlobals()}; diff --git a/be/test/format_v2/parquet/parquet_serde_reader_test.cpp b/be/test/format_v2/parquet/parquet_serde_reader_test.cpp index c35138e3263723..96b7fbeed0dade 100644 --- a/be/test/format_v2/parquet/parquet_serde_reader_test.cpp +++ b/be/test/format_v2/parquet/parquet_serde_reader_test.cpp @@ -17,10 +17,12 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -37,6 +39,7 @@ #include "core/column/column_vector.h" #include "core/data_type/data_type.h" #include "core/data_type/data_type_nullable.h" +#include "core/data_type/data_type_timestamptz.h" #include "core/types.h" #include "format_v2/parquet/parquet_column_schema.h" #include "format_v2/parquet/reader/column_reader.h" @@ -146,13 +149,17 @@ class ParquetSerdeReaderTest : public testing::Test { } void write_table(const std::string& file_path, const std::shared_ptr& table, - std::shared_ptr<::parquet::ArrowWriterProperties> arrow_properties = nullptr) { + std::shared_ptr<::parquet::ArrowWriterProperties> arrow_properties = nullptr, + bool enable_dictionary = true) { auto file_result = arrow::io::FileOutputStream::Open(file_path); ASSERT_TRUE(file_result.ok()) << file_result.status(); ::parquet::WriterProperties::Builder writer_builder; writer_builder.version(::parquet::ParquetVersion::PARQUET_2_6); writer_builder.data_page_version(::parquet::ParquetDataPageVersion::V2); writer_builder.compression(::parquet::Compression::UNCOMPRESSED); + if (!enable_dictionary) { + writer_builder.disable_dictionary(); + } if (arrow_properties == nullptr) { ::parquet::ArrowWriterProperties::Builder arrow_builder; arrow_properties = arrow_builder.build(); @@ -238,14 +245,42 @@ class ParquetSerdeReaderTest : public testing::Test { return _fields.size(); } - std::unique_ptr create_reader(size_t field_idx) const { - ParquetColumnReaderFactory factory(_row_group, _file_reader->metadata()->num_columns()); + std::unique_ptr create_reader( + size_t field_idx, const cctz::time_zone* int96_timezone = nullptr) const { + ParquetColumnReaderFactory factory(_row_group, _file_reader->metadata()->num_columns(), + nullptr, {}, nullptr, false, {}, int96_timezone); std::unique_ptr reader; auto st = factory.create(*_fields[field_idx], &reader); EXPECT_TRUE(st.ok()) << st; return reader; } + void write_int96_timestamp_file(const std::string& file_path, bool enable_dictionary) { + auto field = arrow::field("col_datetime", arrow::timestamp(arrow::TimeUnit::MICRO), false); + auto array = build_timestamp_array( + arrow::timestamp(arrow::TimeUnit::MICRO), + {0, 1234567, 1609459200000000, 1615714200000000, 1615717800000000}); + auto table = arrow::Table::Make(arrow::schema({field}), {array}); + + ::parquet::ArrowWriterProperties::Builder arrow_builder; + arrow_builder.enable_force_write_int96_timestamps(); + write_table(file_path, table, arrow_builder.build(), enable_dictionary); + } + + void expect_int96_timestamp_strings(const cctz::time_zone* int96_timezone, + const std::vector& expected) const { + ASSERT_EQ(expected.size(), ROW_COUNT); + auto reader = create_reader(0, int96_timezone); + ASSERT_NE(reader, nullptr); + auto column = _fields[0]->type->create_column(); + int64_t rows_read = 0; + ASSERT_TRUE(reader->read(ROW_COUNT, column, &rows_read).ok()); + ASSERT_EQ(rows_read, ROW_COUNT); + for (int64_t row = 0; row < ROW_COUNT; ++row) { + EXPECT_EQ(_fields[0]->type->to_string(*column, row), expected[row]); + } + } + template void read_and_validate(const std::string& name, Validator validator) const { const auto field_idx = find_field_idx(name); @@ -422,37 +457,75 @@ TEST_F(ParquetSerdeReaderTest, ReadAllSupportedPhysicalAndLogicalTypes) { }); } -TEST_F(ParquetSerdeReaderTest, ReadInt96TimestampAsDateTimeV2) { - const auto file_path = (_test_dir / "int96_timestamp.parquet").string(); - auto field = arrow::field("col_datetime", arrow::timestamp(arrow::TimeUnit::MICRO), false); - auto array = build_timestamp_array(arrow::timestamp(arrow::TimeUnit::MICRO), - {0, 1234567, 1609459200000000, 1609459201000000, -1}); - auto table = arrow::Table::Make(arrow::schema({field}), {array}); - - ::parquet::ArrowWriterProperties::Builder arrow_builder; - arrow_builder.enable_force_write_int96_timestamps(); - _fields.clear(); - _file_reader.reset(); - _row_group.reset(); - write_table(file_path, table, arrow_builder.build()); - open_file(file_path); - - ASSERT_EQ(_fields.size(), 1); - EXPECT_EQ(_fields[0]->type_descriptor.physical_type, ::parquet::Type::INT96); - EXPECT_EQ(_fields[0]->type_descriptor.extra_type_info, ParquetExtraTypeInfo::IMPALA_TIMESTAMP); - ASSERT_TRUE(supports_record_reader(_fields[0]->type_descriptor)); - ASSERT_EQ(remove_nullable(_fields[0]->type)->get_primitive_type(), TYPE_DATETIMEV2); - - auto reader = create_reader(0); - ASSERT_NE(reader, nullptr); - auto column = _fields[0]->type->create_column(); - int64_t rows_read = 0; - ASSERT_TRUE(reader->read(ROW_COUNT, column, &rows_read).ok()); - ASSERT_EQ(rows_read, ROW_COUNT); - EXPECT_EQ(_fields[0]->type->to_string(*column, 0), "1970-01-01 00:00:00.000000"); - EXPECT_EQ(_fields[0]->type->to_string(*column, 1), "1970-01-01 00:00:01.234567"); - EXPECT_EQ(_fields[0]->type->to_string(*column, 2), "2021-01-01 00:00:00.000000"); - EXPECT_EQ(_fields[0]->type->to_string(*column, 4), "1969-12-31 23:59:59.999999"); +TEST_F(ParquetSerdeReaderTest, ReadInt96TimestampUsesConfiguredParquetTimezoneLikeTrino) { + cctz::time_zone shanghai; + cctz::time_zone los_angeles; + ASSERT_TRUE(cctz::load_time_zone("Asia/Shanghai", &shanghai)); + ASSERT_TRUE(cctz::load_time_zone("America/Los_Angeles", &los_angeles)); + + for (const bool enable_dictionary : {false, true}) { + const auto file_path = + (_test_dir / (enable_dictionary ? "int96_dict.parquet" : "int96_plain.parquet")) + .string(); + write_int96_timestamp_file(file_path, enable_dictionary); + _fields.clear(); + _file_reader.reset(); + _row_group.reset(); + open_file(file_path); + + ASSERT_EQ(_fields.size(), 1); + EXPECT_EQ(_fields[0]->type_descriptor.physical_type, ::parquet::Type::INT96); + EXPECT_EQ(_fields[0]->type_descriptor.extra_type_info, + ParquetExtraTypeInfo::IMPALA_TIMESTAMP); + ASSERT_TRUE(supports_record_reader(_fields[0]->type_descriptor)); + ASSERT_EQ(remove_nullable(_fields[0]->type)->get_primitive_type(), TYPE_DATETIMEV2); + const auto encodings = _file_reader->metadata()->RowGroup(0)->ColumnChunk(0)->encodings(); + const bool has_dictionary = + std::find(encodings.begin(), encodings.end(), + ::parquet::Encoding::RLE_DICTIONARY) != encodings.end() || + std::find(encodings.begin(), encodings.end(), + ::parquet::Encoding::PLAIN_DICTIONARY) != encodings.end(); + EXPECT_EQ(has_dictionary, enable_dictionary); + + // The default disables INT96 timezone conversion, so the raw wall-clock value is stable + // regardless of the Doris session timezone. + expect_int96_timestamp_strings(nullptr, + {"1970-01-01 00:00:00.000000", "1970-01-01 00:00:01.234567", + "2021-01-01 00:00:00.000000", "2021-03-14 09:30:00.000000", + "2021-03-14 10:30:00.000000"}); + expect_int96_timestamp_strings(&shanghai, + {"1970-01-01 08:00:00.000000", "1970-01-01 08:00:01.234567", + "2021-01-01 08:00:00.000000", "2021-03-14 17:30:00.000000", + "2021-03-14 18:30:00.000000"}); + // These two UTC instants straddle the 2021 spring-forward transition and verify that the + // configured zone applies its DST rules rather than a fixed offset. + expect_int96_timestamp_strings(&los_angeles, + {"1969-12-31 16:00:00.000000", "1969-12-31 16:00:01.234567", + "2020-12-31 16:00:00.000000", "2021-03-14 01:30:00.000000", + "2021-03-14 03:30:00.000000"}); + + // INT96 is mapped to TIMESTAMPTZ when the scan enables timestamp-with-time-zone mapping. + // Passing a non-UTC reader timezone must not change its instant; the timezone only affects + // how that instant is rendered later. + auto timestamp_tz_type = std::make_shared(6); + _fields[0]->type = timestamp_tz_type; + _fields[0]->type_descriptor.doris_type = timestamp_tz_type; + auto timestamp_tz_reader = create_reader(0, &shanghai); + ASSERT_NE(timestamp_tz_reader, nullptr); + auto timestamp_tz_column = timestamp_tz_type->create_column(); + int64_t rows_read = 0; + ASSERT_TRUE(timestamp_tz_reader->read(ROW_COUNT, timestamp_tz_column, &rows_read).ok()); + ASSERT_EQ(rows_read, ROW_COUNT); + const auto& timestamp_tz_values = + assert_cast(*timestamp_tz_column); + const auto utc = cctz::utc_time_zone(); + EXPECT_EQ(timestamp_tz_values.get_element(0).to_string(utc, 6), + "1970-01-01 00:00:00.000000+00:00"); + EXPECT_EQ(timestamp_tz_values.get_element(1).to_string(utc, 6), + "1970-01-01 00:00:01.234567+00:00"); + EXPECT_EQ(timestamp_tz_values.get_element(3).to_string(shanghai, 6), + "2021-03-14 17:30:00.000000+08:00"); + } } } // namespace diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/FileFormatConstants.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/FileFormatConstants.java index 774ee4e6e838f6..6245983b3d4e22 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/util/FileFormatConstants.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/FileFormatConstants.java @@ -50,6 +50,7 @@ public class FileFormatConstants { public static final String PROP_ENCLOSE = "enclose"; public static final String PROP_ENABLE_MAPPING_VARBINARY = "enable_mapping_varbinary"; public static final String PROP_ENABLE_MAPPING_TIMESTAMP_TZ = "enable_mapping_timestamp_tz"; + public static final String PROP_HIVE_PARQUET_TIME_ZONE = "hive.parquet.time-zone"; // decimal(p,s) public static final Pattern DECIMAL_TYPE_PATTERN = Pattern.compile("decimal\\((\\d+),(\\d+)\\)"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/FileFormatUtils.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/FileFormatUtils.java index 15240f103b0e51..d9e9efb0ed3e2f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/util/FileFormatUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/FileFormatUtils.java @@ -21,16 +21,47 @@ import org.apache.doris.catalog.PrimitiveType; import org.apache.doris.catalog.ScalarType; import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.DdlException; import org.apache.doris.common.FeNameFormat; import com.google.common.base.Strings; +import java.time.DateTimeException; +import java.time.ZoneId; import java.util.List; +import java.util.Locale; import java.util.Optional; import java.util.regex.Matcher; public class FileFormatUtils { + public static String parseHiveParquetTimeZone(String value) throws DdlException { + String timeZone = value.trim(); + if (timeZone.isEmpty()) { + return ""; + } + + try { + String upperCaseTimeZone = timeZone.toUpperCase(Locale.ROOT); + boolean isUtcOrGmt = upperCaseTimeZone.equals("UTC") || upperCaseTimeZone.equals("GMT"); + boolean isShortAlias = ZoneId.SHORT_IDS.containsKey(upperCaseTimeZone) + || upperCaseTimeZone.equals("CST") || upperCaseTimeZone.equals("PRC"); + if (!isUtcOrGmt && isShortAlias) { + throw new DateTimeException("Ambiguous short timezone aliases are not supported"); + } + String standardizedTimeZone = TimeUtils.checkTimeZoneValidAndStandardize(timeZone); + if ((standardizedTimeZone.startsWith("UTC") || standardizedTimeZone.startsWith("GMT")) + && standardizedTimeZone.length() > 3) { + TimeUtils.checkTimeZoneValidAndStandardize(standardizedTimeZone.substring(3)); + } + return ZoneId.of(standardizedTimeZone).getId(); + } catch (DdlException | DateTimeException e) { + throw new DdlException("The parameter " + FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE + + " must be an IANA timezone or UTC offset in the range -12:00 to +14:00; " + + "short timezone aliases are not supported, value is " + timeZone, e); + } + } + public static boolean isCsv(String formatStr) { return FileFormatConstants.FORMAT_CSV.equalsIgnoreCase(formatStr) || FileFormatConstants.FORMAT_CSV_WITH_NAMES.equalsIgnoreCase(formatStr) diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalTable.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalTable.java index 24de55133be39c..926080174654ec 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalTable.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalTable.java @@ -26,6 +26,7 @@ import org.apache.doris.catalog.TableIndexes; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.Pair; +import org.apache.doris.common.UserException; import org.apache.doris.common.io.Text; import org.apache.doris.common.io.Writable; import org.apache.doris.common.util.PropertyAnalyzer; @@ -230,6 +231,10 @@ public String getMetaCacheEngine() { return "default"; } + public String getHiveParquetTimeZone() throws UserException { + return ""; + } + @Override public String getMysqlType() { return getType().toMysqlType(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/FileQueryScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/FileQueryScanNode.java index 55da4f30ad7043..7ae158f399e063 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/FileQueryScanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/FileQueryScanNode.java @@ -45,6 +45,7 @@ import org.apache.doris.spi.Split; import org.apache.doris.system.Backend; import org.apache.doris.tablefunction.ExternalFileTableValuedFunction; +import org.apache.doris.tablefunction.TableValuedFunctionIf; import org.apache.doris.thrift.TColumnCategory; import org.apache.doris.thrift.TExternalScanRange; import org.apache.doris.thrift.TFileAttributes; @@ -191,6 +192,10 @@ protected void initSchemaParams() throws UserException { // Set enable_mapping_varbinary from catalog or TVF params.setEnableMappingVarbinary(getEnableMappingVarbinary()); params.setEnableMappingTimestampTz(getEnableMappingTimestampTz()); + String hiveParquetTimeZone = getHiveParquetTimeZone(); + if (!hiveParquetTimeZone.isEmpty()) { + params.setHiveParquetTimeZone(hiveParquetTimeZone); + } } private void updateRequiredSlots() throws UserException { @@ -677,6 +682,19 @@ protected boolean getEnableMappingTimestampTz() { return false; } + protected String getHiveParquetTimeZone() throws UserException { + TableIf table = getTargetTable(); + if (table instanceof ExternalTable) { + return ((ExternalTable) table).getHiveParquetTimeZone(); + } + if (table instanceof FunctionGenTable) { + FunctionGenTable functionGenTable = (FunctionGenTable) table; + TableValuedFunctionIf tvf = functionGenTable.getTvf(); + return tvf.getHiveParquetTimeZone(); + } + return ""; + } + protected abstract List getPathPartitionKeys() throws UserException; protected abstract TableIf getTargetTable() throws UserException; diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalCatalog.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalCatalog.java index e4157cf72ddadf..3df91cd29bddca 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalCatalog.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalCatalog.java @@ -20,6 +20,8 @@ import org.apache.doris.catalog.Env; import org.apache.doris.common.DdlException; import org.apache.doris.common.ThreadPoolManager; +import org.apache.doris.common.util.FileFormatConstants; +import org.apache.doris.common.util.FileFormatUtils; import org.apache.doris.common.util.Util; import org.apache.doris.datasource.CatalogProperty; import org.apache.doris.datasource.ExternalCatalog; @@ -65,7 +67,6 @@ public class HMSExternalCatalog extends ExternalCatalog { // But notice that if set to true, the default value of column will be ignored because we cannot get default value // from remoteTable object. public static final String GET_SCHEMA_FROM_TABLE = "get_schema_from_table"; - private static final int FILE_SYSTEM_EXECUTOR_THREAD_NUM = 16; private ThreadPoolExecutor fileSystemExecutor; private SpiSwitchingFileSystem spiFileSystem; @@ -123,9 +124,24 @@ public void checkProperties() throws DdlException { throw new DdlException( "The parameter " + PARTITION_CACHE_TTL_SECOND + " is wrong, value is " + partitionCacheTtlSecond); } + + getHiveParquetTimeZone(); catalogProperty.checkMetaStoreAndStorageProperties(AbstractHiveProperties.class); } + /** + * Timezone used to reverse legacy Parquet INT96 writer normalization. This intentionally + * follows Trino's hive.parquet.time-zone catalog property instead of the SQL session timezone. + * An empty value keeps INT96 wall-clock fields unchanged. A configured value applies to Hive + * and Hudi Parquet files in this catalog because Parquet metadata cannot reliably identify the + * writer's timezone convention. Iceberg timestamp semantics are defined by its table format + * and intentionally ignore this property. + */ + public String getHiveParquetTimeZone() throws DdlException { + return FileFormatUtils.parseHiveParquetTimeZone(catalogProperty.getOrDefault( + FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE, "")); + } + @Override protected synchronized void initPreExecutionAuthenticator() { if (executionAuthenticator == null) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalTable.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalTable.java index e1311237a603d5..23ec991acbb104 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalTable.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalTable.java @@ -579,6 +579,14 @@ public DLAType getDlaType() { return dlaType; } + @Override + public String getHiveParquetTimeZone() throws UserException { + if (getDlaType() == DLAType.ICEBERG) { + return ""; + } + return ((HMSExternalCatalog) getCatalog()).getHiveParquetTimeZone(); + } + @Override public TTableDescriptor toThrift() { List schema = getFullSchema(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/fileformat/ParquetFileFormatProperties.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/fileformat/ParquetFileFormatProperties.java index 9c4d5f2ae494fd..e30a2eec602b80 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/fileformat/ParquetFileFormatProperties.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/fileformat/ParquetFileFormatProperties.java @@ -61,7 +61,7 @@ public class ParquetFileFormatProperties extends FileFormatProperties { private TParquetCompressionType parquetCompressionType = TParquetCompressionType.SNAPPY; private boolean parquetDisableDictionary = false; private TParquetVersion parquetVersion = TParquetVersion.PARQUET_1_0; - private boolean enableInt96Timestamps = true; + private boolean enableInt96Timestamps = false; public ParquetFileFormatProperties() { super(TFileFormatType.FORMAT_PARQUET, FileFormatProperties.FORMAT_PARQUET); @@ -86,7 +86,7 @@ public void analyzeFileFormatProperties(Map formatProperties, bo //save the enable int96 timestamp property if (formatProperties.containsKey(ENABLE_INT96_TIMESTAMPS)) { - this.enableInt96Timestamps = Boolean.valueOf(formatProperties.get(ENABLE_INT96_TIMESTAMPS)).booleanValue(); + this.enableInt96Timestamps = parseEnableInt96Timestamps(formatProperties.get(ENABLE_INT96_TIMESTAMPS)); } // save all parquet prefix property @@ -110,6 +110,16 @@ public void analyzeFileFormatProperties(Map formatProperties, bo } } + public static boolean parseEnableInt96Timestamps(String value) { + if ("true".equalsIgnoreCase(value)) { + return true; + } + if ("false".equalsIgnoreCase(value)) { + return false; + } + throw new AnalysisException(ENABLE_INT96_TIMESTAMPS + + " should be true or false, but is " + value); + } @Override public void fullTResultFileSinkOptions(TResultFileSinkOptions sinkOptions) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/load/ExportJob.java b/fe/fe-core/src/main/java/org/apache/doris/load/ExportJob.java index e286bb3e3bacb2..4b311f9319d7e1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/load/ExportJob.java +++ b/fe/fe-core/src/main/java/org/apache/doris/load/ExportJob.java @@ -38,6 +38,7 @@ import org.apache.doris.common.io.Writable; import org.apache.doris.common.util.TimeUtils; import org.apache.doris.datasource.InternalCatalog; +import org.apache.doris.datasource.property.fileformat.ParquetFileFormatProperties; import org.apache.doris.nereids.StatementContext; import org.apache.doris.nereids.analyzer.UnboundRelation; import org.apache.doris.nereids.analyzer.UnboundSlot; @@ -123,6 +124,8 @@ public class ExportJob implements Writable { private String columns; @SerializedName("format") private String format; + @SerializedName("enableInt96Timestamps") + private String enableInt96Timestamps; @SerializedName("timeoutSecond") private int timeoutSecond; @SerializedName("maxFileSize") @@ -484,6 +487,11 @@ private Map convertOutfileProperties() { outfileProperties.put(ExportCommand.COMPRESS_TYPE, compressType); } + if (enableInt96Timestamps != null) { + outfileProperties.put(ParquetFileFormatProperties.ENABLE_INT96_TIMESTAMPS, + enableInt96Timestamps); + } + if (!maxFileSize.isEmpty()) { outfileProperties.put(OutFileClause.PROP_MAX_FILE_SIZE, maxFileSize); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ExportCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ExportCommand.java index 3fadf9bc05aba4..19663686f636d4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ExportCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ExportCommand.java @@ -38,6 +38,7 @@ import org.apache.doris.common.util.PropertyAnalyzer; import org.apache.doris.datasource.CatalogIf; import org.apache.doris.datasource.InternalCatalog; +import org.apache.doris.datasource.property.fileformat.ParquetFileFormatProperties; import org.apache.doris.load.ExportJob; import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.nereids.exceptions.AnalysisException; @@ -92,6 +93,7 @@ public class ExportCommand extends Command implements NeedAuditEncryption, Forwa .add(PropertyAnalyzer.PROPERTIES_LINE_DELIMITER) .add(PropertyAnalyzer.PROPERTIES_TIMEOUT) .add("format") + .add(ParquetFileFormatProperties.ENABLE_INT96_TIMESTAMPS) .add(OutFileClause.PROP_WITH_BOM) .add(COMPRESS_TYPE) .build(); @@ -291,6 +293,12 @@ private ExportJob generateExportJob(ConnectContext ctx, Map file exportJob.setFormat(fileProperties.getOrDefault(LoadCommand.KEY_IN_PARAM_FORMAT_TYPE, "csv") .toLowerCase()); + String enableInt96Timestamps = fileProperties.get(ParquetFileFormatProperties.ENABLE_INT96_TIMESTAMPS); + if (enableInt96Timestamps != null) { + ParquetFileFormatProperties.parseEnableInt96Timestamps(enableInt96Timestamps); + } + exportJob.setEnableInt96Timestamps(enableInt96Timestamps); + // set withBom exportJob.setWithBom(fileProperties.getOrDefault(OutFileClause.PROP_WITH_BOM, "false")); @@ -431,4 +439,3 @@ public String toDigest() { return sb.toString(); } } - diff --git a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/ExternalFileTableValuedFunction.java b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/ExternalFileTableValuedFunction.java index 6c7962e7267033..8304e19c8b5948 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/ExternalFileTableValuedFunction.java +++ b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/ExternalFileTableValuedFunction.java @@ -34,6 +34,7 @@ import org.apache.doris.catalog.VariantType; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.Config; +import org.apache.doris.common.DdlException; import org.apache.doris.common.ErrorCode; import org.apache.doris.common.Pair; import org.apache.doris.common.UserException; @@ -131,6 +132,7 @@ public abstract class ExternalFileTableValuedFunction extends TableValuedFunctio protected Optional resourceName = Optional.empty(); public FileFormatProperties fileFormatProperties; + private String hiveParquetTimeZone = ""; private long tableId; public abstract TFileType getTFileType(); @@ -224,6 +226,14 @@ protected Map parseCommonProperties(Map properti FileFormatConstants.PROP_ENABLE_MAPPING_TIMESTAMP_TZ, "false"); fileFormatProperties.enableMappingTimestampTz = Boolean.parseBoolean(enableMappingTimestampTzStr); + String hiveParquetTimeZone = getOrDefaultAndRemove(copiedProps, + FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE, ""); + try { + this.hiveParquetTimeZone = FileFormatUtils.parseHiveParquetTimeZone(hiveParquetTimeZone); + } catch (DdlException e) { + throw new AnalysisException(e.getMessage(), e); + } + fileFormatProperties.analyzeFileFormatProperties(copiedProps, true); if (fileFormatProperties instanceof CsvFileFormatProperties @@ -255,6 +265,11 @@ public List getFileStatuses() { return fileStatuses; } + @Override + public String getHiveParquetTimeZone() { + return hiveParquetTimeZone; + } + public TFileAttributes getFileAttributes() { return fileFormatProperties.toTFileAttributes(); } @@ -478,6 +493,10 @@ private PFetchTableSchemaRequest getFetchTableStructureRequest() throws TExcepti // table function fetch schema, whether to enable mapping varbinary fileScanRangeParams.setEnableMappingVarbinary(fileFormatProperties.enableMappingVarbinary); fileScanRangeParams.setEnableMappingTimestampTz(fileFormatProperties.enableMappingTimestampTz); + String hiveParquetTimeZone = getHiveParquetTimeZone(); + if (!hiveParquetTimeZone.isEmpty()) { + fileScanRangeParams.setHiveParquetTimeZone(hiveParquetTimeZone); + } if (getTFileType() == TFileType.FILE_STREAM) { fileStatuses.add(new TBrokerFileStatus("", false, -1, true)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FileTableValuedFunction.java b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FileTableValuedFunction.java index 2cb5bedb4463ce..03d260c9f861f5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FileTableValuedFunction.java +++ b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FileTableValuedFunction.java @@ -109,6 +109,11 @@ public TFileAttributes getFileAttributes() { return delegateTvf.getFileAttributes(); } + @Override + public String getHiveParquetTimeZone() { + return delegateTvf.getHiveParquetTimeZone(); + } + @Override public void checkAuth(ConnectContext ctx) { delegateTvf.checkAuth(ctx); diff --git a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/TableValuedFunctionIf.java b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/TableValuedFunctionIf.java index a36c289aca182c..e637317b1165e4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/TableValuedFunctionIf.java +++ b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/TableValuedFunctionIf.java @@ -115,6 +115,10 @@ public static TableValuedFunctionIf getTableFunction(String funcName, Map properties = new HashMap<>(); + properties.put("type", "hms"); + properties.put("hive.metastore.uris", "thrift://localhost:9083"); + properties.put(FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE, "8:00"); + HMSExternalCatalog catalog = new HMSExternalCatalog(1, "hms", null, properties, ""); + catalog.checkProperties(); + + HMSExternalTable hmsTable = Mockito.mock(HMSExternalTable.class, Mockito.CALLS_REAL_METHODS); + Mockito.doReturn(catalog).when(hmsTable).getCatalog(); + Mockito.doReturn(DLAType.HIVE).when(hmsTable).getDlaType(); + Mockito.doReturn(Collections.emptyList()).when(hmsTable).getBaseSchema(false); + Mockito.doReturn(Collections.emptyList()).when(hmsTable).getFullSchema(); + SessionVariable sessionVariable = new SessionVariable(); + sessionVariable.setTimeZone("America/Los_Angeles"); + TestFileQueryScanNode node = new TestFileQueryScanNode(sessionVariable); + node.setTargetTable(hmsTable); + node.getTupleDescriptor().setTable(hmsTable); + + node.initSchemaParamsForTest(); + + Assert.assertEquals("+08:00", node.getFileScanRangeParams().getHiveParquetTimeZone()); + Assert.assertNotEquals(sessionVariable.getTimeZone(), + node.getFileScanRangeParams().getHiveParquetTimeZone()); + + SessionVariable differentSessionVariable = new SessionVariable(); + differentSessionVariable.setTimeZone("Asia/Tokyo"); + TestFileQueryScanNode nodeWithDifferentSession = new TestFileQueryScanNode(differentSessionVariable); + nodeWithDifferentSession.setTargetTable(hmsTable); + nodeWithDifferentSession.getTupleDescriptor().setTable(hmsTable); + nodeWithDifferentSession.initSchemaParamsForTest(); + + Assert.assertEquals(node.getFileScanRangeParams().getHiveParquetTimeZone(), + nodeWithDifferentSession.getFileScanRangeParams().getHiveParquetTimeZone()); + } + + @Test + public void testHiveParquetTimezoneIsNotSetForHmsIcebergTable() throws Exception { + HMSExternalCatalog catalog = Mockito.mock(HMSExternalCatalog.class); + Mockito.when(catalog.getHiveParquetTimeZone()).thenReturn("Asia/Shanghai"); + HMSExternalTable hmsTable = Mockito.mock(HMSExternalTable.class, Mockito.CALLS_REAL_METHODS); + Mockito.doReturn(catalog).when(hmsTable).getCatalog(); + Mockito.doReturn(DLAType.ICEBERG).when(hmsTable).getDlaType(); + Mockito.doReturn(Collections.emptyList()).when(hmsTable).getBaseSchema(false); + Mockito.doReturn(Collections.emptyList()).when(hmsTable).getFullSchema(); + + TestFileQueryScanNode node = new TestFileQueryScanNode(new SessionVariable()); + node.setTargetTable(hmsTable); + node.getTupleDescriptor().setTable(hmsTable); + node.initSchemaParamsForTest(); + + Assert.assertFalse(node.getFileScanRangeParams().isSetHiveParquetTimeZone()); + } + + @Test + public void testHiveParquetTimezoneIsSetForHmsHudiTable() throws Exception { + HMSExternalCatalog catalog = Mockito.mock(HMSExternalCatalog.class); + Mockito.when(catalog.getHiveParquetTimeZone()).thenReturn("Asia/Shanghai"); + HMSExternalTable hmsTable = Mockito.mock(HMSExternalTable.class, Mockito.CALLS_REAL_METHODS); + Mockito.doReturn(catalog).when(hmsTable).getCatalog(); + Mockito.doReturn(DLAType.HUDI).when(hmsTable).getDlaType(); + Mockito.doReturn(Collections.emptyList()).when(hmsTable).getBaseSchema(false); + Mockito.doReturn(Collections.emptyList()).when(hmsTable).getFullSchema(); + + TestFileQueryScanNode node = new TestFileQueryScanNode(new SessionVariable()); + node.setTargetTable(hmsTable); + node.getTupleDescriptor().setTable(hmsTable); + node.initSchemaParamsForTest(); + + Assert.assertEquals("Asia/Shanghai", node.getFileScanRangeParams().getHiveParquetTimeZone()); + } + + @Test + public void testHiveParquetTimezoneComesFromTableValuedFunction() throws Exception { + ExternalFileTableValuedFunction tvf = Mockito.mock(ExternalFileTableValuedFunction.class); + tvf.fileFormatProperties = new ParquetFileFormatProperties(); + Mockito.when(tvf.getHiveParquetTimeZone()).thenReturn("Asia/Shanghai"); + FunctionGenTable functionGenTable = Mockito.mock(FunctionGenTable.class); + Mockito.when(functionGenTable.getTvf()).thenReturn(tvf); + Mockito.when(functionGenTable.getBaseSchema(false)).thenReturn(Collections.emptyList()); + Mockito.when(functionGenTable.getFullSchema()).thenReturn(Collections.emptyList()); + + TestFileQueryScanNode node = new TestFileQueryScanNode(new SessionVariable()); + node.setTargetTable(functionGenTable); + node.getTupleDescriptor().setTable(functionGenTable); + node.initSchemaParamsForTest(); + + Assert.assertEquals("Asia/Shanghai", node.getFileScanRangeParams().getHiveParquetTimeZone()); + } + + @Test + public void testHiveParquetTimezoneComesFromFileTableValuedFunctionDelegate() throws Exception { + Map properties = new HashMap<>(); + properties.put("uri", "s3://bucket/path/file.parquet"); + properties.put("s3.endpoint", "s3.us-east-1.amazonaws.com"); + properties.put("s3.region", "us-east-1"); + properties.put("s3.access_key", "access-key"); + properties.put("s3.secret_key", "secret-key"); + properties.put(FileFormatConstants.PROP_FORMAT, FileFormatConstants.FORMAT_PARQUET); + properties.put(FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE, "Asia/Shanghai"); + + boolean originalRunningUnitTest = FeConstants.runningUnitTest; + FeConstants.runningUnitTest = true; + try { + FileTableValuedFunction tvf = new FileTableValuedFunction(properties); + tvf.fileFormatProperties = new ParquetFileFormatProperties(); + FunctionGenTable functionGenTable = new FunctionGenTable( + -1, "file", TableIf.TableType.TABLE_VALUED_FUNCTION, Collections.emptyList(), tvf); + + TestFileQueryScanNode node = new TestFileQueryScanNode(new SessionVariable()); + node.setTargetTable(functionGenTable); + node.getTupleDescriptor().setTable(functionGenTable); + node.initSchemaParamsForTest(); + + Assert.assertEquals("Asia/Shanghai", node.getFileScanRangeParams().getHiveParquetTimeZone()); + } finally { + FeConstants.runningUnitTest = originalRunningUnitTest; + } + } + + @Test + public void testHiveParquetTimezoneIgnoresJdbcQueryTableValuedFunction() throws Exception { + JdbcQueryTableValueFunction tvf = Mockito.mock( + JdbcQueryTableValueFunction.class, Mockito.CALLS_REAL_METHODS); + FunctionGenTable functionGenTable = new FunctionGenTable( + -1, "query", TableIf.TableType.TABLE_VALUED_FUNCTION, Collections.emptyList(), tvf); + TestFileQueryScanNode node = new TestFileQueryScanNode(new SessionVariable()); + node.setTargetTable(functionGenTable); + node.getTupleDescriptor().setTable(functionGenTable); + + node.initSchemaParamsForTest(); + + Assert.assertFalse(node.getFileScanRangeParams().isSetHiveParquetTimeZone()); + } + @Test public void testUpdateRequiredSlotsPreservesInlineDefaultValueExpr() throws Exception { SessionVariable sv = new SessionVariable(); diff --git a/fe/fe-core/src/test/java/org/apache/doris/datasource/hive/HMSExternalCatalogParquetTimeZoneTest.java b/fe/fe-core/src/test/java/org/apache/doris/datasource/hive/HMSExternalCatalogParquetTimeZoneTest.java new file mode 100644 index 00000000000000..6ecdf384bfb8de --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/datasource/hive/HMSExternalCatalogParquetTimeZoneTest.java @@ -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. + +package org.apache.doris.datasource.hive; + +import org.apache.doris.common.DdlException; +import org.apache.doris.common.util.FileFormatConstants; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +public class HMSExternalCatalogParquetTimeZoneTest { + private static Map baseProperties() { + Map properties = new HashMap<>(); + properties.put("type", "hms"); + properties.put("hive.metastore.uris", "thrift://localhost:9083"); + return properties; + } + + @Test + public void testHiveParquetTimeZoneDefaultsToDisabled() throws Exception { + HMSExternalCatalog catalog = new HMSExternalCatalog(1, "hms", null, baseProperties(), ""); + Assertions.assertEquals("", catalog.getHiveParquetTimeZone()); + } + + @Test + public void testHiveParquetTimeZoneAcceptsIanaZoneAndUtcOffset() throws Exception { + for (String timezone : new String[] { + "Asia/Shanghai", "+08:00", "UTC", "+14:00", "-12:00", "UTC+14:00", "GMT-12:00" + }) { + Map properties = baseProperties(); + properties.put(FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE, timezone); + HMSExternalCatalog catalog = new HMSExternalCatalog(1, "hms", null, properties, ""); + catalog.checkProperties(); + Assertions.assertEquals(timezone, catalog.getHiveParquetTimeZone()); + } + } + + @Test + public void testHiveParquetTimeZoneCanonicalizesShorthandOffset() throws Exception { + Map properties = baseProperties(); + properties.put(FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE, "8:00"); + HMSExternalCatalog catalog = new HMSExternalCatalog(1, "hms", null, properties, ""); + catalog.checkProperties(); + Assertions.assertEquals("+08:00", catalog.getHiveParquetTimeZone()); + } + + @Test + public void testHiveParquetTimeZoneRejectsAmbiguousShortAliases() { + for (String timezone : new String[] {"AET", "CST", "PRC"}) { + Map properties = baseProperties(); + properties.put(FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE, timezone); + HMSExternalCatalog catalog = new HMSExternalCatalog(1, "hms", null, properties, ""); + DdlException exception = Assertions.assertThrows(DdlException.class, catalog::checkProperties); + Assertions.assertTrue(exception.getMessage().contains("short timezone aliases are not supported")); + } + } + + @Test + public void testHiveParquetTimeZoneRejectsInvalidZone() { + for (String timezone : new String[] { + "Not/A_Timezone", "+15:00", "-13:00", "UTC+15:00", "GMT-13:00" + }) { + Map properties = baseProperties(); + properties.put(FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE, timezone); + HMSExternalCatalog catalog = new HMSExternalCatalog(1, "hms", null, properties, ""); + DdlException exception = Assertions.assertThrows(DdlException.class, catalog::checkProperties); + Assertions.assertTrue(exception.getMessage().contains(FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE)); + } + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/fileformat/ParquetFileFormatPropertiesTest.java b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/fileformat/ParquetFileFormatPropertiesTest.java index 4d140b2ba57037..0a8831585de4d0 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/fileformat/ParquetFileFormatPropertiesTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/fileformat/ParquetFileFormatPropertiesTest.java @@ -47,7 +47,7 @@ public void testAnalyzeFileFormatProperties() { Assert.assertEquals(TParquetCompressionType.SNAPPY, parquetFileFormatProperties.getParquetCompressionType()); Assert.assertEquals(false, parquetFileFormatProperties.isParquetDisableDictionary()); - Assert.assertTrue(parquetFileFormatProperties.isEnableInt96Timestamps()); + Assert.assertFalse(parquetFileFormatProperties.isEnableInt96Timestamps()); } @Test @@ -106,6 +106,20 @@ public void testEnableInt96Timestamps() { Assert.assertFalse(parquetFileFormatProperties.isEnableInt96Timestamps()); } + @Test + public void testEnableInt96TimestampsRejectsInvalidBoolean() { + for (String value : new String[] {"yes", "1", " true"}) { + Map properties = new HashMap<>(); + properties.put("enable_int96_timestamps", value); + try { + parquetFileFormatProperties.analyzeFileFormatProperties(properties, true); + Assert.fail("Expected invalid boolean value to be rejected: " + value); + } catch (AnalysisException e) { + Assert.assertTrue(e.getMessage().contains("enable_int96_timestamps")); + } + } + } + @Test public void testParquetVersion() { Map properties = new HashMap<>(); diff --git a/fe/fe-core/src/test/java/org/apache/doris/load/ExportJobTest.java b/fe/fe-core/src/test/java/org/apache/doris/load/ExportJobTest.java new file mode 100644 index 00000000000000..e197eb202c1a90 --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/load/ExportJobTest.java @@ -0,0 +1,48 @@ +// 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. + +package org.apache.doris.load; + +import org.apache.doris.analysis.BrokerDesc; +import org.apache.doris.common.jmockit.Deencapsulation; +import org.apache.doris.datasource.property.fileformat.ParquetFileFormatProperties; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Map; + +public class ExportJobTest { + + @Test + public void testEnableInt96TimestampsOutfileProperty() { + ExportJob exportJob = new ExportJob(1); + exportJob.setFormat("parquet"); + exportJob.setMaxFileSize(""); + exportJob.setBrokerDesc(new BrokerDesc("local")); + + Map outfileProperties = + Deencapsulation.invoke(exportJob, "convertOutfileProperties"); + Assert.assertFalse(outfileProperties.containsKey( + ParquetFileFormatProperties.ENABLE_INT96_TIMESTAMPS)); + + exportJob.setEnableInt96Timestamps("false"); + outfileProperties = Deencapsulation.invoke(exportJob, "convertOutfileProperties"); + Assert.assertEquals("false", outfileProperties.get( + ParquetFileFormatProperties.ENABLE_INT96_TIMESTAMPS)); + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ExportCommandTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ExportCommandTest.java new file mode 100644 index 00000000000000..981b7be805b898 --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ExportCommandTest.java @@ -0,0 +1,44 @@ +// 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. + +package org.apache.doris.nereids.trees.plans.commands; + +import org.apache.doris.common.jmockit.Deencapsulation; +import org.apache.doris.datasource.property.fileformat.ParquetFileFormatProperties; + +import com.google.common.collect.ImmutableMap; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.Map; +import java.util.Optional; + +public class ExportCommandTest { + + @Test + void testEnableInt96TimestampsProperty() { + Map properties = ImmutableMap.of( + ParquetFileFormatProperties.ENABLE_INT96_TIMESTAMPS, "false"); + ExportCommand exportCommand = new ExportCommand( + Collections.singletonList("test_table"), Collections.emptyList(), Optional.empty(), + "file:///tmp/export", properties, Optional.empty()); + + Assertions.assertDoesNotThrow( + () -> Deencapsulation.invoke(exportCommand, "checkPropertyKey", properties)); + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/tablefunction/ExternalFileTableValuedFunctionTest.java b/fe/fe-core/src/test/java/org/apache/doris/tablefunction/ExternalFileTableValuedFunctionTest.java index e5b06bd5dd4101..34df496439589c 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/tablefunction/ExternalFileTableValuedFunctionTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/tablefunction/ExternalFileTableValuedFunctionTest.java @@ -28,11 +28,41 @@ import com.google.common.collect.Maps; import org.junit.Assert; import org.junit.Test; +import org.mockito.Mockito; import java.util.List; import java.util.Map; public class ExternalFileTableValuedFunctionTest { + @Test + public void testHiveParquetTimeZoneIsCanonicalizedAndRemovedFromStorageProperties() + throws AnalysisException { + ExternalFileTableValuedFunction tvf = Mockito.mock( + ExternalFileTableValuedFunction.class, Mockito.CALLS_REAL_METHODS); + Map properties = Maps.newHashMap(); + properties.put(FileFormatConstants.PROP_FORMAT, FileFormatConstants.FORMAT_PARQUET); + properties.put(FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE, "8:00"); + + Map storageProperties = tvf.parseCommonProperties(properties); + + Assert.assertEquals("+08:00", tvf.getHiveParquetTimeZone()); + Assert.assertFalse(storageProperties.containsKey(FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE)); + } + + @Test + public void testHiveParquetTimeZoneRejectsAmbiguousShortAlias() { + ExternalFileTableValuedFunction tvf = Mockito.mock( + ExternalFileTableValuedFunction.class, Mockito.CALLS_REAL_METHODS); + Map properties = Maps.newHashMap(); + properties.put(FileFormatConstants.PROP_FORMAT, FileFormatConstants.FORMAT_PARQUET); + properties.put(FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE, "CST"); + + AnalysisException exception = Assert.assertThrows( + AnalysisException.class, () -> tvf.parseCommonProperties(properties)); + + Assert.assertTrue(exception.getMessage().contains("short timezone aliases are not supported")); + } + @Test public void testCsvSchemaParse() { Config.enable_date_conversion = true; diff --git a/gensrc/thrift/PlanNodes.thrift b/gensrc/thrift/PlanNodes.thrift index b546649933c239..4ae117d94819c5 100644 --- a/gensrc/thrift/PlanNodes.thrift +++ b/gensrc/thrift/PlanNodes.thrift @@ -560,6 +560,9 @@ struct TFileScanRangeParams { 32: optional map es_docvalue_context // ES fields field→keyword mappings 33: optional map es_fields_context + // HMS catalog property hive.parquet.time-zone. When absent, format_v2 keeps INT96 wall-clock + // values unchanged. When present, only INT96 TIMESTAMP values are converted with this zone. + 34: optional string hive_parquet_time_zone } struct TFileRangeDesc { diff --git a/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_array_type.out b/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_array_type.out index 497fcc7d7b8190..2d11f7eda340a2 100644 --- a/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_array_type.out +++ b/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_array_type.out @@ -60,12 +60,12 @@ 7 doris7 [null, null, null, "2017-10-01 00:00:00", "2011-10-01 01:23:59"] -- !select_load_datetime -- -1 doris1 ["2017-10-01 00:00:00.000000", "2011-10-01 01:23:59.000000"] -2 doris2 ["2017-10-01 00:00:00.000000", "2011-10-01 01:23:59.000000"] +1 doris1 ["2017-10-01 00:00:00.000", "2011-10-01 01:23:59.000"] +2 doris2 ["2017-10-01 00:00:00.000", "2011-10-01 01:23:59.000"] 3 doris3 [] -5 doris5 ["2017-10-01 00:00:00.000000", null, "2017-10-01 00:00:00.000000"] +5 doris5 ["2017-10-01 00:00:00.000", null, "2017-10-01 00:00:00.000"] 6 doris6 [null, null, null] -7 doris7 [null, null, null, "2017-10-01 00:00:00.000000", "2011-10-01 01:23:59.000000"] +7 doris7 [null, null, null, "2017-10-01 00:00:00.000", "2011-10-01 01:23:59.000"] -- !select_base_varchar -- 1 doris1 ["2017-10-01 00:00:00", "2011-10-01 01:23:59"] diff --git a/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_complex_type.out b/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_complex_type.out index cd7fe1e40fdb2d..8d8eb55024f07c 100644 --- a/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_complex_type.out +++ b/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_complex_type.out @@ -116,26 +116,26 @@ 10 doris_10 {"user_id":10, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00", "city":null, "age":null, "sex":null, "bool_col":null, "int_col":null, "bigint_col":null, "largeint_col":null, "float_col":null, "double_col":null, "char_col":null, "decimal_col":null} -- !select_load7 -- -1 doris_1 {"user_id":1, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":1, "sex":1, "bool_col":1, "int_col":1, "bigint_col":1, "largeint_col":"1", "float_col":1.1, "double_col":1.1, "char_col":"char1_1234", "decimal_col":1.000000000} -2 doris_2 {"user_id":2, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":2, "sex":2, "bool_col":1, "int_col":2, "bigint_col":2, "largeint_col":"2", "float_col":2.2, "double_col":2.2, "char_col":"char2_1234", "decimal_col":2.000000000} -3 doris_3 {"user_id":3, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":3, "sex":3, "bool_col":1, "int_col":3, "bigint_col":3, "largeint_col":"3", "float_col":3.3, "double_col":3.3, "char_col":"char3_1234", "decimal_col":3.000000000} -4 doris_4 {"user_id":4, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":4, "sex":4, "bool_col":1, "int_col":4, "bigint_col":4, "largeint_col":"4", "float_col":4.4, "double_col":4.4, "char_col":"char4_1234", "decimal_col":4.000000000} -5 doris_5 {"user_id":5, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":5, "sex":5, "bool_col":1, "int_col":5, "bigint_col":5, "largeint_col":"5", "float_col":5.5, "double_col":5.5, "char_col":"char5_1234", "decimal_col":5.000000000} -6 doris_6 {"user_id":6, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":6, "sex":6, "bool_col":1, "int_col":6, "bigint_col":6, "largeint_col":"6", "float_col":6.6, "double_col":6.6, "char_col":"char6_1234", "decimal_col":6.000000000} -7 doris_7 {"user_id":7, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":7, "sex":7, "bool_col":1, "int_col":7, "bigint_col":7, "largeint_col":"7", "float_col":7.7, "double_col":7.7, "char_col":"char7_1234", "decimal_col":7.000000000} -8 doris_8 {"user_id":8, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":8, "sex":8, "bool_col":1, "int_col":8, "bigint_col":8, "largeint_col":"8", "float_col":8.8, "double_col":8.800000000000001, "char_col":"char8_1234", "decimal_col":8.000000000} -9 doris_9 {"user_id":9, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":9, "sex":9, "bool_col":1, "int_col":9, "bigint_col":9, "largeint_col":"9", "float_col":9.9, "double_col":9.9, "char_col":"char9_1234", "decimal_col":9.000000000} -10 doris_10 {"user_id":10, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":null, "age":null, "sex":null, "bool_col":null, "int_col":null, "bigint_col":null, "largeint_col":null, "float_col":null, "double_col":null, "char_col":null, "decimal_col":null} +1 doris_1 {"user_id":1, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":1, "sex":1, "bool_col":1, "int_col":1, "bigint_col":1, "largeint_col":"1", "float_col":1.1, "double_col":1.1, "char_col":"char1_1234", "decimal_col":1.000000000} +2 doris_2 {"user_id":2, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":2, "sex":2, "bool_col":1, "int_col":2, "bigint_col":2, "largeint_col":"2", "float_col":2.2, "double_col":2.2, "char_col":"char2_1234", "decimal_col":2.000000000} +3 doris_3 {"user_id":3, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":3, "sex":3, "bool_col":1, "int_col":3, "bigint_col":3, "largeint_col":"3", "float_col":3.3, "double_col":3.3, "char_col":"char3_1234", "decimal_col":3.000000000} +4 doris_4 {"user_id":4, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":4, "sex":4, "bool_col":1, "int_col":4, "bigint_col":4, "largeint_col":"4", "float_col":4.4, "double_col":4.4, "char_col":"char4_1234", "decimal_col":4.000000000} +5 doris_5 {"user_id":5, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":5, "sex":5, "bool_col":1, "int_col":5, "bigint_col":5, "largeint_col":"5", "float_col":5.5, "double_col":5.5, "char_col":"char5_1234", "decimal_col":5.000000000} +6 doris_6 {"user_id":6, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":6, "sex":6, "bool_col":1, "int_col":6, "bigint_col":6, "largeint_col":"6", "float_col":6.6, "double_col":6.6, "char_col":"char6_1234", "decimal_col":6.000000000} +7 doris_7 {"user_id":7, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":7, "sex":7, "bool_col":1, "int_col":7, "bigint_col":7, "largeint_col":"7", "float_col":7.7, "double_col":7.7, "char_col":"char7_1234", "decimal_col":7.000000000} +8 doris_8 {"user_id":8, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":8, "sex":8, "bool_col":1, "int_col":8, "bigint_col":8, "largeint_col":"8", "float_col":8.8, "double_col":8.800000000000001, "char_col":"char8_1234", "decimal_col":8.000000000} +9 doris_9 {"user_id":9, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":9, "sex":9, "bool_col":1, "int_col":9, "bigint_col":9, "largeint_col":"9", "float_col":9.9, "double_col":9.9, "char_col":"char9_1234", "decimal_col":9.000000000} +10 doris_10 {"user_id":10, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":null, "age":null, "sex":null, "bool_col":null, "int_col":null, "bigint_col":null, "largeint_col":null, "float_col":null, "double_col":null, "char_col":null, "decimal_col":null} -- !select_load7 -- -1 doris_1 {"user_id":1, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":1, "sex":1, "bool_col":1, "int_col":1, "bigint_col":1, "largeint_col":"1", "float_col":1.1, "double_col":1.1, "char_col":"char1_1234", "decimal_col":1.000000000} -2 doris_2 {"user_id":2, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":2, "sex":2, "bool_col":1, "int_col":2, "bigint_col":2, "largeint_col":"2", "float_col":2.2, "double_col":2.2, "char_col":"char2_1234", "decimal_col":2.000000000} -3 doris_3 {"user_id":3, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":3, "sex":3, "bool_col":1, "int_col":3, "bigint_col":3, "largeint_col":"3", "float_col":3.3, "double_col":3.3, "char_col":"char3_1234", "decimal_col":3.000000000} -4 doris_4 {"user_id":4, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":4, "sex":4, "bool_col":1, "int_col":4, "bigint_col":4, "largeint_col":"4", "float_col":4.4, "double_col":4.4, "char_col":"char4_1234", "decimal_col":4.000000000} -5 doris_5 {"user_id":5, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":5, "sex":5, "bool_col":1, "int_col":5, "bigint_col":5, "largeint_col":"5", "float_col":5.5, "double_col":5.5, "char_col":"char5_1234", "decimal_col":5.000000000} -6 doris_6 {"user_id":6, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":6, "sex":6, "bool_col":1, "int_col":6, "bigint_col":6, "largeint_col":"6", "float_col":6.6, "double_col":6.6, "char_col":"char6_1234", "decimal_col":6.000000000} -7 doris_7 {"user_id":7, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":7, "sex":7, "bool_col":1, "int_col":7, "bigint_col":7, "largeint_col":"7", "float_col":7.7, "double_col":7.7, "char_col":"char7_1234", "decimal_col":7.000000000} -8 doris_8 {"user_id":8, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":8, "sex":8, "bool_col":1, "int_col":8, "bigint_col":8, "largeint_col":"8", "float_col":8.8, "double_col":8.800000000000001, "char_col":"char8_1234", "decimal_col":8.000000000} -9 doris_9 {"user_id":9, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":"Beijing", "age":9, "sex":9, "bool_col":1, "int_col":9, "bigint_col":9, "largeint_col":"9", "float_col":9.9, "double_col":9.9, "char_col":"char9_1234", "decimal_col":9.000000000} -10 doris_10 {"user_id":10, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000000", "city":null, "age":null, "sex":null, "bool_col":null, "int_col":null, "bigint_col":null, "largeint_col":null, "float_col":null, "double_col":null, "char_col":null, "decimal_col":null} +1 doris_1 {"user_id":1, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":1, "sex":1, "bool_col":1, "int_col":1, "bigint_col":1, "largeint_col":"1", "float_col":1.1, "double_col":1.1, "char_col":"char1_1234", "decimal_col":1.000000000} +2 doris_2 {"user_id":2, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":2, "sex":2, "bool_col":1, "int_col":2, "bigint_col":2, "largeint_col":"2", "float_col":2.2, "double_col":2.2, "char_col":"char2_1234", "decimal_col":2.000000000} +3 doris_3 {"user_id":3, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":3, "sex":3, "bool_col":1, "int_col":3, "bigint_col":3, "largeint_col":"3", "float_col":3.3, "double_col":3.3, "char_col":"char3_1234", "decimal_col":3.000000000} +4 doris_4 {"user_id":4, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":4, "sex":4, "bool_col":1, "int_col":4, "bigint_col":4, "largeint_col":"4", "float_col":4.4, "double_col":4.4, "char_col":"char4_1234", "decimal_col":4.000000000} +5 doris_5 {"user_id":5, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":5, "sex":5, "bool_col":1, "int_col":5, "bigint_col":5, "largeint_col":"5", "float_col":5.5, "double_col":5.5, "char_col":"char5_1234", "decimal_col":5.000000000} +6 doris_6 {"user_id":6, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":6, "sex":6, "bool_col":1, "int_col":6, "bigint_col":6, "largeint_col":"6", "float_col":6.6, "double_col":6.6, "char_col":"char6_1234", "decimal_col":6.000000000} +7 doris_7 {"user_id":7, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":7, "sex":7, "bool_col":1, "int_col":7, "bigint_col":7, "largeint_col":"7", "float_col":7.7, "double_col":7.7, "char_col":"char7_1234", "decimal_col":7.000000000} +8 doris_8 {"user_id":8, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":8, "sex":8, "bool_col":1, "int_col":8, "bigint_col":8, "largeint_col":"8", "float_col":8.8, "double_col":8.800000000000001, "char_col":"char8_1234", "decimal_col":8.000000000} +9 doris_9 {"user_id":9, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":"Beijing", "age":9, "sex":9, "bool_col":1, "int_col":9, "bigint_col":9, "largeint_col":"9", "float_col":9.9, "double_col":9.9, "char_col":"char9_1234", "decimal_col":9.000000000} +10 doris_10 {"user_id":10, "date":"2017-10-01", "datetime":"2017-10-01 00:00:00.000", "city":null, "age":null, "sex":null, "bool_col":null, "int_col":null, "bigint_col":null, "largeint_col":null, "float_col":null, "double_col":null, "char_col":null, "decimal_col":null} diff --git a/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_map_type.out b/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_map_type.out index f210bf62460cda..8c58581f95f858 100644 --- a/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_map_type.out +++ b/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_map_type.out @@ -218,14 +218,14 @@ 8 doris8 {"2025-12-31 12:01:41":524524, "2006-02-19 09:01:02":2534} -- !select_load11 -- -1 doris1 {"2023-04-20 01:02:03.000000":null, "2018-04-20 10:40:35.000000":123} -2 doris2 {"2000-04-20 00:00:00.000000":-2147483648, "1967-12-31 12:24:56.000000":2147483647} -3 doris3 {"2023-01-01 00:00:00.000000":1246, "2023-02-27 00:01:02.000000":5646} +1 doris1 {"2023-04-20 01:02:03.000":null, "2018-04-20 10:40:35.000":123} +2 doris2 {"2000-04-20 00:00:00.000":-2147483648, "1967-12-31 12:24:56.000":2147483647} +3 doris3 {"2023-01-01 00:00:00.000":1246, "2023-02-27 00:01:02.000":5646} 4 doris4 {} 5 doris5 {} 6 \N \N 7 doris7 \N -8 doris8 {"2025-12-31 12:01:41.000000":524524, "2006-02-19 09:01:02.000000":2534} +8 doris8 {"2025-12-31 12:01:41.000":524524, "2006-02-19 09:01:02.000":2534} -- !select_base12 -- 1 doris1 {"2023-04-20":null, "2018-04-20":123} @@ -278,14 +278,14 @@ 8 doris8 {"2025-12-31 11:22:33":"min_largeint", "2006-02-19 00:44:55":"max_largeint"} -- !select_load14 -- -1 doris1 {"2023-04-20 12:20:03.000000":"null", "2018-04-20 12:59:59.000000":null} -2 doris2 {"2000-04-20 23:59:59.000000":"-2147483648", "1967-12-31 00:00:00.000000":"2147483647"} -3 doris3 {"2023-01-01 07:24:54.000000":"1246", "2023-02-27 15:12:13.000000":"5646"} +1 doris1 {"2023-04-20 12:20:03.000":"null", "2018-04-20 12:59:59.000":null} +2 doris2 {"2000-04-20 23:59:59.000":"-2147483648", "1967-12-31 00:00:00.000":"2147483647"} +3 doris3 {"2023-01-01 07:24:54.000":"1246", "2023-02-27 15:12:13.000":"5646"} 4 doris4 {} 5 doris5 {} 6 \N \N 7 doris7 \N -8 doris8 {"2025-12-31 11:22:33.000000":"min_largeint", "2006-02-19 00:44:55.000000":"max_largeint"} +8 doris8 {"2025-12-31 11:22:33.000":"min_largeint", "2006-02-19 00:44:55.000":"max_largeint"} -- !select_base15 -- 1 doris1 {100:"null", 111:"b"} diff --git a/regression-test/data/external_table_p0/export/hive_read/parquet/test_doris_int96_round_trip.out b/regression-test/data/external_table_p0/export/hive_read/parquet/test_doris_int96_round_trip.out new file mode 100644 index 00000000000000..5cbdb0c83ce1bc --- /dev/null +++ b/regression-test/data/external_table_p0/export/hive_read/parquet/test_doris_int96_round_trip.out @@ -0,0 +1,7 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !session_timezone -- +America/Los_Angeles + +-- !int96_round_trip -- +1 2023-04-20T00:00 2023-04-20T00:00:00.123456 +2 1970-01-01T08:00 1970-01-01T08:00:00.654321 diff --git a/regression-test/data/external_table_p0/paimon/paimon_timestamp_types.out b/regression-test/data/external_table_p0/paimon/paimon_timestamp_types.out index 9df5553d1493c5..4267bc26cbbbe6 100644 --- a/regression-test/data/external_table_p0/paimon/paimon_timestamp_types.out +++ b/regression-test/data/external_table_p0/paimon/paimon_timestamp_types.out @@ -136,4 +136,3 @@ -- !ltz_ntz_simple15 -- 2024-01-02T10:12:34.123456 - diff --git a/regression-test/data/external_table_p0/tvf/orc_tvf/test_hdfs_orc_group4_orc_files.out b/regression-test/data/external_table_p0/tvf/orc_tvf/test_hdfs_orc_group4_orc_files.out index 1f5ea9741485ca..855cae3466835c 100644 --- a/regression-test/data/external_table_p0/tvf/orc_tvf/test_hdfs_orc_group4_orc_files.out +++ b/regression-test/data/external_table_p0/tvf/orc_tvf/test_hdfs_orc_group4_orc_files.out @@ -1,6 +1,6 @@ -- This file is automatically generated. You should know what you did if you want to edit this -- !test_0 -- -2022-06-10T05:26:22.753999 2022-06-09T21:26:22.753999 +2022-06-10T05:26:22.754 2022-06-09T21:26:22.754 -- !test_1 -- 1 John Doe diff --git a/regression-test/data/external_table_p0/tvf/orc_tvf/test_hdfs_orc_group6_orc_files.out b/regression-test/data/external_table_p0/tvf/orc_tvf/test_hdfs_orc_group6_orc_files.out index 85b52a6b28fb6f..dcf3cdb63ef76f 100644 Binary files a/regression-test/data/external_table_p0/tvf/orc_tvf/test_hdfs_orc_group6_orc_files.out and b/regression-test/data/external_table_p0/tvf/orc_tvf/test_hdfs_orc_group6_orc_files.out differ diff --git a/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group1.out b/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group1.out index 55ae6199bfb7ad..51c9f773485999 100644 --- a/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group1.out +++ b/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group1.out @@ -90,9 +90,9 @@ [{"latitude":0, "longitude":180}, {"latitude":0, "longitude":0}] -- !test_17 -- -1 1880-01-01T15:58:41 -2 1884-01-01T16:05:43 -3 1990-01-01T16:00 +1 1880-01-01T07:52:58 +2 1884-01-01T08:00 +3 1990-01-01T08:00 -- !test_18 -- [{"latitude":0, "longitude":0}, null, {"latitude":0, "longitude":180}] diff --git a/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group2.out b/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group2.out index 79b63e41cc1b4d..7b1744aa72f61d 100644 --- a/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group2.out +++ b/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group2.out @@ -122,14 +122,14 @@ apple_banana_mango9 3 Cecilia 2022-11-16T02:32:09.123534 -- !test_17 -- -1001-01-07T17:07:46.123456 1001-01-07T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-08T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-09T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-10T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-11T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-12T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-13T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-14T17:07:46.123456 +1001-01-07T09:02:03.123456 1001-01-07T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-08T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-09T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-10T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-11T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-12T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-13T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-14T09:02:03.123456 -- !test_18 -- 0.00 @@ -151,14 +151,14 @@ apple_banana_mango9 2 -- !test_20 -- -1001-01-07T17:07:46.123456 1001-01-07T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-08T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-09T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-10T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-11T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-12T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-13T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-14T17:07:46.123456 +1001-01-07T09:02:03.123456 1001-01-07T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-08T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-09T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-10T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-11T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-12T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-13T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-14T09:02:03.123456 -- !test_21 -- 1001-01-07 1001-01-07 @@ -181,14 +181,14 @@ apple_banana_mango9 1001-01-07T17:07:46.123 1001-01-14T17:07:46.123 -- !test_23 -- -1001-01-07T17:07:46.123456 1001-01-07T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-08T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-09T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-10T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-11T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-12T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-13T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-14T17:07:46.123456 +1001-01-07T09:02:03.123456 1001-01-07T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-08T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-09T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-10T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-11T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-12T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-13T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-14T09:02:03.123456 -- !test_24 -- false 1 2 3 10 1.2 val_1 val_1 HEARTS false 1 2 3 10 1.2 val_1 val_1 HEARTS ["arr_1", "arr_2", "arr_3"] [1] {1:"val_1", 2:"val_2", 3:"val_3"} {1:[{"nestedintscolumn":[1, 2, 3], "nestedstringcolumn":"val_1"}, {"nestedintscolumn":[2, 3, 4], "nestedstringcolumn":"val_2"}, {"nestedintscolumn":[3, 4, 5], "nestedstringcolumn":"val_3"}], 2:[{"nestedintscolumn":[1, 2, 3], "nestedstringcolumn":"val_1"}, {"nestedintscolumn":[2, 3, 4], "nestedstringcolumn":"val_2"}, {"nestedintscolumn":[3, 4, 5], "nestedstringcolumn":"val_3"}], 3:[{"nestedintscolumn":[1, 2, 3], "nestedstringcolumn":"val_1"}, {"nestedintscolumn":[2, 3, 4], "nestedstringcolumn":"val_2"}, {"nestedintscolumn":[3, 4, 5], "nestedstringcolumn":"val_3"}]} @@ -238,14 +238,14 @@ true 8 9 10 80 8.199999999999999 val_8 val_8 SPADES true 8 9 10 80 8.19999999999 9.00 -- !test_29 -- -1001-01-07T17:07:46.123456 1001-01-07T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-08T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-09T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-10T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-11T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-12T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-13T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-14T17:07:46.123456 +1001-01-07T09:02:03.123456 1001-01-07T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-08T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-09T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-10T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-11T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-12T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-13T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-14T09:02:03.123456 -- !test_30 -- \N @@ -265,14 +265,14 @@ true 8 9 10 80 8.199999999999999 val_8 val_8 SPADES true 8 9 10 80 8.19999999999 1970-01-01T08:00:00.010 -- !test_33 -- -1001-01-07T17:07:46.123456 1001-01-07T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-08T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-09T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-10T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-11T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-12T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-13T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-14T17:07:46.123456 +1001-01-07T09:02:03.123456 1001-01-07T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-08T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-09T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-10T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-11T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-12T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-13T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-14T09:02:03.123456 -- !test_34 -- 1001-01-07 1001-01-07 @@ -295,12 +295,12 @@ true 8 9 10 80 8.199999999999999 val_8 val_8 SPADES true 8 9 10 80 8.19999999999 1001-01-07T17:07:46.123 1001-01-14T17:07:46.123 -- !test_36 -- -1001-01-07T17:07:46.123456 1001-01-07T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-08T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-09T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-10T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-11T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-12T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-13T17:07:46.123456 -1001-01-07T17:07:46.123456 1001-01-14T17:07:46.123456 +1001-01-07T09:02:03.123456 1001-01-07T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-08T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-09T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-10T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-11T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-12T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-13T09:02:03.123456 +1001-01-07T09:02:03.123456 1001-01-14T09:02:03.123456 diff --git a/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group4.out b/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group4.out index d694f2db141554..e05cee918971e3 100644 Binary files a/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group4.out and b/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group4.out differ diff --git a/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group5.out b/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group5.out index c7b9542f5c7662..ccf2d100dfdcf2 100644 Binary files a/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group5.out and b/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group5.out differ diff --git a/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group6.out b/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group6.out index 4fe42d7fcdcc77..4fe18442d22819 100644 --- a/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group6.out +++ b/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group6.out @@ -65,13 +65,13 @@ value 0 value value 0 value value value value value value value value value valu -- !test_7 -- \N \N \N \N false \N -30534 -95459914 \N \N \N \N \N \N \N \N \N HYUWPBeQIs true \N \N \N \N 5668838.0 -2.120059243561625e+16 -6097.20 0.00035 -999999999999987628.942299254 -\N 2002-11-27T15:59:05.061 l6wBh \N \N \N \N 15002 -304114916502530 \N \N \N 626149930.15083 -342806041448622928.487799977 -\N 2009-05-28T21:28:07.366 \N \N true \N 327 \N -6655500289 -64307.05 \N \N \N 559739.491848528 -\N 2016-09-28T23:11:08.215 \N TCo6SPO1zXZ \N 1 \N -2 \N -1.032116E8 \N -9024.34 23874458.82144 65266925.915131517 -1991-03-16 2010-11-01T11:14:05.926 LkgyT \N true -1 \N -574 -343357407 \N \N \N \N \N -1993-05-23 2017-03-28T10:26:07.676 i61eSAVRBUP 77e7GSkck5 \N \N 7 \N \N -4198450.0 952.7765389591106 \N \N \N +\N 2002-11-27T07:59:05.061 l6wBh \N \N \N \N 15002 -304114916502530 \N \N \N 626149930.15083 -342806041448622928.487799977 +\N 2009-05-28T13:28:07.366 \N \N true \N 327 \N -6655500289 -64307.05 \N \N \N 559739.491848528 +\N 2016-09-28T15:11:08.215 \N TCo6SPO1zXZ \N 1 \N -2 \N -1.032116E8 \N -9024.34 23874458.82144 65266925.915131517 +1991-03-16 2010-11-01T03:14:05.926 LkgyT \N true -1 \N -574 -343357407 \N \N \N \N \N +1993-05-23 2017-03-28T02:26:07.676 i61eSAVRBUP 77e7GSkck5 \N \N 7 \N \N -4198450.0 952.7765389591106 \N \N \N 2005-01-25 \N \N \N -5 \N 1921 \N \N \N \N -999995892.35713 23269406.486042474 -2006-02-27 2001-09-25T16:26:47.300 BPskRWGA gcmrrVqQt6R \N \N \N -1543735 \N 2590.209 \N \N 73497326.28347 -999999999999898938.480337100 +2006-02-27 2001-09-25T08:26:47.300 BPskRWGA gcmrrVqQt6R \N \N \N -1543735 \N 2590.209 \N \N 73497326.28347 -999999999999898938.480337100 2015-02-20 \N \N HQKN4ASUraeL8NNNHh \N \N 54 3882526 -856 1.406034 -1.279787767916979e+16 \N \N \N -- !test_8 -- @@ -87,16 +87,16 @@ value 0 value value 0 value value value value value value value value value valu 9 99992 9 [9, null, 992] -- !test_9 -- -1993-07-09 2016-11-28T16:57:26.412 OAtaHgz9a7 Q true 6 -19 -38 9097047508263797290 7731680.0 -121728722.2031124 -1154.82 752082487.88019 5.7E-8 -1995-10-13 2018-07-25T13:28:16.353 6B1MKHZbNj Ue false -3 6483 -10 276697333351 66.8299 -2993435.894921361 0.50 -18062223.54616 5.964274135 -2003-05-21 2007-11-19T11:40:17.021 Wl7r6JqbodTF9RZjg2M cXiMBdxi4r4Lhd false 15 -32768 54878688 -464978533025156213 8051.383 -33985165651.60472 -243.23 181891130.71682 460802553225718373.114208380 -2004-11-10 2007-11-15T20:35:43.718 KQ KH false 0 -16257 272 38140166608 -1.679896E8 428194.3986519449 5497.48 10.46596 -420009827642394960.188567358 -2008-04-22 2002-12-25T12:09:16.420 4kH5O5ybnFKPBl 4xJ0bhE false -128 1 -1 548713867 -9408828.0 -3586.981150391522 1133.39 0.00001 -999999999999994163.822122718 -2009-03-31 2012-12-03T18:43:27.198 zwqN6MyIt0sXgtS famUtQ89d false 0 3 -11386 -912910402761414 -2.174159 -160640974619.1197 -846.12 -71235588.43915 -999999999999987320.759086933 -2010-10-31 2005-04-17T12:03:23.494 X5BgkX8vfQaR1 0L0cjpDeR true -128 2347 170 -9223372036854775808 -19973.1 -67.78219076624707 7733.21 -745864683.31989 0.000049816 -2012-04-25 2019-01-25T18:10:14.405 dSy2VDH 3hAt false 2 28294 216429 16924943782792692 12260.86 -86480240881.19473 -1296.28 233593957.16006 45878.254447167 -2014-10-30 2009-01-11T11:00:19.863 rRisIUbjYGag5b HImOsPm3xAK5E true -14 2363 -9226116 -1457371919909538548 -5.189642E7 0 -5784.72 437105919.24636 -999999999999999299.479624925 -2018-07-13 2009-06-10T01:57:16.892 JB Frti1wqV5kkrGusZ1H true 14 -6 59221576 -408428197 -0.1664757 -2516558996473.452 9621.02 0.26084 -42325491533103445.913484694 +1993-07-09 2016-11-28T08:57:26.412 OAtaHgz9a7 Q true 6 -19 -38 9097047508263797290 7731680.0 -121728722.2031124 -1154.82 752082487.88019 5.7E-8 +1995-10-13 2018-07-25T05:28:16.353 6B1MKHZbNj Ue false -3 6483 -10 276697333351 66.8299 -2993435.894921361 0.50 -18062223.54616 5.964274135 +2003-05-21 2007-11-19T03:40:17.021 Wl7r6JqbodTF9RZjg2M cXiMBdxi4r4Lhd false 15 -32768 54878688 -464978533025156213 8051.383 -33985165651.60472 -243.23 181891130.71682 460802553225718373.114208380 +2004-11-10 2007-11-15T12:35:43.718 KQ KH false 0 -16257 272 38140166608 -1.679896E8 428194.3986519449 5497.48 10.46596 -420009827642394960.188567358 +2008-04-22 2002-12-25T04:09:16.420 4kH5O5ybnFKPBl 4xJ0bhE false -128 1 -1 548713867 -9408828.0 -3586.981150391522 1133.39 0.00001 -999999999999994163.822122718 +2009-03-31 2012-12-03T10:43:27.198 zwqN6MyIt0sXgtS famUtQ89d false 0 3 -11386 -912910402761414 -2.174159 -160640974619.1197 -846.12 -71235588.43915 -999999999999987320.759086933 +2010-10-31 2005-04-17T04:03:23.494 X5BgkX8vfQaR1 0L0cjpDeR true -128 2347 170 -9223372036854775808 -19973.1 -67.78219076624707 7733.21 -745864683.31989 0.000049816 +2012-04-25 2019-01-25T10:10:14.405 dSy2VDH 3hAt false 2 28294 216429 16924943782792692 12260.86 -86480240881.19473 -1296.28 233593957.16006 45878.254447167 +2014-10-30 2009-01-11T03:00:19.863 rRisIUbjYGag5b HImOsPm3xAK5E true -14 2363 -9226116 -1457371919909538548 -5.189642E7 0 -5784.72 437105919.24636 -999999999999999299.479624925 +2018-07-13 2009-06-09T17:57:16.892 JB Frti1wqV5kkrGusZ1H true 14 -6 59221576 -408428197 -0.1664757 -2516558996473.452 9621.02 0.26084 -42325491533103445.913484694 -- !test_10 -- [["1"], ["2"], ["3"]] @@ -112,9 +112,9 @@ value 0 value value 0 value value value value value value value value value valu -- !test_11 -- \N \N F1d35xOVJG31IoyAHK false \N \N \N -16116431125110 0.7584148 \N 4482.69 \N 267447479231804607.470906473 -\N 2003-10-28T06:03:36.804 O04hp8wtzdC7zSYtc \N \N -18 -545 -3047 1533338786768 \N \N 3264.23 \N \N -\N 2008-03-21T15:03:02.757 \N JcKkM true 127 7173 2469 -268023590206237 \N -297771931599.887 -5662.19 \N \N -1996-12-30 2001-03-24T05:23:39.359 vOnbg7cMnCWq \N \N 6 -6 \N 1190871035109913 \N -1.128227048915135e+18 \N -780234040.86481 \N +\N 2003-10-27T22:03:36.804 O04hp8wtzdC7zSYtc \N \N -18 -545 -3047 1533338786768 \N \N 3264.23 \N \N +\N 2008-03-21T07:03:02.757 \N JcKkM true 127 7173 2469 -268023590206237 \N -297771931599.887 -5662.19 \N \N +1996-12-30 2001-03-23T21:23:39.359 vOnbg7cMnCWq \N \N 6 -6 \N 1190871035109913 \N -1.128227048915135e+18 \N -780234040.86481 \N 2005-04-12 \N y1eanPF IgkoA66BE3OXDl52 true -12 \N \N 31341103465938607 \N \N -3815.76 -999999998.00657 8971757.612018771 2006-01-15 \N \N \N true 40 \N \N \N \N 224.4690878435726 4164.91 \N 5676520121029773.581110883 2008-11-08 \N \N 1VhVt9Epflt7ROPA7 false 60 -3464 0 22085294 -5553881.0 2.171085895925136e+16 7397.38 \N 0.001711346 @@ -148,14 +148,14 @@ value 0 value value 0 value value value value value value value value value valu -- !test_14 -- \N \N 2 \N true \N \N 137 112616312904 \N \N \N -611304404.17092 \N -\N 2005-05-13T23:13:16.418 \N ysoW5wqFAFri \N \N -7 1 -9351934 -451883.7 \N -3982.29 14533783.04822 -997466062686998917.734291979 -\N 2005-06-16T22:34:54.817 njmbivb \N true 41 \N \N -1966215586 \N \N \N \N -712077536464721044.286680021 -\N 2015-02-04T07:41:27.652 \N dGdjfud4s false 2 \N -4961107 68485728 -1.278023E7 \N \N -999909210.29165 \N -\N 2019-10-18T09:37:55.423 5HsKkeBW6H3d \N -3 302 \N \N \N -66.98652227375422 \N 789667232.73094 -999999999999999758.850088265 -1992-01-06 2010-06-10T12:28:28.020 \N \N true \N \N \N -7966 70028.09 \N \N -999998056.04185 \N +\N 2005-05-13T15:13:16.418 \N ysoW5wqFAFri \N \N -7 1 -9351934 -451883.7 \N -3982.29 14533783.04822 -997466062686998917.734291979 +\N 2005-06-16T14:34:54.817 njmbivb \N true 41 \N \N -1966215586 \N \N \N \N -712077536464721044.286680021 +\N 2015-02-03T23:41:27.652 \N dGdjfud4s false 2 \N -4961107 68485728 -1.278023E7 \N \N -999909210.29165 \N +\N 2019-10-18T01:37:55.423 5HsKkeBW6H3d \N -3 302 \N \N \N -66.98652227375422 \N 789667232.73094 -999999999999999758.850088265 +1992-01-06 2010-06-10T04:28:28.020 \N \N true \N \N \N -7966 70028.09 \N \N -999998056.04185 \N 1992-06-29 \N u7i 9vO76 \N \N 20 -11221855 \N -2.909401 \N -5862.49 -999999999.00409 \N 2005-10-06 \N 3o6hR \N false -24 -16 \N \N 380006.3 \N \N 925890570.30189 \N -2008-05-20 2011-08-26T14:18:47.434 8k22z uavd6EwXTAcR0bSANw3 \N \N \N \N -138646833896913 -5210.832 \N 0.60 10992151.97185 \N +2008-05-20 2011-08-26T06:18:47.434 8k22z uavd6EwXTAcR0bSANw3 \N \N \N \N -138646833896913 -5210.832 \N 0.60 10992151.97185 \N 2016-11-11 \N IbOPGImUgG4Y5sy \N \N 2 -354 \N \N -655341.2 \N -7489.70 -999999999.88004 711135859187441144.808999832 -- !test_15 -- @@ -169,16 +169,16 @@ value 0 value value 0 value value value value value value value value value valu 6  -- !test_18 -- -2002-09-08 2003-01-28T13:11:07.683 8X qp3jpOhuc3eeZn03znr false 4 -900 64505843 8210173644705794 3.94371584E8 103534.6075051678 -900.39 -186247140.75010 114045.570460308 -2003-05-08 2008-01-06T10:29:02.211 SItDIC3uwANKX true -55 8696 489616 1019447917106 12.38736 -1293790206.959883 79.85 -542890844.45144 -145238424377195751.171188385 -2005-04-08 2021-02-01T14:11:49.630 3v Gx8QKePDvCwF7aGy true -14 -61 10760 -331135 49217.85 -234153.6911193004 4.89 -494030422.71905 -312769651681244534.280137860 -2016-09-09 2006-03-11T00:35:44.612 DWaJDqg0 V false 3 32767 2 5615011 -1.387982E7 -2.750639816473331e+17 9082.52 -569497743.72838 4.49E-7 -2017-09-06 2004-03-06T08:56:42.061 K F true -3 -883 -28 414773929736 -751990.1 12.12531144274905 -4100.43 711833124.68878 94632666424.390004677 -2018-09-24 2018-10-17T02:12:51.210 tQP16Gpgj dCQW9h1a true 1 753 -2062674302 -29320118537 -8.0908749E8 2310.039844142755 19.59 -999980581.24367 123524421718.093704007 -2019-08-02 2016-12-14T08:41:05.186 wTZ848PxJqEnaBMD kkDfs true 0 286 -1550 -6562177520288 0.9325238 14965275933.70474 0.02 -312990864.87022 511700796202755649.975651452 -2020-04-21 2020-02-17T21:43:21.471 Q eONgENF3D false 2 600 20290 -3 16499.78 -17287107871.53508 7761.82 -862509993.55026 36332045.071458104 -2020-06-03 2018-02-15T22:14:24.682 A6d8 uKDub4rKu8GIrdIC false -108 -29 -1037025 3328152340705000 7.3087091E8 -54596924.56914027 5259.55 0.00479 143368958436554803.272255766 -2021-07-13 2020-02-29T15:28:52.649 asPkr665RxfA9h szPIvfcywrcGU true 127 15 2963 632 -2.110992E8 14466304061.33279 -8252.28 -371633465.36918 0.000407358 +2002-09-08 2003-01-28T05:11:07.683 8X qp3jpOhuc3eeZn03znr false 4 -900 64505843 8210173644705794 3.94371584E8 103534.6075051678 -900.39 -186247140.75010 114045.570460308 +2003-05-08 2008-01-06T02:29:02.211 SItDIC3uwANKX true -55 8696 489616 1019447917106 12.38736 -1293790206.959883 79.85 -542890844.45144 -145238424377195751.171188385 +2005-04-08 2021-02-01T06:11:49.630 3v Gx8QKePDvCwF7aGy true -14 -61 10760 -331135 49217.85 -234153.6911193004 4.89 -494030422.71905 -312769651681244534.280137860 +2016-09-09 2006-03-10T16:35:44.612 DWaJDqg0 V false 3 32767 2 5615011 -1.387982E7 -2.750639816473331e+17 9082.52 -569497743.72838 4.49E-7 +2017-09-06 2004-03-06T00:56:42.061 K F true -3 -883 -28 414773929736 -751990.1 12.12531144274905 -4100.43 711833124.68878 94632666424.390004677 +2018-09-24 2018-10-16T18:12:51.210 tQP16Gpgj dCQW9h1a true 1 753 -2062674302 -29320118537 -8.0908749E8 2310.039844142755 19.59 -999980581.24367 123524421718.093704007 +2019-08-02 2016-12-14T00:41:05.186 wTZ848PxJqEnaBMD kkDfs true 0 286 -1550 -6562177520288 0.9325238 14965275933.70474 0.02 -312990864.87022 511700796202755649.975651452 +2020-04-21 2020-02-17T13:43:21.471 Q eONgENF3D false 2 600 20290 -3 16499.78 -17287107871.53508 7761.82 -862509993.55026 36332045.071458104 +2020-06-03 2018-02-15T14:14:24.682 A6d8 uKDub4rKu8GIrdIC false -108 -29 -1037025 3328152340705000 7.3087091E8 -54596924.56914027 5259.55 0.00479 143368958436554803.272255766 +2021-07-13 2020-02-29T07:28:52.649 asPkr665RxfA9h szPIvfcywrcGU true 127 15 2963 632 -2.110992E8 14466304061.33279 -8252.28 -371633465.36918 0.000407358 -- !test_19 -- 1 Customer#000000001 IVhzIApeRb ot,c,E 15 25-989-741-2988 711.56 BUILDING to the even, regular platelets. regular, ironic epitaphs nag e @@ -195,14 +195,14 @@ value 0 value value 0 value value value value value value value value value valu -- !test_20 -- \N \N \N \N \N \N \N 291 \N 39147.38 \N \N -816181887.32042 61270.940141523 \N \N WcxU7O4Hm2xrbrmKQ6n \N \N \N \N -2 245703305612 \N -2.04051912684475e+17 140.27 \N 469154562686611464.327886993 -\N 2002-12-02T00:36:11.314 \N FMI \N \N 13 9168 12891941282 990.1851 -54.07166021867196 -9974.61 735195658.19245 \N -\N 2011-08-30T06:35:52.701 \N \N \N 0 \N \N -443556077 \N \N \N -350110268.13106 \N -\N 2016-02-14T05:57:43.183 \N \N \N \N -147 \N \N \N 105719.4255176597 \N 300569778.99094 \N -\N 2019-10-08T15:55:55.986 9Ooqi \N \N \N \N \N -3004445243511957620 83.40178 \N \N -870347656.09195 323665571958231388.269910350 -1993-03-25 2012-08-03T11:23:01.478 \N \N true 86 -27004 6104 224268356114751076 -3560930.0 0.3358768327568655 1953.28 -761257627.82180 971048314430408841.695829480 +\N 2002-12-01T16:36:11.314 \N FMI \N \N 13 9168 12891941282 990.1851 -54.07166021867196 -9974.61 735195658.19245 \N +\N 2011-08-29T22:35:52.701 \N \N \N 0 \N \N -443556077 \N \N \N -350110268.13106 \N +\N 2016-02-13T21:57:43.183 \N \N \N \N -147 \N \N \N 105719.4255176597 \N 300569778.99094 \N +\N 2019-10-08T07:55:55.986 9Ooqi \N \N \N \N \N -3004445243511957620 83.40178 \N \N -870347656.09195 323665571958231388.269910350 +1993-03-25 2012-08-03T03:23:01.478 \N \N true 86 -27004 6104 224268356114751076 -3560930.0 0.3358768327568655 1953.28 -761257627.82180 971048314430408841.695829480 1997-08-31 \N EvqlJD2guEwZAIr MoKkyVc4uQpvf \N \N -97 353044 \N -782142.8 \N \N \N \N -2002-08-12 2005-09-07T04:48:42.429 rafciKRbnAZdvp \N true \N \N \N \N \N \N 3952.04 383675819.57043 \N -2003-08-04 2002-06-04T13:57:07.609 \N xPwEiNepXBk5gNJBpBR \N -1 -629 120514580 650311539060 \N \N 4924.61 \N \N +2002-08-12 2005-09-06T20:48:42.429 rafciKRbnAZdvp \N true \N \N \N \N \N \N 3952.04 383675819.57043 \N +2003-08-04 2002-06-04T05:57:07.609 \N xPwEiNepXBk5gNJBpBR \N -1 -629 120514580 650311539060 \N \N 4924.61 \N \N -- !test_21 -- 1 {"a":1} {"a":"a", "b":1} @@ -263,31 +263,31 @@ value 0 value value 0 value value value value value value value value value valu [["1"], ["2"], ["3"]] -- !test_28 -- -1993-06-01 2018-04-10T17:13:52.824 MHOTXTBClN 8UK false 109 -694 195 -13726981971 -1702638.0 -1607.505167959101 2455.64 27.78291 -999999999893414493.163433192 -1993-11-27 2005-04-26T04:21:29.567 mVP1sPLw89dqSh duVqO93GAW0TMab true 4 2 -710439346 438693955904002 -52187.16 -3815209.846927328 4360.87 542541791.18857 -318806180479147509.931466623 -1994-09-08 2009-08-07T11:16:19.122 4hJ0sOZMUM8rJLj BS true -17 -16568 1 553260146989808 -1297636.0 3.855932905989339e+16 -6716.04 273137853.92911 -569638083965584851.911245365 -2001-05-09 2021-10-23T07:10:42.501 k9azcT cJQnLLhLi1L false 107 -259 2725 1 70.45084 6.648256255495498e+16 2033.37 925329758.57587 0.001725467 -2005-04-22 2003-10-01T03:29:20.952 FNKT RuEup false 46 -10 4025 13801261311498 -1.68063296E8 -47.60461662053456 -3441.21 33326814.68001 827943523557240735.204869090 -2006-02-08 2016-07-12T05:00:20.134 O2V01ZFAUc5N1SrBZy U3zFVx2J1p4lRV7MD true -5 -17359 45903040 2058536974681213 177.0258 -688336389133906.5 1220.68 -999998385.95779 68817903234581.252697042 -2006-02-27 2020-04-09T12:50:56.697 obhNELQRgH6g9lfimq CJvlpx2Tv2em true -46 13 193 357682430329 3329588.0 26.06508496540823 -5413.09 -130481893.47558 469231731687303886.025289187 -2006-10-23 2003-10-30T13:01:54.580 E8U7Bv6O true -100 4402 5275 -4434303290 -1.01665798E9 -6197594101754.311 -3673.02 0.03154 123870631987912211.391062272 -2011-11-15 2014-09-15T12:24:19.721 Teso2e gXkyK528n false -128 40 -2 781 -0.05770421 -4.466107229397915e+16 330.35 -896716537.57214 519829000681966303.281283646 -2018-08-19 2004-08-09T04:07:44.845 rZvadRhXBNdlrwD ZALemg false 29 -1 -965071489 -1765826 -5.31722E7 42486674436.94251 449.69 -989134835.82182 -999999999999999999.990363473 +1993-06-01 2018-04-10T09:13:52.824 MHOTXTBClN 8UK false 109 -694 195 -13726981971 -1702638.0 -1607.505167959101 2455.64 27.78291 -999999999893414493.163433192 +1993-11-27 2005-04-25T20:21:29.567 mVP1sPLw89dqSh duVqO93GAW0TMab true 4 2 -710439346 438693955904002 -52187.16 -3815209.846927328 4360.87 542541791.18857 -318806180479147509.931466623 +1994-09-08 2009-08-07T03:16:19.122 4hJ0sOZMUM8rJLj BS true -17 -16568 1 553260146989808 -1297636.0 3.855932905989339e+16 -6716.04 273137853.92911 -569638083965584851.911245365 +2001-05-09 2021-10-22T23:10:42.501 k9azcT cJQnLLhLi1L false 107 -259 2725 1 70.45084 6.648256255495498e+16 2033.37 925329758.57587 0.001725467 +2005-04-22 2003-09-30T19:29:20.952 FNKT RuEup false 46 -10 4025 13801261311498 -1.68063296E8 -47.60461662053456 -3441.21 33326814.68001 827943523557240735.204869090 +2006-02-08 2016-07-11T21:00:20.134 O2V01ZFAUc5N1SrBZy U3zFVx2J1p4lRV7MD true -5 -17359 45903040 2058536974681213 177.0258 -688336389133906.5 1220.68 -999998385.95779 68817903234581.252697042 +2006-02-27 2020-04-09T04:50:56.697 obhNELQRgH6g9lfimq CJvlpx2Tv2em true -46 13 193 357682430329 3329588.0 26.06508496540823 -5413.09 -130481893.47558 469231731687303886.025289187 +2006-10-23 2003-10-30T05:01:54.580 E8U7Bv6O true -100 4402 5275 -4434303290 -1.01665798E9 -6197594101754.311 -3673.02 0.03154 123870631987912211.391062272 +2011-11-15 2014-09-15T04:24:19.721 Teso2e gXkyK528n false -128 40 -2 781 -0.05770421 -4.466107229397915e+16 330.35 -896716537.57214 519829000681966303.281283646 +2018-08-19 2004-08-08T20:07:44.845 rZvadRhXBNdlrwD ZALemg false 29 -1 -965071489 -1765826 -5.31722E7 42486674436.94251 449.69 -989134835.82182 -999999999999999999.990363473 -- !test_29 -- -1990-09-14 2010-05-24T00:29:22.086 RZd8Fol2 kTYLrR6YpBV4YrGe6GJ true 47 \N -1059875306 5110434996844838 \N -1211.746555695639 8608.24 -469562994.41053 \N +1990-09-14 2010-05-23T16:29:22.086 RZd8Fol2 kTYLrR6YpBV4YrGe6GJ true 47 \N -1059875306 5110434996844838 \N -1211.746555695639 8608.24 -469562994.41053 \N -- !test_30 -- \N \N \N GGQ3GKDEKFx4pCO false -6 \N 1758480 \N \N \N -9999.92 261658953.76656 \N \N \N \N b0ELn \N -88 \N \N 114626475407551 \N 641.9788873396103 \N \N \N \N \N \N uy true \N \N -1912073838 -32124366597410108 \N -16001891925897.45 -9998.98 157588649.93899 5481236331293411.919263188 \N \N wi \N \N \N \N \N \N 1.106744E8 \N \N 740120594.78737 0.488577228 -\N 2020-06-25T19:16:55.522 \N \N \N 51 \N 1525569 514725 -0.7716029 -15.16433905752949 \N 18436691.83034 \N -2011-05-01 2015-05-05T10:31:42.359 OnEJp9TRBl4g ruTLeXH6Xh8YLi \N \N \N -520 -1414566394050596 \N 268240689620402.2 \N \N \N -2015-10-06 2016-03-21T17:00:33.021 tsjvqYAu \N \N 21 -588744001 -610456926992694 \N \N 347.71 516467205.01627 329683922415812795.124208836 +\N 2020-06-25T11:16:55.522 \N \N \N 51 \N 1525569 514725 -0.7716029 -15.16433905752949 \N 18436691.83034 \N +2011-05-01 2015-05-05T02:31:42.359 OnEJp9TRBl4g ruTLeXH6Xh8YLi \N \N \N -520 -1414566394050596 \N 268240689620402.2 \N \N \N +2015-10-06 2016-03-21T09:00:33.021 tsjvqYAu \N \N 21 -588744001 -610456926992694 \N \N 347.71 516467205.01627 329683922415812795.124208836 2016-05-09 \N \N false -1 2 \N \N \N -410157781684380.6 -8499.34 \N -442949280946678321.087072493 2020-04-09 \N jmnUDJIq NK5dKGb \N -2 24529 -462099 53667311088374226 \N 2330.39386823334 \N 338811455.89151 \N -2020-12-16 2010-10-30T17:35:13.116 csVYmrP9cLKzq \N false 14 -455 \N \N 1.21245E7 \N \N -691583845.86904 \N +2020-12-16 2010-10-30T09:35:13.116 csVYmrP9cLKzq \N false 14 -455 \N \N 1.21245E7 \N \N -691583845.86904 \N -- !test_31 -- ["1"] @@ -314,23 +314,23 @@ SINGLE_ITEM {"limitTag":false} -- !test_33 -- -1990-02-21 2012-11-01T07:08:20.929 ImrmK10nqXofuJ YQtKCNpBL42UJfykj9 true -124 -12616 -2147483648 -67731985705176135 -6.5918528E7 -2.748174175029641e+18 179.99 0.01610 -897288714445017375.459313317 -1997-02-05 2001-09-25T10:14:11.771 78xHKpQTg g true -128 32767 -616201217 31014898 -8578.377 -1.677798880876122 -9999.75 582725944.11517 0.093275561 -1997-07-04 2020-02-18T11:05:40.350 dZ75dwyBHu Q false 2 5 2855 52962 3569.957 73.39598490486459 -9988.67 534632185.88460 739668509720211560.038685772 -2000-12-10 2006-04-29T13:36:10.932 30PUkPEjg yDpEu true 127 -46 22 -14591 9.4648928E7 53116.45202971164 2218.71 -999999999.99972 -999999999697088351.830142154 -2003-12-26 2012-07-17T07:27:13.003 6iAuQndnuV 0 true -13 -1 9394 8533950590 -1.455696E7 1872.817972229336 -1995.49 -999999999.99996 -468409029198915838.191775790 -2004-11-09 2018-09-10T15:25:09.832 bKvCqcmjigGZF6m 3z9DpIQtvbcbZ false 4 29126 -7851198 6647298083 -467437.3 -126.7522229749863 1402.15 0.00726 3191411356.484232654 -2005-07-10 2005-01-15T07:22:56.154 QewxF41E3jEF eN1TV19Rntx9qXxo false -101 736 -3 836825 -418692.5 -196125.3995570403 -6328.06 0.00068 -999999999999972866.982146783 -2013-07-26 2014-05-22T07:26:21.340 G5nyDkEZ3yrqX4D false -128 32767 -93 19577135702247335 -207222.9 169161723648672.8 -2821.07 -658186555.33968 319263362007.627792379 -2018-03-05 2010-05-14T18:28:32.238 8 E false 4 -1086 -101 -502 -40.63856 -168139090585.4518 9117.01 -330067900.83006 71856700793137.221604271 -2021-10-30 2006-05-08T11:19:17.414 cB5lU ACXBhPBLyYaSeEhhGOK false -3 941 25 -5 -1.77348608E8 -1.06923644492037e+17 -6757.02 -886964956.30550 -999999910882130931.136697944 +1990-02-21 2012-10-31T23:08:20.929 ImrmK10nqXofuJ YQtKCNpBL42UJfykj9 true -124 -12616 -2147483648 -67731985705176135 -6.5918528E7 -2.748174175029641e+18 179.99 0.01610 -897288714445017375.459313317 +1997-02-05 2001-09-25T02:14:11.771 78xHKpQTg g true -128 32767 -616201217 31014898 -8578.377 -1.677798880876122 -9999.75 582725944.11517 0.093275561 +1997-07-04 2020-02-18T03:05:40.350 dZ75dwyBHu Q false 2 5 2855 52962 3569.957 73.39598490486459 -9988.67 534632185.88460 739668509720211560.038685772 +2000-12-10 2006-04-29T05:36:10.932 30PUkPEjg yDpEu true 127 -46 22 -14591 9.4648928E7 53116.45202971164 2218.71 -999999999.99972 -999999999697088351.830142154 +2003-12-26 2012-07-16T23:27:13.003 6iAuQndnuV 0 true -13 -1 9394 8533950590 -1.455696E7 1872.817972229336 -1995.49 -999999999.99996 -468409029198915838.191775790 +2004-11-09 2018-09-10T07:25:09.832 bKvCqcmjigGZF6m 3z9DpIQtvbcbZ false 4 29126 -7851198 6647298083 -467437.3 -126.7522229749863 1402.15 0.00726 3191411356.484232654 +2005-07-10 2005-01-14T23:22:56.154 QewxF41E3jEF eN1TV19Rntx9qXxo false -101 736 -3 836825 -418692.5 -196125.3995570403 -6328.06 0.00068 -999999999999972866.982146783 +2013-07-26 2014-05-21T23:26:21.340 G5nyDkEZ3yrqX4D false -128 32767 -93 19577135702247335 -207222.9 169161723648672.8 -2821.07 -658186555.33968 319263362007.627792379 +2018-03-05 2010-05-14T10:28:32.238 8 E false 4 -1086 -101 -502 -40.63856 -168139090585.4518 9117.01 -330067900.83006 71856700793137.221604271 +2021-10-30 2006-05-08T03:19:17.414 cB5lU ACXBhPBLyYaSeEhhGOK false -3 941 25 -5 -1.77348608E8 -1.06923644492037e+17 -6757.02 -886964956.30550 -999999910882130931.136697944 -- !test_34 -- \N -2023-04-29T00:40:22.618760 -2023-04-29T00:40:22.618760 -2023-04-29T00:40:22.618760 -2023-04-29T00:40:22.618760 +2023-04-28T16:40:22.618760 +2023-04-28T16:40:22.618760 +2023-04-28T16:40:22.618760 +2023-04-28T16:40:22.618760 -- !test_35 -- 0 {"b1":0, "b2":0} {0:0} @@ -399,42 +399,42 @@ parquet_data_file.parquet 2 9 99992 9 [9, null, 992] -- !test_42 -- -1990-10-15 2012-05-29T03:10:37.964 qwWJdCpg OAX5WUvk true -128 8 70201 415992747803601 277691.1 698305821.9301682 5236.50 -915747844.59052 -151809513929934942.371226079 -1995-10-24 2004-01-30T21:00:30.486 tEJO5k75lgvTD true 24 2729 890274705 -13248059 -6.7806032E7 -23473176209.90597 5749.02 417.66104 -377237991904019590.464639292 -1996-03-14 2017-06-22T13:25:19.097 IbFcGpq4Dt hNVle1Icvtb false 1 32767 1433164198 734505698338 -4.526574 -78334509811.75497 3521.68 649748177.57451 0.000010449 -2000-03-14 2020-10-05T19:55:20.362 xqIlQ Zwam true -51 -5 -1006 -9223372036854775808 8.0106872E7 -197245175397986 2687.46 0.60408 -905703471809530507.253916180 -2007-06-11 2010-11-01T00:57:02.744 yrAziDOB iH2adlVi7g5cx4Cyh true -1 -2337 858955 14873402064357665 -4239774.0 -294873846030.8438 -4115.82 302548072.65452 2192082088530.236826232 -2011-10-14 2019-05-22T01:20:17.910 3xT J1yXHBr true 127 -189 74072 -2126 1.45417696E8 9621.719542471843 2662.49 356503871.73248 675081427984.952655367 -2012-03-22 2021-12-22T14:24:40.395 BqheA3qJO1bM91yX sqOxIZxewcIOIiP false -27 -12868 21290790 64434563 -1.46099904E8 -134089569.0511059 6632.68 -999999999.99946 13208046.785158373 -2014-06-13 2017-06-28T04:08:04.993 QfTk XycLETfYi9T9 false 61 280 -31133708 -206 -5.759916 -6.914461224115192e+18 -5262.14 721969037.46596 14986373522438733.195695080 -2015-12-25 2015-07-12T12:14:21.599 84 false -2 2743 46577299 -127300633 -12.78254 44811233853.52415 8451.82 454242344.81844 -999999999999997310.190565741 -2019-07-04 2008-03-12T09:21:53.699 Vi2jfRquzess3Wp QzvCGCUwBZ false -128 -5 7704448 -76164530828 29.64875 5460285013113021 -9188.58 -999992594.11003 -999997183115766047.908014305 +1990-10-15 2012-05-28T19:10:37.964 qwWJdCpg OAX5WUvk true -128 8 70201 415992747803601 277691.1 698305821.9301682 5236.50 -915747844.59052 -151809513929934942.371226079 +1995-10-24 2004-01-30T13:00:30.486 tEJO5k75lgvTD true 24 2729 890274705 -13248059 -6.7806032E7 -23473176209.90597 5749.02 417.66104 -377237991904019590.464639292 +1996-03-14 2017-06-22T05:25:19.097 IbFcGpq4Dt hNVle1Icvtb false 1 32767 1433164198 734505698338 -4.526574 -78334509811.75497 3521.68 649748177.57451 0.000010449 +2000-03-14 2020-10-05T11:55:20.362 xqIlQ Zwam true -51 -5 -1006 -9223372036854775808 8.0106872E7 -197245175397986 2687.46 0.60408 -905703471809530507.253916180 +2007-06-11 2010-10-31T16:57:02.744 yrAziDOB iH2adlVi7g5cx4Cyh true -1 -2337 858955 14873402064357665 -4239774.0 -294873846030.8438 -4115.82 302548072.65452 2192082088530.236826232 +2011-10-14 2019-05-21T17:20:17.910 3xT J1yXHBr true 127 -189 74072 -2126 1.45417696E8 9621.719542471843 2662.49 356503871.73248 675081427984.952655367 +2012-03-22 2021-12-22T06:24:40.395 BqheA3qJO1bM91yX sqOxIZxewcIOIiP false -27 -12868 21290790 64434563 -1.46099904E8 -134089569.0511059 6632.68 -999999999.99946 13208046.785158373 +2014-06-13 2017-06-27T20:08:04.993 QfTk XycLETfYi9T9 false 61 280 -31133708 -206 -5.759916 -6.914461224115192e+18 -5262.14 721969037.46596 14986373522438733.195695080 +2015-12-25 2015-07-12T04:14:21.599 84 false -2 2743 46577299 -127300633 -12.78254 44811233853.52415 8451.82 454242344.81844 -999999999999997310.190565741 +2019-07-04 2008-03-12T01:21:53.699 Vi2jfRquzess3Wp QzvCGCUwBZ false -128 -5 7704448 -76164530828 29.64875 5460285013113021 -9188.58 -999992594.11003 -999997183115766047.908014305 -- !test_43 -- \N \N NRtUp4mIn6 \N \N 81 61 14662764 \N \N 24.76579004869427 -7093.75 -508742383.78760 \N \N \N RTZIjxAvxiuya2O sxKm4 false \N \N -2920 \N -1.684244E7 89589245.12385154 -4844.93 0.00000 -999999078390954433.266521050 -\N 2006-11-27T23:08:53.637 ir78 21LsWbsSvr1w31bFIge false 4 \N -253 \N -0.7320864 36343026.9159499 \N \N 0.000419719 -\N 2013-02-20T10:17:53.692 \N 9A6xyElnTReuD7y \N -120 9559 4 -879625317 -2468.177 \N 7674.13 \N 822001113348911013.353861458 -\N 2019-12-27T03:18:59.650 CKAEWKO6KXdMH5 \N false \N \N -2616198 \N -6497.424 \N \N \N \N +\N 2006-11-27T15:08:53.637 ir78 21LsWbsSvr1w31bFIge false 4 \N -253 \N -0.7320864 36343026.9159499 \N \N 0.000419719 +\N 2013-02-20T02:17:53.692 \N 9A6xyElnTReuD7y \N -120 9559 4 -879625317 -2468.177 \N 7674.13 \N 822001113348911013.353861458 +\N 2019-12-26T19:18:59.650 CKAEWKO6KXdMH5 \N false \N \N -2616198 \N -6497.424 \N \N \N \N 1995-04-19 \N \N \N \N \N \N \N -3758662708917 \N 15079428976.45838 -4499.76 \N \N 2011-08-29 \N X5sOCL \N \N \N 32767 -159726 7549920896729 \N -1722.752843791083 8563.72 \N 396140954904591.906214897 -2012-01-16 2015-04-10T02:22:47.570 \N \N true 117 \N 1 13105467619782 -3050.602 -1913.374330370559 -8505.21 \N \N +2012-01-16 2015-04-09T18:22:47.570 \N \N true 117 \N 1 13105467619782 -3050.602 -1913.374330370559 -8505.21 \N \N 2014-06-19 \N e 6 false -23 3 -22865 1121243794 1.36607002E9 \N \N 573087963.56260 -999999999999999999.999999989 -2019-07-13 2014-12-26T17:36:32.015 pZ B true -1 -1652 3 -717976107 4.683132E7 187044292546452.3 -3250.34 -683065719.90078 -999999999999999996.167109911 +2019-07-13 2014-12-26T09:36:32.015 pZ B true -1 -1652 3 -717976107 4.683132E7 187044292546452.3 -3250.34 -683065719.90078 -999999999999999996.167109911 -- !test_44 -- -- !test_45 -- -1991-06-01 2005-10-05T12:55:52.803 1l2Gn65kabMBXXwRjYc u7E5o false 2 -2 213 428562943575 435.2552 43.32856728620497 -4710.14 -999999999.99991 -436880549193609652.958539482 -2000-03-13 2006-06-09T06:52:35.413 TDcm true 1 -7472 -15341663 -129538814800626 -2.97772288E8 5.384143949269808e+17 4263.84 -999321187.22295 -6391367146305982.860036925 -2003-10-17 2016-06-27T01:24:45.343 XgdsmoxEAFn8jXdlS5K YiJ3rhVe true 2 0 1527 7700997125042 1.212632 1.022898355780803e+17 9060.14 727039787.02689 813586819130092898.615426235 -2004-05-07 2007-01-14T14:12:41.238 0t H2zTnyhHP9St false 0 32 206960 16621 -338.0919 1912.507370190854 0.01 32714754.84074 211319775403678702.066657740 -2009-09-25 2004-02-20T20:35:27.365 5bb WwSwysDYuED5VJm false -128 -4 51533 -4169945864799 90324.57 218744241804287.4 5900.23 655701181.79243 299238077925743041.896872344 -2010-04-13 2007-03-08T21:50:47.393 xgRYLcU false 40 -5 1 -16 1055.089 1415626.338734332 -5923.80 -241431028.99397 1.4E-8 -2010-10-10 2003-05-09T09:36:06.082 rAXG8uKttPK1 MmHlORGYt6 true 3 -1591 367 -6608084 1.70200205E9 1.710698211616725e+18 -5723.81 -673610194.00662 -999999999999999991.707182758 -2012-03-19 2015-10-01T23:13:42.342 jtiyfW84Ki9 8nXLc true -7 -4930 144 127 -109.4621 -50762.95206166508 0.36 111694542.21589 -999999999999798265.982290349 -2015-11-11 2021-10-12T05:25:50.721 mNAJVvwLtANmKv B7bZ5IXwij true 11 -56 92 -25882090133467 74298.34 0.434995867398801 6294.06 414483781.16850 -999999999999999999.999613855 -2019-04-06 2011-05-01T04:33:13.797 RhNmU1fI hLW9BaI7zAeH3 false 127 -2053 790 -241190 -10.89894 253.2984662146607 2770.64 3.27874 -549617965788434935.429869459 +1991-06-01 2005-10-05T04:55:52.803 1l2Gn65kabMBXXwRjYc u7E5o false 2 -2 213 428562943575 435.2552 43.32856728620497 -4710.14 -999999999.99991 -436880549193609652.958539482 +2000-03-13 2006-06-08T22:52:35.413 TDcm true 1 -7472 -15341663 -129538814800626 -2.97772288E8 5.384143949269808e+17 4263.84 -999321187.22295 -6391367146305982.860036925 +2003-10-17 2016-06-26T17:24:45.343 XgdsmoxEAFn8jXdlS5K YiJ3rhVe true 2 0 1527 7700997125042 1.212632 1.022898355780803e+17 9060.14 727039787.02689 813586819130092898.615426235 +2004-05-07 2007-01-14T06:12:41.238 0t H2zTnyhHP9St false 0 32 206960 16621 -338.0919 1912.507370190854 0.01 32714754.84074 211319775403678702.066657740 +2009-09-25 2004-02-20T12:35:27.365 5bb WwSwysDYuED5VJm false -128 -4 51533 -4169945864799 90324.57 218744241804287.4 5900.23 655701181.79243 299238077925743041.896872344 +2010-04-13 2007-03-08T13:50:47.393 xgRYLcU false 40 -5 1 -16 1055.089 1415626.338734332 -5923.80 -241431028.99397 1.4E-8 +2010-10-10 2003-05-09T01:36:06.082 rAXG8uKttPK1 MmHlORGYt6 true 3 -1591 367 -6608084 1.70200205E9 1.710698211616725e+18 -5723.81 -673610194.00662 -999999999999999991.707182758 +2012-03-19 2015-10-01T15:13:42.342 jtiyfW84Ki9 8nXLc true -7 -4930 144 127 -109.4621 -50762.95206166508 0.36 111694542.21589 -999999999999798265.982290349 +2015-11-11 2021-10-11T21:25:50.721 mNAJVvwLtANmKv B7bZ5IXwij true 11 -56 92 -25882090133467 74298.34 0.434995867398801 6294.06 414483781.16850 -999999999999999999.999613855 +2019-04-06 2011-04-30T20:33:13.797 RhNmU1fI hLW9BaI7zAeH3 false 127 -2053 790 -241190 -10.89894 253.2984662146607 2770.64 3.27874 -549617965788434935.429869459 -- !test_46 -- 1 {"age":10, "detail":{"height":150, "sex":1}} {1:{"height":100}} [{"height":140}] @@ -483,16 +483,16 @@ parquet_data_file.parquet 2 20230313151812747 20230313151812747_0_4 uuid:AA1 0e99d67b-6a4c-4aac-b3b0-b74735368a0f-0_0-140-3305_20230313151812747.parquet AA1 10 0 hello \N \N {"a":null, "b":{"key1":10}, "c":{"a":[10, 20], "b":{"a":10, "b":"world"}}} -- !test_52 -- -0 vin0 log_domain0 file_name0 is_collection0 is_center0 is_cloud0 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 error_collection_tips0 error_center_tips0 error_cloud_tips0 error_collection_time0 error_center_time0 error_cloud_time0 original_time0 0 -1 vin1 log_domain1 file_name1 is_collection1 is_center1 is_cloud1 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 error_collection_tips1 error_center_tips1 error_cloud_tips1 error_collection_time1 error_center_time1 error_cloud_time1 original_time1 0 -2 vin2 log_domain2 file_name2 is_collection2 is_center2 is_cloud2 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 error_collection_tips2 error_center_tips2 error_cloud_tips2 error_collection_time2 error_center_time2 error_cloud_time2 original_time2 0 -3 vin3 log_domain3 file_name3 is_collection3 is_center3 is_cloud3 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 error_collection_tips3 error_center_tips3 error_cloud_tips3 error_collection_time3 error_center_time3 error_cloud_time3 original_time3 0 -4 vin4 log_domain4 file_name4 is_collection4 is_center4 is_cloud4 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 error_collection_tips4 error_center_tips4 error_cloud_tips4 error_collection_time4 error_center_time4 error_cloud_time4 original_time4 0 -5 vin5 log_domain5 file_name5 is_collection5 is_center5 is_cloud5 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 error_collection_tips5 error_center_tips5 error_cloud_tips5 error_collection_time5 error_center_time5 error_cloud_time5 original_time5 0 -6 vin6 log_domain6 file_name6 is_collection6 is_center6 is_cloud6 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 error_collection_tips6 error_center_tips6 error_cloud_tips6 error_collection_time6 error_center_time6 error_cloud_time6 original_time6 0 -7 vin7 log_domain7 file_name7 is_collection7 is_center7 is_cloud7 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 error_collection_tips7 error_center_tips7 error_cloud_tips7 error_collection_time7 error_center_time7 error_cloud_time7 original_time7 0 -8 vin8 log_domain8 file_name8 is_collection8 is_center8 is_cloud8 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 error_collection_tips8 error_center_tips8 error_cloud_tips8 error_collection_time8 error_center_time8 error_cloud_time8 original_time8 0 -9 vin9 log_domain9 file_name9 is_collection9 is_center9 is_cloud9 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 2022-09-29T23:31:40.352203 error_collection_tips9 error_center_tips9 error_cloud_tips9 error_collection_time9 error_center_time9 error_cloud_time9 original_time9 0 +0 vin0 log_domain0 file_name0 is_collection0 is_center0 is_cloud0 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 error_collection_tips0 error_center_tips0 error_cloud_tips0 error_collection_time0 error_center_time0 error_cloud_time0 original_time0 0 +1 vin1 log_domain1 file_name1 is_collection1 is_center1 is_cloud1 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 error_collection_tips1 error_center_tips1 error_cloud_tips1 error_collection_time1 error_center_time1 error_cloud_time1 original_time1 0 +2 vin2 log_domain2 file_name2 is_collection2 is_center2 is_cloud2 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 error_collection_tips2 error_center_tips2 error_cloud_tips2 error_collection_time2 error_center_time2 error_cloud_time2 original_time2 0 +3 vin3 log_domain3 file_name3 is_collection3 is_center3 is_cloud3 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 error_collection_tips3 error_center_tips3 error_cloud_tips3 error_collection_time3 error_center_time3 error_cloud_time3 original_time3 0 +4 vin4 log_domain4 file_name4 is_collection4 is_center4 is_cloud4 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 error_collection_tips4 error_center_tips4 error_cloud_tips4 error_collection_time4 error_center_time4 error_cloud_time4 original_time4 0 +5 vin5 log_domain5 file_name5 is_collection5 is_center5 is_cloud5 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 error_collection_tips5 error_center_tips5 error_cloud_tips5 error_collection_time5 error_center_time5 error_cloud_time5 original_time5 0 +6 vin6 log_domain6 file_name6 is_collection6 is_center6 is_cloud6 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 error_collection_tips6 error_center_tips6 error_cloud_tips6 error_collection_time6 error_center_time6 error_cloud_time6 original_time6 0 +7 vin7 log_domain7 file_name7 is_collection7 is_center7 is_cloud7 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 error_collection_tips7 error_center_tips7 error_cloud_tips7 error_collection_time7 error_center_time7 error_cloud_time7 original_time7 0 +8 vin8 log_domain8 file_name8 is_collection8 is_center8 is_cloud8 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 error_collection_tips8 error_center_tips8 error_cloud_tips8 error_collection_time8 error_center_time8 error_cloud_time8 original_time8 0 +9 vin9 log_domain9 file_name9 is_collection9 is_center9 is_cloud9 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 2022-09-29T15:31:40.352203 error_collection_tips9 error_center_tips9 error_cloud_tips9 error_collection_time9 error_center_time9 error_cloud_time9 original_time9 0 -- !test_53 -- 0 {"b1":0, "b2":0} {0:0} @@ -731,7 +731,7 @@ true -- !test_85 -- \N \N \N -2019-04-17T04:00 2019-04-17T04:00 2019-04-17T04:00 +2019-04-16T20:00 2019-04-16T20:00 2019-04-16T20:00 -- !test_86 -- 3 {"c2_2":{30:{"c2_2_3":"Hangzhou"}}, "c2_3":{"c2_3_2":null}, "c2_4":{"c2_4_1":null}} [null, {{"c3_1":300, "c3_2":null}:null}, {{"c3_1":null, "c3_2":1}:[null, {"c3_3_1":null}, null, {"c3_3_1":"2003-01-01"}]}] @@ -792,7 +792,7 @@ true 20221122195832392 20221122195832392_0_6 uuid:3 7b8c2810-aae6-40c0-840b-d5214a496e4a-0_0-51-46_20221122195832392.parquet 3 \N -- !test_96 -- -1999-03-02 2006-07-12T11:33:10.064 WjU8dGtokSea KmNbdNWDTZ06Wv69 true -52 -1767 -63310 -129 3043601.0 -7207.499333344393 -924.27 474768031.34812 13157.406434180 +1999-03-02 2006-07-12T03:33:10.064 WjU8dGtokSea KmNbdNWDTZ06Wv69 true -52 -1767 -63310 -129 3043601.0 -7207.499333344393 -924.27 474768031.34812 13157.406434180 -- !test_97 -- \N @@ -826,8 +826,8 @@ abcDeFGhijkLmnOp \N 1212 1317018404 1 18063592 674090 270648 19931008 5-LOW 0 8 851248 8452558 7 791660 63843 2 19931215 REG AIR Customer#018063592 ,bHuHED0BKD8NLBUfTYk3 SAUDI ARA1 SAUDI ARABIA MIDDLE EAST 30-885-812-7051 HOUSEHOLD Supplier#000270648 Ip69p0H8L BRAZIL 1 BRAZIL AMERICA 12-320-229-9718 khaki floral MFGR#2 MFGR#23 MFGR#2312 maroon ECONOMY POLISHED NICKEL 4 JUMBO BOX -- !test_101 -- -2006-01-02T15:04:05 -9999-12-31T23:59:59.009999 +2006-01-02T07:04:05 +9999-12-31T15:59:59.009999 -- !test_102 -- \N \N diff --git a/regression-test/data/external_table_p0/tvf/test_local_tvf_with_complex_type.out b/regression-test/data/external_table_p0/tvf/test_local_tvf_with_complex_type.out index 8037fb48de571c..7ae67a5d160d39 100644 --- a/regression-test/data/external_table_p0/tvf/test_local_tvf_with_complex_type.out +++ b/regression-test/data/external_table_p0/tvf/test_local_tvf_with_complex_type.out @@ -28,29 +28,29 @@ 100 [["MMSb41-6NUS4hS-P2I-Stnt"]] [{"Il0ca1-eM4PI1A-Q5D-C6Ew":"2023-08-10"}, {"aTqTxn-waY9G25-16n-I68i":"2023-08-10"}, {"fT1Pyb-4mgLPTT-4j0-NaNl":"2023-08-10"}] [{"vin":"NjY99J-RgRtp6k-6vC-xyfn", "charge_id":6}] {"Hnt4rk-e5QmZDz-WdV-eWR7":{"568TFe-xVyRi28-5Fn-I85j":0.6948208839746508, "8r4FMo-VUl8ydc-JgO-6X0D":0.2733065358111243, "azcHey-UCyX8eL-zR3-Wnbs":0.6961260171818049}} {0:[0.1937748952971504, 0.8936328260822543], 2:[0.745335410464371, 0.1861208546102494]} {"2023-08-10 22:40:46.403000":{"vin":"yFb2VK-h4pNNz7-Jft-Hwf6", "charge_id":7596, "start_time":0.1239780988349064}, "2023-08-10 22:41:11.854000":{"vin":"5MKPSq-R5KmuX9-cz0-4Pg7", "charge_id":7371, "start_time":0.373214996451953}} {"aa":["pJxaDv-gfpSsFF-8MH-QPkL", "SqNtD0-8wUcmX6-lGr-mjvL"], "mm":{"2023-08-10":"qtx78x-pc27epo-ZMN-obsM"}} -- !sql -- -50 [["OJyf5G-1l5N1wC-9Hj-IKGp"]] [{"Mh9Vgo-vmwsonZ-OvE-aVJZ":"2023-08-11"}, {"a7nqDE-M0JQhsa-I7G-5zAe":"2023-08-11"}] [{"vin":"SXPFww-a2tkCrE-GQF-KnSO", "charge_id":6}, {"vin":"qvBW6S-fD7XxGk-ezl-FGpj", "charge_id":4}, {"vin":"trPDbP-N68BmSR-PGx-jpgX", "charge_id":9}, {"vin":"zPMAsm-DQdYVm7-Cw5-4x7l", "charge_id":9}] {"ngasOr-QkHxzUi-an3-mvnD":{"j3zMIh-4jGIqZE-t5v-iAP5":0.625987684013195, "XqFnCA-tESLikA-joX-wE4r":0.3363446363188292, "h4qPEW-9FUdlyJ-aXn-FSn9":0.2436246850264091}} {5:[0.5407513708371531]} {"2023-08-11 01:30:37.989000":{"vin":"Wx6tPb-fFw7x7a-7oI-w8LJ", "charge_id":7263, "start_time":0.1679449798048476}, "2023-08-11 01:26:19.428000":{"vin":"h9IA1Y-Lsd2xZ7-0F0-e4qx", "charge_id":8930, "start_time":0.0138682364640994}} {"aa":["2qPsxm-QsHcRIN-STs-Ixh9"], "mm":{"2023-08-11":"mwbqWb-1HGkyb2-EtC-tEvS"}} -51 [["sBVI5j-gdL1cOo-YQI-IXJr", "rDZred-qSjyjjw-jTP-lBhu", "xXFoLr-6vI4ZEf-Zqb-YTbs", "m6XFf1-mclt1rX-FvF-nQaJ", "XFhrro-QosIPIk-dHs-d9wF"], ["j8X7fu-1fJEKXQ-Rtz-yVpx", "KWXzh3-wfWtVqp-Wjj-zgga", "Zjxzv2-1h73rDe-Tct-buHl", "Rmc896-R6MnQRc-t6u-JVi5", "GvsMv8-VEjxTVY-IMp-yVsE"], ["6k9sRr-oQeVsvK-szu-2tVP", "wR2W0G-gQXVWv6-2cU-BKVH", "DObfgG-AFn7XOI-tYw-Ta1F", "rNjOF1-IB3jWMQ-wxD-1X5H", "n02DgB-CFodhtQ-0ax-E4uK"], ["jfe2PG-W7ozOHf-mL3-atfA", "EB5GAW-3q01IFi-4iK-lcZa", "J4ELjV-Y9ZPT0B-QSU-211b", "Zgh77K-gAw8Bsy-129-UrUO", "JjiXCP-J9H2kY2-an4-EUBY"], ["4Dn1DZ-dPTPGYp-pVm-w9Tx", "ksyweA-yKuZJxN-MVV-awBR", "nmQpe5-0U8f34D-9eJ-znTA", "GygEiP-0r7YQkl-yJ6-4ier", "Qsu8kC-pDMuTbq-ke6-EPgN"]] [{"JGOYVi-4mr74Co-XcM-mViW":"2023-08-11"}, {"MlWwHK-RMJmcRs-Fmy-zj8l":"2023-08-11"}, {"cm8ZO8-dnzPMK2-Kq4-0Hea":"2023-08-11"}, {"2MDBEA-lLa2rNl-4MH-RAEM":"2023-08-11"}, {"0MCl20-VGkcTvY-M3n-VHhL":"2023-08-11"}, {"8OO4co-J9PFuce-x7a-7zyF":"2023-08-11"}, {"h8hgiJ-pjYIIzT-G96-IPri":"2023-08-11"}] [{"vin":"41fYNE-BlmV197-ozJ-yEyf", "charge_id":4}, {"vin":"6hXps7-zl6FJZl-Znb-zjE3", "charge_id":9}, {"vin":"6W91au-4KOUEVb-iNu-F6sf", "charge_id":5}, {"vin":"LtPhOE-T2AawgH-CBb-B3kf", "charge_id":7}, {"vin":"gTlKg3-RyKeRwe-x25-bDIS", "charge_id":3}, {"vin":"S1Y5Fz-VktR7PW-JaM-vSVp", "charge_id":2}, {"vin":"K8VjDI-9FK14Zk-laT-kxs1", "charge_id":9}, {"vin":"AaFtUS-1Hty9Ku-Ak5-ivBm", "charge_id":8}] {"AEaExA-Bo520FM-m8D-vX09":{"45AbDK-ZI3NDAL-MBK-UHU9":0.1785072792027651, "RMV2hk-Cyfb0b9-e8j-oMdC":0.4860786160307595, "n77pdB-9Bzi4C4-ffg-o6s2":0.5622987014897542, "O3Lmqt-TrYjDiG-vt8-Bomp":0.1939136112431907, "yA7ZBL-fiOZ5a6-eGX-5ZEh":0.6416163764279614, "px5xwX-DIeSh63-4Ev-FkBN":0.2591379673500095, "AJvUQC-Hjl1IVt-WB2-9wet":0.5117800998827022, "wIW4Yf-fgowpP9-s8A-X9qh":0.37736051041066}} {5:[0.1700666382941209, 0.4264700429633189, 0.2922353786055721, 0.509794805959957, 0.582851942990984, 0.8588434326795624], 8:[0.02499568257654983, 0.9737691446265131, 0.1117742274726051, 0.6297243954458742, 0.1260973908093503, 0.3375182210168451], 3:[0.1183025858479653, 0.6817375870979785, 0.1280896747715272, 0.4572591125592925, 0.6522023191794], 1:[0.273488000439285, 0.6277329395555634, 0.7268475070213382, 0.6404334819581489, 0.2767294943356197, 0.02203034237495372]} {"2023-08-11 01:24:38.430000":{"vin":"zWkPM6-Gt0a01I-OkZ-RVgV", "charge_id":9889, "start_time":0.1578405336139553}, "2023-08-11 01:25:11.069000":{"vin":"bYq0d6-hJkwCkJ-8EC-W1tc", "charge_id":8559, "start_time":0.006868030161507499}, "2023-08-11 01:25:50.362000":{"vin":"DKdNeT-Z8e6bue-3WV-oz4M", "charge_id":7662, "start_time":0.8718064619367956}, "2023-08-11 01:30:34.826000":{"vin":"0zce3x-RfFT3t9-oWP-I6gs", "charge_id":1346, "start_time":0.06755262400087614}, "2023-08-11 01:25:46.334000":{"vin":"TOY787-DYrX3fb-kcY-W6AB", "charge_id":4112, "start_time":0.3494696933972377}, "2023-08-11 01:21:36.222000":{"vin":"Bk17ny-zAQSUvo-FlT-tu7u", "charge_id":5407, "start_time":0.2265186267992506}} {"aa":["DkiuiF-rnuvVPY-byF-QuOr", "1pITZu-IzgylrJ-KWr-sdKa", "XYH5vz-DJ9xNU9-xCZ-4dmC", "cq2wLj-NrsLqit-v6g-jMby", "LU43CY-MFRLr9Q-wYw-ddF2"], "mm":{"2023-08-11":"qub6zo-LRZEPE1-vAm-WtX3"}} -52 [["ZBSvQB-aQBY2nd-MCF-soCt", "vbC4hZ-qdr16gX-Lxy-om5o", "cz4kJJ-6M6SMMI-ZFL-rahc", "qYPejc-FuxoLFj-bNy-ZYGn", "4wF8bB-wk1L9d5-Ke7-L8DG", "0qtdJX-lonqdSw-R2M-w5Rv"], ["olt9LY-jZ5urI2-tUQ-BzlO", "WyXhga-8bHzpxZ-2l8-TEQt", "sVd6PQ-Ou5Wqf3-fBD-ePsE", "JWyeob-I1pvFrD-Gj3-Q08o", "yhz9UY-yeGxUwN-N1b-R01q", "bLWLvI-V43WdsI-4lp-S15D"], ["tSkvqc-NsEJXRf-8jr-qCmg", "InREIK-3hCdQq7-GId-OcUV", "wOecEe-4p4nCA3-qHK-CgHl", "UHGwmD-iTn5SYe-Fsf-VHuI", "WQNS3L-6a0IZ5t-aOD-pJTJ", "ueJabh-NYDHQrM-oU0-A1YQ"], ["heHGxB-5F2dL4y-6W6-ubCC", "2YsY71-ahDUlja-iRK-Q4lu", "2wjBg1-eZikgaq-TbV-nitL", "VBDgNT-9R1Gt86-V2M-is92", "6TDv1k-op24SGV-G0v-AB6q", "H01qFG-Ki71EsO-vvi-6ME3"], ["YK4DJc-XVFPLhR-qf9-liML", "v3LMTq-qGURBt1-cT8-NpZv", "X3fQSh-bFdmn56-OGr-bcr6", "njwWAe-Gy3G7TR-kno-MWTp", "jdqbHe-8JYKvpx-x8S-deRg", "AK4Ain-KUSAPnJ-xCa-o1dl"], ["ydpKFG-9ZvzGZC-lDP-piR6", "IjpFZo-n1HMpt0-Cbh-QJBu", "kdMvgk-AL80Ce3-zTW-umXy", "vaRCRv-4cKBPBh-RoK-uw0Q", "bhJbot-0HLqEBp-Nbv-YW0w", "1dRnGO-cITeRuO-voI-sddl"]] [{"EJU778-4rkp97p-AN2-xln5":"2023-08-11"}, {"OMNt2e-uUvimc6-hSI-AtYw":"2023-08-11"}, {"OrfpYU-j1wp7nh-vBD-dKrH":"2023-08-11"}, {"SYa1iU-DZi9XUK-S05-FVPj":"2023-08-11"}, {"InLBze-TdbnQqB-5kA-WXFI":"2023-08-11"}, {"oZXWlU-HeVXDBi-U1R-O0Lb":"2023-08-11"}, {"1jC94W-4FeKChe-TOk-aBdS":"2023-08-11"}, {"KU90Ac-1rAxcGs-3LW-G33J":"2023-08-11"}] [{"vin":"mB1wMA-25TeXAF-koh-U3LD", "charge_id":6}, {"vin":"ti7pKz-IpjwaJb-4bR-Hsv7", "charge_id":9}, {"vin":"zaA1eL-whJ6aPq-tbJ-BfxY", "charge_id":1}, {"vin":"1Pzv9F-3iBfmeW-Tof-UzFU", "charge_id":6}, {"vin":"YjMgGA-zd9hQfp-b9M-clQn", "charge_id":5}, {"vin":"AJ1v47-R4iR5Xv-LwH-QQeM", "charge_id":2}, {"vin":"G5T9UZ-BelHINh-8Au-21BW", "charge_id":4}, {"vin":"buJWf1-J3Hlxmx-4wM-kPNt", "charge_id":9}] {"YJdqhT-VsB2Ggb-zPa-2Tt0":{"PoSy1Z-Dkffr0R-iOr-KWVz":0.2122697431552237, "pHx8Do-r5yqvn7-4Tr-xweX":0.120128226768535, "ofdTLa-rvfYoUa-a7J-mzwt":0.5104783468857063, "YObyoB-iZYXZf0-Obz-8x3n":0.648071472230249, "Dl9PvO-Znb0F00-oFZ-OcK2":0.9336549413795939, "8a2Irz-phXvS7d-xJx-uQKv":0.9184785275241031, "ZnNJKu-77MbRPM-CfO-LYVR":0.4437479922182787, "gC80J5-XKsoNjH-db0-PEd0":0.9126170535701229, "ywF3pC-P91wFbd-dY6-zAvL":0.03935272525999434}} {5:[0.1095200626799708, 0.5326028937979516, 0.8060140669268681, 0.4505727832758978, 0.4720516029232681, 0.3338205256060737, 0.8180208046571064], 1:[0.8852323802900887, 0.3936906402008711, 0.009063507617334543, 0.6718020739313536, 0.4776097486972591, 0.03634630538503381], 9:[0.9745187582597405, 0.5329473911569335, 0.1337213123674127, 0.1664769754188556, 0.9585403121110279, 0.8541557798394191, 0.8138556208878084], 3:[0.8158672597965407, 0.8415505009462715, 0.2435423353229933, 0.04768732903974227, 0.3537519796773547, 0.9333370152687068, 0.2363489169167885, 0.3578394548105978], 8:[0.02195386085297124, 0.3554487712668294, 0.6615765479331985, 0.2878190508421222, 0.03122025084043323, 0.6427488195845875]} {"2023-08-11 01:24:49.961000":{"vin":"LUzbIM-FicsJ5v-fAn-PKEh", "charge_id":3384, "start_time":0.8429338153414312}, "2023-08-11 01:22:49.842000":{"vin":"VzJYgc-WT3HAy6-Nuv-IcAy", "charge_id":4916, "start_time":0.5424016158099249}, "2023-08-11 01:17:39.600000":{"vin":"5QN7Z9-IZ4c0ya-XzS-oyUR", "charge_id":242, "start_time":0.2072576413495201}, "2023-08-11 01:16:37.045000":{"vin":"E1ENuJ-KswTM63-j2y-GWxD", "charge_id":8395, "start_time":0.6927241557707922}, "2023-08-11 01:27:36.100000":{"vin":"3kPnr0-yFe62Kl-Uq3-hfN1", "charge_id":5421, "start_time":0.1554667403138459}, "2023-08-11 01:20:09.702000":{"vin":"UCeBR9-jrruL6t-V5n-gP3t", "charge_id":2070, "start_time":0.3970687223420232}, "2023-08-11 01:31:47.863000":{"vin":"ivfz6d-sgtuhOV-DUQ-bAu9", "charge_id":3178, "start_time":0.8169479600287797}} {"aa":["DdBVX6-ir4ZFQF-2LE-4dAb", "7wpEoC-MK2MvoJ-onr-XHN7", "j5quwH-VOqhQsO-WIJ-m6nC", "YdICtd-FKq0mbK-mNo-CY7G", "nHMrI6-cqlREYX-HGq-G0JN", "KGmQQf-VBRkP1Z-3JB-WBLd"], "mm":{"2023-08-11":"D6LJ2X-1UcHumS-JAW-UbOl"}} -53 [["47WIS8-D37ArUU-CV6-IYG3", "uWvd6M-9MBOee4-KGg-2oSG", "y7VMGg-t2zOLt9-AOK-sbjR", "tZgIOJ-AYqQi3o-NSK-X1GF"], ["1XpQgP-gLIjrtO-4Zu-O5cI", "nk8vfb-ZFkclF5-cX5-xtBv", "YMT3yV-obXtNAe-b0W-GZlD", "36Au2q-hBGOfJA-7XL-K7qb"], ["oevn57-q9YiBvC-6yu-1yqM", "7kTndL-jA5ExoF-OsI-wQM2", "oX21RP-aO3GKm1-b0Q-cQQC", "yW2pbp-B3PooaJ-yRx-dgo8"], ["kwov6B-RAtH8QU-OnB-549V", "saJYw9-brNhBsr-2aq-y92u", "pbP7NL-6Fim9UQ-OMM-PLz3", "03qWjx-ClOrhJO-Gda-nMLA"]] [{"f9fPY7-xePmB2Q-Vhx-qaj8":"2023-08-11"}, {"6V6hrD-q0mffM6-7U2-JTHW":"2023-08-11"}, {"TEKl1b-8dKwaxs-Mhf-sC3J":"2023-08-11"}, {"MN1vTk-sGWIJgG-Yha-5DFE":"2023-08-11"}, {"ZwNnTT-ni0OID1-Miy-fZHo":"2023-08-11"}, {"ZVE2zM-oHTuEYI-EbE-XX7o":"2023-08-11"}, {"R85D59-iqTLE6z-948-GM9D":"2023-08-11"}] [{"vin":"mwcQ91-xYjlxUP-qZT-eJqF", "charge_id":8}, {"vin":"ncDhIz-0oZhq2m-Ew3-6WjP", "charge_id":1}, {"vin":"PyS3kC-aO2CPH2-BNN-oqqx", "charge_id":2}, {"vin":"2xIKH0-v3faZTl-fOo-rI7K", "charge_id":8}, {"vin":"ROR1jk-O5vS2Kd-dpZ-h72n", "charge_id":7}] {"U7pxgM-KShkiX7-Keb-PHsM":{"Jq14yl-XpoXLJX-99I-Ve9R":0.2784139613362793, "JDVF3t-xFdwu5P-kpj-OauK":0.05174728870278311, "3ajEN9-xqJHBh9-us5-R7MF":0.3469192046700897, "9X8M8I-UQaJhDO-9i7-nChq":0.3018919459484262, "P0gt8U-ds5LvWs-Vbt-gaT7":0.3400361501804748, "WoFf4O-vkLxKWM-Sz7-G8Ox":0.9261570442932751}} {5:[0.3105743065465537, 0.08772836767962744, 0.6921575663295787, 0.6959748289457285], 9:[0.2215892614044007, 0.334159816938011, 0.327421430497192, 0.4861872798090753, 0.8364978227937394, 0.1101084834829856], 2:[0.1459836382064356, 0.3284361771162454, 0.00902187158361778, 0.7926872473953445], 7:[0.5400736561823897, 0.8932790579874702, 0.0044636868329746, 0.8164341088142658], 3:[0.3287245418435573, 0.150084014153181, 0.5045330146679782, 0.5904841498223871, 0.105812522019689, 0.5984371322829315]} {"2023-08-11 01:19:45.586000":{"vin":"11jVvo-9Oidxl9-3rj-ogdB", "charge_id":4134, "start_time":0.3898729376781794}, "2023-08-11 01:16:59.650000":{"vin":"srRfgD-U68LMHa-Yk1-hyB5", "charge_id":1407, "start_time":0.3008674220521801}, "2023-08-11 01:22:51.450000":{"vin":"vcHWQw-jLhG31Z-dq4-jGkq", "charge_id":8517, "start_time":0.999917828828064}, "2023-08-11 01:32:10.235000":{"vin":"OF613x-Z18yN3r-cpo-ifE9", "charge_id":6809, "start_time":0.3624238623966848}, "2023-08-11 01:25:12.599000":{"vin":"iKubfU-P0phSEy-5fH-LT67", "charge_id":1515, "start_time":0.4587106504603173}} {"aa":["E5EREH-ACc2wdA-bPn-U56J", "PxLRTM-n5BfpOh-N72-XdCY", "xCOXOY-p6mhzJ0-9FN-VTKp", "ezcySD-RMTak3u-l87-dQe8", "A6QYHI-aBYZbgi-0JX-S5Af"], "mm":{"2023-08-11":"DybtpN-j7vofti-uKr-5mT3"}} -54 [["tv7ku4-B0qy58C-rnk-kkhr", "CG8oh7-fA9GKEc-wne-D3t1", "thnMmZ-KkcvALw-osb-UIaf"], ["rfGgEs-EGKBaBY-bJt-daf3", "GujPmo-qQAxCdy-QNT-gleN", "DOego0-LyeJ5lK-4Z3-qFR1"], ["Vv4xgi-vVeu2nW-zJq-YTzy", "UHKGZ2-cUra2rJ-XSB-GMN5", "m2ZWQ0-Xs1IZya-HUK-63jD"]] [{"yeNMdp-6nJycB0-Tv7-fKnA":"2023-08-11"}, {"FvPZQL-CZrZ4Dk-ww5-DF3Z":"2023-08-11"}, {"1pQYQx-Z4bB3ee-Qga-tJPG":"2023-08-11"}, {"xWZ7Gy-b0uCoyn-W83-I7jp":"2023-08-11"}, {"4LPKBa-GHghXdY-jn8-uoEQ":"2023-08-11"}, {"ljkpDM-lcjUezP-khm-iDs5":"2023-08-11"}] [{"vin":"NoAlqA-56udIoA-5EX-JOIl", "charge_id":2}, {"vin":"B8bibN-6GEWLUI-93I-d4do", "charge_id":9}, {"vin":"SNwK77-8TH2RsG-MJ2-tKS8", "charge_id":4}, {"vin":"A9LvGS-2aOsPHG-Lwz-FtGm", "charge_id":3}, {"vin":"2kOOyB-krSdpzw-TRx-QH8n", "charge_id":4}, {"vin":"fqsXj0-8HB8czv-ZmJ-7Ckt", "charge_id":0}] {"JhCyv0-MKRMKvR-aWn-5MB6":{"icdwkC-luzK634-b2u-iEYF":0.4938651434973199, "EuzIDF-MJDGRfb-tf3-TgDn":0.3519559100997417, "FpsnY1-Z6jjGyH-gt6-BvQH":0.4337762056803064, "KAxH7u-0myxapf-dEK-7FYa":0.991984799775244, "xYtrIb-lbsRBwW-RKS-eRw4":0.5741690975495818}} {2:[0.7299412764262242, 0.9260029048793296, 0.5925181040243392], 8:[0.1001250718790359, 0.3431254184444573, 0.6691677401146177], 0:[0.6478354429360543, 0.6767751382169649, 0.9633797914100292, 0.1223335712078517]} {"2023-08-11 01:31:17.873000":{"vin":"foTlm1-1V2Szcg-1aC-MRrj", "charge_id":6912, "start_time":0.9511447433388256}, "2023-08-11 01:16:16.618000":{"vin":"L5n0DV-bJpJ2UM-a3B-h0vE", "charge_id":327, "start_time":0.765822377291262}, "2023-08-11 01:24:28.231000":{"vin":"mMwYIl-C05IUrq-XuX-CnzU", "charge_id":2368, "start_time":0.999737189962702}, "2023-08-11 01:29:06.290000":{"vin":"rTuq9T-F70Hyk1-Z8s-ZLqD", "charge_id":744, "start_time":0.8416130249155471}} {"aa":["sO6sfK-baO1xra-t3H-h6H6", "bF5B0y-424xZmC-CDB-aFkh", "OYSGIr-miwxtIW-6xY-VZh7"], "mm":{"2023-08-11":"QqMyyg-k6zEC8l-O78-lql8"}} -55 [["IDDP9l-HAAtgJO-huQ-EsgQ", "bMTI9M-yiJwpBY-BYW-5FAB"], ["BbFM5T-1WumGnp-hBE-evyG", "uoi5pO-ELgBUoV-c4u-MGzw"]] [{"vXONHn-e4K7wwf-RRH-gfYJ":"2023-08-11"}, {"lyIsB6-5QRyiQy-RBa-e5pL":"2023-08-11"}, {"eAeanR-xnq2Ylk-85Z-DTG6":"2023-08-11"}] [{"vin":"Ckbjdv-PKi7NsU-JFJ-oNA8", "charge_id":1}, {"vin":"2o2uiK-JyZ3HsU-9LU-NL9c", "charge_id":0}, {"vin":"IW6Z1R-7hjCW6w-fLI-uqZn", "charge_id":9}, {"vin":"nzo4jb-Z9aKR8t-ERY-rChn", "charge_id":2}] {"MsVPVP-Wz76O3W-M5u-6OZC":{"Rol41F-LBr4xIj-aHo-1z7r":0.7833197547141593, "8aI88U-jcHxuax-KGu-CveS":0.2183506335135603, "cXLOdV-jPT3pRZ-WVm-jsBC":0.604329438109007, "Zeorfe-Qt6Cjkf-QuH-0Bqy":0.4620636946252842}} {7:[0.4746254106090101, 0.9857918700983427, 0.5769353163838751, 0.1047035813690067], 8:[0.1361586396241807, 0.6908150185985129, 0.5613378428541096, 0.1870891763057041], 0:[0.3511016662407238, 0.9075663088683685, 0.477110729748815]} {"2023-08-11 01:15:51.033000":{"vin":"U9NRbd-0lzKeh7-axS-G16W", "charge_id":8905, "start_time":0.7292260002107532}, "2023-08-11 01:22:39.875000":{"vin":"7Mmdex-3HlmTpR-XLY-rLv1", "charge_id":5332, "start_time":0.1762868182364091}, "2023-08-11 01:28:22.816000":{"vin":"er4l9A-yoTjsdx-8rd-AaOP", "charge_id":7931, "start_time":0.4702979685445514}} {"aa":["6z8Xzp-2y7lDnn-33P-OqY5", "eNjmCC-4jP4Zre-FOr-gQzr"], "mm":{"2023-08-11":"edoY8U-e2ImHTH-wCk-gSKC"}} -56 [["0SGkZP-19FJJaL-THD-s1fw", "ExSXMv-VBOFSSw-Sg6-14Eq", "BwOxTw-ScMrtz8-AGG-hrVk", "RzVFvM-MnCYjcv-edV-GLcq", "Fwckw8-O2JqmoZ-6vU-DuOh", "G1WHNn-neF869S-me9-TRPI"], ["ZjUIXT-IbpVwur-uQE-ELnv", "YuOMYW-hxV3kVk-CPx-om2u", "zUtaqm-DgkYNXC-OHr-7RXt", "Nov4Wi-6sCuNy8-s3o-Fc4Y", "ubA8qi-YOF4tnI-3UV-aTNO", "R2BCgS-QVsoOkT-BKs-v2Q0"], ["JrTyT9-UPN5hqC-CO9-v3gq", "2TiX5V-Bsw4Cl1-cjd-h3Vx", "n3cWcG-z1AJcYj-txy-Dm1H", "vF36BW-ZZk8sGY-eHs-6Gbf", "jqxuw2-XJi0yMN-DaW-OEkC", "4irn8U-c9RY6Ef-Ul2-cbUJ"], ["vK0BGO-wNN7x0i-hsD-e5SL", "vqaheW-Q15fcjD-lwZ-0f4Q", "yxyaij-TWMXyTc-x0L-mdjp", "icemcN-YCVC96Q-gNK-cKcx", "YvQ2B5-auonVY5-yBs-8MeK", "k91VC6-4S20Ogi-m99-0rcx"], ["bCKSRM-rA0wtaE-uHa-qnQF", "cYalS3-Jx78aAN-j8i-83ph", "iIuVam-hsiKh76-1IR-1BEG", "nK8dX4-RtL0NzQ-Cr4-GcKH", "0UGFr2-FrMVoOE-XH9-YYX2", "eNhrjH-YFr0wGi-rtW-AOSW"], ["TvAp3u-4goQDzU-Ywl-M7kd", "O92Rkt-s0yqc5n-OCC-DQ5y", "o7IktR-dASp1OP-dsN-abpf", "yvDWnP-V9tOMqP-Nke-qZlD", "PCxx3p-YjenaxU-wS2-gsFh", "3Q85bO-X7h8V3u-jAE-NqmW"]] [{"zO3Zbu-xc97X2W-KW8-MvYa":"2023-08-11"}, {"B4R32w-phZ8WJd-wjT-aDYh":"2023-08-11"}, {"FpIZES-JTz76gt-Z4J-DTff":"2023-08-11"}, {"ZgkK7C-0GxwhT4-dg2-lshn":"2023-08-11"}, {"FiRgdi-XAz0EPl-pHO-ANq8":"2023-08-11"}, {"1v0U97-1n67bPm-jmw-BRcM":"2023-08-11"}] [{"vin":"1gFWcC-xcp50hp-4p7-1EVz", "charge_id":0}, {"vin":"Kgp18n-YTsyj7J-e5T-c5b4", "charge_id":2}, {"vin":"WrgDxH-nXtyVO3-3MN-OfKX", "charge_id":8}, {"vin":"SMjdRd-sB0ri8I-QT2-q1z8", "charge_id":7}, {"vin":"uY313u-aXZTQuQ-6k6-BWQg", "charge_id":2}, {"vin":"iFW48f-kUUSxMX-Vdv-fvEx", "charge_id":1}, {"vin":"7CokZM-Cq9uv8A-oiK-mAMH", "charge_id":2}] {"3ozluK-ci3e3R3-gmq-C5ho":{"vusH9K-GHvOYrC-l56-kVQh":0.129388566712362, "7BKEm6-2Clqn39-rCX-YUHQ":0.4809108845587262, "KTWxg7-5ao8Wwp-t3z-gymk":0.6294341468307141, "iwgn9N-9CFVU5g-DLl-lraX":0.1346828032226828, "SkJcRB-7FqgMxe-PR1-IOlo":0.3087147067379575, "h4Pxo6-ibJ8j23-mDD-vTOT":0.4731438850707492, "mYAmYG-Co9mcGO-qbm-YyAY":0.3073838041496642}} {0:[0.7525522283577646, 0.5203187152521088, 0.8792304693362081, 0.01340886748698289, 0.7557097854781354, 0.9546731696243579, 0.4144012408947869], 1:[0.9150561736362857, 0.3041083280603063, 0.9684160362225539, 0.9409237111830627, 0.00354028801537265, 0.130343409616228, 0.9103415272904609], 6:[0.2682159399833898, 0.6639432709162291, 0.3392017811899227, 0.8380127499413075, 0.806416028074902, 0.1240849470764859, 0.9478796564929635, 0.5731165220662204], 9:[0.7639131751196545, 0.6666784120698608, 0.7397691301158906, 0.9186054374290861, 0.003110414383702298, 0.6037897503982196, 0.9985326765983019], 8:[0.2988361843513174, 0.103517835152557, 0.5419295412535603, 0.8073911299674146, 0.05102931349342199, 0.8089829465862552, 0.918047804060321, 0.7216668725501939], 4:[0.1713016023542038, 0.2645729861704954, 0.9243517891965869, 0.2873064271854678, 0.7047728931934353, 0.9883572314533633, 0.5951113350943464, 0.9609428256171617]} {"2023-08-11 01:18:39.350000":{"vin":"lpeXRW-PPFDZen-LvV-2bfr", "charge_id":9558, "start_time":0.7456703072443472}, "2023-08-11 01:19:53.775000":{"vin":"we2QqG-1KirOd1-sI9-IJEm", "charge_id":5408, "start_time":0.1406524653813722}, "2023-08-11 01:16:55.770000":{"vin":"TmyYbJ-rcaycRp-ON6-nwBl", "charge_id":9774, "start_time":0.1870807255181824}, "2023-08-11 01:23:01.164000":{"vin":"13XTKv-LBwCJhi-sTd-ZslV", "charge_id":33, "start_time":0.7722409867065521}, "2023-08-11 01:17:47.494000":{"vin":"abagbu-IW3cP5T-2g7-OG32", "charge_id":7118, "start_time":0.1189162502162576}, "2023-08-11 01:17:23.207000":{"vin":"6bK6Hu-8jePZHC-MTt-HUXf", "charge_id":8998, "start_time":0.3419994373830386}, "2023-08-11 01:27:56.164000":{"vin":"aayyRg-1CeZoSu-Zri-wfSx", "charge_id":1744, "start_time":0.4839834661494162}} {"aa":["GNko8o-Boz741L-kPW-XNiQ", "6RsNb8-SCKCBjH-MdP-BLmu", "YeMqrb-pLvxNLT-uVz-W0q1", "cuAXjr-jI1QUjz-nCP-5ghg", "NLp17C-8V0Zz2N-ZlN-Eo2z", "pl4Yze-I01JFTN-zoJ-y0Al"], "mm":{"2023-08-11":"6CdfNp-m1kJt11-a5u-qgoJ"}} -57 [["xjLC0V-fZbCLn5-OhF-tWgX", "H7KVdf-KYc1y5u-Wqe-fjPI", "6y3cDw-YzJoo5I-xrH-92hN", "g4ExGu-I1Gg123-BwX-bLTd", "yCiyB3-vWe7FSW-b5A-5VnG"], ["0VDAIo-WEmr9tJ-GTP-HTqt", "wlwghG-NRybwTB-0wa-7Y65", "wDtlBa-KTsNGpQ-xi1-BNGP", "MnZeBR-mIihbIG-xIB-FMtI", "y31rp3-KZEBlP7-zUh-z3Nw"], ["4uvQS4-YTd8zNZ-H0h-ZB5n", "dpma3c-ZwlWGAW-qx4-xL3u", "d0ioBH-G5fmU74-Xio-afGU", "JU1nD5-c7Dy1ym-aqc-0Zz7", "CxMyPc-UH4bGjo-L7u-8WxO"], ["PTtesO-5FL0ggm-KrR-8apS", "fIa5Az-u74YSXP-FWL-bYjw", "mMFpnl-bnVbkWg-aJl-bqAW", "HyKtYi-FSP3KeN-3xT-vR7I", "W6XVtJ-kfrAZl3-Mqi-TEDe"], ["fYc6fU-dfgP3bu-EsY-F7eR", "SRuJDK-R1veC02-OYg-RzBS", "ICM0iH-yCKTgam-H4M-VZAf", "yb0dm1-UKJ7Myt-5Xh-Sa2G", "VMrMry-c74mliy-LWU-EFVe"]] [{"K3rLF9-cv4vCnQ-Vx8-6KFM":"2023-08-11"}, {"R3cD7L-rWkq0UU-vJ0-WmGG":"2023-08-11"}, {"nXDkVH-oUSxhvt-WYK-D6ZR":"2023-08-11"}, {"xYgtFe-NTlGci2-UDa-bxiL":"2023-08-11"}, {"NMao5a-2BCieWb-tsC-6mot":"2023-08-11"}, {"UfkJb1-mD2kzmM-Gzc-b3Ko":"2023-08-11"}, {"WrGdy1-zKDeXyJ-RZ9-l8IG":"2023-08-11"}, {"suGsAt-d7iu8go-hNr-njpi":"2023-08-11"}] [{"vin":"LMqyVM-Uydqj0R-Bnf-IUWl", "charge_id":2}, {"vin":"RGL9wJ-ILUGycd-Ymd-igcq", "charge_id":8}, {"vin":"FN6HTM-mcfXylZ-PTz-gyZo", "charge_id":7}, {"vin":"05CH4X-AbQdji4-jZu-eL7e", "charge_id":1}, {"vin":"JJP5Bi-4BFFM8T-ux1-gUF2", "charge_id":0}] {"Ju6K5d-zEMnWG9-L7l-QjAa":{"TDXY00-qRlBafH-4Kj-0GCA":0.5227028115723444, "dGfVdV-Jyv85Tj-SK3-cKJs":0.1053550385918921, "IZiark-GCNJc9k-iAQ-zWqx":0.6392321712185968, "GcYQOH-h50Xe2P-ApZ-5A39":0.525933769632311, "5Ntpy0-WAtHnaR-Qqn-ObNP":0.9031187380770488, "bRux7C-KlrVYNS-7UP-g6h5":0.9580617594212908}} {7:[0.9656121197784733, 0.6592734098621122, 0.2739019612541155, 0.01366028991365853, 0.1813631749663133], 4:[0.141307729992178, 0.5455543114849581, 0.6812056106659004, 0.2892375116061335, 0.09408023757345707, 0.9232139106288936, 0.5992306345160531], 6:[0.9765132272606117, 0.4731640380711279, 0.07522271838321337, 0.442210144648944, 0.8330747996642478], 9:[0.8830207795706935, 0.502873103103274, 0.4640703655720798, 0.8318661515981369, 0.9449570391195257, 0.6151676126043052]} {"2023-08-11 01:25:21.986000":{"vin":"8XXnJy-C9fssTo-Lms-2zjK", "charge_id":5917, "start_time":0.1419896861837719}, "2023-08-11 01:27:05.100000":{"vin":"Aezjvy-a2KfZo1-8EP-49xe", "charge_id":9169, "start_time":0.6886316934962607}, "2023-08-11 01:19:54.626000":{"vin":"652NTa-zBLe2Cf-HLj-U54B", "charge_id":5091, "start_time":0.1393061353913715}, "2023-08-11 01:25:44.821000":{"vin":"pxnUhN-L6MBkA7-jJY-mfte", "charge_id":8279, "start_time":0.2652365789894289}, "2023-08-11 01:27:16.453000":{"vin":"dXL5rv-NOTXI2I-H5n-e3JG", "charge_id":1679, "start_time":0.8934533395824213}, "2023-08-11 01:25:50.843000":{"vin":"qjGfIp-vi4d0kX-nHZ-N3Jf", "charge_id":3034, "start_time":0.5151735040237844}} {"aa":["haaxCE-0Z5MO7h-jT4-qPyj", "uzjhQX-8B6x9jK-MXV-sPfy", "fsXMlC-1HgHySU-CT5-9r9z", "23gfYA-lNd5Z8q-4mx-Qx88", "4bloJi-gT5EV1V-PvB-BUKw"], "mm":{"2023-08-11":"akqEqV-63IgvI3-xP4-sd2w"}} -58 [] [] [] {"TV7uGy-aO1AV8O-WGo-G9QJ":{"2ijOl0-YuQ24Xb-84Z-6yuL":0.5422329420566728, "6Y5MKA-fUSOCA4-t6r-McwZ":0.9847437995543189}} {7:[]} {"2023-08-11 01:30:33.958000":{"vin":"GuR7Av-ITVNylK-FYJ-lkWG", "charge_id":8409, "start_time":0.4128720093520603}} {"aa":[], "mm":{"2023-08-11":"3lNdsp-DMpQXEE-uDe-EDeJ"}} -59 [] [] [{"vin":"gmtVdc-VJMScRR-YeH-3vZX", "charge_id":8}] {"Kn73oB-NzIcrXR-VHT-EUiu":{"oaqAaF-LIoyD1D-gKJ-azLI":0.1839240637973197}} {1:[0.3038146593833805, 0.269155429439049]} {"2023-08-11 01:25:18.053000":{"vin":"T6DwRz-G3K2gey-LaS-tpBP", "charge_id":325, "start_time":0.8037233701597274}} {"aa":["qcbNea-90nwFBA-1cX-dEQy"], "mm":{"2023-08-11":"vsN6kn-7UJ5XKo-nPa-yiBo"}} -60 [] [{"YG2fQt-xiLaYHm-0Sz-KhEp":"2023-08-11"}] [] {"dnTCTG-0xpi67O-ifv-ilSk":{"cltPYv-uzrjg9i-MeR-R6RS":0.311517024869693, "tKkh0C-3kOHfC0-Ier-nphs":0.239287360403646}} {8:[0.348392576321308]} {"2023-08-11 01:29:28.375000":{"vin":"dTRDCc-HNDyVSA-bpI-qmM8", "charge_id":6070, "start_time":0.3469296305314755}} {"aa":["kFPSxl-fzFQ0n4-HUj-nLlu"], "mm":{"2023-08-11":"3JWsT0-lyNM8uP-KD3-dCf2"}} -61 [["7oEQZe-HTPSKPW-Vgi-0pja", "rpzOX5-LFewxLG-GCz-UAdF", "sMwz9W-mHnnQWh-Xis-BJwA", "kBE4U4-Pqzg0Wk-KHi-Dlik", "dkJYro-mtXVmMT-av2-Y0Cu"], ["LS7qB3-Hoxge48-nBY-O0eF", "ZMeSIa-xSeq71y-ZgU-omNK", "i479K2-1zSiNZf-aw3-Kw4l", "ZmxIwz-qaAVXFG-w7D-Ur3a", "vlyqCD-RSX1Ikp-BEk-SO5L"], ["HLFwQw-xneBZCk-9Je-niub", "KNLTQT-2p3ZIYi-Gzx-EElb", "ZpLvwF-nEPnMGk-16x-AuEm", "Hlcklf-eTpL3VQ-cSA-Aqtd", "dvODDc-R3wlzAk-2uI-Ygsp"], ["Aw13xJ-KTiFsf0-mPd-iD9B", "7SiCSP-TeymfRE-aun-ULeN", "g6eNOz-28H7yHE-BC1-dmVN", "YBywzw-1RyIt82-jIe-ibDf", "YCI717-HVdfcJM-SX1-8iX4"], ["h0hEao-vQs8oIo-Ewa-LGeS", "sJ88wk-E6Qfj4o-KDp-r6tx", "3kUIr4-E1m7mxJ-kHz-CnAe", "3WM5yM-IG5U7Gv-A4n-XVvk", "F7wPJE-x8f0UwY-s4e-dQ7J"]] [{"aAmFzX-9FQJCbD-QZK-jfFR":"2023-08-11"}, {"kbpFOq-NX3cEsN-5JT-CVwN":"2023-08-11"}, {"YlI5uN-h2eD0RK-KPp-eQ6G":"2023-08-11"}, {"g3OD3s-jMtT2Ht-nXF-MLhO":"2023-08-11"}, {"0yIsNz-srjWM76-qQo-lAPs":"2023-08-11"}, {"jatETJ-juetmT4-lI2-pzzV":"2023-08-11"}] [{"vin":"dPFejv-cSjZQXG-tcQ-5Vpa", "charge_id":3}, {"vin":"dU3iAJ-y7W6QA4-6nD-y3gw", "charge_id":5}, {"vin":"S8FEsQ-SdFeyE7-JiW-VRuz", "charge_id":5}, {"vin":"XQ1xtF-DJkaA3Q-VVn-nm88", "charge_id":1}, {"vin":"0ZBwg2-gETNAT6-BAx-fMjD", "charge_id":5}, {"vin":"A71eTf-4b0bFKj-eK4-o0wT", "charge_id":4}, {"vin":"dgmrHL-BWDEIQC-AEG-Ekpm", "charge_id":3}] {"EEXBex-kEpzEdG-wk0-WFI3":{"5LBMLR-0QPqjgA-b04-VUBQ":0.9594353750727006, "FbR8QW-hIAaK1t-jDs-YDDs":0.6753414995932897, "XEvjpr-kvfBZ93-hXt-K1T4":0.9746749650160776, "46bLB0-10hKBbi-Uzr-hiwi":0.5900114794066044, "TaKpjP-WBKUz8w-Xjz-uiA0":0.5483617041164721, "Z3udCe-YhB3iZw-Ht3-oJ7N":0.8372630332720171, "MY7pV7-TlcsMvY-rnW-eTrO":0.5692853847175321}} {3:[0.7291695481004961, 0.6630008011133933, 0.957537815397795, 0.6660870525125724, 0.736920618979871, 0.1131792039742632], 8:[0.7212531843939823, 0.6042106965664266, 0.1227327480404046, 0.4952361090573217, 0.5622573232261584, 0.2892389709037597], 2:[0.8778956914765943, 0.8782933398747464, 0.3931444243626142, 0.4446540653534949, 0.2525514591717621, 0.8635328809742461, 0.3091605813084479], 0:[0.4477016043802801, 0.3084922790781928, 0.7585338529068617, 0.5991256259965572, 0.8265029042529952, 0.4894416569738526, 0.3937897110106579]} {"2023-08-11 01:18:43.073000":{"vin":"v3XiMu-cpou6RT-JrN-eskx", "charge_id":4659, "start_time":0.6704776945432359}, "2023-08-11 01:20:51.066000":{"vin":"52YeAE-TqLn8va-S2q-RpHv", "charge_id":8498, "start_time":0.1728724785061412}, "2023-08-11 01:28:30.173000":{"vin":"Tw7yHA-HorUUPX-60o-zznJ", "charge_id":8188, "start_time":0.4651910291727306}, "2023-08-11 01:17:04.479000":{"vin":"JCZfON-uPPwFEi-uWG-LXek", "charge_id":6834, "start_time":0.10124110347782}, "2023-08-11 01:19:25.035000":{"vin":"6SPs3w-O22E3wC-rLj-r7Ui", "charge_id":8774, "start_time":0.08927242534692026}, "2023-08-11 01:30:50.449000":{"vin":"RUgOB0-Xy8IR6S-K9G-sCXn", "charge_id":2419, "start_time":0.5801503469877168}} {"aa":["JKl3l1-D2MMhJ3-6kr-qQGR", "kOPU4g-AvIshaA-jqO-LUUZ", "2qJF5X-U7b9ZaR-xSE-3cOZ", "3N8hLv-nPdHNSW-iWF-BQiq", "fHdwUQ-mz7lvZ6-Aqx-Aswe", "U5dY2z-Ao1Lgrh-Rhi-DwAR"], "mm":{"2023-08-11":"AZW2sJ-iOcNRYo-iKL-EJ5c"}} -62 [["FOrv5W-2rSmKlZ-cq5-T1bX", "0szhed-lYzoYqD-Tso-gaRh", "tNpqER-0ScyUgw-bW7-nl1z", "cUD7TB-g3dUt6U-A3w-zT69", "xp72Xe-fGFKBls-Xtz-6HG2"], ["hBikFg-WSiFubZ-ZIt-C1Vw", "n8y4mF-xcfBtPm-Ey8-nLPe", "Tb1wYf-jKWkbQz-ywK-z9a5", "GLt4mz-W3P7Awk-iyV-paHA", "A8cfsp-lbk7AWO-pm8-sjex"], ["Pi5Eyz-4X2QK97-RJT-02qa", "DrUctu-sj9PhoH-149-JrzP", "LaseiS-xhKbzCP-PHg-ueug", "hJwHZy-lsSF0lW-23P-aiSU", "C3MVLA-2BTquO0-jDm-sQjY"], ["GCVJrI-WoROlLC-KKn-wUZo", "NmEqB0-6g5YgOG-muy-SdOQ", "xFzgQ3-IZcZPko-VTn-q8Bg", "JJ1sBg-LrFQLuC-5yX-aLay", "JvDvPs-D2Rcfvp-nGQ-cBlv"], ["s885Lu-obt25zN-ij2-MXci", "bpNv7A-9a7qk9z-Sok-bJMI", "cofVir-CD7lg55-OgE-zUVv", "dENW2c-q4Ry3Q7-zBp-5gVd", "ux3miv-Pq2xmNw-aig-mn5U"]] [{"OtDkEu-McIs8ml-hwr-i6ep":"2023-08-11"}, {"UUB7eM-SBBZqaS-npH-7GVP":"2023-08-11"}, {"4IaZgV-PcP6kor-sjI-zzbx":"2023-08-11"}, {"XcTiLL-fa9Vnl9-wGl-RQv6":"2023-08-11"}, {"ubM1ll-Mzpy0jI-NEr-kufM":"2023-08-11"}, {"t58CdW-yfXBpgI-si7-NaUK":"2023-08-11"}, {"LPjRsq-wLsDeOo-tXC-kgyL":"2023-08-11"}] [{"vin":"2g0sDN-UqZQBFa-ZJ5-VY17", "charge_id":1}, {"vin":"adGDBd-JkT0X3E-srU-dpW6", "charge_id":7}, {"vin":"4RkGb8-vqFIZQy-pYE-Vld4", "charge_id":7}, {"vin":"G6tZa0-axKR17V-DgM-QqRa", "charge_id":1}, {"vin":"ORknAk-aeeW4Fx-RNv-LwNb", "charge_id":4}, {"vin":"XpLuWf-0xLpgxf-DHK-MtOq", "charge_id":9}] {"lpAhbv-dqrJAgp-jpT-IW6q":{"JeFkey-R4bW970-tGX-1Bgm":0.5082853540749284, "iwVaRV-oRn0OQJ-0ZS-W0aL":0.6876455403920271, "rrngmU-8fHplSu-5oI-6o2t":0.9938887839316269, "ZsajmF-BPWdiuM-N3c-JaaI":0.6805468481913053, "uwe64l-LdHSuuj-cnt-RLwY":0.4518562711269524, "FqQASw-0mXVBXm-lKo-2GAr":0.5888134151200064, "FxWNaq-o9E03Ot-OuC-6RYn":0.4935367629474818}} {2:[0.533796774021022, 0.7958570811711682, 0.1553345897860017, 0.002260810271764058, 0.3183921958447888], 6:[0.426915349150189, 0.2532335569194092, 0.6490036684761226, 0.3156541187276246, 0.563185611956019, 0.8465447672713232, 0.6742663440597226], 9:[0.4711657931226115, 0.4369916152167725, 0.7208138048024109, 0.7824456152990077, 0.01545990438891287], 5:[0.758802779485154, 0.4675790936770324, 0.1439184295715378, 0.1597675594612853, 0.7883621369757384]} {"2023-08-11 01:17:03.321000":{"vin":"Rqe4Hr-u1aj3FI-4MZ-t1Rj", "charge_id":866, "start_time":0.5948947171738422}, "2023-08-11 01:27:56.973000":{"vin":"yMtWEu-LkXxF8m-5sH-vK0E", "charge_id":5680, "start_time":0.6514353517221358}, "2023-08-11 01:19:40.452000":{"vin":"HhlsZt-JLfOp08-bko-Znc8", "charge_id":5812, "start_time":0.5586502064978098}, "2023-08-11 01:26:20.532000":{"vin":"hdtMRN-dL6Qlmx-Nck-ugjS", "charge_id":5280, "start_time":0.4279013810071601}, "2023-08-11 01:23:57.466000":{"vin":"IVJJoY-6C7l8da-kHj-qMXU", "charge_id":5599, "start_time":0.9137608819126282}, "2023-08-11 01:17:04.364000":{"vin":"7Jo2ua-fE9k7u2-tNR-8hLy", "charge_id":882, "start_time":0.1185946142399849}} {"aa":["izgBzO-Ez1Q4NI-jbp-62UZ", "Qtz7IG-kGcpoAg-0eT-ry56", "l3TIlT-g4Cjhfn-DVT-yE1m", "etKh07-LuPdMfE-BRe-7rpz", "aGFABf-v2AoNF3-Od4-LRVt"], "mm":{"2023-08-11":"dYtWNy-4MfC15K-aIM-28u7"}} -63 [["usA42u-DTLNnxO-9tb-2DsA", "PPNAAN-IxNiFgr-8gI-cdyP", "etyfgF-cCapaP0-c7j-sCsf"], ["CpsTED-Xr0GS13-aFQ-SAuN", "9U9S1D-ycAsMjt-Ghw-6zU0", "GgEISg-IRX6Ehs-63o-x2sQ"], ["sgMTuY-pDNyoLP-LNg-IlMB", "Lsuwpk-fPCvqDB-6lJ-Ht8q", "8YbbwZ-NpYq2ZO-1Jd-vT5e"]] [{"Tz8pDq-rjuq2ge-kEz-7jov":"2023-08-11"}, {"VPbHT2-3hIEpEe-Ayf-fGKa":"2023-08-11"}, {"8ZQSNK-QfhN6J4-M8m-1mlf":"2023-08-11"}, {"d3yPuD-LejqEkb-Rbg-jiUw":"2023-08-11"}, {"QuLnrp-tdB1tZ4-t44-kp0v":"2023-08-11"}] [{"vin":"P5WigM-bC5FWne-HTK-GcuV", "charge_id":7}, {"vin":"a3T2nh-ktaifdD-RCZ-wLsJ", "charge_id":4}, {"vin":"wXex2J-xOLVf4m-sfA-drGC", "charge_id":1}, {"vin":"oGv5wQ-tjPng3b-cv2-PRww", "charge_id":7}, {"vin":"2IMdC8-nWoy2q1-DiS-SBRj", "charge_id":9}, {"vin":"zfpYKR-FEOvBlN-UKw-hM7i", "charge_id":0}] {"dVgK7k-SRvdPp9-8vb-pKoj":{"90F5BI-3GkRcBK-fE2-tYCv":0.06458620033520768, "hKvzmp-8laHz8d-aH3-OaxJ":0.1866966208600762, "KiusSu-583J2Gy-XeD-rNAR":0.2449894257026729, "dmep6f-J5isEwC-liO-yi5G":0.8372054686998823, "n8CbTG-OVUF6WQ-k96-pD1M":0.9355327362244028, "ScpQ8S-i4Ap9VZ-run-0LIX":0.1597515046135692}} {6:[0.2849988138683293, 0.4651556812428728, 0.2365199666544998, 0.83986127502324, 0.8857334498442996], 3:[0.5259369162919219, 0.8175926454446628, 0.6339910995870129, 0.6355920232291508], 4:[0.3982259010694618, 0.3190576227753816, 0.7077945369111771, 0.06333149853798858, 0.7978815610750313], 8:[0.8754349658548269, 0.1125435215567862, 0.6748539861219062]} {"2023-08-11 01:22:28.309000":{"vin":"WHkQrc-pgmjMuq-OAL-oDGt", "charge_id":7307, "start_time":0.8691325203323025}, "2023-08-11 01:25:27.178000":{"vin":"Qhh6mj-YEk3sDZ-jbk-Wxcs", "charge_id":6433, "start_time":0.4172126482608913}, "2023-08-11 01:31:15.046000":{"vin":"k5WHvS-NGZCQvN-Dtw-WACy", "charge_id":3455, "start_time":0.7034558449369689}, "2023-08-11 01:20:38.286000":{"vin":"rZQ29W-U8mxXY8-vve-zV9P", "charge_id":5310, "start_time":0.5264369623586872}} {"aa":["jvVceb-sAcZqMh-i8w-9RTK", "pu4Fme-DmHSYWT-4Xf-6BnQ", "a4cgfR-ag8KaAF-Gkl-xJiW", "Cmsbic-oqJXxWf-fGQ-JM32"], "mm":{"2023-08-11":"3Mh3PY-rGFANnk-wcM-y6sc"}} -64 [["P1g2nU-im1070k-r7i-nSpd", "L4YXhB-7cqpAwy-nM0-tE5V", "9A76CV-jJ2g8bT-Gf7-sCAI"], ["bo5Osd-h6kZBJl-hAR-e44s", "DR8rFE-ncXwt5V-jR4-UQXJ", "D4UwcI-cCvgDUG-oew-nDuZ"], ["ROqoO4-6Myd6v5-B4n-DN0P", "YJ0BNR-bsXjZDo-qug-hE22", "NmdEyJ-dyQqJsm-T7M-SsYL"]] [{"YNIJCp-WR2n5Dw-Acn-Aa6N":"2023-08-11"}, {"mNKF0g-3VFqCO4-Tqe-za2s":"2023-08-11"}, {"j295B8-2DbaveH-EMq-ll4H":"2023-08-11"}] [{"vin":"dThwbf-C1OKdeK-JYG-wF66", "charge_id":9}, {"vin":"LdBoOB-L4t62in-WiN-gxn0", "charge_id":6}, {"vin":"gdbKOH-MoruM9a-dCi-9pt1", "charge_id":2}, {"vin":"ttDyHe-1WI23zj-tV7-pOzU", "charge_id":2}, {"vin":"q97jt4-PtURfWy-xqD-drum", "charge_id":9}] {"j84znC-FVXQvtE-WZk-LZ3e":{"yIu6DU-xNKsZQt-mpb-QPfT":0.3173938929015944, "0p3gXA-WO5VpyV-Gpe-8kBj":0.5753145201273284, "tqNp7D-Tr3VJkN-8yC-KnEz":0.5154278455249841, "RSkucX-BQx70ZW-3LI-N61T":0.7784781984571406, "9FuJvE-epEtGci-l0Y-Yy9l":0.5208184566677192, "ER9NvD-AV1Wbzf-4dO-LAUR":0.2119242903033582}} {1:[0.7215767292777553, 0.5450452191865959, 0.6998580138083651], 9:[0.5761924689171235, 0.06293988871766676, 0.8853990644122416, 0.5100316528079006, 0.5938084489076774], 2:[0.9854245558331454, 0.008085342039870436, 0.9038540889121772, 0.3945900294974377, 0.2317368761512505], 4:[0.03555658789466809, 0.9358280991143105, 0.3684738584229781, 0.2819247559776834]} {"2023-08-11 01:19:27.026000":{"vin":"BOxoMo-LOJhV1I-2yQ-Mr1g", "charge_id":3089, "start_time":0.2420109633395051}, "2023-08-11 01:31:18.297000":{"vin":"hjfk4J-U1u5wNa-oRD-I7d0", "charge_id":1994, "start_time":0.3713256256791723}, "2023-08-11 01:16:20.285000":{"vin":"XcWkJj-VSq0Lv7-osE-eDLc", "charge_id":2501, "start_time":0.4716809968989929}, "2023-08-11 01:24:45.142000":{"vin":"d6k4z9-vOm55qG-kq4-IzS6", "charge_id":6852, "start_time":0.573348069207453}} {"aa":["FdKqXK-MD10dQP-Qeq-coWK", "rbGo4t-LkyX84b-Wfr-tq2D", "HtYgKr-9rJmv8t-RtD-aydO", "CP0gMZ-6HIj4Ry-uSR-5lDj"], "mm":{"2023-08-11":"kIc0aE-GFVA8ar-68Y-c5ZV"}} -65 [["qlIv3R-jOOnUWs-ioK-RVi1", "plSLmk-fw56OkM-GLU-cWv0", "m7Tg1W-8qoOv6x-SOZ-TihX", "zELSrX-17n8Lar-drw-FxrH", "vFLqBU-eS7LXTs-Fa9-rLd8", "RNPL9D-FJIENYF-p7l-6NR6"], ["0g3dvq-OMsoTq4-HJY-mAUC", "3QK3tT-hruqpg8-ovm-cZlm", "FyWH7n-xtVinAe-ukD-9OID", "bkMMCQ-OAdNMuz-raf-aQO4", "ogUWcT-SnVTQyk-c34-h53I", "EtOBKo-Ftu10c2-wLp-lPWt"], ["kuThkh-iK1BEiI-FRH-60dG", "ARJ0DN-HuITnS0-v9u-TlTB", "MJvIDI-xGhMulB-Q03-KkxX", "0VCljo-tOieAtx-biy-wTv9", "dZQTUy-iibNEDO-59J-1csP", "WijuMq-yDqZHNT-HsW-wVjm"], ["hDxkiu-sUkHoVB-MJ2-cCWU", "ugvgaG-YSbfjYz-xNJ-sPd2", "eyAnim-yP26r0m-XOx-Kkpi", "mhb2gT-QlxjAxI-VSz-TAqw", "8zdhp2-GfYeUxI-DTh-1s1k", "FdzmcZ-AA2NL27-9Nb-cOLv"], ["WtUDhA-4FsaCuG-Uc4-37Zm", "bZ6w0C-BHWFq5J-6eK-5kRo", "dB6s8u-mzZaGNj-Kyq-sp4E", "bY7osA-dA5TU2R-lDT-FQOx", "HWlt9a-IlTgbu0-NG7-tn6I", "jXt8Y2-AOCxgWo-eoa-iMKF"], ["mIDNh7-xIbB4bU-dpy-AbKw", "ih5av3-LdqWzqu-be4-Q7qo", "AXB6mV-XQUx8X9-WoW-kQnS", "bD9IkH-KK4oMsG-ici-trcC", "ucFFv5-81LMAGR-ave-QgoM", "1Amd77-5QVEgte-oZq-Ncbl"]] [{"krPUDy-CPCHiPS-rV3-10bX":"2023-08-11"}, {"VbYSe7-YRkwYNt-qk3-vkeK":"2023-08-11"}, {"S9SYGk-EtokAbZ-Spg-siou":"2023-08-11"}, {"h0YxJ4-QtKtppt-zEx-VnnS":"2023-08-11"}, {"qMSe3j-CnBVfb7-xdc-XnM0":"2023-08-11"}, {"hWH2nO-xWTIPeI-l2Q-OTF1":"2023-08-11"}] [{"vin":"h3sMx3-eceSGVx-qhe-LE42", "charge_id":3}, {"vin":"p5i0wH-aldscj8-qaf-QxU9", "charge_id":2}, {"vin":"LDbX2F-vbvLKkd-Nir-Lqy6", "charge_id":0}, {"vin":"CKlgkl-glsdK9K-s19-WvPy", "charge_id":4}, {"vin":"ZqLHzR-VIbR1yb-YSV-p5es", "charge_id":9}, {"vin":"RH1mDB-laZ1dcp-BcX-6UmE", "charge_id":7}, {"vin":"a9HQcN-UZqpIoS-re6-u2zQ", "charge_id":9}] {"7MxWP7-QSjn9t0-DTm-hr1l":{"jnZOvz-j5Wj8vk-Uh7-vEOF":0.8792529873427823, "deOkFQ-zuNL6rE-xA3-xJ1W":0.7891300684176269, "cvJ0cm-KUqTLYO-9Nd-FO72":0.4838146593498607, "In6S4U-q7VBTCE-bvu-5srH":0.1454420585059233, "IHz7gW-7AI0ufo-rt6-SYXI":0.5490150044745433, "90zpTc-t3rISsA-4fM-Zyxe":0.9685215341287539, "EamSbi-Lodvma8-RKc-Tovu":0.549277394043476}} {8:[0.442136583504404, 0.6744591152496611, 0.5933599746532719, 0.8026001343301067, 0.1638944167743935, 0.9326583201127897, 0.2873273726799473], 1:[0.373393482277358, 0.6653450487875695, 0.7102007505130804, 0.1838779588745427, 0.9969481231579442, 0.2339420163712275], 0:[0.2845609864588027, 0.2479405902662357, 0.908033011350321, 0.330851669808077, 0.2617647901553333, 0.2652004097959256, 0.7032597751275278], 6:[0.8429724056601859, 0.1730576411048207, 0.1115579728971939, 0.3530999948851733, 0.1937797148588007, 0.3476905134060055]} {"2023-08-11 01:31:13.020000":{"vin":"Qfd9RZ-iIxEhgA-sw5-NU16", "charge_id":9140, "start_time":0.3772122901610612}, "2023-08-11 01:17:50.199000":{"vin":"vcZOps-jADYs1V-p73-2beO", "charge_id":8570, "start_time":0.7206652736385138}, "2023-08-11 01:28:11.647000":{"vin":"UhXH7c-PhNvHVe-qMq-VuDT", "charge_id":3327, "start_time":0.1523741624810179}, "2023-08-11 01:22:47.011000":{"vin":"hPqQep-dYgbS0n-0bu-RPOK", "charge_id":9727, "start_time":0.7942951811023238}, "2023-08-11 01:18:29.131000":{"vin":"o2FBox-z3mCJng-wDx-TuOH", "charge_id":560, "start_time":0.6580943205956693}, "2023-08-11 01:27:41.025000":{"vin":"5XSJzs-EZDGVrh-M1g-WFkB", "charge_id":6933, "start_time":0.363667164087543}, "2023-08-11 01:26:09.973000":{"vin":"rf1U0Y-C8WRJQ2-fhT-csKT", "charge_id":704, "start_time":0.986365155218468}} {"aa":["kCqfTz-YYTir3V-agc-O4qC", "ncMLJL-Rn90jI4-XJX-3kPZ", "VmqRWj-9Pbkirz-3PR-Pq5h", "8YE00C-lu4YAf8-Vrd-xSex", "AYRBJ4-Rq0g2EH-kSV-7abK", "OAJfA9-pB98dLe-6yi-wQzf"], "mm":{"2023-08-11":"y0hdJd-tmwm1cs-rFK-nItG"}} -66 [["yseJkR-mYnUqcG-ri6-fZx4", "idAxpL-jXLlTAf-WrW-2CL0", "h4BcXN-ti3hO89-Fqx-93Rr", "33S2ao-rvMGYF6-wPR-0VzI", "ordbOY-N5P3ARA-XEd-N1Xz"], ["0HtYva-ySQeiEH-Wkt-QT7K", "ZA4xJ7-aY9MhrR-UTi-opFm", "zeKo56-254thJr-INf-eZmS", "5DOvVc-9bEpO0u-Sih-BRhL", "qbGeBx-odB2DPA-o7D-1aEf"], ["qRMo1F-4TJGabD-EDJ-cY4c", "ADyYZY-UdIjpjk-2RS-GxLe", "STBkK4-KZkCuIV-uQ9-r02v", "cVeFWz-b1faXCI-ccP-Mwyc", "pPqNsb-PvChKof-v7e-I2OB"], ["AMDkUq-XfAeeBT-AJw-7vTm", "VENw7L-6Vm9Gt4-lQg-NcM0", "cfc09p-1SBUcfP-HSj-mZmI", "KRYdp2-JYEvrcf-OmJ-eIys", "cQUrPH-RNdp4mf-vu6-4Lhn"], ["xOd6Ps-N4CpWeF-1Y9-c2ar", "HKdHcw-GywbRqy-beH-n2Uc", "zjaeEC-6oNX0e6-svz-N5WD", "dunNPb-UtdPJco-9AH-5VB6", "N0OvJa-GAstkDa-sRX-PfWJ"]] [{"bq0CSj-FMlM2V3-tj5-sXvg":"2023-08-11"}, {"W7uUGW-MDdTt1g-FMB-cq7z":"2023-08-11"}, {"19gsSZ-q5cwo5y-h0a-KWPj":"2023-08-11"}, {"WJ52jJ-Fo6HvxW-A3B-hMLg":"2023-08-11"}, {"y6FA5T-DuvONCr-19a-J4Sp":"2023-08-11"}, {"DBfivM-1Qs4yp6-ct6-R71g":"2023-08-11"}, {"bj0aSs-DWjupQ8-VVx-qW6n":"2023-08-11"}, {"SyUBP9-Nx31xOA-7Bi-LhQq":"2023-08-11"}] [{"vin":"nkxU4W-pjKeEnI-HKn-zD85", "charge_id":7}, {"vin":"vCSDea-XOk3nYM-uZO-MdWx", "charge_id":0}, {"vin":"JCwZ4R-oTiIyS3-9uP-5fuN", "charge_id":6}, {"vin":"9uvfKv-qdv4kiv-lCS-6Kde", "charge_id":8}, {"vin":"ZC9yTa-VqPU3eA-afS-viSI", "charge_id":6}, {"vin":"eabPKi-e0BoTUo-Y0L-Onbh", "charge_id":9}, {"vin":"Z8qSvu-emqvITG-3J2-FiFO", "charge_id":5}, {"vin":"Yqvgnn-jKfE8UM-Dkk-j5sQ", "charge_id":9}] {"rqlOUx-2Evnoof-B06-DwHs":{"F6iRMd-9Wr8rCf-agK-HhOh":0.2592456321360164, "bZJTeD-srsbWv0-6B9-ANqK":0.5731247544453553, "m5Uk0W-pcxozD2-Lys-TyYs":0.1905793611751156, "ryw3al-tKYZ0J7-JJJ-TDZb":0.9418369805858259, "fjytS9-477J3Rd-R8l-2z5v":0.4764718195914912, "0uOvcW-0t6wdfi-bBo-SFog":0.6128295295620225}} {3:[0.5108170713346386, 0.694733680487424, 0.5847721423779517, 0.3919952795818217, 0.7025307949387688, 0.1555599264146892, 0.432746943020953], 2:[0.4713742747750252, 0.4488223258534443, 0.1892436892846434, 0.8953290692964038, 0.7144884057361491], 5:[0.9815374065739699, 0.7603397070368498, 0.5366724360694827, 0.03759974733479021, 0.2484054636728981, 0.63148643240591], 7:[0.4565972568797313, 0.4430565803732961, 0.1513951545522643, 0.1611032259961541, 0.7101073832702474, 0.9705159004002205]} {"2023-08-11 01:27:12.900000":{"vin":"jtYqP6-v1voPvm-6Qm-uprK", "charge_id":805, "start_time":0.2329701990503849}, "2023-08-11 01:22:42.691000":{"vin":"PymHXr-Y7IP0yH-Vz8-ruYd", "charge_id":2788, "start_time":0.9872463526689467}, "2023-08-11 01:31:56.338000":{"vin":"4jI9S2-scL3YNL-qpe-SJgG", "charge_id":8278, "start_time":0.4654387595933797}, "2023-08-11 01:16:17.555000":{"vin":"T1koWk-ufY0H3X-xg3-QWZT", "charge_id":9552, "start_time":0.3842931023900751}, "2023-08-11 01:19:30.662000":{"vin":"qfT5jA-yIOapLO-dey-tj3W", "charge_id":8180, "start_time":0.3528909371787147}, "2023-08-11 01:24:34.595000":{"vin":"kylZUD-cUafFd7-lIy-bdEH", "charge_id":1456, "start_time":0.8611328701077273}} {"aa":["9cGpXQ-SIP2HAk-X90-jdzA", "UdKMv4-OQAIQBy-gAA-9JC8", "xY2ywz-sqRJSZs-WIx-Sb8X", "XV41A5-8642PmD-qp2-6e4f", "rCZ4fb-AK4r6JF-nqW-mnGe", "IxSocj-1irAxYu-12t-vKXL"], "mm":{"2023-08-11":"qMl9Cs-O2reqpZ-d0R-I6Ku"}} -67 [] [] [{"vin":"TGDwzi-WxxKkeo-6MV-ENp6", "charge_id":4}, {"vin":"Yd6oNd-y7PK4d0-GFs-M3dC", "charge_id":1}, {"vin":"yeSXnv-Be8vHDf-xx3-7nKp", "charge_id":8}] {"eQOJrZ-jgcN3GD-t1i-yMYw":{"CmSUYY-bSNuHV7-ng0-Mwmv":0.09340246757037196, "En91ra-EUR3pfD-q4t-3ocA":0.6740899544305328}} {4:[]} {"2023-08-11 01:23:04.702000":{"vin":"2XHLzr-g0nScny-wZQ-4twE", "charge_id":9597, "start_time":0.380992647680271}} {"aa":["Bf5cVE-HRnWpYw-Uyo-RYhe"], "mm":{"2023-08-11":"RV9dST-XvX55Tp-nk7-CTwP"}} -68 [["NWjXO1-MgHhJW9-qDm-TPeh", "PSPNXO-S5kPM0n-zDl-19k4", "WTuAHL-PbR29Lm-K2P-lB2H", "NfUJF5-H7jS7tz-paf-VSxr"], ["z2RJXc-Gzo0eRA-2gE-uiRr", "xCf3fn-V36EBdV-vt1-Nq75", "8JmTVS-Fdg1kmZ-DFQ-Zcpz", "GSKOKp-JbvugnM-fEH-M9Rq"], ["gD4GOs-Uo8GoEm-Jh6-ZyZ5", "8nJZS6-1pzMRQn-oTP-gyWd", "Bh2wgL-UcsZovl-Qui-I3Kb", "TYssTW-zRfzEN4-was-hmey"], ["IkLdF5-nqcHnIb-51L-9wat", "ZEWews-DUKqzmf-2WV-hcae", "wrlWLv-QiGjZei-8zV-zyvI", "2xBvRl-ebri2PT-TWp-sKx0"]] [{"xw3OCW-myeu4WS-fcr-1XRk":"2023-08-11"}, {"5zVrWY-TtIFxYy-StA-vCll":"2023-08-11"}, {"dXly8A-SmOMbbX-g4x-Phsi":"2023-08-11"}, {"V9B3Lr-UnzOxKT-ArJ-Wjma":"2023-08-11"}, {"wXKIps-Iz8zSYt-KWe-jb59":"2023-08-11"}, {"6OOZA3-Hvzh47R-z4E-E5MW":"2023-08-11"}, {"oHP5Gd-7htQbOt-NAW-VIga":"2023-08-11"}] [{"vin":"MQQ0JP-VggWoJ2-yVe-pnbD", "charge_id":4}, {"vin":"yVaMra-ZXjspHr-Vjd-rPjg", "charge_id":4}, {"vin":"b57pq0-ySSSwY0-05P-qDDY", "charge_id":7}, {"vin":"0iPeia-ItTARTn-taG-Or6j", "charge_id":6}, {"vin":"9XahgA-VUEfB0K-fDB-jUMM", "charge_id":8}] {"0QnBuM-A3OyzdC-xUX-5Tk9":{"IDNogz-pHaOzEk-c4F-Fi0A":0.844196067769477, "HM0mgH-zS8SPug-NLd-Lgcj":0.1073568923986608, "NxwWCn-Ai0UCp3-a06-1gKf":0.1577289050450112, "SXcmsE-Zy6VaCI-PZH-zQ6l":0.7233749321501123, "HLJjWv-Aa4WNl7-xSd-3bTD":0.8037999098884792}} {7:[0.07758810547926309, 0.08487947523622119, 0.4548075894348014, 0.8925188994490023, 0.3290618212330633], 9:[0.2701047150475561, 0.4015773524573091, 0.9390787086698963, 0.3020461441432944, 0.4095883387789641, 0.5161915200884376], 0:[0.6092400030873681, 0.06726592097286599, 0.0644033766655504, 0.4371531929781138, 0.6492833871020278], 6:[0.9557478590105815, 0.3163370718034627, 0.1549927139156595, 0.8211973783371688, 0.2575350286775442]} {"2023-08-11 01:28:08.205000":{"vin":"WXEc7r-BL91dxv-T0x-woo9", "charge_id":7983, "start_time":0.9205153933976353}, "2023-08-11 01:24:16.950000":{"vin":"wVN9Ww-wI78Qvd-pZZ-DuP8", "charge_id":6311, "start_time":0.05810329763876854}, "2023-08-11 01:28:18.841000":{"vin":"H21wtI-00g2hc6-3Q9-oODm", "charge_id":6201, "start_time":0.7886091118186112}, "2023-08-11 01:19:10.656000":{"vin":"a9mmjm-bxptLGz-rBI-2ZOB", "charge_id":1532, "start_time":0.5437494682141608}, "2023-08-11 01:24:33.197000":{"vin":"bMKT9c-2b8E5eN-PsF-44Az", "charge_id":8880, "start_time":0.09666947735432174}} {"aa":["8WKCAu-TVaVUbH-4v6-YZM4", "kwJ85m-LlpRO3k-yUN-WVgn", "6SVKE7-kBMGY1T-u0B-GZBW", "EJDv6R-b2vbxXg-mZV-1SgU"], "mm":{"2023-08-11":"1t3nYA-iVPrbFP-l8S-Qy1X"}} -69 [["KijBVm-c2k789a-PVu-ItY4", "T6sGjy-mnPQJP4-rJ9-vy4c"], ["zAGbz5-C64nFxO-fDg-Jj4A", "qy9zkB-x5FBojQ-IhM-EcIx"]] [{"0uwOJs-mMGrGsH-NbN-iFj3":"2023-08-11"}, {"4IYdHY-u4jKtxu-igC-0JEE":"2023-08-11"}, {"AfFPEn-fT1Z0Iv-4wb-yKQY":"2023-08-11"}, {"NjXxv7-Qqh5ozK-adt-5sDB":"2023-08-11"}, {"iimGHq-42vMsEE-7qu-zfm9":"2023-08-11"}] [{"vin":"z3FXbF-b7p5kM4-Rnx-eubh", "charge_id":1}, {"vin":"Gf4uVI-ryYDvac-uv9-LAY3", "charge_id":4}, {"vin":"CDDuIj-f3VzbA8-GM4-3Uui", "charge_id":6}, {"vin":"bcRVZ6-UhYeVDN-PAA-yeJD", "charge_id":2}] {"qHlqTg-Ofv34TZ-XC2-4xoi":{"XOprYs-PpTFYan-iMU-trij":0.5868702448498487, "IZt1tM-FmQnWEn-2ub-GWZw":0.7757291197671391, "s9WZ9H-iF1wemC-vy4-zEq1":0.6776072259464606}} {1:[0.222234266834496, 0.3193435731277943, 0.8816004519972791, 0.008614051730678973], 4:[0.5471299260604703, 0.7011579162176416, 0.4352971619078166, 0.5623263397366467]} {"2023-08-11 01:28:33.819000":{"vin":"1XlbFN-QyWV3LI-SaG-e6Rp", "charge_id":4029, "start_time":0.8422199586485317}, "2023-08-11 01:29:32.101000":{"vin":"ivG7Hj-O6dzjxI-scv-vd3o", "charge_id":4298, "start_time":0.360641397981218}, "2023-08-11 01:28:51.762000":{"vin":"NRPnf2-I0KgSyF-cMd-kizH", "charge_id":3616, "start_time":0.7567238767777844}} {"aa":["1nXK1x-9HIm3l5-DL0-WBYl", "ttVsde-7Amsjkm-lFG-N1At", "hATiU2-OE9mMDC-0lJ-ywfi"], "mm":{"2023-08-11":"DbV25w-f3VM3N6-knw-jhTg"}} -70 [["HKBu7f-9CJsfcB-DHn-x22X", "3CseZr-7o58TGm-apK-vLfb", "Uil06h-tyeldsd-opa-WiPa", "E4ti7M-yuziF8i-FHF-8Gp7", "DXNq1v-7VERP48-Q8E-Qe9A"], ["uvXnm9-TXexRUW-G2a-cZT7", "Ujv3zN-Q35JDnn-tip-mCoZ", "bV9A9Z-39WBVnM-paQ-Wc1w", "aiyrJZ-0mXpd2k-wtK-YIIB", "HxoSl4-LSjMmYT-l3D-rNHN"], ["xP61bS-If7U8ZU-wBi-udqF", "WEEX7E-d9wPriy-JxD-UkEh", "13FeV4-V8lBbjr-A6U-uN0e", "gpWdzi-LkyPbPk-tyP-GQka", "ebzQuo-wlibSEQ-wXM-z8wh"], ["pKwIod-OyzD9Q1-ue9-eyBP", "PAQpiK-6zciJ6j-k13-Q0PJ", "L1pLc7-rLIQq7F-RKK-jvLG", "m7FFIg-gwXjMsl-khj-mFYL", "9lMI5Z-Ds58rvC-Lfz-GaYf"], ["0rmRq9-0vtTOsf-yS9-wXR8", "Iap78a-sJsISEY-dj0-l66l", "LE4ARk-unLNfU8-tcU-4QJH", "uTPlN2-mm1baoL-sfp-OSAT", "Hk9QBv-YEkBXOn-hnr-AJte"]] [{"3abwPy-ukMWGWU-BTs-eKSr":"2023-08-11"}, {"aoAvwG-A5eY1Vy-PK1-QvN5":"2023-08-11"}, {"NCEHio-98FEDhA-9xA-rjuU":"2023-08-11"}, {"LKOzND-Gj636vM-8fg-rtU5":"2023-08-11"}, {"p8WTi5-lgQcZpg-R9O-oCNT":"2023-08-11"}] [{"vin":"tSRutj-sgo4Zx9-fbR-OmZ9", "charge_id":0}, {"vin":"SaflL9-y1fCqr5-zwF-UtxT", "charge_id":1}, {"vin":"xYX28I-PDm4cPL-umM-Z9Bq", "charge_id":4}, {"vin":"wfTArZ-QKC9mCy-zYR-M721", "charge_id":5}, {"vin":"nsoPVU-iiP7MKP-Gil-rSdq", "charge_id":8}, {"vin":"v5EX2U-SL8pZxW-DzN-4PtH", "charge_id":2}] {"8vV5Ig-2ZsZGY4-bfV-NCzx":{"9meyb1-XLbz2nb-kly-Pq7y":0.3757210143167539, "HoDNyz-5Gatl0L-EZz-5bQu":0.1104183455366734, "s4PvxG-arOmccI-3vG-mE1v":0.7929717408097942, "xLqWuU-GaKyEZc-GNb-uPqR":0.07595716385640072, "t7fCOz-u9pcCsK-CkC-emIA":0.5461176084547499, "LSj7AW-Mcnvu8y-DIs-A628":0.2730563298530834}} {2:[0.0298944740216478, 0.9714365118707564, 0.8661680940053891, 0.9234054287899386, 0.6604446176653759, 0.4069659495108542], 4:[0.8668538621240134, 0.3611658096024434, 0.2059107549542697, 0.8074344326905948, 0.4322034851071777], 1:[0.2876909106620456, 0.9925271938822068, 0.03553969962729986, 0.1499310836467337, 0.226392244715485, 0.6460624192767683, 0.4092320272346437], 9:[0.1642225376926598, 0.7540999046927834, 0.8056662286536563, 0.9852505060305374, 0.9427245964388594]} {"2023-08-11 01:24:59.971000":{"vin":"4jkA4y-kC8TmTf-5vA-Ckvi", "charge_id":3624, "start_time":0.3458551738066535}, "2023-08-11 01:17:09.138000":{"vin":"lDSnpm-dIm7oBM-6Dm-IdsB", "charge_id":8419, "start_time":0.6050714521877386}, "2023-08-11 01:23:00.480000":{"vin":"osc2AN-IV0DQ72-wXE-I0W1", "charge_id":2877, "start_time":0.9040510323123244}, "2023-08-11 01:18:06.026000":{"vin":"pSf2dC-3PaKokY-DMZ-1ysk", "charge_id":15, "start_time":0.2999061442616917}, "2023-08-11 01:15:42.485000":{"vin":"TMfGIb-4wqlkdc-N8I-jWgR", "charge_id":7413, "start_time":0.8383744673514338}, "2023-08-11 01:29:10.953000":{"vin":"gHj58i-wMqga3o-8PJ-bnAo", "charge_id":8757, "start_time":0.9316564693850775}} {"aa":["dLTJnR-YfogYG8-mq2-RRiW", "mTjfdC-EMOrnSi-GaD-lFNu", "LrRYQ4-r9KvMl5-NDr-EaDt", "MdTnye-0T2ndsD-JRQ-Ud1Z", "RewQg5-NtkdAqO-UgW-Rbwf", "o4n2W2-3ZSXplE-Otx-b5GI"], "mm":{"2023-08-11":"vFo4D5-pi9BoTQ-i4z-iMms"}} -71 [["J78ISD-Gn7UEkZ-9eK-ilK6", "1oe34X-G1VOEsF-XoJ-toOB", "DxbQKs-TfDmQoe-T12-Au4T", "DRdkVu-3FgvGLS-Xd2-60Zq"], ["DxAKxE-NAJ3v7t-bAW-x4qO", "SR42UN-02EGjAA-aDA-kvbE", "rSSi93-RNir1Bp-9wz-oR74", "2b4qwg-7XcHRxS-RNa-ZpA8"], ["cCJI4i-5Xz0v2w-TH3-DFkU", "d4u3wT-QfOakK0-jsN-NC0Z", "jZEzCE-zHQ2Tdb-rlP-Zn8y", "mUgxfB-SmJiqwa-N3l-Dax0"], ["8SDqix-FqNflfg-C41-Quyh", "tyXsal-eLgUOMM-OGW-ZUj8", "76nfAr-dWfNjRE-FA6-dFug", "nya7GZ-zN7Wgcr-kBp-NLW7"]] [{"vt76t6-YwxvIV2-8uP-5Qd5":"2023-08-11"}, {"8OuNm8-7EvIViS-ZLE-aSsN":"2023-08-11"}, {"KekOb0-qaVqrgB-fPB-vGiY":"2023-08-11"}, {"KPEJG5-ChVcmB4-a6p-Ua6N":"2023-08-11"}, {"mf9rao-66tkYAv-4Ye-hfje":"2023-08-11"}, {"3qcNIW-xGzUSZe-Q3J-oLAw":"2023-08-11"}] [{"vin":"QfleAo-h3qbceZ-MsG-m6Pr", "charge_id":2}, {"vin":"wEkuae-wzs6LJH-D6t-ZMjn", "charge_id":7}, {"vin":"j0PLep-QejmaTe-pw5-snP5", "charge_id":0}, {"vin":"UgFDYV-i0JCXB8-oy8-KYvc", "charge_id":8}, {"vin":"ailgNk-mqDm6ZS-FxQ-xs9G", "charge_id":2}] {"ie6XUp-nmI5DJt-zCu-FAo5":{"a5Y4Q0-5Yo5P44-5UE-ltHZ":0.6561729304089763, "HIXQmQ-7A6Rbtq-Q4m-Zv2N":0.7952120890568426, "jyWBDQ-xSZfFwe-vXJ-h0Ox":0.7993693937904595, "cu9wHA-qaDLOgm-6t7-mxjV":0.2939320551668124, "3icFAQ-I0xVWgG-X8T-pAGA":0.8718636551569146}} {2:[0.1525083066316051, 0.3454523111784535, 0.7684881029622597, 0.7993506966166495, 0.2444319528893922], 8:[0.1347861106840632, 0.7570160505784378, 0.3374740101083857, 0.6092485644120333, 0.9046653468193437, 0.4066370457034264], 0:[0.569492878397295, 0.06745605574862257, 0.5735585729049126, 0.8406617667594581, 0.1525784273733451, 0.3815264135329941], 7:[0.6690743827101662, 0.3374760354215898, 0.7325837970950498, 0.2375615825238736, 0.3700845716548422, 0.9484417543363359]} {"2023-08-11 01:30:15.255000":{"vin":"MmC44l-R6P6b5t-LQy-LlxK", "charge_id":4937, "start_time":0.8885891505686204}, "2023-08-11 01:18:40.187000":{"vin":"xOofy3-i98eM4J-dK3-Fk3O", "charge_id":3362, "start_time":0.6650127085922444}, "2023-08-11 01:21:13.618000":{"vin":"RiDDaC-OJfMF9B-iLz-Uws3", "charge_id":2253, "start_time":0.2823599435885674}, "2023-08-11 01:19:23.280000":{"vin":"zwEdsH-Q6oYjyz-8Ju-NSso", "charge_id":9899, "start_time":0.3161388615953645}, "2023-08-11 01:18:25.474000":{"vin":"9Grp1J-YO2rmfa-62i-xWF4", "charge_id":112, "start_time":0.2839480484993304}} {"aa":["H8U2EF-0ehaydm-PMA-gl0b", "hqI2VY-8nqgYw0-WaU-chEP", "dHcRs0-aJKaKn2-Lgu-yJLf", "ZkSWnu-0x84NN2-OAS-NFU9", "qtHqpH-LToR4SM-0zy-SABv"], "mm":{"2023-08-11":"fr39gR-i7PpLeS-qM5-7IQQ"}} -72 [["wAWHas-dC7YfHn-2h4-V53s", "o5QYBq-9O7vDiE-Gjd-378a", "egsjg7-QYQsLrr-1vy-W7jH"], ["8CqVhe-fx6xu0Y-hUM-eeWm", "w9Xa6F-1gLD2KB-Mdv-s5E9", "gQ2p8k-MHDbxCc-0cy-QQ8N"], ["5uQNvH-sOqsHOG-YmF-LddT", "gCzHje-K1sIVVu-lvL-tTtF", "wE9zB4-JiMBxi2-h2K-SCRe"]] [{"lnZJRS-ZXpd76h-Rgx-SuYO":"2023-08-11"}, {"Xv4iQs-hmECuu6-rSi-hLRl":"2023-08-11"}, {"RmaI3A-yJ9bkHF-Pdh-I3X0":"2023-08-11"}, {"Tx7J2o-tgKSrYX-Sms-SuAB":"2023-08-11"}, {"FKG2Xc-giDD962-ITv-2xeW":"2023-08-11"}, {"8XQ8Xc-M1UVNM3-gu0-EzkO":"2023-08-11"}] [{"vin":"fVX25h-z4DmRT7-LGK-dxE2", "charge_id":5}, {"vin":"WPbYeT-weKhzAn-Dl2-llDR", "charge_id":2}, {"vin":"isUdK9-fIWcQK2-qko-OXHB", "charge_id":3}, {"vin":"oN95lc-vKonTnV-vZ8-iXRt", "charge_id":4}, {"vin":"mO2Qj1-14UIfzj-UqR-w5Ww", "charge_id":3}, {"vin":"aOYI5T-DgGptWW-08Y-Dwy5", "charge_id":5}] {"aEUwNw-Id6P3NH-WCT-1Ks7":{"dK5eKN-Chj2eE1-LMH-0Da4":0.4287359708837412, "1LJfOw-iKSpsCk-IKG-ZnLC":0.8408483326119406, "yGTReH-UltmFu3-vyd-BUtI":0.5672716489764478, "xU3YNq-pVQHwik-wQo-I39I":0.9602682047436565}} {2:[0.5789772903390551, 0.4877794092035377, 0.5151198991472977, 0.2235565371155868, 0.3049232794357719], 8:[0.8194505803815813, 0.3097954738602396, 0.1734855997722714, 0.519965636665689], 4:[0.8699354418533036, 0.4288692255289976, 0.7242838763214541, 0.7244937606016093], 0:[0.199731814938207, 0.6137012815628313, 0.8700022644635989, 0.9252442347969377]} {"2023-08-11 01:23:03.528000":{"vin":"OkqBtA-300FH89-Cuv-EWl4", "charge_id":6435, "start_time":0.4404101562856072}, "2023-08-11 01:17:52.098000":{"vin":"ODDkum-BWajY2F-Ttt-t5eP", "charge_id":9413, "start_time":0.5666078509497287}, "2023-08-11 01:16:11.683000":{"vin":"teE02s-2apLg0Y-nQS-RH3d", "charge_id":4695, "start_time":0.0380926299580443}, "2023-08-11 01:16:44.586000":{"vin":"99Ch5P-nG8mz6O-5Zi-Yl0w", "charge_id":1993, "start_time":0.8639900839647179}} {"aa":["iixw4a-wjtpBCQ-TQR-Gwq7", "F1SX5X-NN68IbJ-TBt-sPiF", "yXDzLx-HhPeQdK-EE8-JQEE", "8dxFfz-6P96Qan-UIb-d6Tr"], "mm":{"2023-08-11":"YRDD4K-aGaEcaD-Jq4-Yp88"}} -73 [["FB3LA5-Wr0osX1-iAI-G60s", "EmoQk1-YxKiYZE-SK2-CDR1", "ctETaU-ih8pv8A-CIL-lCXs"], ["Ehe0ke-ZOy7JF9-qlM-Ev8d", "mc6EVR-NSx9c04-yqG-SToI", "4Tvb4u-rHZKjO0-Kp0-1t5P"], ["F23kM5-4G0YkxZ-4EZ-UuzP", "1HOF4e-TfiKJMd-eLb-UWRA", "VDAsOU-cK9naIS-DWZ-StrS"]] [{"XABX6h-ul376BZ-rNY-d7En":"2023-08-11"}, {"s1Hpzu-NhpuCh0-jAM-nUKa":"2023-08-11"}, {"a5a1AL-Hc3mBFk-hVZ-h6Em":"2023-08-11"}, {"Qv6hWT-gIKJNSi-ZQt-9MBz":"2023-08-11"}, {"USiUhc-OZNjvdc-TNd-cPYe":"2023-08-11"}] [{"vin":"Z668rR-ARkjV4R-Lz8-nGve", "charge_id":9}, {"vin":"dzj4P7-bGJ19Tc-yru-0TWs", "charge_id":0}, {"vin":"8iBLE7-aHTnF9y-CZE-2vew", "charge_id":5}, {"vin":"C4RlQr-WDMvzYA-9iU-bkVT", "charge_id":5}] {"IgFuFe-PNk74tz-eOL-UWnp":{"7M5Hy9-lL48pFo-Cwp-gky5":0.6285270238081867, "3UYPJZ-5oyNa3G-Ww9-nri8":0.4108397789216884, "B4Hm24-UZ6t2Xb-h8i-HtrO":0.6020434500606853, "v0mf1t-X5BrcQx-mId-zeSN":0.3451516657956651, "L7urgE-Ca2znN2-cQW-Llv0":0.5584463276869119}} {4:[0.7562118831749121, 0.7075390363864825, 0.9768521217227412, 0.6023707395806606], 2:[0.1955890456471261, 0.3969713514832753, 0.9843252480752234], 0:[0.5463468513278282, 0.8981182219098134, 0.3440890956649176, 0.8757479117433546]} {"2023-08-11 01:24:32.080000":{"vin":"Dm9SsF-HC51wbf-HV3-Jo2d", "charge_id":8303, "start_time":0.9725107903722114}, "2023-08-11 01:19:05.013000":{"vin":"uW3Juz-DiC1Fq0-bwi-J6Ub", "charge_id":9433, "start_time":0.1377050324067952}, "2023-08-11 01:28:05.580000":{"vin":"Osugi6-vPXRRAM-tgs-jE14", "charge_id":238, "start_time":0.525958892182644}, "2023-08-11 01:30:46.277000":{"vin":"YBiLAz-dvm1SLs-cyZ-l8X0", "charge_id":5117, "start_time":0.6059062734165274}} {"aa":["peG75n-i3CWUsM-4E0-DchN", "2vQQEf-LRLtvg2-oop-Imnr", "KHuRmU-rLFNWCh-KIZ-OCLT", "ztVivV-aDHKqMK-UZp-5ZvD"], "mm":{"2023-08-11":"KRJrqv-8h0M4I7-J5r-UvvB"}} -74 [["aSIj2h-Quzlyqu-pat-gD2q"]] [{"JafVcq-8njhCGs-cOa-gmOh":"2023-08-11"}] [{"vin":"Z5iqdE-3GPzX2b-NGE-Ngmf", "charge_id":2}, {"vin":"9YcdU4-f4za4lz-w5E-diMC", "charge_id":6}, {"vin":"Mi2huv-X67WqVd-vBU-JUgm", "charge_id":6}, {"vin":"w2I8KF-g24bXkr-PTK-QKZw", "charge_id":9}] {"5BUymI-KGQXpmu-q7f-aU6p":{"stC9l7-YP7mgCs-hdq-mSHe":0.07908976585263905, "pC7T64-ZS4OOeO-iS8-k2Kv":0.9458151810152464}} {7:[0.3263760205939285], 9:[0.1410369277204621, 0.7885564729425142, 0.2700937702957682]} {"2023-08-11 01:26:47.384000":{"vin":"C4qJhk-O5gzecE-ryW-s1Qx", "charge_id":734, "start_time":0.5362083075783354}, "2023-08-11 01:31:16.250000":{"vin":"nXmuHf-ztVRgFB-UEb-Fgig", "charge_id":9297, "start_time":0.6218545494657998}} {"aa":["cSa0v0-j9Dl0cX-H92-Or2y"], "mm":{"2023-08-11":"l8ul1m-usPXCPY-spf-3EQk"}} +50 [["OJyf5G-1l5N1wC-9Hj-IKGp"]] [{"Mh9Vgo-vmwsonZ-OvE-aVJZ":"2023-08-11"}, {"a7nqDE-M0JQhsa-I7G-5zAe":"2023-08-11"}] [{"vin":"SXPFww-a2tkCrE-GQF-KnSO", "charge_id":6}, {"vin":"qvBW6S-fD7XxGk-ezl-FGpj", "charge_id":4}, {"vin":"trPDbP-N68BmSR-PGx-jpgX", "charge_id":9}, {"vin":"zPMAsm-DQdYVm7-Cw5-4x7l", "charge_id":9}] {"ngasOr-QkHxzUi-an3-mvnD":{"j3zMIh-4jGIqZE-t5v-iAP5":0.625987684013195, "XqFnCA-tESLikA-joX-wE4r":0.3363446363188292, "h4qPEW-9FUdlyJ-aXn-FSn9":0.2436246850264091}} {5:[0.5407513708371531]} {"2023-08-10 17:30:37.989000":{"vin":"Wx6tPb-fFw7x7a-7oI-w8LJ", "charge_id":7263, "start_time":0.1679449798048476}, "2023-08-10 17:26:19.428000":{"vin":"h9IA1Y-Lsd2xZ7-0F0-e4qx", "charge_id":8930, "start_time":0.0138682364640994}} {"aa":["2qPsxm-QsHcRIN-STs-Ixh9"], "mm":{"2023-08-11":"mwbqWb-1HGkyb2-EtC-tEvS"}} +51 [["sBVI5j-gdL1cOo-YQI-IXJr", "rDZred-qSjyjjw-jTP-lBhu", "xXFoLr-6vI4ZEf-Zqb-YTbs", "m6XFf1-mclt1rX-FvF-nQaJ", "XFhrro-QosIPIk-dHs-d9wF"], ["j8X7fu-1fJEKXQ-Rtz-yVpx", "KWXzh3-wfWtVqp-Wjj-zgga", "Zjxzv2-1h73rDe-Tct-buHl", "Rmc896-R6MnQRc-t6u-JVi5", "GvsMv8-VEjxTVY-IMp-yVsE"], ["6k9sRr-oQeVsvK-szu-2tVP", "wR2W0G-gQXVWv6-2cU-BKVH", "DObfgG-AFn7XOI-tYw-Ta1F", "rNjOF1-IB3jWMQ-wxD-1X5H", "n02DgB-CFodhtQ-0ax-E4uK"], ["jfe2PG-W7ozOHf-mL3-atfA", "EB5GAW-3q01IFi-4iK-lcZa", "J4ELjV-Y9ZPT0B-QSU-211b", "Zgh77K-gAw8Bsy-129-UrUO", "JjiXCP-J9H2kY2-an4-EUBY"], ["4Dn1DZ-dPTPGYp-pVm-w9Tx", "ksyweA-yKuZJxN-MVV-awBR", "nmQpe5-0U8f34D-9eJ-znTA", "GygEiP-0r7YQkl-yJ6-4ier", "Qsu8kC-pDMuTbq-ke6-EPgN"]] [{"JGOYVi-4mr74Co-XcM-mViW":"2023-08-11"}, {"MlWwHK-RMJmcRs-Fmy-zj8l":"2023-08-11"}, {"cm8ZO8-dnzPMK2-Kq4-0Hea":"2023-08-11"}, {"2MDBEA-lLa2rNl-4MH-RAEM":"2023-08-11"}, {"0MCl20-VGkcTvY-M3n-VHhL":"2023-08-11"}, {"8OO4co-J9PFuce-x7a-7zyF":"2023-08-11"}, {"h8hgiJ-pjYIIzT-G96-IPri":"2023-08-11"}] [{"vin":"41fYNE-BlmV197-ozJ-yEyf", "charge_id":4}, {"vin":"6hXps7-zl6FJZl-Znb-zjE3", "charge_id":9}, {"vin":"6W91au-4KOUEVb-iNu-F6sf", "charge_id":5}, {"vin":"LtPhOE-T2AawgH-CBb-B3kf", "charge_id":7}, {"vin":"gTlKg3-RyKeRwe-x25-bDIS", "charge_id":3}, {"vin":"S1Y5Fz-VktR7PW-JaM-vSVp", "charge_id":2}, {"vin":"K8VjDI-9FK14Zk-laT-kxs1", "charge_id":9}, {"vin":"AaFtUS-1Hty9Ku-Ak5-ivBm", "charge_id":8}] {"AEaExA-Bo520FM-m8D-vX09":{"45AbDK-ZI3NDAL-MBK-UHU9":0.1785072792027651, "RMV2hk-Cyfb0b9-e8j-oMdC":0.4860786160307595, "n77pdB-9Bzi4C4-ffg-o6s2":0.5622987014897542, "O3Lmqt-TrYjDiG-vt8-Bomp":0.1939136112431907, "yA7ZBL-fiOZ5a6-eGX-5ZEh":0.6416163764279614, "px5xwX-DIeSh63-4Ev-FkBN":0.2591379673500095, "AJvUQC-Hjl1IVt-WB2-9wet":0.5117800998827022, "wIW4Yf-fgowpP9-s8A-X9qh":0.37736051041066}} {5:[0.1700666382941209, 0.4264700429633189, 0.2922353786055721, 0.509794805959957, 0.582851942990984, 0.8588434326795624], 8:[0.02499568257654983, 0.9737691446265131, 0.1117742274726051, 0.6297243954458742, 0.1260973908093503, 0.3375182210168451], 3:[0.1183025858479653, 0.6817375870979785, 0.1280896747715272, 0.4572591125592925, 0.6522023191794], 1:[0.273488000439285, 0.6277329395555634, 0.7268475070213382, 0.6404334819581489, 0.2767294943356197, 0.02203034237495372]} {"2023-08-10 17:24:38.430000":{"vin":"zWkPM6-Gt0a01I-OkZ-RVgV", "charge_id":9889, "start_time":0.1578405336139553}, "2023-08-10 17:25:11.069000":{"vin":"bYq0d6-hJkwCkJ-8EC-W1tc", "charge_id":8559, "start_time":0.006868030161507499}, "2023-08-10 17:25:50.362000":{"vin":"DKdNeT-Z8e6bue-3WV-oz4M", "charge_id":7662, "start_time":0.8718064619367956}, "2023-08-10 17:30:34.826000":{"vin":"0zce3x-RfFT3t9-oWP-I6gs", "charge_id":1346, "start_time":0.06755262400087614}, "2023-08-10 17:25:46.334000":{"vin":"TOY787-DYrX3fb-kcY-W6AB", "charge_id":4112, "start_time":0.3494696933972377}, "2023-08-10 17:21:36.222000":{"vin":"Bk17ny-zAQSUvo-FlT-tu7u", "charge_id":5407, "start_time":0.2265186267992506}} {"aa":["DkiuiF-rnuvVPY-byF-QuOr", "1pITZu-IzgylrJ-KWr-sdKa", "XYH5vz-DJ9xNU9-xCZ-4dmC", "cq2wLj-NrsLqit-v6g-jMby", "LU43CY-MFRLr9Q-wYw-ddF2"], "mm":{"2023-08-11":"qub6zo-LRZEPE1-vAm-WtX3"}} +52 [["ZBSvQB-aQBY2nd-MCF-soCt", "vbC4hZ-qdr16gX-Lxy-om5o", "cz4kJJ-6M6SMMI-ZFL-rahc", "qYPejc-FuxoLFj-bNy-ZYGn", "4wF8bB-wk1L9d5-Ke7-L8DG", "0qtdJX-lonqdSw-R2M-w5Rv"], ["olt9LY-jZ5urI2-tUQ-BzlO", "WyXhga-8bHzpxZ-2l8-TEQt", "sVd6PQ-Ou5Wqf3-fBD-ePsE", "JWyeob-I1pvFrD-Gj3-Q08o", "yhz9UY-yeGxUwN-N1b-R01q", "bLWLvI-V43WdsI-4lp-S15D"], ["tSkvqc-NsEJXRf-8jr-qCmg", "InREIK-3hCdQq7-GId-OcUV", "wOecEe-4p4nCA3-qHK-CgHl", "UHGwmD-iTn5SYe-Fsf-VHuI", "WQNS3L-6a0IZ5t-aOD-pJTJ", "ueJabh-NYDHQrM-oU0-A1YQ"], ["heHGxB-5F2dL4y-6W6-ubCC", "2YsY71-ahDUlja-iRK-Q4lu", "2wjBg1-eZikgaq-TbV-nitL", "VBDgNT-9R1Gt86-V2M-is92", "6TDv1k-op24SGV-G0v-AB6q", "H01qFG-Ki71EsO-vvi-6ME3"], ["YK4DJc-XVFPLhR-qf9-liML", "v3LMTq-qGURBt1-cT8-NpZv", "X3fQSh-bFdmn56-OGr-bcr6", "njwWAe-Gy3G7TR-kno-MWTp", "jdqbHe-8JYKvpx-x8S-deRg", "AK4Ain-KUSAPnJ-xCa-o1dl"], ["ydpKFG-9ZvzGZC-lDP-piR6", "IjpFZo-n1HMpt0-Cbh-QJBu", "kdMvgk-AL80Ce3-zTW-umXy", "vaRCRv-4cKBPBh-RoK-uw0Q", "bhJbot-0HLqEBp-Nbv-YW0w", "1dRnGO-cITeRuO-voI-sddl"]] [{"EJU778-4rkp97p-AN2-xln5":"2023-08-11"}, {"OMNt2e-uUvimc6-hSI-AtYw":"2023-08-11"}, {"OrfpYU-j1wp7nh-vBD-dKrH":"2023-08-11"}, {"SYa1iU-DZi9XUK-S05-FVPj":"2023-08-11"}, {"InLBze-TdbnQqB-5kA-WXFI":"2023-08-11"}, {"oZXWlU-HeVXDBi-U1R-O0Lb":"2023-08-11"}, {"1jC94W-4FeKChe-TOk-aBdS":"2023-08-11"}, {"KU90Ac-1rAxcGs-3LW-G33J":"2023-08-11"}] [{"vin":"mB1wMA-25TeXAF-koh-U3LD", "charge_id":6}, {"vin":"ti7pKz-IpjwaJb-4bR-Hsv7", "charge_id":9}, {"vin":"zaA1eL-whJ6aPq-tbJ-BfxY", "charge_id":1}, {"vin":"1Pzv9F-3iBfmeW-Tof-UzFU", "charge_id":6}, {"vin":"YjMgGA-zd9hQfp-b9M-clQn", "charge_id":5}, {"vin":"AJ1v47-R4iR5Xv-LwH-QQeM", "charge_id":2}, {"vin":"G5T9UZ-BelHINh-8Au-21BW", "charge_id":4}, {"vin":"buJWf1-J3Hlxmx-4wM-kPNt", "charge_id":9}] {"YJdqhT-VsB2Ggb-zPa-2Tt0":{"PoSy1Z-Dkffr0R-iOr-KWVz":0.2122697431552237, "pHx8Do-r5yqvn7-4Tr-xweX":0.120128226768535, "ofdTLa-rvfYoUa-a7J-mzwt":0.5104783468857063, "YObyoB-iZYXZf0-Obz-8x3n":0.648071472230249, "Dl9PvO-Znb0F00-oFZ-OcK2":0.9336549413795939, "8a2Irz-phXvS7d-xJx-uQKv":0.9184785275241031, "ZnNJKu-77MbRPM-CfO-LYVR":0.4437479922182787, "gC80J5-XKsoNjH-db0-PEd0":0.9126170535701229, "ywF3pC-P91wFbd-dY6-zAvL":0.03935272525999434}} {5:[0.1095200626799708, 0.5326028937979516, 0.8060140669268681, 0.4505727832758978, 0.4720516029232681, 0.3338205256060737, 0.8180208046571064], 1:[0.8852323802900887, 0.3936906402008711, 0.009063507617334543, 0.6718020739313536, 0.4776097486972591, 0.03634630538503381], 9:[0.9745187582597405, 0.5329473911569335, 0.1337213123674127, 0.1664769754188556, 0.9585403121110279, 0.8541557798394191, 0.8138556208878084], 3:[0.8158672597965407, 0.8415505009462715, 0.2435423353229933, 0.04768732903974227, 0.3537519796773547, 0.9333370152687068, 0.2363489169167885, 0.3578394548105978], 8:[0.02195386085297124, 0.3554487712668294, 0.6615765479331985, 0.2878190508421222, 0.03122025084043323, 0.6427488195845875]} {"2023-08-10 17:24:49.961000":{"vin":"LUzbIM-FicsJ5v-fAn-PKEh", "charge_id":3384, "start_time":0.8429338153414312}, "2023-08-10 17:22:49.842000":{"vin":"VzJYgc-WT3HAy6-Nuv-IcAy", "charge_id":4916, "start_time":0.5424016158099249}, "2023-08-10 17:17:39.600000":{"vin":"5QN7Z9-IZ4c0ya-XzS-oyUR", "charge_id":242, "start_time":0.2072576413495201}, "2023-08-10 17:16:37.045000":{"vin":"E1ENuJ-KswTM63-j2y-GWxD", "charge_id":8395, "start_time":0.6927241557707922}, "2023-08-10 17:27:36.100000":{"vin":"3kPnr0-yFe62Kl-Uq3-hfN1", "charge_id":5421, "start_time":0.1554667403138459}, "2023-08-10 17:20:09.702000":{"vin":"UCeBR9-jrruL6t-V5n-gP3t", "charge_id":2070, "start_time":0.3970687223420232}, "2023-08-10 17:31:47.863000":{"vin":"ivfz6d-sgtuhOV-DUQ-bAu9", "charge_id":3178, "start_time":0.8169479600287797}} {"aa":["DdBVX6-ir4ZFQF-2LE-4dAb", "7wpEoC-MK2MvoJ-onr-XHN7", "j5quwH-VOqhQsO-WIJ-m6nC", "YdICtd-FKq0mbK-mNo-CY7G", "nHMrI6-cqlREYX-HGq-G0JN", "KGmQQf-VBRkP1Z-3JB-WBLd"], "mm":{"2023-08-11":"D6LJ2X-1UcHumS-JAW-UbOl"}} +53 [["47WIS8-D37ArUU-CV6-IYG3", "uWvd6M-9MBOee4-KGg-2oSG", "y7VMGg-t2zOLt9-AOK-sbjR", "tZgIOJ-AYqQi3o-NSK-X1GF"], ["1XpQgP-gLIjrtO-4Zu-O5cI", "nk8vfb-ZFkclF5-cX5-xtBv", "YMT3yV-obXtNAe-b0W-GZlD", "36Au2q-hBGOfJA-7XL-K7qb"], ["oevn57-q9YiBvC-6yu-1yqM", "7kTndL-jA5ExoF-OsI-wQM2", "oX21RP-aO3GKm1-b0Q-cQQC", "yW2pbp-B3PooaJ-yRx-dgo8"], ["kwov6B-RAtH8QU-OnB-549V", "saJYw9-brNhBsr-2aq-y92u", "pbP7NL-6Fim9UQ-OMM-PLz3", "03qWjx-ClOrhJO-Gda-nMLA"]] [{"f9fPY7-xePmB2Q-Vhx-qaj8":"2023-08-11"}, {"6V6hrD-q0mffM6-7U2-JTHW":"2023-08-11"}, {"TEKl1b-8dKwaxs-Mhf-sC3J":"2023-08-11"}, {"MN1vTk-sGWIJgG-Yha-5DFE":"2023-08-11"}, {"ZwNnTT-ni0OID1-Miy-fZHo":"2023-08-11"}, {"ZVE2zM-oHTuEYI-EbE-XX7o":"2023-08-11"}, {"R85D59-iqTLE6z-948-GM9D":"2023-08-11"}] [{"vin":"mwcQ91-xYjlxUP-qZT-eJqF", "charge_id":8}, {"vin":"ncDhIz-0oZhq2m-Ew3-6WjP", "charge_id":1}, {"vin":"PyS3kC-aO2CPH2-BNN-oqqx", "charge_id":2}, {"vin":"2xIKH0-v3faZTl-fOo-rI7K", "charge_id":8}, {"vin":"ROR1jk-O5vS2Kd-dpZ-h72n", "charge_id":7}] {"U7pxgM-KShkiX7-Keb-PHsM":{"Jq14yl-XpoXLJX-99I-Ve9R":0.2784139613362793, "JDVF3t-xFdwu5P-kpj-OauK":0.05174728870278311, "3ajEN9-xqJHBh9-us5-R7MF":0.3469192046700897, "9X8M8I-UQaJhDO-9i7-nChq":0.3018919459484262, "P0gt8U-ds5LvWs-Vbt-gaT7":0.3400361501804748, "WoFf4O-vkLxKWM-Sz7-G8Ox":0.9261570442932751}} {5:[0.3105743065465537, 0.08772836767962744, 0.6921575663295787, 0.6959748289457285], 9:[0.2215892614044007, 0.334159816938011, 0.327421430497192, 0.4861872798090753, 0.8364978227937394, 0.1101084834829856], 2:[0.1459836382064356, 0.3284361771162454, 0.00902187158361778, 0.7926872473953445], 7:[0.5400736561823897, 0.8932790579874702, 0.0044636868329746, 0.8164341088142658], 3:[0.3287245418435573, 0.150084014153181, 0.5045330146679782, 0.5904841498223871, 0.105812522019689, 0.5984371322829315]} {"2023-08-10 17:19:45.586000":{"vin":"11jVvo-9Oidxl9-3rj-ogdB", "charge_id":4134, "start_time":0.3898729376781794}, "2023-08-10 17:16:59.650000":{"vin":"srRfgD-U68LMHa-Yk1-hyB5", "charge_id":1407, "start_time":0.3008674220521801}, "2023-08-10 17:22:51.450000":{"vin":"vcHWQw-jLhG31Z-dq4-jGkq", "charge_id":8517, "start_time":0.999917828828064}, "2023-08-10 17:32:10.235000":{"vin":"OF613x-Z18yN3r-cpo-ifE9", "charge_id":6809, "start_time":0.3624238623966848}, "2023-08-10 17:25:12.599000":{"vin":"iKubfU-P0phSEy-5fH-LT67", "charge_id":1515, "start_time":0.4587106504603173}} {"aa":["E5EREH-ACc2wdA-bPn-U56J", "PxLRTM-n5BfpOh-N72-XdCY", "xCOXOY-p6mhzJ0-9FN-VTKp", "ezcySD-RMTak3u-l87-dQe8", "A6QYHI-aBYZbgi-0JX-S5Af"], "mm":{"2023-08-11":"DybtpN-j7vofti-uKr-5mT3"}} +54 [["tv7ku4-B0qy58C-rnk-kkhr", "CG8oh7-fA9GKEc-wne-D3t1", "thnMmZ-KkcvALw-osb-UIaf"], ["rfGgEs-EGKBaBY-bJt-daf3", "GujPmo-qQAxCdy-QNT-gleN", "DOego0-LyeJ5lK-4Z3-qFR1"], ["Vv4xgi-vVeu2nW-zJq-YTzy", "UHKGZ2-cUra2rJ-XSB-GMN5", "m2ZWQ0-Xs1IZya-HUK-63jD"]] [{"yeNMdp-6nJycB0-Tv7-fKnA":"2023-08-11"}, {"FvPZQL-CZrZ4Dk-ww5-DF3Z":"2023-08-11"}, {"1pQYQx-Z4bB3ee-Qga-tJPG":"2023-08-11"}, {"xWZ7Gy-b0uCoyn-W83-I7jp":"2023-08-11"}, {"4LPKBa-GHghXdY-jn8-uoEQ":"2023-08-11"}, {"ljkpDM-lcjUezP-khm-iDs5":"2023-08-11"}] [{"vin":"NoAlqA-56udIoA-5EX-JOIl", "charge_id":2}, {"vin":"B8bibN-6GEWLUI-93I-d4do", "charge_id":9}, {"vin":"SNwK77-8TH2RsG-MJ2-tKS8", "charge_id":4}, {"vin":"A9LvGS-2aOsPHG-Lwz-FtGm", "charge_id":3}, {"vin":"2kOOyB-krSdpzw-TRx-QH8n", "charge_id":4}, {"vin":"fqsXj0-8HB8czv-ZmJ-7Ckt", "charge_id":0}] {"JhCyv0-MKRMKvR-aWn-5MB6":{"icdwkC-luzK634-b2u-iEYF":0.4938651434973199, "EuzIDF-MJDGRfb-tf3-TgDn":0.3519559100997417, "FpsnY1-Z6jjGyH-gt6-BvQH":0.4337762056803064, "KAxH7u-0myxapf-dEK-7FYa":0.991984799775244, "xYtrIb-lbsRBwW-RKS-eRw4":0.5741690975495818}} {2:[0.7299412764262242, 0.9260029048793296, 0.5925181040243392], 8:[0.1001250718790359, 0.3431254184444573, 0.6691677401146177], 0:[0.6478354429360543, 0.6767751382169649, 0.9633797914100292, 0.1223335712078517]} {"2023-08-10 17:31:17.873000":{"vin":"foTlm1-1V2Szcg-1aC-MRrj", "charge_id":6912, "start_time":0.9511447433388256}, "2023-08-10 17:16:16.618000":{"vin":"L5n0DV-bJpJ2UM-a3B-h0vE", "charge_id":327, "start_time":0.765822377291262}, "2023-08-10 17:24:28.231000":{"vin":"mMwYIl-C05IUrq-XuX-CnzU", "charge_id":2368, "start_time":0.999737189962702}, "2023-08-10 17:29:06.290000":{"vin":"rTuq9T-F70Hyk1-Z8s-ZLqD", "charge_id":744, "start_time":0.8416130249155471}} {"aa":["sO6sfK-baO1xra-t3H-h6H6", "bF5B0y-424xZmC-CDB-aFkh", "OYSGIr-miwxtIW-6xY-VZh7"], "mm":{"2023-08-11":"QqMyyg-k6zEC8l-O78-lql8"}} +55 [["IDDP9l-HAAtgJO-huQ-EsgQ", "bMTI9M-yiJwpBY-BYW-5FAB"], ["BbFM5T-1WumGnp-hBE-evyG", "uoi5pO-ELgBUoV-c4u-MGzw"]] [{"vXONHn-e4K7wwf-RRH-gfYJ":"2023-08-11"}, {"lyIsB6-5QRyiQy-RBa-e5pL":"2023-08-11"}, {"eAeanR-xnq2Ylk-85Z-DTG6":"2023-08-11"}] [{"vin":"Ckbjdv-PKi7NsU-JFJ-oNA8", "charge_id":1}, {"vin":"2o2uiK-JyZ3HsU-9LU-NL9c", "charge_id":0}, {"vin":"IW6Z1R-7hjCW6w-fLI-uqZn", "charge_id":9}, {"vin":"nzo4jb-Z9aKR8t-ERY-rChn", "charge_id":2}] {"MsVPVP-Wz76O3W-M5u-6OZC":{"Rol41F-LBr4xIj-aHo-1z7r":0.7833197547141593, "8aI88U-jcHxuax-KGu-CveS":0.2183506335135603, "cXLOdV-jPT3pRZ-WVm-jsBC":0.604329438109007, "Zeorfe-Qt6Cjkf-QuH-0Bqy":0.4620636946252842}} {7:[0.4746254106090101, 0.9857918700983427, 0.5769353163838751, 0.1047035813690067], 8:[0.1361586396241807, 0.6908150185985129, 0.5613378428541096, 0.1870891763057041], 0:[0.3511016662407238, 0.9075663088683685, 0.477110729748815]} {"2023-08-10 17:15:51.033000":{"vin":"U9NRbd-0lzKeh7-axS-G16W", "charge_id":8905, "start_time":0.7292260002107532}, "2023-08-10 17:22:39.875000":{"vin":"7Mmdex-3HlmTpR-XLY-rLv1", "charge_id":5332, "start_time":0.1762868182364091}, "2023-08-10 17:28:22.816000":{"vin":"er4l9A-yoTjsdx-8rd-AaOP", "charge_id":7931, "start_time":0.4702979685445514}} {"aa":["6z8Xzp-2y7lDnn-33P-OqY5", "eNjmCC-4jP4Zre-FOr-gQzr"], "mm":{"2023-08-11":"edoY8U-e2ImHTH-wCk-gSKC"}} +56 [["0SGkZP-19FJJaL-THD-s1fw", "ExSXMv-VBOFSSw-Sg6-14Eq", "BwOxTw-ScMrtz8-AGG-hrVk", "RzVFvM-MnCYjcv-edV-GLcq", "Fwckw8-O2JqmoZ-6vU-DuOh", "G1WHNn-neF869S-me9-TRPI"], ["ZjUIXT-IbpVwur-uQE-ELnv", "YuOMYW-hxV3kVk-CPx-om2u", "zUtaqm-DgkYNXC-OHr-7RXt", "Nov4Wi-6sCuNy8-s3o-Fc4Y", "ubA8qi-YOF4tnI-3UV-aTNO", "R2BCgS-QVsoOkT-BKs-v2Q0"], ["JrTyT9-UPN5hqC-CO9-v3gq", "2TiX5V-Bsw4Cl1-cjd-h3Vx", "n3cWcG-z1AJcYj-txy-Dm1H", "vF36BW-ZZk8sGY-eHs-6Gbf", "jqxuw2-XJi0yMN-DaW-OEkC", "4irn8U-c9RY6Ef-Ul2-cbUJ"], ["vK0BGO-wNN7x0i-hsD-e5SL", "vqaheW-Q15fcjD-lwZ-0f4Q", "yxyaij-TWMXyTc-x0L-mdjp", "icemcN-YCVC96Q-gNK-cKcx", "YvQ2B5-auonVY5-yBs-8MeK", "k91VC6-4S20Ogi-m99-0rcx"], ["bCKSRM-rA0wtaE-uHa-qnQF", "cYalS3-Jx78aAN-j8i-83ph", "iIuVam-hsiKh76-1IR-1BEG", "nK8dX4-RtL0NzQ-Cr4-GcKH", "0UGFr2-FrMVoOE-XH9-YYX2", "eNhrjH-YFr0wGi-rtW-AOSW"], ["TvAp3u-4goQDzU-Ywl-M7kd", "O92Rkt-s0yqc5n-OCC-DQ5y", "o7IktR-dASp1OP-dsN-abpf", "yvDWnP-V9tOMqP-Nke-qZlD", "PCxx3p-YjenaxU-wS2-gsFh", "3Q85bO-X7h8V3u-jAE-NqmW"]] [{"zO3Zbu-xc97X2W-KW8-MvYa":"2023-08-11"}, {"B4R32w-phZ8WJd-wjT-aDYh":"2023-08-11"}, {"FpIZES-JTz76gt-Z4J-DTff":"2023-08-11"}, {"ZgkK7C-0GxwhT4-dg2-lshn":"2023-08-11"}, {"FiRgdi-XAz0EPl-pHO-ANq8":"2023-08-11"}, {"1v0U97-1n67bPm-jmw-BRcM":"2023-08-11"}] [{"vin":"1gFWcC-xcp50hp-4p7-1EVz", "charge_id":0}, {"vin":"Kgp18n-YTsyj7J-e5T-c5b4", "charge_id":2}, {"vin":"WrgDxH-nXtyVO3-3MN-OfKX", "charge_id":8}, {"vin":"SMjdRd-sB0ri8I-QT2-q1z8", "charge_id":7}, {"vin":"uY313u-aXZTQuQ-6k6-BWQg", "charge_id":2}, {"vin":"iFW48f-kUUSxMX-Vdv-fvEx", "charge_id":1}, {"vin":"7CokZM-Cq9uv8A-oiK-mAMH", "charge_id":2}] {"3ozluK-ci3e3R3-gmq-C5ho":{"vusH9K-GHvOYrC-l56-kVQh":0.129388566712362, "7BKEm6-2Clqn39-rCX-YUHQ":0.4809108845587262, "KTWxg7-5ao8Wwp-t3z-gymk":0.6294341468307141, "iwgn9N-9CFVU5g-DLl-lraX":0.1346828032226828, "SkJcRB-7FqgMxe-PR1-IOlo":0.3087147067379575, "h4Pxo6-ibJ8j23-mDD-vTOT":0.4731438850707492, "mYAmYG-Co9mcGO-qbm-YyAY":0.3073838041496642}} {0:[0.7525522283577646, 0.5203187152521088, 0.8792304693362081, 0.01340886748698289, 0.7557097854781354, 0.9546731696243579, 0.4144012408947869], 1:[0.9150561736362857, 0.3041083280603063, 0.9684160362225539, 0.9409237111830627, 0.00354028801537265, 0.130343409616228, 0.9103415272904609], 6:[0.2682159399833898, 0.6639432709162291, 0.3392017811899227, 0.8380127499413075, 0.806416028074902, 0.1240849470764859, 0.9478796564929635, 0.5731165220662204], 9:[0.7639131751196545, 0.6666784120698608, 0.7397691301158906, 0.9186054374290861, 0.003110414383702298, 0.6037897503982196, 0.9985326765983019], 8:[0.2988361843513174, 0.103517835152557, 0.5419295412535603, 0.8073911299674146, 0.05102931349342199, 0.8089829465862552, 0.918047804060321, 0.7216668725501939], 4:[0.1713016023542038, 0.2645729861704954, 0.9243517891965869, 0.2873064271854678, 0.7047728931934353, 0.9883572314533633, 0.5951113350943464, 0.9609428256171617]} {"2023-08-10 17:18:39.350000":{"vin":"lpeXRW-PPFDZen-LvV-2bfr", "charge_id":9558, "start_time":0.7456703072443472}, "2023-08-10 17:19:53.775000":{"vin":"we2QqG-1KirOd1-sI9-IJEm", "charge_id":5408, "start_time":0.1406524653813722}, "2023-08-10 17:16:55.770000":{"vin":"TmyYbJ-rcaycRp-ON6-nwBl", "charge_id":9774, "start_time":0.1870807255181824}, "2023-08-10 17:23:01.164000":{"vin":"13XTKv-LBwCJhi-sTd-ZslV", "charge_id":33, "start_time":0.7722409867065521}, "2023-08-10 17:17:47.494000":{"vin":"abagbu-IW3cP5T-2g7-OG32", "charge_id":7118, "start_time":0.1189162502162576}, "2023-08-10 17:17:23.207000":{"vin":"6bK6Hu-8jePZHC-MTt-HUXf", "charge_id":8998, "start_time":0.3419994373830386}, "2023-08-10 17:27:56.164000":{"vin":"aayyRg-1CeZoSu-Zri-wfSx", "charge_id":1744, "start_time":0.4839834661494162}} {"aa":["GNko8o-Boz741L-kPW-XNiQ", "6RsNb8-SCKCBjH-MdP-BLmu", "YeMqrb-pLvxNLT-uVz-W0q1", "cuAXjr-jI1QUjz-nCP-5ghg", "NLp17C-8V0Zz2N-ZlN-Eo2z", "pl4Yze-I01JFTN-zoJ-y0Al"], "mm":{"2023-08-11":"6CdfNp-m1kJt11-a5u-qgoJ"}} +57 [["xjLC0V-fZbCLn5-OhF-tWgX", "H7KVdf-KYc1y5u-Wqe-fjPI", "6y3cDw-YzJoo5I-xrH-92hN", "g4ExGu-I1Gg123-BwX-bLTd", "yCiyB3-vWe7FSW-b5A-5VnG"], ["0VDAIo-WEmr9tJ-GTP-HTqt", "wlwghG-NRybwTB-0wa-7Y65", "wDtlBa-KTsNGpQ-xi1-BNGP", "MnZeBR-mIihbIG-xIB-FMtI", "y31rp3-KZEBlP7-zUh-z3Nw"], ["4uvQS4-YTd8zNZ-H0h-ZB5n", "dpma3c-ZwlWGAW-qx4-xL3u", "d0ioBH-G5fmU74-Xio-afGU", "JU1nD5-c7Dy1ym-aqc-0Zz7", "CxMyPc-UH4bGjo-L7u-8WxO"], ["PTtesO-5FL0ggm-KrR-8apS", "fIa5Az-u74YSXP-FWL-bYjw", "mMFpnl-bnVbkWg-aJl-bqAW", "HyKtYi-FSP3KeN-3xT-vR7I", "W6XVtJ-kfrAZl3-Mqi-TEDe"], ["fYc6fU-dfgP3bu-EsY-F7eR", "SRuJDK-R1veC02-OYg-RzBS", "ICM0iH-yCKTgam-H4M-VZAf", "yb0dm1-UKJ7Myt-5Xh-Sa2G", "VMrMry-c74mliy-LWU-EFVe"]] [{"K3rLF9-cv4vCnQ-Vx8-6KFM":"2023-08-11"}, {"R3cD7L-rWkq0UU-vJ0-WmGG":"2023-08-11"}, {"nXDkVH-oUSxhvt-WYK-D6ZR":"2023-08-11"}, {"xYgtFe-NTlGci2-UDa-bxiL":"2023-08-11"}, {"NMao5a-2BCieWb-tsC-6mot":"2023-08-11"}, {"UfkJb1-mD2kzmM-Gzc-b3Ko":"2023-08-11"}, {"WrGdy1-zKDeXyJ-RZ9-l8IG":"2023-08-11"}, {"suGsAt-d7iu8go-hNr-njpi":"2023-08-11"}] [{"vin":"LMqyVM-Uydqj0R-Bnf-IUWl", "charge_id":2}, {"vin":"RGL9wJ-ILUGycd-Ymd-igcq", "charge_id":8}, {"vin":"FN6HTM-mcfXylZ-PTz-gyZo", "charge_id":7}, {"vin":"05CH4X-AbQdji4-jZu-eL7e", "charge_id":1}, {"vin":"JJP5Bi-4BFFM8T-ux1-gUF2", "charge_id":0}] {"Ju6K5d-zEMnWG9-L7l-QjAa":{"TDXY00-qRlBafH-4Kj-0GCA":0.5227028115723444, "dGfVdV-Jyv85Tj-SK3-cKJs":0.1053550385918921, "IZiark-GCNJc9k-iAQ-zWqx":0.6392321712185968, "GcYQOH-h50Xe2P-ApZ-5A39":0.525933769632311, "5Ntpy0-WAtHnaR-Qqn-ObNP":0.9031187380770488, "bRux7C-KlrVYNS-7UP-g6h5":0.9580617594212908}} {7:[0.9656121197784733, 0.6592734098621122, 0.2739019612541155, 0.01366028991365853, 0.1813631749663133], 4:[0.141307729992178, 0.5455543114849581, 0.6812056106659004, 0.2892375116061335, 0.09408023757345707, 0.9232139106288936, 0.5992306345160531], 6:[0.9765132272606117, 0.4731640380711279, 0.07522271838321337, 0.442210144648944, 0.8330747996642478], 9:[0.8830207795706935, 0.502873103103274, 0.4640703655720798, 0.8318661515981369, 0.9449570391195257, 0.6151676126043052]} {"2023-08-10 17:25:21.986000":{"vin":"8XXnJy-C9fssTo-Lms-2zjK", "charge_id":5917, "start_time":0.1419896861837719}, "2023-08-10 17:27:05.100000":{"vin":"Aezjvy-a2KfZo1-8EP-49xe", "charge_id":9169, "start_time":0.6886316934962607}, "2023-08-10 17:19:54.626000":{"vin":"652NTa-zBLe2Cf-HLj-U54B", "charge_id":5091, "start_time":0.1393061353913715}, "2023-08-10 17:25:44.821000":{"vin":"pxnUhN-L6MBkA7-jJY-mfte", "charge_id":8279, "start_time":0.2652365789894289}, "2023-08-10 17:27:16.453000":{"vin":"dXL5rv-NOTXI2I-H5n-e3JG", "charge_id":1679, "start_time":0.8934533395824213}, "2023-08-10 17:25:50.843000":{"vin":"qjGfIp-vi4d0kX-nHZ-N3Jf", "charge_id":3034, "start_time":0.5151735040237844}} {"aa":["haaxCE-0Z5MO7h-jT4-qPyj", "uzjhQX-8B6x9jK-MXV-sPfy", "fsXMlC-1HgHySU-CT5-9r9z", "23gfYA-lNd5Z8q-4mx-Qx88", "4bloJi-gT5EV1V-PvB-BUKw"], "mm":{"2023-08-11":"akqEqV-63IgvI3-xP4-sd2w"}} +58 [] [] [] {"TV7uGy-aO1AV8O-WGo-G9QJ":{"2ijOl0-YuQ24Xb-84Z-6yuL":0.5422329420566728, "6Y5MKA-fUSOCA4-t6r-McwZ":0.9847437995543189}} {7:[]} {"2023-08-10 17:30:33.958000":{"vin":"GuR7Av-ITVNylK-FYJ-lkWG", "charge_id":8409, "start_time":0.4128720093520603}} {"aa":[], "mm":{"2023-08-11":"3lNdsp-DMpQXEE-uDe-EDeJ"}} +59 [] [] [{"vin":"gmtVdc-VJMScRR-YeH-3vZX", "charge_id":8}] {"Kn73oB-NzIcrXR-VHT-EUiu":{"oaqAaF-LIoyD1D-gKJ-azLI":0.1839240637973197}} {1:[0.3038146593833805, 0.269155429439049]} {"2023-08-10 17:25:18.053000":{"vin":"T6DwRz-G3K2gey-LaS-tpBP", "charge_id":325, "start_time":0.8037233701597274}} {"aa":["qcbNea-90nwFBA-1cX-dEQy"], "mm":{"2023-08-11":"vsN6kn-7UJ5XKo-nPa-yiBo"}} +60 [] [{"YG2fQt-xiLaYHm-0Sz-KhEp":"2023-08-11"}] [] {"dnTCTG-0xpi67O-ifv-ilSk":{"cltPYv-uzrjg9i-MeR-R6RS":0.311517024869693, "tKkh0C-3kOHfC0-Ier-nphs":0.239287360403646}} {8:[0.348392576321308]} {"2023-08-10 17:29:28.375000":{"vin":"dTRDCc-HNDyVSA-bpI-qmM8", "charge_id":6070, "start_time":0.3469296305314755}} {"aa":["kFPSxl-fzFQ0n4-HUj-nLlu"], "mm":{"2023-08-11":"3JWsT0-lyNM8uP-KD3-dCf2"}} +61 [["7oEQZe-HTPSKPW-Vgi-0pja", "rpzOX5-LFewxLG-GCz-UAdF", "sMwz9W-mHnnQWh-Xis-BJwA", "kBE4U4-Pqzg0Wk-KHi-Dlik", "dkJYro-mtXVmMT-av2-Y0Cu"], ["LS7qB3-Hoxge48-nBY-O0eF", "ZMeSIa-xSeq71y-ZgU-omNK", "i479K2-1zSiNZf-aw3-Kw4l", "ZmxIwz-qaAVXFG-w7D-Ur3a", "vlyqCD-RSX1Ikp-BEk-SO5L"], ["HLFwQw-xneBZCk-9Je-niub", "KNLTQT-2p3ZIYi-Gzx-EElb", "ZpLvwF-nEPnMGk-16x-AuEm", "Hlcklf-eTpL3VQ-cSA-Aqtd", "dvODDc-R3wlzAk-2uI-Ygsp"], ["Aw13xJ-KTiFsf0-mPd-iD9B", "7SiCSP-TeymfRE-aun-ULeN", "g6eNOz-28H7yHE-BC1-dmVN", "YBywzw-1RyIt82-jIe-ibDf", "YCI717-HVdfcJM-SX1-8iX4"], ["h0hEao-vQs8oIo-Ewa-LGeS", "sJ88wk-E6Qfj4o-KDp-r6tx", "3kUIr4-E1m7mxJ-kHz-CnAe", "3WM5yM-IG5U7Gv-A4n-XVvk", "F7wPJE-x8f0UwY-s4e-dQ7J"]] [{"aAmFzX-9FQJCbD-QZK-jfFR":"2023-08-11"}, {"kbpFOq-NX3cEsN-5JT-CVwN":"2023-08-11"}, {"YlI5uN-h2eD0RK-KPp-eQ6G":"2023-08-11"}, {"g3OD3s-jMtT2Ht-nXF-MLhO":"2023-08-11"}, {"0yIsNz-srjWM76-qQo-lAPs":"2023-08-11"}, {"jatETJ-juetmT4-lI2-pzzV":"2023-08-11"}] [{"vin":"dPFejv-cSjZQXG-tcQ-5Vpa", "charge_id":3}, {"vin":"dU3iAJ-y7W6QA4-6nD-y3gw", "charge_id":5}, {"vin":"S8FEsQ-SdFeyE7-JiW-VRuz", "charge_id":5}, {"vin":"XQ1xtF-DJkaA3Q-VVn-nm88", "charge_id":1}, {"vin":"0ZBwg2-gETNAT6-BAx-fMjD", "charge_id":5}, {"vin":"A71eTf-4b0bFKj-eK4-o0wT", "charge_id":4}, {"vin":"dgmrHL-BWDEIQC-AEG-Ekpm", "charge_id":3}] {"EEXBex-kEpzEdG-wk0-WFI3":{"5LBMLR-0QPqjgA-b04-VUBQ":0.9594353750727006, "FbR8QW-hIAaK1t-jDs-YDDs":0.6753414995932897, "XEvjpr-kvfBZ93-hXt-K1T4":0.9746749650160776, "46bLB0-10hKBbi-Uzr-hiwi":0.5900114794066044, "TaKpjP-WBKUz8w-Xjz-uiA0":0.5483617041164721, "Z3udCe-YhB3iZw-Ht3-oJ7N":0.8372630332720171, "MY7pV7-TlcsMvY-rnW-eTrO":0.5692853847175321}} {3:[0.7291695481004961, 0.6630008011133933, 0.957537815397795, 0.6660870525125724, 0.736920618979871, 0.1131792039742632], 8:[0.7212531843939823, 0.6042106965664266, 0.1227327480404046, 0.4952361090573217, 0.5622573232261584, 0.2892389709037597], 2:[0.8778956914765943, 0.8782933398747464, 0.3931444243626142, 0.4446540653534949, 0.2525514591717621, 0.8635328809742461, 0.3091605813084479], 0:[0.4477016043802801, 0.3084922790781928, 0.7585338529068617, 0.5991256259965572, 0.8265029042529952, 0.4894416569738526, 0.3937897110106579]} {"2023-08-10 17:18:43.073000":{"vin":"v3XiMu-cpou6RT-JrN-eskx", "charge_id":4659, "start_time":0.6704776945432359}, "2023-08-10 17:20:51.066000":{"vin":"52YeAE-TqLn8va-S2q-RpHv", "charge_id":8498, "start_time":0.1728724785061412}, "2023-08-10 17:28:30.173000":{"vin":"Tw7yHA-HorUUPX-60o-zznJ", "charge_id":8188, "start_time":0.4651910291727306}, "2023-08-10 17:17:04.479000":{"vin":"JCZfON-uPPwFEi-uWG-LXek", "charge_id":6834, "start_time":0.10124110347782}, "2023-08-10 17:19:25.035000":{"vin":"6SPs3w-O22E3wC-rLj-r7Ui", "charge_id":8774, "start_time":0.08927242534692026}, "2023-08-10 17:30:50.449000":{"vin":"RUgOB0-Xy8IR6S-K9G-sCXn", "charge_id":2419, "start_time":0.5801503469877168}} {"aa":["JKl3l1-D2MMhJ3-6kr-qQGR", "kOPU4g-AvIshaA-jqO-LUUZ", "2qJF5X-U7b9ZaR-xSE-3cOZ", "3N8hLv-nPdHNSW-iWF-BQiq", "fHdwUQ-mz7lvZ6-Aqx-Aswe", "U5dY2z-Ao1Lgrh-Rhi-DwAR"], "mm":{"2023-08-11":"AZW2sJ-iOcNRYo-iKL-EJ5c"}} +62 [["FOrv5W-2rSmKlZ-cq5-T1bX", "0szhed-lYzoYqD-Tso-gaRh", "tNpqER-0ScyUgw-bW7-nl1z", "cUD7TB-g3dUt6U-A3w-zT69", "xp72Xe-fGFKBls-Xtz-6HG2"], ["hBikFg-WSiFubZ-ZIt-C1Vw", "n8y4mF-xcfBtPm-Ey8-nLPe", "Tb1wYf-jKWkbQz-ywK-z9a5", "GLt4mz-W3P7Awk-iyV-paHA", "A8cfsp-lbk7AWO-pm8-sjex"], ["Pi5Eyz-4X2QK97-RJT-02qa", "DrUctu-sj9PhoH-149-JrzP", "LaseiS-xhKbzCP-PHg-ueug", "hJwHZy-lsSF0lW-23P-aiSU", "C3MVLA-2BTquO0-jDm-sQjY"], ["GCVJrI-WoROlLC-KKn-wUZo", "NmEqB0-6g5YgOG-muy-SdOQ", "xFzgQ3-IZcZPko-VTn-q8Bg", "JJ1sBg-LrFQLuC-5yX-aLay", "JvDvPs-D2Rcfvp-nGQ-cBlv"], ["s885Lu-obt25zN-ij2-MXci", "bpNv7A-9a7qk9z-Sok-bJMI", "cofVir-CD7lg55-OgE-zUVv", "dENW2c-q4Ry3Q7-zBp-5gVd", "ux3miv-Pq2xmNw-aig-mn5U"]] [{"OtDkEu-McIs8ml-hwr-i6ep":"2023-08-11"}, {"UUB7eM-SBBZqaS-npH-7GVP":"2023-08-11"}, {"4IaZgV-PcP6kor-sjI-zzbx":"2023-08-11"}, {"XcTiLL-fa9Vnl9-wGl-RQv6":"2023-08-11"}, {"ubM1ll-Mzpy0jI-NEr-kufM":"2023-08-11"}, {"t58CdW-yfXBpgI-si7-NaUK":"2023-08-11"}, {"LPjRsq-wLsDeOo-tXC-kgyL":"2023-08-11"}] [{"vin":"2g0sDN-UqZQBFa-ZJ5-VY17", "charge_id":1}, {"vin":"adGDBd-JkT0X3E-srU-dpW6", "charge_id":7}, {"vin":"4RkGb8-vqFIZQy-pYE-Vld4", "charge_id":7}, {"vin":"G6tZa0-axKR17V-DgM-QqRa", "charge_id":1}, {"vin":"ORknAk-aeeW4Fx-RNv-LwNb", "charge_id":4}, {"vin":"XpLuWf-0xLpgxf-DHK-MtOq", "charge_id":9}] {"lpAhbv-dqrJAgp-jpT-IW6q":{"JeFkey-R4bW970-tGX-1Bgm":0.5082853540749284, "iwVaRV-oRn0OQJ-0ZS-W0aL":0.6876455403920271, "rrngmU-8fHplSu-5oI-6o2t":0.9938887839316269, "ZsajmF-BPWdiuM-N3c-JaaI":0.6805468481913053, "uwe64l-LdHSuuj-cnt-RLwY":0.4518562711269524, "FqQASw-0mXVBXm-lKo-2GAr":0.5888134151200064, "FxWNaq-o9E03Ot-OuC-6RYn":0.4935367629474818}} {2:[0.533796774021022, 0.7958570811711682, 0.1553345897860017, 0.002260810271764058, 0.3183921958447888], 6:[0.426915349150189, 0.2532335569194092, 0.6490036684761226, 0.3156541187276246, 0.563185611956019, 0.8465447672713232, 0.6742663440597226], 9:[0.4711657931226115, 0.4369916152167725, 0.7208138048024109, 0.7824456152990077, 0.01545990438891287], 5:[0.758802779485154, 0.4675790936770324, 0.1439184295715378, 0.1597675594612853, 0.7883621369757384]} {"2023-08-10 17:17:03.321000":{"vin":"Rqe4Hr-u1aj3FI-4MZ-t1Rj", "charge_id":866, "start_time":0.5948947171738422}, "2023-08-10 17:27:56.973000":{"vin":"yMtWEu-LkXxF8m-5sH-vK0E", "charge_id":5680, "start_time":0.6514353517221358}, "2023-08-10 17:19:40.452000":{"vin":"HhlsZt-JLfOp08-bko-Znc8", "charge_id":5812, "start_time":0.5586502064978098}, "2023-08-10 17:26:20.532000":{"vin":"hdtMRN-dL6Qlmx-Nck-ugjS", "charge_id":5280, "start_time":0.4279013810071601}, "2023-08-10 17:23:57.466000":{"vin":"IVJJoY-6C7l8da-kHj-qMXU", "charge_id":5599, "start_time":0.9137608819126282}, "2023-08-10 17:17:04.364000":{"vin":"7Jo2ua-fE9k7u2-tNR-8hLy", "charge_id":882, "start_time":0.1185946142399849}} {"aa":["izgBzO-Ez1Q4NI-jbp-62UZ", "Qtz7IG-kGcpoAg-0eT-ry56", "l3TIlT-g4Cjhfn-DVT-yE1m", "etKh07-LuPdMfE-BRe-7rpz", "aGFABf-v2AoNF3-Od4-LRVt"], "mm":{"2023-08-11":"dYtWNy-4MfC15K-aIM-28u7"}} +63 [["usA42u-DTLNnxO-9tb-2DsA", "PPNAAN-IxNiFgr-8gI-cdyP", "etyfgF-cCapaP0-c7j-sCsf"], ["CpsTED-Xr0GS13-aFQ-SAuN", "9U9S1D-ycAsMjt-Ghw-6zU0", "GgEISg-IRX6Ehs-63o-x2sQ"], ["sgMTuY-pDNyoLP-LNg-IlMB", "Lsuwpk-fPCvqDB-6lJ-Ht8q", "8YbbwZ-NpYq2ZO-1Jd-vT5e"]] [{"Tz8pDq-rjuq2ge-kEz-7jov":"2023-08-11"}, {"VPbHT2-3hIEpEe-Ayf-fGKa":"2023-08-11"}, {"8ZQSNK-QfhN6J4-M8m-1mlf":"2023-08-11"}, {"d3yPuD-LejqEkb-Rbg-jiUw":"2023-08-11"}, {"QuLnrp-tdB1tZ4-t44-kp0v":"2023-08-11"}] [{"vin":"P5WigM-bC5FWne-HTK-GcuV", "charge_id":7}, {"vin":"a3T2nh-ktaifdD-RCZ-wLsJ", "charge_id":4}, {"vin":"wXex2J-xOLVf4m-sfA-drGC", "charge_id":1}, {"vin":"oGv5wQ-tjPng3b-cv2-PRww", "charge_id":7}, {"vin":"2IMdC8-nWoy2q1-DiS-SBRj", "charge_id":9}, {"vin":"zfpYKR-FEOvBlN-UKw-hM7i", "charge_id":0}] {"dVgK7k-SRvdPp9-8vb-pKoj":{"90F5BI-3GkRcBK-fE2-tYCv":0.06458620033520768, "hKvzmp-8laHz8d-aH3-OaxJ":0.1866966208600762, "KiusSu-583J2Gy-XeD-rNAR":0.2449894257026729, "dmep6f-J5isEwC-liO-yi5G":0.8372054686998823, "n8CbTG-OVUF6WQ-k96-pD1M":0.9355327362244028, "ScpQ8S-i4Ap9VZ-run-0LIX":0.1597515046135692}} {6:[0.2849988138683293, 0.4651556812428728, 0.2365199666544998, 0.83986127502324, 0.8857334498442996], 3:[0.5259369162919219, 0.8175926454446628, 0.6339910995870129, 0.6355920232291508], 4:[0.3982259010694618, 0.3190576227753816, 0.7077945369111771, 0.06333149853798858, 0.7978815610750313], 8:[0.8754349658548269, 0.1125435215567862, 0.6748539861219062]} {"2023-08-10 17:22:28.309000":{"vin":"WHkQrc-pgmjMuq-OAL-oDGt", "charge_id":7307, "start_time":0.8691325203323025}, "2023-08-10 17:25:27.178000":{"vin":"Qhh6mj-YEk3sDZ-jbk-Wxcs", "charge_id":6433, "start_time":0.4172126482608913}, "2023-08-10 17:31:15.046000":{"vin":"k5WHvS-NGZCQvN-Dtw-WACy", "charge_id":3455, "start_time":0.7034558449369689}, "2023-08-10 17:20:38.286000":{"vin":"rZQ29W-U8mxXY8-vve-zV9P", "charge_id":5310, "start_time":0.5264369623586872}} {"aa":["jvVceb-sAcZqMh-i8w-9RTK", "pu4Fme-DmHSYWT-4Xf-6BnQ", "a4cgfR-ag8KaAF-Gkl-xJiW", "Cmsbic-oqJXxWf-fGQ-JM32"], "mm":{"2023-08-11":"3Mh3PY-rGFANnk-wcM-y6sc"}} +64 [["P1g2nU-im1070k-r7i-nSpd", "L4YXhB-7cqpAwy-nM0-tE5V", "9A76CV-jJ2g8bT-Gf7-sCAI"], ["bo5Osd-h6kZBJl-hAR-e44s", "DR8rFE-ncXwt5V-jR4-UQXJ", "D4UwcI-cCvgDUG-oew-nDuZ"], ["ROqoO4-6Myd6v5-B4n-DN0P", "YJ0BNR-bsXjZDo-qug-hE22", "NmdEyJ-dyQqJsm-T7M-SsYL"]] [{"YNIJCp-WR2n5Dw-Acn-Aa6N":"2023-08-11"}, {"mNKF0g-3VFqCO4-Tqe-za2s":"2023-08-11"}, {"j295B8-2DbaveH-EMq-ll4H":"2023-08-11"}] [{"vin":"dThwbf-C1OKdeK-JYG-wF66", "charge_id":9}, {"vin":"LdBoOB-L4t62in-WiN-gxn0", "charge_id":6}, {"vin":"gdbKOH-MoruM9a-dCi-9pt1", "charge_id":2}, {"vin":"ttDyHe-1WI23zj-tV7-pOzU", "charge_id":2}, {"vin":"q97jt4-PtURfWy-xqD-drum", "charge_id":9}] {"j84znC-FVXQvtE-WZk-LZ3e":{"yIu6DU-xNKsZQt-mpb-QPfT":0.3173938929015944, "0p3gXA-WO5VpyV-Gpe-8kBj":0.5753145201273284, "tqNp7D-Tr3VJkN-8yC-KnEz":0.5154278455249841, "RSkucX-BQx70ZW-3LI-N61T":0.7784781984571406, "9FuJvE-epEtGci-l0Y-Yy9l":0.5208184566677192, "ER9NvD-AV1Wbzf-4dO-LAUR":0.2119242903033582}} {1:[0.7215767292777553, 0.5450452191865959, 0.6998580138083651], 9:[0.5761924689171235, 0.06293988871766676, 0.8853990644122416, 0.5100316528079006, 0.5938084489076774], 2:[0.9854245558331454, 0.008085342039870436, 0.9038540889121772, 0.3945900294974377, 0.2317368761512505], 4:[0.03555658789466809, 0.9358280991143105, 0.3684738584229781, 0.2819247559776834]} {"2023-08-10 17:19:27.026000":{"vin":"BOxoMo-LOJhV1I-2yQ-Mr1g", "charge_id":3089, "start_time":0.2420109633395051}, "2023-08-10 17:31:18.297000":{"vin":"hjfk4J-U1u5wNa-oRD-I7d0", "charge_id":1994, "start_time":0.3713256256791723}, "2023-08-10 17:16:20.285000":{"vin":"XcWkJj-VSq0Lv7-osE-eDLc", "charge_id":2501, "start_time":0.4716809968989929}, "2023-08-10 17:24:45.142000":{"vin":"d6k4z9-vOm55qG-kq4-IzS6", "charge_id":6852, "start_time":0.573348069207453}} {"aa":["FdKqXK-MD10dQP-Qeq-coWK", "rbGo4t-LkyX84b-Wfr-tq2D", "HtYgKr-9rJmv8t-RtD-aydO", "CP0gMZ-6HIj4Ry-uSR-5lDj"], "mm":{"2023-08-11":"kIc0aE-GFVA8ar-68Y-c5ZV"}} +65 [["qlIv3R-jOOnUWs-ioK-RVi1", "plSLmk-fw56OkM-GLU-cWv0", "m7Tg1W-8qoOv6x-SOZ-TihX", "zELSrX-17n8Lar-drw-FxrH", "vFLqBU-eS7LXTs-Fa9-rLd8", "RNPL9D-FJIENYF-p7l-6NR6"], ["0g3dvq-OMsoTq4-HJY-mAUC", "3QK3tT-hruqpg8-ovm-cZlm", "FyWH7n-xtVinAe-ukD-9OID", "bkMMCQ-OAdNMuz-raf-aQO4", "ogUWcT-SnVTQyk-c34-h53I", "EtOBKo-Ftu10c2-wLp-lPWt"], ["kuThkh-iK1BEiI-FRH-60dG", "ARJ0DN-HuITnS0-v9u-TlTB", "MJvIDI-xGhMulB-Q03-KkxX", "0VCljo-tOieAtx-biy-wTv9", "dZQTUy-iibNEDO-59J-1csP", "WijuMq-yDqZHNT-HsW-wVjm"], ["hDxkiu-sUkHoVB-MJ2-cCWU", "ugvgaG-YSbfjYz-xNJ-sPd2", "eyAnim-yP26r0m-XOx-Kkpi", "mhb2gT-QlxjAxI-VSz-TAqw", "8zdhp2-GfYeUxI-DTh-1s1k", "FdzmcZ-AA2NL27-9Nb-cOLv"], ["WtUDhA-4FsaCuG-Uc4-37Zm", "bZ6w0C-BHWFq5J-6eK-5kRo", "dB6s8u-mzZaGNj-Kyq-sp4E", "bY7osA-dA5TU2R-lDT-FQOx", "HWlt9a-IlTgbu0-NG7-tn6I", "jXt8Y2-AOCxgWo-eoa-iMKF"], ["mIDNh7-xIbB4bU-dpy-AbKw", "ih5av3-LdqWzqu-be4-Q7qo", "AXB6mV-XQUx8X9-WoW-kQnS", "bD9IkH-KK4oMsG-ici-trcC", "ucFFv5-81LMAGR-ave-QgoM", "1Amd77-5QVEgte-oZq-Ncbl"]] [{"krPUDy-CPCHiPS-rV3-10bX":"2023-08-11"}, {"VbYSe7-YRkwYNt-qk3-vkeK":"2023-08-11"}, {"S9SYGk-EtokAbZ-Spg-siou":"2023-08-11"}, {"h0YxJ4-QtKtppt-zEx-VnnS":"2023-08-11"}, {"qMSe3j-CnBVfb7-xdc-XnM0":"2023-08-11"}, {"hWH2nO-xWTIPeI-l2Q-OTF1":"2023-08-11"}] [{"vin":"h3sMx3-eceSGVx-qhe-LE42", "charge_id":3}, {"vin":"p5i0wH-aldscj8-qaf-QxU9", "charge_id":2}, {"vin":"LDbX2F-vbvLKkd-Nir-Lqy6", "charge_id":0}, {"vin":"CKlgkl-glsdK9K-s19-WvPy", "charge_id":4}, {"vin":"ZqLHzR-VIbR1yb-YSV-p5es", "charge_id":9}, {"vin":"RH1mDB-laZ1dcp-BcX-6UmE", "charge_id":7}, {"vin":"a9HQcN-UZqpIoS-re6-u2zQ", "charge_id":9}] {"7MxWP7-QSjn9t0-DTm-hr1l":{"jnZOvz-j5Wj8vk-Uh7-vEOF":0.8792529873427823, "deOkFQ-zuNL6rE-xA3-xJ1W":0.7891300684176269, "cvJ0cm-KUqTLYO-9Nd-FO72":0.4838146593498607, "In6S4U-q7VBTCE-bvu-5srH":0.1454420585059233, "IHz7gW-7AI0ufo-rt6-SYXI":0.5490150044745433, "90zpTc-t3rISsA-4fM-Zyxe":0.9685215341287539, "EamSbi-Lodvma8-RKc-Tovu":0.549277394043476}} {8:[0.442136583504404, 0.6744591152496611, 0.5933599746532719, 0.8026001343301067, 0.1638944167743935, 0.9326583201127897, 0.2873273726799473], 1:[0.373393482277358, 0.6653450487875695, 0.7102007505130804, 0.1838779588745427, 0.9969481231579442, 0.2339420163712275], 0:[0.2845609864588027, 0.2479405902662357, 0.908033011350321, 0.330851669808077, 0.2617647901553333, 0.2652004097959256, 0.7032597751275278], 6:[0.8429724056601859, 0.1730576411048207, 0.1115579728971939, 0.3530999948851733, 0.1937797148588007, 0.3476905134060055]} {"2023-08-10 17:31:13.020000":{"vin":"Qfd9RZ-iIxEhgA-sw5-NU16", "charge_id":9140, "start_time":0.3772122901610612}, "2023-08-10 17:17:50.199000":{"vin":"vcZOps-jADYs1V-p73-2beO", "charge_id":8570, "start_time":0.7206652736385138}, "2023-08-10 17:28:11.647000":{"vin":"UhXH7c-PhNvHVe-qMq-VuDT", "charge_id":3327, "start_time":0.1523741624810179}, "2023-08-10 17:22:47.011000":{"vin":"hPqQep-dYgbS0n-0bu-RPOK", "charge_id":9727, "start_time":0.7942951811023238}, "2023-08-10 17:18:29.131000":{"vin":"o2FBox-z3mCJng-wDx-TuOH", "charge_id":560, "start_time":0.6580943205956693}, "2023-08-10 17:27:41.025000":{"vin":"5XSJzs-EZDGVrh-M1g-WFkB", "charge_id":6933, "start_time":0.363667164087543}, "2023-08-10 17:26:09.973000":{"vin":"rf1U0Y-C8WRJQ2-fhT-csKT", "charge_id":704, "start_time":0.986365155218468}} {"aa":["kCqfTz-YYTir3V-agc-O4qC", "ncMLJL-Rn90jI4-XJX-3kPZ", "VmqRWj-9Pbkirz-3PR-Pq5h", "8YE00C-lu4YAf8-Vrd-xSex", "AYRBJ4-Rq0g2EH-kSV-7abK", "OAJfA9-pB98dLe-6yi-wQzf"], "mm":{"2023-08-11":"y0hdJd-tmwm1cs-rFK-nItG"}} +66 [["yseJkR-mYnUqcG-ri6-fZx4", "idAxpL-jXLlTAf-WrW-2CL0", "h4BcXN-ti3hO89-Fqx-93Rr", "33S2ao-rvMGYF6-wPR-0VzI", "ordbOY-N5P3ARA-XEd-N1Xz"], ["0HtYva-ySQeiEH-Wkt-QT7K", "ZA4xJ7-aY9MhrR-UTi-opFm", "zeKo56-254thJr-INf-eZmS", "5DOvVc-9bEpO0u-Sih-BRhL", "qbGeBx-odB2DPA-o7D-1aEf"], ["qRMo1F-4TJGabD-EDJ-cY4c", "ADyYZY-UdIjpjk-2RS-GxLe", "STBkK4-KZkCuIV-uQ9-r02v", "cVeFWz-b1faXCI-ccP-Mwyc", "pPqNsb-PvChKof-v7e-I2OB"], ["AMDkUq-XfAeeBT-AJw-7vTm", "VENw7L-6Vm9Gt4-lQg-NcM0", "cfc09p-1SBUcfP-HSj-mZmI", "KRYdp2-JYEvrcf-OmJ-eIys", "cQUrPH-RNdp4mf-vu6-4Lhn"], ["xOd6Ps-N4CpWeF-1Y9-c2ar", "HKdHcw-GywbRqy-beH-n2Uc", "zjaeEC-6oNX0e6-svz-N5WD", "dunNPb-UtdPJco-9AH-5VB6", "N0OvJa-GAstkDa-sRX-PfWJ"]] [{"bq0CSj-FMlM2V3-tj5-sXvg":"2023-08-11"}, {"W7uUGW-MDdTt1g-FMB-cq7z":"2023-08-11"}, {"19gsSZ-q5cwo5y-h0a-KWPj":"2023-08-11"}, {"WJ52jJ-Fo6HvxW-A3B-hMLg":"2023-08-11"}, {"y6FA5T-DuvONCr-19a-J4Sp":"2023-08-11"}, {"DBfivM-1Qs4yp6-ct6-R71g":"2023-08-11"}, {"bj0aSs-DWjupQ8-VVx-qW6n":"2023-08-11"}, {"SyUBP9-Nx31xOA-7Bi-LhQq":"2023-08-11"}] [{"vin":"nkxU4W-pjKeEnI-HKn-zD85", "charge_id":7}, {"vin":"vCSDea-XOk3nYM-uZO-MdWx", "charge_id":0}, {"vin":"JCwZ4R-oTiIyS3-9uP-5fuN", "charge_id":6}, {"vin":"9uvfKv-qdv4kiv-lCS-6Kde", "charge_id":8}, {"vin":"ZC9yTa-VqPU3eA-afS-viSI", "charge_id":6}, {"vin":"eabPKi-e0BoTUo-Y0L-Onbh", "charge_id":9}, {"vin":"Z8qSvu-emqvITG-3J2-FiFO", "charge_id":5}, {"vin":"Yqvgnn-jKfE8UM-Dkk-j5sQ", "charge_id":9}] {"rqlOUx-2Evnoof-B06-DwHs":{"F6iRMd-9Wr8rCf-agK-HhOh":0.2592456321360164, "bZJTeD-srsbWv0-6B9-ANqK":0.5731247544453553, "m5Uk0W-pcxozD2-Lys-TyYs":0.1905793611751156, "ryw3al-tKYZ0J7-JJJ-TDZb":0.9418369805858259, "fjytS9-477J3Rd-R8l-2z5v":0.4764718195914912, "0uOvcW-0t6wdfi-bBo-SFog":0.6128295295620225}} {3:[0.5108170713346386, 0.694733680487424, 0.5847721423779517, 0.3919952795818217, 0.7025307949387688, 0.1555599264146892, 0.432746943020953], 2:[0.4713742747750252, 0.4488223258534443, 0.1892436892846434, 0.8953290692964038, 0.7144884057361491], 5:[0.9815374065739699, 0.7603397070368498, 0.5366724360694827, 0.03759974733479021, 0.2484054636728981, 0.63148643240591], 7:[0.4565972568797313, 0.4430565803732961, 0.1513951545522643, 0.1611032259961541, 0.7101073832702474, 0.9705159004002205]} {"2023-08-10 17:27:12.900000":{"vin":"jtYqP6-v1voPvm-6Qm-uprK", "charge_id":805, "start_time":0.2329701990503849}, "2023-08-10 17:22:42.691000":{"vin":"PymHXr-Y7IP0yH-Vz8-ruYd", "charge_id":2788, "start_time":0.9872463526689467}, "2023-08-10 17:31:56.338000":{"vin":"4jI9S2-scL3YNL-qpe-SJgG", "charge_id":8278, "start_time":0.4654387595933797}, "2023-08-10 17:16:17.555000":{"vin":"T1koWk-ufY0H3X-xg3-QWZT", "charge_id":9552, "start_time":0.3842931023900751}, "2023-08-10 17:19:30.662000":{"vin":"qfT5jA-yIOapLO-dey-tj3W", "charge_id":8180, "start_time":0.3528909371787147}, "2023-08-10 17:24:34.595000":{"vin":"kylZUD-cUafFd7-lIy-bdEH", "charge_id":1456, "start_time":0.8611328701077273}} {"aa":["9cGpXQ-SIP2HAk-X90-jdzA", "UdKMv4-OQAIQBy-gAA-9JC8", "xY2ywz-sqRJSZs-WIx-Sb8X", "XV41A5-8642PmD-qp2-6e4f", "rCZ4fb-AK4r6JF-nqW-mnGe", "IxSocj-1irAxYu-12t-vKXL"], "mm":{"2023-08-11":"qMl9Cs-O2reqpZ-d0R-I6Ku"}} +67 [] [] [{"vin":"TGDwzi-WxxKkeo-6MV-ENp6", "charge_id":4}, {"vin":"Yd6oNd-y7PK4d0-GFs-M3dC", "charge_id":1}, {"vin":"yeSXnv-Be8vHDf-xx3-7nKp", "charge_id":8}] {"eQOJrZ-jgcN3GD-t1i-yMYw":{"CmSUYY-bSNuHV7-ng0-Mwmv":0.09340246757037196, "En91ra-EUR3pfD-q4t-3ocA":0.6740899544305328}} {4:[]} {"2023-08-10 17:23:04.702000":{"vin":"2XHLzr-g0nScny-wZQ-4twE", "charge_id":9597, "start_time":0.380992647680271}} {"aa":["Bf5cVE-HRnWpYw-Uyo-RYhe"], "mm":{"2023-08-11":"RV9dST-XvX55Tp-nk7-CTwP"}} +68 [["NWjXO1-MgHhJW9-qDm-TPeh", "PSPNXO-S5kPM0n-zDl-19k4", "WTuAHL-PbR29Lm-K2P-lB2H", "NfUJF5-H7jS7tz-paf-VSxr"], ["z2RJXc-Gzo0eRA-2gE-uiRr", "xCf3fn-V36EBdV-vt1-Nq75", "8JmTVS-Fdg1kmZ-DFQ-Zcpz", "GSKOKp-JbvugnM-fEH-M9Rq"], ["gD4GOs-Uo8GoEm-Jh6-ZyZ5", "8nJZS6-1pzMRQn-oTP-gyWd", "Bh2wgL-UcsZovl-Qui-I3Kb", "TYssTW-zRfzEN4-was-hmey"], ["IkLdF5-nqcHnIb-51L-9wat", "ZEWews-DUKqzmf-2WV-hcae", "wrlWLv-QiGjZei-8zV-zyvI", "2xBvRl-ebri2PT-TWp-sKx0"]] [{"xw3OCW-myeu4WS-fcr-1XRk":"2023-08-11"}, {"5zVrWY-TtIFxYy-StA-vCll":"2023-08-11"}, {"dXly8A-SmOMbbX-g4x-Phsi":"2023-08-11"}, {"V9B3Lr-UnzOxKT-ArJ-Wjma":"2023-08-11"}, {"wXKIps-Iz8zSYt-KWe-jb59":"2023-08-11"}, {"6OOZA3-Hvzh47R-z4E-E5MW":"2023-08-11"}, {"oHP5Gd-7htQbOt-NAW-VIga":"2023-08-11"}] [{"vin":"MQQ0JP-VggWoJ2-yVe-pnbD", "charge_id":4}, {"vin":"yVaMra-ZXjspHr-Vjd-rPjg", "charge_id":4}, {"vin":"b57pq0-ySSSwY0-05P-qDDY", "charge_id":7}, {"vin":"0iPeia-ItTARTn-taG-Or6j", "charge_id":6}, {"vin":"9XahgA-VUEfB0K-fDB-jUMM", "charge_id":8}] {"0QnBuM-A3OyzdC-xUX-5Tk9":{"IDNogz-pHaOzEk-c4F-Fi0A":0.844196067769477, "HM0mgH-zS8SPug-NLd-Lgcj":0.1073568923986608, "NxwWCn-Ai0UCp3-a06-1gKf":0.1577289050450112, "SXcmsE-Zy6VaCI-PZH-zQ6l":0.7233749321501123, "HLJjWv-Aa4WNl7-xSd-3bTD":0.8037999098884792}} {7:[0.07758810547926309, 0.08487947523622119, 0.4548075894348014, 0.8925188994490023, 0.3290618212330633], 9:[0.2701047150475561, 0.4015773524573091, 0.9390787086698963, 0.3020461441432944, 0.4095883387789641, 0.5161915200884376], 0:[0.6092400030873681, 0.06726592097286599, 0.0644033766655504, 0.4371531929781138, 0.6492833871020278], 6:[0.9557478590105815, 0.3163370718034627, 0.1549927139156595, 0.8211973783371688, 0.2575350286775442]} {"2023-08-10 17:28:08.205000":{"vin":"WXEc7r-BL91dxv-T0x-woo9", "charge_id":7983, "start_time":0.9205153933976353}, "2023-08-10 17:24:16.950000":{"vin":"wVN9Ww-wI78Qvd-pZZ-DuP8", "charge_id":6311, "start_time":0.05810329763876854}, "2023-08-10 17:28:18.841000":{"vin":"H21wtI-00g2hc6-3Q9-oODm", "charge_id":6201, "start_time":0.7886091118186112}, "2023-08-10 17:19:10.656000":{"vin":"a9mmjm-bxptLGz-rBI-2ZOB", "charge_id":1532, "start_time":0.5437494682141608}, "2023-08-10 17:24:33.197000":{"vin":"bMKT9c-2b8E5eN-PsF-44Az", "charge_id":8880, "start_time":0.09666947735432174}} {"aa":["8WKCAu-TVaVUbH-4v6-YZM4", "kwJ85m-LlpRO3k-yUN-WVgn", "6SVKE7-kBMGY1T-u0B-GZBW", "EJDv6R-b2vbxXg-mZV-1SgU"], "mm":{"2023-08-11":"1t3nYA-iVPrbFP-l8S-Qy1X"}} +69 [["KijBVm-c2k789a-PVu-ItY4", "T6sGjy-mnPQJP4-rJ9-vy4c"], ["zAGbz5-C64nFxO-fDg-Jj4A", "qy9zkB-x5FBojQ-IhM-EcIx"]] [{"0uwOJs-mMGrGsH-NbN-iFj3":"2023-08-11"}, {"4IYdHY-u4jKtxu-igC-0JEE":"2023-08-11"}, {"AfFPEn-fT1Z0Iv-4wb-yKQY":"2023-08-11"}, {"NjXxv7-Qqh5ozK-adt-5sDB":"2023-08-11"}, {"iimGHq-42vMsEE-7qu-zfm9":"2023-08-11"}] [{"vin":"z3FXbF-b7p5kM4-Rnx-eubh", "charge_id":1}, {"vin":"Gf4uVI-ryYDvac-uv9-LAY3", "charge_id":4}, {"vin":"CDDuIj-f3VzbA8-GM4-3Uui", "charge_id":6}, {"vin":"bcRVZ6-UhYeVDN-PAA-yeJD", "charge_id":2}] {"qHlqTg-Ofv34TZ-XC2-4xoi":{"XOprYs-PpTFYan-iMU-trij":0.5868702448498487, "IZt1tM-FmQnWEn-2ub-GWZw":0.7757291197671391, "s9WZ9H-iF1wemC-vy4-zEq1":0.6776072259464606}} {1:[0.222234266834496, 0.3193435731277943, 0.8816004519972791, 0.008614051730678973], 4:[0.5471299260604703, 0.7011579162176416, 0.4352971619078166, 0.5623263397366467]} {"2023-08-10 17:28:33.819000":{"vin":"1XlbFN-QyWV3LI-SaG-e6Rp", "charge_id":4029, "start_time":0.8422199586485317}, "2023-08-10 17:29:32.101000":{"vin":"ivG7Hj-O6dzjxI-scv-vd3o", "charge_id":4298, "start_time":0.360641397981218}, "2023-08-10 17:28:51.762000":{"vin":"NRPnf2-I0KgSyF-cMd-kizH", "charge_id":3616, "start_time":0.7567238767777844}} {"aa":["1nXK1x-9HIm3l5-DL0-WBYl", "ttVsde-7Amsjkm-lFG-N1At", "hATiU2-OE9mMDC-0lJ-ywfi"], "mm":{"2023-08-11":"DbV25w-f3VM3N6-knw-jhTg"}} +70 [["HKBu7f-9CJsfcB-DHn-x22X", "3CseZr-7o58TGm-apK-vLfb", "Uil06h-tyeldsd-opa-WiPa", "E4ti7M-yuziF8i-FHF-8Gp7", "DXNq1v-7VERP48-Q8E-Qe9A"], ["uvXnm9-TXexRUW-G2a-cZT7", "Ujv3zN-Q35JDnn-tip-mCoZ", "bV9A9Z-39WBVnM-paQ-Wc1w", "aiyrJZ-0mXpd2k-wtK-YIIB", "HxoSl4-LSjMmYT-l3D-rNHN"], ["xP61bS-If7U8ZU-wBi-udqF", "WEEX7E-d9wPriy-JxD-UkEh", "13FeV4-V8lBbjr-A6U-uN0e", "gpWdzi-LkyPbPk-tyP-GQka", "ebzQuo-wlibSEQ-wXM-z8wh"], ["pKwIod-OyzD9Q1-ue9-eyBP", "PAQpiK-6zciJ6j-k13-Q0PJ", "L1pLc7-rLIQq7F-RKK-jvLG", "m7FFIg-gwXjMsl-khj-mFYL", "9lMI5Z-Ds58rvC-Lfz-GaYf"], ["0rmRq9-0vtTOsf-yS9-wXR8", "Iap78a-sJsISEY-dj0-l66l", "LE4ARk-unLNfU8-tcU-4QJH", "uTPlN2-mm1baoL-sfp-OSAT", "Hk9QBv-YEkBXOn-hnr-AJte"]] [{"3abwPy-ukMWGWU-BTs-eKSr":"2023-08-11"}, {"aoAvwG-A5eY1Vy-PK1-QvN5":"2023-08-11"}, {"NCEHio-98FEDhA-9xA-rjuU":"2023-08-11"}, {"LKOzND-Gj636vM-8fg-rtU5":"2023-08-11"}, {"p8WTi5-lgQcZpg-R9O-oCNT":"2023-08-11"}] [{"vin":"tSRutj-sgo4Zx9-fbR-OmZ9", "charge_id":0}, {"vin":"SaflL9-y1fCqr5-zwF-UtxT", "charge_id":1}, {"vin":"xYX28I-PDm4cPL-umM-Z9Bq", "charge_id":4}, {"vin":"wfTArZ-QKC9mCy-zYR-M721", "charge_id":5}, {"vin":"nsoPVU-iiP7MKP-Gil-rSdq", "charge_id":8}, {"vin":"v5EX2U-SL8pZxW-DzN-4PtH", "charge_id":2}] {"8vV5Ig-2ZsZGY4-bfV-NCzx":{"9meyb1-XLbz2nb-kly-Pq7y":0.3757210143167539, "HoDNyz-5Gatl0L-EZz-5bQu":0.1104183455366734, "s4PvxG-arOmccI-3vG-mE1v":0.7929717408097942, "xLqWuU-GaKyEZc-GNb-uPqR":0.07595716385640072, "t7fCOz-u9pcCsK-CkC-emIA":0.5461176084547499, "LSj7AW-Mcnvu8y-DIs-A628":0.2730563298530834}} {2:[0.0298944740216478, 0.9714365118707564, 0.8661680940053891, 0.9234054287899386, 0.6604446176653759, 0.4069659495108542], 4:[0.8668538621240134, 0.3611658096024434, 0.2059107549542697, 0.8074344326905948, 0.4322034851071777], 1:[0.2876909106620456, 0.9925271938822068, 0.03553969962729986, 0.1499310836467337, 0.226392244715485, 0.6460624192767683, 0.4092320272346437], 9:[0.1642225376926598, 0.7540999046927834, 0.8056662286536563, 0.9852505060305374, 0.9427245964388594]} {"2023-08-10 17:24:59.971000":{"vin":"4jkA4y-kC8TmTf-5vA-Ckvi", "charge_id":3624, "start_time":0.3458551738066535}, "2023-08-10 17:17:09.138000":{"vin":"lDSnpm-dIm7oBM-6Dm-IdsB", "charge_id":8419, "start_time":0.6050714521877386}, "2023-08-10 17:23:00.480000":{"vin":"osc2AN-IV0DQ72-wXE-I0W1", "charge_id":2877, "start_time":0.9040510323123244}, "2023-08-10 17:18:06.026000":{"vin":"pSf2dC-3PaKokY-DMZ-1ysk", "charge_id":15, "start_time":0.2999061442616917}, "2023-08-10 17:15:42.485000":{"vin":"TMfGIb-4wqlkdc-N8I-jWgR", "charge_id":7413, "start_time":0.8383744673514338}, "2023-08-10 17:29:10.953000":{"vin":"gHj58i-wMqga3o-8PJ-bnAo", "charge_id":8757, "start_time":0.9316564693850775}} {"aa":["dLTJnR-YfogYG8-mq2-RRiW", "mTjfdC-EMOrnSi-GaD-lFNu", "LrRYQ4-r9KvMl5-NDr-EaDt", "MdTnye-0T2ndsD-JRQ-Ud1Z", "RewQg5-NtkdAqO-UgW-Rbwf", "o4n2W2-3ZSXplE-Otx-b5GI"], "mm":{"2023-08-11":"vFo4D5-pi9BoTQ-i4z-iMms"}} +71 [["J78ISD-Gn7UEkZ-9eK-ilK6", "1oe34X-G1VOEsF-XoJ-toOB", "DxbQKs-TfDmQoe-T12-Au4T", "DRdkVu-3FgvGLS-Xd2-60Zq"], ["DxAKxE-NAJ3v7t-bAW-x4qO", "SR42UN-02EGjAA-aDA-kvbE", "rSSi93-RNir1Bp-9wz-oR74", "2b4qwg-7XcHRxS-RNa-ZpA8"], ["cCJI4i-5Xz0v2w-TH3-DFkU", "d4u3wT-QfOakK0-jsN-NC0Z", "jZEzCE-zHQ2Tdb-rlP-Zn8y", "mUgxfB-SmJiqwa-N3l-Dax0"], ["8SDqix-FqNflfg-C41-Quyh", "tyXsal-eLgUOMM-OGW-ZUj8", "76nfAr-dWfNjRE-FA6-dFug", "nya7GZ-zN7Wgcr-kBp-NLW7"]] [{"vt76t6-YwxvIV2-8uP-5Qd5":"2023-08-11"}, {"8OuNm8-7EvIViS-ZLE-aSsN":"2023-08-11"}, {"KekOb0-qaVqrgB-fPB-vGiY":"2023-08-11"}, {"KPEJG5-ChVcmB4-a6p-Ua6N":"2023-08-11"}, {"mf9rao-66tkYAv-4Ye-hfje":"2023-08-11"}, {"3qcNIW-xGzUSZe-Q3J-oLAw":"2023-08-11"}] [{"vin":"QfleAo-h3qbceZ-MsG-m6Pr", "charge_id":2}, {"vin":"wEkuae-wzs6LJH-D6t-ZMjn", "charge_id":7}, {"vin":"j0PLep-QejmaTe-pw5-snP5", "charge_id":0}, {"vin":"UgFDYV-i0JCXB8-oy8-KYvc", "charge_id":8}, {"vin":"ailgNk-mqDm6ZS-FxQ-xs9G", "charge_id":2}] {"ie6XUp-nmI5DJt-zCu-FAo5":{"a5Y4Q0-5Yo5P44-5UE-ltHZ":0.6561729304089763, "HIXQmQ-7A6Rbtq-Q4m-Zv2N":0.7952120890568426, "jyWBDQ-xSZfFwe-vXJ-h0Ox":0.7993693937904595, "cu9wHA-qaDLOgm-6t7-mxjV":0.2939320551668124, "3icFAQ-I0xVWgG-X8T-pAGA":0.8718636551569146}} {2:[0.1525083066316051, 0.3454523111784535, 0.7684881029622597, 0.7993506966166495, 0.2444319528893922], 8:[0.1347861106840632, 0.7570160505784378, 0.3374740101083857, 0.6092485644120333, 0.9046653468193437, 0.4066370457034264], 0:[0.569492878397295, 0.06745605574862257, 0.5735585729049126, 0.8406617667594581, 0.1525784273733451, 0.3815264135329941], 7:[0.6690743827101662, 0.3374760354215898, 0.7325837970950498, 0.2375615825238736, 0.3700845716548422, 0.9484417543363359]} {"2023-08-10 17:30:15.255000":{"vin":"MmC44l-R6P6b5t-LQy-LlxK", "charge_id":4937, "start_time":0.8885891505686204}, "2023-08-10 17:18:40.187000":{"vin":"xOofy3-i98eM4J-dK3-Fk3O", "charge_id":3362, "start_time":0.6650127085922444}, "2023-08-10 17:21:13.618000":{"vin":"RiDDaC-OJfMF9B-iLz-Uws3", "charge_id":2253, "start_time":0.2823599435885674}, "2023-08-10 17:19:23.280000":{"vin":"zwEdsH-Q6oYjyz-8Ju-NSso", "charge_id":9899, "start_time":0.3161388615953645}, "2023-08-10 17:18:25.474000":{"vin":"9Grp1J-YO2rmfa-62i-xWF4", "charge_id":112, "start_time":0.2839480484993304}} {"aa":["H8U2EF-0ehaydm-PMA-gl0b", "hqI2VY-8nqgYw0-WaU-chEP", "dHcRs0-aJKaKn2-Lgu-yJLf", "ZkSWnu-0x84NN2-OAS-NFU9", "qtHqpH-LToR4SM-0zy-SABv"], "mm":{"2023-08-11":"fr39gR-i7PpLeS-qM5-7IQQ"}} +72 [["wAWHas-dC7YfHn-2h4-V53s", "o5QYBq-9O7vDiE-Gjd-378a", "egsjg7-QYQsLrr-1vy-W7jH"], ["8CqVhe-fx6xu0Y-hUM-eeWm", "w9Xa6F-1gLD2KB-Mdv-s5E9", "gQ2p8k-MHDbxCc-0cy-QQ8N"], ["5uQNvH-sOqsHOG-YmF-LddT", "gCzHje-K1sIVVu-lvL-tTtF", "wE9zB4-JiMBxi2-h2K-SCRe"]] [{"lnZJRS-ZXpd76h-Rgx-SuYO":"2023-08-11"}, {"Xv4iQs-hmECuu6-rSi-hLRl":"2023-08-11"}, {"RmaI3A-yJ9bkHF-Pdh-I3X0":"2023-08-11"}, {"Tx7J2o-tgKSrYX-Sms-SuAB":"2023-08-11"}, {"FKG2Xc-giDD962-ITv-2xeW":"2023-08-11"}, {"8XQ8Xc-M1UVNM3-gu0-EzkO":"2023-08-11"}] [{"vin":"fVX25h-z4DmRT7-LGK-dxE2", "charge_id":5}, {"vin":"WPbYeT-weKhzAn-Dl2-llDR", "charge_id":2}, {"vin":"isUdK9-fIWcQK2-qko-OXHB", "charge_id":3}, {"vin":"oN95lc-vKonTnV-vZ8-iXRt", "charge_id":4}, {"vin":"mO2Qj1-14UIfzj-UqR-w5Ww", "charge_id":3}, {"vin":"aOYI5T-DgGptWW-08Y-Dwy5", "charge_id":5}] {"aEUwNw-Id6P3NH-WCT-1Ks7":{"dK5eKN-Chj2eE1-LMH-0Da4":0.4287359708837412, "1LJfOw-iKSpsCk-IKG-ZnLC":0.8408483326119406, "yGTReH-UltmFu3-vyd-BUtI":0.5672716489764478, "xU3YNq-pVQHwik-wQo-I39I":0.9602682047436565}} {2:[0.5789772903390551, 0.4877794092035377, 0.5151198991472977, 0.2235565371155868, 0.3049232794357719], 8:[0.8194505803815813, 0.3097954738602396, 0.1734855997722714, 0.519965636665689], 4:[0.8699354418533036, 0.4288692255289976, 0.7242838763214541, 0.7244937606016093], 0:[0.199731814938207, 0.6137012815628313, 0.8700022644635989, 0.9252442347969377]} {"2023-08-10 17:23:03.528000":{"vin":"OkqBtA-300FH89-Cuv-EWl4", "charge_id":6435, "start_time":0.4404101562856072}, "2023-08-10 17:17:52.098000":{"vin":"ODDkum-BWajY2F-Ttt-t5eP", "charge_id":9413, "start_time":0.5666078509497287}, "2023-08-10 17:16:11.683000":{"vin":"teE02s-2apLg0Y-nQS-RH3d", "charge_id":4695, "start_time":0.0380926299580443}, "2023-08-10 17:16:44.586000":{"vin":"99Ch5P-nG8mz6O-5Zi-Yl0w", "charge_id":1993, "start_time":0.8639900839647179}} {"aa":["iixw4a-wjtpBCQ-TQR-Gwq7", "F1SX5X-NN68IbJ-TBt-sPiF", "yXDzLx-HhPeQdK-EE8-JQEE", "8dxFfz-6P96Qan-UIb-d6Tr"], "mm":{"2023-08-11":"YRDD4K-aGaEcaD-Jq4-Yp88"}} +73 [["FB3LA5-Wr0osX1-iAI-G60s", "EmoQk1-YxKiYZE-SK2-CDR1", "ctETaU-ih8pv8A-CIL-lCXs"], ["Ehe0ke-ZOy7JF9-qlM-Ev8d", "mc6EVR-NSx9c04-yqG-SToI", "4Tvb4u-rHZKjO0-Kp0-1t5P"], ["F23kM5-4G0YkxZ-4EZ-UuzP", "1HOF4e-TfiKJMd-eLb-UWRA", "VDAsOU-cK9naIS-DWZ-StrS"]] [{"XABX6h-ul376BZ-rNY-d7En":"2023-08-11"}, {"s1Hpzu-NhpuCh0-jAM-nUKa":"2023-08-11"}, {"a5a1AL-Hc3mBFk-hVZ-h6Em":"2023-08-11"}, {"Qv6hWT-gIKJNSi-ZQt-9MBz":"2023-08-11"}, {"USiUhc-OZNjvdc-TNd-cPYe":"2023-08-11"}] [{"vin":"Z668rR-ARkjV4R-Lz8-nGve", "charge_id":9}, {"vin":"dzj4P7-bGJ19Tc-yru-0TWs", "charge_id":0}, {"vin":"8iBLE7-aHTnF9y-CZE-2vew", "charge_id":5}, {"vin":"C4RlQr-WDMvzYA-9iU-bkVT", "charge_id":5}] {"IgFuFe-PNk74tz-eOL-UWnp":{"7M5Hy9-lL48pFo-Cwp-gky5":0.6285270238081867, "3UYPJZ-5oyNa3G-Ww9-nri8":0.4108397789216884, "B4Hm24-UZ6t2Xb-h8i-HtrO":0.6020434500606853, "v0mf1t-X5BrcQx-mId-zeSN":0.3451516657956651, "L7urgE-Ca2znN2-cQW-Llv0":0.5584463276869119}} {4:[0.7562118831749121, 0.7075390363864825, 0.9768521217227412, 0.6023707395806606], 2:[0.1955890456471261, 0.3969713514832753, 0.9843252480752234], 0:[0.5463468513278282, 0.8981182219098134, 0.3440890956649176, 0.8757479117433546]} {"2023-08-10 17:24:32.080000":{"vin":"Dm9SsF-HC51wbf-HV3-Jo2d", "charge_id":8303, "start_time":0.9725107903722114}, "2023-08-10 17:19:05.013000":{"vin":"uW3Juz-DiC1Fq0-bwi-J6Ub", "charge_id":9433, "start_time":0.1377050324067952}, "2023-08-10 17:28:05.580000":{"vin":"Osugi6-vPXRRAM-tgs-jE14", "charge_id":238, "start_time":0.525958892182644}, "2023-08-10 17:30:46.277000":{"vin":"YBiLAz-dvm1SLs-cyZ-l8X0", "charge_id":5117, "start_time":0.6059062734165274}} {"aa":["peG75n-i3CWUsM-4E0-DchN", "2vQQEf-LRLtvg2-oop-Imnr", "KHuRmU-rLFNWCh-KIZ-OCLT", "ztVivV-aDHKqMK-UZp-5ZvD"], "mm":{"2023-08-11":"KRJrqv-8h0M4I7-J5r-UvvB"}} +74 [["aSIj2h-Quzlyqu-pat-gD2q"]] [{"JafVcq-8njhCGs-cOa-gmOh":"2023-08-11"}] [{"vin":"Z5iqdE-3GPzX2b-NGE-Ngmf", "charge_id":2}, {"vin":"9YcdU4-f4za4lz-w5E-diMC", "charge_id":6}, {"vin":"Mi2huv-X67WqVd-vBU-JUgm", "charge_id":6}, {"vin":"w2I8KF-g24bXkr-PTK-QKZw", "charge_id":9}] {"5BUymI-KGQXpmu-q7f-aU6p":{"stC9l7-YP7mgCs-hdq-mSHe":0.07908976585263905, "pC7T64-ZS4OOeO-iS8-k2Kv":0.9458151810152464}} {7:[0.3263760205939285], 9:[0.1410369277204621, 0.7885564729425142, 0.2700937702957682]} {"2023-08-10 17:26:47.384000":{"vin":"C4qJhk-O5gzecE-ryW-s1Qx", "charge_id":734, "start_time":0.5362083075783354}, "2023-08-10 17:31:16.250000":{"vin":"nXmuHf-ztVRgFB-UEb-Fgig", "charge_id":9297, "start_time":0.6218545494657998}} {"aa":["cSa0v0-j9Dl0cX-H92-Or2y"], "mm":{"2023-08-11":"l8ul1m-usPXCPY-spf-3EQk"}} diff --git a/regression-test/data/external_table_p0/tvf/test_local_tvf_with_complex_type_element_at.out b/regression-test/data/external_table_p0/tvf/test_local_tvf_with_complex_type_element_at.out index e0da95fe00d3a6..489d664613f8d4 100644 --- a/regression-test/data/external_table_p0/tvf/test_local_tvf_with_complex_type_element_at.out +++ b/regression-test/data/external_table_p0/tvf/test_local_tvf_with_complex_type_element_at.out @@ -382,4 +382,3 @@ GFxQDj-0srwp6A-nB0-G1XJ \N \N \N - diff --git a/regression-test/data/external_table_p0/tvf/test_tvf_p0.out b/regression-test/data/external_table_p0/tvf/test_tvf_p0.out index 5ec7cc860da33b..a2069039c4875f 100644 --- a/regression-test/data/external_table_p0/tvf/test_tvf_p0.out +++ b/regression-test/data/external_table_p0/tvf/test_tvf_p0.out @@ -43,12 +43,12 @@ 25001 25001 25001 -- !fix_byte_array -- -\N 64.1234 128.123456 \N 64.1234 128.123456 2023-01-01 2023-01-01 2023-01-01T20:00:00.123456 2023-01-01 2023-01-01 2023-01-01T20:00:00.123456 -32.123 \N 128.789012 32.123 \N 128.789012 2023-02-15 2023-02-15 2023-02-15T23:30:45.123456 2023-02-15 2023-02-15 2023-02-15T23:30:45.123456 +\N 64.1234 128.123456 \N 64.1234 128.123456 2023-01-01 2023-01-01 2023-01-01T12:00:00.123456 2023-01-01 2023-01-01 2023-01-01T12:00:00.123456 +32.123 \N 128.789012 32.123 \N 128.789012 2023-02-15 2023-02-15 2023-02-15T15:30:45.123456 2023-02-15 2023-02-15 2023-02-15T15:30:45.123456 32.456 64.5678 128.345678 32.456 64.5678 128.345678 2023-03-30 2023-03-30 \N 2023-03-30 2023-03-30 \N -32.789 64.9012 \N 32.789 64.9012 \N \N \N 2023-03-31T02:45:30.123456 \N \N 2023-03-31T02:45:30.123456 -32.024 64.0000 128.901468 32.024 64.0000 128.901468 2023-07-07 2023-07-07 2021-07-07T19:15:31.123456 2023-07-07 2023-07-07 2021-07-07T19:15:31.123456 -32.689 64.2580 128.745382 32.689 64.2580 128.745382 2023-11-11 2023-11-11 2022-11-11T16:35:37.123456 2023-11-11 2023-11-11 2022-11-11T16:35:37.123456 +32.789 64.9012 \N 32.789 64.9012 \N \N \N 2023-03-30T18:45:30.123456 \N \N 2023-03-30T18:45:30.123456 +32.024 64.0000 128.901468 32.024 64.0000 128.901468 2023-07-07 2023-07-07 2021-07-07T11:15:31.123456 2023-07-07 2023-07-07 2021-07-07T11:15:31.123456 +32.689 64.2580 128.745382 32.689 64.2580 128.745382 2023-11-11 2023-11-11 2022-11-11T08:35:37.123456 2023-11-11 2023-11-11 2022-11-11T08:35:37.123456 -- !wrong_page_header -- 53587 38687 2689589 99480 2971 1999262 218 386 5265 86 33.14 56.33 40.55 0.00 3487.30 2850.04 4844.38 69.74 0.00 3487.30 3557.04 637.26 diff --git a/regression-test/suites/datatype_p0/nested_types/query/test_nested_types_insert_into_with_s3.groovy b/regression-test/suites/datatype_p0/nested_types/query/test_nested_types_insert_into_with_s3.groovy index 3f74b34a70b865..84b4b103a10b60 100644 --- a/regression-test/suites/datatype_p0/nested_types/query/test_nested_types_insert_into_with_s3.groovy +++ b/regression-test/suites/datatype_p0/nested_types/query/test_nested_types_insert_into_with_s3.groovy @@ -234,6 +234,7 @@ suite("test_nested_types_insert_into_with_s3", "p0") { "s3.access_key"= "${ak}", "s3.secret_key" = "${sk}", "provider" = "${getS3Provider()}", + "hive.parquet.time-zone" = "Asia/Shanghai", "format" = "parquet") order by k1 limit 1; """ @@ -242,6 +243,7 @@ suite("test_nested_types_insert_into_with_s3", "p0") { "s3.access_key"= "${ak}", "s3.secret_key" = "${sk}", "provider" = "${getS3Provider()}", + "hive.parquet.time-zone" = "Asia/Shanghai", "format" = "parquet") order by k1 limit 1; """ @@ -278,6 +280,7 @@ suite("test_nested_types_insert_into_with_s3", "p0") { "uri" = "${parquetFiles[i]}", "s3.access_key"= "${ak}", "s3.secret_key" = "${sk}", + "hive.parquet.time-zone" = "Asia/Shanghai", "format" = "parquet") order by k1 limit 1; """ @@ -287,6 +290,7 @@ suite("test_nested_types_insert_into_with_s3", "p0") { "uri" = "${parquetFiles[i]}", "s3.access_key"= "${ak}", "s3.secret_key" = "${sk}", + "hive.parquet.time-zone" = "Asia/Shanghai", "format" = "parquet");""" qt_sql_arr_parquet_doris """ select c_bool,c_bigint,c_decimalv3,c_datetimev2 from ${table_names[i]} order by k1 limit 1; """ diff --git a/regression-test/suites/export_p0/outfile/parquet/test_outfile_parquet.groovy b/regression-test/suites/export_p0/outfile/parquet/test_outfile_parquet.groovy index cd92abea53079d..f87e656c7c11ac 100644 --- a/regression-test/suites/export_p0/outfile/parquet/test_outfile_parquet.groovy +++ b/regression-test/suites/export_p0/outfile/parquet/test_outfile_parquet.groovy @@ -114,7 +114,9 @@ suite("test_outfile_parquet") { throw new IllegalStateException("""${outFilePath} already exists! """) } sql """ - SELECT * FROM ${tableName} t ORDER BY user_id INTO OUTFILE "file://${outFilePath}/" FORMAT AS PARQUET; + SELECT * FROM ${tableName} t ORDER BY user_id + INTO OUTFILE "file://${outFilePath}/" + FORMAT AS PARQUET; """ File[] files = path.listFiles() diff --git a/regression-test/suites/external_table_p0/export/hive_read/parquet/test_doris_int96_round_trip.groovy b/regression-test/suites/external_table_p0/export/hive_read/parquet/test_doris_int96_round_trip.groovy new file mode 100644 index 00000000000000..05f2fa9526080f --- /dev/null +++ b/regression-test/suites/external_table_p0/export/hive_read/parquet/test_doris_int96_round_trip.groovy @@ -0,0 +1,75 @@ +// 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_doris_int96_round_trip", "p0,external") { + String enabled = context.config.otherConfigs.get("enableHiveTest") + if (enabled == null || !enabled.equalsIgnoreCase("true")) { + logger.info("disable Hive test.") + return + } + + String hdfsPort = context.config.otherConfigs.get("hive2HdfsPort") + String externalEnvIp = context.config.otherConfigs.get("externalEnvIp") + String defaultFs = "hdfs://${externalEnvIp}:${hdfsPort}" + String uri = "${defaultFs}/user/doris/tmp_data/${UUID.randomUUID()}/exp_" + + sql """ set enable_nereids_planner=true """ + sql """ set enable_fallback_to_original_planner=false """ + sql """ set time_zone='Asia/Shanghai' """ + + sql """ DROP TABLE IF EXISTS test_doris_int96_round_trip """ + sql """ + CREATE TABLE test_doris_int96_round_trip ( + id INT, + datetime_value DATETIME, + datetimev2_value DATETIMEV2(6) + ) + DISTRIBUTED BY HASH(id) + PROPERTIES ("replication_num" = "1") + """ + sql """ + INSERT INTO test_doris_int96_round_trip VALUES + (1, '2023-04-20 00:00:00', '2023-04-20 00:00:00.123456'), + (2, '1970-01-01 08:00:00', '1970-01-01 08:00:00.654321') + """ + + def result = sql """ + SELECT * FROM test_doris_int96_round_trip ORDER BY id + INTO OUTFILE "${uri}" + FORMAT AS parquet + PROPERTIES ( + "fs.defaultFS" = "${defaultFs}", + "hadoop.username" = "doris", + "enable_int96_timestamps" = "true" + ) + """ + String int96OutfileUrl = result[0][3] + + // Doris normalizes INT96 using the export session timezone. Use a different read session + // timezone to prove hive.parquet.time-zone, rather than the session, restores wall-clock time. + sql """ set time_zone='America/Los_Angeles' """ + qt_session_timezone """ SELECT @@time_zone """ + qt_int96_round_trip """ + SELECT * FROM HDFS( + "uri" = "${int96OutfileUrl}0.parquet", + "hadoop.username" = "doris", + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai" + ) + ORDER BY id + """ +} diff --git a/regression-test/suites/external_table_p0/export/hive_read/parquet/test_hive_read_parquet.groovy b/regression-test/suites/external_table_p0/export/hive_read/parquet/test_hive_read_parquet.groovy index 7803883c51266c..fa6d1a2f8e8e75 100644 --- a/regression-test/suites/external_table_p0/export/hive_read/parquet/test_hive_read_parquet.groovy +++ b/regression-test/suites/external_table_p0/export/hive_read/parquet/test_hive_read_parquet.groovy @@ -61,9 +61,11 @@ suite("test_hive_read_parquet", "p0,external") { """ } - def outfile_to_HDFS = { + def outfile_to_HDFS = { enableInt96Timestamps -> // select ... into outfile ... def uuid = UUID.randomUUID().toString() + def int96Property = enableInt96Timestamps == null ? "" : + ",\n \"enable_int96_timestamps\" = \"${enableInt96Timestamps}\"" outfile_path = "/user/doris/tmp_data/${uuid}" uri = "${defaultFS}" + "${outfile_path}/exp_" @@ -74,8 +76,7 @@ suite("test_hive_read_parquet", "p0,external") { FORMAT AS ${format} PROPERTIES ( "fs.defaultFS"="${defaultFS}", - "hadoop.username" = "${hdfsUserName}", - "enable_int96_timestamps" = "true" + "hadoop.username" = "${hdfsUserName}"${int96Property} ); """ logger.info("outfile success path: " + res[0][3]); @@ -135,7 +136,8 @@ suite("test_hive_read_parquet", "p0,external") { qt_select_base1 """ SELECT * FROM ${export_table_name} ORDER BY user_id; """ // test outfile to hdfs - def outfile_url = outfile_to_HDFS() + // The default Doris OUTFILE path uses INT64 timestamps. + def outfile_url = outfile_to_HDFS(null) // create hive table create_hive_table(hive_table, hive_column_define) @@ -249,9 +251,8 @@ suite("test_hive_read_parquet", "p0,external") { qt_select_base2 """ SELECT * FROM ${export_table_name} t ORDER BY user_id; """ // test outfile to hdfs - def outfile_url = outfile_to_HDFS() - // create hive table - create_hive_table(hive_table, hive_column_define) + // The default Doris OUTFILE path uses INT64 timestamps. + def outfile_url = outfile_to_HDFS(null) qt_select_tvf2 """ select * from HDFS( "uri" = "${outfile_url}0.parquet", @@ -259,6 +260,10 @@ suite("test_hive_read_parquet", "p0,external") { "format" = "${format}"); """ + // Hive 2 and 3 do not support Parquet INT64 logical timestamps. Keep the Doris + // OUTFILE/TVF path on INT64, and use INT96 only for the legacy Hive compatibility check. + outfile_to_HDFS(true) + create_hive_table(hive_table, hive_column_define) qt_hive_docker_02 """ SELECT * FROM ${hive_database}.${hive_table};""" } finally { diff --git a/regression-test/suites/external_table_p0/export/hive_read/parquet/test_hive_read_parquet_complex_type.groovy b/regression-test/suites/external_table_p0/export/hive_read/parquet/test_hive_read_parquet_complex_type.groovy index 94c516478b534b..5fa054d44f9006 100644 --- a/regression-test/suites/external_table_p0/export/hive_read/parquet/test_hive_read_parquet_complex_type.groovy +++ b/regression-test/suites/external_table_p0/export/hive_read/parquet/test_hive_read_parquet_complex_type.groovy @@ -90,9 +90,11 @@ suite("test_hive_read_parquet_complex_type", "p0,external") { hive_docker """ ${create_table_str} """ } - def outfile_to_HDFS = { + def outfile_to_HDFS = { enableInt96Timestamps -> // select ... into outfile ... def uuid = UUID.randomUUID().toString() + def int96Property = enableInt96Timestamps == null ? "" : + ",\n \"enable_int96_timestamps\" = \"${enableInt96Timestamps}\"" outfile_path = "/user/doris/tmp_data/${uuid}" uri = "${defaultFS}" + "${outfile_path}/exp_" @@ -102,8 +104,7 @@ suite("test_hive_read_parquet_complex_type", "p0,external") { INTO OUTFILE "${uri}" FORMAT AS ${format} PROPERTIES ( - "hadoop.username" = "${hdfsUserName}", - "enable_int96_timestamps" = "true" + "hadoop.username" = "${hdfsUserName}"${int96Property} ); """ logger.info("outfile success path: " + res[0][3]); @@ -143,7 +144,8 @@ suite("test_hive_read_parquet_complex_type", "p0,external") { qt_select_base1 """ SELECT * FROM ${export_table_name} t ORDER BY user_id; """ // test outfile to hdfs - def outfile_url = outfile_to_HDFS() + // The default Doris OUTFILE path uses INT64 timestamps. + def outfile_url = outfile_to_HDFS(null) // create hive table create_hive_table(hive_table, hive_field_define) @@ -182,7 +184,8 @@ suite("test_hive_read_parquet_complex_type", "p0,external") { qt_select_base2 """ SELECT * FROM ${export_table_name} t ORDER BY user_id; """ // test outfile to hdfs - def outfile_url = outfile_to_HDFS() + // The default Doris OUTFILE path uses INT64 timestamps. + def outfile_url = outfile_to_HDFS(null) // create hive table create_hive_table(hive_table, hive_field_define) @@ -223,7 +226,8 @@ suite("test_hive_read_parquet_complex_type", "p0,external") { qt_select_base3 """ SELECT * FROM ${export_table_name} t ORDER BY user_id; """ // test outfile to hdfs - def outfile_url = outfile_to_HDFS() + // The default Doris OUTFILE path uses INT64 timestamps. + def outfile_url = outfile_to_HDFS(null) // create hive table create_hive_table(hive_table, hive_field_define) @@ -268,17 +272,24 @@ suite("test_hive_read_parquet_complex_type", "p0,external") { qt_select_base4 """ SELECT * FROM ${export_table_name} t ORDER BY user_id; """ // test outfile to hdfs - def outfile_url = outfile_to_HDFS() - - // create hive table - create_hive_table(hive_table, hive_field_define) - - qt_select_tvf4 """ select * from HDFS( + // The default Doris OUTFILE path uses INT64 timestamps. + def outfile_url = outfile_to_HDFS(null) + + qt_select_tvf4 """ select user_id, name, + cast(s_info as struct) + from HDFS( "uri" = "${outfile_url}0.parquet", "hadoop.username" = "${hdfsUserName}", "format" = "${format}"); """ + // Hive 2 and 3 do not support Parquet INT64 logical timestamps. Keep the Doris + // OUTFILE/TVF path on INT64, and use INT96 only for the legacy Hive compatibility check. + outfile_to_HDFS(true) + create_hive_table(hive_table, hive_field_define) qt_hive_docker_04 """ SELECT * FROM ${hive_database}.${hive_table};""" } finally { diff --git a/regression-test/suites/external_table_p0/hive/ddl/test_hive_ctas.groovy b/regression-test/suites/external_table_p0/hive/ddl/test_hive_ctas.groovy index 64c127c030dab4..15b562a082a020 100644 --- a/regression-test/suites/external_table_p0/hive/ddl/test_hive_ctas.groovy +++ b/regression-test/suites/external_table_p0/hive/ddl/test_hive_ctas.groovy @@ -569,7 +569,8 @@ suite("test_hive_ctas", "p0,external") { 'type'='hms', 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', 'fs.defaultFS' = 'hdfs://${externalEnvIp}:${hdfs_port}', - 'use_meta_cache' = 'true' + 'use_meta_cache' = 'true', + 'hive.parquet.time-zone' = 'Asia/Shanghai' );""" sql """switch ${catalog_name}""" diff --git a/regression-test/suites/external_table_p0/hive/test_complex_types.groovy b/regression-test/suites/external_table_p0/hive/test_complex_types.groovy index 40a815a4688d6b..ac59d835b603be 100644 --- a/regression-test/suites/external_table_p0/hive/test_complex_types.groovy +++ b/regression-test/suites/external_table_p0/hive/test_complex_types.groovy @@ -30,7 +30,8 @@ suite("test_complex_types", "p0,external") { sql """drop catalog if exists ${catalog_name}""" sql """create catalog if not exists ${catalog_name} properties ( "type"="hms", - 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}' + 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', + 'hive.parquet.time-zone' = 'Asia/Shanghai' );""" logger.info("catalog " + catalog_name + " created") sql """switch ${catalog_name};""" diff --git a/regression-test/suites/external_table_p0/hive/test_external_catalog_hive.groovy b/regression-test/suites/external_table_p0/hive/test_external_catalog_hive.groovy index 50a72ddff075b3..e23cd7f67c1cab 100644 --- a/regression-test/suites/external_table_p0/hive/test_external_catalog_hive.groovy +++ b/regression-test/suites/external_table_p0/hive/test_external_catalog_hive.groovy @@ -33,7 +33,8 @@ suite("test_external_catalog_hive", "p0,external") { sql """ create catalog if not exists ${catalog_name} properties ( 'type'='hms', - 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}' + 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', + 'hive.parquet.time-zone' = 'Asia/Shanghai' ); """ diff --git a/regression-test/suites/external_table_p0/hive/test_external_catalog_hive_partition.groovy b/regression-test/suites/external_table_p0/hive/test_external_catalog_hive_partition.groovy index beef3b2254b739..85bd031a3048fe 100644 --- a/regression-test/suites/external_table_p0/hive/test_external_catalog_hive_partition.groovy +++ b/regression-test/suites/external_table_p0/hive/test_external_catalog_hive_partition.groovy @@ -30,7 +30,8 @@ suite("test_external_catalog_hive_partition", "p0,external") { sql """ create catalog if not exists ${catalog_name} properties ( 'type'='hms', - 'hive.metastore.uris' = 'thrift://${extHiveHmsHost}:${extHiveHmsPort}' + 'hive.metastore.uris' = 'thrift://${extHiveHmsHost}:${extHiveHmsPort}', + 'hive.parquet.time-zone' = 'Asia/Shanghai' ); """ diff --git a/regression-test/suites/external_table_p0/hive/test_hive_basic_type.groovy b/regression-test/suites/external_table_p0/hive/test_hive_basic_type.groovy index 1a5965694935a1..9829388457e54c 100644 --- a/regression-test/suites/external_table_p0/hive/test_hive_basic_type.groovy +++ b/regression-test/suites/external_table_p0/hive/test_hive_basic_type.groovy @@ -39,7 +39,8 @@ suite("test_hive_basic_type", "p0,external") { sql """CREATE CATALOG ${catalog_name} PROPERTIES ( 'type'='hms', 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', - 'hadoop.username' = 'hive' + 'hadoop.username' = 'hive', + 'hive.parquet.time-zone' = 'Asia/Shanghai' );""" sql """switch ${catalog_name}""" diff --git a/regression-test/suites/external_table_p0/hive/test_hive_compress_type.groovy b/regression-test/suites/external_table_p0/hive/test_hive_compress_type.groovy index 5742ddfd12984a..6dfeb2873c512c 100644 --- a/regression-test/suites/external_table_p0/hive/test_hive_compress_type.groovy +++ b/regression-test/suites/external_table_p0/hive/test_hive_compress_type.groovy @@ -31,7 +31,8 @@ suite("test_hive_compress_type", "p0,external") { sql """drop catalog if exists ${catalog_name}""" sql """create catalog if not exists ${catalog_name} properties ( "type"="hms", - 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}' + 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', + 'hive.parquet.time-zone' = 'Asia/Shanghai' );""" sql """use `${catalog_name}`.`multi_catalog`""" diff --git a/regression-test/suites/external_table_p0/hive/test_hive_get_schema_from_table.groovy b/regression-test/suites/external_table_p0/hive/test_hive_get_schema_from_table.groovy index 772cf4d01f2bac..7c63764be7ccf8 100644 --- a/regression-test/suites/external_table_p0/hive/test_hive_get_schema_from_table.groovy +++ b/regression-test/suites/external_table_p0/hive/test_hive_get_schema_from_table.groovy @@ -78,7 +78,8 @@ suite("test_hive_get_schema_from_table", "p0,external") { 'type'='hms', 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', 'hadoop.username' = 'hive', - 'get_schema_from_table' = 'true' + 'get_schema_from_table' = 'true', + 'hive.parquet.time-zone' = 'Asia/Shanghai' );""" sql """switch ${catalog_name}""" diff --git a/regression-test/suites/external_table_p0/hive/test_hive_page_index.groovy b/regression-test/suites/external_table_p0/hive/test_hive_page_index.groovy index 113494275622f5..7a28188ffb37e8 100644 --- a/regression-test/suites/external_table_p0/hive/test_hive_page_index.groovy +++ b/regression-test/suites/external_table_p0/hive/test_hive_page_index.groovy @@ -34,7 +34,8 @@ suite("test_hive_page_index", "p0,external") { sql """drop catalog if exists ${catalog_name}""" sql """create catalog if not exists ${catalog_name} properties ( "type"="hms", - 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}' + 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', + 'hive.parquet.time-zone' = 'Asia/Shanghai' );""" sql """switch ${catalog_name}""" diff --git a/regression-test/suites/external_table_p0/hive/test_hive_schema_evolution.groovy b/regression-test/suites/external_table_p0/hive/test_hive_schema_evolution.groovy index 746a956f07eee4..0f94daedc48b17 100644 --- a/regression-test/suites/external_table_p0/hive/test_hive_schema_evolution.groovy +++ b/regression-test/suites/external_table_p0/hive/test_hive_schema_evolution.groovy @@ -67,7 +67,8 @@ suite("test_hive_schema_evolution", "p0,external") { sql """drop catalog if exists ${catalog_name}""" sql """create catalog if not exists ${catalog_name} properties ( "type"="hms", - 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}' + 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', + 'hive.parquet.time-zone' = 'Asia/Shanghai' );""" sql """switch ${catalog_name}""" sql """use `${catalog_name}`.`default`""" diff --git a/regression-test/suites/external_table_p0/hive/write/test_hive_text_write_insert.groovy b/regression-test/suites/external_table_p0/hive/write/test_hive_text_write_insert.groovy index 4f59b19f231b46..e867e0744361ce 100644 --- a/regression-test/suites/external_table_p0/hive/write/test_hive_text_write_insert.groovy +++ b/regression-test/suites/external_table_p0/hive/write/test_hive_text_write_insert.groovy @@ -893,7 +893,8 @@ suite("test_hive_text_write_insert", "p0,external") { sql """create catalog if not exists ${catalog_name} properties ( 'type'='hms', 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', - 'fs.defaultFS' = 'hdfs://${externalEnvIp}:${hdfs_port}' + 'fs.defaultFS' = 'hdfs://${externalEnvIp}:${hdfs_port}', + 'hive.parquet.time-zone' = 'Asia/Shanghai' );""" sql """use `${catalog_name}`.`write_test`""" logger.info("hive sql: " + """ use `write_test` """) diff --git a/regression-test/suites/external_table_p0/hive/write/test_hive_write_insert.groovy b/regression-test/suites/external_table_p0/hive/write/test_hive_write_insert.groovy index 4942bc2383d715..6f5251afe75972 100644 --- a/regression-test/suites/external_table_p0/hive/write/test_hive_write_insert.groovy +++ b/regression-test/suites/external_table_p0/hive/write/test_hive_write_insert.groovy @@ -892,7 +892,8 @@ INSERT INTO all_types_par_${format_compression}_${catalog_name}_q03 sql """create catalog if not exists ${catalog_name} properties ( 'type'='hms', 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', - 'fs.defaultFS' = 'hdfs://${externalEnvIp}:${hdfs_port}' + 'fs.defaultFS' = 'hdfs://${externalEnvIp}:${hdfs_port}', + 'hive.parquet.time-zone' = 'Asia/Shanghai' );""" sql """use `${catalog_name}`.`write_test`""" logger.info("hive sql: " + """ use `write_test` """) diff --git a/regression-test/suites/external_table_p0/hive/write/test_hive_write_partitions.groovy b/regression-test/suites/external_table_p0/hive/write/test_hive_write_partitions.groovy index 6a2e3fe4a5351f..8dd0cac5cb7d0b 100644 --- a/regression-test/suites/external_table_p0/hive/write/test_hive_write_partitions.groovy +++ b/regression-test/suites/external_table_p0/hive/write/test_hive_write_partitions.groovy @@ -224,7 +224,8 @@ suite("test_hive_write_partitions", "p0,external") { sql """create catalog if not exists ${catalog_name} properties ( 'type'='hms', 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', - 'fs.defaultFS' = 'hdfs://${externalEnvIp}:${hdfs_port}' + 'fs.defaultFS' = 'hdfs://${externalEnvIp}:${hdfs_port}', + 'hive.parquet.time-zone' = 'Asia/Shanghai' );""" sql """use `${catalog_name}`.`write_test`""" logger.info("hive sql: " + """ use `write_test` """) diff --git a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_insert_overwrite.groovy b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_insert_overwrite.groovy index 0acc21bc90ac1b..2b3414d633c89c 100644 --- a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_insert_overwrite.groovy +++ b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_insert_overwrite.groovy @@ -831,6 +831,7 @@ suite("test_iceberg_insert_overwrite", "p0,external") { 'type'='hms', 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', 'fs.defaultFS' = 'hdfs://${externalEnvIp}:${hdfs_port}', + 'hive.parquet.time-zone' = 'Asia/Shanghai', 'use_meta_cache' = 'true' );""" diff --git a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_insert.groovy b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_insert.groovy index 8b8973e416592e..5aef540d63c02e 100644 --- a/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_insert.groovy +++ b/regression-test/suites/external_table_p0/iceberg/write/test_iceberg_write_insert.groovy @@ -826,6 +826,7 @@ suite("test_iceberg_write_insert", "p0,external") { 'type'='hms', 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', 'fs.defaultFS' = 'hdfs://${externalEnvIp}:${hdfs_port}', + 'hive.parquet.time-zone' = 'Asia/Shanghai', 'use_meta_cache' = 'true' );""" diff --git a/regression-test/suites/external_table_p0/paimon/paimon_timestamp_types.groovy b/regression-test/suites/external_table_p0/paimon/paimon_timestamp_types.groovy index dd3fcaadac2934..b2b0f3f66800d2 100644 --- a/regression-test/suites/external_table_p0/paimon/paimon_timestamp_types.groovy +++ b/regression-test/suites/external_table_p0/paimon/paimon_timestamp_types.groovy @@ -23,6 +23,7 @@ suite("paimon_timestamp_types", "p0,external") { return } + def originalTimeZone = sql("SELECT @@time_zone")[0][0] try { String catalog_name = "paimon_timestamp_types" String minio_port = context.config.otherConfigs.get("iceberg_minio_port") @@ -44,6 +45,8 @@ suite("paimon_timestamp_types", "p0,external") { sql """use flink_paimon;""" logger.info("use test_paimon_db") + // The expected timestamp_ltz values are defined in the Asia/Shanghai timezone. + sql """set time_zone = 'Asia/Shanghai'""" def test_ltz_ntz = { table -> qt_ltz_ntz2 """ select * from ${table} """ @@ -108,10 +111,11 @@ suite("paimon_timestamp_types", "p0,external") { test_ltz_ntz_simple("test_timestamp_ntz_ltz_simple_parquet") } finally { sql """set force_jni_scanner=false""" + sql """set time_zone = '${originalTimeZone}'""" } // TODO: - // 1. Fix: native read + parquet + timestamp(7/8/9) (ts7,ts8,ts9), it will be 8 hour more + // 1. Fix: FileScannerV1 + parquet + timestamp(7/8/9) (ts7,ts8,ts9), it will be 8 hour more // 2. paimon bugs: native read + orc + timestamp_ltz. // In the Shanghai time zone, the read data will be 8 hours less, // because the data written by Flink to the orc file is UTC, but the time zone saved in the orc file is Shanghai. diff --git a/regression-test/suites/external_table_p0/tvf/test_hdfs_parquet_group0.groovy b/regression-test/suites/external_table_p0/tvf/test_hdfs_parquet_group0.groovy index 531bc0deac22b1..9e95864b123ecc 100644 --- a/regression-test/suites/external_table_p0/tvf/test_hdfs_parquet_group0.groovy +++ b/regression-test/suites/external_table_p0/tvf/test_hdfs_parquet_group0.groovy @@ -86,7 +86,8 @@ suite("test_hdfs_parquet_group0", "p0,external") { order_qt_test_8 """ select * from HDFS( "uri" = "${uri}", "hadoop.username" = "${hdfsUserName}", - "format" = "parquet") limit 10; """ + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai") limit 10; """ uri = "${defaultFS}" + "/user/doris/tvf_data/test_hdfs_parquet/group0/delta_encoding_optional_column.parquet" @@ -212,7 +213,8 @@ suite("test_hdfs_parquet_group0", "p0,external") { order_qt_test_26 """ select * from HDFS( "uri" = "${uri}", "hadoop.username" = "${hdfsUserName}", - "format" = "parquet") limit 10; """ + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai") limit 10; """ uri = "${defaultFS}" + "/user/doris/tvf_data/test_hdfs_parquet/group0/dict-page-offset-zero.parquet" @@ -361,14 +363,16 @@ suite("test_hdfs_parquet_group0", "p0,external") { order_qt_test_47 """ select * from HDFS( "uri" = "${uri}", "hadoop.username" = "${hdfsUserName}", - "format" = "parquet") limit 10; """ + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai") limit 10; """ uri = "${defaultFS}" + "/user/doris/tvf_data/test_hdfs_parquet/group0/alltypes_tiny_pages_plain.parquet" order_qt_test_48 """ select * from HDFS( "uri" = "${uri}", "hadoop.username" = "${hdfsUserName}", - "format" = "parquet") limit 10; """ + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai") limit 10; """ uri = "${defaultFS}" + "/user/doris/tvf_data/test_hdfs_parquet/group0/single_nan.parquet" @@ -417,7 +421,8 @@ suite("test_hdfs_parquet_group0", "p0,external") { order_qt_test_55 """ select * from HDFS( "uri" = "${uri}", "hadoop.username" = "${hdfsUserName}", - "format" = "parquet") limit 10; """ + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai") limit 10; """ } finally { } } diff --git a/regression-test/suites/external_table_p0/tvf/test_local_tvf_with_complex_type_element_at.groovy b/regression-test/suites/external_table_p0/tvf/test_local_tvf_with_complex_type_element_at.groovy index 28ddf9c7a51fe5..2ad30283df2ff6 100644 --- a/regression-test/suites/external_table_p0/tvf/test_local_tvf_with_complex_type_element_at.groovy +++ b/regression-test/suites/external_table_p0/tvf/test_local_tvf_with_complex_type_element_at.groovy @@ -95,40 +95,48 @@ suite("test_local_tvf_with_complex_type_element_at", "p0,external") { select * from local( "file_path" = "${outFilePath}/t.parquet", "backend_id" = "${be_id}", - "format" = "parquet"); """ + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai"); """ qt_sql """ select count(*) from local( "file_path" = "${outFilePath}/t.parquet", "backend_id" = "${be_id}", - "format" = "parquet"); """ + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai"); """ qt_sql """ select arr_arr[1][1] from local ( "file_path" = "${outFilePath}/t.parquet", "backend_id" = "${be_id}", - "format" = "parquet");""" + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai");""" qt_sql """ select arr_map[1] from local ( "file_path" = "${outFilePath}/t.parquet", "backend_id" = "${be_id}", - "format" = "parquet");""" + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai");""" qt_sql """ select arr_map[1]["WdTnFb-LHW8Nel-laB-HCQA"] from local ( "file_path" = "${outFilePath}/t.parquet", "backend_id" = "${be_id}", - "format" = "parquet");""" + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai");""" qt_sql """ select map_map["W1iF16-DE1gzJx-avC-Mrf6"]["HJVQSC-46l3xm7-J6c-moIH"] from local ( "file_path" = "${outFilePath}/t.parquet", "backend_id" = "${be_id}", - "format" = "parquet");""" + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai");""" qt_sql """ select map_arr[1] from local ( "file_path" = "${outFilePath}/t.parquet", "backend_id" = "${be_id}", - "format" = "parquet");""" + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai");""" qt_sql """ select map_arr[1][7] from local ( "file_path" = "${outFilePath}/t.parquet", "backend_id" = "${be_id}", - "format" = "parquet");""" + "format" = "parquet", + "hive.parquet.time-zone" = "Asia/Shanghai");""" }