mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-18 17:14:20 +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 => {
|
limbo_core::OwnedValue::Null => {
|
||||||
LimboValue::new(ValueType::Null, ValueUnion::from_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::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);
|
||||||
|
|||||||
@@ -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(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
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};
|
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,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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!(),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
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::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(),
|
||||||
|
|||||||
@@ -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(),
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user