Skip to content

Commit 8f2941f

Browse files
tseavertswast
authored andcommitted
Add 'QueryJob.undeclared_query_parameters' property. (#3802)
1 parent d20afc4 commit 8f2941f

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

bigquery/google/cloud/bigquery/job.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
from google.cloud.bigquery.table import Table
2929
from google.cloud.bigquery.table import _build_schema_resource
3030
from google.cloud.bigquery.table import _parse_schema_resource
31+
from google.cloud.bigquery._helpers import ArrayQueryParameter
3132
from google.cloud.bigquery._helpers import QueryParametersProperty
33+
from google.cloud.bigquery._helpers import ScalarQueryParameter
34+
from google.cloud.bigquery._helpers import StructQueryParameter
3235
from google.cloud.bigquery._helpers import UDFResourcesProperty
3336
from google.cloud.bigquery._helpers import _EnumProperty
3437
from google.cloud.bigquery._helpers import _TypedProperty
@@ -1417,6 +1420,36 @@ def referenced_tables(self):
14171420

14181421
return tables
14191422

1423+
@property
1424+
def undeclared_query_paramters(self):
1425+
"""Return undeclared query parameters from job statistics, if present.
1426+
1427+
See:
1428+
https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs#statistics.query.undeclaredQueryParamters
1429+
1430+
:rtype:
1431+
list of
1432+
:class:`~google.cloud.bigquery._helpers.AbstractQueryParameter`
1433+
:returns: undeclared parameters, or an empty list if the query has
1434+
not yet completed.
1435+
"""
1436+
parameters = []
1437+
undeclared = self._job_statistics().get('undeclaredQueryParamters', ())
1438+
1439+
for parameter in undeclared:
1440+
p_type = parameter['parameterType']
1441+
1442+
if 'arrayType' in p_type:
1443+
klass = ArrayQueryParameter
1444+
elif 'structTypes' in p_type:
1445+
klass = StructQueryParameter
1446+
else:
1447+
klass = ScalarQueryParameter
1448+
1449+
parameters.append(klass.from_api_repr(parameter))
1450+
1451+
return parameters
1452+
14201453
def query_results(self):
14211454
"""Construct a QueryResults instance, bound to this job.
14221455

bigquery/tests/unit/test_job.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,6 +1887,81 @@ def test_referenced_tables(self):
18871887
self.assertEqual(remote.project, 'other-project-123')
18881888
self.assertIs(remote._dataset._client, client)
18891889

1890+
def test_undeclared_query_paramters(self):
1891+
from google.cloud.bigquery._helpers import ArrayQueryParameter
1892+
from google.cloud.bigquery._helpers import ScalarQueryParameter
1893+
from google.cloud.bigquery._helpers import StructQueryParameter
1894+
1895+
undeclared = [{
1896+
'name': 'my_scalar',
1897+
'parameterType': {
1898+
'type': 'STRING',
1899+
},
1900+
'parameterValue': {
1901+
'value': 'value',
1902+
},
1903+
}, {
1904+
'name': 'my_array',
1905+
'parameterType': {
1906+
'type': 'ARRAY',
1907+
'arrayType': {
1908+
'type': 'INT64',
1909+
},
1910+
},
1911+
'parameterValue': {
1912+
'arrayValues': [
1913+
{'value': '1066'},
1914+
{'value': '1745'},
1915+
],
1916+
},
1917+
}, {
1918+
'name': 'my_struct',
1919+
'parameterType': {
1920+
'type': 'STRUCT',
1921+
'structTypes': [{
1922+
'name': 'count',
1923+
'type': {
1924+
'type': 'INT64',
1925+
}
1926+
}],
1927+
},
1928+
'parameterValue': {
1929+
'structValues': {
1930+
'count': {
1931+
'value': '123',
1932+
},
1933+
}
1934+
},
1935+
}]
1936+
client = _Client(self.PROJECT)
1937+
job = self._make_one(self.JOB_NAME, self.QUERY, client)
1938+
self.assertEqual(job.undeclared_query_paramters, [])
1939+
1940+
statistics = job._properties['statistics'] = {}
1941+
self.assertEqual(job.undeclared_query_paramters, [])
1942+
1943+
query_stats = statistics['query'] = {}
1944+
self.assertEqual(job.undeclared_query_paramters, [])
1945+
1946+
query_stats['undeclaredQueryParamters'] = undeclared
1947+
1948+
scalar, array, struct = job.undeclared_query_paramters
1949+
1950+
self.assertIsInstance(scalar, ScalarQueryParameter)
1951+
self.assertEqual(scalar.name, 'my_scalar')
1952+
self.assertEqual(scalar.type_, 'STRING')
1953+
self.assertEqual(scalar.value, 'value')
1954+
1955+
self.assertIsInstance(array, ArrayQueryParameter)
1956+
self.assertEqual(array.name, 'my_array')
1957+
self.assertEqual(array.array_type, 'INT64')
1958+
self.assertEqual(array.values, [1066, 1745])
1959+
1960+
self.assertIsInstance(struct, StructQueryParameter)
1961+
self.assertEqual(struct.name, 'my_struct')
1962+
self.assertEqual(struct.struct_types, {'count': 'INT64'})
1963+
self.assertEqual(struct.struct_values, {'count': 123})
1964+
18901965
def test_query_results(self):
18911966
from google.cloud.bigquery.query import QueryResults
18921967

0 commit comments

Comments
 (0)