blob: af2765c44551563f095b418d9dc2a160c37acfc2 [file]
// 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.
use crate::error::Error::IllegalArgument;
use crate::error::Result;
use crate::metadata::DataType;
use crate::row::Datum;
use crate::row::binary::BinaryRowFormat;
/// Writer to write a composite data format, like row, array,
#[allow(dead_code)]
pub trait BinaryWriter {
/// Reset writer to prepare next write
fn reset(&mut self);
/// Set null to this field
fn set_null_at(&mut self, pos: usize);
fn write_boolean(&mut self, value: bool);
fn write_byte(&mut self, value: u8);
fn write_bytes(&mut self, value: &[u8]);
fn write_char(&mut self, value: &str, length: usize);
fn write_string(&mut self, value: &str);
fn write_short(&mut self, value: i16);
fn write_int(&mut self, value: i32);
fn write_long(&mut self, value: i64);
fn write_float(&mut self, value: f32);
fn write_double(&mut self, value: f64);
fn write_binary(&mut self, bytes: &[u8], length: usize);
fn write_decimal(&mut self, value: &crate::row::Decimal, precision: u32);
/// Writes a TIME value.
///
/// Note: TIME is physically stored as an i32 (milliseconds since midnight).
/// This method exists for type safety and semantic clarity, even though it's
/// currently equivalent to `write_int()`. The precision parameter is accepted
/// for API consistency with TIMESTAMP types, though TIME encoding doesn't
/// currently vary by precision.
fn write_time(&mut self, value: i32, precision: u32);
fn write_timestamp_ntz(&mut self, value: &crate::row::datum::TimestampNtz, precision: u32);
fn write_timestamp_ltz(&mut self, value: &crate::row::datum::TimestampLtz, precision: u32);
// TODO InternalArray, ArraySerializer
// fn write_array(&mut self, pos: i32, value: i64);
// TODO Row serializer
// fn write_row(&mut self, pos: i32, value: &InternalRow);
/// Finally, complete write to set real size to binary.
fn complete(&mut self);
}
pub enum ValueWriter {
Nullable(InnerValueWriter),
NonNullable(InnerValueWriter),
}
impl ValueWriter {
pub fn create_value_writer(
element_type: &DataType,
binary_row_format: Option<&BinaryRowFormat>,
) -> Result<ValueWriter> {
let value_writer =
InnerValueWriter::create_inner_value_writer(element_type, binary_row_format)?;
if element_type.is_nullable() {
Ok(Self::Nullable(value_writer))
} else {
Ok(Self::NonNullable(value_writer))
}
}
pub fn write_value<W: BinaryWriter>(
&self,
writer: &mut W,
pos: usize,
value: &Datum,
) -> Result<()> {
match self {
Self::Nullable(inner_value_writer) => {
if let Datum::Null = value {
writer.set_null_at(pos);
Ok(())
} else {
inner_value_writer.write_value(writer, pos, value)
}
}
Self::NonNullable(inner_value_writer) => {
inner_value_writer.write_value(writer, pos, value)
}
}
}
}
#[derive(Debug)]
pub enum InnerValueWriter {
Char,
String,
Boolean,
Binary,
Bytes,
TinyInt,
SmallInt,
Int,
BigInt,
Float,
Double,
Decimal(u32, u32), // precision, scale
Date,
Time(u32), // precision (not used in wire format, but kept for consistency)
TimestampNtz(u32), // precision
TimestampLtz(u32), // precision
// TODO Array, Row
}
/// Accessor for writing the fields/elements of a binary writer during runtime, the
/// fields/elements must be written in the order.
impl InnerValueWriter {
pub fn create_inner_value_writer(
data_type: &DataType,
_: Option<&BinaryRowFormat>,
) -> Result<InnerValueWriter> {
match data_type {
DataType::Char(_) => Ok(InnerValueWriter::Char),
DataType::String(_) => Ok(InnerValueWriter::String),
DataType::Boolean(_) => Ok(InnerValueWriter::Boolean),
DataType::Binary(_) => Ok(InnerValueWriter::Binary),
DataType::Bytes(_) => Ok(InnerValueWriter::Bytes),
DataType::TinyInt(_) => Ok(InnerValueWriter::TinyInt),
DataType::SmallInt(_) => Ok(InnerValueWriter::SmallInt),
DataType::Int(_) => Ok(InnerValueWriter::Int),
DataType::BigInt(_) => Ok(InnerValueWriter::BigInt),
DataType::Float(_) => Ok(InnerValueWriter::Float),
DataType::Double(_) => Ok(InnerValueWriter::Double),
DataType::Decimal(d) => {
// Validation is done at DecimalType construction time
Ok(InnerValueWriter::Decimal(d.precision(), d.scale()))
}
DataType::Date(_) => Ok(InnerValueWriter::Date),
DataType::Time(t) => {
// Validation is done at TimeType construction time
Ok(InnerValueWriter::Time(t.precision()))
}
DataType::Timestamp(t) => {
// Validation is done at TimestampType construction time
Ok(InnerValueWriter::TimestampNtz(t.precision()))
}
DataType::TimestampLTz(t) => {
// Validation is done at TimestampLTzType construction time
Ok(InnerValueWriter::TimestampLtz(t.precision()))
}
_ => unimplemented!(
"ValueWriter for DataType {:?} is currently not implemented",
data_type
),
}
}
pub fn write_value<W: BinaryWriter>(
&self,
writer: &mut W,
_pos: usize,
value: &Datum,
) -> Result<()> {
match (self, value) {
(InnerValueWriter::Char, Datum::String(v)) => {
writer.write_char(v, v.len());
}
(InnerValueWriter::String, Datum::String(v)) => {
writer.write_string(v);
}
(InnerValueWriter::Boolean, Datum::Bool(v)) => {
writer.write_boolean(*v);
}
(InnerValueWriter::Binary, Datum::Blob(v)) => {
let b = v.as_ref();
writer.write_binary(b, b.len());
}
(InnerValueWriter::Bytes, Datum::Blob(v)) => {
writer.write_bytes(v.as_ref());
}
(InnerValueWriter::TinyInt, Datum::Int8(v)) => {
writer.write_byte(*v as u8);
}
(InnerValueWriter::SmallInt, Datum::Int16(v)) => {
writer.write_short(*v);
}
(InnerValueWriter::Int, Datum::Int32(v)) => {
writer.write_int(*v);
}
(InnerValueWriter::BigInt, Datum::Int64(v)) => {
writer.write_long(*v);
}
(InnerValueWriter::Float, Datum::Float32(v)) => {
writer.write_float(v.into_inner());
}
(InnerValueWriter::Double, Datum::Float64(v)) => {
writer.write_double(v.into_inner());
}
(InnerValueWriter::Decimal(p, _s), Datum::Decimal(v)) => {
writer.write_decimal(v, *p);
}
(InnerValueWriter::Date, Datum::Date(d)) => {
writer.write_int(d.get_inner());
}
(InnerValueWriter::Time(p), Datum::Time(t)) => {
writer.write_time(t.get_inner(), *p);
}
(InnerValueWriter::TimestampNtz(p), Datum::TimestampNtz(ts)) => {
writer.write_timestamp_ntz(ts, *p);
}
(InnerValueWriter::TimestampLtz(p), Datum::TimestampLtz(ts)) => {
writer.write_timestamp_ltz(ts, *p);
}
_ => {
return Err(IllegalArgument {
message: format!("{self:?} used to write value {value:?}"),
});
}
}
Ok(())
}
}