| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| # |
| from datetime import datetime |
| |
| import numpy as np |
| |
| from tsfile.constants import TSDataType |
| from tsfile.date_utils import parse_date_to_int, parse_int_to_date |
| |
| |
| class NoneDataTypeException(Exception): |
| pass |
| |
| |
| class Field(object): |
| def __init__(self, field_name, value=None, data_type=None): |
| """ |
| :param field_name: field's name |
| :param data_type: TSDataType |
| """ |
| self.field_name = field_name |
| self.data_type = data_type |
| self.value = value |
| |
| def get_data_type(self): |
| return self.data_type |
| |
| def get_field_name(self): |
| return self.field_name |
| |
| def is_null(self): |
| return self.value is None |
| |
| def set_value(self, value): |
| self.value = value |
| |
| def set_data_type(self, data_type): |
| self.data_type = data_type |
| |
| def get_value(self): |
| return self.value |
| |
| def get_bool_value(self): |
| if self.value is None: |
| return None |
| if self.data_type is None: |
| raise NoneDataTypeException("None Data Type Exception!") |
| if self.data_type != TSDataType.BOOLEAN: |
| raise TypeError(f"Expected BOOLEAN data type, got {self.data_type}.") |
| |
| if isinstance(self.value, bool): |
| return self.value |
| else: |
| raise TypeError(f"Value is not a boolean: {type(self.value)}") |
| |
| def get_int_value(self): |
| if self.value is None: |
| return None |
| if self.data_type is None: |
| raise NoneDataTypeException("None Data Type Exception!") |
| |
| if ( |
| self.data_type != TSDataType.INT32 |
| and self.data_type != TSDataType.DATE |
| and self.data_type != TSDataType.INT64 |
| and self.data_type != TSDataType.FLOAT |
| and self.data_type != TSDataType.DOUBLE |
| ): |
| raise TypeError( |
| f"Expected INT32/64 or DOUBLE/FLOAT data type, got {self.data_type}." |
| ) |
| min_int32, max_int32 = np.iinfo(np.int32).min, np.iinfo(np.int32).max |
| if self.data_type == TSDataType.DATE: |
| return parse_date_to_int(self.value) |
| |
| if not (min_int32 <= self.value <= max_int32): |
| raise OverflowError( |
| f"Value {self.value} exceeds int range [{min_int32}, {max_int32}]" |
| ) |
| return np.int32(self.value) |
| |
| def get_long_value(self): |
| if self.value is None: |
| return None |
| if self.data_type is None: |
| raise NoneDataTypeException("None Data Type Exception!") |
| |
| if ( |
| self.data_type != TSDataType.INT32 |
| and self.data_type != TSDataType.INT64 |
| and self.data_type != TSDataType.FLOAT |
| and self.data_type != TSDataType.DOUBLE |
| ): |
| raise TypeError( |
| f"Expected INT32/64 or DOUBLE/FLOAT data type, got {self.data_type}." |
| ) |
| |
| return np.int64(self.value) |
| |
| def get_timestamp_value(self): |
| if self.value is None: |
| return None |
| if self.data_type is None: |
| raise NoneDataTypeException("None Data Type Exception!") |
| if ( |
| self.data_type != TSDataType.TIMESTAMP |
| and self.data_type != TSDataType.INT64 |
| ): |
| raise TypeError( |
| f"Expected INT64/TIMESTAMP data type, got {self.data_type}." |
| ) |
| return np.int64(self.value) |
| |
| def get_float_value(self): |
| if self.value is None: |
| return None |
| if self.data_type is None: |
| raise NoneDataTypeException("None Data Type Exception!") |
| if ( |
| self.data_type != TSDataType.INT32 |
| and self.data_type != TSDataType.INT64 |
| and self.data_type != TSDataType.FLOAT |
| and self.data_type != TSDataType.DOUBLE |
| ): |
| raise TypeError( |
| f"Expected INT32/64 or DOUBLE/FLOAT data type, got {self.data_type}." |
| ) |
| min_float32, max_float32 = np.finfo(np.float32).min, np.finfo(np.float32).max |
| if not (min_float32 <= self.value <= max_float32): |
| raise OverflowError( |
| f"Value {self.value} exceeds float range [{min_float32}, {max_float32}]" |
| ) |
| |
| return np.float32(self.value) |
| |
| def get_double_value(self): |
| if self.value is None: |
| return None |
| if self.data_type is None: |
| raise NoneDataTypeException("None Data Type Exception!") |
| if ( |
| self.data_type != TSDataType.INT32 |
| and self.data_type != TSDataType.INT64 |
| and self.data_type != TSDataType.FLOAT |
| and self.data_type != TSDataType.DOUBLE |
| ): |
| raise TypeError( |
| f"Expected INT32/64 or DOUBLE/FLOAT data type, got {self.data_type}." |
| ) |
| return np.float64(self.value) |
| |
| def get_date_value(self): |
| if self.value is None: |
| return None |
| if self.data_type is None: |
| raise NoneDataTypeException("None Data Type Exception!") |
| if self.data_type != TSDataType.DATE and self.data_type != TSDataType.INT64: |
| raise TypeError(f"Expected DATE/INT64 data type, got {self.data_type}.") |
| if isinstance(self.value, datetime): |
| return self.value |
| elif isinstance(self.value, int): |
| return parse_int_to_date(self.value) |
| else: |
| raise TypeError(f"Value is not a int or datetime: {type(self.value)}") |
| |
| def get_string_value(self): |
| if self.value is None: |
| return None |
| if self.data_type is None: |
| raise NoneDataTypeException("None Data Type Exception!") |
| |
| # TEXT, STRING |
| if self.data_type == TSDataType.TEXT or self.data_type == TSDataType.STRING: |
| return str(self.value) |
| # BLOB |
| elif self.data_type == TSDataType.BLOB: |
| return self.value |
| else: |
| return str(self.get_object_value(self.data_type)) |
| |
| def get_bytes_value(self): |
| if self.value is None: |
| return None |
| if self.data_type is None: |
| raise NoneDataTypeException("None Data Type Exception!") |
| |
| if self.data_type == TSDataType.BLOB: |
| return self.value |
| else: |
| raise TypeError("get_bytes_value() only supports BLOB data type") |
| |
| def __str__(self): |
| return self.get_string_value() |
| |
| def get_object_value(self, data_type: TSDataType): |
| """ |
| :param data_type: TSDataType |
| """ |
| if self.value is None: |
| return None |
| if data_type == TSDataType.BOOLEAN: |
| return bool(self.value) |
| elif data_type == TSDataType.INT32: |
| return np.int32(self.value) |
| elif data_type == TSDataType.INT64 or data_type == TSDataType.TIMESTAMP: |
| return np.int64(self.value) |
| elif data_type == TSDataType.FLOAT: |
| return np.float32(self.value) |
| elif data_type == TSDataType.DOUBLE: |
| return np.float64(self.value) |
| elif data_type == TSDataType.DATE: |
| if isinstance(self.value, datetime): |
| return self.value |
| elif isinstance(self.value, int): |
| return parse_int_to_date(self.value) |
| elif ( |
| data_type == TSDataType.TEXT |
| or data_type == TSDataType.BLOB |
| or data_type == TSDataType.STRING |
| ): |
| return self.value |
| else: |
| raise RuntimeError("Unsupported data type:" + str(data_type)) |