From 9c229886d9c493b7b3f1ca01c1018d71f730273c Mon Sep 17 00:00:00 2001 From: Peter Lamut Date: Wed, 14 Aug 2019 17:29:06 +0200 Subject: [PATCH] Fix deserializing None QueryParameters (#9029) For None parameters, the back-end does not return the parameter value in response. This commit adjusts the ScalarQueryParameter's method from_api_repr(). --- bigquery/google/cloud/bigquery/query.py | 11 +++++++++-- bigquery/tests/unit/test_query.py | 9 +++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/bigquery/google/cloud/bigquery/query.py b/bigquery/google/cloud/bigquery/query.py index 726b598d3aaf9..4039be33db8cc 100644 --- a/bigquery/google/cloud/bigquery/query.py +++ b/bigquery/google/cloud/bigquery/query.py @@ -126,8 +126,15 @@ def from_api_repr(cls, resource): """ name = resource.get("name") type_ = resource["parameterType"]["type"] - value = resource["parameterValue"]["value"] - converted = _QUERY_PARAMS_FROM_JSON[type_](value, None) + + # parameterValue might not be present if JSON resource originates + # from the back-end - the latter omits it for None values. + value = resource.get("parameterValue", {}).get("value") + if value is not None: + converted = _QUERY_PARAMS_FROM_JSON[type_](value, None) + else: + converted = None + return cls(name, type_, converted) def to_api_repr(self): diff --git a/bigquery/tests/unit/test_query.py b/bigquery/tests/unit/test_query.py index 896ab78e3024f..a7c639ed1e777 100644 --- a/bigquery/tests/unit/test_query.py +++ b/bigquery/tests/unit/test_query.py @@ -121,6 +121,15 @@ def test_from_api_repr_wo_name(self): self.assertEqual(param.type_, "INT64") self.assertEqual(param.value, 123) + def test_from_api_repr_wo_value(self): + # Back-end may not send back values for None params. See #9027 + RESOURCE = {"name": "foo", "parameterType": {"type": "INT64"}} + klass = self._get_target_class() + param = klass.from_api_repr(RESOURCE) + self.assertEqual(param.name, "foo") + self.assertEqual(param.type_, "INT64") + self.assertIs(param.value, None) + def test_to_api_repr_w_name(self): EXPECTED = { "name": "foo",