mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-18 00:54:19 +01:00
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:
@@ -160,7 +160,6 @@ impl LimboValue {
|
||||
limbo_core::OwnedValue::Null => {
|
||||
LimboValue::new(ValueType::Null, ValueUnion::from_null())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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::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) {
|
||||
eprintln!("Error on parsing row: {:?}", e);
|
||||
|
||||
@@ -101,7 +101,6 @@ fn to_js_value(env: &napi::Env, value: &limbo_core::OwnedValue) -> JsUnknown {
|
||||
limbo_core::OwnedValue::Blob(b) => {
|
||||
env.create_buffer_copy(b.as_ref()).unwrap().into_unknown()
|
||||
}
|
||||
_ => env.get_null().unwrap().into_unknown(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -333,7 +333,6 @@ fn row_to_py(py: Python, row: &limbo_core::Row) -> Result<PyObject> {
|
||||
limbo_core::OwnedValue::Blob(b) => {
|
||||
py_values.push(PyBytes::new(py, b.as_slice()).into())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
Ok(PyTuple::new(py, &py_values)
|
||||
|
||||
@@ -236,8 +236,6 @@ impl Row {
|
||||
limbo_core::OwnedValue::Float(f) => Ok(Value::Real(*f)),
|
||||
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::Agg(_agg_context) => todo!(),
|
||||
limbo_core::OwnedValue::Record(_record) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +191,6 @@ fn to_js_value(value: &limbo_core::OwnedValue) -> JsValue {
|
||||
limbo_core::OwnedValue::Float(f) => JsValue::from(*f),
|
||||
limbo_core::OwnedValue::Text(t) => JsValue::from_str(t.as_str()),
|
||||
limbo_core::OwnedValue::Blob(b) => js_sys::Uint8Array::from(b.as_slice()).into(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -717,7 +717,6 @@ impl<'a> Limbo<'a> {
|
||||
OwnedValue::Blob(b) => {
|
||||
format!("{}", String::from_utf8_lossy(b))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
.as_bytes(),
|
||||
)?;
|
||||
@@ -784,7 +783,6 @@ impl<'a> Limbo<'a> {
|
||||
String::from_utf8_lossy(b).to_string(),
|
||||
CellAlignment::Left,
|
||||
),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
row.add_cell(
|
||||
Cell::new(content)
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
use crate::types::OwnedValue;
|
||||
use crate::LimboError::InvalidModifier;
|
||||
use crate::Result;
|
||||
use crate::{types::OwnedValue, vdbe::Register};
|
||||
use chrono::{
|
||||
DateTime, Datelike, NaiveDate, NaiveDateTime, NaiveTime, TimeDelta, TimeZone, Timelike, Utc,
|
||||
};
|
||||
|
||||
/// Execution of date/time/datetime functions
|
||||
#[inline(always)]
|
||||
pub fn exec_date(values: &[OwnedValue]) -> OwnedValue {
|
||||
pub fn exec_date(values: &[Register]) -> OwnedValue {
|
||||
exec_datetime(values, DateTimeOutput::Date)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn exec_time(values: &[OwnedValue]) -> OwnedValue {
|
||||
pub fn exec_time(values: &[Register]) -> OwnedValue {
|
||||
exec_datetime(values, DateTimeOutput::Time)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn exec_datetime_full(values: &[OwnedValue]) -> OwnedValue {
|
||||
pub fn exec_datetime_full(values: &[Register]) -> OwnedValue {
|
||||
exec_datetime(values, DateTimeOutput::DateTime)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn exec_strftime(values: &[OwnedValue]) -> OwnedValue {
|
||||
pub fn exec_strftime(values: &[Register]) -> OwnedValue {
|
||||
if values.is_empty() {
|
||||
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::Integer(num) => num.to_string(),
|
||||
OwnedValue::Float(num) => format!("{:.14}", num),
|
||||
@@ -45,7 +45,7 @@ enum DateTimeOutput {
|
||||
StrfTime(String),
|
||||
}
|
||||
|
||||
fn exec_datetime(values: &[OwnedValue], output_type: DateTimeOutput) -> OwnedValue {
|
||||
fn exec_datetime(values: &[Register], output_type: DateTimeOutput) -> OwnedValue {
|
||||
if values.is_empty() {
|
||||
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
|
||||
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
|
||||
modify_dt(&mut dt, &values[1..], output_type)
|
||||
} else {
|
||||
@@ -69,15 +69,11 @@ fn exec_datetime(values: &[OwnedValue], output_type: DateTimeOutput) -> OwnedVal
|
||||
}
|
||||
}
|
||||
|
||||
fn modify_dt(
|
||||
dt: &mut NaiveDateTime,
|
||||
mods: &[OwnedValue],
|
||||
output_type: DateTimeOutput,
|
||||
) -> OwnedValue {
|
||||
fn modify_dt(dt: &mut NaiveDateTime, mods: &[Register], output_type: DateTimeOutput) -> OwnedValue {
|
||||
let mut subsec_requested = false;
|
||||
|
||||
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
|
||||
// need to keep track of the current timezone and apply it to the modifier.
|
||||
match apply_modifier(dt, text_rc.as_str()) {
|
||||
@@ -806,7 +802,7 @@ mod tests {
|
||||
];
|
||||
|
||||
for (input, expected) in test_cases {
|
||||
let result = exec_date(&[input.clone()]);
|
||||
let result = exec_date(&[Register::OwnedValue(input.clone())]);
|
||||
assert_eq!(
|
||||
result,
|
||||
OwnedValue::build_text(expected),
|
||||
@@ -847,7 +843,7 @@ mod tests {
|
||||
];
|
||||
|
||||
for case in invalid_cases.iter() {
|
||||
let result = exec_date(&[case.clone()]);
|
||||
let result = exec_date(&[Register::OwnedValue(case.clone())]);
|
||||
match result {
|
||||
OwnedValue::Text(ref result_str) if result_str.value.is_empty() => (),
|
||||
_ => panic!(
|
||||
@@ -960,7 +956,7 @@ mod tests {
|
||||
];
|
||||
|
||||
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 {
|
||||
assert_eq!(result_str.as_str(), expected);
|
||||
} else {
|
||||
@@ -1000,7 +996,7 @@ mod tests {
|
||||
];
|
||||
|
||||
for case in invalid_cases {
|
||||
let result = exec_time(&[case.clone()]);
|
||||
let result = exec_time(&[Register::OwnedValue(case.clone())]);
|
||||
match result {
|
||||
OwnedValue::Text(ref result_str) if result_str.value.is_empty() => (),
|
||||
_ => panic!(
|
||||
@@ -1302,8 +1298,8 @@ mod tests {
|
||||
assert_eq!(dt, create_datetime(2023, 6, 15, 0, 0, 0));
|
||||
}
|
||||
|
||||
fn text(value: &str) -> OwnedValue {
|
||||
OwnedValue::build_text(value)
|
||||
fn text(value: &str) -> Register {
|
||||
Register::OwnedValue(OwnedValue::build_text(value))
|
||||
}
|
||||
|
||||
fn format(dt: NaiveDateTime) -> String {
|
||||
@@ -1321,7 +1317,7 @@ mod tests {
|
||||
&[text("2023-06-15 12:30:45"), text("-1 day")],
|
||||
DateTimeOutput::DateTime,
|
||||
);
|
||||
assert_eq!(result, text(&expected));
|
||||
assert_eq!(result, *text(&expected).get_owned_value());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1336,7 +1332,7 @@ mod tests {
|
||||
],
|
||||
DateTimeOutput::DateTime,
|
||||
);
|
||||
assert_eq!(result, text(&expected));
|
||||
assert_eq!(result, *text(&expected).get_owned_value());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1363,7 +1359,7 @@ mod tests {
|
||||
],
|
||||
DateTimeOutput::DateTime,
|
||||
);
|
||||
assert_eq!(result, text(&expected));
|
||||
assert_eq!(result, *text(&expected).get_owned_value());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1382,7 +1378,7 @@ mod tests {
|
||||
],
|
||||
DateTimeOutput::DateTime,
|
||||
);
|
||||
assert_eq!(result, text(&expected));
|
||||
assert_eq!(result, *text(&expected).get_owned_value());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1402,7 +1398,7 @@ mod tests {
|
||||
],
|
||||
DateTimeOutput::DateTime,
|
||||
);
|
||||
assert_eq!(result, text(&expected));
|
||||
assert_eq!(result, *text(&expected).get_owned_value());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1414,12 +1410,13 @@ mod tests {
|
||||
);
|
||||
assert_eq!(
|
||||
result_local,
|
||||
text(
|
||||
*text(
|
||||
&dt.and_utc()
|
||||
.with_timezone(&chrono::Local)
|
||||
.format("%Y-%m-%d %H:%M:%S")
|
||||
.to_string()
|
||||
)
|
||||
.get_owned_value()
|
||||
);
|
||||
// TODO: utc modifier assumes time given is not already utc
|
||||
// add test when fixed in the future
|
||||
@@ -1457,7 +1454,7 @@ mod tests {
|
||||
.unwrap();
|
||||
let expected = format(max);
|
||||
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
|
||||
@@ -1469,7 +1466,7 @@ mod tests {
|
||||
.unwrap();
|
||||
let expected = String::new(); // SQLite ignores leap seconds
|
||||
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]
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use crate::types::OwnedValue;
|
||||
use crate::vdbe::Register;
|
||||
use crate::LimboError;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn exec_printf(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
|
||||
pub fn exec_printf(values: &[Register]) -> crate::Result<OwnedValue> {
|
||||
if values.is_empty() {
|
||||
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(),
|
||||
_ => return Ok(OwnedValue::Null),
|
||||
};
|
||||
@@ -30,7 +31,7 @@ pub fn exec_printf(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
|
||||
if args_index >= values.len() {
|
||||
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::Float(f) => result.push_str(&f.to_string()),
|
||||
_ => result.push_str("0".into()),
|
||||
@@ -41,7 +42,7 @@ pub fn exec_printf(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
|
||||
if args_index >= values.len() {
|
||||
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::Null => result.push_str("(null)"),
|
||||
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() {
|
||||
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::Integer(i) => result.push_str(&(*i as f64).to_string()),
|
||||
_ => result.push_str("0.0".into()),
|
||||
@@ -78,16 +79,16 @@ pub fn exec_printf(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn text(value: &str) -> OwnedValue {
|
||||
OwnedValue::build_text(value)
|
||||
fn text(value: &str) -> Register {
|
||||
Register::OwnedValue(OwnedValue::build_text(value))
|
||||
}
|
||||
|
||||
fn integer(value: i64) -> OwnedValue {
|
||||
OwnedValue::Integer(value)
|
||||
fn integer(value: i64) -> Register {
|
||||
Register::OwnedValue(OwnedValue::Integer(value))
|
||||
}
|
||||
|
||||
fn float(value: f64) -> OwnedValue {
|
||||
OwnedValue::Float(value)
|
||||
fn float(value: f64) -> Register {
|
||||
Register::OwnedValue(OwnedValue::Float(value))
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -99,7 +100,7 @@ mod tests {
|
||||
fn test_printf_basic_string() {
|
||||
assert_eq!(
|
||||
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
|
||||
(
|
||||
vec![text("Hello, %s!"), OwnedValue::Null],
|
||||
vec![text("Hello, %s!"), Register::OwnedValue(OwnedValue::Null)],
|
||||
text("Hello, (null)!"),
|
||||
),
|
||||
// String with number conversion
|
||||
@@ -127,7 +128,7 @@ mod tests {
|
||||
(vec![text("100%% complete")], text("100% complete")),
|
||||
];
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
assert_eq!(exec_printf(&input).unwrap(), expected);
|
||||
assert_eq!(exec_printf(&input).unwrap(), *expected.get_owned_value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{collections::VecDeque, rc::Rc};
|
||||
|
||||
use crate::types::OwnedValue;
|
||||
use crate::{types::OwnedValue, vdbe::Register};
|
||||
|
||||
use super::{
|
||||
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() {
|
||||
return Ok(OwnedValue::Null);
|
||||
}
|
||||
|
||||
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..] {
|
||||
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 _ = 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)
|
||||
}
|
||||
|
||||
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() {
|
||||
return Ok(OwnedValue::Null);
|
||||
}
|
||||
|
||||
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..] {
|
||||
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 _ = 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())))
|
||||
}
|
||||
|
||||
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() {
|
||||
return Ok(OwnedValue::Null);
|
||||
}
|
||||
|
||||
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);
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
|
||||
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() {
|
||||
return Ok(OwnedValue::Null);
|
||||
}
|
||||
|
||||
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);
|
||||
for chunk in other {
|
||||
let path = json_path_from_owned_value(&chunk[0], true)?;
|
||||
let value = convert_dbtype_to_jsonb(&chunk[1], Conv::NotStrict)?;
|
||||
let path = json_path_from_owned_value(&chunk[0].get_owned_value(), true)?;
|
||||
let value = convert_dbtype_to_jsonb(&chunk[1].get_owned_value(), Conv::NotStrict)?;
|
||||
if let Some(path) = path {
|
||||
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)
|
||||
}
|
||||
|
||||
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() {
|
||||
return Ok(OwnedValue::Null);
|
||||
}
|
||||
|
||||
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);
|
||||
for chunk in other {
|
||||
let path = json_path_from_owned_value(&chunk[0], true)?;
|
||||
let value = convert_dbtype_to_jsonb(&chunk[1], Conv::NotStrict)?;
|
||||
let path = json_path_from_owned_value(&chunk[0].get_owned_value(), true)?;
|
||||
let value = convert_dbtype_to_jsonb(&chunk[1].get_owned_value(), Conv::NotStrict)?;
|
||||
if let Some(path) = path {
|
||||
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)
|
||||
}
|
||||
|
||||
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() {
|
||||
return Ok(OwnedValue::Null);
|
||||
}
|
||||
|
||||
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);
|
||||
for chunk in other {
|
||||
let path = json_path_from_owned_value(&chunk[0], true)?;
|
||||
let value = convert_dbtype_to_jsonb(&chunk[1], Conv::NotStrict)?;
|
||||
let path = json_path_from_owned_value(&chunk[0].get_owned_value(), true)?;
|
||||
let value = convert_dbtype_to_jsonb(&chunk[1].get_owned_value(), Conv::NotStrict)?;
|
||||
if let Some(path) = path {
|
||||
let mut op = InsertOperation::new(value);
|
||||
|
||||
@@ -608,7 +608,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
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 result = json_remove(&args, &json_cache).unwrap();
|
||||
@@ -621,9 +624,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_json_remove_multiple_paths() {
|
||||
let args = vec![
|
||||
create_json(r#"{"a": 1, "b": 2, "c": 3}"#),
|
||||
create_text("$.a"),
|
||||
create_text("$.c"),
|
||||
Register::OwnedValue(create_json(r#"{"a": 1, "b": 2, "c": 3}"#)),
|
||||
Register::OwnedValue(create_text("$.a")),
|
||||
Register::OwnedValue(create_text("$.c")),
|
||||
];
|
||||
|
||||
let json_cache = JsonCacheCell::new();
|
||||
@@ -637,8 +640,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_json_remove_nested_paths() {
|
||||
let args = vec![
|
||||
create_json(r#"{"a": {"b": {"c": 1, "d": 2}}}"#),
|
||||
create_text("$.a.b.c"),
|
||||
Register::OwnedValue(create_json(r#"{"a": {"b": {"c": 1, "d": 2}}}"#)),
|
||||
Register::OwnedValue(create_text("$.a.b.c")),
|
||||
];
|
||||
|
||||
let json_cache = JsonCacheCell::new();
|
||||
@@ -652,8 +655,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_json_remove_duplicate_keys() {
|
||||
let args = vec![
|
||||
create_json(r#"{"a": 1, "a": 2, "a": 3}"#),
|
||||
create_text("$.a"),
|
||||
Register::OwnedValue(create_json(r#"{"a": 1, "a": 2, "a": 3}"#)),
|
||||
Register::OwnedValue(create_text("$.a")),
|
||||
];
|
||||
|
||||
let json_cache = JsonCacheCell::new();
|
||||
@@ -667,8 +670,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_json_remove_invalid_path() {
|
||||
let args = vec![
|
||||
create_json(r#"{"a": 1}"#),
|
||||
OwnedValue::Integer(42), // Invalid path type
|
||||
Register::OwnedValue(create_json(r#"{"a": 1}"#)),
|
||||
Register::OwnedValue(OwnedValue::Integer(42)), // Invalid path type
|
||||
];
|
||||
|
||||
let json_cache = JsonCacheCell::new();
|
||||
@@ -678,10 +681,12 @@ mod tests {
|
||||
#[test]
|
||||
fn test_json_remove_complex_case() {
|
||||
let args = vec![
|
||||
create_json(r#"{"a":[1,2,3],"b":{"x":1,"x":2},"c":[{"y":1},{"y":2}]}"#),
|
||||
create_text("$.a[1]"),
|
||||
create_text("$.b.x"),
|
||||
create_text("$.c[0].y"),
|
||||
Register::OwnedValue(create_json(
|
||||
r#"{"a":[1,2,3],"b":{"x":1,"x":2},"c":[{"y":1},{"y":2}]}"#,
|
||||
)),
|
||||
Register::OwnedValue(create_text("$.a[1]")),
|
||||
Register::OwnedValue(create_text("$.b.x")),
|
||||
Register::OwnedValue(create_text("$.c[0].y")),
|
||||
];
|
||||
|
||||
let json_cache = JsonCacheCell::new();
|
||||
|
||||
218
core/json/mod.rs
218
core/json/mod.rs
@@ -15,6 +15,7 @@ pub use crate::json::json_operations::{
|
||||
use crate::json::json_path::{json_path, JsonPath, PathElement};
|
||||
pub use crate::json::ser::to_string;
|
||||
use crate::types::{OwnedValue, OwnedValueType, Text, TextSubtype};
|
||||
use crate::vdbe::Register;
|
||||
use crate::{bail_parse_error, json::de::ordered_object};
|
||||
pub use json_cache::JsonCacheCell;
|
||||
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()?;
|
||||
Ok(json)
|
||||
}
|
||||
OwnedValue::Record(_) | OwnedValue::Agg(_) => {
|
||||
bail_constraint_error!("Wrong number of arguments");
|
||||
}
|
||||
OwnedValue::Null => Ok(Jsonb::from_raw_data(
|
||||
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::Float(f) => Ok(Val::Float(*f)),
|
||||
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());
|
||||
|
||||
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")
|
||||
}
|
||||
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.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)
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
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")
|
||||
}
|
||||
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.finalize_unsafe(ElementType::ARRAY)?;
|
||||
@@ -222,19 +219,19 @@ pub fn json_array_length(
|
||||
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() {
|
||||
return Ok(OwnedValue::Null);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
if let Some(path) = path {
|
||||
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
|
||||
pub fn json_extract(
|
||||
value: &OwnedValue,
|
||||
paths: &[OwnedValue],
|
||||
paths: &[Register],
|
||||
json_cache: &JsonCacheCell,
|
||||
) -> crate::Result<OwnedValue> {
|
||||
if let OwnedValue::Null = value {
|
||||
@@ -334,7 +331,7 @@ pub fn json_extract(
|
||||
|
||||
pub fn jsonb_extract(
|
||||
value: &OwnedValue,
|
||||
paths: &[OwnedValue],
|
||||
paths: &[Register],
|
||||
json_cache: &JsonCacheCell,
|
||||
) -> crate::Result<OwnedValue> {
|
||||
if let OwnedValue::Null = value {
|
||||
@@ -353,13 +350,10 @@ pub fn jsonb_extract(
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn jsonb_extract_internal(
|
||||
value: Jsonb,
|
||||
paths: &[OwnedValue],
|
||||
) -> crate::Result<(Jsonb, ElementType)> {
|
||||
fn jsonb_extract_internal(value: Jsonb, paths: &[Register]) -> crate::Result<(Jsonb, ElementType)> {
|
||||
let null = Jsonb::from_raw_data(JsonbHeader::make_null().into_bytes().as_bytes());
|
||||
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 op = SearchOperation::new(json.len());
|
||||
@@ -383,7 +377,9 @@ fn jsonb_extract_internal(
|
||||
let mut result = Jsonb::make_empty_array(json.len());
|
||||
|
||||
// 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 {
|
||||
if let Some(path) = path? {
|
||||
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.
|
||||
/// 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)
|
||||
pub fn json_object(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
|
||||
pub fn json_object(values: &[Register]) -> crate::Result<OwnedValue> {
|
||||
if values.len() % 2 != 0 {
|
||||
bail_constraint_error!("json_object() requires an even number of arguments")
|
||||
}
|
||||
let mut json = Jsonb::make_empty_obj(values.len() * 50);
|
||||
|
||||
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")
|
||||
}
|
||||
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());
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -602,19 +598,19 @@ pub fn json_object(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
|
||||
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 {
|
||||
bail_constraint_error!("json_object() requires an even number of arguments")
|
||||
}
|
||||
let mut json = Jsonb::make_empty_obj(values.len() * 50);
|
||||
|
||||
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")
|
||||
}
|
||||
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());
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -663,9 +659,6 @@ pub fn json_quote(value: &OwnedValue) -> crate::Result<OwnedValue> {
|
||||
OwnedValue::Float(ref float) => Ok(OwnedValue::Float(float.to_owned())),
|
||||
OwnedValue::Blob(_) => crate::bail_constraint_error!("JSON cannot hold BLOB values"),
|
||||
OwnedValue::Null => Ok(OwnedValue::build_text("null")),
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -806,9 +799,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_json_array_simple() {
|
||||
let text = OwnedValue::build_text("value1");
|
||||
let json = OwnedValue::Text(Text::json("\"value2\"".to_string()));
|
||||
let input = vec![text, json, OwnedValue::Integer(1), OwnedValue::Float(1.1)];
|
||||
let text = Register::OwnedValue(OwnedValue::build_text("value1"));
|
||||
let json = Register::OwnedValue(OwnedValue::Text(Text::json("\"value2\"".to_string())));
|
||||
let input = vec![
|
||||
text,
|
||||
json,
|
||||
Register::OwnedValue(OwnedValue::Integer(1)),
|
||||
Register::OwnedValue(OwnedValue::Float(1.1)),
|
||||
];
|
||||
|
||||
let result = json_array(&input).unwrap();
|
||||
if let OwnedValue::Text(res) = result {
|
||||
@@ -834,7 +832,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
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];
|
||||
|
||||
@@ -962,7 +960,7 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_extract(
|
||||
&OwnedValue::build_text("{\"a\":2}"),
|
||||
&[OwnedValue::build_text("$.x")],
|
||||
&[Register::OwnedValue(OwnedValue::build_text("$.x"))],
|
||||
&json_cache,
|
||||
);
|
||||
|
||||
@@ -976,7 +974,7 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_extract(
|
||||
&OwnedValue::build_text("{\"a\":2}"),
|
||||
&[OwnedValue::Null],
|
||||
&[Register::OwnedValue(OwnedValue::Null)],
|
||||
&json_cache,
|
||||
);
|
||||
|
||||
@@ -991,7 +989,7 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_extract(
|
||||
&OwnedValue::build_text("{\"a\":2}"),
|
||||
&[OwnedValue::Float(1.1)],
|
||||
&[Register::OwnedValue(OwnedValue::Float(1.1))],
|
||||
&json_cache,
|
||||
);
|
||||
|
||||
@@ -1052,8 +1050,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_json_object_simple() {
|
||||
let key = OwnedValue::build_text("key");
|
||||
let value = OwnedValue::build_text("value");
|
||||
let key = Register::OwnedValue(OwnedValue::build_text("key"));
|
||||
let value = Register::OwnedValue(OwnedValue::build_text("value"));
|
||||
let input = vec![key, value];
|
||||
|
||||
let result = json_object(&input).unwrap();
|
||||
@@ -1077,16 +1075,16 @@ mod tests {
|
||||
let null_value = OwnedValue::Null;
|
||||
|
||||
let input = vec![
|
||||
text_key,
|
||||
text_value,
|
||||
json_key,
|
||||
json_value,
|
||||
integer_key,
|
||||
integer_value,
|
||||
float_key,
|
||||
float_value,
|
||||
null_key,
|
||||
null_value,
|
||||
Register::OwnedValue(text_key),
|
||||
Register::OwnedValue(text_value),
|
||||
Register::OwnedValue(json_key),
|
||||
Register::OwnedValue(json_value),
|
||||
Register::OwnedValue(integer_key),
|
||||
Register::OwnedValue(integer_value),
|
||||
Register::OwnedValue(float_key),
|
||||
Register::OwnedValue(float_value),
|
||||
Register::OwnedValue(null_key),
|
||||
Register::OwnedValue(null_value),
|
||||
];
|
||||
|
||||
let result = json_object(&input).unwrap();
|
||||
@@ -1101,8 +1099,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_json_object_json_value_is_rendered_as_json() {
|
||||
let key = OwnedValue::build_text("key");
|
||||
let value = OwnedValue::Text(Text::json(r#"{"json":"value"}"#.to_string()));
|
||||
let key = Register::OwnedValue(OwnedValue::build_text("key"));
|
||||
let value = Register::OwnedValue(OwnedValue::Text(Text::json(
|
||||
r#"{"json":"value"}"#.to_string(),
|
||||
)));
|
||||
let input = vec![key, value];
|
||||
|
||||
let result = json_object(&input).unwrap();
|
||||
@@ -1114,8 +1114,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_json_object_json_text_value_is_rendered_as_regular_text() {
|
||||
let key = OwnedValue::build_text("key");
|
||||
let value = OwnedValue::Text(Text::new(r#"{"json":"value"}"#));
|
||||
let key = Register::OwnedValue(OwnedValue::build_text("key"));
|
||||
let value = Register::OwnedValue(OwnedValue::Text(Text::new(r#"{"json":"value"}"#)));
|
||||
let input = vec![key, value];
|
||||
|
||||
let result = json_object(&input).unwrap();
|
||||
@@ -1127,12 +1127,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_json_object_nested() {
|
||||
let key = OwnedValue::build_text("key");
|
||||
let value = OwnedValue::build_text("value");
|
||||
let key = Register::OwnedValue(OwnedValue::build_text("key"));
|
||||
let value = Register::OwnedValue(OwnedValue::build_text("value"));
|
||||
let input = vec![key, value];
|
||||
|
||||
let parent_key = OwnedValue::build_text("parent_key");
|
||||
let parent_value = json_object(&input).unwrap();
|
||||
let parent_key = Register::OwnedValue(OwnedValue::build_text("parent_key"));
|
||||
let parent_value = Register::OwnedValue(json_object(&input).unwrap());
|
||||
let parent_input = vec![parent_key, parent_value];
|
||||
|
||||
let result = json_object(&parent_input).unwrap();
|
||||
@@ -1145,8 +1145,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_json_object_duplicated_keys() {
|
||||
let key = OwnedValue::build_text("key");
|
||||
let value = OwnedValue::build_text("value");
|
||||
let key = Register::OwnedValue(OwnedValue::build_text("key"));
|
||||
let value = Register::OwnedValue(OwnedValue::build_text("value"));
|
||||
let input = vec![key.clone(), value.clone(), key, value];
|
||||
|
||||
let result = json_object(&input).unwrap();
|
||||
@@ -1169,8 +1169,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_json_object_non_text_key() {
|
||||
let key = OwnedValue::Integer(1);
|
||||
let value = OwnedValue::build_text("value");
|
||||
let key = Register::OwnedValue(OwnedValue::Integer(1));
|
||||
let value = Register::OwnedValue(OwnedValue::build_text("value"));
|
||||
let input = vec![key, value];
|
||||
|
||||
match json_object(&input) {
|
||||
@@ -1181,8 +1181,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_json_odd_number_of_values() {
|
||||
let key = OwnedValue::build_text("key");
|
||||
let value = OwnedValue::build_text("value");
|
||||
let key = Register::OwnedValue(OwnedValue::build_text("key"));
|
||||
let value = Register::OwnedValue(OwnedValue::build_text("value"));
|
||||
let input = vec![key.clone(), value, key];
|
||||
|
||||
assert!(json_object(&input).is_err());
|
||||
@@ -1320,9 +1320,9 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_set(
|
||||
&[
|
||||
OwnedValue::build_text("{}"),
|
||||
OwnedValue::build_text("$.field"),
|
||||
OwnedValue::build_text("value"),
|
||||
Register::OwnedValue(OwnedValue::build_text("{}")),
|
||||
Register::OwnedValue(OwnedValue::build_text("$.field")),
|
||||
Register::OwnedValue(OwnedValue::build_text("value")),
|
||||
],
|
||||
&json_cache,
|
||||
);
|
||||
@@ -1337,9 +1337,9 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_set(
|
||||
&[
|
||||
OwnedValue::build_text(r#"{"field":"old_value"}"#),
|
||||
OwnedValue::build_text("$.field"),
|
||||
OwnedValue::build_text("new_value"),
|
||||
Register::OwnedValue(OwnedValue::build_text(r#"{"field":"old_value"}"#)),
|
||||
Register::OwnedValue(OwnedValue::build_text("$.field")),
|
||||
Register::OwnedValue(OwnedValue::build_text("new_value")),
|
||||
],
|
||||
&json_cache,
|
||||
);
|
||||
@@ -1357,9 +1357,9 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_set(
|
||||
&[
|
||||
OwnedValue::build_text("{}"),
|
||||
OwnedValue::build_text("$.object.doesnt.exist"),
|
||||
OwnedValue::build_text("value"),
|
||||
Register::OwnedValue(OwnedValue::build_text("{}")),
|
||||
Register::OwnedValue(OwnedValue::build_text("$.object.doesnt.exist")),
|
||||
Register::OwnedValue(OwnedValue::build_text("value")),
|
||||
],
|
||||
&json_cache,
|
||||
);
|
||||
@@ -1377,9 +1377,9 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_set(
|
||||
&[
|
||||
OwnedValue::build_text("[]"),
|
||||
OwnedValue::build_text("$[0]"),
|
||||
OwnedValue::build_text("value"),
|
||||
Register::OwnedValue(OwnedValue::build_text("[]")),
|
||||
Register::OwnedValue(OwnedValue::build_text("$[0]")),
|
||||
Register::OwnedValue(OwnedValue::build_text("value")),
|
||||
],
|
||||
&json_cache,
|
||||
);
|
||||
@@ -1394,9 +1394,9 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_set(
|
||||
&[
|
||||
OwnedValue::build_text("{}"),
|
||||
OwnedValue::build_text("$.some_array[0]"),
|
||||
OwnedValue::Integer(123),
|
||||
Register::OwnedValue(OwnedValue::build_text("{}")),
|
||||
Register::OwnedValue(OwnedValue::build_text("$.some_array[0]")),
|
||||
Register::OwnedValue(OwnedValue::Integer(123)),
|
||||
],
|
||||
&json_cache,
|
||||
);
|
||||
@@ -1414,9 +1414,9 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_set(
|
||||
&[
|
||||
OwnedValue::build_text("[123]"),
|
||||
OwnedValue::build_text("$[1]"),
|
||||
OwnedValue::Integer(456),
|
||||
Register::OwnedValue(OwnedValue::build_text("[123]")),
|
||||
Register::OwnedValue(OwnedValue::build_text("$[1]")),
|
||||
Register::OwnedValue(OwnedValue::Integer(456)),
|
||||
],
|
||||
&json_cache,
|
||||
);
|
||||
@@ -1431,9 +1431,9 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_set(
|
||||
&[
|
||||
OwnedValue::build_text("[123]"),
|
||||
OwnedValue::build_text("$[200]"),
|
||||
OwnedValue::Integer(456),
|
||||
Register::OwnedValue(OwnedValue::build_text("[123]")),
|
||||
Register::OwnedValue(OwnedValue::build_text("$[200]")),
|
||||
Register::OwnedValue(OwnedValue::Integer(456)),
|
||||
],
|
||||
&json_cache,
|
||||
);
|
||||
@@ -1448,9 +1448,9 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_set(
|
||||
&[
|
||||
OwnedValue::build_text("[123]"),
|
||||
OwnedValue::build_text("$[0]"),
|
||||
OwnedValue::Integer(456),
|
||||
Register::OwnedValue(OwnedValue::build_text("[123]")),
|
||||
Register::OwnedValue(OwnedValue::build_text("$[0]")),
|
||||
Register::OwnedValue(OwnedValue::Integer(456)),
|
||||
],
|
||||
&json_cache,
|
||||
);
|
||||
@@ -1465,9 +1465,9 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_set(
|
||||
&[
|
||||
OwnedValue::build_text("{}"),
|
||||
OwnedValue::Null,
|
||||
OwnedValue::Integer(456),
|
||||
Register::OwnedValue(OwnedValue::build_text("{}")),
|
||||
Register::OwnedValue(OwnedValue::Null),
|
||||
Register::OwnedValue(OwnedValue::Integer(456)),
|
||||
],
|
||||
&json_cache,
|
||||
);
|
||||
@@ -1482,11 +1482,11 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_set(
|
||||
&[
|
||||
OwnedValue::build_text("[123]"),
|
||||
OwnedValue::build_text("$[0]"),
|
||||
OwnedValue::Integer(456),
|
||||
OwnedValue::build_text("$[1]"),
|
||||
OwnedValue::Integer(789),
|
||||
Register::OwnedValue(OwnedValue::build_text("[123]")),
|
||||
Register::OwnedValue(OwnedValue::build_text("$[0]")),
|
||||
Register::OwnedValue(OwnedValue::Integer(456)),
|
||||
Register::OwnedValue(OwnedValue::build_text("$[1]")),
|
||||
Register::OwnedValue(OwnedValue::Integer(789)),
|
||||
],
|
||||
&json_cache,
|
||||
);
|
||||
@@ -1501,9 +1501,9 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_set(
|
||||
&[
|
||||
OwnedValue::build_text("{}"),
|
||||
OwnedValue::build_text("$.object[0].field"),
|
||||
OwnedValue::Integer(123),
|
||||
Register::OwnedValue(OwnedValue::build_text("{}")),
|
||||
Register::OwnedValue(OwnedValue::build_text("$.object[0].field")),
|
||||
Register::OwnedValue(OwnedValue::Integer(123)),
|
||||
],
|
||||
&json_cache,
|
||||
);
|
||||
@@ -1521,9 +1521,9 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_set(
|
||||
&[
|
||||
OwnedValue::build_text("{}"),
|
||||
OwnedValue::build_text("$.object[0][0]"),
|
||||
OwnedValue::Integer(123),
|
||||
Register::OwnedValue(OwnedValue::build_text("{}")),
|
||||
Register::OwnedValue(OwnedValue::build_text("$.object[0][0]")),
|
||||
Register::OwnedValue(OwnedValue::Integer(123)),
|
||||
],
|
||||
&json_cache,
|
||||
);
|
||||
@@ -1538,11 +1538,11 @@ mod tests {
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_set(
|
||||
&[
|
||||
OwnedValue::build_text("{}"),
|
||||
OwnedValue::build_text("$.object[123].another"),
|
||||
OwnedValue::build_text("value"),
|
||||
OwnedValue::build_text("$.field"),
|
||||
OwnedValue::build_text("value"),
|
||||
Register::OwnedValue(OwnedValue::build_text("{}")),
|
||||
Register::OwnedValue(OwnedValue::build_text("$.object[123].another")),
|
||||
Register::OwnedValue(OwnedValue::build_text("value")),
|
||||
Register::OwnedValue(OwnedValue::build_text("$.field")),
|
||||
Register::OwnedValue(OwnedValue::build_text("value")),
|
||||
],
|
||||
&json_cache,
|
||||
);
|
||||
|
||||
@@ -76,8 +76,6 @@ pub enum OwnedValue {
|
||||
Float(f64),
|
||||
Text(Text),
|
||||
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)]
|
||||
@@ -130,8 +128,6 @@ impl OwnedValue {
|
||||
OwnedValue::Float(_) => OwnedValueType::Float,
|
||||
OwnedValue::Text(_) => OwnedValueType::Text,
|
||||
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::Text(s) => write!(f, "{}", s.as_str()),
|
||||
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::Text(text) => ExtValue::from_text(text.as_str().to_string()),
|
||||
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::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,
|
||||
}
|
||||
}
|
||||
@@ -335,9 +314,6 @@ impl PartialOrd<OwnedValue> for OwnedValue {
|
||||
(Self::Null, Self::Null) => Some(std::cmp::Ordering::Equal),
|
||||
(Self::Null, _) => Some(std::cmp::Ordering::Less),
|
||||
(_, 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),
|
||||
}
|
||||
}
|
||||
@@ -836,8 +812,6 @@ impl From<&OwnedValue> for SerialType {
|
||||
OwnedValue::Blob(b) => SerialType::Blob {
|
||||
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::Text(t) => buf.extend_from_slice(&t.value),
|
||||
OwnedValue::Blob(b) => buf.extend_from_slice(b),
|
||||
// non serializable
|
||||
OwnedValue::Agg(_) => unreachable!(),
|
||||
OwnedValue::Record(_) => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -5,18 +5,6 @@ use crate::storage::wal::CheckpointMode;
|
||||
use crate::types::{OwnedValue, Record};
|
||||
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.
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct CmpInsFlags(usize);
|
||||
@@ -738,8 +726,7 @@ pub enum Cookie {
|
||||
UserVersion = 6,
|
||||
}
|
||||
|
||||
pub fn exec_add(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
final_agg_values!(lhs, rhs);
|
||||
pub fn exec_add(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Integer(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 {
|
||||
final_agg_values!(lhs, rhs);
|
||||
pub fn exec_subtract(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Integer(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 {
|
||||
final_agg_values!(lhs, rhs);
|
||||
pub fn exec_multiply(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Integer(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 {
|
||||
final_agg_values!(lhs, rhs);
|
||||
pub fn exec_divide(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
match (lhs, rhs) {
|
||||
(_, OwnedValue::Integer(0)) | (_, OwnedValue::Float(0.0)) => OwnedValue::Null,
|
||||
(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 {
|
||||
final_agg_values!(lhs, rhs);
|
||||
pub fn exec_bit_and(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
|
||||
(_, 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 {
|
||||
final_agg_values!(lhs, rhs);
|
||||
pub fn exec_bit_or(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
|
||||
(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 {
|
||||
final_agg_values!(lhs, rhs);
|
||||
pub fn exec_remainder(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
match (lhs, rhs) {
|
||||
(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 {
|
||||
final_agg_values!(reg);
|
||||
pub fn exec_bit_not(reg: &OwnedValue) -> OwnedValue {
|
||||
match reg {
|
||||
OwnedValue::Null => OwnedValue::Null,
|
||||
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 {
|
||||
final_agg_values!(lhs, rhs);
|
||||
pub fn exec_shift_left(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
|
||||
(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 {
|
||||
final_agg_values!(lhs, rhs);
|
||||
pub fn exec_shift_right(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
|
||||
(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 {
|
||||
final_agg_values!(reg);
|
||||
pub fn exec_boolean_not(reg: &OwnedValue) -> OwnedValue {
|
||||
match reg {
|
||||
OwnedValue::Null => OwnedValue::Null,
|
||||
OwnedValue::Integer(i) => OwnedValue::Integer((*i == 0) as i64),
|
||||
@@ -1064,8 +1041,7 @@ pub fn exec_boolean_not(mut reg: &OwnedValue) -> OwnedValue {
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
pub fn exec_concat(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
final_agg_values!(lhs, rhs);
|
||||
pub fn exec_concat(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Text(lhs_text), OwnedValue::Text(rhs_text)) => {
|
||||
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(_)) => {
|
||||
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 {
|
||||
final_agg_values!(lhs, rhs);
|
||||
pub fn exec_and(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
match (lhs, rhs) {
|
||||
(_, 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 {
|
||||
final_agg_values!(lhs, rhs);
|
||||
pub fn exec_or(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Null, OwnedValue::Null)
|
||||
| (OwnedValue::Null, OwnedValue::Float(0.0))
|
||||
|
||||
1024
core/vdbe/mod.rs
1024
core/vdbe/mod.rs
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,12 @@
|
||||
use crate::types::OwnedValue;
|
||||
use crate::vdbe::Register;
|
||||
use crate::LimboError;
|
||||
use crate::Result;
|
||||
|
||||
pub mod vector_types;
|
||||
use vector_types::*;
|
||||
|
||||
pub fn vector32(args: &[OwnedValue]) -> Result<OwnedValue> {
|
||||
pub fn vector32(args: &[Register]) -> Result<OwnedValue> {
|
||||
if args.len() != 1 {
|
||||
return Err(LimboError::ConversionError(
|
||||
"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 {
|
||||
return Err(LimboError::ConversionError(
|
||||
"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 {
|
||||
return Err(LimboError::ConversionError(
|
||||
"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,
|
||||
_ => {
|
||||
return Err(LimboError::ConversionError(
|
||||
@@ -64,7 +65,7 @@ pub fn vector_extract(args: &[OwnedValue]) -> Result<OwnedValue> {
|
||||
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 {
|
||||
return Err(LimboError::ConversionError(
|
||||
"vector_distance_cos requires exactly two arguments".to_string(),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::types::{OwnedValue, OwnedValueType};
|
||||
use crate::vdbe::Register;
|
||||
use crate::{LimboError, Result};
|
||||
|
||||
#[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> {
|
||||
match value.value_type() {
|
||||
OwnedValueType::Text => parse_string_vector(vec_ty.unwrap_or(VectorType::Float32), value),
|
||||
pub fn parse_vector(value: &Register, vec_ty: Option<VectorType>) -> Result<Vector> {
|
||||
match value.get_owned_value().value_type() {
|
||||
OwnedValueType::Text => parse_string_vector(
|
||||
vec_ty.unwrap_or(VectorType::Float32),
|
||||
value.get_owned_value(),
|
||||
),
|
||||
OwnedValueType::Blob => {
|
||||
let Some(blob) = value.to_blob() else {
|
||||
let Some(blob) = value.get_owned_value().to_blob() else {
|
||||
return Err(LimboError::ConversionError(
|
||||
"Invalid vector value".to_string(),
|
||||
));
|
||||
|
||||
@@ -501,7 +501,6 @@ impl Interaction {
|
||||
Value::Text(t.as_str().to_string())
|
||||
}
|
||||
limbo_core::OwnedValue::Blob(b) => Value::Blob(b.to_vec()),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
r.push(v);
|
||||
}
|
||||
|
||||
@@ -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::Text(_) => 3,
|
||||
limbo_core::OwnedValue::Blob(_) => 4,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user