diff --git a/google-cloud-spanner/pom.xml b/google-cloud-spanner/pom.xml index 1f33ef2d82..d1f2664141 100644 --- a/google-cloud-spanner/pom.xml +++ b/google-cloud-spanner/pom.xml @@ -364,11 +364,6 @@ ${graal-sdk.version} provided - - com.google.auto.value - auto-value - 1.10.4 - diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/GrpcStruct.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/GrpcStruct.java index ef4643bb63..bd78336699 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/GrpcStruct.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/GrpcStruct.java @@ -513,6 +513,7 @@ protected Date getDateInternal(int columnIndex) { return (Date) rowData.get(columnIndex); } + @Override protected Interval getIntervalInternal(int columnIndex) { ensureDecoded(columnIndex); return (Interval) rowData.get(columnIndex); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Interval.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Interval.java index c53524b3eb..4f5b5c57e4 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Interval.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Interval.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package com.google.cloud.spanner; -import com.google.auto.value.AutoValue; import com.google.errorprone.annotations.Immutable; import java.io.Serializable; import java.math.BigDecimal; @@ -25,9 +24,21 @@ import java.util.regex.Pattern; import org.jetbrains.annotations.NotNull; -@AutoValue +/** + * Represents the time duration as a combination of months, days and nanoseconds. Nanoseconds are + * broken into two components microseconds and nanoFractions, where nanoFractions can range from + * [-999, 999]. Internally, Spanner supports Interval value with the following range of individual + * fields: months: [-120000, 120000] days: [-3660000, 3660000] nanoseconds: [-316224000000000000000, + * 316224000000000000000] Interval value created outside the specified domain will return error when + * sent to Spanner backend. + */ @Immutable -public abstract class Interval implements Serializable { +public class Interval implements Serializable { + private final int months; + private final int days; + private final long microseconds; + private final short nanoFractions; + public static final long MONTHS_PER_YEAR = 12; public static final long DAYS_PER_MONTH = 30; public static final long HOURS_PER_DAY = 24; @@ -48,103 +59,110 @@ public abstract class Interval implements Serializable { BigInteger.valueOf(MICROS_PER_MINUTE * NANOS_PER_MICRO); public static final BigInteger NANOS_PER_HOUR = BigInteger.valueOf(MICROS_PER_HOUR * NANOS_PER_MICRO); + public static final Interval ZERO = Interval.builder().build(); + /** Regex to ISO8601 formatted interval. `P[n]Y[n]M[n]DT[n]H[n]M[n(.[fraction])]S` */ private static final Pattern INTERVAL_PATTERN = Pattern.compile( "^P(?!$)(-?\\d+Y)?(-?\\d+M)?(-?\\d+D)?(T(?=-?.?\\d)(-?\\d+H)?(-?\\d+M)?(-?((\\d+(\\.\\d{1,9})?)|(\\.\\d{1,9}))S)?)?$"); + private Interval(int months, int days, long microseconds, short nanoFractions) { + this.months = months; + this.days = days; + this.microseconds = microseconds; + this.nanoFractions = nanoFractions; + } + /** Returns the months component of the interval. */ - public abstract int months(); + public int getMonths() { + return months; + } /** Returns the days component of the interval. */ - public abstract int days(); + public int getDays() { + return days; + } /** Returns the microseconds component of the interval. */ - public abstract long micros(); + public long getMicroseconds() { + return microseconds; + } /** Returns the nanoFractions component of the interval. */ - public abstract short nanoFractions(); - - public static Builder builder() { - return new AutoValue_Interval.Builder(); + public short getNanoFractions() { + return nanoFractions; } - /** Returns the nanoseconds component of the interval. */ - public BigInteger nanos() { - return BigInteger.valueOf(micros()) + /** Returns the microseconds and nanoFraction of the Interval combined as nanoseconds. */ + public BigInteger getNanoseconds() { + return BigInteger.valueOf(getMicroseconds()) .multiply(BigInteger.valueOf(NANOS_PER_MICRO)) - .add(BigInteger.valueOf(nanoFractions())); + .add(BigInteger.valueOf(getNanoFractions())); + } + + public static Builder builder() { + return new Builder(); } - /** Returns the total microseconds represented by the interval. */ - public long getAsMicros() { - return months() * MICROS_PER_MONTH + days() * MICROS_PER_DAY + micros(); + /** + * Returns the total microseconds represented by the interval. It combines months, days and + * microseconds fields of the interval into microseconds. + */ + public long getAsMicroseconds() { + return Math.addExact( + Math.addExact( + Math.multiplyExact(getMonths(), MICROS_PER_MONTH), + Math.multiplyExact(getDays(), MICROS_PER_DAY)), + getMicroseconds()); } - /** Returns the total nanoseconds represented by the interval. */ - public BigInteger getAsNanos() { - return BigInteger.valueOf(getAsMicros()) + /** + * Returns the total nanoseconds represented by the interval. It combines months, days, + * microseconds and nanoFractions fields of the interval into nanoseconds. + */ + public BigInteger getAsNanoseconds() { + return BigInteger.valueOf(getAsMicroseconds()) .multiply(BigInteger.valueOf(NANOS_PER_MICRO)) - .add(BigInteger.valueOf(nanoFractions())); + .add(BigInteger.valueOf(getNanoFractions())); } /** Creates an interval with specified number of months. */ public static Interval ofMonths(int months) { - return builder().setMonths(months).setDays(0).setMicros(0).setNanoFractions((short) 0).build(); + return builder().setMonths(months).build(); } /** Creates an interval with specified number of days. */ public static Interval ofDays(int days) { - return builder().setMonths(0).setDays(days).setMicros(0).setNanoFractions((short) 0).build(); + return builder().setDays(days).build(); } /** Creates an interval with specified number of seconds. */ public static Interval ofSeconds(long seconds) { - return builder() - .setMonths(0) - .setDays(0) - .setMicros(seconds * MICROS_PER_SECOND) - .setNanoFractions((short) 0) - .build(); + return builder().setMicroseconds(seconds * MICROS_PER_SECOND).build(); } /** Creates an interval with specified number of milliseconds. */ public static Interval ofMilliseconds(long milliseconds) { - return builder() - .setMonths(0) - .setDays(0) - .setMicros(milliseconds * MICROS_PER_MILLI) - .setNanoFractions((short) 0) - .build(); + return builder().setMicroseconds(milliseconds * MICROS_PER_MILLI).build(); } /** Creates an interval with specified number of microseconds. */ - public static Interval ofMicros(long micros) { - return builder().months(0).days(0).micros(micros).nanoFractions((short) 0).build(); + public static Interval ofMicroseconds(long micros) { + return builder().setMicroseconds(micros).build(); } /** Creates an interval with specified number of nanoseconds. */ - public static Interval ofNanos(@NotNull BigInteger nanos) { + public static Interval ofNanoseconds(@NotNull BigInteger nanos) { BigInteger micros = nanos.divide(BigInteger.valueOf(NANOS_PER_MICRO)); BigInteger nanoFractions = nanos.subtract(micros.multiply(BigInteger.valueOf(NANOS_PER_MICRO))); long microsValue = micros.longValueExact(); short nanoFractionsValue = nanoFractions.shortValueExact(); - return builder() - .setMonths(0) - .setDays(0) - .setMicros(microsValue) - .setNanoFractions(nanoFractionsValue) - .build(); + return builder().setMicroseconds(microsValue).setNanoFractions(nanoFractionsValue).build(); } /** Creates an interval with specified number of months, days and microseconds. */ public static Interval fromMonthsDaysMicros(int months, int days, long micros) { - return builder() - .setMonths(months) - .setDays(days) - .setMicros(micros) - .setNanoFractions((short) 0) - .build(); + return builder().setMonths(months).setDays(days).setMicroseconds(micros).build(); } /** Creates an interval with specified number of months, days and nanoseconds. */ @@ -157,7 +175,7 @@ public static Interval fromMonthsDaysNanos(int months, int days, BigInteger nano return builder() .setMonths(months) .setDays(days) - .setMicros(micros) + .setMicroseconds(micros) .setNanoFractions(nanoFractions) .build(); } @@ -195,17 +213,21 @@ public static Interval parseFromString(String interval) { return Interval.builder() .setMonths(Math.toIntExact(totalMonths)) .setDays(Math.toIntExact(days)) - .setMicros(totalMicros.longValueExact()) + .setMicroseconds(totalMicros.longValueExact()) .setNanoFractions(nanoFractions.shortValueExact()) .build(); } /** Converts Interval to ISO8601 Duration Formatted String. */ - public String ToISO8601() { + public String toISO8601() { + if (this.equals(ZERO)) { + return "P0Y"; + } + StringBuilder result = new StringBuilder(); result.append("P"); - long months = this.months(); + long months = this.getMonths(); long years = months / MONTHS_PER_YEAR; months = months - years * MONTHS_PER_YEAR; @@ -217,11 +239,11 @@ public String ToISO8601() { result.append(String.format("%dM", months)); } - if (this.days() != 0) { - result.append(String.format("%dD", this.days())); + if (this.getDays() != 0) { + result.append(String.format("%dD", this.getDays())); } - BigInteger nanos = this.nanos(); + BigInteger nanos = this.getNanoseconds(); BigInteger zero = BigInteger.valueOf(0); if (nanos.compareTo(zero) != 0) { result.append("T"); @@ -245,16 +267,12 @@ public String ToISO8601() { } } - if (result.length() == 1) { - result.append("0Y"); - } - return result.toString(); } - /** Creates an interval which representing 0-duration. */ - public static Interval zeroInterval() { - return builder().setMonths(0).setDays(0).setMicros(0).setNanoFractions((short) 0).build(); + @Override + public String toString() { + return toISO8601(); } @Override @@ -264,43 +282,42 @@ public boolean equals(Object rhs) { } Interval anotherInterval = (Interval) rhs; - return months() == anotherInterval.months() - && days() == anotherInterval.days() - && nanos().equals(anotherInterval.nanos()); + return getMonths() == anotherInterval.getMonths() + && getDays() == anotherInterval.getDays() + && getNanoseconds().equals(anotherInterval.getNanoseconds()); } @Override public int hashCode() { int result = 17; - result = 31 * result + Long.valueOf(months()).hashCode(); - result = 31 * result + Long.valueOf(days()).hashCode(); - result = 31 * result + nanos().hashCode(); + result = 31 * result + Long.valueOf(getMonths()).hashCode(); + result = 31 * result + Long.valueOf(getDays()).hashCode(); + result = 31 * result + getNanoseconds().hashCode(); return result; } - @AutoValue.Builder - public abstract static class Builder { - abstract Builder months(int months); - - abstract Builder days(int days); + public static class Builder { + private int months = 0; + private int days = 0; + private long microseconds = 0; + private short nanoFractions = 0; - abstract Builder micros(long micros); - - abstract Builder nanoFractions(short nanoFractions); - - public Builder setMonths(int months) { - return months(months); + Builder setMonths(int months) { + this.months = months; + return this; } - public Builder setDays(int days) { - return days(days); + Builder setDays(int days) { + this.days = days; + return this; } - public Builder setMicros(long micros) { - return micros(micros); + Builder setMicroseconds(long microseconds) { + this.microseconds = microseconds; + return this; } - public Builder setNanoFractions(short nanoFractions) { + Builder setNanoFractions(short nanoFractions) { if (nanoFractions <= -NANOS_PER_MICRO || nanoFractions >= NANOS_PER_MICRO) { throw SpannerExceptionFactory.newSpannerException( ErrorCode.INVALID_ARGUMENT, @@ -308,9 +325,13 @@ public Builder setNanoFractions(short nanoFractions) { "NanoFractions must be between:[-%d, %d]", NANOS_PER_MICRO - 1, NANOS_PER_MICRO - 1)); } - return nanoFractions(nanoFractions); + + this.nanoFractions = nanoFractions; + return this; } - public abstract Interval build(); + public Interval build() { + return new Interval(months, days, microseconds, nanoFractions); + } } } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Value.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Value.java index 2d6371ea65..4b8d94f481 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Value.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Value.java @@ -52,6 +52,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; +import org.jetbrains.annotations.NotNull; /** * Represents a value to be consumed by the Cloud Spanner API. A value can be {@code NULL} or @@ -1853,12 +1854,17 @@ public Interval getInterval() { @Override void valueToString(StringBuilder b) { - b.append(value.ToISO8601()); + b.append(value.toISO8601()); } @Override com.google.protobuf.Value valueToProto() { - return com.google.protobuf.Value.newBuilder().setStringValue(value.ToISO8601()).build(); + return com.google.protobuf.Value.newBuilder().setStringValue(value.toISO8601()).build(); + } + + @Override + public @NotNull String getAsString() { + return isNull() ? NULL_STRING : value.toISO8601(); } } @@ -2878,12 +2884,12 @@ public List getIntervalArray() { @Override void appendElement(StringBuilder b, Interval element) { - b.append(element.ToISO8601()); + b.append(element.toISO8601()); } @Override - String elementToString(Interval element) { - return element.ToISO8601(); + String elementToString(@NotNull Interval element) { + return element.toISO8601(); } } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractStructReaderTypesTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractStructReaderTypesTest.java index 8a036065bd..7782893025 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractStructReaderTypesTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractStructReaderTypesTest.java @@ -445,7 +445,7 @@ public static Collection parameters() { "getIntervalListInternal", Arrays.asList( Interval.parseFromString("P1Y2M3DT4H5M6.78912345S"), - Interval.zeroInterval(), + Interval.ZERO, Interval.parseFromString("P-1Y2M-3DT-4H5M6.78912345S")), "getIntervalList", Collections.singletonList("getValue") diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/GceTestEnvConfig.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/GceTestEnvConfig.java index efb012ba8e..871cec439a 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/GceTestEnvConfig.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/GceTestEnvConfig.java @@ -58,8 +58,8 @@ public class GceTestEnvConfig implements TestEnvConfig { private final SpannerOptions options; public GceTestEnvConfig() { - String projectId = System.getProperty(GCE_PROJECT_ID, ""); - String serverUrl = System.getProperty(GCE_SERVER_URL, ""); + String projectId = "span-cloud-testing"; + String serverUrl = "https://staging-wrenchworks.sandbox.googleapis.com"; String credentialsFile = System.getProperty(GCE_CREDENTIALS_FILE, ""); double errorProbability = Double.parseDouble(System.getProperty(GCE_STREAM_BROKEN_PROBABILITY, "0.0")); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/GrpcResultSetTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/GrpcResultSetTest.java index bad39e33db..d74216c7c8 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/GrpcResultSetTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/GrpcResultSetTest.java @@ -555,9 +555,9 @@ public void serialization() { Value.date(null), Value.interval( Interval.builder() - .setDays(10) .setMonths(100) - .setMicros(1000) + .setDays(10) + .setMicroseconds(1000) .setNanoFractions((short) 10) .build()), Value.interval(null), @@ -584,7 +584,7 @@ public void serialization() { Date.fromYearMonthDay(2017, 4, 17), Date.fromYearMonthDay(2017, 5, 18))), Value.dateArray(null), Value.intervalArray( - ImmutableList.of(Interval.zeroInterval(), Interval.fromMonthsDaysMicros(10, 20, 30))), + ImmutableList.of(Interval.ZERO, Interval.fromMonthsDaysMicros(10, 20, 30))), Value.intervalArray(null), Value.struct(s(null, 30)), Value.struct(structType, null), diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/IntervalTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/IntervalTest.java index 242a1b27cf..2c8b3b237c 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/IntervalTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/IntervalTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,7 @@ package com.google.cloud.spanner; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; +import static org.junit.Assert.*; import java.math.BigInteger; import org.junit.Test; @@ -29,95 +28,95 @@ public class IntervalTest { @Test - public void testOfMonths() { + public void testOfGetMonths() { Interval interval = Interval.ofMonths(10); - assertEquals(10, interval.months()); - assertEquals(0, interval.days()); - assertEquals(0, interval.micros()); - assertEquals(0, interval.nanoFractions()); + assertEquals(10, interval.getMonths()); + assertEquals(0, interval.getDays()); + assertEquals(0, interval.getMicroseconds()); + assertEquals(0, interval.getNanoFractions()); } @Test - public void testOfDays() { + public void testOfGetDays() { Interval interval = Interval.ofDays(10); - assertEquals(0, interval.months()); - assertEquals(10, interval.days()); - assertEquals(0, interval.micros()); - assertEquals(0, interval.nanoFractions()); + assertEquals(0, interval.getMonths()); + assertEquals(10, interval.getDays()); + assertEquals(0, interval.getMicroseconds()); + assertEquals(0, interval.getNanoFractions()); } @Test public void testOfSeconds() { Interval interval = Interval.ofSeconds(10); - assertEquals(0, interval.months()); - assertEquals(0, interval.days()); - assertEquals(10 * Interval.MICROS_PER_SECOND, interval.micros()); - assertEquals(0, interval.nanoFractions()); + assertEquals(0, interval.getMonths()); + assertEquals(0, interval.getDays()); + assertEquals(10 * Interval.MICROS_PER_SECOND, interval.getMicroseconds()); + assertEquals(0, interval.getNanoFractions()); } @Test public void testOfMilliseconds() { Interval interval = Interval.ofMilliseconds(10); - assertEquals(0, interval.months()); - assertEquals(0, interval.days()); - assertEquals(10 * Interval.MICROS_PER_MILLI, interval.micros()); - assertEquals(0, interval.nanoFractions()); + assertEquals(0, interval.getMonths()); + assertEquals(0, interval.getDays()); + assertEquals(10 * Interval.MICROS_PER_MILLI, interval.getMicroseconds()); + assertEquals(0, interval.getNanoFractions()); } @Test - public void testOfMicros() { - Interval interval = Interval.ofMicros(10); - assertEquals(0, interval.months()); - assertEquals(0, interval.days()); - assertEquals(10, interval.micros()); - assertEquals(0, interval.nanoFractions()); + public void testOfGetMicroseconds() { + Interval interval = Interval.ofMicroseconds(10); + assertEquals(0, interval.getMonths()); + assertEquals(0, interval.getDays()); + assertEquals(10, interval.getMicroseconds()); + assertEquals(0, interval.getNanoFractions()); } @Test - public void testOfNanos() { - Interval interval = Interval.ofNanos(BigInteger.valueOf(10)); - assertEquals(0, interval.months()); - assertEquals(0, interval.days()); - assertEquals(0, interval.micros()); - assertEquals(10, interval.nanoFractions()); + public void testOfGetNanoseconds() { + Interval interval = Interval.ofNanoseconds(BigInteger.valueOf(10)); + assertEquals(0, interval.getMonths()); + assertEquals(0, interval.getDays()); + assertEquals(0, interval.getMicroseconds()); + assertEquals(10, interval.getNanoFractions()); } @Test - public void testFromMonthsDaysMicros() { + public void testFromGetMonthsGetDaysGetMicroseconds() { Interval interval = Interval.fromMonthsDaysMicros(10, 20, 30); - assertEquals(10, interval.months()); - assertEquals(20, interval.days()); - assertEquals(30, interval.micros()); - assertEquals(0, interval.nanoFractions()); + assertEquals(10, interval.getMonths()); + assertEquals(20, interval.getDays()); + assertEquals(30, interval.getMicroseconds()); + assertEquals(0, interval.getNanoFractions()); } @Test - public void testFromMonthsDaysNanos() { + public void testFromGetMonthsGetDaysGetNanoseconds() { Interval interval = Interval.fromMonthsDaysNanos(10, 20, BigInteger.valueOf(1030)); - assertEquals(10, interval.months()); - assertEquals(20, interval.days()); - assertEquals(1, interval.micros()); - assertEquals(30, interval.nanoFractions()); + assertEquals(10, interval.getMonths()); + assertEquals(20, interval.getDays()); + assertEquals(1, interval.getMicroseconds()); + assertEquals(30, interval.getNanoFractions()); Interval interval2 = Interval.fromMonthsDaysNanos(10, 20, BigInteger.valueOf(-1030)); - assertEquals(10, interval2.months()); - assertEquals(20, interval2.days()); - assertEquals(-1, interval2.micros()); - assertEquals(-30, interval2.nanoFractions()); + assertEquals(10, interval2.getMonths()); + assertEquals(20, interval2.getDays()); + assertEquals(-1, interval2.getMicroseconds()); + assertEquals(-30, interval2.getNanoFractions()); } @Test public void testParseFromString() { Interval interval = Interval.parseFromString("P1Y2M3DT4H5M6.789000123S"); - assertEquals(14, interval.months()); - assertEquals(3, interval.days()); + assertEquals(14, interval.getMonths()); + assertEquals(3, interval.getDays()); assertEquals( 4 * Interval.MICROS_PER_HOUR + 5 * Interval.MICROS_PER_MINUTE + 6 * Interval.MICROS_PER_SECOND + 789000, - interval.micros()); - assertEquals(123, interval.nanoFractions()); + interval.getMicroseconds()); + assertEquals(123, interval.getNanoFractions()); } @Test @@ -142,17 +141,11 @@ public void testToISO8601() { + 5 * Interval.MICROS_PER_MINUTE + 6 * Interval.MICROS_PER_SECOND + 789000); - assertEquals("P1Y2M3DT4H5M6.789S", interval.ToISO8601()); + assertEquals("P1Y2M3DT4H5M6.789S", interval.toISO8601()); } @Test - public void testToISO8601_ZeroInterval() { - Interval interval = Interval.zeroInterval(); - assertEquals("P0Y", interval.ToISO8601()); - } - - @Test - public void testToISO8601WithNanos() { + public void testToISO8601WithGetNanoseconds() { Interval interval = Interval.fromMonthsDaysNanos( 14, @@ -162,13 +155,13 @@ public void testToISO8601WithNanos() { .add(BigInteger.valueOf(5).multiply(Interval.NANOS_PER_MINUTE)) .add(BigInteger.valueOf(6).multiply(Interval.NANOS_PER_SECOND)) .add(BigInteger.valueOf(789123456))); - assertEquals("P1Y2M3DT4H5M6.789123456S", interval.ToISO8601()); + assertEquals("P1Y2M3DT4H5M6.789123456S", interval.toISO8601()); } @Test - public void testToISO8601WithOnlyNanos() { - Interval interval = Interval.ofNanos(BigInteger.valueOf(123456789)); - assertEquals("PT0.123456789S", interval.ToISO8601()); + public void testToISO8601WithOnlyGetNanoseconds() { + Interval interval = Interval.ofNanoseconds(BigInteger.valueOf(123456789)); + assertEquals("PT0.123456789S", interval.toISO8601()); } @Test @@ -179,87 +172,127 @@ public void testEquals() { } @Test - public void testHashCode() { + public void testHashCode_equalObjects() { Interval interval1 = Interval.fromMonthsDaysMicros(10, 20, 30); Interval interval2 = Interval.fromMonthsDaysMicros(10, 20, 30); assertEquals(interval1.hashCode(), interval2.hashCode()); } @Test - public void testGetAsMicros() { + public void testHashCode_differentMonths() { + Interval interval1 = Interval.fromMonthsDaysMicros(10, 20, 30); + Interval interval2 = Interval.fromMonthsDaysMicros(11, 20, 30); + assertNotEquals(interval1.hashCode(), interval2.hashCode()); + } + + @Test + public void testHashCode_differentDays() { + Interval interval1 = Interval.fromMonthsDaysMicros(10, 20, 30); + Interval interval2 = Interval.fromMonthsDaysMicros(10, 21, 30); + assertNotEquals(interval1.hashCode(), interval2.hashCode()); + } + + @Test + public void testHashCode_differentMicros() { + Interval interval1 = Interval.fromMonthsDaysMicros(10, 20, 30); + Interval interval2 = Interval.fromMonthsDaysMicros(10, 20, 31); + assertNotEquals(interval1.hashCode(), interval2.hashCode()); + } + + @Test + public void testHashCode_differentNanoFractions() { + Interval interval1 = + Interval.builder() + .setMonths(10) + .setDays(20) + .setMicroseconds(30) + .setNanoFractions((short) 10) + .build(); + Interval interval2 = + Interval.builder() + .setMonths(10) + .setDays(20) + .setMicroseconds(30) + .setNanoFractions((short) -10) + .build(); + assertNotEquals(interval1.hashCode(), interval2.hashCode()); + } + + @Test + public void testGetAsGetMicroseconds() { Interval interval = Interval.fromMonthsDaysMicros(10, 20, 30); long expectedMicros = 10 * Interval.MICROS_PER_MONTH + 20 * Interval.MICROS_PER_DAY + 30; - assertEquals(expectedMicros, interval.getAsMicros()); + assertEquals(expectedMicros, interval.getAsMicroseconds()); } @Test - public void testGetAsNanos() { + public void testGetAsGetNanoseconds() { Interval interval = Interval.fromMonthsDaysNanos(10, 20, BigInteger.valueOf(30)); BigInteger expectedNanos = BigInteger.valueOf(10 * Interval.MICROS_PER_MONTH + 20 * Interval.MICROS_PER_DAY) .multiply(BigInteger.valueOf(Interval.NANOS_PER_MICRO)) .add(BigInteger.valueOf(30)); - assertEquals(expectedNanos, interval.getAsNanos()); + assertEquals(expectedNanos, interval.getAsNanoseconds()); } @Test - public void testNanos() { + public void testGetNanoseconds() { Interval interval = Interval.fromMonthsDaysNanos( 10, 20, BigInteger.valueOf(30 * Interval.NANOS_PER_MICRO + 40)); - assertEquals(30 * Interval.NANOS_PER_MICRO + 40, interval.nanos().longValueExact()); + assertEquals(30 * Interval.NANOS_PER_MICRO + 40, interval.getNanoseconds().longValueExact()); } @Test - public void testParseFromStringWithNanos() { + public void testParseFromStringWithGetNanoseconds() { Interval interval = Interval.parseFromString("P1Y2M3DT4H5M6.789123456S"); - assertEquals(14, interval.months()); - assertEquals(3, interval.days()); + assertEquals(14, interval.getMonths()); + assertEquals(3, interval.getDays()); assertEquals( 4 * Interval.MICROS_PER_HOUR + 5 * Interval.MICROS_PER_MINUTE + 6 * Interval.MICROS_PER_SECOND + 789123, - interval.micros()); - assertEquals(456, interval.nanoFractions()); + interval.getMicroseconds()); + assertEquals(456, interval.getNanoFractions()); } @Test - public void testParseFromStringWithOnlyNanos() { + public void testParseFromStringWithOnlyGetNanoseconds() { Interval interval = Interval.parseFromString("PT.123456789S"); - assertEquals(0, interval.months()); - assertEquals(0, interval.days()); - assertEquals(123456, interval.micros()); - assertEquals(789, interval.nanoFractions()); + assertEquals(0, interval.getMonths()); + assertEquals(0, interval.getDays()); + assertEquals(123456, interval.getMicroseconds()); + assertEquals(789, interval.getNanoFractions()); } @Test public void testParseFromStringWithZeroes() { Interval interval = Interval.parseFromString("P0Y0M0DT0H0M0.0S"); - assertEquals(0, interval.months()); - assertEquals(0, interval.days()); - assertEquals(0, interval.micros()); - assertEquals(0, interval.nanoFractions()); + assertEquals(0, interval.getMonths()); + assertEquals(0, interval.getDays()); + assertEquals(0, interval.getMicroseconds()); + assertEquals(0, interval.getNanoFractions()); } @Test public void testToISO8601WithZeroes() { - Interval interval = Interval.zeroInterval(); - assertEquals("P0Y", interval.ToISO8601()); + Interval interval = Interval.ZERO; + assertEquals("P0Y", interval.toISO8601()); } @Test public void testParseFromStringWithNegativeValues() { Interval interval = Interval.parseFromString("P-1Y-2M-3DT-4H-5M-6.789S"); - assertEquals(-14, interval.months()); - assertEquals(-3, interval.days()); + assertEquals(-14, interval.getMonths()); + assertEquals(-3, interval.getDays()); assertEquals( -4 * Interval.MICROS_PER_HOUR - 5 * Interval.MICROS_PER_MINUTE - 6 * Interval.MICROS_PER_SECOND - 789000, - interval.micros()); - assertEquals(0, interval.nanoFractions()); + interval.getMicroseconds()); + assertEquals(0, interval.getNanoFractions()); } @Test @@ -272,11 +305,11 @@ public void testToISO8601WithNegativeValues() { - 5 * Interval.MICROS_PER_MINUTE - 6 * Interval.MICROS_PER_SECOND - 789000); - assertEquals("P-1Y-2M-3DT-4H-5M-6.789S", interval.ToISO8601()); + assertEquals("P-1Y-2M-3DT-4H-5M-6.789S", interval.toISO8601()); } @Test - public void testEqualsWithNanos() { + public void testEqualsWithGetNanoseconds() { Interval interval1 = Interval.fromMonthsDaysNanos(10, 20, BigInteger.valueOf(30)); Interval interval2 = Interval.fromMonthsDaysNanos(10, 20, BigInteger.valueOf(30)); assertEquals(interval1, interval2); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/RandomResultSetGenerator.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/RandomResultSetGenerator.java index 251b1a555e..e2e4cb4265 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/RandomResultSetGenerator.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/RandomResultSetGenerator.java @@ -150,12 +150,12 @@ private void setRandomValue(Value.Builder builder, Type type) { case INTERVAL: Interval interval = Interval.builder() - .setMonths(10) - .setDays(45) - .setMicros(-89) - .setNanoFractions((short) 45) + .setMonths(random.nextInt(200) - 100) + .setDays(random.nextInt(200) - 100) + .setMicroseconds(random.nextInt(20000000) - 10000000) + .setNanoFractions((short) (random.nextInt(200) - 100)) .build(); - builder.setStringValue(interval.ToISO8601()); + builder.setStringValue(interval.toISO8601()); break; case FLOAT64: builder.setNumberValue(random.nextDouble()); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ResultSetsTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ResultSetsTest.java index 40523a1c8d..235ce4d66b 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ResultSetsTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ResultSetsTest.java @@ -93,9 +93,7 @@ public void resultSetIteration() { Date[] dateArray = { Date.fromYearMonthDay(1, 2, 3), Date.fromYearMonthDay(4, 5, 6), Date.fromYearMonthDay(7, 8, 9) }; - Interval[] intervalArray = { - Interval.zeroInterval(), Interval.parseFromString("P1Y2M3DT-5H-7M8.9675S") - }; + Interval[] intervalArray = {Interval.ZERO, Interval.parseFromString("P1Y2M3DT-5H-7M8.9675S")}; String[] stringArray = {"abc", "def", "ghi"}; String[] jsonArray = {"{}", "{\"color\":\"red\",\"value\":\"#f00\"}", "[]"}; AbstractMessage[] protoMessageArray = { diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueBinderTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueBinderTest.java index 832b3e17d8..944099f1e7 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueBinderTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueBinderTest.java @@ -332,7 +332,7 @@ public static Date defaultDate() { } public static Interval defaultInterval() { - return Interval.zeroInterval(); + return Interval.ZERO; } public static boolean[] defaultBooleanArray() { @@ -397,14 +397,14 @@ public static Interval[] defaultIntervalArray() { Interval.builder() .setMonths(-10) .setDays(-100) - .setMicros(-1000) + .setMicroseconds(-1000) .setNanoFractions((short) 100) .build(), - Interval.zeroInterval(), + Interval.ZERO, Interval.builder() .setMonths(10) .setDays(100) - .setMicros(1000) + .setMicroseconds(1000) .setNanoFractions((short) 100) .build() }; @@ -415,14 +415,14 @@ public static Iterable defaultIntervalIterable() { Interval.builder() .setMonths(-10) .setDays(-100) - .setMicros(-1000) + .setMicroseconds(-1000) .setNanoFractions((short) 100) .build(), - Interval.zeroInterval(), + Interval.ZERO, Interval.builder() .setMonths(10) .setDays(100) - .setMicros(1000) + .setMicroseconds(1000) .setNanoFractions((short) 100) .build()); } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueTest.java index cef76b2998..e752a03889 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueTest.java @@ -1392,9 +1392,9 @@ public void intervalArray() { assertThat(v.isNull()).isFalse(); assertThat(v.getIntervalArray()).containsExactly(interval1, null, interval2).inOrder(); assertThat(v.toString()) - .isEqualTo("[" + interval1.ToISO8601() + ",NULL," + interval2.ToISO8601() + "]"); + .isEqualTo("[" + interval1.toISO8601() + ",NULL," + interval2.toISO8601() + "]"); assertEquals( - String.format("[%s,NULL,%s]", interval1.ToISO8601(), interval2.ToISO8601()), + String.format("[%s,NULL,%s]", interval1.toISO8601(), interval2.toISO8601()), v.getAsString()); } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ChecksumResultSetTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ChecksumResultSetTest.java index 0ee7713b44..4c10115397 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ChecksumResultSetTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ChecksumResultSetTest.java @@ -25,11 +25,19 @@ import com.google.cloud.ByteArray; import com.google.cloud.Date; import com.google.cloud.Timestamp; -import com.google.cloud.spanner.*; +import com.google.cloud.spanner.AbortedDueToConcurrentModificationException; +import com.google.cloud.spanner.AbortedException; +import com.google.cloud.spanner.Interval; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.ResultSets; import com.google.cloud.spanner.SingerProto.Genre; import com.google.cloud.spanner.SingerProto.SingerInfo; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Struct.Builder; +import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.Value; import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.common.collect.ImmutableList; import java.math.BigDecimal; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITQueryTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITQueryTest.java index b5d5ceb2f6..908a680d0b 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITQueryTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITQueryTest.java @@ -30,9 +30,23 @@ import com.google.cloud.ByteArray; import com.google.cloud.Date; import com.google.cloud.Timestamp; -import com.google.cloud.spanner.*; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.IntegrationTestEnv; +import com.google.cloud.spanner.Interval; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.Value; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.base.Joiner;