3030import java .util .ArrayList ;
3131import java .util .HashMap ;
3232import java .util .List ;
33+ import java .util .Map ;
3334
3435/**
3536 * Converts a BQ table schema to protobuf descriptor. All field names will be converted to lowercase
3637 * when constructing the protobuf descriptor. The mapping between field types and field modes are
3738 * shown in the ImmutableMaps below.
3839 */
3940public class BQTableSchemaToProtoDescriptor {
40- private static ImmutableMap <TableFieldSchema .Mode , FieldDescriptorProto .Label >
41- BQTableSchemaModeMap =
42- ImmutableMap .of (
43- TableFieldSchema .Mode .NULLABLE , FieldDescriptorProto .Label .LABEL_OPTIONAL ,
44- TableFieldSchema .Mode .REPEATED , FieldDescriptorProto .Label .LABEL_REPEATED ,
45- TableFieldSchema .Mode .REQUIRED , FieldDescriptorProto .Label .LABEL_REQUIRED );
41+ private static Map <Mode , FieldDescriptorProto .Label > DEFAULT_BQ_TABLE_SCHEMA_MODE_MAP =
42+ ImmutableMap .of (
43+ TableFieldSchema .Mode .NULLABLE , FieldDescriptorProto .Label .LABEL_OPTIONAL ,
44+ TableFieldSchema .Mode .REPEATED , FieldDescriptorProto .Label .LABEL_REPEATED ,
45+ TableFieldSchema .Mode .REQUIRED , FieldDescriptorProto .Label .LABEL_REQUIRED );
4646
47- private static ImmutableMap <TableFieldSchema .Type , FieldDescriptorProto .Type >
48- BQTableSchemaTypeMap =
47+ private static Map <TableFieldSchema .Type , FieldDescriptorProto .Type >
48+ DEFAULT_BQ_TABLE_SCHEMA_TYPE_MAP =
4949 new ImmutableMap .Builder <TableFieldSchema .Type , FieldDescriptorProto .Type >()
5050 .put (TableFieldSchema .Type .BOOL , FieldDescriptorProto .Type .TYPE_BOOL )
5151 .put (TableFieldSchema .Type .BYTES , FieldDescriptorProto .Type .TYPE_BYTES )
@@ -59,7 +59,7 @@ public class BQTableSchemaToProtoDescriptor {
5959 .put (TableFieldSchema .Type .STRING , FieldDescriptorProto .Type .TYPE_STRING )
6060 .put (TableFieldSchema .Type .STRUCT , FieldDescriptorProto .Type .TYPE_MESSAGE )
6161 .put (TableFieldSchema .Type .TIME , FieldDescriptorProto .Type .TYPE_INT64 )
62- .put (TableFieldSchema .Type .TIMESTAMP , FieldDescriptorProto .Type .TYPE_STRING )
62+ .put (TableFieldSchema .Type .TIMESTAMP , FieldDescriptorProto .Type .TYPE_INT64 )
6363 .put (TableFieldSchema .Type .JSON , FieldDescriptorProto .Type .TYPE_STRING )
6464 .put (TableFieldSchema .Type .INTERVAL , FieldDescriptorProto .Type .TYPE_STRING )
6565 .put (TableFieldSchema .Type .RANGE , FieldDescriptorProto .Type .TYPE_MESSAGE )
@@ -142,11 +142,13 @@ private static Descriptor convertBQTableSchemaToProtoDescriptorImpl(
142142 .setType (BQTableField .getRangeElementType ().getType ())
143143 .setName ("start" )
144144 .setMode (Mode .NULLABLE )
145+ .setTimestampPrecision (BQTableField .getTimestampPrecision ())
145146 .build (),
146147 TableFieldSchema .newBuilder ()
147148 .setType (BQTableField .getRangeElementType ().getType ())
148149 .setName ("end" )
149150 .setMode (Mode .NULLABLE )
151+ .setTimestampPrecision (BQTableField .getTimestampPrecision ())
150152 .build ());
151153
152154 if (dependencyMap .containsKey (rangeFields )) {
@@ -189,7 +191,7 @@ private static Descriptor convertBQTableSchemaToProtoDescriptorImpl(
189191 * @param index Index for protobuf fields.
190192 * @param scope used to name descriptors
191193 */
192- private static FieldDescriptorProto convertBQTableFieldToProtoField (
194+ static FieldDescriptorProto convertBQTableFieldToProtoField (
193195 TableFieldSchema BQTableField , int index , String scope ) {
194196 TableFieldSchema .Mode mode = BQTableField .getMode ();
195197 String fieldName = BQTableField .getName ().toLowerCase ();
@@ -198,20 +200,32 @@ private static FieldDescriptorProto convertBQTableFieldToProtoField(
198200 FieldDescriptorProto .newBuilder ()
199201 .setName (fieldName )
200202 .setNumber (index )
201- .setLabel ((FieldDescriptorProto .Label ) BQTableSchemaModeMap .get (mode ));
203+ .setLabel ((FieldDescriptorProto .Label ) DEFAULT_BQ_TABLE_SCHEMA_MODE_MAP .get (mode ));
202204
203205 switch (BQTableField .getType ()) {
204206 case STRUCT :
205207 fieldDescriptor .setTypeName (scope );
206208 break ;
207209 case RANGE :
208210 fieldDescriptor .setType (
209- (FieldDescriptorProto .Type ) BQTableSchemaTypeMap .get (BQTableField .getType ()));
211+ (FieldDescriptorProto .Type )
212+ DEFAULT_BQ_TABLE_SCHEMA_TYPE_MAP .get (BQTableField .getType ()));
210213 fieldDescriptor .setTypeName (scope );
211214 break ;
215+ case TIMESTAMP :
216+ // Can map to either int64 or string based on the BQ Field's timestamp precision
217+ // Default: microsecond (6) maps to int64 and picosecond (12) maps to string
218+ if (BQTableField .getTimestampPrecision ().getValue () == 12L ) {
219+ fieldDescriptor .setType (
220+ (FieldDescriptorProto .Type ) FieldDescriptorProto .Type .TYPE_STRING );
221+ } else {
222+ fieldDescriptor .setType ((FieldDescriptorProto .Type ) FieldDescriptorProto .Type .TYPE_INT64 );
223+ }
224+ break ;
212225 default :
213226 fieldDescriptor .setType (
214- (FieldDescriptorProto .Type ) BQTableSchemaTypeMap .get (BQTableField .getType ()));
227+ (FieldDescriptorProto .Type )
228+ DEFAULT_BQ_TABLE_SCHEMA_TYPE_MAP .get (BQTableField .getType ()));
215229 break ;
216230 }
217231
0 commit comments