Skip to content

Commit b136a58

Browse files
author
Sagar Agarwal
committed
Added integration test for typed query parameter and fixed Interval parsing regex
1 parent f16ae42 commit b136a58

File tree

5 files changed

+84
-38
lines changed

5 files changed

+84
-38
lines changed

google-cloud-spanner/src/main/java/com/google/cloud/spanner/Interval.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public abstract class Interval implements Serializable {
5151

5252
private static final Pattern INTERVAL_PATTERN =
5353
Pattern.compile(
54-
"^P(?!$)(-?\\d+Y)?(-?\\d+M)?(-?\\d+D)?(T(?=-?\\d)(-?\\d+H)?(-?\\d+M)?(-?\\d+(\\.\\d{1,9})?S)?)?$");
54+
"^P(?!$)(-?\\d+Y)?(-?\\d+M)?(-?\\d+D)?(T(?=-?.?\\d)(-?\\d+H)?(-?\\d+M)?(-?((\\d+(\\.\\d{1,9})?)|(\\.\\d{1,9}))S)?)?$");
5555

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

157-
System.out.println("Micros: " + micros + " Nanos: " + nanoFractions);
158-
159157
return builder()
160158
.setMonths(months)
161159
.setDays(days)

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DirectExecuteResultSet.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@
1919
import com.google.cloud.ByteArray;
2020
import com.google.cloud.Date;
2121
import com.google.cloud.Timestamp;
22-
import com.google.cloud.spanner.*;
22+
import com.google.cloud.spanner.ProtobufResultSet;
23+
import com.google.cloud.spanner.ResultSet;
24+
import com.google.cloud.spanner.SpannerException;
25+
import com.google.cloud.spanner.Struct;
26+
import com.google.cloud.spanner.Type;
27+
import com.google.cloud.spanner.Value;
28+
import com.google.cloud.spanner.Interval;
2329
import com.google.common.base.Preconditions;
2430
import com.google.protobuf.AbstractMessage;
2531
import com.google.protobuf.ProtocolMessageEnum;

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ReplaceableForwardingResultSet.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,15 @@
1919
import com.google.cloud.ByteArray;
2020
import com.google.cloud.Date;
2121
import com.google.cloud.Timestamp;
22-
import com.google.cloud.spanner.*;
22+
import com.google.cloud.spanner.ErrorCode;
23+
import com.google.cloud.spanner.Interval;
24+
import com.google.cloud.spanner.ProtobufResultSet;
25+
import com.google.cloud.spanner.ResultSet;
26+
import com.google.cloud.spanner.SpannerException;
27+
import com.google.cloud.spanner.SpannerExceptionFactory;
28+
import com.google.cloud.spanner.Struct;
29+
import com.google.cloud.spanner.Type;
30+
import com.google.cloud.spanner.Value;
2331
import com.google.common.base.Preconditions;
2432
import com.google.protobuf.AbstractMessage;
2533
import com.google.protobuf.ProtocolMessageEnum;

