use greptimedb_proto::v1::{self as proto, column_data_type_extension::TypeExt, value::ValueData};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[repr(i32)]
pub enum SemanticType {
Tag = 0,
Field = 1,
Timestamp = 2,
}
impl SemanticType {
pub const fn to_proto(self) -> i32 {
self as i32
}
pub const fn as_flight_str(self) -> &'static str {
match self {
Self::Tag => "tag",
Self::Field => "field",
Self::Timestamp => "timestamp",
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum TimestampUnit {
Second,
Millisecond,
Microsecond,
#[default]
Nanosecond,
}
impl TimestampUnit {
pub const fn to_column_data_type(self) -> ColumnDataType {
match self {
Self::Second => ColumnDataType::TimestampSecond,
Self::Millisecond => ColumnDataType::TimestampMillisecond,
Self::Microsecond => ColumnDataType::TimestampMicrosecond,
Self::Nanosecond => ColumnDataType::TimestampNanosecond,
}
}
pub const fn one_hour_ticks(self) -> i64 {
match self {
Self::Second => 3_600,
Self::Millisecond => 3_600_000,
Self::Microsecond => 3_600_000_000,
Self::Nanosecond => 3_600_000_000_000,
}
}
}
macro_rules! temporal_type {
($name:ident, $storage:ty, $description:literal) => {
#[doc = $description]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct $name(pub $storage);
};
}
temporal_type!(TimestampSecond, i64, "Unix timestamp in seconds.");
temporal_type!(TimestampMillisecond, i64, "Unix timestamp in milliseconds.");
temporal_type!(TimestampMicrosecond, i64, "Unix timestamp in microseconds.");
temporal_type!(TimestampNanosecond, i64, "Unix timestamp in nanoseconds.");
temporal_type!(Date, i32, "Days since the Unix epoch.");
temporal_type!(DateTime, i64, "An i64 GreptimeDB DATETIME wire value.");
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Decimal128 {
pub value: i128,
pub precision: u32,
pub scale: u32,
}
impl Decimal128 {
pub const fn new(value: i128, precision: u32, scale: u32) -> Self {
Self {
value,
precision,
scale,
}
}
pub const fn hi(self) -> i64 {
(self.value >> 64) as i64
}
pub const fn lo(self) -> u64 {
self.value as u64
}
pub fn to_proto(self) -> proto::Decimal128 {
proto::Decimal128 {
hi: self.hi(),
lo: self.lo() as i64,
}
}
pub fn from_proto(proto: proto::Decimal128, precision: u32, scale: u32) -> Self {
let value = (i128::from(proto.hi) << 64) | i128::from(proto.lo as u64);
Self::new(value, precision, scale)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum ColumnDataType {
Boolean,
Int8,
Int16,
Int32,
Int64,
Uint8,
Uint16,
Uint32,
Uint64,
Float32,
Float64,
Binary,
String,
Date,
DateTime,
TimestampSecond,
TimestampMillisecond,
TimestampMicrosecond,
TimestampNanosecond,
Decimal128 {
precision: u32,
scale: u32,
},
Json,
}
impl ColumnDataType {
pub const fn to_proto_datatype(self) -> i32 {
match self {
Self::Boolean => proto::ColumnDataType::Boolean as i32,
Self::Int8 => proto::ColumnDataType::Int8 as i32,
Self::Int16 => proto::ColumnDataType::Int16 as i32,
Self::Int32 => proto::ColumnDataType::Int32 as i32,
Self::Int64 => proto::ColumnDataType::Int64 as i32,
Self::Uint8 => proto::ColumnDataType::Uint8 as i32,
Self::Uint16 => proto::ColumnDataType::Uint16 as i32,
Self::Uint32 => proto::ColumnDataType::Uint32 as i32,
Self::Uint64 => proto::ColumnDataType::Uint64 as i32,
Self::Float32 => proto::ColumnDataType::Float32 as i32,
Self::Float64 => proto::ColumnDataType::Float64 as i32,
Self::Binary | Self::Json => proto::ColumnDataType::Binary as i32,
Self::String => proto::ColumnDataType::String as i32,
Self::Date => proto::ColumnDataType::Date as i32,
Self::DateTime => proto::ColumnDataType::Datetime as i32,
Self::TimestampSecond => proto::ColumnDataType::TimestampSecond as i32,
Self::TimestampMillisecond => proto::ColumnDataType::TimestampMillisecond as i32,
Self::TimestampMicrosecond => proto::ColumnDataType::TimestampMicrosecond as i32,
Self::TimestampNanosecond => proto::ColumnDataType::TimestampNanosecond as i32,
Self::Decimal128 { .. } => proto::ColumnDataType::Decimal128 as i32,
}
}
pub fn to_proto_extension(self) -> Option<proto::ColumnDataTypeExtension> {
let type_ext = match self {
Self::Decimal128 { precision, scale } => {
TypeExt::DecimalType(proto::DecimalTypeExtension {
precision: precision.min(i32::MAX as u32) as i32,
scale: scale.min(i32::MAX as u32) as i32,
})
}
Self::Json => TypeExt::JsonType(proto::JsonTypeExtension::JsonBinary as i32),
_ => return None,
};
Some(proto::ColumnDataTypeExtension {
type_ext: Some(type_ext),
})
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
Null,
Boolean(bool),
Int8(i8),
Int16(i16),
Int32(i32),
Int64(i64),
Uint8(u8),
Uint16(u16),
Uint32(u32),
Uint64(u64),
Float32(f32),
Float64(f64),
Binary(&'a [u8]),
String(&'a str),
Date(Date),
DateTime(DateTime),
TimestampSecond(i64),
TimestampMillisecond(i64),
TimestampMicrosecond(i64),
TimestampNanosecond(i64),
Decimal128(Decimal128),
Json(&'a str),
}
impl ValueRef<'_> {
pub fn to_proto_value(&self) -> proto::Value {
let value_data = match self {
Self::Null => None,
Self::Boolean(value) => Some(ValueData::BoolValue(*value)),
Self::Int8(value) => Some(ValueData::I8Value(i32::from(*value))),
Self::Int16(value) => Some(ValueData::I16Value(i32::from(*value))),
Self::Int32(value) => Some(ValueData::I32Value(*value)),
Self::Int64(value) => Some(ValueData::I64Value(*value)),
Self::Uint8(value) => Some(ValueData::U8Value(u32::from(*value))),
Self::Uint16(value) => Some(ValueData::U16Value(u32::from(*value))),
Self::Uint32(value) => Some(ValueData::U32Value(*value)),
Self::Uint64(value) => Some(ValueData::U64Value(*value)),
Self::Float32(value) => Some(ValueData::F32Value(*value)),
Self::Float64(value) => Some(ValueData::F64Value(*value)),
Self::Binary(value) => Some(ValueData::BinaryValue(value.to_vec())),
Self::String(value) => Some(ValueData::StringValue((*value).to_owned())),
Self::Date(value) => Some(ValueData::DateValue(value.0)),
Self::DateTime(value) => Some(ValueData::DatetimeValue(value.0)),
Self::TimestampSecond(value) => Some(ValueData::TimestampSecondValue(*value)),
Self::TimestampMillisecond(value) => Some(ValueData::TimestampMillisecondValue(*value)),
Self::TimestampMicrosecond(value) => Some(ValueData::TimestampMicrosecondValue(*value)),
Self::TimestampNanosecond(value) => Some(ValueData::TimestampNanosecondValue(*value)),
Self::Decimal128(value) => Some(ValueData::Decimal128Value(value.to_proto())),
Self::Json(value) => Some(ValueData::BinaryValue(value.as_bytes().to_vec())),
};
proto::Value { value_data }
}
}