Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ let fnck_sql = DataBaseBuilder::path("./data")
- Varchar
- Date
- DateTime
- Time
- Tuple

## Roadmap
Expand Down
2 changes: 2 additions & 0 deletions src/bin/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ fn encode_tuples<'a>(schema: &Schema, tuples: Vec<Tuple>) -> PgWireResult<QueryR
}
LogicalType::Date => encoder.encode_field(&value.date()),
LogicalType::DateTime => encoder.encode_field(&value.datetime()),
LogicalType::Time => encoder.encode_field(&value.time()),
LogicalType::Decimal(_, _) => todo!(),
_ => unreachable!(),
}?;
Expand All @@ -227,6 +228,7 @@ fn into_pg_type(data_type: &LogicalType) -> PgWireResult<Type> {
LogicalType::Varchar(_) => Type::VARCHAR,
LogicalType::Date | LogicalType::DateTime => Type::DATE,
LogicalType::Char(_) => Type::CHAR,
LogicalType::Time => Type::TIME,
LogicalType::Decimal(_, _) => todo!(),
_ => {
return Err(PgWireError::UserError(Box::new(ErrorInfo::new(
Expand Down
5 changes: 4 additions & 1 deletion src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::planner::LogicalPlan;
use crate::storage::kip::KipStorage;
use crate::storage::{Storage, Transaction};
use crate::types::tuple::{SchemaRef, Tuple};
use crate::udf::current_date::CurrentDate;

pub(crate) type Functions = HashMap<FunctionSummary, Arc<dyn ScalarFunctionImpl>>;

Expand Down Expand Up @@ -47,7 +48,9 @@ impl DataBaseBuilder {
self
}

pub async fn build(self) -> Result<Database<KipStorage>, DatabaseError> {
pub async fn build(mut self) -> Result<Database<KipStorage>, DatabaseError> {
self = self.register_function(CurrentDate::new());

let storage = KipStorage::new(self.path).await?;

Ok(Database {
Expand Down
9 changes: 9 additions & 0 deletions src/expression/value_compute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,15 @@ impl DataValue {
&unified_type
)
}
LogicalType::Time => {
numeric_binary_compute!(
DataValue::Time,
self.clone(),
right.clone(),
op,
&unified_type
)
}
LogicalType::Decimal(_, _) => {
let left_value = self.clone().cast(&unified_type)?;
let right_value = right.clone().cast(&unified_type)?;
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ pub mod parser;
pub mod planner;
pub mod storage;
pub mod types;
mod udf;
2 changes: 2 additions & 0 deletions src/marcos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ macro_rules! function {
}

impl $struct_name {
#[allow(unused_mut)]
pub(crate) fn new() -> Arc<Self> {
let function_name = stringify!($function_name).to_lowercase();

Expand All @@ -93,6 +94,7 @@ macro_rules! function {

#[typetag::serde]
impl ScalarFunctionImpl for $struct_name {
#[allow(unused_variables, clippy::redundant_closure_call)]
fn eval(&self, args: &[ScalarExpression], tuple: &Tuple, schema: &[ColumnRef]) -> Result<DataValue, DatabaseError> {
let mut _index = 0;

Expand Down
5 changes: 4 additions & 1 deletion src/optimizer/core/histogram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,13 +279,16 @@ impl Histogram {
}),
_ => unreachable!(),
},
LogicalType::Date | LogicalType::DateTime => match value {
LogicalType::Date | LogicalType::DateTime | LogicalType::Time => match value {
DataValue::Date32(value) => DataValue::Int32(*value)
.cast(&LogicalType::Double)?
.double(),
DataValue::Date64(value) => DataValue::Int64(*value)
.cast(&LogicalType::Double)?
.double(),
DataValue::Time(value) => DataValue::UInt32(*value)
.cast(&LogicalType::Double)?
.double(),
_ => unreachable!(),
},

Expand Down
8 changes: 5 additions & 3 deletions src/storage/table_codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ impl TableCodec {
let tuple_id = tuple.id.clone().ok_or(DatabaseError::PrimaryKeyNotFound)?;
let key = Self::encode_tuple_key(table_name, &tuple_id)?;

Ok((Bytes::from(key), Bytes::from(tuple.serialize_to(types))))
Ok((Bytes::from(key), Bytes::from(tuple.serialize_to(types)?)))
}

pub fn encode_tuple_key(
Expand Down Expand Up @@ -226,8 +226,10 @@ impl TableCodec {
tuple_id: &TupleId,
) -> Result<(Bytes, Bytes), DatabaseError> {
let key = TableCodec::encode_index_key(name, index, Some(tuple_id))?;
let mut bytes = Vec::new();
tuple_id.to_raw(&mut bytes, None)?;

Ok((Bytes::from(key), Bytes::from(tuple_id.to_raw(None))))
Ok((Bytes::from(key), Bytes::from(bytes)))
}

fn _encode_index_key(name: &str, index: &Index) -> Result<Vec<u8>, DatabaseError> {
Expand Down Expand Up @@ -267,7 +269,7 @@ impl TableCodec {

if let Some(tuple_id) = tuple_id {
if matches!(index.ty, IndexType::Normal | IndexType::Composite) {
key_prefix.append(&mut tuple_id.to_raw(None));
tuple_id.to_raw(&mut key_prefix, None)?;
}
}
Ok(key_prefix)
Expand Down
32 changes: 29 additions & 3 deletions src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::any::TypeId;
use std::cmp;

use crate::errors::DatabaseError;
use sqlparser::ast::{CharLengthUnits, CharacterLength, ExactNumberInfo};
use sqlparser::ast::{CharLengthUnits, CharacterLength, ExactNumberInfo, TimezoneInfo};
use strum_macros::AsRefStr;

pub type ColumnId = u32;
Expand Down Expand Up @@ -38,6 +38,7 @@ pub enum LogicalType {
Varchar(Option<u32>),
Date,
DateTime,
Time,
// decimal (precision, scale)
Decimal(Option<u8>, Option<u8>),
Tuple,
Expand Down Expand Up @@ -100,6 +101,7 @@ impl LogicalType {
LogicalType::Decimal(_, _) => Some(16),
LogicalType::Date => Some(4),
LogicalType::DateTime => Some(8),
LogicalType::Time => Some(4),
LogicalType::Invalid | LogicalType::Tuple => unreachable!(),
}
}
Expand Down Expand Up @@ -297,8 +299,12 @@ impl LogicalType {
),
LogicalType::DateTime => matches!(
to,
LogicalType::Date | LogicalType::Varchar(_) | LogicalType::Char(_)
LogicalType::Date
| LogicalType::Time
| LogicalType::Varchar(_)
| LogicalType::Char(_)
),
LogicalType::Time => matches!(to, LogicalType::Varchar(_) | LogicalType::Char(_)),
LogicalType::Decimal(_, _) | LogicalType::Tuple => false,
}
}
Expand Down Expand Up @@ -356,7 +362,27 @@ impl TryFrom<sqlparser::ast::DataType> for LogicalType {
sqlparser::ast::DataType::UnsignedBigInt(_) => Ok(LogicalType::UBigint),
sqlparser::ast::DataType::Boolean => Ok(LogicalType::Boolean),
sqlparser::ast::DataType::Date => Ok(LogicalType::Date),
sqlparser::ast::DataType::Datetime(_) => Ok(LogicalType::DateTime),
sqlparser::ast::DataType::Datetime(precision) => {
if precision.is_some() {
return Err(DatabaseError::UnsupportedStmt(
"time's precision".to_string(),
));
}
Ok(LogicalType::DateTime)
}
sqlparser::ast::DataType::Time(precision, info) => {
if precision.is_some() {
return Err(DatabaseError::UnsupportedStmt(
"time's precision".to_string(),
));
}
if !matches!(info, TimezoneInfo::None) {
return Err(DatabaseError::UnsupportedStmt(
"time's time zone".to_string(),
));
}
Ok(LogicalType::Time)
}
sqlparser::ast::DataType::Decimal(info) | sqlparser::ast::DataType::Dec(info) => {
match info {
ExactNumberInfo::None => Ok(Self::Decimal(None, None)),
Expand Down
16 changes: 9 additions & 7 deletions src/types/tuple.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::catalog::ColumnRef;
use crate::errors::DatabaseError;
use crate::types::value::{DataValue, ValueRef};
use crate::types::LogicalType;
use comfy_table::{Cell, Table};
Expand Down Expand Up @@ -108,7 +109,7 @@ impl Tuple {

/// e.g.: bits(u8)..|data_0(len for utf8_1)|utf8_0|data_1|
/// Tips: all len is u32
pub fn serialize_to(&self, types: &[LogicalType]) -> Vec<u8> {
pub fn serialize_to(&self, types: &[LogicalType]) -> Result<Vec<u8>, DatabaseError> {
assert_eq!(self.values.len(), types.len());

fn flip_bit(bits: u8, i: usize) -> u8 {
Expand All @@ -124,16 +125,17 @@ impl Tuple {
bytes[i / BITS_MAX_INDEX] = flip_bit(bytes[i / BITS_MAX_INDEX], i % BITS_MAX_INDEX);
} else {
let logical_type = types[i];
let mut value_bytes = value.to_raw(Some(logical_type));
let value_len = value.to_raw(&mut bytes, Some(logical_type))?;

if logical_type.raw_len().is_none() {
bytes.append(&mut (value_bytes.len() as u32).encode_fixed_vec());
let index = bytes.len() - value_len;

bytes.splice(index..index, (value_len as u32).encode_fixed_vec());
}
bytes.append(&mut value_bytes);
}
}

bytes
Ok(bytes)
}
}

Expand Down Expand Up @@ -300,13 +302,13 @@ mod tests {
&types,
&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
&columns,
&tuples[0].serialize_to(&types),
&tuples[0].serialize_to(&types).unwrap(),
);
let tuple_1 = Tuple::deserialize_from(
&types,
&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
&columns,
&tuples[1].serialize_to(&types),
&tuples[1].serialize_to(&types).unwrap(),
);

assert_eq!(tuples[0], tuple_0);
Expand Down
Loading