Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/google/cloud/bigquery/standard_sql.py: 35%
162 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# Copyright 2021 Google LLC
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
7# https://www.apache.org/licenses/LICENSE-2.0
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.
15import copy
16import typing
17from typing import Any, Dict, Iterable, List, Optional
19from google.cloud.bigquery.enums import StandardSqlTypeNames
22class StandardSqlDataType:
23 """The type of a variable, e.g., a function argument.
25 See:
26 https://cloud.google.com/bigquery/docs/reference/rest/v2/StandardSqlDataType
28 Examples:
30 .. code-block:: text
32 INT64: {type_kind="INT64"}
33 ARRAY: {type_kind="ARRAY", array_element_type="STRING"}
34 STRUCT<x STRING, y ARRAY>: {
35 type_kind="STRUCT",
36 struct_type={
37 fields=[
38 {name="x", type={type_kind="STRING"}},
39 {
40 name="y",
41 type={type_kind="ARRAY", array_element_type="DATE"}
42 }
43 ]
44 }
45 }
47 Args:
48 type_kind:
49 The top level type of this field. Can be any standard SQL data type,
50 e.g. INT64, DATE, ARRAY.
51 array_element_type:
52 The type of the array's elements, if type_kind is ARRAY.
53 struct_type:
54 The fields of this struct, in order, if type_kind is STRUCT.
55 """
57 def __init__(
58 self,
59 type_kind: Optional[
60 StandardSqlTypeNames
61 ] = StandardSqlTypeNames.TYPE_KIND_UNSPECIFIED,
62 array_element_type: Optional["StandardSqlDataType"] = None,
63 struct_type: Optional["StandardSqlStructType"] = None,
64 ):
65 self._properties: Dict[str, Any] = {}
67 self.type_kind = type_kind
68 self.array_element_type = array_element_type
69 self.struct_type = struct_type
71 @property
72 def type_kind(self) -> Optional[StandardSqlTypeNames]:
73 """The top level type of this field.
75 Can be any standard SQL data type, e.g. INT64, DATE, ARRAY.
76 """
77 kind = self._properties["typeKind"]
78 return StandardSqlTypeNames[kind] # pytype: disable=missing-parameter
80 @type_kind.setter
81 def type_kind(self, value: Optional[StandardSqlTypeNames]):
82 if not value:
83 kind = StandardSqlTypeNames.TYPE_KIND_UNSPECIFIED.value
84 else:
85 kind = value.value
86 self._properties["typeKind"] = kind
88 @property
89 def array_element_type(self) -> Optional["StandardSqlDataType"]:
90 """The type of the array's elements, if type_kind is ARRAY."""
91 element_type = self._properties.get("arrayElementType")
93 if element_type is None:
94 return None
96 result = StandardSqlDataType()
97 result._properties = element_type # We do not use a copy on purpose.
98 return result
100 @array_element_type.setter
101 def array_element_type(self, value: Optional["StandardSqlDataType"]):
102 element_type = None if value is None else value.to_api_repr()
104 if element_type is None:
105 self._properties.pop("arrayElementType", None)
106 else:
107 self._properties["arrayElementType"] = element_type
109 @property
110 def struct_type(self) -> Optional["StandardSqlStructType"]:
111 """The fields of this struct, in order, if type_kind is STRUCT."""
112 struct_info = self._properties.get("structType")
114 if struct_info is None:
115 return None
117 result = StandardSqlStructType()
118 result._properties = struct_info # We do not use a copy on purpose.
119 return result
121 @struct_type.setter
122 def struct_type(self, value: Optional["StandardSqlStructType"]):
123 struct_type = None if value is None else value.to_api_repr()
125 if struct_type is None:
126 self._properties.pop("structType", None)
127 else:
128 self._properties["structType"] = struct_type
130 def to_api_repr(self) -> Dict[str, Any]:
131 """Construct the API resource representation of this SQL data type."""
132 return copy.deepcopy(self._properties)
134 @classmethod
135 def from_api_repr(cls, resource: Dict[str, Any]):
136 """Construct an SQL data type instance given its API representation."""
137 type_kind = resource.get("typeKind")
138 if type_kind not in StandardSqlTypeNames.__members__:
139 type_kind = StandardSqlTypeNames.TYPE_KIND_UNSPECIFIED
140 else:
141 # Convert string to an enum member.
142 type_kind = StandardSqlTypeNames[ # pytype: disable=missing-parameter
143 typing.cast(str, type_kind)
144 ]
146 array_element_type = None
147 if type_kind == StandardSqlTypeNames.ARRAY:
148 element_type = resource.get("arrayElementType")
149 if element_type:
150 array_element_type = cls.from_api_repr(element_type)
152 struct_type = None
153 if type_kind == StandardSqlTypeNames.STRUCT:
154 struct_info = resource.get("structType")
155 if struct_info:
156 struct_type = StandardSqlStructType.from_api_repr(struct_info)
158 return cls(type_kind, array_element_type, struct_type)
160 def __eq__(self, other):
161 if not isinstance(other, StandardSqlDataType):
162 return NotImplemented
163 else:
164 return (
165 self.type_kind == other.type_kind
166 and self.array_element_type == other.array_element_type
167 and self.struct_type == other.struct_type
168 )
170 def __str__(self):
171 result = f"{self.__class__.__name__}(type_kind={self.type_kind!r}, ...)"
172 return result
175class StandardSqlField:
176 """A field or a column.
178 See:
179 https://cloud.google.com/bigquery/docs/reference/rest/v2/StandardSqlField
181 Args:
182 name:
183 The name of this field. Can be absent for struct fields.
184 type:
185 The type of this parameter. Absent if not explicitly specified.
187 For example, CREATE FUNCTION statement can omit the return type; in this
188 case the output parameter does not have this "type" field).
189 """
191 def __init__(
192 self, name: Optional[str] = None, type: Optional[StandardSqlDataType] = None
193 ):
194 type_repr = None if type is None else type.to_api_repr()
195 self._properties = {"name": name, "type": type_repr}
197 @property
198 def name(self) -> Optional[str]:
199 """The name of this field. Can be absent for struct fields."""
200 return typing.cast(Optional[str], self._properties["name"])
202 @name.setter
203 def name(self, value: Optional[str]):
204 self._properties["name"] = value
206 @property
207 def type(self) -> Optional[StandardSqlDataType]:
208 """The type of this parameter. Absent if not explicitly specified.
210 For example, CREATE FUNCTION statement can omit the return type; in this
211 case the output parameter does not have this "type" field).
212 """
213 type_info = self._properties["type"]
215 if type_info is None:
216 return None
218 result = StandardSqlDataType()
219 # We do not use a properties copy on purpose.
220 result._properties = typing.cast(Dict[str, Any], type_info)
222 return result
224 @type.setter
225 def type(self, value: Optional[StandardSqlDataType]):
226 value_repr = None if value is None else value.to_api_repr()
227 self._properties["type"] = value_repr
229 def to_api_repr(self) -> Dict[str, Any]:
230 """Construct the API resource representation of this SQL field."""
231 return copy.deepcopy(self._properties)
233 @classmethod
234 def from_api_repr(cls, resource: Dict[str, Any]):
235 """Construct an SQL field instance given its API representation."""
236 result = cls(
237 name=resource.get("name"),
238 type=StandardSqlDataType.from_api_repr(resource.get("type", {})),
239 )
240 return result
242 def __eq__(self, other):
243 if not isinstance(other, StandardSqlField):
244 return NotImplemented
245 else:
246 return self.name == other.name and self.type == other.type
249class StandardSqlStructType:
250 """Type of a struct field.
252 See:
253 https://cloud.google.com/bigquery/docs/reference/rest/v2/StandardSqlDataType#StandardSqlStructType
255 Args:
256 fields: The fields in this struct.
257 """
259 def __init__(self, fields: Optional[Iterable[StandardSqlField]] = None):
260 if fields is None:
261 fields = []
262 self._properties = {"fields": [field.to_api_repr() for field in fields]}
264 @property
265 def fields(self) -> List[StandardSqlField]:
266 """The fields in this struct."""
267 result = []
269 for field_resource in self._properties.get("fields", []):
270 field = StandardSqlField()
271 field._properties = field_resource # We do not use a copy on purpose.
272 result.append(field)
274 return result
276 @fields.setter
277 def fields(self, value: Iterable[StandardSqlField]):
278 self._properties["fields"] = [field.to_api_repr() for field in value]
280 def to_api_repr(self) -> Dict[str, Any]:
281 """Construct the API resource representation of this SQL struct type."""
282 return copy.deepcopy(self._properties)
284 @classmethod
285 def from_api_repr(cls, resource: Dict[str, Any]) -> "StandardSqlStructType":
286 """Construct an SQL struct type instance given its API representation."""
287 fields = (
288 StandardSqlField.from_api_repr(field_resource)
289 for field_resource in resource.get("fields", [])
290 )
291 return cls(fields=fields)
293 def __eq__(self, other):
294 if not isinstance(other, StandardSqlStructType):
295 return NotImplemented
296 else:
297 return self.fields == other.fields
300class StandardSqlTableType:
301 """A table type.
303 See:
304 https://cloud.google.com/workflows/docs/reference/googleapis/bigquery/v2/Overview#StandardSqlTableType
306 Args:
307 columns: The columns in this table type.
308 """
310 def __init__(self, columns: Iterable[StandardSqlField]):
311 self._properties = {"columns": [col.to_api_repr() for col in columns]}
313 @property
314 def columns(self) -> List[StandardSqlField]:
315 """The columns in this table type."""
316 result = []
318 for column_resource in self._properties.get("columns", []):
319 column = StandardSqlField()
320 column._properties = column_resource # We do not use a copy on purpose.
321 result.append(column)
323 return result
325 @columns.setter
326 def columns(self, value: Iterable[StandardSqlField]):
327 self._properties["columns"] = [col.to_api_repr() for col in value]
329 def to_api_repr(self) -> Dict[str, Any]:
330 """Construct the API resource representation of this SQL table type."""
331 return copy.deepcopy(self._properties)
333 @classmethod
334 def from_api_repr(cls, resource: Dict[str, Any]) -> "StandardSqlTableType":
335 """Construct an SQL table type instance given its API representation."""
336 columns = []
338 for column_resource in resource.get("columns", []):
339 type_ = column_resource.get("type")
340 if type_ is None:
341 type_ = {}
343 column = StandardSqlField(
344 name=column_resource.get("name"),
345 type=StandardSqlDataType.from_api_repr(type_),
346 )
347 columns.append(column)
349 return cls(columns=columns)
351 def __eq__(self, other):
352 if not isinstance(other, StandardSqlTableType):
353 return NotImplemented
354 else:
355 return self.columns == other.columns