diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Field.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Field.java index ba0e45e5f358..ffc8b3779aa6 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Field.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Field.java @@ -112,6 +112,24 @@ public Builder setType(LegacySQLTypeName type, Field... subFields) { return setType(type, subFields.length > 0 ? FieldList.of(subFields) : null); } + /** + * Sets the type of the field. + * + * @param type BigQuery data type + * @param subFields nested schema fields in case if {@code type} is {@link + * StandardSQLTypeName#STRUCT}, empty otherwise + * @throws IllegalArgumentException if {@code type == StandardSQLTypeName.STRUCT && + * subFields.length == 0} or if {@code type != StandardSQLTypeName.STRUCT && + * subFields.length != 0} + * @see Data + * Types + */ + public Builder setType(StandardSQLTypeName type, Field... subFields) { + return setType( + LegacySQLTypeName.legacySQLTypeName(type), + subFields.length > 0 ? FieldList.of(subFields) : null); + } + /** * Sets the type of the field. * @@ -142,6 +160,22 @@ public Builder setType(LegacySQLTypeName type, FieldList subFields) { return this; } + /** + * Sets the type of the field. + * + * @param type BigQuery data type + * @param subFields nested schema fields in case if {@code type} is {@link + * StandardSQLTypeName#STRUCT}, empty otherwise + * @throws IllegalArgumentException if {@code type == StandardSQLTypeName.STRUCT && + * subFields.length == 0} or if {@code type != StandardSQLTypeName.STRUCT && + * subFields.length != 0} + * @see Data + * Types + */ + public Builder setType(StandardSQLTypeName type, FieldList subFields) { + return setType(LegacySQLTypeName.legacySQLTypeName(type), subFields); + } + /** Sets the mode of the field. When not specified {@link Mode#NULLABLE} is used. */ public Builder setMode(Mode mode) { this.mode = mode != null ? mode.name() : Data.nullOf(String.class); @@ -241,11 +275,21 @@ public static Builder newBuilder(String name, LegacySQLTypeName type, Field... s return new Builder().setName(name).setType(type, subFields); } + /** Returns a builder for a Field object with given name and type. */ + public static Builder newBuilder(String name, StandardSQLTypeName type, Field... subFields) { + return new Builder().setName(name).setType(type, subFields); + } + /** Returns a builder for a Field object with given name and type. */ public static Builder newBuilder(String name, LegacySQLTypeName type, FieldList subFields) { return new Builder().setName(name).setType(type, subFields); } + /** Returns a builder for a Field object with given name and type. */ + public static Builder newBuilder(String name, StandardSQLTypeName type, FieldList subFields) { + return new Builder().setName(name).setType(type, subFields); + } + TableFieldSchema toPb() { TableFieldSchema fieldSchemaPb = new TableFieldSchema(); fieldSchemaPb.setName(name); diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LegacySQLTypeName.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LegacySQLTypeName.java index 9c9b12ac8529..035ae8ed9cb0 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LegacySQLTypeName.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LegacySQLTypeName.java @@ -19,6 +19,8 @@ import com.google.api.core.ApiFunction; import com.google.cloud.StringEnumType; import com.google.cloud.StringEnumValue; +import java.util.HashMap; +import java.util.Map; /** * A type used in legacy SQL contexts. NOTE: some contexts use a mix of types; for example, for @@ -84,6 +86,14 @@ public LegacySQLTypeName apply(String constant) { public static final LegacySQLTypeName RECORD = type.createAndRegister("RECORD").setStandardType(StandardSQLTypeName.STRUCT); + private static Map standardToLegacyMap = new HashMap<>(); + + static { + for (LegacySQLTypeName legacySqlTypeName : LegacySQLTypeName.values()) { + standardToLegacyMap.put(legacySqlTypeName.equivalent, legacySqlTypeName); + } + } + private StandardSQLTypeName equivalent; private LegacySQLTypeName setStandardType(StandardSQLTypeName equivalent) { @@ -96,6 +106,11 @@ public StandardSQLTypeName getStandardType() { return equivalent; } + /** Converts StandardSQLTypeName to LegacySQLTypeName */ + public static LegacySQLTypeName legacySQLTypeName(StandardSQLTypeName type) { + return standardToLegacyMap.get(type); + } + private LegacySQLTypeName(String constant) { super(constant); } diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/FieldTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/FieldTest.java index 4ba5ad0929a0..14900cc5d423 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/FieldTest.java +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/FieldTest.java @@ -54,6 +54,25 @@ public class FieldTest { .setMode(FIELD_MODE3) .setDescription(FIELD_DESCRIPTION3) .build(); + private static final Field STANDARD_FIELD_SCHEMA1 = + Field.newBuilder(FIELD_NAME1, StandardSQLTypeName.STRING) + .setMode(FIELD_MODE1) + .setDescription(FIELD_DESCRIPTION1) + .build(); + private static final Field STANDARD_FIELD_SCHEMA2 = + Field.newBuilder(FIELD_NAME2, StandardSQLTypeName.INT64) + .setMode(FIELD_MODE2) + .setDescription(FIELD_DESCRIPTION2) + .build(); + private static final Field STANDARD_FIELD_SCHEMA3 = + Field.newBuilder( + FIELD_NAME3, + StandardSQLTypeName.STRUCT, + STANDARD_FIELD_SCHEMA1, + STANDARD_FIELD_SCHEMA2) + .setMode(FIELD_MODE3) + .setDescription(FIELD_DESCRIPTION3) + .build(); @Test public void testToBuilder() { @@ -66,6 +85,17 @@ public void testToBuilder() { compareFieldSchemas(FIELD_SCHEMA1, field); } + @Test + public void testToBuilderWithStandardSQLTypeName() { + compareFieldSchemas(STANDARD_FIELD_SCHEMA1, STANDARD_FIELD_SCHEMA1.toBuilder().build()); + compareFieldSchemas(STANDARD_FIELD_SCHEMA2, STANDARD_FIELD_SCHEMA2.toBuilder().build()); + compareFieldSchemas(STANDARD_FIELD_SCHEMA3, STANDARD_FIELD_SCHEMA3.toBuilder().build()); + Field field = STANDARD_FIELD_SCHEMA1.toBuilder().setDescription("New Description").build(); + assertEquals("New Description", field.getDescription()); + field = field.toBuilder().setDescription(FIELD_DESCRIPTION1).build(); + compareFieldSchemas(STANDARD_FIELD_SCHEMA1, field); + } + @Test public void testToBuilderIncomplete() { Field field = Field.of(FIELD_NAME1, FIELD_TYPE1); @@ -74,6 +104,14 @@ public void testToBuilderIncomplete() { compareFieldSchemas(field, field.toBuilder().build()); } + @Test + public void testToBuilderIncompleteWithStandardSQLTypeName() { + Field field = Field.of(FIELD_NAME1, FIELD_TYPE1); + compareFieldSchemas(field, field.toBuilder().build()); + field = Field.of(FIELD_NAME2, FIELD_TYPE3, STANDARD_FIELD_SCHEMA1, STANDARD_FIELD_SCHEMA2); + compareFieldSchemas(field, field.toBuilder().build()); + } + @Test public void testBuilder() { assertEquals(FIELD_NAME1, FIELD_SCHEMA1.getName()); @@ -88,6 +126,22 @@ public void testBuilder() { assertEquals(FieldList.of(FIELD_SCHEMA1, FIELD_SCHEMA2), FIELD_SCHEMA3.getSubFields()); } + @Test + public void testBuilderWithStandardSQLTypeName() { + assertEquals(FIELD_NAME1, STANDARD_FIELD_SCHEMA1.getName()); + assertEquals(FIELD_TYPE1, STANDARD_FIELD_SCHEMA1.getType()); + assertEquals(FIELD_MODE1, STANDARD_FIELD_SCHEMA1.getMode()); + assertEquals(FIELD_DESCRIPTION1, STANDARD_FIELD_SCHEMA1.getDescription()); + assertEquals(null, STANDARD_FIELD_SCHEMA1.getSubFields()); + assertEquals(FIELD_NAME3, STANDARD_FIELD_SCHEMA3.getName()); + assertEquals(FIELD_TYPE3, STANDARD_FIELD_SCHEMA3.getType()); + assertEquals(FIELD_MODE3, STANDARD_FIELD_SCHEMA3.getMode()); + assertEquals(FIELD_DESCRIPTION3, STANDARD_FIELD_SCHEMA3.getDescription()); + assertEquals( + FieldList.of(STANDARD_FIELD_SCHEMA1, STANDARD_FIELD_SCHEMA2), + STANDARD_FIELD_SCHEMA3.getSubFields()); + } + @Test public void testToAndFromPb() { compareFieldSchemas(FIELD_SCHEMA1, Field.fromPb(FIELD_SCHEMA1.toPb())); @@ -97,6 +151,15 @@ public void testToAndFromPb() { compareFieldSchemas(field, Field.fromPb(field.toPb())); } + @Test + public void testToAndFromPbWithStandardSQLTypeName() { + compareFieldSchemas(STANDARD_FIELD_SCHEMA1, Field.fromPb(STANDARD_FIELD_SCHEMA1.toPb())); + compareFieldSchemas(STANDARD_FIELD_SCHEMA2, Field.fromPb(STANDARD_FIELD_SCHEMA2.toPb())); + compareFieldSchemas(STANDARD_FIELD_SCHEMA3, Field.fromPb(STANDARD_FIELD_SCHEMA3.toPb())); + Field field = Field.newBuilder(FIELD_NAME1, FIELD_TYPE1).build(); + compareFieldSchemas(field, Field.fromPb(field.toPb())); + } + @Test public void testSubFieldWithClonedType() throws Exception { LegacySQLTypeName record = LegacySQLTypeName.RECORD;