|
19 | 19 |
|
20 | 20 | // TODO: potentially move this to arrow-rs: https://github.com/apache/arrow-rs/issues/4328 |
21 | 21 |
|
22 | | -use arrow::{array::ArrayRef, datatypes::DataType}; |
| 22 | +use arrow::{array::ArrayRef, datatypes::DataType, datatypes::TimeUnit}; |
23 | 23 | use arrow_array::{new_empty_array, new_null_array, UInt64Array}; |
24 | 24 | use arrow_schema::{Field, FieldRef, Schema}; |
25 | 25 | use datafusion_common::{ |
@@ -112,6 +112,26 @@ macro_rules! get_statistic { |
112 | 112 | Some(DataType::UInt64) => { |
113 | 113 | Some(ScalarValue::UInt64(Some((*s.$func()) as u64))) |
114 | 114 | } |
| 115 | + Some(DataType::Timestamp(unit, timezone)) => { |
| 116 | + Some(match unit { |
| 117 | + TimeUnit::Second => ScalarValue::TimestampSecond( |
| 118 | + Some(*s.$func()), |
| 119 | + timezone.clone(), |
| 120 | + ), |
| 121 | + TimeUnit::Millisecond => ScalarValue::TimestampMillisecond( |
| 122 | + Some(*s.$func()), |
| 123 | + timezone.clone(), |
| 124 | + ), |
| 125 | + TimeUnit::Microsecond => ScalarValue::TimestampMicrosecond( |
| 126 | + Some(*s.$func()), |
| 127 | + timezone.clone(), |
| 128 | + ), |
| 129 | + TimeUnit::Nanosecond => ScalarValue::TimestampNanosecond( |
| 130 | + Some(*s.$func()), |
| 131 | + timezone.clone(), |
| 132 | + ), |
| 133 | + }) |
| 134 | + } |
115 | 135 | _ => Some(ScalarValue::Int64(Some(*s.$func()))), |
116 | 136 | } |
117 | 137 | } |
@@ -395,7 +415,8 @@ mod test { |
395 | 415 | use arrow_array::{ |
396 | 416 | new_null_array, Array, BinaryArray, BooleanArray, Date32Array, Date64Array, |
397 | 417 | Decimal128Array, Float32Array, Float64Array, Int16Array, Int32Array, Int64Array, |
398 | | - Int8Array, RecordBatch, StringArray, StructArray, TimestampNanosecondArray, |
| 418 | + Int8Array, RecordBatch, StringArray, StructArray, TimestampMicrosecondArray, |
| 419 | + TimestampMillisecondArray, TimestampNanosecondArray, TimestampSecondArray, |
399 | 420 | }; |
400 | 421 | use arrow_schema::{Field, SchemaRef}; |
401 | 422 | use bytes::Bytes; |
@@ -536,28 +557,209 @@ mod test { |
536 | 557 | } |
537 | 558 |
|
538 | 559 | #[test] |
539 | | - #[should_panic( |
540 | | - expected = "Inconsistent types in ScalarValue::iter_to_array. Expected Int64, got TimestampNanosecond(NULL, None)" |
541 | | - )] |
542 | | - // Due to https://github.com/apache/datafusion/issues/8295 |
543 | 560 | fn roundtrip_timestamp() { |
544 | 561 | Test { |
545 | | - input: timestamp_array([ |
546 | | - // row group 1 |
547 | | - Some(1), |
548 | | - None, |
549 | | - Some(3), |
550 | | - // row group 2 |
551 | | - Some(9), |
552 | | - Some(5), |
| 562 | + input: timestamp_seconds_array( |
| 563 | + [ |
| 564 | + // row group 1 |
| 565 | + Some(1), |
| 566 | + None, |
| 567 | + Some(3), |
| 568 | + // row group 2 |
| 569 | + Some(9), |
| 570 | + Some(5), |
| 571 | + None, |
| 572 | + // row group 3 |
| 573 | + None, |
| 574 | + None, |
| 575 | + None, |
| 576 | + ], |
553 | 577 | None, |
554 | | - // row group 3 |
| 578 | + ), |
| 579 | + expected_min: timestamp_seconds_array([Some(1), Some(5), None], None), |
| 580 | + expected_max: timestamp_seconds_array([Some(3), Some(9), None], None), |
| 581 | + } |
| 582 | + .run(); |
| 583 | + |
| 584 | + Test { |
| 585 | + input: timestamp_milliseconds_array( |
| 586 | + [ |
| 587 | + // row group 1 |
| 588 | + Some(1), |
| 589 | + None, |
| 590 | + Some(3), |
| 591 | + // row group 2 |
| 592 | + Some(9), |
| 593 | + Some(5), |
| 594 | + None, |
| 595 | + // row group 3 |
| 596 | + None, |
| 597 | + None, |
| 598 | + None, |
| 599 | + ], |
555 | 600 | None, |
| 601 | + ), |
| 602 | + expected_min: timestamp_milliseconds_array([Some(1), Some(5), None], None), |
| 603 | + expected_max: timestamp_milliseconds_array([Some(3), Some(9), None], None), |
| 604 | + } |
| 605 | + .run(); |
| 606 | + |
| 607 | + Test { |
| 608 | + input: timestamp_microseconds_array( |
| 609 | + [ |
| 610 | + // row group 1 |
| 611 | + Some(1), |
| 612 | + None, |
| 613 | + Some(3), |
| 614 | + // row group 2 |
| 615 | + Some(9), |
| 616 | + Some(5), |
| 617 | + None, |
| 618 | + // row group 3 |
| 619 | + None, |
| 620 | + None, |
| 621 | + None, |
| 622 | + ], |
556 | 623 | None, |
| 624 | + ), |
| 625 | + expected_min: timestamp_microseconds_array([Some(1), Some(5), None], None), |
| 626 | + expected_max: timestamp_microseconds_array([Some(3), Some(9), None], None), |
| 627 | + } |
| 628 | + .run(); |
| 629 | + |
| 630 | + Test { |
| 631 | + input: timestamp_nanoseconds_array( |
| 632 | + [ |
| 633 | + // row group 1 |
| 634 | + Some(1), |
| 635 | + None, |
| 636 | + Some(3), |
| 637 | + // row group 2 |
| 638 | + Some(9), |
| 639 | + Some(5), |
| 640 | + None, |
| 641 | + // row group 3 |
| 642 | + None, |
| 643 | + None, |
| 644 | + None, |
| 645 | + ], |
557 | 646 | None, |
558 | | - ]), |
559 | | - expected_min: timestamp_array([Some(1), Some(5), None]), |
560 | | - expected_max: timestamp_array([Some(3), Some(9), None]), |
| 647 | + ), |
| 648 | + expected_min: timestamp_nanoseconds_array([Some(1), Some(5), None], None), |
| 649 | + expected_max: timestamp_nanoseconds_array([Some(3), Some(9), None], None), |
| 650 | + } |
| 651 | + .run() |
| 652 | + } |
| 653 | + |
| 654 | + #[test] |
| 655 | + fn roundtrip_timestamp_timezoned() { |
| 656 | + Test { |
| 657 | + input: timestamp_seconds_array( |
| 658 | + [ |
| 659 | + // row group 1 |
| 660 | + Some(1), |
| 661 | + None, |
| 662 | + Some(3), |
| 663 | + // row group 2 |
| 664 | + Some(9), |
| 665 | + Some(5), |
| 666 | + None, |
| 667 | + // row group 3 |
| 668 | + None, |
| 669 | + None, |
| 670 | + None, |
| 671 | + ], |
| 672 | + Some("UTC"), |
| 673 | + ), |
| 674 | + expected_min: timestamp_seconds_array([Some(1), Some(5), None], Some("UTC")), |
| 675 | + expected_max: timestamp_seconds_array([Some(3), Some(9), None], Some("UTC")), |
| 676 | + } |
| 677 | + .run(); |
| 678 | + |
| 679 | + Test { |
| 680 | + input: timestamp_milliseconds_array( |
| 681 | + [ |
| 682 | + // row group 1 |
| 683 | + Some(1), |
| 684 | + None, |
| 685 | + Some(3), |
| 686 | + // row group 2 |
| 687 | + Some(9), |
| 688 | + Some(5), |
| 689 | + None, |
| 690 | + // row group 3 |
| 691 | + None, |
| 692 | + None, |
| 693 | + None, |
| 694 | + ], |
| 695 | + Some("UTC"), |
| 696 | + ), |
| 697 | + expected_min: timestamp_milliseconds_array( |
| 698 | + [Some(1), Some(5), None], |
| 699 | + Some("UTC"), |
| 700 | + ), |
| 701 | + expected_max: timestamp_milliseconds_array( |
| 702 | + [Some(3), Some(9), None], |
| 703 | + Some("UTC"), |
| 704 | + ), |
| 705 | + } |
| 706 | + .run(); |
| 707 | + |
| 708 | + Test { |
| 709 | + input: timestamp_microseconds_array( |
| 710 | + [ |
| 711 | + // row group 1 |
| 712 | + Some(1), |
| 713 | + None, |
| 714 | + Some(3), |
| 715 | + // row group 2 |
| 716 | + Some(9), |
| 717 | + Some(5), |
| 718 | + None, |
| 719 | + // row group 3 |
| 720 | + None, |
| 721 | + None, |
| 722 | + None, |
| 723 | + ], |
| 724 | + Some("UTC"), |
| 725 | + ), |
| 726 | + expected_min: timestamp_microseconds_array( |
| 727 | + [Some(1), Some(5), None], |
| 728 | + Some("UTC"), |
| 729 | + ), |
| 730 | + expected_max: timestamp_microseconds_array( |
| 731 | + [Some(3), Some(9), None], |
| 732 | + Some("UTC"), |
| 733 | + ), |
| 734 | + } |
| 735 | + .run(); |
| 736 | + |
| 737 | + Test { |
| 738 | + input: timestamp_nanoseconds_array( |
| 739 | + [ |
| 740 | + // row group 1 |
| 741 | + Some(1), |
| 742 | + None, |
| 743 | + Some(3), |
| 744 | + // row group 2 |
| 745 | + Some(9), |
| 746 | + Some(5), |
| 747 | + None, |
| 748 | + // row group 3 |
| 749 | + None, |
| 750 | + None, |
| 751 | + None, |
| 752 | + ], |
| 753 | + Some("UTC"), |
| 754 | + ), |
| 755 | + expected_min: timestamp_nanoseconds_array( |
| 756 | + [Some(1), Some(5), None], |
| 757 | + Some("UTC"), |
| 758 | + ), |
| 759 | + expected_max: timestamp_nanoseconds_array( |
| 760 | + [Some(3), Some(9), None], |
| 761 | + Some("UTC"), |
| 762 | + ), |
561 | 763 | } |
562 | 764 | .run() |
563 | 765 | } |
@@ -914,8 +1116,8 @@ mod test { |
914 | 1116 | // File has no min/max for timestamp_col |
915 | 1117 | .with_column(ExpectedColumn { |
916 | 1118 | name: "timestamp_col", |
917 | | - expected_min: timestamp_array([None]), |
918 | | - expected_max: timestamp_array([None]), |
| 1119 | + expected_min: timestamp_nanoseconds_array([None], None), |
| 1120 | + expected_max: timestamp_nanoseconds_array([None], None), |
919 | 1121 | }) |
920 | 1122 | .with_column(ExpectedColumn { |
921 | 1123 | name: "year", |
@@ -1135,9 +1337,48 @@ mod test { |
1135 | 1337 | Arc::new(array) |
1136 | 1338 | } |
1137 | 1339 |
|
1138 | | - fn timestamp_array(input: impl IntoIterator<Item = Option<i64>>) -> ArrayRef { |
| 1340 | + fn timestamp_seconds_array( |
| 1341 | + input: impl IntoIterator<Item = Option<i64>>, |
| 1342 | + timzezone: Option<&str>, |
| 1343 | + ) -> ArrayRef { |
| 1344 | + let array: TimestampSecondArray = input.into_iter().collect(); |
| 1345 | + match timzezone { |
| 1346 | + Some(tz) => Arc::new(array.with_timezone(tz)), |
| 1347 | + None => Arc::new(array), |
| 1348 | + } |
| 1349 | + } |
| 1350 | + |
| 1351 | + fn timestamp_milliseconds_array( |
| 1352 | + input: impl IntoIterator<Item = Option<i64>>, |
| 1353 | + timzezone: Option<&str>, |
| 1354 | + ) -> ArrayRef { |
| 1355 | + let array: TimestampMillisecondArray = input.into_iter().collect(); |
| 1356 | + match timzezone { |
| 1357 | + Some(tz) => Arc::new(array.with_timezone(tz)), |
| 1358 | + None => Arc::new(array), |
| 1359 | + } |
| 1360 | + } |
| 1361 | + |
| 1362 | + fn timestamp_microseconds_array( |
| 1363 | + input: impl IntoIterator<Item = Option<i64>>, |
| 1364 | + timzezone: Option<&str>, |
| 1365 | + ) -> ArrayRef { |
| 1366 | + let array: TimestampMicrosecondArray = input.into_iter().collect(); |
| 1367 | + match timzezone { |
| 1368 | + Some(tz) => Arc::new(array.with_timezone(tz)), |
| 1369 | + None => Arc::new(array), |
| 1370 | + } |
| 1371 | + } |
| 1372 | + |
| 1373 | + fn timestamp_nanoseconds_array( |
| 1374 | + input: impl IntoIterator<Item = Option<i64>>, |
| 1375 | + timzezone: Option<&str>, |
| 1376 | + ) -> ArrayRef { |
1139 | 1377 | let array: TimestampNanosecondArray = input.into_iter().collect(); |
1140 | | - Arc::new(array) |
| 1378 | + match timzezone { |
| 1379 | + Some(tz) => Arc::new(array.with_timezone(tz)), |
| 1380 | + None => Arc::new(array), |
| 1381 | + } |
1141 | 1382 | } |
1142 | 1383 |
|
1143 | 1384 | fn utf8_array<'a>(input: impl IntoIterator<Item = Option<&'a str>>) -> ArrayRef { |
|
0 commit comments