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

feat: support ScalarQueryParameterType for type_ argument in ScalarQueryParameter constructor #850

Merged
merged 7 commits into from Aug 11, 2021
1 change: 1 addition & 0 deletions docs/conf.py
Expand Up @@ -110,6 +110,7 @@
# directories to ignore when looking for source files.
exclude_patterns = [
"_build",
"**/.nox/**/*",
plamut marked this conversation as resolved.
Show resolved Hide resolved
"samples/AUTHORING_GUIDE.md",
"samples/CONTRIBUTING.md",
"samples/snippets/README.rst",
Expand Down
1 change: 1 addition & 0 deletions docs/reference.rst
Expand Up @@ -137,6 +137,7 @@ Query

query.ArrayQueryParameter
query.ScalarQueryParameter
query.ScalarQueryParameterType
query.StructQueryParameter
query.UDFResource

Expand Down
24 changes: 12 additions & 12 deletions google/cloud/bigquery/enums.py
Expand Up @@ -259,23 +259,23 @@ class SqlTypeNames(str, enum.Enum):
class SqlParameterScalarTypes:
"""Supported scalar SQL query parameter types as type objects."""

STRING = ScalarQueryParameterType("STRING")
BOOL = ScalarQueryParameterType("BOOL")
BOOLEAN = ScalarQueryParameterType("BOOL")
BIGDECIMAL = ScalarQueryParameterType("BIGNUMERIC")
BIGNUMERIC = ScalarQueryParameterType("BIGNUMERIC")
BYTES = ScalarQueryParameterType("BYTES")
INTEGER = ScalarQueryParameterType("INT64")
INT64 = ScalarQueryParameterType("INT64")
DATE = ScalarQueryParameterType("DATE")
DATETIME = ScalarQueryParameterType("DATETIME")
DECIMAL = ScalarQueryParameterType("NUMERIC")
FLOAT = ScalarQueryParameterType("FLOAT64")
FLOAT64 = ScalarQueryParameterType("FLOAT64")
NUMERIC = ScalarQueryParameterType("NUMERIC")
BIGNUMERIC = ScalarQueryParameterType("BIGNUMERIC")
DECIMAL = ScalarQueryParameterType("NUMERIC")
BIGDECIMAL = ScalarQueryParameterType("BIGNUMERIC")
BOOLEAN = ScalarQueryParameterType("BOOL")
BOOL = ScalarQueryParameterType("BOOL")
GEOGRAPHY = ScalarQueryParameterType("GEOGRAPHY")
TIMESTAMP = ScalarQueryParameterType("TIMESTAMP")
DATE = ScalarQueryParameterType("DATE")
INT64 = ScalarQueryParameterType("INT64")
INTEGER = ScalarQueryParameterType("INT64")
NUMERIC = ScalarQueryParameterType("NUMERIC")
STRING = ScalarQueryParameterType("STRING")
TIME = ScalarQueryParameterType("TIME")
DATETIME = ScalarQueryParameterType("DATETIME")
TIMESTAMP = ScalarQueryParameterType("TIMESTAMP")
Copy link
Contributor

@plamut plamut Aug 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't INTERVAL too a scalar? Or why don't we include it here in this class?

(can also be done in the #840 if out of scope here)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can't actually at the moment. When I tried in a system test, I got a backend error. The team is aware and fixing it in internal issue 195050789



class WriteDisposition(object):
Expand Down
42 changes: 30 additions & 12 deletions google/cloud/bigquery/query.py
Expand Up @@ -16,14 +16,21 @@

from collections import OrderedDict
import copy
from typing import Union
import datetime
import decimal
from typing import Optional, Union

from google.cloud.bigquery.table import _parse_schema_resource
from google.cloud.bigquery._helpers import _rows_from_json
from google.cloud.bigquery._helpers import _QUERY_PARAMS_FROM_JSON
from google.cloud.bigquery._helpers import _SCALAR_VALUE_TO_JSON_PARAM


_SCALAR_VALUE_TYPES = Optional[
Union[str, int, float, decimal.Decimal, bool, datetime.datetime, datetime.date]
]
plamut marked this conversation as resolved.
Show resolved Hide resolved


class UDFResource(object):
"""Describe a single user-defined function (UDF) resource.

Expand Down Expand Up @@ -325,35 +332,46 @@ class ScalarQueryParameter(_AbstractQueryParameter):
"""Named / positional query parameters for scalar values.

Args:
name (Optional[str]):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the type annotations in the actual method signature, these are unnecessary.

Screen Shot 2021-08-03 at 3 46 15 PM

name:
Parameter name, used via ``@foo`` syntax. If None, the
parameter can only be addressed via position (``?``).

type_ (str):
Name of parameter type. One of 'STRING', 'INT64',
'FLOAT64', 'NUMERIC', 'BIGNUMERIC', 'BOOL', 'TIMESTAMP', 'DATETIME', or
'DATE'.
type_:
Name of parameter type. See
:class:`google.cloud.bigquery.enums.SqlTypeNames` and
:class:`google.cloud.bigquery.enums.SqlParameterScalarTypes` for
supported types.

value (Union[str, int, float, decimal.Decimal, bool, datetime.datetime, datetime.date]):
value:
The scalar parameter value.
"""

def __init__(self, name, type_, value):
def __init__(
self,
name: Optional[str],
type_: Optional[Union[str, ScalarQueryParameterType]],
value: _SCALAR_VALUE_TYPES,
):
self.name = name
self.type_ = type_
if isinstance(type_, ScalarQueryParameterType):
self.type_ = type_._type
else:
self.type_ = type_
self.value = value

@classmethod
def positional(cls, type_: str, value) -> "ScalarQueryParameter":
def positional(
cls, type_: Union[str, ScalarQueryParameterType], value: _SCALAR_VALUE_TYPES
) -> "ScalarQueryParameter":
"""Factory for positional paramater.

Args:
type_ (str):
type_:
Name of parameter type. One of 'STRING', 'INT64',
'FLOAT64', 'NUMERIC', 'BIGNUMERIC', 'BOOL', 'TIMESTAMP', 'DATETIME', or
'DATE'.

value (Union[str, int, float, decimal.Decimal, bool, datetime.datetime, datetime.date]):
value:
The scalar parameter value.

Returns:
Expand Down
13 changes: 13 additions & 0 deletions tests/unit/test_query.py
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.

import datetime
import decimal
import unittest

import mock
Expand Down Expand Up @@ -430,6 +431,18 @@ def test_positional(self):
self.assertEqual(param.type_, "INT64")
self.assertEqual(param.value, 123)

def test_ctor_w_scalar_query_parameter_type(self):
from google.cloud.bigquery import enums

param = self._make_one(
name="foo",
type_=enums.SqlParameterScalarTypes.BIGNUMERIC,
value=decimal.Decimal("123.456"),
)
self.assertEqual(param.name, "foo")
self.assertEqual(param.type_, "BIGNUMERIC")
self.assertEqual(param.value, decimal.Decimal("123.456"))

def test_from_api_repr_w_name(self):
RESOURCE = {
"name": "foo",
Expand Down