Introduce Register struct

OwnedValue has become a powerhouse of madness, mainly because I decided
to do it like that when I first introduced AggContext. I decided it was
enough and I introduced a `Register` struct that contains `OwnedValue`,
`Record` and `Aggregation`, this way we don't use `OwnedValue` for
everything make everyone's life harder.

This is the next step towards making ImmutableRecords the default
because I want to remove unnecessary allocations. Right now we clone
OwnedValues when we generate a record more than needed.
This commit is contained in:
Pere Diaz Bou
2025-03-26 14:52:35 +01:00
parent af6e9cd2c2
commit 9291f60722
18 changed files with 867 additions and 713 deletions

View File

@@ -160,7 +160,6 @@ impl LimboValue {
limbo_core::OwnedValue::Null => { limbo_core::OwnedValue::Null => {
LimboValue::new(ValueType::Null, ValueUnion::from_null()) LimboValue::new(ValueType::Null, ValueUnion::from_null())
} }
_ => unreachable!(),
} }
} }

View File

@@ -116,7 +116,6 @@ fn row_to_obj_array<'local>(
} }
limbo_core::OwnedValue::Text(s) => env.new_string(s.as_str())?.into(), limbo_core::OwnedValue::Text(s) => env.new_string(s.as_str())?.into(),
limbo_core::OwnedValue::Blob(b) => env.byte_array_from_slice(&b)?.into(), limbo_core::OwnedValue::Blob(b) => env.byte_array_from_slice(&b)?.into(),
_ => unreachable!(),
}; };
if let Err(e) = env.set_object_array_element(&obj_array, i as i32, obj) { if let Err(e) = env.set_object_array_element(&obj_array, i as i32, obj) {
eprintln!("Error on parsing row: {:?}", e); eprintln!("Error on parsing row: {:?}", e);

View File

@@ -101,7 +101,6 @@ fn to_js_value(env: &napi::Env, value: &limbo_core::OwnedValue) -> JsUnknown {
limbo_core::OwnedValue::Blob(b) => { limbo_core::OwnedValue::Blob(b) => {
env.create_buffer_copy(b.as_ref()).unwrap().into_unknown() env.create_buffer_copy(b.as_ref()).unwrap().into_unknown()
} }
_ => env.get_null().unwrap().into_unknown(),
} }
} }

View File

@@ -333,7 +333,6 @@ fn row_to_py(py: Python, row: &limbo_core::Row) -> Result<PyObject> {
limbo_core::OwnedValue::Blob(b) => { limbo_core::OwnedValue::Blob(b) => {
py_values.push(PyBytes::new(py, b.as_slice()).into()) py_values.push(PyBytes::new(py, b.as_slice()).into())
} }
_ => unreachable!(),
} }
} }
Ok(PyTuple::new(py, &py_values) Ok(PyTuple::new(py, &py_values)

View File

@@ -236,8 +236,6 @@ impl Row {
limbo_core::OwnedValue::Float(f) => Ok(Value::Real(*f)), limbo_core::OwnedValue::Float(f) => Ok(Value::Real(*f)),
limbo_core::OwnedValue::Text(text) => Ok(Value::Text(text.to_string())), limbo_core::OwnedValue::Text(text) => Ok(Value::Text(text.to_string())),
limbo_core::OwnedValue::Blob(items) => Ok(Value::Blob(items.to_vec())), limbo_core::OwnedValue::Blob(items) => Ok(Value::Blob(items.to_vec())),
limbo_core::OwnedValue::Agg(_agg_context) => todo!(),
limbo_core::OwnedValue::Record(_record) => todo!(),
} }
} }
} }

View File

@@ -191,7 +191,6 @@ fn to_js_value(value: &limbo_core::OwnedValue) -> JsValue {
limbo_core::OwnedValue::Float(f) => JsValue::from(*f), limbo_core::OwnedValue::Float(f) => JsValue::from(*f),
limbo_core::OwnedValue::Text(t) => JsValue::from_str(t.as_str()), limbo_core::OwnedValue::Text(t) => JsValue::from_str(t.as_str()),
limbo_core::OwnedValue::Blob(b) => js_sys::Uint8Array::from(b.as_slice()).into(), limbo_core::OwnedValue::Blob(b) => js_sys::Uint8Array::from(b.as_slice()).into(),
_ => unreachable!(),
} }
} }

View File

