INTERVAL: StandardSQLTypeName.INTERVAL
*
*
* No other types are supported through that entry point. The other types can be created by
@@ -308,12 +310,26 @@ public static QueryParameterValue time(String value) {
/**
* Creates a {@code QueryParameterValue} object with a type of DATETIME. Must be in the format
- * "yyyy-MM-dd HH:mm:ss.SSSSSS", e.g. ""2014-08-19 12:41:35.220000".
+ * "yyyy-MM-dd HH:mm:ss.SSSSSS", e.g. "2014-08-19 12:41:35.220000".
*/
public static QueryParameterValue dateTime(String value) {
return of(value, StandardSQLTypeName.DATETIME);
}
+ /**
+ * Creates a {@code QueryParameterValue} object with a type of INTERVAL. Must be in the canonical
+ * format "[sign]Y-M [sign]D [sign]H:M:S[.F]", e.g. "123-7 -19 0:24:12.000006" or ISO 8601
+ * duration format, e.g. "P123Y7M-19DT0H24M12.000006S"
+ */
+ public static QueryParameterValue interval(String value) {
+ return of(value, StandardSQLTypeName.INTERVAL);
+ }
+
+ /** Creates a {@code QueryParameterValue} object with a type of INTERVAL. */
+ public static QueryParameterValue interval(PeriodDuration value) {
+ return of(value, StandardSQLTypeName.INTERVAL);
+ }
+
/**
* Creates a {@code QueryParameterValue} object with a type of ARRAY, and an array element type
* based on the given class.
@@ -408,6 +424,8 @@ private static String valueToStringOrNull(T value, StandardSQLTypeName type)
return value.toString();
case JSON:
if (value instanceof String || value instanceof JsonObject) return value.toString();
+ case INTERVAL:
+ if (value instanceof String || value instanceof PeriodDuration) return value.toString();
break;
case STRUCT:
throw new IllegalArgumentException("Cannot convert STRUCT to String value");
diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/StandardSQLTypeName.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/StandardSQLTypeName.java
index 57152a2a6..1081fc5d6 100644
--- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/StandardSQLTypeName.java
+++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/StandardSQLTypeName.java
@@ -57,6 +57,8 @@ public enum StandardSQLTypeName {
DATETIME,
/** Represents a set of geographic points, represented as a Well Known Text (WKT) string. */
GEOGRAPHY,
- /** Represents JSON data */
- JSON
+ /** Represents JSON data. */
+ JSON,
+ /** Represents duration or amount of time. */
+ INTERVAL
}
diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/QueryParameterValueTest.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/QueryParameterValueTest.java
index 679b6ec5c..6b5368003 100644
--- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/QueryParameterValueTest.java
+++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/QueryParameterValueTest.java
@@ -27,6 +27,7 @@
import com.google.gson.JsonObject;
import java.math.BigDecimal;
import java.text.ParseException;
+import java.time.Period;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -38,6 +39,7 @@
import org.threeten.bp.format.DateTimeFormatter;
import org.threeten.bp.format.DateTimeFormatterBuilder;
import org.threeten.bp.jdk8.Jdk8Methods;
+import org.threeten.extra.PeriodDuration;
public class QueryParameterValueTest {
@@ -212,6 +214,24 @@ public void testJson() {
assertThat(value1.getArrayType()).isNull();
}
+ @Test
+ public void testInterval() {
+ QueryParameterValue value = QueryParameterValue.interval("123-7 -19 0:24:12.000006");
+ QueryParameterValue value1 = QueryParameterValue.interval("P123Y7M-19DT0H24M12.000006S");
+ QueryParameterValue value2 =
+ QueryParameterValue.interval(
+ PeriodDuration.of(Period.of(1, 2, 25), java.time.Duration.ofHours(8)));
+ assertThat(value.getValue()).isEqualTo("123-7 -19 0:24:12.000006");
+ assertThat(value1.getValue()).isEqualTo("P123Y7M-19DT0H24M12.000006S");
+ assertThat(value2.getValue()).isEqualTo("P1Y2M25DT8H");
+ assertThat(value.getType()).isEqualTo(StandardSQLTypeName.INTERVAL);
+ assertThat(value1.getType()).isEqualTo(StandardSQLTypeName.INTERVAL);
+ assertThat(value2.getType()).isEqualTo(StandardSQLTypeName.INTERVAL);
+ assertThat(value.getArrayType()).isNull();
+ assertThat(value1.getArrayType()).isNull();
+ assertThat(value2.getArrayType()).isNull();
+ }
+
@Test
public void testBytes() {
QueryParameterValue value = QueryParameterValue.bytes(new byte[] {1, 3});
diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java
index b8051122f..282bef986 100644
--- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java
+++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java
@@ -130,6 +130,7 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.time.Instant;
+import java.time.Period;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -151,6 +152,7 @@
import org.junit.Test;
import org.junit.rules.Timeout;
import org.threeten.bp.Duration;
+import org.threeten.extra.PeriodDuration;
public class ITBigQueryTest {
@@ -816,6 +818,77 @@ public void testJsonType() throws InterruptedException {
}
}
+ @Test
+ public void testIntervalType() throws InterruptedException {
+ String tableName = "test_create_table_intervaltype";
+ TableId tableId = TableId.of(DATASET, tableName);
+ Schema schema = Schema.of(Field.of("intervalField", StandardSQLTypeName.INTERVAL));
+ StandardTableDefinition standardTableDefinition = StandardTableDefinition.of(schema);
+ try {
+ // Create a table with a JSON column
+ Table createdTable = bigquery.create(TableInfo.of(tableId, standardTableDefinition));
+ assertNotNull(createdTable);
+
+ // Insert 3 rows of Interval data into the Interval column
+ Map intervalRow1 =
+ Collections.singletonMap("intervalField", "123-7 -19 0:24:12.000006");
+ Map intervalRow2 =
+ Collections.singletonMap("intervalField", "P123Y7M-19DT0H24M12.000006S");
+
+ InsertAllRequest request =
+ InsertAllRequest.newBuilder(tableId).addRow(intervalRow1).addRow(intervalRow2).build();
+ InsertAllResponse response = bigquery.insertAll(request);
+ assertFalse(response.hasErrors());
+ assertEquals(0, response.getInsertErrors().size());
+
+ // Insert another Interval row parsed from a String with Interval positional query parameter
+ String dml = "INSERT INTO " + tableId.getTable() + " (intervalField) VALUES(?)";
+ // Parsing from ISO 8610 format String
+ QueryParameterValue intervalParameter =
+ QueryParameterValue.interval("P125Y7M-19DT0H24M12.000006S");
+ QueryJobConfiguration dmlQueryJobConfiguration =
+ QueryJobConfiguration.newBuilder(dml)
+ .setDefaultDataset(DatasetId.of(DATASET))
+ .setUseLegacySql(false)
+ .addPositionalParameter(intervalParameter)
+ .build();
+ bigquery.query(dmlQueryJobConfiguration);
+ Page rows = bigquery.listTableData(tableId);
+ assertEquals(3, Iterables.size(rows.getValues()));
+
+ // Parsing from threeten-extra PeriodDuration
+ QueryParameterValue intervalParameter1 =
+ QueryParameterValue.interval(
+ PeriodDuration.of(Period.of(1, 2, 25), java.time.Duration.ofHours(8)));
+ QueryJobConfiguration dmlQueryJobConfiguration1 =
+ QueryJobConfiguration.newBuilder(dml)
+ .setDefaultDataset(DatasetId.of(DATASET))
+ .setUseLegacySql(false)
+ .addPositionalParameter(intervalParameter1)
+ .build();
+ bigquery.query(dmlQueryJobConfiguration1);
+ Page rows1 = bigquery.listTableData(tableId);
+ assertEquals(4, Iterables.size(rows1.getValues()));
+
+ // Query the Interval column with Interval positional query parameter
+ String sql = "SELECT intervalField FROM " + tableId.getTable() + " WHERE intervalField = ? ";
+ QueryParameterValue intervalParameter2 =
+ QueryParameterValue.interval("P125Y7M-19DT0H24M12.000006S");
+ QueryJobConfiguration queryJobConfiguration =
+ QueryJobConfiguration.newBuilder(sql)
+ .setDefaultDataset(DatasetId.of(DATASET))
+ .setUseLegacySql(false)
+ .addPositionalParameter(intervalParameter2)
+ .build();
+ TableResult result = bigquery.query(queryJobConfiguration);
+ for (FieldValueList values : result.iterateAll()) {
+ assertEquals("125-7 -19 0:24:12.000006", values.get(0).getValue());
+ }
+ } finally {
+ assertTrue(bigquery.delete(tableId));
+ }
+ }
+
@Test
public void testCreateTableWithConstraints() {
String tableName = "test_create_table_with_constraints";
diff --git a/pom.xml b/pom.xml
index 15d25e3a2..e47211209 100644
--- a/pom.xml
+++ b/pom.xml
@@ -93,12 +93,20 @@
${google-api-services-bigquery.version}