Skip to content

Commit

Permalink
Added integration test for typed query parameter and fixed Interval p…
Browse files Browse the repository at this point in the history
…arsing regex
  • Loading branch information
Sagar Agarwal committed Nov 7, 2024
1 parent f16ae42 commit bea6426
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public abstract class Interval implements Serializable {

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})?S)?)?$");
"^P(?!$)(-?\\d+Y)?(-?\\d+M)?(-?\\d+D)?(T(?=-?.?\\d)(-?\\d+H)?(-?\\d+M)?(-?((\\d+(\\.\\d{1,9})?)|(\\.\\d{1,9}))S)?)?$");

/** Returns the months component of the interval. */
public abstract int months();
Expand Down Expand Up @@ -154,8 +154,6 @@ public static Interval fromMonthsDaysNanos(int months, int days, BigInteger nano
(nanos.subtract(BigInteger.valueOf(micros).multiply(BigInteger.valueOf(NANOS_PER_MICRO))))
.shortValue();

System.out.println("Micros: " + micros + " Nanos: " + nanoFractions);

return builder()
.setMonths(months)
.setDays(days)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@
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.ErrorCode;
import com.google.cloud.spanner.Interval;
import com.google.cloud.spanner.ProtobufResultSet;
import com.google.cloud.spanner.ResultSet;
import com.google.cloud.spanner.SpannerException;
import com.google.cloud.spanner.SpannerExceptionFactory;
import com.google.cloud.spanner.Struct;
import com.google.cloud.spanner.Type;
import com.google.cloud.spanner.Value;
import com.google.common.base.Preconditions;
import com.google.protobuf.AbstractMessage;
import com.google.protobuf.ProtocolMessageEnum;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1855,7 +1855,7 @@ public void testValueToProto() {
.addAllValues(
Arrays.asList(
com.google.protobuf.Value.newBuilder()
.setStringValue("P1Y2M3DT5H6M2.456787800S")
.setStringValue("P1Y2M3DT5H6M2.4567878S")
.build(),
com.google.protobuf.Value.newBuilder()
.setNullValue(NullValue.NULL_VALUE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package com.google.cloud.spanner.it;

import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
Expand All @@ -30,6 +29,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.junit.AfterClass;
Expand Down Expand Up @@ -63,32 +63,30 @@ public static List<DialectTestParameter> data() {
new String[] {
"CREATE TABLE IntervalTable (\n"
+ " key STRING(MAX),\n"
+ " slo_days INT64,\n"
+ " update_time TIMESTAMP,\n"
+ " expiry_days INT64 AS (EXTRACT(DAY FROM make_interval(day => GREATEST(LEAST(slo_days, 365), 1)))),\n"
+ " interval_array_len bigint AS (ARRAY_LENGTH(ARRAY<INTERVAL>[INTERVAL '1-2 3 4:5:6' YEAR TO SECOND]))\n"
+ ") PRIMARY KEY (key);"
+ " create_time TIMESTAMP,\n"
+ " expiry_time TIMESTAMP,\n"
+ " expiry_within_month bool AS (expiry_time - create_time < INTERVAL 30 DAY),\n"
+ " interval_array_len INT64 AS (ARRAY_LENGTH(ARRAY<INTERVAL>[INTERVAL '1-2 3 4:5:6' YEAR TO SECOND]))\n"
+ ") PRIMARY KEY (key)"
};

private static final String[] POSTGRESQL_SCHEMA =
new String[] {
"CREATE TABLE IntervalTable (\n"
+ " key text primary key,\n"
+ " slo_days bigint,\n"
+ " update_time timestamptz,\n"
+ " expiry_days bigint GENERATED ALWAYS AS (EXTRACT(DAY FROM make_interval(days =>GREATEST(LEAST(slo_days, 365), 1)))) STORED,\n"
+ " create_time timestamptz,\n"
+ " expiry_time timestamptz,\n"
+ " expiry_within_month bool GENERATED ALWAYS AS (INTERVAL '1' DAY < INTERVAL '30' DAY) STORED,\n"
+ " interval_array_len bigint GENERATED ALWAYS AS (ARRAY_LENGTH(ARRAY[INTERVAL '1-2 3 4:5:6'], 1)) STORED\n"
+ ");"
+ ")"
};

private static DatabaseClient client;

private static boolean isUsingCloudDevel() {
String jobType = System.getenv("JOB_TYPE");

// Assumes that the jobType contains the string "cloud-devel" to signal that
// the environment is cloud-devel.
return !isNullOrEmpty(jobType) && jobType.contains("cloud-devel");
return Objects.equals(
System.getProperty("spanner.gce.config.server_url"),
"https://staging-wrenchworks.sandbox.googleapis.com");
}

@BeforeClass
Expand Down Expand Up @@ -131,7 +129,8 @@ private Timestamp write(Mutation m) {
}

private Mutation.WriteBuilder baseInsert() {
return Mutation.newInsertOrUpdateBuilder("T").set("Key").to(lastKey = uniqueString());
return Mutation.
newInsertOrUpdateBuilder("IntervalTable").set("Key").to(lastKey = uniqueString());
}

private Struct readRow(String table, String key, String... columns) {
Expand All @@ -141,23 +140,26 @@ private Struct readRow(String table, String key, String... columns) {
}

private Struct readLastRow(String... columns) {
return readRow("T", lastKey, columns);
return readRow("IntervalTable", lastKey, columns);
}

@Test
public void writeToTableWithIntervalExpressions() {
write(
baseInsert()
.set("slo_days")
.to(5)
.set("update_time")
.to(Timestamp.ofTimeMicroseconds(12345678L))
.set("create_time")
.to(Timestamp.parseTimestamp("2004-11-30T04:53:54Z"))
.set("expiry_time")
.to(Timestamp.parseTimestamp("2004-12-15T04:53:54Z"))
.build());
Struct row = readLastRow("expiryDays", "interval_array_len");
assertFalse(row.isNull(0));
assertEquals(5, row.getLong(0));
assertFalse(row.isNull(1));
assertEquals(1, row.getLong(1));
try (ResultSet resultSet =
client
.singleUse()
.executeQuery(Statement.of("SELECT expiry_within_month, interval_array_len FROM IntervalTable WHERE key='"+lastKey+"'"))) {
assertTrue(resultSet.next());
assertTrue(resultSet.getBoolean(0));
assertEquals(1, resultSet.getLong(1));
}
}

@Test
Expand All @@ -167,7 +169,39 @@ public void queryInterval() {
.singleUse()
.executeQuery(Statement.of("SELECT INTERVAL '1' DAY + INTERVAL '1' MONTH AS Col1"))) {
assertTrue(resultSet.next());
assertTrue(resultSet.getInterval(0).equals(Interval.fromMonthsDaysMicros(1, 1, 0)));
assertEquals(resultSet.getInterval(0), Interval.fromMonthsDaysMicros(1, 1, 0));
}
}

@Test
public void queryWithIntervalParam() {
write(
baseInsert()
.set("create_time")
.to(Timestamp.parseTimestamp("2004-08-30T04:53:54Z"))
.set("expiry_time")
.to(Timestamp.parseTimestamp("2004-12-15T04:53:54Z"))
.build());

String query;
if (dialect.dialect == Dialect.POSTGRESQL) {
query =
"SELECT COUNT(*) FROM IntervalTable WHERE create_time < TIMESTAMPTZ '2004-11-30T10:23:54+0530' - $1";
} else {
query =
"SELECT COUNT(*) FROM IntervalTable WHERE create_time < TIMESTAMP('2004-11-30T10:23:54+0530') - @p1";
}

try (ResultSet resultSet =
client
.singleUse()
.executeQuery(
Statement.newBuilder(query)
.bind("p1")
.to(Value.interval(Interval.ofDays(30)))
.build())) {
assertTrue(resultSet.next());
assertEquals(resultSet.getLong(0), 1L);
}
}

Expand Down Expand Up @@ -203,12 +237,12 @@ public void queryIntervalArray() {
"SELECT ARRAY[CAST('P1Y2M3DT4H5M6.789123S' AS INTERVAL), null, CAST('P-1Y-2M-3DT-4H-5M-6.789123S' AS INTERVAL)] AS Col1";
try (ResultSet resultSet = client.singleUse().executeQuery(Statement.of(query))) {
assertTrue(resultSet.next());
assertTrue(
assertEquals(
Arrays.asList(
Interval.parseFromString("P1Y2M3DT4H5M6.789123S"),
null,
Interval.parseFromString("P-1Y-2M-3DT-4H-5M-6.789123S"))
.equals(resultSet.getIntervalList(0)));
Interval.parseFromString("P1Y2M3DT4H5M6.789123S"),
null,
Interval.parseFromString("P-1Y-2M-3DT-4H-5M-6.789123S")),
resultSet.getIntervalList(0));
}
}
}

0 comments on commit bea6426

Please sign in to comment.