@@ -717,7 +717,6 @@ impl<'a> Limbo<'a> {
OwnedValue::Blob(b) => { OwnedValue::Blob(b) => {
format!("{}", String::from_utf8_lossy(b)) format!("{}", String::from_utf8_lossy(b))
} }
_ => unreachable!(),
} }
.as_bytes(), .as_bytes(),
)?; )?;
@@ -784,7 +783,6 @@ impl<'a> Limbo<'a> {
String::from_utf8_lossy(b).to_string(), String::from_utf8_lossy(b).to_string(),
CellAlignment::Left, CellAlignment::Left,
), ),
_ => unreachable!(),
}; };
row.add_cell( row.add_cell(
Cell::new(content) Cell::new(content)

View File

@@ -1,33 +1,33 @@
use crate::types::OwnedValue;
use crate::LimboError::InvalidModifier; use crate::LimboError::InvalidModifier;
use crate::Result; use crate::Result;
use crate::{types::OwnedValue, vdbe::Register};
use chrono::{ use chrono::{
DateTime, Datelike, NaiveDate, NaiveDateTime, NaiveTime, TimeDelta, TimeZone, Timelike, Utc, DateTime, Datelike, NaiveDate, NaiveDateTime, NaiveTime, TimeDelta, TimeZone, Timelike, Utc,
}; };
/// Execution of date/time/datetime functions /// Execution of date/time/datetime functions
#[inline(always)] #[inline(always)]
pub fn exec_date(values: &[OwnedValue]) -> OwnedValue { pub fn exec_date(values: &[Register]) -> OwnedValue {
exec_datetime(values, DateTimeOutput::Date) exec_datetime(values, DateTimeOutput::Date)
} }
#[inline(always)] #[inline(always)]
pub fn exec_time(values: &[OwnedValue]) -> OwnedValue { pub fn exec_time(values: &[Register]) -> OwnedValue {
exec_datetime(values, DateTimeOutput::Time) exec_datetime(values, DateTimeOutput::Time)
} }
#[inline(always)] #[inline(always)]
pub fn exec_datetime_full(values: &[OwnedValue]) -> OwnedValue { pub fn exec_datetime_full(values: &[Register]) -> OwnedValue {
exec_datetime(values, DateTimeOutput::DateTime) exec_datetime(values, DateTimeOutput::DateTime)
} }
#[inline(always)] #[inline(always)]
pub fn exec_strftime(values: &[OwnedValue]) -> OwnedValue { pub fn exec_strftime(values: &[Register]) -> OwnedValue {
if values.is_empty() { if values.is_empty() {
return OwnedValue::Null; return OwnedValue::Null;
} }
let format_str = match &values[0] { let format_str = match &values[0].get_owned_value() {
OwnedValue::Text(text) => text.as_str().to_string(), OwnedValue::Text(text) => text.as_str().to_string(),
OwnedValue::Integer(num) => num.to_string(), OwnedValue::Integer(num) => num.to_string(),
OwnedValue::Float(num) => format!("{:.14}", num), OwnedValue::Float(num) => format!("{:.14}", num),
@@ -45,7 +45,7 @@ enum DateTimeOutput {
StrfTime(String), StrfTime(String),
} }
fn exec_datetime(values: &[OwnedValue], output_type: DateTimeOutput) -> OwnedValue { fn exec_datetime(values: &[Register], output_type: DateTimeOutput) -> OwnedValue {
if values.is_empty() { if values.is_empty() {
let now = parse_naive_date_time(&OwnedValue::build_text("now")).unwrap(); let now = parse_naive_date_time(&OwnedValue::build_text("now")).unwrap();
@@ -59,7 +59,7 @@ fn exec_datetime(values: &[OwnedValue], output_type: DateTimeOutput) -> OwnedVal
// Parse here // Parse here
return OwnedValue::build_text(&formatted_str); return OwnedValue::build_text(&formatted_str);
} }
if let Some(mut dt) = parse_naive_date_time(&values[0]) { if let Some(mut dt) = parse_naive_date_time(values[0].get_owned_value()) {
// if successful, treat subsequent entries as modifiers // if successful, treat subsequent entries as modifiers
modify_dt(&mut dt, &values[1..], output_type) modify_dt(&mut dt, &values[1..], output_type)
} else { } else {
@@ -69,15 +69,11 @@ fn exec_datetime(values: &[OwnedValue], output_type: DateTimeOutput) -> OwnedVal
} }
} }
fn modify_dt( fn modify_dt(dt: &mut NaiveDateTime, mods: &[Register], output_type: DateTimeOutput) -> OwnedValue {
dt: &mut NaiveDateTime,
mods: &[OwnedValue],
output_type: DateTimeOutput,
) -> OwnedValue {
let mut subsec_requested = false; let mut subsec_requested = false;
for modifier in mods { for modifier in mods {
if let OwnedValue::Text(ref text_rc) = modifier { if let OwnedValue::Text(ref text_rc) = modifier.get_owned_value() {
// TODO: to prevent double conversion and properly support 'utc'/'localtime', we also // TODO: to prevent double conversion and properly support 'utc'/'localtime', we also
// need to keep track of the current timezone and apply it to the modifier. // need to keep track of the current timezone and apply it to the modifier.
match apply_modifier(dt, text_rc.as_str()) { match apply_modifier(dt, text_rc.as_str()) {
@@ -806,7 +802,7 @@ mod tests {
]; ];
for (input, expected) in test_cases { for (input, expected) in test_cases {
let result = exec_date(&[input.clone()]); let result = exec_date(&[Register::OwnedValue(input.clone())]);
assert_eq!( assert_eq!(
result, result,
OwnedValue::build_text(expected), OwnedValue::build_text(expected),
@@ -847,7 +843,7 @@ mod tests {
]; ];
for case in invalid_cases.iter() { for case in invalid_cases.iter() {
let result = exec_date(&[case.clone()]); let result = exec_date(&[Register::OwnedValue(case.clone())]);
match result { match result {
OwnedValue::Text(ref result_str) if result_str.value.is_empty() => (), OwnedValue::Text(ref result_str) if result_str.value.is_empty() => (),
_ => panic!( _ => panic!(
@@ -960,7 +956,7 @@ mod tests {
]; ];
for (input, expected) in test_cases { for (input, expected) in test_cases {
let result = exec_time(&[input]); let result = exec_time(&[Register::OwnedValue(input)]);
if let OwnedValue::Text(result_str) = result { if let OwnedValue::Text(result_str) = result {
assert_eq!(result_str.as_str(), expected); assert_eq!(result_str.as_str(), expected);
} else { } else {
@@ -1000,7 +996,7 @@ mod tests {
]; ];
for case in invalid_cases { for case in invalid_cases {
let result = exec_time(&[case.clone()]); let result = exec_time(&[Register::OwnedValue(case.clone())]);
match result { match result {
OwnedValue::Text(ref result_str) if result_str.value.is_empty() => (), OwnedValue::Text(ref result_str) if result_str.value.is_empty() => (),
_ => panic!( _ => panic!(
@@ -1302,8 +1298,8 @@ mod tests {
assert_eq!(dt, create_datetime(2023, 6, 15, 0, 0, 0)); assert_eq!(dt, create_datetime(2023, 6, 15, 0, 0, 0));
} }
fn text(value: &str) -> OwnedValue { fn text(value: &str) -> Register {
OwnedValue::build_text(value) Register::OwnedValue(OwnedValue::build_text(value))
} }
fn format(dt: NaiveDateTime) -> String { fn format(dt: NaiveDateTime) -> String {
@@ -1321,7 +1317,7 @@ mod tests {
&[text("2023-06-15 12:30:45"), text("-1 day")], &[text("2023-06-15 12:30:45"), text("-1 day")],
DateTimeOutput::DateTime, DateTimeOutput::DateTime,
); );
assert_eq!(result, text(&expected)); assert_eq!(result, *text(&expected).get_owned_value());
} }
#[test] #[test]
@@ -1336,7 +1332,7 @@ mod tests {
], ],
DateTimeOutput::DateTime, DateTimeOutput::DateTime,
); );
assert_eq!(result, text(&expected)); assert_eq!(result, *text(&expected).get_owned_value());
} }
#[test] #[test]
@@ -1363,7 +1359,7 @@ mod tests {
], ],
DateTimeOutput::DateTime, DateTimeOutput::DateTime,
); );
assert_eq!(result, text(&expected)); assert_eq!(result, *text(&expected).get_owned_value());
} }
#[test] #[test]
@@ -1382,7 +1378,7 @@ mod tests {
], ],
DateTimeOutput::DateTime, DateTimeOutput::DateTime,
); );
assert_eq!(result, text(&expected)); assert_eq!(result, *text(&expected).get_owned_value());
} }
#[test] #[test]
@@ -1402,7 +1398,7 @@ mod tests {
], ],
DateTimeOutput::DateTime, DateTimeOutput::DateTime,
); );
assert_eq!(result, text(&expected)); assert_eq!(result, *text(&expected).get_owned_value());
} }
#[test] #[test]
@@ -1414,12 +1410,13 @@ mod tests {
); );
assert_eq!( assert_eq!(
result_local, result_local,
text( *text(
&dt.and_utc() &dt.and_utc()
.with_timezone(&chrono::Local) .with_timezone(&chrono::Local)
.format("%Y-%m-%d %H:%M:%S") .format("%Y-%m-%d %H:%M:%S")
.to_string() .to_string()
) )
.get_owned_value()
); );
// TODO: utc modifier assumes time given is not already utc // TODO: utc modifier assumes time given is not already utc
// add test when fixed in the future // add test when fixed in the future
@@ -1457,7 +1454,7 @@ mod tests {
.unwrap(); .unwrap();
let expected = format(max); let expected = format(max);
let result = exec_datetime(&[text("9999-12-31 23:59:59")], DateTimeOutput::DateTime); let result = exec_datetime(&[text("9999-12-31 23:59:59")], DateTimeOutput::DateTime);
assert_eq!(result, text(&expected)); assert_eq!(result, *text(&expected).get_owned_value());
} }
// leap second // leap second
@@ -1469,7 +1466,7 @@ mod tests {
.unwrap(); .unwrap();
let expected = String::new(); // SQLite ignores leap seconds let expected = String::new(); // SQLite ignores leap seconds
let result = exec_datetime(&[text(&leap_second.to_string())], DateTimeOutput::DateTime); let result = exec_datetime(&[text(&leap_second.to_string())], DateTimeOutput::DateTime);
assert_eq!(result, text(&expected)); assert_eq!(result, *text(&expected).get_owned_value());
} }
#[test] #[test]

View File

@@ -1,12 +1,13 @@
use crate::types::OwnedValue; use crate::types::OwnedValue;
use crate::vdbe::Register;
use crate::LimboError; use crate::LimboError;
#[inline(always)] #[inline(always)]
pub fn exec_printf(values: &[OwnedValue]) -> crate::Result<OwnedValue> { pub fn exec_printf(values: &[Register]) -> crate::Result<OwnedValue> {
if values.is_empty() { if values.is_empty() {
return Ok(OwnedValue::Null); return Ok(OwnedValue::Null);
} }
let format_str = match &values[0] { let format_str = match &values[0].get_owned_value() {
OwnedValue::Text(t) => t.as_str(), OwnedValue::Text(t) => t.as_str(),
_ => return Ok(OwnedValue::Null), _ => return Ok(OwnedValue::Null),
}; };
@@ -30,7 +31,7 @@ pub fn exec_printf(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
if args_index >= values.len() { if args_index >= values.len() {
return Err(LimboError::InvalidArgument("not enough arguments".into())); return Err(LimboError::InvalidArgument("not enough arguments".into()));
} }
match &values[args_index] { match &values[args_index].get_owned_value() {
OwnedValue::Integer(i) => result.push_str(&i.to_string()), OwnedValue::Integer(i) => result.push_str(&i.to_string()),
OwnedValue::Float(f) => result.push_str(&f.to_string()), OwnedValue::Float(f) => result.push_str(&f.to_string()),
_ => result.push_str("0".into()), _ => result.push_str("0".into()),
@@ -41,7 +42,7 @@ pub fn exec_printf(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
if args_index >= values.len() { if args_index >= values.len() {
return Err(LimboError::InvalidArgument("not enough arguments".into())); return Err(LimboError::InvalidArgument("not enough arguments".into()));
} }
match &values[args_index] { match &values[args_index].get_owned_value() {
OwnedValue::Text(t) => result.push_str(t.as_str()), OwnedValue::Text(t) => result.push_str(t.as_str()),
OwnedValue::Null => result.push_str("(null)"), OwnedValue::Null => result.push_str("(null)"),
v => result.push_str(&v.to_string()), v => result.push_str(&v.to_string()),
@@ -52,7 +53,7 @@ pub fn exec_printf(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
if args_index >= values.len() { if args_index >= values.len() {
return Err(LimboError::InvalidArgument("not enough arguments".into())); return Err(LimboError::InvalidArgument("not enough arguments".into()));
} }
match &values[args_index] { match &values[args_index].get_owned_value() {
OwnedValue::Float(f) => result.push_str(&f.to_string()), OwnedValue::Float(f) => result.push_str(&f.to_string()),
OwnedValue::Integer(i) => result.push_str(&(*i as f64).to_string()), OwnedValue::Integer(i) => result.push_str(&(*i as f64).to_string()),
_ => result.push_str("0.0".into()), _ => result.push_str("0.0".into()),
@@ -78,16 +79,16 @@ pub fn exec_printf(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
mod tests { mod tests {
use super::*; use super::*;
fn text(value: &str) -> OwnedValue { fn text(value: &str) -> Register {
OwnedValue::build_text(value) Register::OwnedValue(OwnedValue::build_text(value))
} }
fn integer(value: i64) -> OwnedValue { fn integer(value: i64) -> Register {
OwnedValue::Integer(value) Register::OwnedValue(OwnedValue::Integer(value))
} }
fn float(value: f64) -> OwnedValue { fn float(value: f64) -> Register {
OwnedValue::Float(value) Register::OwnedValue(OwnedValue::Float(value))
} }
#[test] #[test]
@@ -99,7 +100,7 @@ mod tests {
fn test_printf_basic_string() { fn test_printf_basic_string() {
assert_eq!( assert_eq!(
exec_printf(&[text("Hello World")]).unwrap(), exec_printf(&[text("Hello World")]).unwrap(),
text("Hello World") *text("Hello World").get_owned_value()
); );
} }
@@ -118,7 +119,7 @@ mod tests {
), ),
// String with null value // String with null value
( (
vec![text("Hello, %s!"), OwnedValue::Null], vec![text("Hello, %s!"), Register::OwnedValue(OwnedValue::Null)],
text("Hello, (null)!"), text("Hello, (null)!"),
), ),
// String with number conversion // String with number conversion
@@ -127,7 +128,7 @@ mod tests {
(vec![text("100%% complete")], text("100% complete")), (vec![text("100%% complete")], text("100% complete")),
]; ];
for (input, output) in test_cases { for (input, output) in test_cases {
assert_eq!(exec_printf(&input).unwrap(), output); assert_eq!(exec_printf(&input).unwrap(), *output.get_owned_value());
} }
} }
@@ -150,7 +151,7 @@ mod tests {
), ),
]; ];
for (input, output) in test_cases { for (input, output) in test_cases {
assert_eq!(exec_printf(&input).unwrap(), output) assert_eq!(exec_printf(&input).unwrap(), *output.get_owned_value())
} }
} }
@@ -179,7 +180,7 @@ mod tests {
]; ];
for (input, expected) in test_cases { for (input, expected) in test_cases {
assert_eq!(exec_printf(&input).unwrap(), expected); assert_eq!(exec_printf(&input).unwrap(), *expected.get_owned_value());
} }
} }
@@ -214,7 +215,7 @@ mod tests {
]; ];
for (input, expected) in test_cases { for (input, expected) in test_cases {
assert_eq!(exec_printf(&input).unwrap(), expected); assert_eq!(exec_printf(&input).unwrap(), *expected.get_owned_value());
} }
} }
@@ -256,7 +257,7 @@ mod tests {
]; ];
for (input, expected) in test_cases { for (input, expected) in test_cases {
assert_eq!(exec_printf(&input).unwrap(), expected); assert_eq!(exec_printf(&input).unwrap(), *expected.get_owned_value());
} }
} }
} }

