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,1076 @@
|
|
|
1
|
+
# Copyright 2015 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
|
+
"""Define API Datasets."""
|
|
16
|
+
|
|
17
|
+
from __future__ import absolute_import
|
|
18
|
+
|
|
19
|
+
import copy
|
|
20
|
+
|
|
21
|
+
import typing
|
|
22
|
+
|
|
23
|
+
import google.cloud._helpers # type: ignore
|
|
24
|
+
|
|
25
|
+
from google.cloud.bigquery import _helpers
|
|
26
|
+
from google.cloud.bigquery.model import ModelReference
|
|
27
|
+
from google.cloud.bigquery.routine import Routine, RoutineReference
|
|
28
|
+
from google.cloud.bigquery.table import Table, TableReference
|
|
29
|
+
from google.cloud.bigquery.encryption_configuration import EncryptionConfiguration
|
|
30
|
+
from google.cloud.bigquery import external_config
|
|
31
|
+
|
|
32
|
+
from typing import Optional, List, Dict, Any, Union
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _get_table_reference(self, table_id: str) -> TableReference:
|
|
36
|
+
"""Constructs a TableReference.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
table_id (str): The ID of the table.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
google.cloud.bigquery.table.TableReference:
|
|
43
|
+
A table reference for a table in this dataset.
|
|
44
|
+
"""
|
|
45
|
+
return TableReference(self, table_id)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _get_model_reference(self, model_id):
|
|
49
|
+
"""Constructs a ModelReference.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
model_id (str): the ID of the model.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
google.cloud.bigquery.model.ModelReference:
|
|
56
|
+
A ModelReference for a model in this dataset.
|
|
57
|
+
"""
|
|
58
|
+
return ModelReference.from_api_repr(
|
|
59
|
+
{"projectId": self.project, "datasetId": self.dataset_id, "modelId": model_id}
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _get_routine_reference(self, routine_id):
|
|
64
|
+
"""Constructs a RoutineReference.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
routine_id (str): the ID of the routine.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
google.cloud.bigquery.routine.RoutineReference:
|
|
71
|
+
A RoutineReference for a routine in this dataset.
|
|
72
|
+
"""
|
|
73
|
+
return RoutineReference.from_api_repr(
|
|
74
|
+
{
|
|
75
|
+
"projectId": self.project,
|
|
76
|
+
"datasetId": self.dataset_id,
|
|
77
|
+
"routineId": routine_id,
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class DatasetReference(object):
|
|
83
|
+
"""DatasetReferences are pointers to datasets.
|
|
84
|
+
|
|
85
|
+
See
|
|
86
|
+
https://cloud.google.com/bigquery/docs/reference/rest/v2/datasets#datasetreference
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
project (str): The ID of the project
|
|
90
|
+
dataset_id (str): The ID of the dataset
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
ValueError: If either argument is not of type ``str``.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
def __init__(self, project: str, dataset_id: str):
|
|
97
|
+
if not isinstance(project, str):
|
|
98
|
+
raise ValueError("Pass a string for project")
|
|
99
|
+
if not isinstance(dataset_id, str):
|
|
100
|
+
raise ValueError("Pass a string for dataset_id")
|
|
101
|
+
self._project = project
|
|
102
|
+
self._dataset_id = dataset_id
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def project(self):
|
|
106
|
+
"""str: Project ID of the dataset."""
|
|
107
|
+
return self._project
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def dataset_id(self):
|
|
111
|
+
"""str: Dataset ID."""
|
|
112
|
+
return self._dataset_id
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def path(self):
|
|
116
|
+
"""str: URL path for the dataset based on project and dataset ID."""
|
|
117
|
+
return "/projects/%s/datasets/%s" % (self.project, self.dataset_id)
|
|
118
|
+
|
|
119
|
+
table = _get_table_reference
|
|
120
|
+
|
|
121
|
+
model = _get_model_reference
|
|
122
|
+
|
|
123
|
+
routine = _get_routine_reference
|
|
124
|
+
|
|
125
|
+
@classmethod
|
|
126
|
+
def from_api_repr(cls, resource: dict) -> "DatasetReference":
|
|
127
|
+
"""Factory: construct a dataset reference given its API representation
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
resource (Dict[str, str]):
|
|
131
|
+
Dataset reference resource representation returned from the API
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
google.cloud.bigquery.dataset.DatasetReference:
|
|
135
|
+
Dataset reference parsed from ``resource``.
|
|
136
|
+
"""
|
|
137
|
+
project = resource["projectId"]
|
|
138
|
+
dataset_id = resource["datasetId"]
|
|
139
|
+
return cls(project, dataset_id)
|
|
140
|
+
|
|
141
|
+
@classmethod
|
|
142
|
+
def from_string(
|
|
143
|
+
cls, dataset_id: str, default_project: Optional[str] = None
|
|
144
|
+
) -> "DatasetReference":
|
|
145
|
+
"""Construct a dataset reference from dataset ID string.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
dataset_id (str):
|
|
149
|
+
A dataset ID in standard SQL format. If ``default_project``
|
|
150
|
+
is not specified, this must include both the project ID and
|
|
151
|
+
the dataset ID, separated by ``.``.
|
|
152
|
+
default_project (Optional[str]):
|
|
153
|
+
The project ID to use when ``dataset_id`` does not include a
|
|
154
|
+
project ID.
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
DatasetReference:
|
|
158
|
+
Dataset reference parsed from ``dataset_id``.
|
|
159
|
+
|
|
160
|
+
Examples:
|
|
161
|
+
>>> DatasetReference.from_string('my-project-id.some_dataset')
|
|
162
|
+
DatasetReference('my-project-id', 'some_dataset')
|
|
163
|
+
|
|
164
|
+
Raises:
|
|
165
|
+
ValueError:
|
|
166
|
+
If ``dataset_id`` is not a fully-qualified dataset ID in
|
|
167
|
+
standard SQL format.
|
|
168
|
+
"""
|
|
169
|
+
output_dataset_id = dataset_id
|
|
170
|
+
parts = _helpers._split_id(dataset_id)
|
|
171
|
+
|
|
172
|
+
if len(parts) == 1:
|
|
173
|
+
if default_project is not None:
|
|
174
|
+
output_project_id = default_project
|
|
175
|
+
else:
|
|
176
|
+
raise ValueError(
|
|
177
|
+
"When default_project is not set, dataset_id must be a "
|
|
178
|
+
"fully-qualified dataset ID in standard SQL format, "
|
|
179
|
+
'e.g., "project.dataset_id" got {}'.format(dataset_id)
|
|
180
|
+
)
|
|
181
|
+
elif len(parts) == 2:
|
|
182
|
+
output_project_id, output_dataset_id = parts
|
|
183
|
+
else:
|
|
184
|
+
raise ValueError(
|
|
185
|
+
"Too many parts in dataset_id. Expected a fully-qualified "
|
|
186
|
+
"dataset ID in standard SQL format, "
|
|
187
|
+
'e.g. "project.dataset_id", got {}'.format(dataset_id)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
return cls(output_project_id, output_dataset_id)
|
|
191
|
+
|
|
192
|
+
def to_api_repr(self) -> dict:
|
|
193
|
+
"""Construct the API resource representation of this dataset reference
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
Dict[str, str]: dataset reference represented as an API resource
|
|
197
|
+
"""
|
|
198
|
+
return {"projectId": self._project, "datasetId": self._dataset_id}
|
|
199
|
+
|
|
200
|
+
def _key(self):
|
|
201
|
+
"""A tuple key that uniquely describes this field.
|
|
202
|
+
|
|
203
|
+
Used to compute this instance's hashcode and evaluate equality.
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
Tuple[str]: The contents of this :class:`.DatasetReference`.
|
|
207
|
+
"""
|
|
208
|
+
return (self._project, self._dataset_id)
|
|
209
|
+
|
|
210
|
+
def __eq__(self, other):
|
|
211
|
+
if not isinstance(other, DatasetReference):
|
|
212
|
+
return NotImplemented
|
|
213
|
+
return self._key() == other._key()
|
|
214
|
+
|
|
215
|
+
def __ne__(self, other):
|
|
216
|
+
return not self == other
|
|
217
|
+
|
|
218
|
+
def __hash__(self):
|
|
219
|
+
return hash(self._key())
|
|
220
|
+
|
|
221
|
+
def __str__(self):
|
|
222
|
+
return f"{self.project}.{self._dataset_id}"
|
|
223
|
+
|
|
224
|
+
def __repr__(self):
|
|
225
|
+
return "DatasetReference{}".format(self._key())
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
class AccessEntry(object):
|
|
229
|
+
"""Represents grant of an access role to an entity.
|
|
230
|
+
|
|
231
|
+
An entry must have exactly one of the allowed
|
|
232
|
+
:class:`google.cloud.bigquery.enums.EntityTypes`. If anything but ``view``, ``routine``,
|
|
233
|
+
or ``dataset`` are set, a ``role`` is also required. ``role`` is omitted for ``view``,
|
|
234
|
+
``routine``, ``dataset``, because they are always read-only.
|
|
235
|
+
|
|
236
|
+
See https://cloud.google.com/bigquery/docs/reference/rest/v2/datasets.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
role:
|
|
240
|
+
Role granted to the entity. The following string values are
|
|
241
|
+
supported: `'READER'`, `'WRITER'`, `'OWNER'`. It may also be
|
|
242
|
+
:data:`None` if the ``entity_type`` is ``view``, ``routine``, or ``dataset``.
|
|
243
|
+
|
|
244
|
+
entity_type:
|
|
245
|
+
Type of entity being granted the role. See
|
|
246
|
+
:class:`google.cloud.bigquery.enums.EntityTypes` for supported types.
|
|
247
|
+
|
|
248
|
+
entity_id:
|
|
249
|
+
If the ``entity_type`` is not 'view', 'routine', or 'dataset', the
|
|
250
|
+
``entity_id`` is the ``str`` ID of the entity being granted the role. If
|
|
251
|
+
the ``entity_type`` is 'view' or 'routine', the ``entity_id`` is a ``dict``
|
|
252
|
+
representing the view or routine from a different dataset to grant access
|
|
253
|
+
to in the following format for views::
|
|
254
|
+
|
|
255
|
+
{
|
|
256
|
+
'projectId': string,
|
|
257
|
+
'datasetId': string,
|
|
258
|
+
'tableId': string
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
For routines::
|
|
262
|
+
|
|
263
|
+
{
|
|
264
|
+
'projectId': string,
|
|
265
|
+
'datasetId': string,
|
|
266
|
+
'routineId': string
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
If the ``entity_type`` is 'dataset', the ``entity_id`` is a ``dict`` that includes
|
|
270
|
+
a 'dataset' field with a ``dict`` representing the dataset and a 'target_types'
|
|
271
|
+
field with a ``str`` value of the dataset's resource type::
|
|
272
|
+
|
|
273
|
+
{
|
|
274
|
+
'dataset': {
|
|
275
|
+
'projectId': string,
|
|
276
|
+
'datasetId': string,
|
|
277
|
+
},
|
|
278
|
+
'target_types: 'VIEWS'
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
Raises:
|
|
282
|
+
ValueError:
|
|
283
|
+
If a ``view``, ``routine``, or ``dataset`` has ``role`` set, or a non ``view``,
|
|
284
|
+
non ``routine``, and non ``dataset`` **does not** have a ``role`` set.
|
|
285
|
+
|
|
286
|
+
Examples:
|
|
287
|
+
>>> entry = AccessEntry('OWNER', 'userByEmail', 'user@example.com')
|
|
288
|
+
|
|
289
|
+
>>> view = {
|
|
290
|
+
... 'projectId': 'my-project',
|
|
291
|
+
... 'datasetId': 'my_dataset',
|
|
292
|
+
... 'tableId': 'my_table'
|
|
293
|
+
... }
|
|
294
|
+
>>> entry = AccessEntry(None, 'view', view)
|
|
295
|
+
"""
|
|
296
|
+
|
|
297
|
+
def __init__(
|
|
298
|
+
self,
|
|
299
|
+
role: Optional[str] = None,
|
|
300
|
+
entity_type: Optional[str] = None,
|
|
301
|
+
entity_id: Optional[Union[Dict[str, Any], str]] = None,
|
|
302
|
+
):
|
|
303
|
+
self._properties = {}
|
|
304
|
+
if entity_type is not None:
|
|
305
|
+
self._properties[entity_type] = entity_id
|
|
306
|
+
self._properties["role"] = role
|
|
307
|
+
self._entity_type = entity_type
|
|
308
|
+
|
|
309
|
+
@property
|
|
310
|
+
def role(self) -> Optional[str]:
|
|
311
|
+
"""The role of the entry."""
|
|
312
|
+
return typing.cast(Optional[str], self._properties.get("role"))
|
|
313
|
+
|
|
314
|
+
@role.setter
|
|
315
|
+
def role(self, value):
|
|
316
|
+
self._properties["role"] = value
|
|
317
|
+
|
|
318
|
+
@property
|
|
319
|
+
def dataset(self) -> Optional[DatasetReference]:
|
|
320
|
+
"""API resource representation of a dataset reference."""
|
|
321
|
+
value = _helpers._get_sub_prop(self._properties, ["dataset", "dataset"])
|
|
322
|
+
return DatasetReference.from_api_repr(value) if value else None
|
|
323
|
+
|
|
324
|
+
@dataset.setter
|
|
325
|
+
def dataset(self, value):
|
|
326
|
+
if self.role is not None:
|
|
327
|
+
raise ValueError(
|
|
328
|
+
"Role must be None for a dataset. Current " "role: %r" % (self.role)
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
if isinstance(value, str):
|
|
332
|
+
value = DatasetReference.from_string(value).to_api_repr()
|
|
333
|
+
|
|
334
|
+
if isinstance(value, (Dataset, DatasetListItem)):
|
|
335
|
+
value = value.reference.to_api_repr()
|
|
336
|
+
|
|
337
|
+
_helpers._set_sub_prop(self._properties, ["dataset", "dataset"], value)
|
|
338
|
+
_helpers._set_sub_prop(
|
|
339
|
+
self._properties,
|
|
340
|
+
["dataset", "targetTypes"],
|
|
341
|
+
self._properties.get("targetTypes"),
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
@property
|
|
345
|
+
def dataset_target_types(self) -> Optional[List[str]]:
|
|
346
|
+
"""Which resources that the dataset in this entry applies to."""
|
|
347
|
+
return typing.cast(
|
|
348
|
+
Optional[List[str]],
|
|
349
|
+
_helpers._get_sub_prop(self._properties, ["dataset", "targetTypes"]),
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
@dataset_target_types.setter
|
|
353
|
+
def dataset_target_types(self, value):
|
|
354
|
+
self._properties.setdefault("dataset", {})
|
|
355
|
+
_helpers._set_sub_prop(self._properties, ["dataset", "targetTypes"], value)
|
|
356
|
+
|
|
357
|
+
@property
|
|
358
|
+
def routine(self) -> Optional[RoutineReference]:
|
|
359
|
+
"""API resource representation of a routine reference."""
|
|
360
|
+
value = typing.cast(Optional[Dict], self._properties.get("routine"))
|
|
361
|
+
return RoutineReference.from_api_repr(value) if value else None
|
|
362
|
+
|
|
363
|
+
@routine.setter
|
|
364
|
+
def routine(self, value):
|
|
365
|
+
if self.role is not None:
|
|
366
|
+
raise ValueError(
|
|
367
|
+
"Role must be None for a routine. Current " "role: %r" % (self.role)
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
if isinstance(value, str):
|
|
371
|
+
value = RoutineReference.from_string(value).to_api_repr()
|
|
372
|
+
|
|
373
|
+
if isinstance(value, RoutineReference):
|
|
374
|
+
value = value.to_api_repr()
|
|
375
|
+
|
|
376
|
+
if isinstance(value, Routine):
|
|
377
|
+
value = value.reference.to_api_repr()
|
|
378
|
+
|
|
379
|
+
self._properties["routine"] = value
|
|
380
|
+
|
|
381
|
+
@property
|
|
382
|
+
def view(self) -> Optional[TableReference]:
|
|
383
|
+
"""API resource representation of a view reference."""
|
|
384
|
+
value = typing.cast(Optional[Dict], self._properties.get("view"))
|
|
385
|
+
return TableReference.from_api_repr(value) if value else None
|
|
386
|
+
|
|
387
|
+
@view.setter
|
|
388
|
+
def view(self, value):
|
|
389
|
+
if self.role is not None:
|
|
390
|
+
raise ValueError(
|
|
391
|
+
"Role must be None for a view. Current " "role: %r" % (self.role)
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
if isinstance(value, str):
|
|
395
|
+
value = TableReference.from_string(value).to_api_repr()
|
|
396
|
+
|
|
397
|
+
if isinstance(value, TableReference):
|
|
398
|
+
value = value.to_api_repr()
|
|
399
|
+
|
|
400
|
+
if isinstance(value, Table):
|
|
401
|
+
value = value.reference.to_api_repr()
|
|
402
|
+
|
|
403
|
+
self._properties["view"] = value
|
|
404
|
+
|
|
405
|
+
@property
|
|
406
|
+
def group_by_email(self) -> Optional[str]:
|
|
407
|
+
"""An email address of a Google Group to grant access to."""
|
|
408
|
+
return typing.cast(Optional[str], self._properties.get("groupByEmail"))
|
|
409
|
+
|
|
410
|
+
@group_by_email.setter
|
|
411
|
+
def group_by_email(self, value):
|
|
412
|
+
self._properties["groupByEmail"] = value
|
|
413
|
+
|
|
414
|
+
@property
|
|
415
|
+
def user_by_email(self) -> Optional[str]:
|
|
416
|
+
"""An email address of a user to grant access to."""
|
|
417
|
+
return typing.cast(Optional[str], self._properties.get("userByEmail"))
|
|
418
|
+
|
|
419
|
+
@user_by_email.setter
|
|
420
|
+
def user_by_email(self, value):
|
|
421
|
+
self._properties["userByEmail"] = value
|
|
422
|
+
|
|
423
|
+
@property
|
|
424
|
+
def domain(self) -> Optional[str]:
|
|
425
|
+
"""A domain to grant access to."""
|
|
426
|
+
return typing.cast(Optional[str], self._properties.get("domain"))
|
|
427
|
+
|
|
428
|
+
@domain.setter
|
|
429
|
+
def domain(self, value):
|
|
430
|
+
self._properties["domain"] = value
|
|
431
|
+
|
|
432
|
+
@property
|
|
433
|
+
def special_group(self) -> Optional[str]:
|
|
434
|
+
"""A special group to grant access to."""
|
|
435
|
+
return typing.cast(Optional[str], self._properties.get("specialGroup"))
|
|
436
|
+
|
|
437
|
+
@special_group.setter
|
|
438
|
+
def special_group(self, value):
|
|
439
|
+
self._properties["specialGroup"] = value
|
|
440
|
+
|
|
441
|
+
@property
|
|
442
|
+
def entity_type(self) -> Optional[str]:
|
|
443
|
+
"""The entity_type of the entry."""
|
|
444
|
+
return self._entity_type
|
|
445
|
+
|
|
446
|
+
@property
|
|
447
|
+
def entity_id(self) -> Optional[Union[Dict[str, Any], str]]:
|
|
448
|
+
"""The entity_id of the entry."""
|
|
449
|
+
return self._properties.get(self._entity_type) if self._entity_type else None
|
|
450
|
+
|
|
451
|
+
def __eq__(self, other):
|
|
452
|
+
if not isinstance(other, AccessEntry):
|
|
453
|
+
return NotImplemented
|
|
454
|
+
return self._key() == other._key()
|
|
455
|
+
|
|
456
|
+
def __ne__(self, other):
|
|
457
|
+
return not self == other
|
|
458
|
+
|
|
459
|
+
def __repr__(self):
|
|
460
|
+
return f"<AccessEntry: role={self.role}, {self._entity_type}={self.entity_id}>"
|
|
461
|
+
|
|
462
|
+
def _key(self):
|
|
463
|
+
"""A tuple key that uniquely describes this field.
|
|
464
|
+
Used to compute this instance's hashcode and evaluate equality.
|
|
465
|
+
Returns:
|
|
466
|
+
Tuple: The contents of this :class:`~google.cloud.bigquery.dataset.AccessEntry`.
|
|
467
|
+
"""
|
|
468
|
+
properties = self._properties.copy()
|
|
469
|
+
prop_tup = tuple(sorted(properties.items()))
|
|
470
|
+
return (self.role, self._entity_type, self.entity_id, prop_tup)
|
|
471
|
+
|
|
472
|
+
def __hash__(self):
|
|
473
|
+
return hash(self._key())
|
|
474
|
+
|
|
475
|
+
def to_api_repr(self):
|
|
476
|
+
"""Construct the API resource representation of this access entry
|
|
477
|
+
|
|
478
|
+
Returns:
|
|
479
|
+
Dict[str, object]: Access entry represented as an API resource
|
|
480
|
+
"""
|
|
481
|
+
resource = copy.deepcopy(self._properties)
|
|
482
|
+
return resource
|
|
483
|
+
|
|
484
|
+
@classmethod
|
|
485
|
+
def from_api_repr(cls, resource: dict) -> "AccessEntry":
|
|
486
|
+
"""Factory: construct an access entry given its API representation
|
|
487
|
+
|
|
488
|
+
Args:
|
|
489
|
+
resource (Dict[str, object]):
|
|
490
|
+
Access entry resource representation returned from the API
|
|
491
|
+
|
|
492
|
+
Returns:
|
|
493
|
+
google.cloud.bigquery.dataset.AccessEntry:
|
|
494
|
+
Access entry parsed from ``resource``.
|
|
495
|
+
|
|
496
|
+
Raises:
|
|
497
|
+
ValueError:
|
|
498
|
+
If the resource has more keys than ``role`` and one additional
|
|
499
|
+
key.
|
|
500
|
+
"""
|
|
501
|
+
entry = resource.copy()
|
|
502
|
+
role = entry.pop("role", None)
|
|
503
|
+
entity_type, entity_id = entry.popitem()
|
|
504
|
+
if len(entry) != 0:
|
|
505
|
+
raise ValueError("Entry has unexpected keys remaining.", entry)
|
|
506
|
+
|
|
507
|
+
return cls(role, entity_type, entity_id)
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
class Dataset(object):
|
|
511
|
+
"""Datasets are containers for tables.
|
|
512
|
+
|
|
513
|
+
See
|
|
514
|
+
https://cloud.google.com/bigquery/docs/reference/rest/v2/datasets#resource-dataset
|
|
515
|
+
|
|
516
|
+
Args:
|
|
517
|
+
dataset_ref (Union[google.cloud.bigquery.dataset.DatasetReference, str]):
|
|
518
|
+
A pointer to a dataset. If ``dataset_ref`` is a string, it must
|
|
519
|
+
include both the project ID and the dataset ID, separated by
|
|
520
|
+
``.``.
|
|
521
|
+
"""
|
|
522
|
+
|
|
523
|
+
_PROPERTY_TO_API_FIELD = {
|
|
524
|
+
"access_entries": "access",
|
|
525
|
+
"created": "creationTime",
|
|
526
|
+
"default_partition_expiration_ms": "defaultPartitionExpirationMs",
|
|
527
|
+
"default_table_expiration_ms": "defaultTableExpirationMs",
|
|
528
|
+
"friendly_name": "friendlyName",
|
|
529
|
+
"default_encryption_configuration": "defaultEncryptionConfiguration",
|
|
530
|
+
"is_case_insensitive": "isCaseInsensitive",
|
|
531
|
+
"storage_billing_model": "storageBillingModel",
|
|
532
|
+
"max_time_travel_hours": "maxTimeTravelHours",
|
|
533
|
+
"default_rounding_mode": "defaultRoundingMode",
|
|
534
|
+
"resource_tags": "resourceTags",
|
|
535
|
+
"external_catalog_dataset_options": "externalCatalogDatasetOptions",
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
def __init__(self, dataset_ref) -> None:
|
|
539
|
+
if isinstance(dataset_ref, str):
|
|
540
|
+
dataset_ref = DatasetReference.from_string(dataset_ref)
|
|
541
|
+
self._properties = {"datasetReference": dataset_ref.to_api_repr(), "labels": {}}
|
|
542
|
+
|
|
543
|
+
@property
|
|
544
|
+
def max_time_travel_hours(self):
|
|
545
|
+
"""
|
|
546
|
+
Optional[int]: Defines the time travel window in hours. The value can
|
|
547
|
+
be from 48 to 168 hours (2 to 7 days), and in multiple of 24 hours
|
|
548
|
+
(48, 72, 96, 120, 144, 168).
|
|
549
|
+
The default value is 168 hours if this is not set.
|
|
550
|
+
"""
|
|
551
|
+
return self._properties.get("maxTimeTravelHours")
|
|
552
|
+
|
|
553
|
+
@max_time_travel_hours.setter
|
|
554
|
+
def max_time_travel_hours(self, hours):
|
|
555
|
+
if not isinstance(hours, int):
|
|
556
|
+
raise ValueError(f"max_time_travel_hours must be an integer. Got {hours}")
|
|
557
|
+
if hours < 2 * 24 or hours > 7 * 24:
|
|
558
|
+
raise ValueError(
|
|
559
|
+
"Time Travel Window should be from 48 to 168 hours (2 to 7 days)"
|
|
560
|
+
)
|
|
561
|
+
if hours % 24 != 0:
|
|
562
|
+
raise ValueError("Time Travel Window should be multiple of 24")
|
|
563
|
+
self._properties["maxTimeTravelHours"] = hours
|
|
564
|
+
|
|
565
|
+
@property
|
|
566
|
+
def default_rounding_mode(self):
|
|
567
|
+
"""Union[str, None]: defaultRoundingMode of the dataset as set by the user
|
|
568
|
+
(defaults to :data:`None`).
|
|
569
|
+
|
|
570
|
+
Set the value to one of ``'ROUND_HALF_AWAY_FROM_ZERO'``, ``'ROUND_HALF_EVEN'``, or
|
|
571
|
+
``'ROUNDING_MODE_UNSPECIFIED'``.
|
|
572
|
+
|
|
573
|
+
See `default rounding mode
|
|
574
|
+
<https://cloud.google.com/bigquery/docs/reference/rest/v2/datasets#Dataset.FIELDS.default_rounding_mode>`_
|
|
575
|
+
in REST API docs and `updating the default rounding model
|
|
576
|
+
<https://cloud.google.com/bigquery/docs/updating-datasets#update_rounding_mode>`_
|
|
577
|
+
guide.
|
|
578
|
+
|
|
579
|
+
Raises:
|
|
580
|
+
ValueError: for invalid value types.
|
|
581
|
+
"""
|
|
582
|
+
return self._properties.get("defaultRoundingMode")
|
|
583
|
+
|
|
584
|
+
@default_rounding_mode.setter
|
|
585
|
+
def default_rounding_mode(self, value):
|
|
586
|
+
possible_values = [
|
|
587
|
+
"ROUNDING_MODE_UNSPECIFIED",
|
|
588
|
+
"ROUND_HALF_AWAY_FROM_ZERO",
|
|
589
|
+
"ROUND_HALF_EVEN",
|
|
590
|
+
]
|
|
591
|
+
if not isinstance(value, str) and value is not None:
|
|
592
|
+
raise ValueError("Pass a string, or None")
|
|
593
|
+
if value is None:
|
|
594
|
+
self._properties["defaultRoundingMode"] = "ROUNDING_MODE_UNSPECIFIED"
|
|
595
|
+
if value not in possible_values and value is not None:
|
|
596
|
+
raise ValueError(
|
|
597
|
+
f'rounding mode needs to be one of {",".join(possible_values)}'
|
|
598
|
+
)
|
|
599
|
+
if value:
|
|
600
|
+
self._properties["defaultRoundingMode"] = value
|
|
601
|
+
|
|
602
|
+
@property
|
|
603
|
+
def project(self):
|
|
604
|
+
"""str: Project ID of the project bound to the dataset."""
|
|
605
|
+
return self._properties["datasetReference"]["projectId"]
|
|
606
|
+
|
|
607
|
+
@property
|
|
608
|
+
def path(self):
|
|
609
|
+
"""str: URL path for the dataset based on project and dataset ID."""
|
|
610
|
+
return "/projects/%s/datasets/%s" % (self.project, self.dataset_id)
|
|
611
|
+
|
|
612
|
+
@property
|
|
613
|
+
def access_entries(self):
|
|
614
|
+
"""List[google.cloud.bigquery.dataset.AccessEntry]: Dataset's access
|
|
615
|
+
entries.
|
|
616
|
+
|
|
617
|
+
``role`` augments the entity type and must be present **unless** the
|
|
618
|
+
entity type is ``view`` or ``routine``.
|
|
619
|
+
|
|
620
|
+
Raises:
|
|
621
|
+
TypeError: If 'value' is not a sequence
|
|
622
|
+
ValueError:
|
|
623
|
+
If any item in the sequence is not an
|
|
624
|
+
:class:`~google.cloud.bigquery.dataset.AccessEntry`.
|
|
625
|
+
"""
|
|
626
|
+
entries = self._properties.get("access", [])
|
|
627
|
+
return [AccessEntry.from_api_repr(entry) for entry in entries]
|
|
628
|
+
|
|
629
|
+
@access_entries.setter
|
|
630
|
+
def access_entries(self, value):
|
|
631
|
+
if not all(isinstance(field, AccessEntry) for field in value):
|
|
632
|
+
raise ValueError("Values must be AccessEntry instances")
|
|
633
|
+
entries = [entry.to_api_repr() for entry in value]
|
|
634
|
+
self._properties["access"] = entries
|
|
635
|
+
|
|
636
|
+
@property
|
|
637
|
+
def created(self):
|
|
638
|
+
"""Union[datetime.datetime, None]: Datetime at which the dataset was
|
|
639
|
+
created (:data:`None` until set from the server).
|
|
640
|
+
"""
|
|
641
|
+
creation_time = self._properties.get("creationTime")
|
|
642
|
+
if creation_time is not None:
|
|
643
|
+
# creation_time will be in milliseconds.
|
|
644
|
+
return google.cloud._helpers._datetime_from_microseconds(
|
|
645
|
+
1000.0 * float(creation_time)
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
@property
|
|
649
|
+
def dataset_id(self):
|
|
650
|
+
"""str: Dataset ID."""
|
|
651
|
+
return self._properties["datasetReference"]["datasetId"]
|
|
652
|
+
|
|
653
|
+
@property
|
|
654
|
+
def full_dataset_id(self):
|
|
655
|
+
"""Union[str, None]: ID for the dataset resource (:data:`None` until
|
|
656
|
+
set from the server)
|
|
657
|
+
|
|
658
|
+
In the format ``project_id:dataset_id``.
|
|
659
|
+
"""
|
|
660
|
+
return self._properties.get("id")
|
|
661
|
+
|
|
662
|
+
@property
|
|
663
|
+
def reference(self):
|
|
664
|
+
"""google.cloud.bigquery.dataset.DatasetReference: A reference to this
|
|
665
|
+
dataset.
|
|
666
|
+
"""
|
|
667
|
+
return DatasetReference(self.project, self.dataset_id)
|
|
668
|
+
|
|
669
|
+
@property
|
|
670
|
+
def etag(self):
|
|
671
|
+
"""Union[str, None]: ETag for the dataset resource (:data:`None` until
|
|
672
|
+
set from the server).
|
|
673
|
+
"""
|
|
674
|
+
return self._properties.get("etag")
|
|
675
|
+
|
|
676
|
+
@property
|
|
677
|
+
def modified(self):
|
|
678
|
+
"""Union[datetime.datetime, None]: Datetime at which the dataset was
|
|
679
|
+
last modified (:data:`None` until set from the server).
|
|
680
|
+
"""
|
|
681
|
+
modified_time = self._properties.get("lastModifiedTime")
|
|
682
|
+
if modified_time is not None:
|
|
683
|
+
# modified_time will be in milliseconds.
|
|
684
|
+
return google.cloud._helpers._datetime_from_microseconds(
|
|
685
|
+
1000.0 * float(modified_time)
|
|
686
|
+
)
|
|
687
|
+
|
|
688
|
+
@property
|
|
689
|
+
def self_link(self):
|
|
690
|
+
"""Union[str, None]: URL for the dataset resource (:data:`None` until
|
|
691
|
+
set from the server).
|
|
692
|
+
"""
|
|
693
|
+
return self._properties.get("selfLink")
|
|
694
|
+
|
|
695
|
+
@property
|
|
696
|
+
def default_partition_expiration_ms(self):
|
|
697
|
+
"""Optional[int]: The default partition expiration for all
|
|
698
|
+
partitioned tables in the dataset, in milliseconds.
|
|
699
|
+
|
|
700
|
+
Once this property is set, all newly-created partitioned tables in
|
|
701
|
+
the dataset will have an ``time_paritioning.expiration_ms`` property
|
|
702
|
+
set to this value, and changing the value will only affect new
|
|
703
|
+
tables, not existing ones. The storage in a partition will have an
|
|
704
|
+
expiration time of its partition time plus this value.
|
|
705
|
+
|
|
706
|
+
Setting this property overrides the use of
|
|
707
|
+
``default_table_expiration_ms`` for partitioned tables: only one of
|
|
708
|
+
``default_table_expiration_ms`` and
|
|
709
|
+
``default_partition_expiration_ms`` will be used for any new
|
|
710
|
+
partitioned table. If you provide an explicit
|
|
711
|
+
``time_partitioning.expiration_ms`` when creating or updating a
|
|
712
|
+
partitioned table, that value takes precedence over the default
|
|
713
|
+
partition expiration time indicated by this property.
|
|
714
|
+
"""
|
|
715
|
+
return _helpers._int_or_none(
|
|
716
|
+
self._properties.get("defaultPartitionExpirationMs")
|
|
717
|
+
)
|
|
718
|
+
|
|
719
|
+
@default_partition_expiration_ms.setter
|
|
720
|
+
def default_partition_expiration_ms(self, value):
|
|
721
|
+
self._properties["defaultPartitionExpirationMs"] = _helpers._str_or_none(value)
|
|
722
|
+
|
|
723
|
+
@property
|
|
724
|
+
def default_table_expiration_ms(self):
|
|
725
|
+
"""Union[int, None]: Default expiration time for tables in the dataset
|
|
726
|
+
(defaults to :data:`None`).
|
|
727
|
+
|
|
728
|
+
Raises:
|
|
729
|
+
ValueError: For invalid value types.
|
|
730
|
+
"""
|
|
731
|
+
return _helpers._int_or_none(self._properties.get("defaultTableExpirationMs"))
|
|
732
|
+
|
|
733
|
+
@default_table_expiration_ms.setter
|
|
734
|
+
def default_table_expiration_ms(self, value):
|
|
735
|
+
if not isinstance(value, int) and value is not None:
|
|
736
|
+
raise ValueError("Pass an integer, or None")
|
|
737
|
+
self._properties["defaultTableExpirationMs"] = _helpers._str_or_none(value)
|
|
738
|
+
|
|
739
|
+
@property
|
|
740
|
+
def description(self):
|
|
741
|
+
"""Optional[str]: Description of the dataset as set by the user
|
|
742
|
+
(defaults to :data:`None`).
|
|
743
|
+
|
|
744
|
+
Raises:
|
|
745
|
+
ValueError: for invalid value types.
|
|
746
|
+
"""
|
|
747
|
+
return self._properties.get("description")
|
|
748
|
+
|
|
749
|
+
@description.setter
|
|
750
|
+
def description(self, value):
|
|
751
|
+
if not isinstance(value, str) and value is not None:
|
|
752
|
+
raise ValueError("Pass a string, or None")
|
|
753
|
+
self._properties["description"] = value
|
|
754
|
+
|
|
755
|
+
@property
|
|
756
|
+
def friendly_name(self):
|
|
757
|
+
"""Union[str, None]: Title of the dataset as set by the user
|
|
758
|
+
(defaults to :data:`None`).
|
|
759
|
+
|
|
760
|
+
Raises:
|
|
761
|
+
ValueError: for invalid value types.
|
|
762
|
+
"""
|
|
763
|
+
return self._properties.get("friendlyName")
|
|
764
|
+
|
|
765
|
+
@friendly_name.setter
|
|
766
|
+
def friendly_name(self, value):
|
|
767
|
+
if not isinstance(value, str) and value is not None:
|
|
768
|
+
raise ValueError("Pass a string, or None")
|
|
769
|
+
self._properties["friendlyName"] = value
|
|
770
|
+
|
|
771
|
+
@property
|
|
772
|
+
def location(self):
|
|
773
|
+
"""Union[str, None]: Location in which the dataset is hosted as set by
|
|
774
|
+
the user (defaults to :data:`None`).
|
|
775
|
+
|
|
776
|
+
Raises:
|
|
777
|
+
ValueError: for invalid value types.
|
|
778
|
+
"""
|
|
779
|
+
return self._properties.get("location")
|
|
780
|
+
|
|
781
|
+
@location.setter
|
|
782
|
+
def location(self, value):
|
|
783
|
+
if not isinstance(value, str) and value is not None:
|
|
784
|
+
raise ValueError("Pass a string, or None")
|
|
785
|
+
self._properties["location"] = value
|
|
786
|
+
|
|
787
|
+
@property
|
|
788
|
+
def labels(self):
|
|
789
|
+
"""Dict[str, str]: Labels for the dataset.
|
|
790
|
+
|
|
791
|
+
This method always returns a dict. To change a dataset's labels,
|
|
792
|
+
modify the dict, then call
|
|
793
|
+
:meth:`google.cloud.bigquery.client.Client.update_dataset`. To delete
|
|
794
|
+
a label, set its value to :data:`None` before updating.
|
|
795
|
+
|
|
796
|
+
Raises:
|
|
797
|
+
ValueError: for invalid value types.
|
|
798
|
+
"""
|
|
799
|
+
return self._properties.setdefault("labels", {})
|
|
800
|
+
|
|
801
|
+
@labels.setter
|
|
802
|
+
def labels(self, value):
|
|
803
|
+
if not isinstance(value, dict):
|
|
804
|
+
raise ValueError("Pass a dict")
|
|
805
|
+
self._properties["labels"] = value
|
|
806
|
+
|
|
807
|
+
@property
|
|
808
|
+
def resource_tags(self):
|
|
809
|
+
"""Dict[str, str]: Resource tags of the dataset.
|
|
810
|
+
|
|
811
|
+
Optional. The tags attached to this dataset. Tag keys are globally
|
|
812
|
+
unique. Tag key is expected to be in the namespaced format, for
|
|
813
|
+
example "123456789012/environment" where 123456789012 is
|
|
814
|
+
the ID of the parent organization or project resource for this tag
|
|
815
|
+
key. Tag value is expected to be the short name, for example
|
|
816
|
+
"Production".
|
|
817
|
+
|
|
818
|
+
Raises:
|
|
819
|
+
ValueError: for invalid value types.
|
|
820
|
+
"""
|
|
821
|
+
return self._properties.setdefault("resourceTags", {})
|
|
822
|
+
|
|
823
|
+
@resource_tags.setter
|
|
824
|
+
def resource_tags(self, value):
|
|
825
|
+
if not isinstance(value, dict) and value is not None:
|
|
826
|
+
raise ValueError("Pass a dict")
|
|
827
|
+
self._properties["resourceTags"] = value
|
|
828
|
+
|
|
829
|
+
@property
|
|
830
|
+
def default_encryption_configuration(self):
|
|
831
|
+
"""google.cloud.bigquery.encryption_configuration.EncryptionConfiguration: Custom
|
|
832
|
+
encryption configuration for all tables in the dataset.
|
|
833
|
+
|
|
834
|
+
Custom encryption configuration (e.g., Cloud KMS keys) or :data:`None`
|
|
835
|
+
if using default encryption.
|
|
836
|
+
|
|
837
|
+
See `protecting data with Cloud KMS keys
|
|
838
|
+
<https://cloud.google.com/bigquery/docs/customer-managed-encryption>`_
|
|
839
|
+
in the BigQuery documentation.
|
|
840
|
+
"""
|
|
841
|
+
prop = self._properties.get("defaultEncryptionConfiguration")
|
|
842
|
+
if prop:
|
|
843
|
+
prop = EncryptionConfiguration.from_api_repr(prop)
|
|
844
|
+
return prop
|
|
845
|
+
|
|
846
|
+
@default_encryption_configuration.setter
|
|
847
|
+
def default_encryption_configuration(self, value):
|
|
848
|
+
api_repr = value
|
|
849
|
+
if value:
|
|
850
|
+
api_repr = value.to_api_repr()
|
|
851
|
+
self._properties["defaultEncryptionConfiguration"] = api_repr
|
|
852
|
+
|
|
853
|
+
@property
|
|
854
|
+
def is_case_insensitive(self):
|
|
855
|
+
"""Optional[bool]: True if the dataset and its table names are case-insensitive, otherwise False.
|
|
856
|
+
By default, this is False, which means the dataset and its table names are case-sensitive.
|
|
857
|
+
This field does not affect routine references.
|
|
858
|
+
|
|
859
|
+
Raises:
|
|
860
|
+
ValueError: for invalid value types.
|
|
861
|
+
"""
|
|
862
|
+
return self._properties.get("isCaseInsensitive") or False
|
|
863
|
+
|
|
864
|
+
@is_case_insensitive.setter
|
|
865
|
+
def is_case_insensitive(self, value):
|
|
866
|
+
if not isinstance(value, bool) and value is not None:
|
|
867
|
+
raise ValueError("Pass a boolean value, or None")
|
|
868
|
+
if value is None:
|
|
869
|
+
value = False
|
|
870
|
+
self._properties["isCaseInsensitive"] = value
|
|
871
|
+
|
|
872
|
+
@property
|
|
873
|
+
def storage_billing_model(self):
|
|
874
|
+
"""Union[str, None]: StorageBillingModel of the dataset as set by the user
|
|
875
|
+
(defaults to :data:`None`).
|
|
876
|
+
|
|
877
|
+
Set the value to one of ``'LOGICAL'``, ``'PHYSICAL'``, or
|
|
878
|
+
``'STORAGE_BILLING_MODEL_UNSPECIFIED'``. This change takes 24 hours to
|
|
879
|
+
take effect and you must wait 14 days before you can change the storage
|
|
880
|
+
billing model again.
|
|
881
|
+
|
|
882
|
+
See `storage billing model
|
|
883
|
+
<https://cloud.google.com/bigquery/docs/reference/rest/v2/datasets#Dataset.FIELDS.storage_billing_model>`_
|
|
884
|
+
in REST API docs and `updating the storage billing model
|
|
885
|
+
<https://cloud.google.com/bigquery/docs/updating-datasets#update_storage_billing_models>`_
|
|
886
|
+
guide.
|
|
887
|
+
|
|
888
|
+
Raises:
|
|
889
|
+
ValueError: for invalid value types.
|
|
890
|
+
"""
|
|
891
|
+
return self._properties.get("storageBillingModel")
|
|
892
|
+
|
|
893
|
+
@storage_billing_model.setter
|
|
894
|
+
def storage_billing_model(self, value):
|
|
895
|
+
if not isinstance(value, str) and value is not None:
|
|
896
|
+
raise ValueError(
|
|
897
|
+
"storage_billing_model must be a string (e.g. 'LOGICAL',"
|
|
898
|
+
" 'PHYSICAL', 'STORAGE_BILLING_MODEL_UNSPECIFIED'), or None."
|
|
899
|
+
f" Got {repr(value)}."
|
|
900
|
+
)
|
|
901
|
+
self._properties["storageBillingModel"] = value
|
|
902
|
+
|
|
903
|
+
@property
|
|
904
|
+
def external_catalog_dataset_options(self):
|
|
905
|
+
"""Options defining open source compatible datasets living in the
|
|
906
|
+
BigQuery catalog. Contains metadata of open source database, schema
|
|
907
|
+
or namespace represented by the current dataset."""
|
|
908
|
+
|
|
909
|
+
prop = _helpers._get_sub_prop(
|
|
910
|
+
self._properties, ["externalCatalogDatasetOptions"]
|
|
911
|
+
)
|
|
912
|
+
|
|
913
|
+
if prop is not None:
|
|
914
|
+
prop = external_config.ExternalCatalogDatasetOptions.from_api_repr(prop)
|
|
915
|
+
return prop
|
|
916
|
+
|
|
917
|
+
@external_catalog_dataset_options.setter
|
|
918
|
+
def external_catalog_dataset_options(self, value):
|
|
919
|
+
value = _helpers._isinstance_or_raise(
|
|
920
|
+
value, external_config.ExternalCatalogDatasetOptions, none_allowed=True
|
|
921
|
+
)
|
|
922
|
+
self._properties[
|
|
923
|
+
self._PROPERTY_TO_API_FIELD["external_catalog_dataset_options"]
|
|
924
|
+
] = (value.to_api_repr() if value is not None else None)
|
|
925
|
+
|
|
926
|
+
@classmethod
|
|
927
|
+
def from_string(cls, full_dataset_id: str) -> "Dataset":
|
|
928
|
+
"""Construct a dataset from fully-qualified dataset ID.
|
|
929
|
+
|
|
930
|
+
Args:
|
|
931
|
+
full_dataset_id (str):
|
|
932
|
+
A fully-qualified dataset ID in standard SQL format. Must
|
|
933
|
+
include both the project ID and the dataset ID, separated by
|
|
934
|
+
``.``.
|
|
935
|
+
|
|
936
|
+
Returns:
|
|
937
|
+
Dataset: Dataset parsed from ``full_dataset_id``.
|
|
938
|
+
|
|
939
|
+
Examples:
|
|
940
|
+
>>> Dataset.from_string('my-project-id.some_dataset')
|
|
941
|
+
Dataset(DatasetReference('my-project-id', 'some_dataset'))
|
|
942
|
+
|
|
943
|
+
Raises:
|
|
944
|
+
ValueError:
|
|
945
|
+
If ``full_dataset_id`` is not a fully-qualified dataset ID in
|
|
946
|
+
standard SQL format.
|
|
947
|
+
"""
|
|
948
|
+
return cls(DatasetReference.from_string(full_dataset_id))
|
|
949
|
+
|
|
950
|
+
@classmethod
|
|
951
|
+
def from_api_repr(cls, resource: dict) -> "Dataset":
|
|
952
|
+
"""Factory: construct a dataset given its API representation
|
|
953
|
+
|
|
954
|
+
Args:
|
|
955
|
+
resource (Dict[str: object]):
|
|
956
|
+
Dataset resource representation returned from the API
|
|
957
|
+
|
|
958
|
+
Returns:
|
|
959
|
+
google.cloud.bigquery.dataset.Dataset:
|
|
960
|
+
Dataset parsed from ``resource``.
|
|
961
|
+
"""
|
|
962
|
+
if (
|
|
963
|
+
"datasetReference" not in resource
|
|
964
|
+
or "datasetId" not in resource["datasetReference"]
|
|
965
|
+
):
|
|
966
|
+
raise KeyError(
|
|
967
|
+
"Resource lacks required identity information:"
|
|
968
|
+
'["datasetReference"]["datasetId"]'
|
|
969
|
+
)
|
|
970
|
+
project_id = resource["datasetReference"]["projectId"]
|
|
971
|
+
dataset_id = resource["datasetReference"]["datasetId"]
|
|
972
|
+
dataset = cls(DatasetReference(project_id, dataset_id))
|
|
973
|
+
dataset._properties = copy.deepcopy(resource)
|
|
974
|
+
return dataset
|
|
975
|
+
|
|
976
|
+
def to_api_repr(self) -> dict:
|
|
977
|
+
"""Construct the API resource representation of this dataset
|
|
978
|
+
|
|
979
|
+
Returns:
|
|
980
|
+
Dict[str, object]: The dataset represented as an API resource
|
|
981
|
+
"""
|
|
982
|
+
return copy.deepcopy(self._properties)
|
|
983
|
+
|
|
984
|
+
def _build_resource(self, filter_fields):
|
|
985
|
+
"""Generate a resource for ``update``."""
|
|
986
|
+
return _helpers._build_resource_from_properties(self, filter_fields)
|
|
987
|
+
|
|
988
|
+
table = _get_table_reference
|
|
989
|
+
|
|
990
|
+
model = _get_model_reference
|
|
991
|
+
|
|
992
|
+
routine = _get_routine_reference
|
|
993
|
+
|
|
994
|
+
def __repr__(self):
|
|
995
|
+
return "Dataset({})".format(repr(self.reference))
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
class DatasetListItem(object):
|
|
999
|
+
"""A read-only dataset resource from a list operation.
|
|
1000
|
+
|
|
1001
|
+
For performance reasons, the BigQuery API only includes some of the
|
|
1002
|
+
dataset properties when listing datasets. Notably,
|
|
1003
|
+
:attr:`~google.cloud.bigquery.dataset.Dataset.access_entries` is missing.
|
|
1004
|
+
|
|
1005
|
+
For a full list of the properties that the BigQuery API returns, see the
|
|
1006
|
+
`REST documentation for datasets.list
|
|
1007
|
+
<https://cloud.google.com/bigquery/docs/reference/rest/v2/datasets/list>`_.
|
|
1008
|
+
|
|
1009
|
+
|
|
1010
|
+
Args:
|
|
1011
|
+
resource (Dict[str, str]):
|
|
1012
|
+
A dataset-like resource object from a dataset list response. A
|
|
1013
|
+
``datasetReference`` property is required.
|
|
1014
|
+
|
|
1015
|
+
Raises:
|
|
1016
|
+
ValueError:
|
|
1017
|
+
If ``datasetReference`` or one of its required members is missing
|
|
1018
|
+
from ``resource``.
|
|
1019
|
+
"""
|
|
1020
|
+
|
|
1021
|
+
def __init__(self, resource):
|
|
1022
|
+
if "datasetReference" not in resource:
|
|
1023
|
+
raise ValueError("resource must contain a datasetReference value")
|
|
1024
|
+
if "projectId" not in resource["datasetReference"]:
|
|
1025
|
+
raise ValueError(
|
|
1026
|
+
"resource['datasetReference'] must contain a projectId value"
|
|
1027
|
+
)
|
|
1028
|
+
if "datasetId" not in resource["datasetReference"]:
|
|
1029
|
+
raise ValueError(
|
|
1030
|
+
"resource['datasetReference'] must contain a datasetId value"
|
|
1031
|
+
)
|
|
1032
|
+
self._properties = resource
|
|
1033
|
+
|
|
1034
|
+
@property
|
|
1035
|
+
def project(self):
|
|
1036
|
+
"""str: Project bound to the dataset."""
|
|
1037
|
+
return self._properties["datasetReference"]["projectId"]
|
|
1038
|
+
|
|
1039
|
+
@property
|
|
1040
|
+
def dataset_id(self):
|
|
1041
|
+
"""str: Dataset ID."""
|
|
1042
|
+
return self._properties["datasetReference"]["datasetId"]
|
|
1043
|
+
|
|
1044
|
+
@property
|
|
1045
|
+
def full_dataset_id(self):
|
|
1046
|
+
"""Union[str, None]: ID for the dataset resource (:data:`None` until
|
|
1047
|
+
set from the server)
|
|
1048
|
+
|
|
1049
|
+
In the format ``project_id:dataset_id``.
|
|
1050
|
+
"""
|
|
1051
|
+
return self._properties.get("id")
|
|
1052
|
+
|
|
1053
|
+
@property
|
|
1054
|
+
def friendly_name(self):
|
|
1055
|
+
"""Union[str, None]: Title of the dataset as set by the user
|
|
1056
|
+
(defaults to :data:`None`).
|
|
1057
|
+
"""
|
|
1058
|
+
return self._properties.get("friendlyName")
|
|
1059
|
+
|
|
1060
|
+
@property
|
|
1061
|
+
def labels(self):
|
|
1062
|
+
"""Dict[str, str]: Labels for the dataset."""
|
|
1063
|
+
return self._properties.setdefault("labels", {})
|
|
1064
|
+
|
|
1065
|
+
@property
|
|
1066
|
+
def reference(self):
|
|
1067
|
+
"""google.cloud.bigquery.dataset.DatasetReference: A reference to this
|
|
1068
|
+
dataset.
|
|
1069
|
+
"""
|
|
1070
|
+
return DatasetReference(self.project, self.dataset_id)
|
|
1071
|
+
|
|
1072
|
+
table = _get_table_reference
|
|
1073
|
+
|
|
1074
|
+
model = _get_model_reference
|
|
1075
|
+
|
|
1076
|
+
routine = _get_routine_reference
|