make starts_with and ends_with work with bytes https://github.com/cozodb/cozo/discussions/132

main
Ziyang Hu 1 year ago
parent f17f63bde5
commit bd1ba17527

@ -1359,28 +1359,24 @@ pub(crate) fn op_trim_end(args: &[DataValue]) -> Result<DataValue> {
define_op!(OP_STARTS_WITH, 2, false); define_op!(OP_STARTS_WITH, 2, false);
pub(crate) fn op_starts_with(args: &[DataValue]) -> Result<DataValue> { pub(crate) fn op_starts_with(args: &[DataValue]) -> Result<DataValue> {
let a = match &args[0] { match (&args[0], &args[1]) {
DataValue::Str(s) => s, (DataValue::Str(l), DataValue::Str(r)) => Ok(DataValue::from(l.starts_with(r as &str))),
_ => bail!("'starts_with' requires strings"), (DataValue::Bytes(l), DataValue::Bytes(r)) => {
}; Ok(DataValue::from(l.starts_with(r as &[u8])))
let b = match &args[1] { }
DataValue::Str(s) => s, _ => bail!("'starts_with' requires strings or bytes"),
_ => bail!("'starts_with' requires strings"), }
};
Ok(DataValue::from(a.starts_with(b as &str)))
} }
define_op!(OP_ENDS_WITH, 2, false); define_op!(OP_ENDS_WITH, 2, false);
pub(crate) fn op_ends_with(args: &[DataValue]) -> Result<DataValue> { pub(crate) fn op_ends_with(args: &[DataValue]) -> Result<DataValue> {
let a = match &args[0] { match (&args[0], &args[1]) {
DataValue::Str(s) => s, (DataValue::Str(l), DataValue::Str(r)) => Ok(DataValue::from(l.ends_with(r as &str))),
_ => bail!("'ends_with' requires strings"), (DataValue::Bytes(l), DataValue::Bytes(r)) => {
}; Ok(DataValue::from(l.ends_with(r as &[u8])))
let b = match &args[1] { }
DataValue::Str(s) => s, _ => bail!("'ends_with' requires strings or bytes"),
_ => bail!("'ends_with' requires strings"), }
};
Ok(DataValue::from(a.ends_with(b as &str)))
} }
define_op!(OP_REGEX, 1, false); define_op!(OP_REGEX, 1, false);
@ -1971,7 +1967,7 @@ pub(crate) fn op_to_int(args: &[DataValue]) -> Result<DataValue> {
.map_err(|_| miette!("The string cannot be interpreted as int"))? .map_err(|_| miette!("The string cannot be interpreted as int"))?
.into() .into()
} }
DataValue::Validity(vld) => DataValue::Num(Num::Int(vld.timestamp.0.0)), DataValue::Validity(vld) => DataValue::Num(Num::Int(vld.timestamp.0 .0)),
v => bail!("'to_int' does not recognize {:?}", v), v => bail!("'to_int' does not recognize {:?}", v),
}) })
} }
@ -2086,16 +2082,28 @@ pub(crate) fn op_vec(args: &[DataValue]) -> Result<DataValue> {
} }
}, },
DataValue::Str(s) => { DataValue::Str(s) => {
let bytes = STANDARD.decode(s).map_err(|_| miette!("Data is not base64 encoded"))?; let bytes = STANDARD
.decode(s)
.map_err(|_| miette!("Data is not base64 encoded"))?;
match t { match t {
VecElementType::F32 => { VecElementType::F32 => {
let f32_count = bytes.len() / mem::size_of::<f32>(); let f32_count = bytes.len() / mem::size_of::<f32>();
let arr = unsafe { ndarray::ArrayView1::from_shape_ptr(ndarray::Dim([f32_count]), bytes.as_ptr() as *const f32) }; let arr = unsafe {
ndarray::ArrayView1::from_shape_ptr(
ndarray::Dim([f32_count]),
bytes.as_ptr() as *const f32,
)
};
Ok(DataValue::Vec(Vector::F32(arr.to_owned()))) Ok(DataValue::Vec(Vector::F32(arr.to_owned())))
} }
VecElementType::F64 => { VecElementType::F64 => {
let f64_count = bytes.len() / mem::size_of::<f64>(); let f64_count = bytes.len() / mem::size_of::<f64>();
let arr = unsafe { ndarray::ArrayView1::from_shape_ptr(ndarray::Dim([f64_count]), bytes.as_ptr() as *const f64) }; let arr = unsafe {
ndarray::ArrayView1::from_shape_ptr(
ndarray::Dim([f64_count]),
bytes.as_ptr() as *const f64,
)
};
Ok(DataValue::Vec(Vector::F64(arr.to_owned()))) Ok(DataValue::Vec(Vector::F64(arr.to_owned())))
} }
} }
@ -2448,7 +2456,7 @@ define_op!(OP_FORMAT_TIMESTAMP, 1, true);
pub(crate) fn op_format_timestamp(args: &[DataValue]) -> Result<DataValue> { pub(crate) fn op_format_timestamp(args: &[DataValue]) -> Result<DataValue> {
let dt = { let dt = {
let millis = match &args[0] { let millis = match &args[0] {
DataValue::Validity(vld) => vld.timestamp.0.0 / 1000, DataValue::Validity(vld) => vld.timestamp.0 .0 / 1000,
v => { v => {
let f = v let f = v
.get_float() .get_float()

Loading…
Cancel
Save