View File

@@ -1,6 +1,6 @@
use std::{collections::VecDeque, rc::Rc}; use std::{collections::VecDeque, rc::Rc};
use crate::types::OwnedValue; use crate::{types::OwnedValue, vdbe::Register};
use super::{ use super::{
convert_dbtype_to_jsonb, convert_json_to_db_type, curry_convert_dbtype_to_jsonb, convert_dbtype_to_jsonb, convert_json_to_db_type, curry_convert_dbtype_to_jsonb,
@@ -152,15 +152,15 @@ impl JsonPatcher {
} }
} }
pub fn json_remove(args: &[OwnedValue], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> { pub fn json_remove(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> {
if args.is_empty() { if args.is_empty() {
return Ok(OwnedValue::Null); return Ok(OwnedValue::Null);
} }
let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict); let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict);
let mut json = json_cache.get_or_insert_with(&args[0], make_jsonb_fn)?; let mut json = json_cache.get_or_insert_with(&args[0].get_owned_value(), make_jsonb_fn)?;
for arg in &args[1..] { for arg in &args[1..] {
if let Some(path) = json_path_from_owned_value(arg, true)? { if let Some(path) = json_path_from_owned_value(arg.get_owned_value(), true)? {
let mut op = DeleteOperation::new(); let mut op = DeleteOperation::new();
let _ = json.operate_on_path(&path, &mut op); let _ = json.operate_on_path(&path, &mut op);
} }
@@ -171,15 +171,15 @@ pub fn json_remove(args: &[OwnedValue], json_cache: &JsonCacheCell) -> crate::Re
json_string_to_db_type(json, el_type, OutputVariant::String) json_string_to_db_type(json, el_type, OutputVariant::String)
} }
pub fn jsonb_remove(args: &[OwnedValue], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> { pub fn jsonb_remove(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> {
if args.is_empty() { if args.is_empty() {
return Ok(OwnedValue::Null); return Ok(OwnedValue::Null);
} }
let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict); let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict);
let mut json = json_cache.get_or_insert_with(&args[0], make_jsonb_fn)?; let mut json = json_cache.get_or_insert_with(&args[0].get_owned_value(), make_jsonb_fn)?;
for arg in &args[1..] { for arg in &args[1..] {
if let Some(path) = json_path_from_owned_value(arg, true)? { if let Some(path) = json_path_from_owned_value(arg.get_owned_value(), true)? {
let mut op = DeleteOperation::new(); let mut op = DeleteOperation::new();
let _ = json.operate_on_path(&path, &mut op); let _ = json.operate_on_path(&path, &mut op);
} }
@@ -188,18 +188,18 @@ pub fn jsonb_remove(args: &[OwnedValue], json_cache: &JsonCacheCell) -> crate::R
Ok(OwnedValue::Blob(Rc::new(json.data()))) Ok(OwnedValue::Blob(Rc::new(json.data())))
} }
pub fn json_replace(args: &[OwnedValue], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> { pub fn json_replace(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> {
if args.is_empty() { if args.is_empty() {
return Ok(OwnedValue::Null); return Ok(OwnedValue::Null);
} }
let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict); let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict);
let mut json = json_cache.get_or_insert_with(&args[0], make_jsonb_fn)?; let mut json = json_cache.get_or_insert_with(&args[0].get_owned_value(), make_jsonb_fn)?;
let other = args[1..].chunks_exact(2); let other = args[1..].chunks_exact(2);
for chunk in other { for chunk in other {
let path = json_path_from_owned_value(&chunk[0], true)?; let path = json_path_from_owned_value(&chunk[0].get_owned_value(), true)?;
let value = convert_dbtype_to_jsonb(&chunk[1], Conv::NotStrict)?; let value = convert_dbtype_to_jsonb(&chunk[1].get_owned_value(), Conv::NotStrict)?;
if let Some(path) = path { if let Some(path) = path {
let mut op = ReplaceOperation::new(value); let mut op = ReplaceOperation::new(value);
@@ -212,17 +212,17 @@ pub fn json_replace(args: &[OwnedValue], json_cache: &JsonCacheCell) -> crate::R
json_string_to_db_type(json, el_type, super::OutputVariant::String) json_string_to_db_type(json, el_type, super::OutputVariant::String)
} }
pub fn jsonb_replace(args: &[OwnedValue], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> { pub fn jsonb_replace(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> {
if args.is_empty() { if args.is_empty() {
return Ok(OwnedValue::Null); return Ok(OwnedValue::Null);
} }
let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict); let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict);
let mut json = json_cache.get_or_insert_with(&args[0], make_jsonb_fn)?; let mut json = json_cache.get_or_insert_with(&args[0].get_owned_value(), make_jsonb_fn)?;
let other = args[1..].chunks_exact(2); let other = args[1..].chunks_exact(2);
for chunk in other { for chunk in other {
let path = json_path_from_owned_value(&chunk[0], true)?; let path = json_path_from_owned_value(&chunk[0].get_owned_value(), true)?;
let value = convert_dbtype_to_jsonb(&chunk[1], Conv::NotStrict)?; let value = convert_dbtype_to_jsonb(&chunk[1].get_owned_value(), Conv::NotStrict)?;
if let Some(path) = path { if let Some(path) = path {
let mut op = ReplaceOperation::new(value); let mut op = ReplaceOperation::new(value);
@@ -235,17 +235,17 @@ pub fn jsonb_replace(args: &[OwnedValue], json_cache: &JsonCacheCell) -> crate::
json_string_to_db_type(json, el_type, OutputVariant::Binary) json_string_to_db_type(json, el_type, OutputVariant::Binary)
} }
pub fn json_insert(args: &[OwnedValue], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> { pub fn json_insert(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> {
if args.is_empty() { if args.is_empty() {
return Ok(OwnedValue::Null); return Ok(OwnedValue::Null);
} }
let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict); let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict);
let mut json = json_cache.get_or_insert_with(&args[0], make_jsonb_fn)?; let mut json = json_cache.get_or_insert_with(&args[0].get_owned_value(), make_jsonb_fn)?;
let other = args[1..].chunks_exact(2); let other = args[1..].chunks_exact(2);
for chunk in other { for chunk in other {
let path = json_path_from_owned_value(&chunk[0], true)?; let path = json_path_from_owned_value(&chunk[0].get_owned_value(), true)?;
let value = convert_dbtype_to_jsonb(&chunk[1], Conv::NotStrict)?; let value = convert_dbtype_to_jsonb(&chunk[1].get_owned_value(), Conv::NotStrict)?;
if let Some(path) = path { if let Some(path) = path {
let mut op = InsertOperation::new(value); let mut op = InsertOperation::new(value);
@@ -258,17 +258,17 @@ pub fn json_insert(args: &[OwnedValue], json_cache: &JsonCacheCell) -> crate::Re
json_string_to_db_type(json, el_type, OutputVariant::String) json_string_to_db_type(json, el_type, OutputVariant::String)
} }
pub fn jsonb_insert(args: &[OwnedValue], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> { pub fn jsonb_insert(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> {
if args.is_empty() { if args.is_empty() {
return Ok(OwnedValue::Null); return Ok(OwnedValue::Null);
} }
let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict); let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict);
let mut json = json_cache.get_or_insert_with(&args[0], make_jsonb_fn)?; let mut json = json_cache.get_or_insert_with(&args[0].get_owned_value(), make_jsonb_fn)?;
let other = args[1..].chunks_exact(2); let other = args[1..].chunks_exact(2);
for chunk in other { for chunk in other {
let path = json_path_from_owned_value(&chunk[0], true)?; let path = json_path_from_owned_value(&chunk[0].get_owned_value(), true)?;
let value = convert_dbtype_to_jsonb(&chunk[1], Conv::NotStrict)?; let value = convert_dbtype_to_jsonb(&chunk[1].get_owned_value(), Conv::NotStrict)?;
if let Some(path) = path { if let Some(path) = path {
let mut op = InsertOperation::new(value); let mut op = InsertOperation::new(value);
@@ -608,7 +608,10 @@ mod tests {
#[test] #[test]
fn test_json_remove_array_element() { fn test_json_remove_array_element() {
let args = vec![create_json(r#"[1,2,3,4,5]"#), create_text("$[2]")]; let args = vec![
Register::OwnedValue(create_json(r#"[1,2,3,4,5]"#)),
Register::OwnedValue(create_text("$[2]")),
];
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_remove(&args, &json_cache).unwrap(); let result = json_remove(&args, &json_cache).unwrap();
@@ -621,9 +624,9 @@ mod tests {
#[test] #[test]
fn test_json_remove_multiple_paths() { fn test_json_remove_multiple_paths() {
let args = vec![ let args = vec![
create_json(r#"{"a": 1, "b": 2, "c": 3}"#), Register::OwnedValue(create_json(r#"{"a": 1, "b": 2, "c": 3}"#)),
create_text("$.a"), Register::OwnedValue(create_text("$.a")),
create_text("$.c"), Register::OwnedValue(create_text("$.c")),
]; ];
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
@@ -637,8 +640,8 @@ mod tests {
#[test] #[test]
fn test_json_remove_nested_paths() { fn test_json_remove_nested_paths() {
let args = vec![ let args = vec![
create_json(r#"{"a": {"b": {"c": 1, "d": 2}}}"#), Register::OwnedValue(create_json(r#"{"a": {"b": {"c": 1, "d": 2}}}"#)),
create_text("$.a.b.c"), Register::OwnedValue(create_text("$.a.b.c")),
]; ];
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
@@ -652,8 +655,8 @@ mod tests {
#[test] #[test]
fn test_json_remove_duplicate_keys() { fn test_json_remove_duplicate_keys() {
let args = vec![ let args = vec![
create_json(r#"{"a": 1, "a": 2, "a": 3}"#), Register::OwnedValue(create_json(r#"{"a": 1, "a": 2, "a": 3}"#)),
create_text("$.a"), Register::OwnedValue(create_text("$.a")),
]; ];
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
@@ -667,8 +670,8 @@ mod tests {
#[test] #[test]
fn test_json_remove_invalid_path() { fn test_json_remove_invalid_path() {
let args = vec![ let args = vec![
create_json(r#"{"a": 1}"#), Register::OwnedValue(create_json(r#"{"a": 1}"#)),
OwnedValue::Integer(42), // Invalid path type Register::OwnedValue(OwnedValue::Integer(42)), // Invalid path type
]; ];
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
@@ -678,10 +681,12 @@ mod tests {
#[test] #[test]
fn test_json_remove_complex_case() { fn test_json_remove_complex_case() {
let args = vec![ let args = vec![
create_json(r#"{"a":[1,2,3],"b":{"x":1,"x":2},"c":[{"y":1},{"y":2}]}"#), Register::OwnedValue(create_json(
create_text("$.a[1]"), r#"{"a":[1,2,3],"b":{"x":1,"x":2},"c":[{"y":1},{"y":2}]}"#,
create_text("$.b.x"), )),
create_text("$.c[0].y"), Register::OwnedValue(create_text("$.a[1]")),
Register::OwnedValue(create_text("$.b.x")),
Register::OwnedValue(create_text("$.c[0].y")),
]; ];
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();

View File

@@ -15,6 +15,7 @@ pub use crate::json::json_operations::{
use crate::json::json_path::{json_path, JsonPath, PathElement}; use crate::json::json_path::{json_path, JsonPath, PathElement};
pub use crate::json::ser::to_string; pub use crate::json::ser::to_string;
use crate::types::{OwnedValue, OwnedValueType, Text, TextSubtype}; use crate::types::{OwnedValue, OwnedValueType, Text, TextSubtype};
use crate::vdbe::Register;
use crate::{bail_parse_error, json::de::ordered_object}; use crate::{bail_parse_error, json::de::ordered_object};
pub use json_cache::JsonCacheCell; pub use json_cache::JsonCacheCell;
use jsonb::{ElementType, Jsonb, JsonbHeader, PathOperationMode, SearchOperation, SetOperation}; use jsonb::{ElementType, Jsonb, JsonbHeader, PathOperationMode, SearchOperation, SetOperation};
@@ -131,9 +132,6 @@ fn convert_dbtype_to_jsonb(val: &OwnedValue, strict: Conv) -> crate::Result<Json
json.is_valid()?; json.is_valid()?;
Ok(json) Ok(json)
} }
OwnedValue::Record(_) | OwnedValue::Agg(_) => {
bail_constraint_error!("Wrong number of arguments");
}
OwnedValue::Null => Ok(Jsonb::from_raw_data( OwnedValue::Null => Ok(Jsonb::from_raw_data(
JsonbHeader::make_null().into_bytes().as_bytes(), JsonbHeader::make_null().into_bytes().as_bytes(),
)), )),
@@ -163,18 +161,17 @@ fn get_json_value(json_value: &OwnedValue) -> crate::Result<Val> {
OwnedValue::Null => Ok(Val::Null), OwnedValue::Null => Ok(Val::Null),
OwnedValue::Float(f) => Ok(Val::Float(*f)), OwnedValue::Float(f) => Ok(Val::Float(*f)),
OwnedValue::Integer(i) => Ok(Val::Integer(*i)), OwnedValue::Integer(i) => Ok(Val::Integer(*i)),
_ => Ok(Val::String(json_value.to_string())),
} }
} }
pub fn json_array(values: &[OwnedValue]) -> crate::Result<OwnedValue> { pub fn json_array(values: &[Register]) -> crate::Result<OwnedValue> {
let mut json = Jsonb::make_empty_array(values.len()); let mut json = Jsonb::make_empty_array(values.len());
for value in values.iter() { for value in values.iter() {
if matches!(value, OwnedValue::Blob(_)) { if matches!(value.get_owned_value(), OwnedValue::Blob(_)) {
crate::bail_constraint_error!("JSON cannot hold BLOB values") crate::bail_constraint_error!("JSON cannot hold BLOB values")
} }
let value = convert_dbtype_to_jsonb(value, Conv::NotStrict)?; let value = convert_dbtype_to_jsonb(value.get_owned_value(), Conv::NotStrict)?;
json.append_jsonb_to_end(value.data()); json.append_jsonb_to_end(value.data());
} }
json.finalize_unsafe(ElementType::ARRAY)?; json.finalize_unsafe(ElementType::ARRAY)?;
@@ -182,14 +179,14 @@ pub fn json_array(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
json_string_to_db_type(json, ElementType::ARRAY, OutputVariant::ElementType) json_string_to_db_type(json, ElementType::ARRAY, OutputVariant::ElementType)
} }
pub fn jsonb_array(values: &[OwnedValue]) -> crate::Result<OwnedValue> { pub fn jsonb_array(values: &[Register]) -> crate::Result<OwnedValue> {
let mut json = Jsonb::make_empty_array(values.len()); let mut json = Jsonb::make_empty_array(values.len());
for value in values.iter() { for value in values.iter() {
if matches!(value, OwnedValue::Blob(_)) { if matches!(value.get_owned_value(), OwnedValue::Blob(_)) {
crate::bail_constraint_error!("JSON cannot hold BLOB values") crate::bail_constraint_error!("JSON cannot hold BLOB values")
} }
let value = convert_dbtype_to_jsonb(value, Conv::NotStrict)?; let value = convert_dbtype_to_jsonb(value.get_owned_value(), Conv::NotStrict)?;
json.append_jsonb_to_end(value.data()); json.append_jsonb_to_end(value.data());
} }
json.finalize_unsafe(ElementType::ARRAY)?; json.finalize_unsafe(ElementType::ARRAY)?;
@@ -222,19 +219,19 @@ pub fn json_array_length(
Ok(OwnedValue::Null) Ok(OwnedValue::Null)
} }
pub fn json_set(args: &[OwnedValue], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> { pub fn json_set(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> {
if args.is_empty() { if args.is_empty() {
return Ok(OwnedValue::Null); return Ok(OwnedValue::Null);
} }
let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict); let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict);
let mut json = json_cache.get_or_insert_with(&args[0], make_jsonb_fn)?; let mut json = json_cache.get_or_insert_with(&args[0].get_owned_value(), make_jsonb_fn)?;
let other = args[1..].chunks_exact(2); let other = args[1..].chunks_exact(2);
for chunk in other { for chunk in other {
let path = json_path_from_owned_value(&chunk[0], true)?; let path = json_path_from_owned_value(&chunk[0].get_owned_value(), true)?;
let value = convert_dbtype_to_jsonb(&chunk[1], Conv::NotStrict)?; let value = convert_dbtype_to_jsonb(&chunk[1].get_owned_value(), Conv::NotStrict)?;
let mut op = SetOperation::new(value); let mut op = SetOperation::new(value);
if let Some(path) = path { if let Some(path) = path {
let _ = json.operate_on_path(&path, &mut op); let _ = json.operate_on_path(&path, &mut op);
@@ -313,7 +310,7 @@ pub fn json_arrow_shift_extract(
/// https://sqlite.org/json1.html#the_json_extract_function /// https://sqlite.org/json1.html#the_json_extract_function
pub fn json_extract( pub fn json_extract(
value: &OwnedValue, value: &OwnedValue,
paths: &[OwnedValue], paths: &[Register],
json_cache: &JsonCacheCell, json_cache: &JsonCacheCell,
) -> crate::Result<OwnedValue> { ) -> crate::Result<OwnedValue> {
if let OwnedValue::Null = value { if let OwnedValue::Null = value {
@@ -334,7 +331,7 @@ pub fn json_extract(
pub fn jsonb_extract( pub fn jsonb_extract(
value: &OwnedValue, value: &OwnedValue,
paths: &[OwnedValue], paths: &[Register],
json_cache: &JsonCacheCell, json_cache: &JsonCacheCell,
) -> crate::Result<OwnedValue> { ) -> crate::Result<OwnedValue> {
if let OwnedValue::Null = value { if let OwnedValue::Null = value {
@@ -353,13 +350,10 @@ pub fn jsonb_extract(
Ok(result) Ok(result)
} }
fn jsonb_extract_internal( fn jsonb_extract_internal(value: Jsonb, paths: &[Register]) -> crate::Result<(Jsonb, ElementType)> {
value: Jsonb,
paths: &[OwnedValue],
) -> crate::Result<(Jsonb, ElementType)> {
let null = Jsonb::from_raw_data(JsonbHeader::make_null().into_bytes().as_bytes()); let null = Jsonb::from_raw_data(JsonbHeader::make_null().into_bytes().as_bytes());
if paths.len() == 1 { if paths.len() == 1 {
if let Some(path) = json_path_from_owned_value(&paths[0], true)? { if let Some(path) = json_path_from_owned_value(&paths[0].get_owned_value(), true)? {
let mut json = value; let mut json = value;
let mut op = SearchOperation::new(json.len()); let mut op = SearchOperation::new(json.len());
@@ -383,7 +377,9 @@ fn jsonb_extract_internal(
let mut result = Jsonb::make_empty_array(json.len()); let mut result = Jsonb::make_empty_array(json.len());
// TODO: make an op to avoid creating new json for every path element // TODO: make an op to avoid creating new json for every path element
let paths = paths.iter().map(|p| json_path_from_owned_value(p, true)); let paths = paths
.iter()
.map(|p| json_path_from_owned_value(p.get_owned_value(), true));
for path in paths { for path in paths {
if let Some(path) = path? { if let Some(path) = path? {
let mut op = SearchOperation::new(json.len()); let mut op = SearchOperation::new(json.len());
@@ -581,19 +577,19 @@ pub fn json_error_position(json: &OwnedValue) -> crate::Result<OwnedValue> {
/// Constructs a JSON object from a list of values that represent key-value pairs. /// Constructs a JSON object from a list of values that represent key-value pairs.
/// The number of values must be even, and the first value of each pair (which represents the map key) /// The number of values must be even, and the first value of each pair (which represents the map key)
/// must be a TEXT value. The second value of each pair can be any JSON value (which represents the map value) /// must be a TEXT value. The second value of each pair can be any JSON value (which represents the map value)
pub fn json_object(values: &[OwnedValue]) -> crate::Result<OwnedValue> { pub fn json_object(values: &[Register]) -> crate::Result<OwnedValue> {
if values.len() % 2 != 0 { if values.len() % 2 != 0 {
bail_constraint_error!("json_object() requires an even number of arguments") bail_constraint_error!("json_object() requires an even number of arguments")
} }
let mut json = Jsonb::make_empty_obj(values.len() * 50); let mut json = Jsonb::make_empty_obj(values.len() * 50);
for chunk in values.chunks_exact(2) { for chunk in values.chunks_exact(2) {
if chunk[0].value_type() != OwnedValueType::Text { if chunk[0].get_owned_value().value_type() != OwnedValueType::Text {
bail_constraint_error!("json_object() labels must be TEXT") bail_constraint_error!("json_object() labels must be TEXT")
} }
let key = convert_dbtype_to_jsonb(&chunk[0], Conv::ToString)?; let key = convert_dbtype_to_jsonb(&chunk[0].get_owned_value(), Conv::ToString)?;
json.append_jsonb_to_end(key.data()); json.append_jsonb_to_end(key.data());
let value = convert_dbtype_to_jsonb(&chunk[1], Conv::NotStrict)?; let value = convert_dbtype_to_jsonb(&chunk[1].get_owned_value(), Conv::NotStrict)?;
json.append_jsonb_to_end(value.data()); json.append_jsonb_to_end(value.data());
} }
@@ -602,19 +598,19 @@ pub fn json_object(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
json_string_to_db_type(json, ElementType::OBJECT, OutputVariant::String) json_string_to_db_type(json, ElementType::OBJECT, OutputVariant::String)
} }
pub fn jsonb_object(values: &[OwnedValue]) -> crate::Result<OwnedValue> { pub fn jsonb_object(values: &[Register]) -> crate::Result<OwnedValue> {
if values.len() % 2 != 0 { if values.len() % 2 != 0 {
bail_constraint_error!("json_object() requires an even number of arguments") bail_constraint_error!("json_object() requires an even number of arguments")
} }
let mut json = Jsonb::make_empty_obj(values.len() * 50); let mut json = Jsonb::make_empty_obj(values.len() * 50);
for chunk in values.chunks_exact(2) { for chunk in values.chunks_exact(2) {
if chunk[0].value_type() != OwnedValueType::Text { if chunk[0].get_owned_value().value_type() != OwnedValueType::Text {
bail_constraint_error!("json_object() labels must be TEXT") bail_constraint_error!("json_object() labels must be TEXT")
} }
let key = convert_dbtype_to_jsonb(&chunk[0], Conv::ToString)?; let key = convert_dbtype_to_jsonb(&chunk[0].get_owned_value(), Conv::ToString)?;
json.append_jsonb_to_end(key.data()); json.append_jsonb_to_end(key.data());
let value = convert_dbtype_to_jsonb(&chunk[1], Conv::NotStrict)?; let value = convert_dbtype_to_jsonb(&chunk[1].get_owned_value(), Conv::NotStrict)?;
json.append_jsonb_to_end(value.data()); json.append_jsonb_to_end(value.data());
} }
@@ -663,9 +659,6 @@ pub fn json_quote(value: &OwnedValue) -> crate::Result<OwnedValue> {
OwnedValue::Float(ref float) => Ok(OwnedValue::Float(float.to_owned())), OwnedValue::Float(ref float) => Ok(OwnedValue::Float(float.to_owned())),
OwnedValue::Blob(_) => crate::bail_constraint_error!("JSON cannot hold BLOB values"), OwnedValue::Blob(_) => crate::bail_constraint_error!("JSON cannot hold BLOB values"),
OwnedValue::Null => Ok(OwnedValue::build_text("null")), OwnedValue::Null => Ok(OwnedValue::build_text("null")),
_ => {
unreachable!()
}
} }
} }
@@ -806,9 +799,14 @@ mod tests {
#[test] #[test]
fn test_json_array_simple() { fn test_json_array_simple() {
let text = OwnedValue::build_text("value1"); let text = Register::OwnedValue(OwnedValue::build_text("value1"));
let json = OwnedValue::Text(Text::json("\"value2\"".to_string())); let json = Register::OwnedValue(OwnedValue::Text(Text::json("\"value2\"".to_string())));
let input = vec![text, json, OwnedValue::Integer(1), OwnedValue::Float(1.1)]; let input = vec![
text,
json,
Register::OwnedValue(OwnedValue::Integer(1)),
Register::OwnedValue(OwnedValue::Float(1.1)),
];
let result = json_array(&input).unwrap(); let result = json_array(&input).unwrap();
if let OwnedValue::Text(res) = result { if let OwnedValue::Text(res) = result {
@@ -834,7 +832,7 @@ mod tests {
#[test] #[test]
fn test_json_array_blob_invalid() { fn test_json_array_blob_invalid() {
let blob = OwnedValue::Blob(Rc::new("1".as_bytes().to_vec())); let blob = Register::OwnedValue(OwnedValue::Blob(Rc::new("1".as_bytes().to_vec())));
let input = vec![blob]; let input = vec![blob];
@@ -962,7 +960,7 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_extract( let result = json_extract(
&OwnedValue::build_text("{\"a\":2}"), &OwnedValue::build_text("{\"a\":2}"),
&[OwnedValue::build_text("$.x")], &[Register::OwnedValue(OwnedValue::build_text("$.x"))],
&json_cache, &json_cache,
); );
@@ -976,7 +974,7 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_extract( let result = json_extract(
&OwnedValue::build_text("{\"a\":2}"), &OwnedValue::build_text("{\"a\":2}"),
&[OwnedValue::Null], &[Register::OwnedValue(OwnedValue::Null)],
&json_cache, &json_cache,
); );
@@ -991,7 +989,7 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_extract( let result = json_extract(
&OwnedValue::build_text("{\"a\":2}"), &OwnedValue::build_text("{\"a\":2}"),
&[OwnedValue::Float(1.1)], &[Register::OwnedValue(OwnedValue::Float(1.1))],
&json_cache, &json_cache,
); );
@@ -1052,8 +1050,8 @@ mod tests {
#[test] #[test]
fn test_json_object_simple() { fn test_json_object_simple() {
let key = OwnedValue::build_text("key"); let key = Register::OwnedValue(OwnedValue::build_text("key"));
let value = OwnedValue::build_text("value"); let value = Register::OwnedValue(OwnedValue::build_text("value"));
let input = vec![key, value]; let input = vec![key, value];
let result = json_object(&input).unwrap(); let result = json_object(&input).unwrap();
@@ -1077,16 +1075,16 @@ mod tests {
let null_value = OwnedValue::Null; let null_value = OwnedValue::Null;
let input = vec![ let input = vec![
text_key, Register::OwnedValue(text_key),
text_value, Register::OwnedValue(text_value),
json_key, Register::OwnedValue(json_key),
json_value, Register::OwnedValue(json_value),
integer_key, Register::OwnedValue(integer_key),
integer_value, Register::OwnedValue(integer_value),
float_key, Register::OwnedValue(float_key),
float_value, Register::OwnedValue(float_value),
null_key, Register::OwnedValue(null_key),
null_value, Register::OwnedValue(null_value),
]; ];
let result = json_object(&input).unwrap(); let result = json_object(&input).unwrap();
@@ -1101,8 +1099,10 @@ mod tests {
#[test] #[test]
fn test_json_object_json_value_is_rendered_as_json() { fn test_json_object_json_value_is_rendered_as_json() {
let key = OwnedValue::build_text("key"); let key = Register::OwnedValue(OwnedValue::build_text("key"));
let value = OwnedValue::Text(Text::json(r#"{"json":"value"}"#.to_string())); let value = Register::OwnedValue(OwnedValue::Text(Text::json(
r#"{"json":"value"}"#.to_string(),
)));
let input = vec![key, value]; let input = vec![key, value];
let result = json_object(&input).unwrap(); let result = json_object(&input).unwrap();
@@ -1114,8 +1114,8 @@ mod tests {
#[test] #[test]
fn test_json_object_json_text_value_is_rendered_as_regular_text() { fn test_json_object_json_text_value_is_rendered_as_regular_text() {
let key = OwnedValue::build_text("key"); let key = Register::OwnedValue(OwnedValue::build_text("key"));
let value = OwnedValue::Text(Text::new(r#"{"json":"value"}"#)); let value = Register::OwnedValue(OwnedValue::Text(Text::new(r#"{"json":"value"}"#)));
let input = vec![key, value]; let input = vec![key, value];
let result = json_object(&input).unwrap(); let result = json_object(&input).unwrap();
@@ -1127,12 +1127,12 @@ mod tests {
#[test] #[test]
fn test_json_object_nested() { fn test_json_object_nested() {
let key = OwnedValue::build_text("key"); let key = Register::OwnedValue(OwnedValue::build_text("key"));
let value = OwnedValue::build_text("value"); let value = Register::OwnedValue(OwnedValue::build_text("value"));
let input = vec![key, value]; let input = vec![key, value];
let parent_key = OwnedValue::build_text("parent_key"); let parent_key = Register::OwnedValue(OwnedValue::build_text("parent_key"));
let parent_value = json_object(&input).unwrap(); let parent_value = Register::OwnedValue(json_object(&input).unwrap());
let parent_input = vec![parent_key, parent_value]; let parent_input = vec![parent_key, parent_value];
let result = json_object(&parent_input).unwrap(); let result = json_object(&parent_input).unwrap();
@@ -1145,8 +1145,8 @@ mod tests {
#[test] #[test]
fn test_json_object_duplicated_keys() { fn test_json_object_duplicated_keys() {
let key = OwnedValue::build_text("key"); let key = Register::OwnedValue(OwnedValue::build_text("key"));
let value = OwnedValue::build_text("value"); let value = Register::OwnedValue(OwnedValue::build_text("value"));
let input = vec![key.clone(), value.clone(), key, value]; let input = vec![key.clone(), value.clone(), key, value];
let result = json_object(&input).unwrap(); let result = json_object(&input).unwrap();
@@ -1169,8 +1169,8 @@ mod tests {
#[test] #[test]
fn test_json_object_non_text_key() { fn test_json_object_non_text_key() {
let key = OwnedValue::Integer(1); let key = Register::OwnedValue(OwnedValue::Integer(1));
let value = OwnedValue::build_text("value"); let value = Register::OwnedValue(OwnedValue::build_text("value"));
let input = vec![key, value]; let input = vec![key, value];
match json_object(&input) { match json_object(&input) {
@@ -1181,8 +1181,8 @@ mod tests {
#[test] #[test]
fn test_json_odd_number_of_values() { fn test_json_odd_number_of_values() {
let key = OwnedValue::build_text("key"); let key = Register::OwnedValue(OwnedValue::build_text("key"));
let value = OwnedValue::build_text("value"); let value = Register::OwnedValue(OwnedValue::build_text("value"));
let input = vec![key.clone(), value, key]; let input = vec![key.clone(), value, key];
assert!(json_object(&input).is_err()); assert!(json_object(&input).is_err());
@@ -1320,9 +1320,9 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_set( let result = json_set(
&[ &[
OwnedValue::build_text("{}"), Register::OwnedValue(OwnedValue::build_text("{}")),
OwnedValue::build_text("$.field"), Register::OwnedValue(OwnedValue::build_text("$.field")),
OwnedValue::build_text("value"), Register::OwnedValue(OwnedValue::build_text("value")),
], ],
&json_cache, &json_cache,
); );
@@ -1337,9 +1337,9 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_set( let result = json_set(
&[ &[
OwnedValue::build_text(r#"{"field":"old_value"}"#), Register::OwnedValue(OwnedValue::build_text(r#"{"field":"old_value"}"#)),
OwnedValue::build_text("$.field"), Register::OwnedValue(OwnedValue::build_text("$.field")),
OwnedValue::build_text("new_value"), Register::OwnedValue(OwnedValue::build_text("new_value")),
], ],
&json_cache, &json_cache,
); );
@@ -1357,9 +1357,9 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_set( let result = json_set(
&[ &[
OwnedValue::build_text("{}"), Register::OwnedValue(OwnedValue::build_text("{}")),
OwnedValue::build_text("$.object.doesnt.exist"), Register::OwnedValue(OwnedValue::build_text("$.object.doesnt.exist")),
OwnedValue::build_text("value"), Register::OwnedValue(OwnedValue::build_text("value")),
], ],
&json_cache, &json_cache,
); );
@@ -1377,9 +1377,9 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_set( let result = json_set(
&[ &[
OwnedValue::build_text("[]"), Register::OwnedValue(OwnedValue::build_text("[]")),
OwnedValue::build_text("$[0]"), Register::OwnedValue(OwnedValue::build_text("$[0]")),
OwnedValue::build_text("value"), Register::OwnedValue(OwnedValue::build_text("value")),
], ],
&json_cache, &json_cache,
); );
@@ -1394,9 +1394,9 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_set( let result = json_set(
&[ &[
OwnedValue::build_text("{}"), Register::OwnedValue(OwnedValue::build_text("{}")),
OwnedValue::build_text("$.some_array[0]"), Register::OwnedValue(OwnedValue::build_text("$.some_array[0]")),
OwnedValue::Integer(123), Register::OwnedValue(OwnedValue::Integer(123)),
], ],
&json_cache, &json_cache,
); );
@@ -1414,9 +1414,9 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_set( let result = json_set(
&[ &[
OwnedValue::build_text("[123]"), Register::OwnedValue(OwnedValue::build_text("[123]")),
OwnedValue::build_text("$[1]"), Register::OwnedValue(OwnedValue::build_text("$[1]")),
OwnedValue::Integer(456), Register::OwnedValue(OwnedValue::Integer(456)),
], ],
&json_cache, &json_cache,
); );
@@ -1431,9 +1431,9 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_set( let result = json_set(
&[ &[
OwnedValue::build_text("[123]"), Register::OwnedValue(OwnedValue::build_text("[123]")),
OwnedValue::build_text("$[200]"), Register::OwnedValue(OwnedValue::build_text("$[200]")),
OwnedValue::Integer(456), Register::OwnedValue(OwnedValue::Integer(456)),
], ],
&json_cache, &json_cache,
); );
@@ -1448,9 +1448,9 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_set( let result = json_set(
&[ &[
OwnedValue::build_text("[123]"), Register::OwnedValue(OwnedValue::build_text("[123]")),
OwnedValue::build_text("$[0]"), Register::OwnedValue(OwnedValue::build_text("$[0]")),
OwnedValue::Integer(456), Register::OwnedValue(OwnedValue::Integer(456)),
], ],
&json_cache, &json_cache,
); );
@@ -1465,9 +1465,9 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_set( let result = json_set(
&[ &[
OwnedValue::build_text("{}"), Register::OwnedValue(OwnedValue::build_text("{}")),
OwnedValue::Null, Register::OwnedValue(OwnedValue::Null),
OwnedValue::Integer(456), Register::OwnedValue(OwnedValue::Integer(456)),
], ],
&json_cache, &json_cache,
); );
@@ -1482,11 +1482,11 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_set( let result = json_set(
&[ &[
OwnedValue::build_text("[123]"), Register::OwnedValue(OwnedValue::build_text("[123]")),
OwnedValue::build_text("$[0]"), Register::OwnedValue(OwnedValue::build_text("$[0]")),
OwnedValue::Integer(456), Register::OwnedValue(OwnedValue::Integer(456)),
OwnedValue::build_text("$[1]"), Register::OwnedValue(OwnedValue::build_text("$[1]")),
OwnedValue::Integer(789), Register::OwnedValue(OwnedValue::Integer(789)),
], ],
&json_cache, &json_cache,
); );
@@ -1501,9 +1501,9 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_set( let result = json_set(
&[ &[
OwnedValue::build_text("{}"), Register::OwnedValue(OwnedValue::build_text("{}")),
OwnedValue::build_text("$.object[0].field"), Register::OwnedValue(OwnedValue::build_text("$.object[0].field")),
OwnedValue::Integer(123), Register::OwnedValue(OwnedValue::Integer(123)),
], ],
&json_cache, &json_cache,
); );
@@ -1521,9 +1521,9 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_set( let result = json_set(
&[ &[
OwnedValue::build_text("{}"), Register::OwnedValue(OwnedValue::build_text("{}")),
OwnedValue::build_text("$.object[0][0]"), Register::OwnedValue(OwnedValue::build_text("$.object[0][0]")),
OwnedValue::Integer(123), Register::OwnedValue(OwnedValue::Integer(123)),
], ],
&json_cache, &json_cache,
); );
@@ -1538,11 +1538,11 @@ mod tests {
let json_cache = JsonCacheCell::new(); let json_cache = JsonCacheCell::new();
let result = json_set( let result = json_set(
&[ &[
OwnedValue::build_text("{}"), Register::OwnedValue(OwnedValue::build_text("{}")),
OwnedValue::build_text("$.object[123].another"), Register::OwnedValue(OwnedValue::build_text("$.object[123].another")),
OwnedValue::build_text("value"), Register::OwnedValue(OwnedValue::build_text("value")),
OwnedValue::build_text("$.field"), Register::OwnedValue(OwnedValue::build_text("$.field")),
OwnedValue::build_text("value"), Register::OwnedValue(OwnedValue::build_text("value")),
], ],
&json_cache, &json_cache,
); );

View File

@@ -76,8 +76,6 @@ pub enum OwnedValue {
Float(f64), Float(f64),
Text(Text), Text(Text),
Blob(Rc<Vec<u8>>), Blob(Rc<Vec<u8>>),
Agg(Box<AggContext>), // TODO(pere): make this without Box. Currently this might cause cache miss but let's leave it for future analysis
Record(Record),
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@@ -130,8 +128,6 @@ impl OwnedValue {
OwnedValue::Float(_) => OwnedValueType::Float, OwnedValue::Float(_) => OwnedValueType::Float,
OwnedValue::Text(_) => OwnedValueType::Text, OwnedValue::Text(_) => OwnedValueType::Text,
OwnedValue::Blob(_) => OwnedValueType::Blob, OwnedValue::Blob(_) => OwnedValueType::Blob,
OwnedValue::Agg(_) => OwnedValueType::Null, // Map Agg to Null for FFI
OwnedValue::Record(_) => OwnedValueType::Null, // Map Record to Null for FFI
} }
} }
} }
@@ -160,18 +156,6 @@ impl Display for OwnedValue {
Self::Float(fl) => write!(f, "{:?}", fl), Self::Float(fl) => write!(f, "{:?}", fl),
Self::Text(s) => write!(f, "{}", s.as_str()), Self::Text(s) => write!(f, "{}", s.as_str()),
Self::Blob(b) => write!(f, "{}", String::from_utf8_lossy(b)), Self::Blob(b) => write!(f, "{}", String::from_utf8_lossy(b)),
Self::Agg(a) => match a.as_ref() {
AggContext::Avg(acc, _count) => write!(f, "{}", acc),
AggContext::Sum(acc) => write!(f, "{}", acc),
AggContext::Count(count) => write!(f, "{}", count),
AggContext::Max(max) => write!(f, "{}", max.as_ref().unwrap_or(&Self::Null)),
AggContext::Min(min) => write!(f, "{}", min.as_ref().unwrap_or(&Self::Null)),
AggContext::GroupConcat(s) => write!(f, "{}", s),
AggContext::External(v) => {
write!(f, "{}", v.finalized_value.as_ref().unwrap_or(&Self::Null))
}
},
Self::Record(r) => write!(f, "{:?}", r),
} }
} }
} }
@@ -184,8 +168,6 @@ impl OwnedValue {
Self::Float(fl) => ExtValue::from_float(*fl), Self::Float(fl) => ExtValue::from_float(*fl),
Self::Text(text) => ExtValue::from_text(text.as_str().to_string()), Self::Text(text) => ExtValue::from_text(text.as_str().to_string()),
Self::Blob(blob) => ExtValue::from_blob(blob.to_vec()), Self::Blob(blob) => ExtValue::from_blob(blob.to_vec()),
Self::Agg(_) => todo!(),
Self::Record(_) => todo!("Record values not yet supported"),
} }
} }
@@ -290,9 +272,6 @@ impl PartialEq<OwnedValue> for OwnedValue {
} }
(Self::Blob(blob_left), Self::Blob(blob_right)) => blob_left.eq(blob_right), (Self::Blob(blob_left), Self::Blob(blob_right)) => blob_left.eq(blob_right),
(Self::Null, Self::Null) => true, (Self::Null, Self::Null) => true,
(Self::Agg(a), Self::Agg(b)) => a.eq(b),
(Self::Agg(a), other) => a.final_value().eq(other),
(other, Self::Agg(b)) => other.eq(b.final_value()),
_ => false, _ => false,
} }
} }
@@ -335,9 +314,6 @@ impl PartialOrd<OwnedValue> for OwnedValue {
(Self::Null, Self::Null) => Some(std::cmp::Ordering::Equal), (Self::Null, Self::Null) => Some(std::cmp::Ordering::Equal),
(Self::Null, _) => Some(std::cmp::Ordering::Less), (Self::Null, _) => Some(std::cmp::Ordering::Less),
(_, Self::Null) => Some(std::cmp::Ordering::Greater), (_, Self::Null) => Some(std::cmp::Ordering::Greater),
(Self::Agg(a), Self::Agg(b)) => a.partial_cmp(b),
(Self::Agg(a), other) => a.final_value().partial_cmp(other),
(other, Self::Agg(b)) => other.partial_cmp(b.final_value()),
other => todo!("{:?}", other), other => todo!("{:?}", other),
} }
} }
@@ -836,8 +812,6 @@ impl From<&OwnedValue> for SerialType {
OwnedValue::Blob(b) => SerialType::Blob { OwnedValue::Blob(b) => SerialType::Blob {
content_size: b.len(), content_size: b.len(),
}, },
OwnedValue::Agg(_) => unreachable!(),
OwnedValue::Record(_) => unreachable!(),
} }
} }
} }
@@ -896,9 +870,6 @@ impl Record {
OwnedValue::Float(f) => buf.extend_from_slice(&f.to_be_bytes()), OwnedValue::Float(f) => buf.extend_from_slice(&f.to_be_bytes()),
OwnedValue::Text(t) => buf.extend_from_slice(&t.value), OwnedValue::Text(t) => buf.extend_from_slice(&t.value),
OwnedValue::Blob(b) => buf.extend_from_slice(b), OwnedValue::Blob(b) => buf.extend_from_slice(b),
// non serializable
OwnedValue::Agg(_) => unreachable!(),
OwnedValue::Record(_) => unreachable!(),
}; };
} }

View File

@@ -5,18 +5,6 @@ use crate::storage::wal::CheckpointMode;
use crate::types::{OwnedValue, Record}; use crate::types::{OwnedValue, Record};
use limbo_macros::Description; use limbo_macros::Description;
macro_rules! final_agg_values {
($var:ident) => {
if let OwnedValue::Agg(agg) = $var {
$var = agg.final_value();
}
};
($lhs:ident, $rhs:ident) => {
final_agg_values!($lhs);
final_agg_values!($rhs);
};
}
/// Flags provided to comparison instructions (e.g. Eq, Ne) which determine behavior related to NULL values. /// Flags provided to comparison instructions (e.g. Eq, Ne) which determine behavior related to NULL values.
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
pub struct CmpInsFlags(usize); pub struct CmpInsFlags(usize);
@@ -738,8 +726,7 @@ pub enum Cookie {
UserVersion = 6, UserVersion = 6,
} }
pub fn exec_add(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue { pub fn exec_add(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
final_agg_values!(lhs, rhs);
match (lhs, rhs) { match (lhs, rhs) {
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => { (OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
let result = lhs.overflowing_add(*rhs); let result = lhs.overflowing_add(*rhs);
@@ -764,8 +751,7 @@ pub fn exec_add(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
} }
} }
pub fn exec_subtract(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue { pub fn exec_subtract(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
final_agg_values!(lhs, rhs);
match (lhs, rhs) { match (lhs, rhs) {
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => { (OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
let result = lhs.overflowing_sub(*rhs); let result = lhs.overflowing_sub(*rhs);
@@ -793,8 +779,7 @@ pub fn exec_subtract(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
} }
} }
pub fn exec_multiply(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue { pub fn exec_multiply(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
final_agg_values!(lhs, rhs);
match (lhs, rhs) { match (lhs, rhs) {
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => { (OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
let result = lhs.overflowing_mul(*rhs); let result = lhs.overflowing_mul(*rhs);
@@ -820,8 +805,7 @@ pub fn exec_multiply(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
} }
} }
pub fn exec_divide(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue { pub fn exec_divide(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
final_agg_values!(lhs, rhs);
match (lhs, rhs) { match (lhs, rhs) {
(_, OwnedValue::Integer(0)) | (_, OwnedValue::Float(0.0)) => OwnedValue::Null, (_, OwnedValue::Integer(0)) | (_, OwnedValue::Float(0.0)) => OwnedValue::Null,
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => { (OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
@@ -846,8 +830,7 @@ pub fn exec_divide(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
} }
} }
pub fn exec_bit_and(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue { pub fn exec_bit_and(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
final_agg_values!(lhs, rhs);
match (lhs, rhs) { match (lhs, rhs) {
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null, (OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
(_, OwnedValue::Integer(0)) (_, OwnedValue::Integer(0))
@@ -871,8 +854,7 @@ pub fn exec_bit_and(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
} }
} }
pub fn exec_bit_or(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue { pub fn exec_bit_or(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
final_agg_values!(lhs, rhs);
match (lhs, rhs) { match (lhs, rhs) {
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null, (OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
(OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => OwnedValue::Integer(lh | rh), (OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => OwnedValue::Integer(lh | rh),
@@ -892,8 +874,7 @@ pub fn exec_bit_or(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
} }
} }
pub fn exec_remainder(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue { pub fn exec_remainder(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
final_agg_values!(lhs, rhs);
match (lhs, rhs) { match (lhs, rhs) {
(OwnedValue::Null, _) (OwnedValue::Null, _)
| (_, OwnedValue::Null) | (_, OwnedValue::Null)
@@ -933,8 +914,7 @@ pub fn exec_remainder(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue
} }
} }
pub fn exec_bit_not(mut reg: &OwnedValue) -> OwnedValue { pub fn exec_bit_not(reg: &OwnedValue) -> OwnedValue {
final_agg_values!(reg);
match reg { match reg {
OwnedValue::Null => OwnedValue::Null, OwnedValue::Null => OwnedValue::Null,
OwnedValue::Integer(i) => OwnedValue::Integer(!i), OwnedValue::Integer(i) => OwnedValue::Integer(!i),
@@ -944,8 +924,7 @@ pub fn exec_bit_not(mut reg: &OwnedValue) -> OwnedValue {
} }
} }
pub fn exec_shift_left(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue { pub fn exec_shift_left(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
final_agg_values!(lhs, rhs);
match (lhs, rhs) { match (lhs, rhs) {
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null, (OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
(OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => { (OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => {
@@ -998,8 +977,7 @@ fn compute_shl(lhs: i64, rhs: i64) -> i64 {
} }
} }
pub fn exec_shift_right(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue { pub fn exec_shift_right(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
final_agg_values!(lhs, rhs);
match (lhs, rhs) { match (lhs, rhs) {
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null, (OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
(OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => { (OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => {
@@ -1054,8 +1032,7 @@ fn compute_shr(lhs: i64, rhs: i64) -> i64 {
} }
} }
pub fn exec_boolean_not(mut reg: &OwnedValue) -> OwnedValue { pub fn exec_boolean_not(reg: &OwnedValue) -> OwnedValue {
final_agg_values!(reg);
match reg { match reg {
OwnedValue::Null => OwnedValue::Null, OwnedValue::Null => OwnedValue::Null,
OwnedValue::Integer(i) => OwnedValue::Integer((*i == 0) as i64), OwnedValue::Integer(i) => OwnedValue::Integer((*i == 0) as i64),
@@ -1064,8 +1041,7 @@ pub fn exec_boolean_not(mut reg: &OwnedValue) -> OwnedValue {
_ => todo!(), _ => todo!(),
} }
} }
pub fn exec_concat(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue { pub fn exec_concat(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
final_agg_values!(lhs, rhs);
match (lhs, rhs) { match (lhs, rhs) {
(OwnedValue::Text(lhs_text), OwnedValue::Text(rhs_text)) => { (OwnedValue::Text(lhs_text), OwnedValue::Text(rhs_text)) => {
OwnedValue::build_text(&(lhs_text.as_str().to_string() + rhs_text.as_str())) OwnedValue::build_text(&(lhs_text.as_str().to_string() + rhs_text.as_str()))
@@ -1098,15 +1074,10 @@ pub fn exec_concat(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
(OwnedValue::Blob(_), _) | (_, OwnedValue::Blob(_)) => { (OwnedValue::Blob(_), _) | (_, OwnedValue::Blob(_)) => {
todo!("TODO: Handle Blob conversion to String") todo!("TODO: Handle Blob conversion to String")
} }
(OwnedValue::Record(_), _)
| (_, OwnedValue::Record(_))
| (OwnedValue::Agg(_), _)
| (_, OwnedValue::Agg(_)) => unreachable!(),
} }
} }
pub fn exec_and(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue { pub fn exec_and(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
final_agg_values!(lhs, rhs);
match (lhs, rhs) { match (lhs, rhs) {
(_, OwnedValue::Integer(0)) (_, OwnedValue::Integer(0))
| (OwnedValue::Integer(0), _) | (OwnedValue::Integer(0), _)
@@ -1124,8 +1095,7 @@ pub fn exec_and(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
} }
} }
pub fn exec_or(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue { pub fn exec_or(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
final_agg_values!(lhs, rhs);
match (lhs, rhs) { match (lhs, rhs) {
(OwnedValue::Null, OwnedValue::Null) (OwnedValue::Null, OwnedValue::Null)
| (OwnedValue::Null, OwnedValue::Float(0.0)) | (OwnedValue::Null, OwnedValue::Float(0.0))

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,12 @@
use crate::types::OwnedValue; use crate::types::OwnedValue;
use crate::vdbe::Register;
use crate::LimboError; use crate::LimboError;
use crate::Result; use crate::Result;
pub mod vector_types; pub mod vector_types;
use vector_types::*; use vector_types::*;
pub fn vector32(args: &[OwnedValue]) -> Result<OwnedValue> { pub fn vector32(args: &[Register]) -> Result<OwnedValue> {
if args.len() != 1 { if args.len() != 1 {
return Err(LimboError::ConversionError( return Err(LimboError::ConversionError(
"vector32 requires exactly one argument".to_string(), "vector32 requires exactly one argument".to_string(),
@@ -22,7 +23,7 @@ pub fn vector32(args: &[OwnedValue]) -> Result<OwnedValue> {
} }
} }
pub fn vector64(args: &[OwnedValue]) -> Result<OwnedValue> { pub fn vector64(args: &[Register]) -> Result<OwnedValue> {
if args.len() != 1 { if args.len() != 1 {
return Err(LimboError::ConversionError( return Err(LimboError::ConversionError(
"vector64 requires exactly one argument".to_string(), "vector64 requires exactly one argument".to_string(),
@@ -39,14 +40,14 @@ pub fn vector64(args: &[OwnedValue]) -> Result<OwnedValue> {
} }
} }
pub fn vector_extract(args: &[OwnedValue]) -> Result<OwnedValue> { pub fn vector_extract(args: &[Register]) -> Result<OwnedValue> {
if args.len() != 1 { if args.len() != 1 {
return Err(LimboError::ConversionError( return Err(LimboError::ConversionError(
"vector_extract requires exactly one argument".to_string(), "vector_extract requires exactly one argument".to_string(),
)); ));
} }
let blob = match &args[0] { let blob = match &args[0].get_owned_value() {
OwnedValue::Blob(b) => b, OwnedValue::Blob(b) => b,
_ => { _ => {
return Err(LimboError::ConversionError( return Err(LimboError::ConversionError(
@@ -64,7 +65,7 @@ pub fn vector_extract(args: &[OwnedValue]) -> Result<OwnedValue> {
Ok(OwnedValue::build_text(&vector_to_text(&vector))) Ok(OwnedValue::build_text(&vector_to_text(&vector)))
} }
pub fn vector_distance_cos(args: &[OwnedValue]) -> Result<OwnedValue> { pub fn vector_distance_cos(args: &[Register]) -> Result<OwnedValue> {
if args.len() != 2 { if args.len() != 2 {
return Err(LimboError::ConversionError( return Err(LimboError::ConversionError(
"vector_distance_cos requires exactly two arguments".to_string(), "vector_distance_cos requires exactly two arguments".to_string(),

View File

@@ -1,4 +1,5 @@
use crate::types::{OwnedValue, OwnedValueType}; use crate::types::{OwnedValue, OwnedValueType};
use crate::vdbe::Register;
use crate::{LimboError, Result}; use crate::{LimboError, Result};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@@ -103,11 +104,14 @@ pub fn parse_string_vector(vector_type: VectorType, value: &OwnedValue) -> Resul
}) })
} }
pub fn parse_vector(value: &OwnedValue, vec_ty: Option<VectorType>) -> Result<Vector> { pub fn parse_vector(value: &Register, vec_ty: Option<VectorType>) -> Result<Vector> {
match value.value_type() { match value.get_owned_value().value_type() {
OwnedValueType::Text => parse_string_vector(vec_ty.unwrap_or(VectorType::Float32), value), OwnedValueType::Text => parse_string_vector(
vec_ty.unwrap_or(VectorType::Float32),
value.get_owned_value(),
),
OwnedValueType::Blob => { OwnedValueType::Blob => {
let Some(blob) = value.to_blob() else { let Some(blob) = value.get_owned_value().to_blob() else {
return Err(LimboError::ConversionError( return Err(LimboError::ConversionError(
"Invalid vector value".to_string(), "Invalid vector value".to_string(),
)); ));

View File

@@ -501,7 +501,6 @@ impl Interaction {
Value::Text(t.as_str().to_string()) Value::Text(t.as_str().to_string())
} }
limbo_core::OwnedValue::Blob(b) => Value::Blob(b.to_vec()), limbo_core::OwnedValue::Blob(b) => Value::Blob(b.to_vec()),
_ => unreachable!(),
}; };
r.push(v); r.push(v);
} }

View File

@@ -572,7 +572,6 @@ pub unsafe extern "C" fn sqlite3_value_type(value: *mut ffi::c_void) -> ffi::c_i
limbo_core::OwnedValue::Float(_) => 2, limbo_core::OwnedValue::Float(_) => 2,
limbo_core::OwnedValue::Text(_) => 3, limbo_core::OwnedValue::Text(_) => 3,
limbo_core::OwnedValue::Blob(_) => 4, limbo_core::OwnedValue::Blob(_) => 4,
_ => unreachable!(),
} }
} }