|
74 | 74 | #include "runtime/runtime_state.h" |
75 | 75 | #include "storage/segment/condition_cache.h" |
76 | 76 | #include "storage/utils.h" |
| 77 | +#include "util/timezone_utils.h" |
77 | 78 |
|
78 | 79 | namespace doris { |
79 | 80 | namespace { |
@@ -2455,6 +2456,49 @@ class NullableGreaterThanExpr final : public VExpr { |
2455 | 2456 | const std::string _expr_name; |
2456 | 2457 | }; |
2457 | 2458 |
|
| 2459 | +template <PrimitiveType Primitive> |
| 2460 | +class NullableEqualsExpr final : public VExpr { |
| 2461 | +public: |
| 2462 | + using ColumnType = typename PrimitiveTypeTraits<Primitive>::ColumnType; |
| 2463 | + using ValueType = typename PrimitiveTypeTraits<Primitive>::CppType; |
| 2464 | + |
| 2465 | + NullableEqualsExpr(int column_id, DataTypePtr type, const Field& value, std::string column_name) |
| 2466 | + : VExpr(std::make_shared<DataTypeUInt8>(), false), |
| 2467 | + _column_id(column_id), |
| 2468 | + _value(value.get<Primitive>()), |
| 2469 | + _expr_name("NullableEqualsExpr") { |
| 2470 | + _node_type = TExprNodeType::BINARY_PRED; |
| 2471 | + _opcode = TExprOpcode::EQ; |
| 2472 | + add_child(TableSlotRef::create_shared(column_id, column_id, -1, make_nullable(type), |
| 2473 | + std::move(column_name))); |
| 2474 | + add_child(TableLiteral::create_shared(std::move(type), value)); |
| 2475 | + } |
| 2476 | + |
| 2477 | + Status execute_column_impl(VExprContext* context, const Block* block, const Selector* selector, |
| 2478 | + size_t count, ColumnPtr& result_column) const override { |
| 2479 | + const auto& nullable_column = |
| 2480 | + assert_cast<const ColumnNullable&>(*block->get_by_position(_column_id).column); |
| 2481 | + const auto& input = assert_cast<const ColumnType&>(nullable_column.get_nested_column()); |
| 2482 | + auto result = ColumnUInt8::create(); |
| 2483 | + auto& result_data = result->get_data(); |
| 2484 | + result_data.resize(count); |
| 2485 | + for (size_t row = 0; row < count; ++row) { |
| 2486 | + const size_t input_row = selector == nullptr ? row : (*selector)[row]; |
| 2487 | + result_data[row] = !nullable_column.is_null_at(input_row) && |
| 2488 | + input.get_element(input_row) == _value; |
| 2489 | + } |
| 2490 | + result_column = std::move(result); |
| 2491 | + return Status::OK(); |
| 2492 | + } |
| 2493 | + |
| 2494 | + const std::string& expr_name() const override { return _expr_name; } |
| 2495 | + |
| 2496 | +private: |
| 2497 | + const int _column_id; |
| 2498 | + const ValueType _value; |
| 2499 | + const std::string _expr_name; |
| 2500 | +}; |
| 2501 | + |
2458 | 2502 | template <PrimitiveType Primitive> |
2459 | 2503 | class NullableInExpr final : public VExpr { |
2460 | 2504 | public: |
@@ -4036,7 +4080,9 @@ void write_multi_stripe_orc_sarg_types_file(const std::string& file_path) { |
4036 | 4080 | out.write(memory_stream.getData(), static_cast<std::streamsize>(memory_stream.getLength())); |
4037 | 4081 | } |
4038 | 4082 |
|
4039 | | -void write_multi_stripe_orc_timestamp_instant_sarg_file(const std::string& file_path) { |
| 4083 | +void write_multi_stripe_orc_timestamp_instant_sarg_file( |
| 4084 | + const std::string& file_path, int64_t first_timestamp_second = 0, |
| 4085 | + int64_t second_timestamp_second = 1609459200) { |
4040 | 4086 | auto type = std::unique_ptr<::orc::Type>(::orc::Type::buildTypeFromString( |
4041 | 4087 | "struct<timestamp_instant_col:timestamp with local time zone,payload:string>")); |
4042 | 4088 |
|
@@ -4068,8 +4114,8 @@ void write_multi_stripe_orc_timestamp_instant_sarg_file(const std::string& file_ |
4068 | 4114 | writer->add(*batch); |
4069 | 4115 | }; |
4070 | 4116 |
|
4071 | | - add_batch(0); |
4072 | | - add_batch(1609459200); |
| 4117 | + add_batch(first_timestamp_second); |
| 4118 | + add_batch(second_timestamp_second); |
4073 | 4119 | writer->close(); |
4074 | 4120 |
|
4075 | 4121 | std::ofstream out(file_path, std::ios::binary); |
@@ -8327,6 +8373,49 @@ TEST_F(NewOrcReaderTest, SargTimestampInstantConjunctUsesSessionTimezone) { |
8327 | 8373 | EXPECT_EQ(reader->reader_statistics().filtered_group_rows, 200); |
8328 | 8374 | } |
8329 | 8375 |
|
| 8376 | +TEST_F(NewOrcReaderTest, SargTimestampInstantRepeatedCivilTimeDoesNotPruneStripes) { |
| 8377 | + const auto multi_stripe_file_path = |
| 8378 | + (_test_dir / "sarg_timestamp_instant_dst_rollback.orc").string(); |
| 8379 | + // These UTC instants both decode to 2021-11-07 01:30:00.123 in America/New_York, |
| 8380 | + // once before and once after the UTC-04:00 to UTC-05:00 rollback. |
| 8381 | + write_multi_stripe_orc_timestamp_instant_sarg_file(multi_stripe_file_path, 1636263000, |
| 8382 | + 1636266600); |
| 8383 | + ASSERT_EQ(get_orc_stripe_count(multi_stripe_file_path), 2); |
| 8384 | + |
| 8385 | + auto reader = create_reader_for_path(multi_stripe_file_path); |
| 8386 | + RuntimeState state {TQueryOptions(), TQueryGlobals()}; |
| 8387 | + TimezoneUtils::load_timezones_to_cache(); |
| 8388 | + state.set_timezone("America/New_York"); |
| 8389 | + ASSERT_TRUE(reader->init(&state).ok()); |
| 8390 | + |
| 8391 | + std::vector<format::ColumnDefinition> schema; |
| 8392 | + ASSERT_TRUE(reader->get_schema(&schema).ok()); |
| 8393 | + ASSERT_EQ(schema.size(), 2); |
| 8394 | + |
| 8395 | + const auto literal = |
| 8396 | + Field::create_field<TYPE_DATETIMEV2>(make_datetime_v2(2021, 11, 7, 1, 30, 0, 123000)); |
| 8397 | + auto request = std::make_shared<format::FileScanRequest>(); |
| 8398 | + request->predicate_columns = {field_projection(0)}; |
| 8399 | + request->conjuncts.push_back( |
| 8400 | + VExprContext::create_shared(std::make_shared<NullableEqualsExpr<TYPE_DATETIMEV2>>( |
| 8401 | + 0, remove_nullable(schema[0].type), literal, "timestamp_instant_col"))); |
| 8402 | + ASSERT_TRUE(reader->open(request).ok()); |
| 8403 | + |
| 8404 | + bool eof = false; |
| 8405 | + size_t result_rows = 0; |
| 8406 | + while (!eof) { |
| 8407 | + Block block = build_file_block({schema[0]}); |
| 8408 | + size_t rows = 0; |
| 8409 | + ASSERT_TRUE(reader->get_block(&block, &rows, &eof).ok()); |
| 8410 | + result_rows += rows; |
| 8411 | + } |
| 8412 | + |
| 8413 | + EXPECT_EQ(result_rows, 2); |
| 8414 | + EXPECT_EQ(reader->reader_statistics().filtered_row_groups, 0); |
| 8415 | + EXPECT_EQ(reader->reader_statistics().filtered_row_groups_by_min_max, 0); |
| 8416 | + EXPECT_EQ(reader->reader_statistics().filtered_group_rows, 0); |
| 8417 | +} |
| 8418 | + |
8330 | 8419 | TEST_F(NewOrcReaderTest, SargTimestampLowerPrecisionCastDoesNotPruneStripes) { |
8331 | 8420 | const auto multi_stripe_file_path = |
8332 | 8421 | (_test_dir / "sarg_timestamp_lower_precision_cast.orc").string(); |
|
0 commit comments