@@ -24,6 +24,12 @@ def _get_target_class():
24
24
25
25
return SchemaField
26
26
27
+ @staticmethod
28
+ def _get_standard_sql_data_type_class ():
29
+ from google .cloud .bigquery_v2 import types
30
+
31
+ return types .StandardSqlDataType
32
+
27
33
def _make_one (self , * args , ** kw ):
28
34
return self ._get_target_class ()(* args , ** kw )
29
35
@@ -151,6 +157,166 @@ def test_fields_property(self):
151
157
schema_field = self ._make_one ("boat" , "RECORD" , fields = fields )
152
158
self .assertIs (schema_field .fields , fields )
153
159
160
+ def test_to_standard_sql_simple_type (self ):
161
+ sql_type = self ._get_standard_sql_data_type_class ()
162
+ examples = (
163
+ # a few legacy types
164
+ ("INTEGER" , sql_type .INT64 ),
165
+ ("FLOAT" , sql_type .FLOAT64 ),
166
+ ("BOOLEAN" , sql_type .BOOL ),
167
+ ("DATETIME" , sql_type .DATETIME ),
168
+ # a few standard types
169
+ ("INT64" , sql_type .INT64 ),
170
+ ("FLOAT64" , sql_type .FLOAT64 ),
171
+ ("BOOL" , sql_type .BOOL ),
172
+ ("GEOGRAPHY" , sql_type .GEOGRAPHY ),
173
+ )
174
+ for legacy_type , standard_type in examples :
175
+ field = self ._make_one ("some_field" , legacy_type )
176
+ standard_field = field .to_standard_sql ()
177
+ self .assertEqual (standard_field .name , "some_field" )
178
+ self .assertEqual (standard_field .type .type_kind , standard_type )
179
+ self .assertFalse (standard_field .type .HasField ("sub_type" ))
180
+
181
+ def test_to_standard_sql_struct_type (self ):
182
+ from google .cloud .bigquery_v2 import types
183
+
184
+ # Expected result object:
185
+ #
186
+ # name: "image_usage"
187
+ # type {
188
+ # type_kind: STRUCT
189
+ # struct_type {
190
+ # fields {
191
+ # name: "image_content"
192
+ # type {type_kind: BYTES}
193
+ # }
194
+ # fields {
195
+ # name: "last_used"
196
+ # type {
197
+ # type_kind: STRUCT
198
+ # struct_type {
199
+ # fields {
200
+ # name: "date_field"
201
+ # type {type_kind: DATE}
202
+ # }
203
+ # fields {
204
+ # name: "time_field"
205
+ # type {type_kind: TIME}
206
+ # }
207
+ # }
208
+ # }
209
+ # }
210
+ # }
211
+ # }
212
+
213
+ sql_type = self ._get_standard_sql_data_type_class ()
214
+
215
+ # level 2 fields
216
+ sub_sub_field_date = types .StandardSqlField (
217
+ name = "date_field" , type = sql_type (type_kind = sql_type .DATE )
218
+ )
219
+ sub_sub_field_time = types .StandardSqlField (
220
+ name = "time_field" , type = sql_type (type_kind = sql_type .TIME )
221
+ )
222
+
223
+ # level 1 fields
224
+ sub_field_struct = types .StandardSqlField (
225
+ name = "last_used" , type = sql_type (type_kind = sql_type .STRUCT )
226
+ )
227
+ sub_field_struct .type .struct_type .fields .extend (
228
+ [sub_sub_field_date , sub_sub_field_time ]
229
+ )
230
+ sub_field_bytes = types .StandardSqlField (
231
+ name = "image_content" , type = sql_type (type_kind = sql_type .BYTES )
232
+ )
233
+
234
+ # level 0 (top level)
235
+ expected_result = types .StandardSqlField (
236
+ name = "image_usage" , type = sql_type (type_kind = sql_type .STRUCT )
237
+ )
238
+ expected_result .type .struct_type .fields .extend (
239
+ [sub_field_bytes , sub_field_struct ]
240
+ )
241
+
242
+ # construct legacy SchemaField object
243
+ sub_sub_field1 = self ._make_one ("date_field" , "DATE" )
244
+ sub_sub_field2 = self ._make_one ("time_field" , "TIME" )
245
+ sub_field_record = self ._make_one (
246
+ "last_used" , "RECORD" , fields = (sub_sub_field1 , sub_sub_field2 )
247
+ )
248
+ sub_field_bytes = self ._make_one ("image_content" , "BYTES" )
249
+
250
+ for type_name in ("RECORD" , "STRUCT" ):
251
+ schema_field = self ._make_one (
252
+ "image_usage" , type_name , fields = (sub_field_bytes , sub_field_record )
253
+ )
254
+ standard_field = schema_field .to_standard_sql ()
255
+ self .assertEqual (standard_field , expected_result )
256
+
257
+ def test_to_standard_sql_array_type_simple (self ):
258
+ from google .cloud .bigquery_v2 import types
259
+
260
+ sql_type = self ._get_standard_sql_data_type_class ()
261
+
262
+ # construct expected result object
263
+ expected_sql_type = sql_type (type_kind = sql_type .ARRAY )
264
+ expected_sql_type .array_element_type .type_kind = sql_type .INT64
265
+ expected_result = types .StandardSqlField (
266
+ name = "valid_numbers" , type = expected_sql_type
267
+ )
268
+
269
+ # construct "repeated" SchemaField object and convert to standard SQL
270
+ schema_field = self ._make_one ("valid_numbers" , "INT64" , mode = "REPEATED" )
271
+ standard_field = schema_field .to_standard_sql ()
272
+
273
+ self .assertEqual (standard_field , expected_result )
274
+
275
+ def test_to_standard_sql_array_type_struct (self ):
276
+ from google .cloud .bigquery_v2 import types
277
+
278
+ sql_type = self ._get_standard_sql_data_type_class ()
279
+
280
+ # define person STRUCT
281
+ name_field = types .StandardSqlField (
282
+ name = "name" , type = sql_type (type_kind = sql_type .STRING )
283
+ )
284
+ age_field = types .StandardSqlField (
285
+ name = "age" , type = sql_type (type_kind = sql_type .INT64 )
286
+ )
287
+ person_struct = types .StandardSqlField (
288
+ name = "person_info" , type = sql_type (type_kind = sql_type .STRUCT )
289
+ )
290
+ person_struct .type .struct_type .fields .extend ([name_field , age_field ])
291
+
292
+ # define expected result - an ARRAY of person structs
293
+ expected_sql_type = sql_type (
294
+ type_kind = sql_type .ARRAY , array_element_type = person_struct .type
295
+ )
296
+ expected_result = types .StandardSqlField (
297
+ name = "known_people" , type = expected_sql_type
298
+ )
299
+
300
+ # construct legacy repeated SchemaField object
301
+ sub_field1 = self ._make_one ("name" , "STRING" )
302
+ sub_field2 = self ._make_one ("age" , "INTEGER" )
303
+ schema_field = self ._make_one (
304
+ "known_people" , "RECORD" , fields = (sub_field1 , sub_field2 ), mode = "REPEATED"
305
+ )
306
+
307
+ standard_field = schema_field .to_standard_sql ()
308
+ self .assertEqual (standard_field , expected_result )
309
+
310
+ def test_to_standard_sql_unknown_type (self ):
311
+ sql_type = self ._get_standard_sql_data_type_class ()
312
+ field = self ._make_one ("weird_field" , "TROOLEAN" )
313
+
314
+ standard_field = field .to_standard_sql ()
315
+
316
+ self .assertEqual (standard_field .name , "weird_field" )
317
+ self .assertEqual (standard_field .type .type_kind , sql_type .TYPE_KIND_UNSPECIFIED )
318
+ self .assertFalse (standard_field .type .HasField ("sub_type" ))
319
+
154
320
def test___eq___wrong_type (self ):
155
321
field = self ._make_one ("test" , "STRING" )
156
322
other = object ()
0 commit comments