43
43
import io .trino .hive .thrift .metastore .SerDeInfo ;
44
44
import io .trino .hive .thrift .metastore .StorageDescriptor ;
45
45
import io .trino .hive .thrift .metastore .StringColumnStatsData ;
46
+ import io .trino .hive .thrift .metastore .Timestamp ;
47
+ import io .trino .hive .thrift .metastore .TimestampColumnStatsData ;
46
48
import io .trino .metastore .AcidOperation ;
47
49
import io .trino .metastore .Column ;
48
50
import io .trino .metastore .Database ;
83
85
import java .math .BigInteger ;
84
86
import java .nio .ByteBuffer ;
85
87
import java .time .LocalDate ;
88
+ import java .time .LocalDateTime ;
89
+ import java .time .ZoneOffset ;
86
90
import java .util .ArrayDeque ;
87
91
import java .util .Arrays ;
88
92
import java .util .Collection ;
148
152
import static io .trino .spi .type .IntegerType .INTEGER ;
149
153
import static io .trino .spi .type .RealType .REAL ;
150
154
import static io .trino .spi .type .SmallintType .SMALLINT ;
155
+ import static io .trino .spi .type .StandardTypes .TIMESTAMP ;
156
+ import static io .trino .spi .type .Timestamps .MICROSECONDS_PER_MILLISECOND ;
157
+ import static io .trino .spi .type .Timestamps .MICROSECONDS_PER_SECOND ;
151
158
import static io .trino .spi .type .TinyintType .TINYINT ;
152
159
import static io .trino .spi .type .VarbinaryType .VARBINARY ;
160
+ import static java .lang .Math .ceilDiv ;
161
+ import static java .lang .Math .floorDiv ;
153
162
import static java .lang .Math .toIntExact ;
154
163
import static java .lang .String .format ;
155
164
import static java .util .Locale .ENGLISH ;
@@ -521,6 +530,10 @@ public static HiveColumnStatistics fromMetastoreApiColumnStatistics(ColumnStatis
521
530
LongColumnStatsData longStatsData = columnStatistics .getStatsData ().getLongStats ();
522
531
OptionalLong min = longStatsData .isSetLowValue () ? OptionalLong .of (longStatsData .getLowValue ()) : OptionalLong .empty ();
523
532
OptionalLong max = longStatsData .isSetHighValue () ? OptionalLong .of (longStatsData .getHighValue ()) : OptionalLong .empty ();
533
+ if (min .isPresent () && max .isPresent () && columnStatistics .getColType ().equals (TIMESTAMP )) {
534
+ min = OptionalLong .of (min .getAsLong () * MICROSECONDS_PER_SECOND );
535
+ max = OptionalLong .of (max .getAsLong () * MICROSECONDS_PER_SECOND );
536
+ }
524
537
OptionalLong nullsCount = longStatsData .isSetNumNulls () ? fromMetastoreNullsCount (longStatsData .getNumNulls ()) : OptionalLong .empty ();
525
538
OptionalLong distinctValuesWithNullCount = longStatsData .isSetNumDVs () ? OptionalLong .of (longStatsData .getNumDVs ()) : OptionalLong .empty ();
526
539
return createIntegerColumnStatistics (min , max , nullsCount , distinctValuesWithNullCount );
@@ -585,6 +598,14 @@ public static HiveColumnStatistics fromMetastoreApiColumnStatistics(ColumnStatis
585
598
averageColumnLength ,
586
599
nullsCount );
587
600
}
601
+ if (columnStatistics .getStatsData ().isSetTimestampStats ()) {
602
+ TimestampColumnStatsData timestampStatsData = columnStatistics .getStatsData ().getTimestampStats ();
603
+ OptionalLong min = timestampStatsData .isSetLowValue () ? fromMetastoreTimestamp (timestampStatsData .getLowValue ()) : OptionalLong .empty ();
604
+ OptionalLong max = timestampStatsData .isSetHighValue () ? fromMetastoreTimestamp (timestampStatsData .getHighValue ()) : OptionalLong .empty ();
605
+ OptionalLong nullsCount = timestampStatsData .isSetNumNulls () ? fromMetastoreNullsCount (timestampStatsData .getNumNulls ()) : OptionalLong .empty ();
606
+ OptionalLong distinctValuesWithNullCount = timestampStatsData .isSetNumDVs () ? OptionalLong .of (timestampStatsData .getNumDVs ()) : OptionalLong .empty ();
607
+ return createIntegerColumnStatistics (min , max , nullsCount , distinctValuesWithNullCount );
608
+ }
588
609
throw new TrinoException (HIVE_INVALID_METADATA , "Invalid column statistics data: " + columnStatistics );
589
610
}
590
611
@@ -609,6 +630,14 @@ public static OptionalLong fromMetastoreNullsCount(long nullsCount)
609
630
return OptionalLong .of (nullsCount );
610
631
}
611
632
633
+ private static OptionalLong fromMetastoreTimestamp (Timestamp timestamp )
634
+ {
635
+ if (timestamp == null ) {
636
+ return OptionalLong .empty ();
637
+ }
638
+ return OptionalLong .of (LocalDateTime .ofEpochSecond (timestamp .getSecondsSinceEpoch (), 0 , ZoneOffset .UTC ).toInstant (ZoneOffset .UTC ).toEpochMilli () * MICROSECONDS_PER_MILLISECOND );
639
+ }
640
+
612
641
private static Optional <BigDecimal > fromMetastoreDecimal (@ Nullable Decimal decimal )
613
642
{
614
643
if (decimal == null ) {
@@ -768,8 +797,9 @@ public static ColumnStatisticsObj createMetastoreColumnStatistics(String columnN
768
797
case SHORT :
769
798
case INT :
770
799
case LONG :
771
- case TIMESTAMP :
772
800
return createLongStatistics (columnName , columnType , statistics );
801
+ case TIMESTAMP :
802
+ return createTimestampStatistics (columnName , columnType , statistics );
773
803
case FLOAT :
774
804
case DOUBLE :
775
805
return createDoubleStatistics (columnName , columnType , statistics );
@@ -819,6 +849,18 @@ private static ColumnStatisticsObj createLongStatistics(String columnName, HiveT
819
849
return new ColumnStatisticsObj (columnName , columnType .toString (), longStats (data ));
820
850
}
821
851
852
+ private static ColumnStatisticsObj createTimestampStatistics (String columnName , HiveType columnType , HiveColumnStatistics statistics )
853
+ {
854
+ LongColumnStatsData data = new LongColumnStatsData ();
855
+ statistics .getIntegerStatistics ().ifPresent (timestampStatistics -> {
856
+ timestampStatistics .getMin ().ifPresent (value -> data .setLowValue (floorDiv (value , MICROSECONDS_PER_SECOND )));
857
+ timestampStatistics .getMax ().ifPresent (value -> data .setHighValue (ceilDiv (value , MICROSECONDS_PER_SECOND )));
858
+ });
859
+ statistics .getNullsCount ().ifPresent (data ::setNumNulls );
860
+ statistics .getDistinctValuesWithNullCount ().ifPresent (data ::setNumDVs );
861
+ return new ColumnStatisticsObj (columnName , columnType .toString (), longStats (data ));
862
+ }
863
+
822
864
private static ColumnStatisticsObj createDoubleStatistics (String columnName , HiveType columnType , HiveColumnStatistics statistics )
823
865
{
824
866
DoubleColumnStatsData data = new DoubleColumnStatsData ();
@@ -893,8 +935,7 @@ public static Set<HiveColumnStatisticType> getSupportedColumnStatistics(Type typ
893
935
return ImmutableSet .of (MIN_VALUE , MAX_VALUE , NUMBER_OF_DISTINCT_VALUES , NUMBER_OF_NON_NULL_VALUES );
894
936
}
895
937
if (type instanceof TimestampType || type instanceof TimestampWithTimeZoneType ) {
896
- // TODO (https://github.com/trinodb/trino/issues/5859) Add support for timestamp MIN_VALUE, MAX_VALUE
897
- return ImmutableSet .of (NUMBER_OF_DISTINCT_VALUES , NUMBER_OF_NON_NULL_VALUES );
938
+ return ImmutableSet .of (MIN_VALUE , MAX_VALUE , NUMBER_OF_DISTINCT_VALUES , NUMBER_OF_NON_NULL_VALUES );
898
939
}
899
940
if (type instanceof VarcharType || type instanceof CharType ) {
900
941
// TODO Collect MIN,MAX once it is used by the optimizer
0 commit comments