Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/google/cloud/bigquery/routine/routine.py: 53%
219 statements
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 06:07 +0000
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 06:07 +0000
1# -*- coding: utf-8 -*-
2#
3# Copyright 2019 Google LLC
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# https://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
17"""Define resources for the BigQuery Routines API."""
19from typing import Any, Dict, Optional
21import google.cloud._helpers # type: ignore
22from google.cloud.bigquery import _helpers
23from google.cloud.bigquery.standard_sql import StandardSqlDataType
24from google.cloud.bigquery.standard_sql import StandardSqlTableType
27class RoutineType:
28 """The fine-grained type of the routine.
30 https://cloud.google.com/bigquery/docs/reference/rest/v2/routines#routinetype
32 .. versionadded:: 2.22.0
33 """
35 ROUTINE_TYPE_UNSPECIFIED = "ROUTINE_TYPE_UNSPECIFIED"
36 SCALAR_FUNCTION = "SCALAR_FUNCTION"
37 PROCEDURE = "PROCEDURE"
38 TABLE_VALUED_FUNCTION = "TABLE_VALUED_FUNCTION"
41class Routine(object):
42 """Resource representing a user-defined routine.
44 See
45 https://cloud.google.com/bigquery/docs/reference/rest/v2/routines
47 Args:
48 routine_ref (Union[str, google.cloud.bigquery.routine.RoutineReference]):
49 A pointer to a routine. If ``routine_ref`` is a string, it must
50 included a project ID, dataset ID, and routine ID, each separated
51 by ``.``.
52 ``**kwargs`` (Dict):
53 Initial property values.
54 """
56 _PROPERTY_TO_API_FIELD = {
57 "arguments": "arguments",
58 "body": "definitionBody",
59 "created": "creationTime",
60 "etag": "etag",
61 "imported_libraries": "importedLibraries",
62 "language": "language",
63 "modified": "lastModifiedTime",
64 "reference": "routineReference",
65 "return_type": "returnType",
66 "return_table_type": "returnTableType",
67 "type_": "routineType",
68 "description": "description",
69 "determinism_level": "determinismLevel",
70 }
72 def __init__(self, routine_ref, **kwargs) -> None:
73 if isinstance(routine_ref, str):
74 routine_ref = RoutineReference.from_string(routine_ref)
76 self._properties = {"routineReference": routine_ref.to_api_repr()}
77 for property_name in kwargs:
78 setattr(self, property_name, kwargs[property_name])
80 @property
81 def reference(self):
82 """google.cloud.bigquery.routine.RoutineReference: Reference
83 describing the ID of this routine.
84 """
85 return RoutineReference.from_api_repr(
86 self._properties[self._PROPERTY_TO_API_FIELD["reference"]]
87 )
89 @property
90 def path(self):
91 """str: URL path for the routine's APIs."""
92 return self.reference.path
94 @property
95 def project(self):
96 """str: ID of the project containing the routine."""
97 return self.reference.project
99 @property
100 def dataset_id(self):
101 """str: ID of dataset containing the routine."""
102 return self.reference.dataset_id
104 @property
105 def routine_id(self):
106 """str: The routine ID."""
107 return self.reference.routine_id
109 @property
110 def etag(self):
111 """str: ETag for the resource (:data:`None` until set from the
112 server).
114 Read-only.
115 """
116 return self._properties.get(self._PROPERTY_TO_API_FIELD["etag"])
118 @property
119 def type_(self):
120 """str: The fine-grained type of the routine.
122 See:
123 https://cloud.google.com/bigquery/docs/reference/rest/v2/routines#RoutineType
124 """
125 return self._properties.get(self._PROPERTY_TO_API_FIELD["type_"])
127 @type_.setter
128 def type_(self, value):
129 self._properties[self._PROPERTY_TO_API_FIELD["type_"]] = value
131 @property
132 def created(self):
133 """Optional[datetime.datetime]: Datetime at which the routine was
134 created (:data:`None` until set from the server).
136 Read-only.
137 """
138 value = self._properties.get(self._PROPERTY_TO_API_FIELD["created"])
139 if value is not None and value != 0:
140 # value will be in milliseconds.
141 return google.cloud._helpers._datetime_from_microseconds(
142 1000.0 * float(value)
143 )
145 @property
146 def modified(self):
147 """Optional[datetime.datetime]: Datetime at which the routine was
148 last modified (:data:`None` until set from the server).
150 Read-only.
151 """
152 value = self._properties.get(self._PROPERTY_TO_API_FIELD["modified"])
153 if value is not None and value != 0:
154 # value will be in milliseconds.
155 return google.cloud._helpers._datetime_from_microseconds(
156 1000.0 * float(value)
157 )
159 @property
160 def language(self):
161 """Optional[str]: The language of the routine.
163 Defaults to ``SQL``.
164 """
165 return self._properties.get(self._PROPERTY_TO_API_FIELD["language"])
167 @language.setter
168 def language(self, value):
169 self._properties[self._PROPERTY_TO_API_FIELD["language"]] = value
171 @property
172 def arguments(self):
173 """List[google.cloud.bigquery.routine.RoutineArgument]: Input/output
174 argument of a function or a stored procedure.
176 In-place modification is not supported. To set, replace the entire
177 property value with the modified list of
178 :class:`~google.cloud.bigquery.routine.RoutineArgument` objects.
179 """
180 resources = self._properties.get(self._PROPERTY_TO_API_FIELD["arguments"], [])
181 return [RoutineArgument.from_api_repr(resource) for resource in resources]
183 @arguments.setter
184 def arguments(self, value):
185 if not value:
186 resource = []
187 else:
188 resource = [argument.to_api_repr() for argument in value]
189 self._properties[self._PROPERTY_TO_API_FIELD["arguments"]] = resource
191 @property
192 def return_type(self):
193 """google.cloud.bigquery.StandardSqlDataType: Return type of
194 the routine.
196 If absent, the return type is inferred from
197 :attr:`~google.cloud.bigquery.routine.Routine.body` at query time in
198 each query that references this routine. If present, then the
199 evaluated result will be cast to the specified returned type at query
200 time.
202 See:
203 https://cloud.google.com/bigquery/docs/reference/rest/v2/routines#Routine.FIELDS.return_type
204 """
205 resource = self._properties.get(self._PROPERTY_TO_API_FIELD["return_type"])
206 if not resource:
207 return resource
209 return StandardSqlDataType.from_api_repr(resource)
211 @return_type.setter
212 def return_type(self, value: StandardSqlDataType):
213 resource = None if not value else value.to_api_repr()
214 self._properties[self._PROPERTY_TO_API_FIELD["return_type"]] = resource
216 @property
217 def return_table_type(self) -> Optional[StandardSqlTableType]:
218 """The return type of a Table Valued Function (TVF) routine.
220 .. versionadded:: 2.22.0
221 """
222 resource = self._properties.get(
223 self._PROPERTY_TO_API_FIELD["return_table_type"]
224 )
225 if not resource:
226 return resource
228 return StandardSqlTableType.from_api_repr(resource)
230 @return_table_type.setter
231 def return_table_type(self, value: Optional[StandardSqlTableType]):
232 if not value:
233 resource = None
234 else:
235 resource = value.to_api_repr()
237 self._properties[self._PROPERTY_TO_API_FIELD["return_table_type"]] = resource
239 @property
240 def imported_libraries(self):
241 """List[str]: The path of the imported JavaScript libraries.
243 The :attr:`~google.cloud.bigquery.routine.Routine.language` must
244 equal ``JAVACRIPT``.
246 Examples:
247 Set the ``imported_libraries`` to a list of Google Cloud Storage
248 URIs.
250 .. code-block:: python
252 routine = bigquery.Routine("proj.dataset.routine_id")
253 routine.imported_libraries = [
254 "gs://cloud-samples-data/bigquery/udfs/max-value.js",
255 ]
256 """
257 return self._properties.get(
258 self._PROPERTY_TO_API_FIELD["imported_libraries"], []
259 )
261 @imported_libraries.setter
262 def imported_libraries(self, value):
263 if not value:
264 resource = []
265 else:
266 resource = value
267 self._properties[self._PROPERTY_TO_API_FIELD["imported_libraries"]] = resource
269 @property
270 def body(self):
271 """str: The body of the routine."""
272 return self._properties.get(self._PROPERTY_TO_API_FIELD["body"])
274 @body.setter
275 def body(self, value):
276 self._properties[self._PROPERTY_TO_API_FIELD["body"]] = value
278 @property
279 def description(self):
280 """Optional[str]: Description of the routine (defaults to
281 :data:`None`).
282 """
283 return self._properties.get(self._PROPERTY_TO_API_FIELD["description"])
285 @description.setter
286 def description(self, value):
287 self._properties[self._PROPERTY_TO_API_FIELD["description"]] = value
289 @property
290 def determinism_level(self):
291 """Optional[str]: (experimental) The determinism level of the JavaScript UDF
292 if defined.
293 """
294 return self._properties.get(self._PROPERTY_TO_API_FIELD["determinism_level"])
296 @determinism_level.setter
297 def determinism_level(self, value):
298 self._properties[self._PROPERTY_TO_API_FIELD["determinism_level"]] = value
300 @classmethod
301 def from_api_repr(cls, resource: dict) -> "Routine":
302 """Factory: construct a routine given its API representation.
304 Args:
305 resource (Dict[str, object]):
306 Resource, as returned from the API.
308 Returns:
309 google.cloud.bigquery.routine.Routine:
310 Python object, as parsed from ``resource``.
311 """
312 ref = cls(RoutineReference.from_api_repr(resource["routineReference"]))
313 ref._properties = resource
314 return ref
316 def to_api_repr(self) -> dict:
317 """Construct the API resource representation of this routine.
319 Returns:
320 Dict[str, object]: Routine represented as an API resource.
321 """
322 return self._properties
324 def _build_resource(self, filter_fields):
325 """Generate a resource for ``update``."""
326 return _helpers._build_resource_from_properties(self, filter_fields)
328 def __repr__(self):
329 return "Routine('{}.{}.{}')".format(
330 self.project, self.dataset_id, self.routine_id
331 )
334class RoutineArgument(object):
335 """Input/output argument of a function or a stored procedure.
337 See:
338 https://cloud.google.com/bigquery/docs/reference/rest/v2/routines#argument
340 Args:
341 ``**kwargs`` (Dict):
342 Initial property values.
343 """
345 _PROPERTY_TO_API_FIELD = {
346 "data_type": "dataType",
347 "kind": "argumentKind",
348 # Even though it's not necessary for field mapping to map when the
349 # property name equals the resource name, we add these here so that we
350 # have an exhaustive list of all properties.
351 "name": "name",
352 "mode": "mode",
353 }
355 def __init__(self, **kwargs) -> None:
356 self._properties: Dict[str, Any] = {}
357 for property_name in kwargs:
358 setattr(self, property_name, kwargs[property_name])
360 @property
361 def name(self):
362 """Optional[str]: Name of this argument.
364 Can be absent for function return argument.
365 """
366 return self._properties.get(self._PROPERTY_TO_API_FIELD["name"])
368 @name.setter
369 def name(self, value):
370 self._properties[self._PROPERTY_TO_API_FIELD["name"]] = value
372 @property
373 def kind(self):
374 """Optional[str]: The kind of argument, for example ``FIXED_TYPE`` or
375 ``ANY_TYPE``.
377 See:
378 https://cloud.google.com/bigquery/docs/reference/rest/v2/routines#Argument.FIELDS.argument_kind
379 """
380 return self._properties.get(self._PROPERTY_TO_API_FIELD["kind"])
382 @kind.setter
383 def kind(self, value):
384 self._properties[self._PROPERTY_TO_API_FIELD["kind"]] = value
386 @property
387 def mode(self):
388 """Optional[str]: The input/output mode of the argument."""
389 return self._properties.get(self._PROPERTY_TO_API_FIELD["mode"])
391 @mode.setter
392 def mode(self, value):
393 self._properties[self._PROPERTY_TO_API_FIELD["mode"]] = value
395 @property
396 def data_type(self):
397 """Optional[google.cloud.bigquery.StandardSqlDataType]: Type
398 of a variable, e.g., a function argument.
400 See:
401 https://cloud.google.com/bigquery/docs/reference/rest/v2/routines#Argument.FIELDS.data_type
402 """
403 resource = self._properties.get(self._PROPERTY_TO_API_FIELD["data_type"])
404 if not resource:
405 return resource
407 return StandardSqlDataType.from_api_repr(resource)
409 @data_type.setter
410 def data_type(self, value):
411 if value:
412 resource = value.to_api_repr()
413 else:
414 resource = None
415 self._properties[self._PROPERTY_TO_API_FIELD["data_type"]] = resource
417 @classmethod
418 def from_api_repr(cls, resource: dict) -> "RoutineArgument":
419 """Factory: construct a routine argument given its API representation.
421 Args:
422 resource (Dict[str, object]): Resource, as returned from the API.
424 Returns:
425 google.cloud.bigquery.routine.RoutineArgument:
426 Python object, as parsed from ``resource``.
427 """
428 ref = cls()
429 ref._properties = resource
430 return ref
432 def to_api_repr(self) -> dict:
433 """Construct the API resource representation of this routine argument.
435 Returns:
436 Dict[str, object]: Routine argument represented as an API resource.
437 """
438 return self._properties
440 def __eq__(self, other):
441 if not isinstance(other, RoutineArgument):
442 return NotImplemented
443 return self._properties == other._properties
445 def __ne__(self, other):
446 return not self == other
448 def __repr__(self):
449 all_properties = [
450 "{}={}".format(property_name, repr(getattr(self, property_name)))
451 for property_name in sorted(self._PROPERTY_TO_API_FIELD)
452 ]
453 return "RoutineArgument({})".format(", ".join(all_properties))
456class RoutineReference(object):
457 """A pointer to a routine.
459 See:
460 https://cloud.google.com/bigquery/docs/reference/rest/v2/routines#routinereference
461 """
463 def __init__(self):
464 self._properties = {}
466 @property
467 def project(self):
468 """str: ID of the project containing the routine."""
469 return self._properties["projectId"] # pytype: disable=key-error
471 @property
472 def dataset_id(self):
473 """str: ID of dataset containing the routine."""
474 return self._properties["datasetId"] # pytype: disable=key-error
476 @property
477 def routine_id(self):
478 """str: The routine ID."""
479 return self._properties["routineId"] # pytype: disable=key-error
481 @property
482 def path(self):
483 """str: URL path for the routine's APIs."""
484 return "/projects/%s/datasets/%s/routines/%s" % (
485 self.project,
486 self.dataset_id,
487 self.routine_id,
488 )
490 @classmethod
491 def from_api_repr(cls, resource: dict) -> "RoutineReference":
492 """Factory: construct a routine reference given its API representation.
494 Args:
495 resource (Dict[str, object]):
496 Routine reference representation returned from the API.
498 Returns:
499 google.cloud.bigquery.routine.RoutineReference:
500 Routine reference parsed from ``resource``.
501 """
502 ref = cls()
503 ref._properties = resource
504 return ref
506 @classmethod
507 def from_string(
508 cls, routine_id: str, default_project: str = None
509 ) -> "RoutineReference":
510 """Factory: construct a routine reference from routine ID string.
512 Args:
513 routine_id (str):
514 A routine ID in standard SQL format. If ``default_project``
515 is not specified, this must included a project ID, dataset
516 ID, and routine ID, each separated by ``.``.
517 default_project (Optional[str]):
518 The project ID to use when ``routine_id`` does not
519 include a project ID.
521 Returns:
522 google.cloud.bigquery.routine.RoutineReference:
523 Routine reference parsed from ``routine_id``.
525 Raises:
526 ValueError:
527 If ``routine_id`` is not a fully-qualified routine ID in
528 standard SQL format.
529 """
530 proj, dset, routine = _helpers._parse_3_part_id(
531 routine_id, default_project=default_project, property_name="routine_id"
532 )
533 return cls.from_api_repr(
534 {"projectId": proj, "datasetId": dset, "routineId": routine}
535 )
537 def to_api_repr(self) -> dict:
538 """Construct the API resource representation of this routine reference.
540 Returns:
541 Dict[str, object]: Routine reference represented as an API resource.
542 """
543 return self._properties
545 def __eq__(self, other):
546 """Two RoutineReferences are equal if they point to the same routine."""
547 if not isinstance(other, RoutineReference):
548 return NotImplemented
549 return str(self) == str(other)
551 def __hash__(self):
552 return hash(str(self))
554 def __ne__(self, other):
555 return not self == other
557 def __repr__(self):
558 return "RoutineReference.from_string('{}')".format(str(self))
560 def __str__(self):
561 """String representation of the reference.
563 This is a fully-qualified ID, including the project ID and dataset ID.
564 """
565 return "{}.{}.{}".format(self.project, self.dataset_id, self.routine_id)