|
13 | 13 | */ |
14 | 14 | package io.trino.type; |
15 | 15 |
|
| 16 | +import io.trino.sql.ExpressionFormatter; |
16 | 17 | import io.trino.sql.query.QueryAssertions; |
| 18 | +import io.trino.sql.query.QueryAssertions.ExpressionAssertProvider.Result; |
| 19 | +import io.trino.sql.tree.IntervalLiteral; |
| 20 | +import org.intellij.lang.annotations.Language; |
17 | 21 | import org.junit.jupiter.api.AfterAll; |
18 | 22 | import org.junit.jupiter.api.BeforeAll; |
19 | 23 | import org.junit.jupiter.api.Test; |
20 | 24 | import org.junit.jupiter.api.TestInstance; |
21 | 25 | import org.junit.jupiter.api.parallel.Execution; |
22 | 26 |
|
| 27 | +import java.time.Duration; |
| 28 | + |
23 | 29 | import static io.trino.spi.StandardErrorCode.INVALID_FUNCTION_ARGUMENT; |
24 | 30 | import static io.trino.spi.function.OperatorType.ADD; |
25 | 31 | import static io.trino.spi.function.OperatorType.DIVIDE; |
|
32 | 38 | import static io.trino.spi.function.OperatorType.SUBTRACT; |
33 | 39 | import static io.trino.spi.type.VarcharType.VARCHAR; |
34 | 40 | import static io.trino.testing.assertions.TrinoExceptionAssert.assertTrinoExceptionThrownBy; |
| 41 | +import static io.trino.util.DateTimeUtils.formatDayTimeInterval; |
35 | 42 | import static java.util.concurrent.TimeUnit.DAYS; |
36 | 43 | import static org.assertj.core.api.Assertions.assertThat; |
37 | 44 | import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; |
@@ -523,4 +530,74 @@ public void testIndeterminate() |
523 | 530 | assertThat(assertions.operator(INDETERMINATE, "INTERVAL '45' MINUTE TO SECOND")) |
524 | 531 | .isEqualTo(false); |
525 | 532 | } |
| 533 | + |
| 534 | + @Test |
| 535 | + void testIntervalDayTimeRoundTrip() |
| 536 | + { |
| 537 | + testIntervalDayTimeRoundTrip("INTERVAL '0' SECOND", "INTERVAL '0 0:00:00' DAY TO SECOND"); |
| 538 | + testIntervalDayTimeRoundTrip("INTERVAL -'0' SECOND", "INTERVAL '0 0:00:00' DAY TO SECOND"); |
| 539 | + testIntervalDayTimeRoundTrip("INTERVAL '0.000' SECOND", "INTERVAL '0 0:00:00' DAY TO SECOND"); |
| 540 | + testIntervalDayTimeRoundTrip("INTERVAL '0.4' SECOND", "INTERVAL '0 0:00:00.400' DAY TO SECOND"); |
| 541 | + testIntervalDayTimeRoundTrip("INTERVAL '0.04' SECOND", "INTERVAL '0 0:00:00.040' DAY TO SECOND"); |
| 542 | + testIntervalDayTimeRoundTrip("INTERVAL '0.040' SECOND", "INTERVAL '0 0:00:00.040' DAY TO SECOND"); |
| 543 | + testIntervalDayTimeRoundTrip("INTERVAL '45' SECOND", "INTERVAL '0 0:00:45' DAY TO SECOND"); |
| 544 | + testIntervalDayTimeRoundTrip("INTERVAL -'45' SECOND", "INTERVAL -'0 0:00:45' DAY TO SECOND"); |
| 545 | + testIntervalDayTimeRoundTrip("INTERVAL '0.555' SECOND", "INTERVAL '0 0:00:00.555' DAY TO SECOND"); |
| 546 | + testIntervalDayTimeRoundTrip("INTERVAL '59.999' SECOND", "INTERVAL '0 0:00:59.999' DAY TO SECOND"); |
| 547 | + testIntervalDayTimeRoundTrip("INTERVAL '60' SECOND", "INTERVAL '0 0:01:00' DAY TO SECOND"); |
| 548 | + testIntervalDayTimeRoundTrip("INTERVAL '61' SECOND", "INTERVAL '0 0:01:01' DAY TO SECOND"); |
| 549 | + testIntervalDayTimeRoundTrip("INTERVAL '3661' SECOND", "INTERVAL '0 1:01:01' DAY TO SECOND"); |
| 550 | + testIntervalDayTimeRoundTrip("INTERVAL '90061' SECOND", "INTERVAL '1 1:01:01' DAY TO SECOND"); |
| 551 | + |
| 552 | + testIntervalDayTimeRoundTrip("INTERVAL '0' MINUTE", "INTERVAL '0 0:00:00' DAY TO SECOND"); |
| 553 | + testIntervalDayTimeRoundTrip("INTERVAL -'0' MINUTE", "INTERVAL '0 0:00:00' DAY TO SECOND"); |
| 554 | + testIntervalDayTimeRoundTrip("INTERVAL '25' MINUTE", "INTERVAL '0 0:25:00' DAY TO SECOND"); |
| 555 | + testIntervalDayTimeRoundTrip("INTERVAL -'25' MINUTE", "INTERVAL -'0 0:25:00' DAY TO SECOND"); |
| 556 | + testIntervalDayTimeRoundTrip("INTERVAL '15:30' MINUTE TO SECOND", "INTERVAL '0 0:15:30' DAY TO SECOND"); |
| 557 | + testIntervalDayTimeRoundTrip("INTERVAL '59:00.999' MINUTE TO SECOND", "INTERVAL '0 0:59:00.999' DAY TO SECOND"); |
| 558 | + testIntervalDayTimeRoundTrip("INTERVAL '60' MINUTE", "INTERVAL '0 1:00:00' DAY TO SECOND"); |
| 559 | + testIntervalDayTimeRoundTrip("INTERVAL '61' MINUTE", "INTERVAL '0 1:01:00' DAY TO SECOND"); |
| 560 | + testIntervalDayTimeRoundTrip("INTERVAL '1500' MINUTE", "INTERVAL '1 1:00:00' DAY TO SECOND"); |
| 561 | + testIntervalDayTimeRoundTrip("INTERVAL '1501' MINUTE", "INTERVAL '1 1:01:00' DAY TO SECOND"); |
| 562 | + |
| 563 | + testIntervalDayTimeRoundTrip("INTERVAL '0' HOUR", "INTERVAL '0 0:00:00' DAY TO SECOND"); |
| 564 | + testIntervalDayTimeRoundTrip("INTERVAL -'0' HOUR", "INTERVAL '0 0:00:00' DAY TO SECOND"); |
| 565 | + testIntervalDayTimeRoundTrip("INTERVAL '8' HOUR", "INTERVAL '0 8:00:00' DAY TO SECOND"); |
| 566 | + testIntervalDayTimeRoundTrip("INTERVAL -'8' HOUR", "INTERVAL -'0 8:00:00' DAY TO SECOND"); |
| 567 | + testIntervalDayTimeRoundTrip("INTERVAL '2:45' HOUR TO MINUTE", "INTERVAL '0 2:45:00' DAY TO SECOND"); |
| 568 | + testIntervalDayTimeRoundTrip("INTERVAL '2:00:45' HOUR TO SECOND", "INTERVAL '0 2:00:45' DAY TO SECOND"); |
| 569 | + testIntervalDayTimeRoundTrip("INTERVAL '1:30:45' HOUR TO SECOND", "INTERVAL '0 1:30:45' DAY TO SECOND"); |
| 570 | + testIntervalDayTimeRoundTrip("INTERVAL '1:00:00.999' HOUR TO SECOND", "INTERVAL '0 1:00:00.999' DAY TO SECOND"); |
| 571 | + testIntervalDayTimeRoundTrip("INTERVAL '24' HOUR", "INTERVAL '1 0:00:00' DAY TO SECOND"); |
| 572 | + testIntervalDayTimeRoundTrip("INTERVAL '25' HOUR", "INTERVAL '1 1:00:00' DAY TO SECOND"); |
| 573 | + testIntervalDayTimeRoundTrip("INTERVAL '17520' HOUR", "INTERVAL '730 0:00:00' DAY TO SECOND"); |
| 574 | + |
| 575 | + testIntervalDayTimeRoundTrip("INTERVAL '0' DAY", "INTERVAL '0 0:00:00' DAY TO SECOND"); |
| 576 | + testIntervalDayTimeRoundTrip("INTERVAL -'0' DAY", "INTERVAL '0 0:00:00' DAY TO SECOND"); |
| 577 | + testIntervalDayTimeRoundTrip("INTERVAL '340' DAY", "INTERVAL '340 0:00:00' DAY TO SECOND"); |
| 578 | + testIntervalDayTimeRoundTrip("INTERVAL -'340' DAY", "INTERVAL -'340 0:00:00' DAY TO SECOND"); |
| 579 | + testIntervalDayTimeRoundTrip("INTERVAL '2 6' DAY TO HOUR", "INTERVAL '2 6:00:00' DAY TO SECOND"); |
| 580 | + testIntervalDayTimeRoundTrip("INTERVAL '3 0:30' DAY TO MINUTE", "INTERVAL '3 0:30:00' DAY TO SECOND"); |
| 581 | + testIntervalDayTimeRoundTrip("INTERVAL '3 12:30' DAY TO MINUTE", "INTERVAL '3 12:30:00' DAY TO SECOND"); |
| 582 | + testIntervalDayTimeRoundTrip("INTERVAL '1 0:00:15' DAY TO SECOND", "INTERVAL '1 0:00:15' DAY TO SECOND"); |
| 583 | + testIntervalDayTimeRoundTrip("INTERVAL '1 4:20:15' DAY TO SECOND", "INTERVAL '1 4:20:15' DAY TO SECOND"); |
| 584 | + testIntervalDayTimeRoundTrip("INTERVAL '1 0:00:00.999' DAY TO SECOND", "INTERVAL '1 0:00:00.999' DAY TO SECOND"); |
| 585 | + testIntervalDayTimeRoundTrip("INTERVAL '1 23:59:59.999' DAY TO SECOND", "INTERVAL '1 23:59:59.999' DAY TO SECOND"); |
| 586 | + } |
| 587 | + |
| 588 | + private void testIntervalDayTimeRoundTrip(@Language("SQL") String input, @Language("SQL") String expectedFormatted) |
| 589 | + { |
| 590 | + Result evaluatedResult = assertions.expression(input).evaluate(); |
| 591 | + assertThat(evaluatedResult.type()).isEqualTo(IntervalDayTimeType.INTERVAL_DAY_TIME); |
| 592 | + SqlIntervalDayTime originalInterval = (SqlIntervalDayTime) evaluatedResult.value(); |
| 593 | + |
| 594 | + Duration duration = Duration.ofMillis(originalInterval.getMillis()); |
| 595 | + IntervalLiteral formattedLiteral = formatDayTimeInterval(duration); |
| 596 | + String formatted = ExpressionFormatter.formatExpression(formattedLiteral); |
| 597 | + assertThat(formatted).isEqualTo(expectedFormatted); |
| 598 | + |
| 599 | + Result reparsedResult = assertions.expression(formatted).evaluate(); |
| 600 | + SqlIntervalDayTime reparsedInterval = (SqlIntervalDayTime) reparsedResult.value(); |
| 601 | + assertThat(reparsedInterval).isEqualTo(originalInterval); |
| 602 | + } |
526 | 603 | } |
0 commit comments