diff --git a/presto-iceberg/src/test/java/com/facebook/presto/iceberg/hive/TestIcebergHiveStatistics.java b/presto-iceberg/src/test/java/com/facebook/presto/iceberg/hive/TestIcebergHiveStatistics.java index f154cae8c4190..ec29e4aae83e2 100644 --- a/presto-iceberg/src/test/java/com/facebook/presto/iceberg/hive/TestIcebergHiveStatistics.java +++ b/presto-iceberg/src/test/java/com/facebook/presto/iceberg/hive/TestIcebergHiveStatistics.java @@ -54,6 +54,7 @@ import com.facebook.presto.spi.statistics.TableStatistics; import com.facebook.presto.sql.planner.Plan; import com.facebook.presto.testing.MaterializedResult; +import com.facebook.presto.testing.MaterializedRow; import com.facebook.presto.testing.QueryRunner; import com.facebook.presto.tests.AbstractTestQueryFramework; import com.google.common.cache.CacheBuilder; @@ -466,6 +467,32 @@ public void testStatisticsCachePartialEviction() } } + @Test + public void testShowStatsWithTimestampWithTimeZone() + { + assertQuerySucceeds("CREATE TABLE test_timestamp_tz(id BIGINT, ts TIMESTAMP WITH TIME ZONE)"); + assertUpdate("INSERT INTO test_timestamp_tz VALUES " + + "(1, TIMESTAMP '2024-01-01 12:00:00 UTC'), " + + "(2, TIMESTAMP '2024-01-02 18:30:00 UTC'), " + + "(3, TIMESTAMP '2024-01-03 00:00:00 America/New_York')", 3); + + MaterializedResult stats = getQueryRunner().execute("SHOW STATS FOR test_timestamp_tz"); + + assertStatValue(StatsSchema.LOW_VALUE, stats, ImmutableSet.of("ts"), null, true); + assertStatValue(StatsSchema.HIGH_VALUE, stats, ImmutableSet.of("ts"), null, true); + + Optional tsRow = stats.getMaterializedRows().stream() + .filter(row -> row.getField(StatsSchema.COLUMN_NAME.ordinal()) != null) + .filter(row -> row.getField(StatsSchema.COLUMN_NAME.ordinal()).equals("ts")) + .findFirst(); + assertTrue(tsRow.isPresent(), "Statistics for column 'ts' not found"); + MaterializedRow row = tsRow.get(); + assertEquals((String) row.getField(StatsSchema.LOW_VALUE.ordinal()), "2024-01-01 12:00:00.000 UTC"); + assertEquals((String) row.getField(StatsSchema.HIGH_VALUE.ordinal()), "2024-01-03 05:00:00.000 UTC"); + + assertQuerySucceeds("DROP TABLE test_timestamp_tz"); + } + private TableStatistics getScanStatsEstimate(Session session, @Language("SQL") String sql) { Plan plan = plan(sql, session); diff --git a/presto-main-base/src/main/java/com/facebook/presto/sql/rewrite/ShowStatsRewrite.java b/presto-main-base/src/main/java/com/facebook/presto/sql/rewrite/ShowStatsRewrite.java index e485217bb40df..705c780256bb2 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/sql/rewrite/ShowStatsRewrite.java +++ b/presto-main-base/src/main/java/com/facebook/presto/sql/rewrite/ShowStatsRewrite.java @@ -23,6 +23,7 @@ import com.facebook.presto.common.type.SmallintType; import com.facebook.presto.common.type.SqlTime; import com.facebook.presto.common.type.SqlTimestamp; +import com.facebook.presto.common.type.SqlTimestampWithTimeZone; import com.facebook.presto.common.type.TinyintType; import com.facebook.presto.common.type.Type; import com.facebook.presto.metadata.Metadata; @@ -82,7 +83,9 @@ import static com.facebook.presto.common.type.StandardTypes.DOUBLE; import static com.facebook.presto.common.type.StandardTypes.VARCHAR; import static com.facebook.presto.common.type.TimeType.TIME; +import static com.facebook.presto.common.type.TimeZoneKey.UTC_KEY; import static com.facebook.presto.common.type.TimestampType.TIMESTAMP; +import static com.facebook.presto.common.type.TimestampWithTimeZoneType.TIMESTAMP_WITH_TIME_ZONE; import static com.facebook.presto.metadata.MetadataUtil.createQualifiedObjectName; import static com.facebook.presto.sql.QueryUtil.aliased; import static com.facebook.presto.sql.QueryUtil.selectAll; @@ -381,6 +384,9 @@ private Expression toStringLiteral(Type type, double value) if (type.equals(TIME)) { return new StringLiteral(new SqlTime(round(value)).toString()); } + if (type.equals(TIMESTAMP_WITH_TIME_ZONE)) { + return new StringLiteral(new SqlTimestampWithTimeZone(round(value) / MICROSECONDS_PER_MILLISECOND, UTC_KEY).toString()); + } throw new IllegalArgumentException("Unexpected type: " + type); } }