From 9d6f4f4f070cf4ca14cacb9f492f6fad2da93d18 Mon Sep 17 00:00:00 2001 From: Praful Makani Date: Wed, 11 Mar 2020 19:32:13 +0530 Subject: [PATCH 1/6] feat: struct query parameters --- .../cloud/bigquery/QueryParameterValue.java | 84 ++++++++++++++++++- .../bigquery/QueryParameterValueTest.java | 19 +++++ .../cloud/bigquery/it/ITBigQueryTest.java | 41 +++++++++ 3 files changed, 143 insertions(+), 1 deletion(-) diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java index 732f189eb..fbfbc6dfb 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java @@ -26,13 +26,16 @@ import com.google.cloud.Timestamp; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.io.BaseEncoding; import java.io.Serializable; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.annotation.Nullable; import org.threeten.bp.Instant; import org.threeten.bp.ZoneOffset; @@ -127,12 +130,23 @@ public Builder setArrayValues(List arrayValues) { abstract Builder setArrayValuesInner(ImmutableList arrayValues); + /** Sets struct values. The type must set to STRUCT. */ + public Builder setStructValues(Map structValues) { + setStructTypes(ImmutableMap.copyOf(structValues)); + return setStructValuesInner(ImmutableMap.copyOf(structValues)); + } + + abstract Builder setStructValuesInner(Map structValues); + /** Sets the parameter data type. */ public abstract Builder setType(StandardSQLTypeName type); /** Sets the data type of the array elements. The type must set to ARRAY. */ public abstract Builder setArrayType(StandardSQLTypeName arrayType); + /** Sets the data type of the struct elements. The type must set to STRUCT. */ + abstract Builder setStructTypes(Map structTypes); + /** Creates a {@code QueryParameterValue} object. */ public abstract QueryParameterValue build(); } @@ -154,6 +168,15 @@ public List getArrayValues() { @Nullable abstract ImmutableList getArrayValuesInner(); + /** Returns the struct values of this parameter. The returned map, if not null, is immutable. */ + @Nullable + public Map getStructValues() { + return getStructValuesInner(); + } + + @Nullable + abstract Map getStructValuesInner(); + /** Returns the data type of this parameter. */ public abstract StandardSQLTypeName getType(); @@ -161,6 +184,10 @@ public List getArrayValues() { @Nullable public abstract StandardSQLTypeName getArrayType(); + /** Returns the data type of the struct elements. */ + @Nullable + public abstract Map getStructTypes(); + /** Creates a {@code QueryParameterValue} object with the given value and type. */ public static QueryParameterValue of(T value, Class type) { return of(value, classToType(type)); @@ -274,6 +301,18 @@ public static QueryParameterValue array(T[] array, StandardSQLTypeName type) .build(); } + /** + * Creates a map with {@code QueryParameterValue} object and a type of STRUCT the given struct + * element type. + */ + public static QueryParameterValue struct(Map struct) { + return QueryParameterValue.newBuilder() + .setStructValues(struct) + .setType(StandardSQLTypeName.STRUCT) + .setStructTypes(struct) + .build(); + } + private static StandardSQLTypeName classToType(Class type) { if (Boolean.class.isAssignableFrom(type)) { return StandardSQLTypeName.BOOL; @@ -398,6 +437,14 @@ com.google.api.services.bigquery.model.QueryParameterValue toValuePb() { valuePb.setArrayValues( Lists.transform(getArrayValues(), QueryParameterValue.TO_VALUE_PB_FUNCTION)); } + if (getStructValues() != null) { + Map valueMap = + new HashMap<>(); + for (Map.Entry map : getStructValues().entrySet()) { + valueMap.put(map.getKey(), map.getValue().toValuePb()); + } + valuePb.setStructValues(valueMap); + } return valuePb; } @@ -409,6 +456,16 @@ QueryParameterType toTypePb() { arrayTypePb.setType(getArrayType().toString()); typePb.setArrayType(arrayTypePb); } + if (getStructTypes() != null) { + List structTypes = new ArrayList<>(); + for (Map.Entry entry : getStructTypes().entrySet()) { + QueryParameterType.StructTypes structType = new QueryParameterType.StructTypes(); + structType.setName(entry.getKey()); + structType.setType(entry.getValue().toTypePb()); + structTypes.add(structType); + } + typePb.setStructTypes(structTypes); + } return typePb; } @@ -416,7 +473,7 @@ static QueryParameterValue fromPb( com.google.api.services.bigquery.model.QueryParameterValue valuePb, QueryParameterType typePb) { Builder valueBuilder = newBuilder(); - + Map parameterTypes = new HashMap<>(); StandardSQLTypeName type = StandardSQLTypeName.valueOf(typePb.getType()); valueBuilder.setType(type); if (type == StandardSQLTypeName.ARRAY) { @@ -431,6 +488,31 @@ static QueryParameterValue fromPb( } valueBuilder.setArrayValues(arrayValues.build()); } + } else if (type == StandardSQLTypeName.STRUCT) { + Map structValues = new HashMap<>(); + Map structTypes = new HashMap<>(); + for (QueryParameterType.StructTypes types : typePb.getStructTypes()) { + structTypes.put( + types.getName(), + QueryParameterValue.newBuilder() + .setType(StandardSQLTypeName.valueOf(types.getType().getType())) + .build()); + } + valueBuilder.setStructTypes(structTypes); + if (valuePb == null || valuePb.getStructValues() == null) { + valueBuilder.setStructValues(ImmutableMap.of()); + } else { + for (QueryParameterType.StructTypes structType : typePb.getStructTypes()) { + parameterTypes.put(structType.getName(), structType.getType()); + } + for (Map.Entry entry : + valuePb.getStructValues().entrySet()) { + structValues.put( + entry.getKey(), + QueryParameterValue.fromPb(entry.getValue(), parameterTypes.get(entry.getKey()))); + } + valueBuilder.setStructValues(structValues); + } } else { valueBuilder.setValue(valuePb == null ? "" : valuePb.getValue()); } 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 0e6b9cc9d..176d47a3d 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 @@ -23,6 +23,7 @@ import static org.threeten.bp.temporal.ChronoField.SECOND_OF_MINUTE; import com.google.api.services.bigquery.model.QueryParameterType; +import com.google.common.collect.ImmutableMap; import java.math.BigDecimal; import java.text.ParseException; import java.util.Date; @@ -378,6 +379,24 @@ public void testFromEmptyArray() { assertThat(value.getArrayValues()).isEmpty(); } + @Test + public void testStruct() { + QueryParameterValue booleanField = QueryParameterValue.bool(true); + QueryParameterValue integerField = QueryParameterValue.int64(15); + QueryParameterValue stringField = QueryParameterValue.string("test-string"); + QueryParameterValue recordField = + QueryParameterValue.struct( + ImmutableMap.of( + "booleanField", + booleanField, + "integerField", + integerField, + "stringField", + stringField)); + assertThat(recordField.getValue()).isNull(); + assertThat(recordField.getType()).isEqualTo(StandardSQLTypeName.STRUCT); + } + private static void assertArrayDataEquals( String[] expectedValues, StandardSQLTypeName expectedType, 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 f2e747319..b19ea474c 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 @@ -1428,6 +1428,47 @@ public void testNamedQueryParameters() throws InterruptedException { assertEquals(2, Iterables.size(result.getValues())); } + @Test + public void testStructNamedQueryParameters() throws InterruptedException { + String tableName = "test_record_type_table_struct_named_query"; + TableId tableId = TableId.of(DATASET, tableName); + Field integerField = Field.of("integerField", LegacySQLTypeName.INTEGER); + Field booleanField = Field.of("booleanField", LegacySQLTypeName.BOOLEAN); + Field stringField = Field.of("stringField", LegacySQLTypeName.STRING); + Field recordField = + Field.of("recordField", LegacySQLTypeName.RECORD, integerField, booleanField, stringField); + Schema schema = Schema.of(recordField); + Table createTable = bigquery.create(TableInfo.of(tableId, StandardTableDefinition.of(schema))); + assertNotNull(createTable); + // Insert Dummy data + for (int i = 0; i < 10; i++) { + Map rows = new HashMap<>(); + rows.put("booleanField", i % 2 == 0 ? true : false); + rows.put("stringField", "test-stringField-" + i); + rows.put("integerField", i * 2); + Map record = new HashMap<>(); + record.put("recordField", rows); + bigquery.insertAll(InsertAllRequest.newBuilder(tableId).addRow(record).build()); + } + // Query Struct + QueryParameterValue booleanValue = QueryParameterValue.bool(true); + QueryParameterValue stringValue = QueryParameterValue.string("test-stringField-5"); + Map struct = new HashMap<>(); + struct.put("booleanField", booleanValue); + struct.put("stringField", stringValue); + QueryParameterValue recordValue = QueryParameterValue.struct(struct); + String query = "SELECT STRUCT(@recordField) FROM " + tableId.getTable(); + QueryJobConfiguration config = + QueryJobConfiguration.newBuilder(query) + .setDefaultDataset(DATASET) + .setUseLegacySql(false) + .addNamedParameter("recordField", recordValue) + .build(); + TableResult result = bigquery.query(config); + assertEquals(schema, result.getSchema()); + assertEquals(1, Iterables.size(result.getValues())); + } + @Test public void testBytesParameter() throws Exception { String query = "SELECT BYTE_LENGTH(@p) AS length"; From e7acf2999ea293494b53d8c0ed15df234787030b Mon Sep 17 00:00:00 2001 From: Praful Makani Date: Fri, 13 Mar 2020 17:01:18 +0530 Subject: [PATCH 2/6] feat: unit and integration test case --- .../clirr-ignored-differences.xml | 9 +++++++ .../cloud/bigquery/QueryParameterValue.java | 18 ++++++------- .../bigquery/QueryParameterValueTest.java | 8 ++++++ .../cloud/bigquery/it/ITBigQueryTest.java | 26 +++---------------- 4 files changed, 29 insertions(+), 32 deletions(-) create mode 100644 google-cloud-bigquery/clirr-ignored-differences.xml diff --git a/google-cloud-bigquery/clirr-ignored-differences.xml b/google-cloud-bigquery/clirr-ignored-differences.xml new file mode 100644 index 000000000..e04788fa8 --- /dev/null +++ b/google-cloud-bigquery/clirr-ignored-differences.xml @@ -0,0 +1,9 @@ + + + + + com/google/cloud/bigquery/QueryParameterValue + java.util.Map getStructTypes() + 7013 + + diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java index fbfbc6dfb..495310fbf 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java @@ -309,7 +309,6 @@ public static QueryParameterValue struct(Map struct return QueryParameterValue.newBuilder() .setStructValues(struct) .setType(StandardSQLTypeName.STRUCT) - .setStructTypes(struct) .build(); } @@ -438,12 +437,12 @@ com.google.api.services.bigquery.model.QueryParameterValue toValuePb() { Lists.transform(getArrayValues(), QueryParameterValue.TO_VALUE_PB_FUNCTION)); } if (getStructValues() != null) { - Map valueMap = + Map structValues = new HashMap<>(); - for (Map.Entry map : getStructValues().entrySet()) { - valueMap.put(map.getKey(), map.getValue().toValuePb()); + for (Map.Entry structValue : getStructValues().entrySet()) { + structValues.put(structValue.getKey(), structValue.getValue().toValuePb()); } - valuePb.setStructValues(valueMap); + valuePb.setStructValues(structValues); } return valuePb; } @@ -505,11 +504,12 @@ static QueryParameterValue fromPb( for (QueryParameterType.StructTypes structType : typePb.getStructTypes()) { parameterTypes.put(structType.getName(), structType.getType()); } - for (Map.Entry entry : - valuePb.getStructValues().entrySet()) { + for (Map.Entry + structValue : valuePb.getStructValues().entrySet()) { structValues.put( - entry.getKey(), - QueryParameterValue.fromPb(entry.getValue(), parameterTypes.get(entry.getKey()))); + structValue.getKey(), + QueryParameterValue.fromPb( + structValue.getValue(), parameterTypes.get(structValue.getKey()))); } valueBuilder.setStructValues(structValues); } 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 176d47a3d..c7a7d5cb2 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 @@ -393,8 +393,16 @@ public void testStruct() { integerField, "stringField", stringField)); + com.google.api.services.bigquery.model.QueryParameterValue parameterValue = + recordField.toValuePb(); + QueryParameterType parameterType = recordField.toTypePb(); + QueryParameterValue queryParameterValue = + QueryParameterValue.fromPb(parameterValue, parameterType); + assertThat(queryParameterValue).isEqualTo(recordField); assertThat(recordField.getValue()).isNull(); assertThat(recordField.getType()).isEqualTo(StandardSQLTypeName.STRUCT); + assertThat(recordField.getStructTypes()).isNotNull(); + assertThat(recordField.getStructValues()).isNotNull(); } private static void assertArrayDataEquals( 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 b19ea474c..e430a1b40 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 @@ -1430,34 +1430,15 @@ public void testNamedQueryParameters() throws InterruptedException { @Test public void testStructNamedQueryParameters() throws InterruptedException { - String tableName = "test_record_type_table_struct_named_query"; - TableId tableId = TableId.of(DATASET, tableName); - Field integerField = Field.of("integerField", LegacySQLTypeName.INTEGER); - Field booleanField = Field.of("booleanField", LegacySQLTypeName.BOOLEAN); - Field stringField = Field.of("stringField", LegacySQLTypeName.STRING); - Field recordField = - Field.of("recordField", LegacySQLTypeName.RECORD, integerField, booleanField, stringField); - Schema schema = Schema.of(recordField); - Table createTable = bigquery.create(TableInfo.of(tableId, StandardTableDefinition.of(schema))); - assertNotNull(createTable); - // Insert Dummy data - for (int i = 0; i < 10; i++) { - Map rows = new HashMap<>(); - rows.put("booleanField", i % 2 == 0 ? true : false); - rows.put("stringField", "test-stringField-" + i); - rows.put("integerField", i * 2); - Map record = new HashMap<>(); - record.put("recordField", rows); - bigquery.insertAll(InsertAllRequest.newBuilder(tableId).addRow(record).build()); - } - // Query Struct QueryParameterValue booleanValue = QueryParameterValue.bool(true); QueryParameterValue stringValue = QueryParameterValue.string("test-stringField-5"); + QueryParameterValue integerValue = QueryParameterValue.int64(10); Map struct = new HashMap<>(); struct.put("booleanField", booleanValue); + struct.put("integerField", integerValue); struct.put("stringField", stringValue); QueryParameterValue recordValue = QueryParameterValue.struct(struct); - String query = "SELECT STRUCT(@recordField) FROM " + tableId.getTable(); + String query = "SELECT STRUCT(@recordField) AS record"; QueryJobConfiguration config = QueryJobConfiguration.newBuilder(query) .setDefaultDataset(DATASET) @@ -1465,7 +1446,6 @@ public void testStructNamedQueryParameters() throws InterruptedException { .addNamedParameter("recordField", recordValue) .build(); TableResult result = bigquery.query(config); - assertEquals(schema, result.getSchema()); assertEquals(1, Iterables.size(result.getValues())); } From e7bc009fad1a87bc0bf030973970a5d5e1354b4e Mon Sep 17 00:00:00 2001 From: Praful Makani Date: Mon, 16 Mar 2020 10:53:33 +0530 Subject: [PATCH 3/6] feat: adjust code --- .../java/com/google/cloud/bigquery/QueryParameterValue.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java index 495310fbf..1fb51a259 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java @@ -488,7 +488,6 @@ static QueryParameterValue fromPb( valueBuilder.setArrayValues(arrayValues.build()); } } else if (type == StandardSQLTypeName.STRUCT) { - Map structValues = new HashMap<>(); Map structTypes = new HashMap<>(); for (QueryParameterType.StructTypes types : typePb.getStructTypes()) { structTypes.put( @@ -501,6 +500,7 @@ static QueryParameterValue fromPb( if (valuePb == null || valuePb.getStructValues() == null) { valueBuilder.setStructValues(ImmutableMap.of()); } else { + Map structValues = new HashMap<>(); for (QueryParameterType.StructTypes structType : typePb.getStructTypes()) { parameterTypes.put(structType.getName(), structType.getType()); } @@ -516,7 +516,6 @@ static QueryParameterValue fromPb( } else { valueBuilder.setValue(valuePb == null ? "" : valuePb.getValue()); } - return valueBuilder.build(); } } From 056603e6e479be22c8c5c83f03b63e0d0d26b73d Mon Sep 17 00:00:00 2001 From: Praful Makani Date: Tue, 17 Mar 2020 10:32:29 +0530 Subject: [PATCH 4/6] feat: remove clirr and refactor code --- google-cloud-bigquery/clirr-ignored-differences.xml | 9 --------- .../google/cloud/bigquery/QueryParameterValue.java | 13 +++++++++++-- 2 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 google-cloud-bigquery/clirr-ignored-differences.xml diff --git a/google-cloud-bigquery/clirr-ignored-differences.xml b/google-cloud-bigquery/clirr-ignored-differences.xml deleted file mode 100644 index e04788fa8..000000000 --- a/google-cloud-bigquery/clirr-ignored-differences.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - com/google/cloud/bigquery/QueryParameterValue - java.util.Map getStructTypes() - 7013 - - diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java index 1fb51a259..e9c21674f 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java @@ -145,7 +145,11 @@ public Builder setStructValues(Map structValues) { public abstract Builder setArrayType(StandardSQLTypeName arrayType); /** Sets the data type of the struct elements. The type must set to STRUCT. */ - abstract Builder setStructTypes(Map structTypes); + public Builder setStructTypes(Map structTypes) { + return setStructTypesInner(structTypes); + } + + abstract Builder setStructTypesInner(Map structTypes); /** Creates a {@code QueryParameterValue} object. */ public abstract QueryParameterValue build(); @@ -186,7 +190,12 @@ public Map getStructValues() { /** Returns the data type of the struct elements. */ @Nullable - public abstract Map getStructTypes(); + public Map getStructTypes() { + return getStructTypesInner(); + } + + @Nullable + abstract Map getStructTypesInner(); /** Creates a {@code QueryParameterValue} object with the given value and type. */ public static QueryParameterValue of(T value, Class type) { From beb5c854eb726579cfd2a1004f2c91985fb5fbba Mon Sep 17 00:00:00 2001 From: Praful Makani Date: Thu, 19 Mar 2020 18:54:53 +0530 Subject: [PATCH 5/6] feat: additional test case --- .../bigquery/QueryParameterValueTest.java | 38 +++++++++++++++++++ .../cloud/bigquery/it/ITBigQueryTest.java | 27 +++++++++++++ 2 files changed, 65 insertions(+) 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 c7a7d5cb2..930a29c40 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,7 +27,9 @@ import java.math.BigDecimal; import java.text.ParseException; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.junit.Test; import org.threeten.bp.Instant; import org.threeten.bp.ZoneOffset; @@ -405,6 +407,42 @@ public void testStruct() { assertThat(recordField.getStructValues()).isNotNull(); } + @Test + public void testNestedStruct() { + QueryParameterValue booleanField = QueryParameterValue.bool(true); + QueryParameterValue integerField = QueryParameterValue.int64(15); + QueryParameterValue stringField = QueryParameterValue.string("test-string"); + QueryParameterValue recordField = + QueryParameterValue.struct( + ImmutableMap.of( + "booleanField", + booleanField, + "integerField", + integerField, + "stringField", + stringField)); + Map structValue = new HashMap<>(); + structValue.put("bool", booleanField); + structValue.put("int", integerField); + structValue.put("string", stringField); + structValue.put("struct", recordField); + QueryParameterValue nestedRecordField = QueryParameterValue.struct(structValue); + com.google.api.services.bigquery.model.QueryParameterValue parameterValue = + nestedRecordField.toValuePb(); + QueryParameterType parameterType = nestedRecordField.toTypePb(); + QueryParameterValue queryParameterValue = + QueryParameterValue.fromPb(parameterValue, parameterType); + assertThat(queryParameterValue).isEqualTo(nestedRecordField); + assertThat(nestedRecordField.getValue()).isNull(); + assertThat(nestedRecordField.getType()).isEqualTo(StandardSQLTypeName.STRUCT); + assertThat(nestedRecordField.getStructTypes().get("struct").getType()) + .isEqualTo(StandardSQLTypeName.STRUCT); + assertThat(nestedRecordField.getStructValues().get("struct").getStructValues()) + .containsAtLeastEntriesIn(recordField.getStructValues()); + assertThat(nestedRecordField.getStructTypes().size()).isEqualTo(structValue.size()); + assertThat(nestedRecordField.getStructValues().size()).isEqualTo(structValue.size()); + } + private static void assertArrayDataEquals( String[] expectedValues, StandardSQLTypeName expectedType, 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 e430a1b40..27c052e46 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 @@ -1449,6 +1449,33 @@ public void testStructNamedQueryParameters() throws InterruptedException { assertEquals(1, Iterables.size(result.getValues())); } + @Test + public void testNestedStructNamedQueryParameters() throws InterruptedException { + QueryParameterValue booleanValue = QueryParameterValue.bool(true); + QueryParameterValue stringValue = QueryParameterValue.string("test-stringField-5"); + QueryParameterValue integerValue = QueryParameterValue.int64(10); + Map struct = new HashMap<>(); + struct.put("booleanField", booleanValue); + struct.put("integerField", integerValue); + struct.put("stringField", stringValue); + QueryParameterValue recordValue = QueryParameterValue.struct(struct); + Map structValue = new HashMap<>(); + structValue.put("bool", booleanValue); + structValue.put("int", integerValue); + structValue.put("string", stringValue); + structValue.put("struct", recordValue); + QueryParameterValue nestedRecordField = QueryParameterValue.struct(structValue); + String query = "SELECT STRUCT(@nestedRecordField) AS record"; + QueryJobConfiguration config = + QueryJobConfiguration.newBuilder(query) + .setDefaultDataset(DATASET) + .setUseLegacySql(false) + .addNamedParameter("nestedRecordField", nestedRecordField) + .build(); + TableResult result = bigquery.query(config); + assertEquals(1, Iterables.size(result.getValues())); + } + @Test public void testBytesParameter() throws Exception { String query = "SELECT BYTE_LENGTH(@p) AS length"; From a0600cf0d0b3986c27b5061a992fe94af6a80fe3 Mon Sep 17 00:00:00 2001 From: Praful Makani Date: Fri, 20 Mar 2020 18:05:58 +0530 Subject: [PATCH 6/6] feat: add asserts for values --- .../cloud/bigquery/it/ITBigQueryTest.java | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) 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 27c052e46..0bc97c5ea 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 @@ -1431,7 +1431,7 @@ public void testNamedQueryParameters() throws InterruptedException { @Test public void testStructNamedQueryParameters() throws InterruptedException { QueryParameterValue booleanValue = QueryParameterValue.bool(true); - QueryParameterValue stringValue = QueryParameterValue.string("test-stringField-5"); + QueryParameterValue stringValue = QueryParameterValue.string("test-stringField"); QueryParameterValue integerValue = QueryParameterValue.int64(10); Map struct = new HashMap<>(); struct.put("booleanField", booleanValue); @@ -1447,12 +1447,22 @@ public void testStructNamedQueryParameters() throws InterruptedException { .build(); TableResult result = bigquery.query(config); assertEquals(1, Iterables.size(result.getValues())); + for (FieldValueList values : result.iterateAll()) { + for (FieldValue value : values) { + for (FieldValue record : value.getRecordValue()) { + assertEquals(FieldValue.Attribute.RECORD, record.getAttribute()); + assertEquals(true, record.getRecordValue().get(0).getBooleanValue()); + assertEquals(10, record.getRecordValue().get(1).getLongValue()); + assertEquals("test-stringField", record.getRecordValue().get(2).getStringValue()); + } + } + } } @Test public void testNestedStructNamedQueryParameters() throws InterruptedException { QueryParameterValue booleanValue = QueryParameterValue.bool(true); - QueryParameterValue stringValue = QueryParameterValue.string("test-stringField-5"); + QueryParameterValue stringValue = QueryParameterValue.string("test-stringField"); QueryParameterValue integerValue = QueryParameterValue.int64(10); Map struct = new HashMap<>(); struct.put("booleanField", booleanValue); @@ -1474,6 +1484,22 @@ public void testNestedStructNamedQueryParameters() throws InterruptedException { .build(); TableResult result = bigquery.query(config); assertEquals(1, Iterables.size(result.getValues())); + for (FieldValueList values : result.iterateAll()) { + for (FieldValue value : values) { + assertEquals(FieldValue.Attribute.RECORD, value.getAttribute()); + for (FieldValue record : value.getRecordValue()) { + assertEquals( + true, record.getRecordValue().get(0).getRecordValue().get(0).getBooleanValue()); + assertEquals(10, record.getRecordValue().get(0).getRecordValue().get(1).getLongValue()); + assertEquals( + "test-stringField", + record.getRecordValue().get(0).getRecordValue().get(2).getStringValue()); + assertEquals(true, record.getRecordValue().get(1).getBooleanValue()); + assertEquals("test-stringField", record.getRecordValue().get(2).getStringValue()); + assertEquals(10, record.getRecordValue().get(3).getLongValue()); + } + } + } } @Test