google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1855,7 +1855,7 @@ public void testValueToProto() {
18551855
.addAllValues(
18561856
Arrays.asList(
18571857
com.google.protobuf.Value.newBuilder()
1858-
.setStringValue("P1Y2M3DT5H6M2.456787800S")
1858+
.setStringValue("P1Y2M3DT5H6M2.4567878S")
18591859
.build(),
18601860
com.google.protobuf.Value.newBuilder()
18611861
.setNullValue(NullValue.NULL_VALUE)

google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITIntervalTest.java

Lines changed: 66 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.google.cloud.spanner.it;
1818

1919
import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator;
20-
import static com.google.common.base.Strings.isNullOrEmpty;
2120
import static org.junit.Assert.assertEquals;
2221
import static org.junit.Assert.assertFalse;
2322
import static org.junit.Assert.assertTrue;
@@ -30,6 +29,7 @@
3029
import java.util.Arrays;
3130
import java.util.Collections;
3231
import java.util.List;
32+
import java.util.Objects;
3333
import java.util.concurrent.ExecutionException;
3434
import java.util.concurrent.TimeoutException;
3535
import org.junit.AfterClass;
@@ -63,32 +63,30 @@ public static List<DialectTestParameter> data() {
6363
new String[] {
6464
"CREATE TABLE IntervalTable (\n"
6565
+ " key STRING(MAX),\n"
66-
+ " slo_days INT64,\n"
67-
+ " update_time TIMESTAMP,\n"
68-
+ " expiry_days INT64 AS (EXTRACT(DAY FROM make_interval(day => GREATEST(LEAST(slo_days, 365), 1)))),\n"
69-
+ " interval_array_len bigint AS (ARRAY_LENGTH(ARRAY<INTERVAL>[INTERVAL '1-2 3 4:5:6' YEAR TO SECOND]))\n"
70-
+ ") PRIMARY KEY (key);"
66+
+ " create_time TIMESTAMP,\n"
67+
+ " expiry_time TIMESTAMP,\n"
68+
+ " expiry_within_month bool AS (expiry_time - create_time < INTERVAL 30 DAY),\n"
69+
+ " interval_array_len INT64 AS (ARRAY_LENGTH(ARRAY<INTERVAL>[INTERVAL '1-2 3 4:5:6' YEAR TO SECOND]))\n"
70+
+ ") PRIMARY KEY (key)"
7171
};
7272

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

8484
private static DatabaseClient client;
8585

8686
private static boolean isUsingCloudDevel() {
87-
String jobType = System.getenv("JOB_TYPE");
88-
89-
// Assumes that the jobType contains the string "cloud-devel" to signal that
90-
// the environment is cloud-devel.
91-
return !isNullOrEmpty(jobType) && jobType.contains("cloud-devel");
87+
return Objects.equals(
88+
System.getProperty("spanner.gce.config.server_url"),
89+
"https://staging-wrenchworks.sandbox.googleapis.com");
9290
}
9391

9492
@BeforeClass
@@ -131,7 +129,8 @@ private Timestamp write(Mutation m) {
131129
}
132130

133131
private Mutation.WriteBuilder baseInsert() {
134-
return Mutation.newInsertOrUpdateBuilder("T").set("Key").to(lastKey = uniqueString());
132+
return Mutation.
133+
newInsertOrUpdateBuilder("IntervalTable").set("Key").to(lastKey = uniqueString());
135134
}
136135

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

143142
private Struct readLastRow(String... columns) {
144-
return readRow("T", lastKey, columns);
143+
return readRow("IntervalTable", lastKey, columns);
145144
}
146145

147146
@Test
148147
public void writeToTableWithIntervalExpressions() {
149148
write(
150149
baseInsert()
151-
.set("slo_days")
152-
.to(5)
153-
.set("update_time")
154-
.to(Timestamp.ofTimeMicroseconds(12345678L))
150+
.set("create_time")
151+
.to(Timestamp.parseTimestamp("2004-11-30T04:53:54Z"))
152+
.set("expiry_time")
153+
.to(Timestamp.parseTimestamp("2004-12-15T04:53:54Z"))
155154
.build());
156-
Struct row = readLastRow("expiryDays", "interval_array_len");
157-
assertFalse(row.isNull(0));
158-
assertEquals(5, row.getLong(0));
159-
assertFalse(row.isNull(1));
160-
assertEquals(1, row.getLong(1));
155+
try (ResultSet resultSet =
156+
client
157+
.singleUse()
158+
.executeQuery(Statement.of("SELECT expiry_within_month, interval_array_len FROM IntervalTable WHERE key='"+lastKey+"'"))) {
159+
assertTrue(resultSet.next());
160+
assertTrue(resultSet.getBoolean(0));
161+
assertEquals(1, resultSet.getLong(1));
162+
}
161163
}
162164

163165
@Test
@@ -167,7 +169,39 @@ public void queryInterval() {
167169
.singleUse()
168170
.executeQuery(Statement.of("SELECT INTERVAL '1' DAY + INTERVAL '1' MONTH AS Col1"))) {
169171
assertTrue(resultSet.next());
170-
assertTrue(resultSet.getInterval(0).equals(Interval.fromMonthsDaysMicros(1, 1, 0)));
172+
assertEquals(resultSet.getInterval(0), Interval.fromMonthsDaysMicros(1, 1, 0));
173+
}
174+
}
175+
176+
@Test
177+
public void queryWithIntervalParam() {
178+
write(
179+
baseInsert()
180+
.set("create_time")
181+
.to(Timestamp.parseTimestamp("2004-08-30T04:53:54Z"))
182+
.set("expiry_time")
183+
.to(Timestamp.parseTimestamp("2004-12-15T04:53:54Z"))
184+
.build());
185+
186+
String query;
187+
if (dialect.dialect == Dialect.POSTGRESQL) {
188+
query =
189+
"SELECT COUNT(*) FROM IntervalTable WHERE create_time < TIMESTAMPTZ '2004-11-30T10:23:54+0530' - $1";
190+
} else {
191+
query =
192+
"SELECT COUNT(*) FROM IntervalTable WHERE create_time < TIMESTAMP('2004-11-30T10:23:54+0530') - @p1";
193+
}
194+
195+
try (ResultSet resultSet =
196+
client
197+
.singleUse()
198+
.executeQuery(
199+
Statement.newBuilder(query)
200+
.bind("p1")
201+
.to(Value.interval(Interval.ofDays(30)))
202+
.build())) {
203+
assertTrue(resultSet.next());
204+
assertEquals(resultSet.getLong(0), 1L);
171205
}
172206
}
173207

@@ -203,12 +237,12 @@ public void queryIntervalArray() {
203237
"SELECT ARRAY[CAST('P1Y2M3DT4H5M6.789123S' AS INTERVAL), null, CAST('P-1Y-2M-3DT-4H-5M-6.789123S' AS INTERVAL)] AS Col1";
204238
try (ResultSet resultSet = client.singleUse().executeQuery(Statement.of(query))) {
205239
assertTrue(resultSet.next());
206-
assertTrue(
240+
assertEquals(
207241
Arrays.asList(
208-
Interval.parseFromString("P1Y2M3DT4H5M6.789123S"),
209-
null,
210-
Interval.parseFromString("P-1Y-2M-3DT-4H-5M-6.789123S"))
211-
.equals(resultSet.getIntervalList(0)));
242+
Interval.parseFromString("P1Y2M3DT4H5M6.789123S"),
243+
null,
244+
Interval.parseFromString("P-1Y-2M-3DT-4H-5M-6.789123S")),
245+
resultSet.getIntervalList(0));
212246
}
213247
}
214248
}

0 commit comments

Comments
 (0)