additional types

main
Ziyang Hu 1 year ago
parent a21c571ca0
commit 01b5dfca9b

@ -1274,6 +1274,7 @@ pub(crate) fn op_to_bool(args: &[DataValue]) -> Result<DataValue> {
DataValue::Regex(r) => !r.0.as_str().is_empty(),
DataValue::List(l) => !l.is_empty(),
DataValue::Set(s) => !s.is_empty(),
DataValue::Arr(_) => true,
DataValue::Validity(vld) => vld.is_assert.0,
DataValue::Bot => false,
}))
@ -1291,6 +1292,7 @@ pub(crate) fn op_to_unity(args: &[DataValue]) -> Result<DataValue> {
DataValue::Regex(r) => i64::from(!r.0.as_str().is_empty()),
DataValue::List(l) => i64::from(!l.is_empty()),
DataValue::Set(s) => i64::from(!s.is_empty()),
DataValue::Arr(_) => 1,
DataValue::Validity(vld) => i64::from(vld.is_assert.0),
DataValue::Bot => 0,
}))

@ -11,7 +11,7 @@ use base64::Engine;
use serde_json::json;
pub(crate) use serde_json::Value as JsonValue;
use crate::data::value::{DataValue, Num};
use crate::data::value::{Array, DataValue, Num};
impl From<JsonValue> for DataValue {
fn from(v: JsonValue) -> Self {
@ -97,6 +97,14 @@ impl From<DataValue> for JsonValue {
DataValue::Uuid(u) => {
json!(u.0)
}
DataValue::Arr(arr) => {
match arr {
Array::F32(a) => json!(a),
Array::F64(a) => json!(a),
Array::I32(a) => json!(a),
Array::I64(a) => json!(a),
}
}
DataValue::Validity(v) => {
json!([v.timestamp.0, v.is_assert])
}

@ -14,12 +14,13 @@ use std::str::FromStr;
use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
use regex::Regex;
use crate::data::value::{DataValue, Num, RegexWrapper, UuidWrapper, Validity, ValidityTs};
use crate::data::value::{Array, DataValue, Num, RegexWrapper, UuidWrapper, Validity, ValidityTs};
const INIT_TAG: u8 = 0x00;
const NULL_TAG: u8 = 0x01;
const FALSE_TAG: u8 = 0x02;
const TRUE_TAG: u8 = 0x03;
const ARR_TAG: u8 = 0x04;
const NUM_TAG: u8 = 0x05;
const STR_TAG: u8 = 0x06;
const BYTES_TAG: u8 = 0x07;
@ -30,6 +31,11 @@ const SET_TAG: u8 = 0x0B;
const VLD_TAG: u8 = 0x0C;
const BOT_TAG: u8 = 0xFF;
const ARR_F32: u8 = 0x01;
const ARR_F64: u8 = 0x02;
const ARR_I32: u8 = 0x03;
const ARR_I64: u8 = 0x04;
const IS_FLOAT: u8 = 0b00010000;
const IS_APPROX_INT: u8 = 0b00000100;
const IS_EXACT_INT: u8 = 0b00000000;
@ -41,6 +47,43 @@ pub(crate) trait MemCmpEncoder: Write {
DataValue::Null => self.write_u8(NULL_TAG).unwrap(),
DataValue::Bool(false) => self.write_u8(FALSE_TAG).unwrap(),
DataValue::Bool(true) => self.write_u8(TRUE_TAG).unwrap(),
DataValue::Arr(arr) => {
self.write_u8(ARR_TAG).unwrap();
match arr {
Array::F32(a) => {
self.write_u8(ARR_F32).unwrap();
let l = a.len();
self.write_u64::<BigEndian>(l as u64).unwrap();
for el in a {
self.write_f32::<BigEndian>(*el).unwrap();
}
}
Array::F64(a) => {
self.write_u8(ARR_F64).unwrap();
let l = a.len();
self.write_u64::<BigEndian>(l as u64).unwrap();
for el in a {
self.write_f64::<BigEndian>(*el).unwrap();
}
}
Array::I32(a) => {
self.write_u8(ARR_I32).unwrap();
let l = a.len();
self.write_u64::<BigEndian>(l as u64).unwrap();
for el in a {
self.write_i32::<BigEndian>(*el).unwrap();
}
}
Array::I64(a) => {
self.write_u8(ARR_I64).unwrap();
let l = a.len();
self.write_u64::<BigEndian>(l as u64).unwrap();
for el in a {
self.write_i64::<BigEndian>(*el).unwrap();
}
}
}
}
DataValue::Num(n) => {
self.write_u8(NUM_TAG).unwrap();
self.encode_num(*n);
@ -295,6 +338,54 @@ impl DataValue {
)
}
BOT_TAG => (DataValue::Bot, remaining),
ARR_TAG => {
let (t_tag, remaining) = remaining.split_first().unwrap();
let (len_bytes, mut rest) = remaining.split_at(8);
let len = BigEndian::read_u64(len_bytes) as usize;
match *t_tag {
ARR_F32 => {
let mut res_arr = Vec::with_capacity(len);
for _ in 0..len {
let (f_bytes, next_chunk) = rest.split_at(4);
rest = next_chunk;
let f = BigEndian::read_f32(f_bytes);
res_arr.push(f);
}
(DataValue::Arr(Array::F32(res_arr)), rest)
}
ARR_F64 => {
let mut res_arr = Vec::with_capacity(len);
for _ in 0..len {
let (f_bytes, next_chunk) = rest.split_at(8);
rest = next_chunk;
let f = BigEndian::read_f64(f_bytes);
res_arr.push(f);
}
(DataValue::Arr(Array::F64(res_arr)), rest)
}
ARR_I32 => {
let mut res_arr = Vec::with_capacity(len);
for _ in 0..len {
let (i_bytes, next_chunk) = rest.split_at(4);
rest = next_chunk;
let i = BigEndian::read_i32(i_bytes);
res_arr.push(i);
}
(DataValue::Arr(Array::I32(res_arr)), rest)
}
ARR_I64 => {
let mut res_arr = Vec::with_capacity(len);
for _ in 0..len {
let (i_bytes, next_chunk) = rest.split_at(8);
rest = next_chunk;
let i = BigEndian::read_i64(i_bytes);
res_arr.push(i);
}
(DataValue::Arr(Array::I64(res_arr)), rest)
}
_ => unreachable!()
}
}
_ => unreachable!("{:?}", bs),
}
}

@ -57,6 +57,17 @@ impl Display for NullableColType {
}
f.write_str(")")?;
}
ColType::Array { eltype, len } => {
f.write_str("<")?;
match eltype {
ArrayElementType::F32 => f.write_str("F32")?,
ArrayElementType::F64 => f.write_str("F64")?,
ArrayElementType::I32 => f.write_str("I32")?,
ArrayElementType::I64 => f.write_str("I64")?,
}
write!(f, ";{len}")?;
f.write_str(">")?;
}
}
if self.nullable {
f.write_str("?")?;
@ -78,10 +89,22 @@ pub(crate) enum ColType {
eltype: Box<NullableColType>,
len: Option<usize>,
},
Array {
eltype: ArrayElementType,
len: usize,
},
Tuple(Vec<NullableColType>),
Validity,
}
#[derive(Debug, Clone, Eq, PartialEq, serde_derive::Deserialize, serde_derive::Serialize)]
pub(crate) enum ArrayElementType {
F32,
F64,
I32,
I64,
}
#[derive(Debug, Clone, Eq, PartialEq, serde_derive::Deserialize, serde_derive::Serialize)]
pub(crate) struct ColumnDef {
pub(crate) name: SmartString<LazyCompact>,
@ -223,6 +246,9 @@ impl NullableColType {
bail!(make_err())
}
}
ColType::Array { eltype, len } => {
todo!("array coercion")
}
ColType::Tuple(typ) => {
if let DataValue::List(l) = data {
ensure!(typ.len() == l.len(), BadListLength(self.clone(), l.len()));

@ -146,12 +146,119 @@ pub enum DataValue {
List(Vec<DataValue>),
/// set, used internally only
Set(BTreeSet<DataValue>),
/// validity
/// Array, mainly for proximity search
Arr(Array),
/// validity,
Validity(Validity),
/// bottom type, used internally only
Bot,
}
#[derive(Clone, serde_derive::Serialize, serde_derive::Deserialize)]
pub enum Array {
F32(Vec<f32>),
F64(Vec<f64>),
I32(Vec<i32>),
I64(Vec<i64>),
}
impl Array {
pub fn len(&self) -> usize {
match self {
Array::F32(v) => v.len(),
Array::F64(v) => v.len(),
Array::I32(v) => v.len(),
Array::I64(v) => v.len(),
}
}
}
impl PartialEq<Self> for Array {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Array::F32(l), Array::F32(r)) => {
for (le, re) in l.iter().zip(r) {
if !OrderedFloat(*le).eq(&OrderedFloat(*re)) {
return false;
}
}
true
}
(Array::F64(l), Array::F64(r)) => {
for (le, re) in l.iter().zip(r) {
if !OrderedFloat(*le).eq(&OrderedFloat(*re)) {
return false;
}
}
true
}
(Array::I32(l), Array::I32(r)) => l == r,
(Array::I64(l), Array::I64(r)) => l == r,
_ => false,
}
}
}
impl Eq for Array {}
impl PartialOrd for Array {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Array {
fn cmp(&self, other: &Self) -> Ordering {
match (self, other) {
(Array::F32(l), Array::F32(r)) => {
for (le, re) in l.iter().zip(r) {
match OrderedFloat(*le).cmp(&OrderedFloat(*re)) {
Ordering::Equal => continue,
o => return o,
}
}
return Ordering::Equal;
}
(Array::F32(_), _) => Ordering::Less,
(Array::F64(l), Array::F64(r)) => {
for (le, re) in l.iter().zip(r) {
match OrderedFloat(*le).cmp(&OrderedFloat(*re)) {
Ordering::Equal => continue,
o => return o,
}
}
return Ordering::Equal;
}
(Array::F64(_), Array::F32(_)) => Ordering::Greater,
(Array::F64(_), _) => Ordering::Less,
(Array::I32(l), Array::I32(r)) => l.cmp(r),
(Array::I32(_), Array::I64(_)) => Ordering::Less,
(Array::I32(_), _) => Ordering::Greater,
(Array::I64(l), Array::I64(r)) => l.cmp(r),
(Array::I64(_), _) => Ordering::Greater,
}
}
}
impl Hash for Array {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
Array::F32(a) => {
for el in a {
OrderedFloat(*el).hash(state)
}
}
Array::F64(a) => {
for el in a {
OrderedFloat(*el).hash(state)
}
}
Array::I32(a) => {a.hash(state)}
Array::I64(a) => {a.hash(state)}
}
}
}
impl From<i64> for DataValue {
fn from(v: i64) -> Self {
DataValue::Num(Num::Int(v))
@ -322,6 +429,9 @@ impl Display for DataValue {
.field("timestamp", &v.timestamp.0)
.field("retracted", &v.is_assert)
.finish(),
DataValue::Arr(a) => {
write!(f, "array<{:?} elements>", a.len())
}
}
}
}

Loading…
Cancel
Save