Skip to content

Commit 0307017

Browse files
committed
feat: support range sql
1 parent 6249032 commit 0307017

File tree

4 files changed

+84
-2
lines changed

4 files changed

+84
-2
lines changed

google/cloud/bigquery/client.py

+27-1
Original file line numberDiff line numberDiff line change
@@ -2860,7 +2860,34 @@ def load_table_from_json(
28602860

28612861
data_str = "\n".join(json.dumps(item, ensure_ascii=False) for item in json_rows)
28622862
encoded_str = data_str.encode()
2863+
#print(encoded_str)
2864+
#print(len(encoded_str))
28632865
data_file = io.BytesIO(encoded_str)
2866+
#print(data_file)
2867+
#print(data_file.getvalue())
2868+
2869+
#with open("temp.json", "w") as f:
2870+
#b = bytes(encoded_str)
2871+
#json_file = json.dump(b, f)
2872+
# f.write(data_str)
2873+
#f.close()
2874+
2875+
if False:
2876+
with open("temp.json", "rb") as f:
2877+
return self.load_table_from_file(
2878+
f,
2879+
# data_file,
2880+
destination,
2881+
size=len(encoded_str),
2882+
num_retries=num_retries,
2883+
job_id=job_id,
2884+
job_id_prefix=job_id_prefix,
2885+
location=location,
2886+
project=project,
2887+
job_config=new_job_config,
2888+
timeout=timeout,
2889+
)
2890+
28642891
return self.load_table_from_file(
28652892
data_file,
28662893
destination,
@@ -2873,7 +2900,6 @@ def load_table_from_json(
28732900
job_config=new_job_config,
28742901
timeout=timeout,
28752902
)
2876-
28772903
def _do_resumable_upload(
28782904
self,
28792905
stream: IO[bytes],

google/cloud/bigquery/enums.py

+2
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ def _generate_next_value_(name, start, count, last_values):
254254
JSON = enum.auto()
255255
ARRAY = enum.auto()
256256
STRUCT = enum.auto()
257+
RANGE = enum.auto()
257258

258259

259260
class EntityTypes(str, enum.Enum):
@@ -292,6 +293,7 @@ class SqlTypeNames(str, enum.Enum):
292293
TIME = "TIME"
293294
DATETIME = "DATETIME"
294295
INTERVAL = "INTERVAL" # NOTE: not available in legacy types
296+
RANGE = "RANGE"
295297

296298

297299
class WriteDisposition(object):

google/cloud/bigquery/standard_sql.py

+34-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class StandardSqlDataType:
5252
The type of the array's elements, if type_kind is ARRAY.
5353
struct_type:
5454
The fields of this struct, in order, if type_kind is STRUCT.
55+
range_element_type:
56+
The type of the range's elements, if type_kind = "RANGE".
5557
"""
5658

5759
def __init__(
@@ -61,12 +63,14 @@ def __init__(
6163
] = StandardSqlTypeNames.TYPE_KIND_UNSPECIFIED,
6264
array_element_type: Optional["StandardSqlDataType"] = None,
6365
struct_type: Optional["StandardSqlStructType"] = None,
66+
range_element_type: Optional["StandardSqlDataType"] = None,
6467
):
6568
self._properties: Dict[str, Any] = {}
6669

6770
self.type_kind = type_kind
6871
self.array_element_type = array_element_type
6972
self.struct_type = struct_type
73+
self.range_element_type = range_element_type
7074

7175
@property
7276
def type_kind(self) -> Optional[StandardSqlTypeNames]:
@@ -127,6 +131,28 @@ def struct_type(self, value: Optional["StandardSqlStructType"]):
127131
else:
128132
self._properties["structType"] = struct_type
129133

134+
@property
135+
def range_element_type(self) -> Optional["StandardSqlDataType"]:
136+
"""The type of the range's elements, if type_kind = "RANGE". Must be
137+
one of DATETIME, DATE, or TIMESTAMP."""
138+
range_element_info = self._properties.get("rangeElementType")
139+
140+
if range_element_info is None:
141+
return None
142+
143+
result = StandardSqlDataType()
144+
result._properties = range_element_info # We do not use a copy on purpose.
145+
return result
146+
147+
@struct_type.setter
148+
def range_element_type(self, value: Optional["StandardSqlDataType"]):
149+
range_element_type = None if value is None else value.to_api_repr()
150+
151+
if range_element_type is None:
152+
self._properties.pop("rangeElementType", None)
153+
else:
154+
self._properties["rangeElementType"] = range_element_type
155+
130156
def to_api_repr(self) -> Dict[str, Any]:
131157
"""Construct the API resource representation of this SQL data type."""
132158
return copy.deepcopy(self._properties)
@@ -155,7 +181,13 @@ def from_api_repr(cls, resource: Dict[str, Any]):
155181
if struct_info:
156182
struct_type = StandardSqlStructType.from_api_repr(struct_info)
157183

158-
return cls(type_kind, array_element_type, struct_type)
184+
range_element_type = None
185+
if type_kind == StandardSqlTypeNames.RANGE:
186+
range_element_info = resource.get("rangeElementType")
187+
if range_element_info:
188+
range_element_type = cls.from_api_repr(range_element_info)
189+
190+
return cls(type_kind, array_element_type, struct_type, range_element_type)
159191

160192
def __eq__(self, other):
161193
if not isinstance(other, StandardSqlDataType):
@@ -165,6 +197,7 @@ def __eq__(self, other):
165197
self.type_kind == other.type_kind
166198
and self.array_element_type == other.array_element_type
167199
and self.struct_type == other.struct_type
200+
and self.range_element_type == other.range_element_type
168201
)
169202

170203
def __str__(self):

tests/unit/test_standard_sql_types.py

+21
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,22 @@ def test_from_api_repr_struct_type_incomplete_field_info(self):
276276
)
277277
assert result == expected
278278

279+
def test_from_api_repr_range_type():
280+
pass
281+
282+
def test_from_api_repr_range_type_missing_element():
283+
pass
284+
285+
def test_from_api_repr_range_type_invalid_element():
286+
pass
287+
288+
def test_to_api_repr_range_type_element_type_missing():
289+
pass
290+
291+
def test_to_api_repr_range_type_w_element_type():
292+
pass
293+
294+
279295
def test__eq__another_type(self):
280296
instance = self._make_one()
281297

@@ -321,6 +337,11 @@ def test__eq__similar_instance(self):
321337
bq.StandardSqlStructType(fields=[bq.StandardSqlField(name="foo")]),
322338
bq.StandardSqlStructType(fields=[bq.StandardSqlField(name="bar")]),
323339
),
340+
(
341+
"range_element_type",
342+
bq.StandardSqlDataType(type_kind=bq.StandardSqlTypeNames.DATE),
343+
bq.StandardSqlDataType(type_kind=bq.StandardSqlTypeNames.DATE),
344+
),
324345
),
325346
)
326347
def test__eq__attribute_differs(self, attr_name, value, value2):

0 commit comments

Comments
 (0)