Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for query parameters #2776

Merged
merged 20 commits into from
Dec 2, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions bigquery/google/cloud/bigquery/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,66 @@ def _build_udf_resources(resources):
udf = {resource.udf_type: resource.value}
udfs.append(udf)
return udfs


class ScalarQueryParameter(object):
"""Named / positional query parameters for scalar values.

:type name: str or None

This comment was marked as spam.

:param name: Parameter name, used via `@foo` syntax. If None, the

This comment was marked as spam.

This comment was marked as spam.

paramter can only be addressed via position (`?`).

This comment was marked as spam.


:type type_: str
:param type_: name of parameter type. One of `'STRING'`, `'INT64'`,
`'FLOAT64'`, `'BOOLEAN'`, `'TIMESTAMP'`, or `'DATE'`.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.


:type value: str, int, float, bool, :class:`datetime.datetime`, or
:class:`datetime.date`.
:param value: the scalar parameter value.
"""
def __init__(self, name, type_, value):

This comment was marked as spam.

This comment was marked as spam.

self.name = name
self.type_ = type_
self.value = value

@classmethod
def positional(cls, type_, value):
"""Factory for positional paramters.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.


:type type_: str
:param type_: name of paramter type. One of `'STRING'`, `'INT64'`,
`'FLOAT64'`, `'BOOLEAN'`, `'TIMESTAMP'`, or `'DATE'`.

:type value: str, int, float, bool, :class:`datetime.datetime`, or
:class:`datetime.date`.
:param value: the scalar parameter value.
"""
return cls(None, type_, value)

@classmethod
def from_api_repr(cls, resource):
"""Factory: construct paramter from JSON resource.

:type resource: dict
:param resource: JSON mapping of parameter
"""
name = resource.get('name')
type_ = resource['parameterType']['type']
value = resource['parameterValue']['value']

This comment was marked as spam.

converted = _CELLDATA_FROM_JSON[type_](value, None)
return cls(name, type_, converted)

def to_api_repr(self):
"""Construct JSON API representation for the parameter."""
resource = {
'parameterType': {
'type': self.type_,
},
'parameterValue': {
'value': self.value,
},
}
if self.name is not None:
resource['name'] = self.name
return resource
81 changes: 81 additions & 0 deletions bigquery/unit_tests/test__helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,87 @@ def test_instance_setter_w_bad_udfs(self):
self.assertEqual(instance.udf_resources, [])


class Test_ScalarQueryParameter(unittest.TestCase):

@staticmethod
def _get_target_class():
from google.cloud.bigquery._helpers import ScalarQueryParameter
return ScalarQueryParameter

def _make_one(self, *args, **kw):
return self._get_target_class()(*args, **kw)

def test_ctor_scalar(self):
parm = self._make_one(name='foo', type_='INT64', value=123)
self.assertEqual(parm.name, 'foo')
self.assertEqual(parm.type_, 'INT64')
self.assertEqual(parm.value, 123)

def test_positional_scalar(self):
klass = self._get_target_class()
parm = klass.positional(type_='INT64', value=123)
self.assertEqual(parm.name, None)
self.assertEqual(parm.type_, 'INT64')
self.assertEqual(parm.value, 123)

def test_from_api_repr_w_name(self):
RESOURCE = {
'name': 'foo',
'parameterType': {
'type': 'INT64',
},
'parameterValue': {
'value': 123,
},
}
klass = self._get_target_class()
parm = klass.from_api_repr(RESOURCE)
self.assertEqual(parm.name, 'foo')
self.assertEqual(parm.type_, 'INT64')
self.assertEqual(parm.value, 123)

def test_from_api_repr_wo_name(self):
RESOURCE = {
'parameterType': {
'type': 'INT64',
},
'parameterValue': {
'value': 123,
},
}
klass = self._get_target_class()
parm = klass.from_api_repr(RESOURCE)
self.assertEqual(parm.name, None)
self.assertEqual(parm.type_, 'INT64')
self.assertEqual(parm.value, 123)

def test_to_api_repr_w_name(self):
EXPECTED = {
'name': 'foo',
'parameterType': {
'type': 'INT64',
},
'parameterValue': {
'value': 123,
},
}
parm = self._make_one(name='foo', type_='INT64', value=123)
self.assertEqual(parm.to_api_repr(), EXPECTED)

def test_to_api_repr_wo_name(self):
EXPECTED = {
'parameterType': {
'type': 'INT64',
},
'parameterValue': {
'value': 123,
},
}
klass = self._get_target_class()
parm = klass.positional(type_='INT64', value=123)
self.assertEqual(parm.to_api_repr(), EXPECTED)


class _Field(object):

def __init__(self, mode, name='unknown', field_type='UNKNOWN', fields=()):
Expand Down