google-cloud-bigquery 3.31.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- google/cloud/bigquery/__init__.py +249 -0
- google/cloud/bigquery/_helpers.py +1102 -0
- google/cloud/bigquery/_http.py +47 -0
- google/cloud/bigquery/_job_helpers.py +600 -0
- google/cloud/bigquery/_pandas_helpers.py +1181 -0
- google/cloud/bigquery/_pyarrow_helpers.py +147 -0
- google/cloud/bigquery/_tqdm_helpers.py +137 -0
- google/cloud/bigquery/_versions_helpers.py +264 -0
- google/cloud/bigquery/client.py +4406 -0
- google/cloud/bigquery/dataset.py +1076 -0
- google/cloud/bigquery/dbapi/__init__.py +87 -0
- google/cloud/bigquery/dbapi/_helpers.py +522 -0
- google/cloud/bigquery/dbapi/connection.py +128 -0
- google/cloud/bigquery/dbapi/cursor.py +586 -0
- google/cloud/bigquery/dbapi/exceptions.py +58 -0
- google/cloud/bigquery/dbapi/types.py +96 -0
- google/cloud/bigquery/encryption_configuration.py +84 -0
- google/cloud/bigquery/enums.py +389 -0
- google/cloud/bigquery/exceptions.py +35 -0
- google/cloud/bigquery/external_config.py +1188 -0
- google/cloud/bigquery/format_options.py +147 -0
- google/cloud/bigquery/iam.py +38 -0
- google/cloud/bigquery/job/__init__.py +87 -0
- google/cloud/bigquery/job/base.py +1116 -0
- google/cloud/bigquery/job/copy_.py +282 -0
- google/cloud/bigquery/job/extract.py +271 -0
- google/cloud/bigquery/job/load.py +985 -0
- google/cloud/bigquery/job/query.py +2498 -0
- google/cloud/bigquery/magics/__init__.py +20 -0
- google/cloud/bigquery/magics/line_arg_parser/__init__.py +34 -0
- google/cloud/bigquery/magics/line_arg_parser/exceptions.py +25 -0
- google/cloud/bigquery/magics/line_arg_parser/lexer.py +200 -0
- google/cloud/bigquery/magics/line_arg_parser/parser.py +484 -0
- google/cloud/bigquery/magics/line_arg_parser/visitors.py +159 -0
- google/cloud/bigquery/magics/magics.py +776 -0
- google/cloud/bigquery/model.py +517 -0
- google/cloud/bigquery/opentelemetry_tracing.py +164 -0
- google/cloud/bigquery/py.typed +2 -0
- google/cloud/bigquery/query.py +1344 -0
- google/cloud/bigquery/retry.py +207 -0
- google/cloud/bigquery/routine/__init__.py +33 -0
- google/cloud/bigquery/routine/routine.py +744 -0
- google/cloud/bigquery/schema.py +896 -0
- google/cloud/bigquery/standard_sql.py +389 -0
- google/cloud/bigquery/table.py +3594 -0
- google/cloud/bigquery/version.py +15 -0
- google/cloud/bigquery_v2/__init__.py +56 -0
- google/cloud/bigquery_v2/types/__init__.py +54 -0
- google/cloud/bigquery_v2/types/encryption_config.py +48 -0
- google/cloud/bigquery_v2/types/model.py +1994 -0
- google/cloud/bigquery_v2/types/model_reference.py +57 -0
- google/cloud/bigquery_v2/types/standard_sql.py +156 -0
- google/cloud/bigquery_v2/types/table_reference.py +80 -0
- google_cloud_bigquery-3.31.0.dist-info/LICENSE +202 -0
- google_cloud_bigquery-3.31.0.dist-info/METADATA +203 -0
- google_cloud_bigquery-3.31.0.dist-info/RECORD +58 -0
- google_cloud_bigquery-3.31.0.dist-info/WHEEL +5 -0
- google_cloud_bigquery-3.31.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Copyright 2017 Google LLC
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Google BigQuery implementation of the Database API Specification v2.0.
|
|
16
|
+
|
|
17
|
+
This module implements the `Python Database API Specification v2.0 (DB-API)`_
|
|
18
|
+
for Google BigQuery.
|
|
19
|
+
|
|
20
|
+
.. _Python Database API Specification v2.0 (DB-API):
|
|
21
|
+
https://www.python.org/dev/peps/pep-0249/
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from google.cloud.bigquery.dbapi.connection import connect
|
|
25
|
+
from google.cloud.bigquery.dbapi.connection import Connection
|
|
26
|
+
from google.cloud.bigquery.dbapi.cursor import Cursor
|
|
27
|
+
from google.cloud.bigquery.dbapi.exceptions import Warning
|
|
28
|
+
from google.cloud.bigquery.dbapi.exceptions import Error
|
|
29
|
+
from google.cloud.bigquery.dbapi.exceptions import InterfaceError
|
|
30
|
+
from google.cloud.bigquery.dbapi.exceptions import DatabaseError
|
|
31
|
+
from google.cloud.bigquery.dbapi.exceptions import DataError
|
|
32
|
+
from google.cloud.bigquery.dbapi.exceptions import OperationalError
|
|
33
|
+
from google.cloud.bigquery.dbapi.exceptions import IntegrityError
|
|
34
|
+
from google.cloud.bigquery.dbapi.exceptions import InternalError
|
|
35
|
+
from google.cloud.bigquery.dbapi.exceptions import ProgrammingError
|
|
36
|
+
from google.cloud.bigquery.dbapi.exceptions import NotSupportedError
|
|
37
|
+
from google.cloud.bigquery.dbapi.types import Binary
|
|
38
|
+
from google.cloud.bigquery.dbapi.types import Date
|
|
39
|
+
from google.cloud.bigquery.dbapi.types import DateFromTicks
|
|
40
|
+
from google.cloud.bigquery.dbapi.types import Time
|
|
41
|
+
from google.cloud.bigquery.dbapi.types import TimeFromTicks
|
|
42
|
+
from google.cloud.bigquery.dbapi.types import Timestamp
|
|
43
|
+
from google.cloud.bigquery.dbapi.types import TimestampFromTicks
|
|
44
|
+
from google.cloud.bigquery.dbapi.types import BINARY
|
|
45
|
+
from google.cloud.bigquery.dbapi.types import DATETIME
|
|
46
|
+
from google.cloud.bigquery.dbapi.types import NUMBER
|
|
47
|
+
from google.cloud.bigquery.dbapi.types import ROWID
|
|
48
|
+
from google.cloud.bigquery.dbapi.types import STRING
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
apilevel = "2.0"
|
|
52
|
+
|
|
53
|
+
# Threads may share the module and connections, but not cursors.
|
|
54
|
+
threadsafety = 2
|
|
55
|
+
|
|
56
|
+
paramstyle = "pyformat"
|
|
57
|
+
|
|
58
|
+
__all__ = [
|
|
59
|
+
"apilevel",
|
|
60
|
+
"threadsafety",
|
|
61
|
+
"paramstyle",
|
|
62
|
+
"connect",
|
|
63
|
+
"Connection",
|
|
64
|
+
"Cursor",
|
|
65
|
+
"Warning",
|
|
66
|
+
"Error",
|
|
67
|
+
"InterfaceError",
|
|
68
|
+
"DatabaseError",
|
|
69
|
+
"DataError",
|
|
70
|
+
"OperationalError",
|
|
71
|
+
"IntegrityError",
|
|
72
|
+
"InternalError",
|
|
73
|
+
"ProgrammingError",
|
|
74
|
+
"NotSupportedError",
|
|
75
|
+
"Binary",
|
|
76
|
+
"Date",
|
|
77
|
+
"DateFromTicks",
|
|
78
|
+
"Time",
|
|
79
|
+
"TimeFromTicks",
|
|
80
|
+
"Timestamp",
|
|
81
|
+
"TimestampFromTicks",
|
|
82
|
+
"BINARY",
|
|
83
|
+
"DATETIME",
|
|
84
|
+
"NUMBER",
|
|
85
|
+
"ROWID",
|
|
86
|
+
"STRING",
|
|
87
|
+
]
|
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
# Copyright 2017 Google LLC
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
from collections import abc as collections_abc
|
|
17
|
+
import datetime
|
|
18
|
+
import decimal
|
|
19
|
+
import functools
|
|
20
|
+
import numbers
|
|
21
|
+
import re
|
|
22
|
+
import typing
|
|
23
|
+
|
|
24
|
+
from google.cloud import bigquery
|
|
25
|
+
from google.cloud.bigquery import table, query
|
|
26
|
+
from google.cloud.bigquery.dbapi import exceptions
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
_NUMERIC_SERVER_MIN = decimal.Decimal("-9.9999999999999999999999999999999999999E+28")
|
|
30
|
+
_NUMERIC_SERVER_MAX = decimal.Decimal("9.9999999999999999999999999999999999999E+28")
|
|
31
|
+
|
|
32
|
+
type_parameters_re = re.compile(
|
|
33
|
+
r"""
|
|
34
|
+
\(
|
|
35
|
+
\s*[0-9]+\s*
|
|
36
|
+
(,
|
|
37
|
+
\s*[0-9]+\s*
|
|
38
|
+
)*
|
|
39
|
+
\)
|
|
40
|
+
""",
|
|
41
|
+
re.VERBOSE,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _parameter_type(name, value, query_parameter_type=None, value_doc=""):
|
|
46
|
+
if query_parameter_type:
|
|
47
|
+
# Strip type parameters
|
|
48
|
+
query_parameter_type = type_parameters_re.sub("", query_parameter_type)
|
|
49
|
+
try:
|
|
50
|
+
parameter_type = getattr(
|
|
51
|
+
query.SqlParameterScalarTypes, query_parameter_type.upper()
|
|
52
|
+
)._type
|
|
53
|
+
except AttributeError:
|
|
54
|
+
raise exceptions.ProgrammingError(
|
|
55
|
+
f"The given parameter type, {query_parameter_type},"
|
|
56
|
+
f" for {name} is not a valid BigQuery scalar type."
|
|
57
|
+
)
|
|
58
|
+
else:
|
|
59
|
+
parameter_type = bigquery_scalar_type(value)
|
|
60
|
+
if parameter_type is None:
|
|
61
|
+
raise exceptions.ProgrammingError(
|
|
62
|
+
f"Encountered parameter {name} with "
|
|
63
|
+
f"{value_doc} value {value} of unexpected type."
|
|
64
|
+
)
|
|
65
|
+
return parameter_type
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def scalar_to_query_parameter(value, name=None, query_parameter_type=None):
|
|
69
|
+
"""Convert a scalar value into a query parameter.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
value (Any):
|
|
73
|
+
A scalar value to convert into a query parameter.
|
|
74
|
+
|
|
75
|
+
name (str):
|
|
76
|
+
(Optional) Name of the query parameter.
|
|
77
|
+
query_parameter_type (Optional[str]): Given type for the parameter.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
google.cloud.bigquery.ScalarQueryParameter:
|
|
81
|
+
A query parameter corresponding with the type and value of the plain
|
|
82
|
+
Python object.
|
|
83
|
+
|
|
84
|
+
Raises:
|
|
85
|
+
google.cloud.bigquery.dbapi.exceptions.ProgrammingError:
|
|
86
|
+
if the type cannot be determined.
|
|
87
|
+
"""
|
|
88
|
+
return bigquery.ScalarQueryParameter(
|
|
89
|
+
name, _parameter_type(name, value, query_parameter_type), value
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def array_to_query_parameter(value, name=None, query_parameter_type=None):
|
|
94
|
+
"""Convert an array-like value into a query parameter.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
value (Sequence[Any]): The elements of the array (should not be a
|
|
98
|
+
string-like Sequence).
|
|
99
|
+
name (Optional[str]): Name of the query parameter.
|
|
100
|
+
query_parameter_type (Optional[str]): Given type for the parameter.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
A query parameter corresponding with the type and value of the plain
|
|
104
|
+
Python object.
|
|
105
|
+
|
|
106
|
+
Raises:
|
|
107
|
+
google.cloud.bigquery.dbapi.exceptions.ProgrammingError:
|
|
108
|
+
if the type of array elements cannot be determined.
|
|
109
|
+
"""
|
|
110
|
+
if not array_like(value):
|
|
111
|
+
raise exceptions.ProgrammingError(
|
|
112
|
+
"The value of parameter {} must be a sequence that is "
|
|
113
|
+
"not string-like.".format(name)
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
if query_parameter_type or value:
|
|
117
|
+
array_type = _parameter_type(
|
|
118
|
+
name,
|
|
119
|
+
value[0] if value else None,
|
|
120
|
+
query_parameter_type,
|
|
121
|
+
value_doc="array element ",
|
|
122
|
+
)
|
|
123
|
+
else:
|
|
124
|
+
raise exceptions.ProgrammingError(
|
|
125
|
+
"Encountered an empty array-like value of parameter {}, cannot "
|
|
126
|
+
"determine array elements type.".format(name)
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
return bigquery.ArrayQueryParameter(name, array_type, value)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _parse_struct_fields(
|
|
133
|
+
fields,
|
|
134
|
+
base,
|
|
135
|
+
parse_struct_field=re.compile(
|
|
136
|
+
r"""
|
|
137
|
+
(?:(\w+)\s+) # field name
|
|
138
|
+
([A-Z0-9<> ,()]+) # Field type
|
|
139
|
+
$""",
|
|
140
|
+
re.VERBOSE | re.IGNORECASE,
|
|
141
|
+
).match,
|
|
142
|
+
):
|
|
143
|
+
# Split a string of struct fields. They're defined by commas, but
|
|
144
|
+
# we have to avoid splitting on commas internal to fields. For
|
|
145
|
+
# example:
|
|
146
|
+
# name string, children array<struct<name string, bdate date>>
|
|
147
|
+
#
|
|
148
|
+
# only has 2 top-level fields.
|
|
149
|
+
fields = fields.split(",")
|
|
150
|
+
fields = list(reversed(fields)) # in the off chance that there are very many
|
|
151
|
+
while fields:
|
|
152
|
+
field = fields.pop()
|
|
153
|
+
while fields and field.count("<") != field.count(">"):
|
|
154
|
+
field += "," + fields.pop()
|
|
155
|
+
|
|
156
|
+
m = parse_struct_field(field.strip())
|
|
157
|
+
if not m:
|
|
158
|
+
raise exceptions.ProgrammingError(
|
|
159
|
+
f"Invalid struct field, {field}, in {base}"
|
|
160
|
+
)
|
|
161
|
+
yield m.group(1, 2)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
SCALAR, ARRAY, STRUCT = ("s", "a", "r")
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _parse_type(
|
|
168
|
+
type_,
|
|
169
|
+
name,
|
|
170
|
+
base,
|
|
171
|
+
complex_query_parameter_parse=re.compile(
|
|
172
|
+
r"""
|
|
173
|
+
\s*
|
|
174
|
+
(ARRAY|STRUCT|RECORD) # Type
|
|
175
|
+
\s*
|
|
176
|
+
<([A-Z0-9_<> ,()]+)> # Subtype(s)
|
|
177
|
+
\s*$
|
|
178
|
+
""",
|
|
179
|
+
re.IGNORECASE | re.VERBOSE,
|
|
180
|
+
).match,
|
|
181
|
+
):
|
|
182
|
+
if "<" not in type_:
|
|
183
|
+
# Scalar
|
|
184
|
+
|
|
185
|
+
# Strip type parameters
|
|
186
|
+
type_ = type_parameters_re.sub("", type_).strip()
|
|
187
|
+
try:
|
|
188
|
+
type_ = getattr(query.SqlParameterScalarTypes, type_.upper())
|
|
189
|
+
except AttributeError:
|
|
190
|
+
raise exceptions.ProgrammingError(
|
|
191
|
+
f"The given parameter type, {type_},"
|
|
192
|
+
f"{' for ' + name if name else ''}"
|
|
193
|
+
f" is not a valid BigQuery scalar type, in {base}."
|
|
194
|
+
)
|
|
195
|
+
if name:
|
|
196
|
+
type_ = type_.with_name(name)
|
|
197
|
+
return SCALAR, type_
|
|
198
|
+
|
|
199
|
+
m = complex_query_parameter_parse(type_)
|
|
200
|
+
if not m:
|
|
201
|
+
raise exceptions.ProgrammingError(f"Invalid parameter type, {type_}")
|
|
202
|
+
tname, sub = m.group(1, 2)
|
|
203
|
+
if tname.upper() == "ARRAY":
|
|
204
|
+
sub_type = complex_query_parameter_type(None, sub, base)
|
|
205
|
+
if isinstance(sub_type, query.ArrayQueryParameterType):
|
|
206
|
+
raise exceptions.ProgrammingError(f"Array can't contain an array in {base}")
|
|
207
|
+
sub_type._complex__src = sub
|
|
208
|
+
return ARRAY, sub_type
|
|
209
|
+
else:
|
|
210
|
+
return STRUCT, _parse_struct_fields(sub, base)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def complex_query_parameter_type(name: typing.Optional[str], type_: str, base: str):
|
|
214
|
+
"""Construct a parameter type (`StructQueryParameterType`) for a complex type
|
|
215
|
+
|
|
216
|
+
or a non-complex type that's part of a complex type.
|
|
217
|
+
|
|
218
|
+
Examples:
|
|
219
|
+
|
|
220
|
+
array<struct<x float64, y float64>>
|
|
221
|
+
|
|
222
|
+
struct<name string, children array<struct<name string, bdate date>>>
|
|
223
|
+
|
|
224
|
+
This is used for computing array types.
|
|
225
|
+
"""
|
|
226
|
+
|
|
227
|
+
type_type, sub_type = _parse_type(type_, name, base)
|
|
228
|
+
if type_type == SCALAR:
|
|
229
|
+
result_type = sub_type
|
|
230
|
+
elif type_type == ARRAY:
|
|
231
|
+
result_type = query.ArrayQueryParameterType(sub_type, name=name)
|
|
232
|
+
elif type_type == STRUCT:
|
|
233
|
+
fields = [
|
|
234
|
+
complex_query_parameter_type(field_name, field_type, base)
|
|
235
|
+
for field_name, field_type in sub_type
|
|
236
|
+
]
|
|
237
|
+
result_type = query.StructQueryParameterType(*fields, name=name)
|
|
238
|
+
else: # pragma: NO COVER
|
|
239
|
+
raise AssertionError("Bad type_type", type_type) # Can't happen :)
|
|
240
|
+
|
|
241
|
+
return result_type
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def complex_query_parameter(
|
|
245
|
+
name: typing.Optional[str], value, type_: str, base: typing.Optional[str] = None
|
|
246
|
+
):
|
|
247
|
+
"""
|
|
248
|
+
Construct a query parameter for a complex type (array or struct record)
|
|
249
|
+
|
|
250
|
+
or for a subtype, which may not be complex
|
|
251
|
+
|
|
252
|
+
Examples:
|
|
253
|
+
|
|
254
|
+
array<struct<x float64, y float64>>
|
|
255
|
+
|
|
256
|
+
struct<name string, children array<struct<name string, bdate date>>>
|
|
257
|
+
|
|
258
|
+
"""
|
|
259
|
+
param: typing.Union[
|
|
260
|
+
query.ScalarQueryParameter,
|
|
261
|
+
query.ArrayQueryParameter,
|
|
262
|
+
query.StructQueryParameter,
|
|
263
|
+
]
|
|
264
|
+
|
|
265
|
+
base = base or type_
|
|
266
|
+
|
|
267
|
+
type_type, sub_type = _parse_type(type_, name, base)
|
|
268
|
+
|
|
269
|
+
if type_type == SCALAR:
|
|
270
|
+
param = query.ScalarQueryParameter(name, sub_type._type, value)
|
|
271
|
+
elif type_type == ARRAY:
|
|
272
|
+
if not array_like(value):
|
|
273
|
+
raise exceptions.ProgrammingError(
|
|
274
|
+
f"Array type with non-array-like value"
|
|
275
|
+
f" with type {type(value).__name__}"
|
|
276
|
+
)
|
|
277
|
+
param = query.ArrayQueryParameter(
|
|
278
|
+
name,
|
|
279
|
+
sub_type,
|
|
280
|
+
(
|
|
281
|
+
value
|
|
282
|
+
if isinstance(sub_type, query.ScalarQueryParameterType)
|
|
283
|
+
else [
|
|
284
|
+
complex_query_parameter(None, v, sub_type._complex__src, base)
|
|
285
|
+
for v in value
|
|
286
|
+
]
|
|
287
|
+
),
|
|
288
|
+
)
|
|
289
|
+
elif type_type == STRUCT:
|
|
290
|
+
if not isinstance(value, collections_abc.Mapping):
|
|
291
|
+
raise exceptions.ProgrammingError(f"Non-mapping value for type {type_}")
|
|
292
|
+
value_keys = set(value)
|
|
293
|
+
fields = []
|
|
294
|
+
for field_name, field_type in sub_type:
|
|
295
|
+
if field_name not in value:
|
|
296
|
+
raise exceptions.ProgrammingError(
|
|
297
|
+
f"No field value for {field_name} in {type_}"
|
|
298
|
+
)
|
|
299
|
+
value_keys.remove(field_name)
|
|
300
|
+
fields.append(
|
|
301
|
+
complex_query_parameter(field_name, value[field_name], field_type, base)
|
|
302
|
+
)
|
|
303
|
+
if value_keys:
|
|
304
|
+
raise exceptions.ProgrammingError(f"Extra data keys for {type_}")
|
|
305
|
+
|
|
306
|
+
param = query.StructQueryParameter(name, *fields)
|
|
307
|
+
else: # pragma: NO COVER
|
|
308
|
+
raise AssertionError("Bad type_type", type_type) # Can't happen :)
|
|
309
|
+
|
|
310
|
+
return param
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def _dispatch_parameter(type_, value, name=None):
|
|
314
|
+
if type_ is not None and "<" in type_:
|
|
315
|
+
param = complex_query_parameter(name, value, type_)
|
|
316
|
+
elif isinstance(value, collections_abc.Mapping):
|
|
317
|
+
raise NotImplementedError(
|
|
318
|
+
f"STRUCT-like parameter values are not supported"
|
|
319
|
+
f"{' (parameter ' + name + ')' if name else ''},"
|
|
320
|
+
f" unless an explicit type is give in the parameter placeholder"
|
|
321
|
+
f" (e.g. '%({name if name else ''}:struct<...>)s')."
|
|
322
|
+
)
|
|
323
|
+
elif array_like(value):
|
|
324
|
+
param = array_to_query_parameter(value, name, type_)
|
|
325
|
+
else:
|
|
326
|
+
param = scalar_to_query_parameter(value, name, type_)
|
|
327
|
+
|
|
328
|
+
return param
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def to_query_parameters_list(parameters, parameter_types):
|
|
332
|
+
"""Converts a sequence of parameter values into query parameters.
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
parameters (Sequence[Any]): Sequence of query parameter values.
|
|
336
|
+
parameter_types:
|
|
337
|
+
A list of parameter types, one for each parameter.
|
|
338
|
+
Unknown types are provided as None.
|
|
339
|
+
|
|
340
|
+
Returns:
|
|
341
|
+
List[google.cloud.bigquery.query._AbstractQueryParameter]:
|
|
342
|
+
A list of query parameters.
|
|
343
|
+
"""
|
|
344
|
+
return [
|
|
345
|
+
_dispatch_parameter(type_, value)
|
|
346
|
+
for value, type_ in zip(parameters, parameter_types)
|
|
347
|
+
]
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def to_query_parameters_dict(parameters, query_parameter_types):
|
|
351
|
+
"""Converts a dictionary of parameter values into query parameters.
|
|
352
|
+
|
|
353
|
+
Args:
|
|
354
|
+
parameters (Mapping[str, Any]): Dictionary of query parameter values.
|
|
355
|
+
parameter_types:
|
|
356
|
+
A dictionary of parameter types. It needn't have a key for each
|
|
357
|
+
parameter.
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
List[google.cloud.bigquery.query._AbstractQueryParameter]:
|
|
361
|
+
A list of named query parameters.
|
|
362
|
+
"""
|
|
363
|
+
return [
|
|
364
|
+
_dispatch_parameter(query_parameter_types.get(name), value, name)
|
|
365
|
+
for name, value in parameters.items()
|
|
366
|
+
]
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def to_query_parameters(parameters, parameter_types):
|
|
370
|
+
"""Converts DB-API parameter values into query parameters.
|
|
371
|
+
|
|
372
|
+
Args:
|
|
373
|
+
parameters (Union[Mapping[str, Any], Sequence[Any]]):
|
|
374
|
+
A dictionary or sequence of query parameter values.
|
|
375
|
+
parameter_types (Union[Mapping[str, str], Sequence[str]]):
|
|
376
|
+
A dictionary or list of parameter types.
|
|
377
|
+
|
|
378
|
+
If parameters is a mapping, then this must be a dictionary
|
|
379
|
+
of parameter types. It needn't have a key for each
|
|
380
|
+
parameter.
|
|
381
|
+
|
|
382
|
+
If parameters is a sequence, then this must be a list of
|
|
383
|
+
parameter types, one for each paramater. Unknown types
|
|
384
|
+
are provided as None.
|
|
385
|
+
|
|
386
|
+
Returns:
|
|
387
|
+
List[google.cloud.bigquery.query._AbstractQueryParameter]:
|
|
388
|
+
A list of query parameters.
|
|
389
|
+
"""
|
|
390
|
+
if parameters is None:
|
|
391
|
+
return []
|
|
392
|
+
|
|
393
|
+
if isinstance(parameters, collections_abc.Mapping):
|
|
394
|
+
return to_query_parameters_dict(parameters, parameter_types)
|
|
395
|
+
else:
|
|
396
|
+
return to_query_parameters_list(parameters, parameter_types)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def bigquery_scalar_type(value):
|
|
400
|
+
"""Return a BigQuery name of the scalar type that matches the given value.
|
|
401
|
+
|
|
402
|
+
If the scalar type name could not be determined (e.g. for non-scalar
|
|
403
|
+
values), ``None`` is returned.
|
|
404
|
+
|
|
405
|
+
Args:
|
|
406
|
+
value (Any)
|
|
407
|
+
|
|
408
|
+
Returns:
|
|
409
|
+
Optional[str]: The BigQuery scalar type name.
|
|
410
|
+
"""
|
|
411
|
+
if isinstance(value, bool):
|
|
412
|
+
return "BOOL"
|
|
413
|
+
elif isinstance(value, numbers.Integral):
|
|
414
|
+
return "INT64"
|
|
415
|
+
elif isinstance(value, numbers.Real):
|
|
416
|
+
return "FLOAT64"
|
|
417
|
+
elif isinstance(value, decimal.Decimal):
|
|
418
|
+
vtuple = value.as_tuple()
|
|
419
|
+
# NUMERIC values have precision of 38 (number of digits) and scale of 9 (number
|
|
420
|
+
# of fractional digits), and their max absolute value must be strictly smaller
|
|
421
|
+
# than 1.0E+29.
|
|
422
|
+
# https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#decimal_types
|
|
423
|
+
if (
|
|
424
|
+
len(vtuple.digits) <= 38 # max precision: 38
|
|
425
|
+
and vtuple.exponent >= -9 # max scale: 9
|
|
426
|
+
and _NUMERIC_SERVER_MIN <= value <= _NUMERIC_SERVER_MAX
|
|
427
|
+
):
|
|
428
|
+
return "NUMERIC"
|
|
429
|
+
else:
|
|
430
|
+
return "BIGNUMERIC"
|
|
431
|
+
|
|
432
|
+
elif isinstance(value, str):
|
|
433
|
+
return "STRING"
|
|
434
|
+
elif isinstance(value, bytes):
|
|
435
|
+
return "BYTES"
|
|
436
|
+
elif isinstance(value, datetime.datetime):
|
|
437
|
+
return "DATETIME" if value.tzinfo is None else "TIMESTAMP"
|
|
438
|
+
elif isinstance(value, datetime.date):
|
|
439
|
+
return "DATE"
|
|
440
|
+
elif isinstance(value, datetime.time):
|
|
441
|
+
return "TIME"
|
|
442
|
+
|
|
443
|
+
return None
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def array_like(value):
|
|
447
|
+
"""Determine if the given value is array-like.
|
|
448
|
+
|
|
449
|
+
Examples of array-like values (as interpreted by this function) are
|
|
450
|
+
sequences such as ``list`` and ``tuple``, but not strings and other
|
|
451
|
+
iterables such as sets.
|
|
452
|
+
|
|
453
|
+
Args:
|
|
454
|
+
value (Any)
|
|
455
|
+
|
|
456
|
+
Returns:
|
|
457
|
+
bool: ``True`` if the value is considered array-like, ``False`` otherwise.
|
|
458
|
+
"""
|
|
459
|
+
return isinstance(value, collections_abc.Sequence) and not isinstance(
|
|
460
|
+
value, (str, bytes, bytearray)
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def to_bq_table_rows(rows_iterable):
|
|
465
|
+
"""Convert table rows to BigQuery table Row instances.
|
|
466
|
+
|
|
467
|
+
Args:
|
|
468
|
+
rows_iterable (Iterable[Mapping]):
|
|
469
|
+
An iterable of row data items to convert to ``Row`` instances.
|
|
470
|
+
|
|
471
|
+
Returns:
|
|
472
|
+
Iterable[google.cloud.bigquery.table.Row]
|
|
473
|
+
"""
|
|
474
|
+
|
|
475
|
+
def to_table_row(row):
|
|
476
|
+
# NOTE: We fetch ARROW values, thus we need to convert them to Python
|
|
477
|
+
# objects with as_py().
|
|
478
|
+
values = tuple(value.as_py() for value in row.values())
|
|
479
|
+
keys_to_index = {key: i for i, key in enumerate(row.keys())}
|
|
480
|
+
return table.Row(values, keys_to_index)
|
|
481
|
+
|
|
482
|
+
return (to_table_row(row_data) for row_data in rows_iterable)
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
def raise_on_closed(
|
|
486
|
+
exc_msg, exc_class=exceptions.ProgrammingError, closed_attr_name="_closed"
|
|
487
|
+
):
|
|
488
|
+
"""Make public instance methods raise an error if the instance is closed."""
|
|
489
|
+
|
|
490
|
+
def _raise_on_closed(method):
|
|
491
|
+
"""Make a non-static method raise an error if its containing instance is closed."""
|
|
492
|
+
|
|
493
|
+
def with_closed_check(self, *args, **kwargs):
|
|
494
|
+
if getattr(self, closed_attr_name):
|
|
495
|
+
raise exc_class(exc_msg)
|
|
496
|
+
return method(self, *args, **kwargs)
|
|
497
|
+
|
|
498
|
+
functools.update_wrapper(with_closed_check, method)
|
|
499
|
+
return with_closed_check
|
|
500
|
+
|
|
501
|
+
def decorate_public_methods(klass):
|
|
502
|
+
"""Apply ``_raise_on_closed()`` decorator to public instance methods."""
|
|
503
|
+
for name in dir(klass):
|
|
504
|
+
if name.startswith("_") and name != "__iter__":
|
|
505
|
+
continue
|
|
506
|
+
|
|
507
|
+
member = getattr(klass, name)
|
|
508
|
+
if not callable(member):
|
|
509
|
+
continue
|
|
510
|
+
|
|
511
|
+
# We need to check for class/static methods directly in the instance
|
|
512
|
+
# __dict__, not via the retrieved attribute (`member`), as the
|
|
513
|
+
# latter is already a callable *produced* by one of these descriptors.
|
|
514
|
+
if isinstance(klass.__dict__[name], (staticmethod, classmethod)):
|
|
515
|
+
continue
|
|
516
|
+
|
|
517
|
+
member = _raise_on_closed(member)
|
|
518
|
+
setattr(klass, name, member)
|
|
519
|
+
|
|
520
|
+
return klass
|
|
521
|
+
|
|
522
|
+
return decorate_public_methods
|