Skip to content

Commit bfb4060

Browse files
committed
Conform to expected wire format for struct query parameters.
Closes: #2887.
1 parent a8fb997 commit bfb4060

File tree

3 files changed

+54
-16
lines changed

3 files changed

+54
-16
lines changed

bigquery/google/cloud/bigquery/_helpers.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ def to_api_repr(self):
501501
values = [converter(value) for value in values]
502502
resource = {
503503
'parameterType': {
504+
'type': 'ARRAY',
504505
'arrayType': self.array_type,
505506
},
506507
'parameterValue': {
@@ -554,10 +555,12 @@ def from_api_repr(cls, resource):
554555
instance = cls(name)
555556
types = instance.struct_types
556557
for item in resource['parameterType']['structTypes']:
557-
types[item['name']] = item['type']
558+
types[item['name']] = item['type']['type']
558559
struct_values = resource['parameterValue']['structValues']
559560
for key, value in struct_values.items():
560-
converted = _CELLDATA_FROM_JSON[types[key]](value, None)
561+
type_ = types[key]
562+
value = value['value']
563+
converted = _CELLDATA_FROM_JSON[type_](value, None)
561564
instance.struct_values[key] = converted
562565
return instance
563566

@@ -568,18 +571,19 @@ def to_api_repr(self):
568571
:returns: JSON mapping
569572
"""
570573
types = [
571-
{'name': key, 'type': value}
574+
{'name': key, 'type': {'type': value}}
572575
for key, value in self.struct_types.items()
573576
]
574577
values = {}
575578
for name, value in self.struct_values.items():
576579
converter = _SCALAR_VALUE_TO_JSON.get(self.struct_types[name])
577580
if converter is not None:
578581
value = converter(value)
579-
values[name] = value
582+
values[name] = {'value': value}
580583

581584
resource = {
582585
'parameterType': {
586+
'type': 'STRUCT',
583587
'structTypes': types,
584588
},
585589
'parameterValue': {

bigquery/unit_tests/test__helpers.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,7 @@ def test_from_api_repr_w_name(self):
10821082
def test_from_api_repr_wo_name(self):
10831083
RESOURCE = {
10841084
'parameterType': {
1085+
'type': 'ARRAY',
10851086
'arrayType': 'INT64',
10861087
},
10871088
'parameterValue': {
@@ -1098,6 +1099,7 @@ def test_to_api_repr_w_name(self):
10981099
EXPECTED = {
10991100
'name': 'foo',
11001101
'parameterType': {
1102+
'type': 'ARRAY',
11011103
'arrayType': 'INT64',
11021104
},
11031105
'parameterValue': {
@@ -1110,6 +1112,7 @@ def test_to_api_repr_w_name(self):
11101112
def test_to_api_repr_wo_name(self):
11111113
EXPECTED = {
11121114
'parameterType': {
1115+
'type': 'ARRAY',
11131116
'arrayType': 'INT64',
11141117
},
11151118
'parameterValue': {
@@ -1123,6 +1126,7 @@ def test_to_api_repr_wo_name(self):
11231126
def test_to_api_repr_w_unknown_type(self):
11241127
EXPECTED = {
11251128
'parameterType': {
1129+
'type': 'ARRAY',
11261130
'arrayType': 'UNKNOWN',
11271131
},
11281132
'parameterValue': {
@@ -1170,13 +1174,17 @@ def test_from_api_repr_w_name(self):
11701174
RESOURCE = {
11711175
'name': 'foo',
11721176
'parameterType': {
1177+
'type': 'STRUTCT',
11731178
'structTypes': [
1174-
{'name': 'bar', 'type': 'INT64'},
1175-
{'name': 'baz', 'type': 'STRING'},
1179+
{'name': 'bar', 'type': {'type': 'INT64'}},
1180+
{'name': 'baz', 'type': {'type': 'STRING'}},
11761181
],
11771182
},
11781183
'parameterValue': {
1179-
'structValues': {'bar': 123, 'baz': 'abc'},
1184+
'structValues': {
1185+
'bar': {'value': 123},
1186+
'baz': {'value': 'abc'},
1187+
},
11801188
},
11811189
}
11821190
klass = self._get_target_class()
@@ -1188,13 +1196,17 @@ def test_from_api_repr_w_name(self):
11881196
def test_from_api_repr_wo_name(self):
11891197
RESOURCE = {
11901198
'parameterType': {
1199+
'type': 'STRUTCT',
11911200
'structTypes': [
1192-
{'name': 'bar', 'type': 'INT64'},
1193-
{'name': 'baz', 'type': 'STRING'},
1201+
{'name': 'bar', 'type': {'type': 'INT64'}},
1202+
{'name': 'baz', 'type': {'type': 'STRING'}},
11941203
],
11951204
},
11961205
'parameterValue': {
1197-
'structValues': {'bar': 123, 'baz': 'abc'},
1206+
'structValues': {
1207+
'bar': {'value': 123},
1208+
'baz': {'value': 'abc'},
1209+
},
11981210
},
11991211
}
12001212
klass = self._get_target_class()
@@ -1207,13 +1219,17 @@ def test_to_api_repr_w_name(self):
12071219
EXPECTED = {
12081220
'name': 'foo',
12091221
'parameterType': {
1222+
'type': 'STRUCT',
12101223
'structTypes': [
1211-
{'name': 'bar', 'type': 'INT64'},
1212-
{'name': 'baz', 'type': 'STRING'},
1224+
{'name': 'bar', 'type': {'type': 'INT64'}},
1225+
{'name': 'baz', 'type': {'type': 'STRING'}},
12131226
],
12141227
},
12151228
'parameterValue': {
1216-
'structValues': {'bar': '123', 'baz': 'abc'},
1229+
'structValues': {
1230+
'bar': {'value': '123'},
1231+
'baz': {'value': 'abc'},
1232+
},
12171233
},
12181234
}
12191235
sub_1 = self._make_subparam('bar', 'INT64', 123)
@@ -1224,13 +1240,17 @@ def test_to_api_repr_w_name(self):
12241240
def test_to_api_repr_wo_name(self):
12251241
EXPECTED = {
12261242
'parameterType': {
1243+
'type': 'STRUCT',
12271244
'structTypes': [
1228-
{'name': 'bar', 'type': 'INT64'},
1229-
{'name': 'baz', 'type': 'STRING'},
1245+
{'name': 'bar', 'type': {'type': 'INT64'}},
1246+
{'name': 'baz', 'type': {'type': 'STRING'}},
12301247
],
12311248
},
12321249
'parameterValue': {
1233-
'structValues': {'bar': '123', 'baz': 'abc'},
1250+
'structValues': {
1251+
'bar': {'value': '123'},
1252+
'baz': {'value': 'abc'},
1253+
},
12341254
},
12351255
}
12361256
sub_1 = self._make_subparam('bar', 'INT64', 123)

system_tests/bigquery.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,11 +483,20 @@ def test_sync_query_w_standard_sql_types(self):
483483
import datetime
484484
from google.cloud._helpers import UTC
485485
from google.cloud.bigquery._helpers import ScalarQueryParameter
486+
from google.cloud.bigquery._helpers import StructQueryParameter
486487
naive = datetime.datetime(2016, 12, 5, 12, 41, 9)
487488
stamp = "%s %s" % (naive.date().isoformat(), naive.time().isoformat())
488489
zoned = naive.replace(tzinfo=UTC)
489490
zoned_param = ScalarQueryParameter(
490491
name='zoned', type_='TIMESTAMP', value=zoned)
492+
question = 'What is the answer to life, the universe, and everything?'
493+
question_param = ScalarQueryParameter(
494+
name='question', type_='STRING', value=question)
495+
answer = 42
496+
answer_param = ScalarQueryParameter(
497+
name='answer', type_='INT64', value=answer)
498+
struct_param = StructQueryParameter(
499+
'hitchhiker', question_param, answer_param)
491500
EXAMPLES = [
492501
{
493502
'sql': 'SELECT 1',
@@ -561,6 +570,11 @@ def test_sync_query_w_standard_sql_types(self):
561570
'expected': zoned,
562571
'query_parameters': [zoned_param],
563572
},
573+
{
574+
'sql': 'SELECT (@hitchhiker.question, @hitchhiker.answer)',
575+
'expected': ({'_field_1': question, '_field_2': answer}),
576+
'query_parameters': [struct_param],
577+
},
564578
]
565579
for example in EXAMPLES:
566580
query = Config.CLIENT.run_sync_query(

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy