mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-14 12:34:20 +01:00
Rename OwnedValue -> Value
We have not had enough merge conflicts for a while so let's do a tree-wide rename.
This commit is contained in:
@@ -2,7 +2,7 @@ use crate::{
|
||||
types::{LimboValue, ResultCode},
|
||||
LimboConn,
|
||||
};
|
||||
use limbo_core::{LimboError, OwnedValue, Statement, StepResult};
|
||||
use limbo_core::{LimboError, Statement, StepResult, Value};
|
||||
use std::ffi::{c_char, c_void};
|
||||
|
||||
pub struct LimboRows<'conn> {
|
||||
@@ -75,7 +75,7 @@ pub extern "C" fn rows_get_value(ctx: *mut c_void, col_idx: usize) -> *const c_v
|
||||
let ctx = LimboRows::from_ptr(ctx);
|
||||
|
||||
if let Some(row) = ctx.stmt.row() {
|
||||
if let Ok(value) = row.get::<&OwnedValue>(col_idx) {
|
||||
if let Ok(value) = row.get::<&Value>(col_idx) {
|
||||
return LimboValue::from_owned_value(value).to_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,64 +174,62 @@ impl LimboValue {
|
||||
Box::into_raw(Box::new(self)) as *const c_void
|
||||
}
|
||||
|
||||
pub fn from_owned_value(value: &limbo_core::OwnedValue) -> Self {
|
||||
pub fn from_owned_value(value: &limbo_core::Value) -> Self {
|
||||
match value {
|
||||
limbo_core::OwnedValue::Integer(i) => {
|
||||
limbo_core::Value::Integer(i) => {
|
||||
LimboValue::new(ValueType::Integer, ValueUnion::from_int(*i))
|
||||
}
|
||||
limbo_core::OwnedValue::Float(r) => {
|
||||
limbo_core::Value::Float(r) => {
|
||||
LimboValue::new(ValueType::Real, ValueUnion::from_real(*r))
|
||||
}
|
||||
limbo_core::OwnedValue::Text(s) => {
|
||||
limbo_core::Value::Text(s) => {
|
||||
LimboValue::new(ValueType::Text, ValueUnion::from_str(s.as_str()))
|
||||
}
|
||||
limbo_core::OwnedValue::Blob(b) => {
|
||||
limbo_core::Value::Blob(b) => {
|
||||
LimboValue::new(ValueType::Blob, ValueUnion::from_bytes(b.as_slice()))
|
||||
}
|
||||
limbo_core::OwnedValue::Null => {
|
||||
LimboValue::new(ValueType::Null, ValueUnion::from_null())
|
||||
}
|
||||
limbo_core::Value::Null => LimboValue::new(ValueType::Null, ValueUnion::from_null()),
|
||||
}
|
||||
}
|
||||
|
||||
// The values we get from Go need to be temporarily owned by the statement until they are bound
|
||||
// then they can be cleaned up immediately afterwards
|
||||
pub fn to_value(&self, pool: &mut AllocPool) -> limbo_core::OwnedValue {
|
||||
pub fn to_value(&self, pool: &mut AllocPool) -> limbo_core::Value {
|
||||
match self.value_type {
|
||||
ValueType::Integer => {
|
||||
if unsafe { self.value.int_val == 0 } {
|
||||
return limbo_core::OwnedValue::Null;
|
||||
return limbo_core::Value::Null;
|
||||
}
|
||||
limbo_core::OwnedValue::Integer(unsafe { self.value.int_val })
|
||||
limbo_core::Value::Integer(unsafe { self.value.int_val })
|
||||
}
|
||||
ValueType::Real => {
|
||||
if unsafe { self.value.real_val == 0.0 } {
|
||||
return limbo_core::OwnedValue::Null;
|
||||
return limbo_core::Value::Null;
|
||||
}
|
||||
limbo_core::OwnedValue::Float(unsafe { self.value.real_val })
|
||||
limbo_core::Value::Float(unsafe { self.value.real_val })
|
||||
}
|
||||
ValueType::Text => {
|
||||
if unsafe { self.value.text_ptr.is_null() } {
|
||||
return limbo_core::OwnedValue::Null;
|
||||
return limbo_core::Value::Null;
|
||||
}
|
||||
let cstr = unsafe { std::ffi::CStr::from_ptr(self.value.text_ptr) };
|
||||
match cstr.to_str() {
|
||||
Ok(utf8_str) => {
|
||||
let owned = utf8_str.to_owned();
|
||||
let borrowed = pool.add_string(owned);
|
||||
limbo_core::OwnedValue::build_text(borrowed)
|
||||
limbo_core::Value::build_text(borrowed)
|
||||
}
|
||||
Err(_) => limbo_core::OwnedValue::Null,
|
||||
Err(_) => limbo_core::Value::Null,
|
||||
}
|
||||
}
|
||||
ValueType::Blob => {
|
||||
if unsafe { self.value.blob_ptr.is_null() } {
|
||||
return limbo_core::OwnedValue::Null;
|
||||
return limbo_core::Value::Null;
|
||||
}
|
||||
let bytes = self.value.to_bytes();
|
||||
limbo_core::OwnedValue::Blob(bytes.to_vec())
|
||||
limbo_core::Value::Blob(bytes.to_vec())
|
||||
}
|
||||
ValueType::Null => limbo_core::OwnedValue::Null,
|
||||
ValueType::Null => limbo_core::Value::Null,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::utils::set_err_msg_and_throw_exception;
|
||||
use jni::objects::{JByteArray, JObject, JObjectArray, JString, JValue};
|
||||
use jni::sys::{jdouble, jint, jlong};
|
||||
use jni::JNIEnv;
|
||||
use limbo_core::{OwnedValue, Statement, StepResult};
|
||||
use limbo_core::{Statement, StepResult, Value};
|
||||
use std::num::NonZero;
|
||||
|
||||
pub const STEP_RESULT_ID_ROW: i32 = 10;
|
||||
@@ -106,15 +106,15 @@ fn row_to_obj_array<'local>(
|
||||
|
||||
for (i, value) in row.get_values().enumerate() {
|
||||
let obj = match value {
|
||||
limbo_core::OwnedValue::Null => JObject::null(),
|
||||
limbo_core::OwnedValue::Integer(i) => {
|
||||
limbo_core::Value::Null => JObject::null(),
|
||||
limbo_core::Value::Integer(i) => {
|
||||
env.new_object("java/lang/Long", "(J)V", &[JValue::Long(*i)])?
|
||||
}
|
||||
limbo_core::OwnedValue::Float(f) => {
|
||||
limbo_core::Value::Float(f) => {
|
||||
env.new_object("java/lang/Double", "(D)V", &[JValue::Double(*f)])?
|
||||
}
|
||||
limbo_core::OwnedValue::Text(s) => env.new_string(s.as_str())?.into(),
|
||||
limbo_core::OwnedValue::Blob(b) => env.byte_array_from_slice(&b.as_slice())?.into(),
|
||||
limbo_core::Value::Text(s) => env.new_string(s.as_str())?.into(),
|
||||
limbo_core::Value::Blob(b) => env.byte_array_from_slice(&b.as_slice())?.into(),
|
||||
};
|
||||
if let Err(e) = env.set_object_array_element(&obj_array, i as i32, obj) {
|
||||
eprintln!("Error on parsing row: {:?}", e);
|
||||
@@ -162,7 +162,7 @@ pub extern "system" fn Java_tech_turso_core_LimboStatement_bindNull<'local>(
|
||||
};
|
||||
|
||||
stmt.stmt
|
||||
.bind_at(NonZero::new(position as usize).unwrap(), OwnedValue::Null);
|
||||
.bind_at(NonZero::new(position as usize).unwrap(), Value::Null);
|
||||
SQLITE_OK
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ pub extern "system" fn Java_tech_turso_core_LimboStatement_bindLong<'local>(
|
||||
|
||||
stmt.stmt.bind_at(
|
||||
NonZero::new(position as usize).unwrap(),
|
||||
OwnedValue::Integer(value),
|
||||
Value::Integer(value),
|
||||
);
|
||||
SQLITE_OK
|
||||
}
|
||||
@@ -207,7 +207,7 @@ pub extern "system" fn Java_tech_turso_core_LimboStatement_bindDouble<'local>(
|
||||
|
||||
stmt.stmt.bind_at(
|
||||
NonZero::new(position as usize).unwrap(),
|
||||
OwnedValue::Float(value),
|
||||
Value::Float(value),
|
||||
);
|
||||
SQLITE_OK
|
||||
}
|
||||
@@ -235,7 +235,7 @@ pub extern "system" fn Java_tech_turso_core_LimboStatement_bindText<'local>(
|
||||
|
||||
stmt.stmt.bind_at(
|
||||
NonZero::new(position as usize).unwrap(),
|
||||
OwnedValue::build_text(text.as_str()),
|
||||
Value::build_text(text.as_str()),
|
||||
);
|
||||
SQLITE_OK
|
||||
}
|
||||
@@ -261,10 +261,8 @@ pub extern "system" fn Java_tech_turso_core_LimboStatement_bindBlob<'local>(
|
||||
Err(_) => return SQLITE_ERROR,
|
||||
};
|
||||
|
||||
stmt.stmt.bind_at(
|
||||
NonZero::new(position as usize).unwrap(),
|
||||
OwnedValue::Blob(blob),
|
||||
);
|
||||
stmt.stmt
|
||||
.bind_at(NonZero::new(position as usize).unwrap(), Value::Blob(blob));
|
||||
SQLITE_OK
|
||||
}
|
||||
|
||||
|
||||
@@ -266,36 +266,36 @@ impl Statement {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_js_value(env: &napi::Env, value: &limbo_core::OwnedValue) -> napi::Result<JsUnknown> {
|
||||
fn to_js_value(env: &napi::Env, value: &limbo_core::Value) -> napi::Result<JsUnknown> {
|
||||
match value {
|
||||
limbo_core::OwnedValue::Null => Ok(env.get_null()?.into_unknown()),
|
||||
limbo_core::OwnedValue::Integer(i) => Ok(env.create_int64(*i)?.into_unknown()),
|
||||
limbo_core::OwnedValue::Float(f) => Ok(env.create_double(*f)?.into_unknown()),
|
||||
limbo_core::OwnedValue::Text(s) => Ok(env.create_string(s.as_str())?.into_unknown()),
|
||||
limbo_core::OwnedValue::Blob(b) => Ok(env.create_buffer_copy(b.as_slice())?.into_unknown()),
|
||||
limbo_core::Value::Null => Ok(env.get_null()?.into_unknown()),
|
||||
limbo_core::Value::Integer(i) => Ok(env.create_int64(*i)?.into_unknown()),
|
||||
limbo_core::Value::Float(f) => Ok(env.create_double(*f)?.into_unknown()),
|
||||
limbo_core::Value::Text(s) => Ok(env.create_string(s.as_str())?.into_unknown()),
|
||||
limbo_core::Value::Blob(b) => Ok(env.create_buffer_copy(b.as_slice())?.into_unknown()),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_js_value(value: JsUnknown) -> napi::Result<limbo_core::OwnedValue> {
|
||||
fn from_js_value(value: JsUnknown) -> napi::Result<limbo_core::Value> {
|
||||
match value.get_type()? {
|
||||
napi::ValueType::Undefined | napi::ValueType::Null | napi::ValueType::Unknown => {
|
||||
Ok(limbo_core::OwnedValue::Null)
|
||||
Ok(limbo_core::Value::Null)
|
||||
}
|
||||
napi::ValueType::Boolean => {
|
||||
let b = value.coerce_to_bool()?.get_value()?;
|
||||
Ok(limbo_core::OwnedValue::Integer(b as i64))
|
||||
Ok(limbo_core::Value::Integer(b as i64))
|
||||
}
|
||||
napi::ValueType::Number => {
|
||||
let num = value.coerce_to_number()?.get_double()?;
|
||||
if num.fract() == 0.0 {
|
||||
Ok(limbo_core::OwnedValue::Integer(num as i64))
|
||||
Ok(limbo_core::Value::Integer(num as i64))
|
||||
} else {
|
||||
Ok(limbo_core::OwnedValue::Float(num))
|
||||
Ok(limbo_core::Value::Float(num))
|
||||
}
|
||||
}
|
||||
napi::ValueType::String => {
|
||||
let s = value.coerce_to_string()?;
|
||||
Ok(limbo_core::OwnedValue::Text(Text::from_str(
|
||||
Ok(limbo_core::Value::Text(Text::from_str(
|
||||
s.into_utf8()?.as_str()?,
|
||||
)))
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use anyhow::Result;
|
||||
use errors::*;
|
||||
use limbo_core::types::Text;
|
||||
use limbo_core::OwnedValue;
|
||||
use limbo_core::Value;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyBytes, PyList, PyTuple};
|
||||
use std::cell::RefCell;
|
||||
@@ -326,13 +326,11 @@ fn row_to_py(py: Python, row: &limbo_core::Row) -> Result<PyObject> {
|
||||
let mut py_values = Vec::new();
|
||||
for value in row.get_values() {
|
||||
match value {
|
||||
limbo_core::OwnedValue::Null => py_values.push(py.None()),
|
||||
limbo_core::OwnedValue::Integer(i) => py_values.push(i.into_pyobject(py)?.into()),
|
||||
limbo_core::OwnedValue::Float(f) => py_values.push(f.into_pyobject(py)?.into()),
|
||||
limbo_core::OwnedValue::Text(s) => py_values.push(s.as_str().into_pyobject(py)?.into()),
|
||||
limbo_core::OwnedValue::Blob(b) => {
|
||||
py_values.push(PyBytes::new(py, b.as_slice()).into())
|
||||
}
|
||||
limbo_core::Value::Null => py_values.push(py.None()),
|
||||
limbo_core::Value::Integer(i) => py_values.push(i.into_pyobject(py)?.into()),
|
||||
limbo_core::Value::Float(f) => py_values.push(f.into_pyobject(py)?.into()),
|
||||
limbo_core::Value::Text(s) => py_values.push(s.as_str().into_pyobject(py)?.into()),
|
||||
limbo_core::Value::Blob(b) => py_values.push(PyBytes::new(py, b.as_slice()).into()),
|
||||
}
|
||||
}
|
||||
Ok(PyTuple::new(py, &py_values)
|
||||
@@ -341,18 +339,18 @@ fn row_to_py(py: Python, row: &limbo_core::Row) -> Result<PyObject> {
|
||||
.into())
|
||||
}
|
||||
|
||||
/// Converts a Python object to a Limbo OwnedValue
|
||||
fn py_to_owned_value(obj: &Bound<PyAny>) -> Result<limbo_core::OwnedValue> {
|
||||
/// Converts a Python object to a Limbo Value
|
||||
fn py_to_owned_value(obj: &Bound<PyAny>) -> Result<limbo_core::Value> {
|
||||
if obj.is_none() {
|
||||
return Ok(OwnedValue::Null);
|
||||
return Ok(Value::Null);
|
||||
} else if let Ok(integer) = obj.extract::<i64>() {
|
||||
return Ok(OwnedValue::Integer(integer));
|
||||
return Ok(Value::Integer(integer));
|
||||
} else if let Ok(float) = obj.extract::<f64>() {
|
||||
return Ok(OwnedValue::Float(float));
|
||||
return Ok(Value::Float(float));
|
||||
} else if let Ok(string) = obj.extract::<String>() {
|
||||
return Ok(OwnedValue::Text(Text::from_str(string)));
|
||||
return Ok(Value::Text(Text::from_str(string)));
|
||||
} else if let Ok(bytes) = obj.downcast::<PyBytes>() {
|
||||
return Ok(OwnedValue::Blob(bytes.as_bytes().to_vec()));
|
||||
return Ok(Value::Blob(bytes.as_bytes().to_vec()));
|
||||
} else {
|
||||
return Err(PyErr::new::<ProgrammingError, _>(format!(
|
||||
"Unsupported Python type: {}",
|
||||
|
||||
@@ -285,7 +285,7 @@ impl Rows {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Row {
|
||||
values: Vec<limbo_core::OwnedValue>,
|
||||
values: Vec<limbo_core::Value>,
|
||||
}
|
||||
|
||||
unsafe impl Send for Row {}
|
||||
@@ -295,11 +295,11 @@ impl Row {
|
||||
pub fn get_value(&self, index: usize) -> Result<Value> {
|
||||
let value = &self.values[index];
|
||||
match value {
|
||||
limbo_core::OwnedValue::Integer(i) => Ok(Value::Integer(*i)),
|
||||
limbo_core::OwnedValue::Null => Ok(Value::Null),
|
||||
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::Value::Integer(i) => Ok(Value::Integer(*i)),
|
||||
limbo_core::Value::Null => Ok(Value::Null),
|
||||
limbo_core::Value::Float(f) => Ok(Value::Real(*f)),
|
||||
limbo_core::Value::Text(text) => Ok(Value::Text(text.to_string())),
|
||||
limbo_core::Value::Blob(items) => Ok(Value::Blob(items.to_vec())),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -110,14 +110,14 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<limbo_core::OwnedValue> for Value {
|
||||
fn into(self) -> limbo_core::OwnedValue {
|
||||
impl Into<limbo_core::Value> for Value {
|
||||
fn into(self) -> limbo_core::Value {
|
||||
match self {
|
||||
Value::Null => limbo_core::OwnedValue::Null,
|
||||
Value::Integer(n) => limbo_core::OwnedValue::Integer(n),
|
||||
Value::Real(n) => limbo_core::OwnedValue::Float(n),
|
||||
Value::Text(t) => limbo_core::OwnedValue::from_text(&t),
|
||||
Value::Blob(items) => limbo_core::OwnedValue::from_blob(items),
|
||||
Value::Null => limbo_core::Value::Null,
|
||||
Value::Integer(n) => limbo_core::Value::Integer(n),
|
||||
Value::Real(n) => limbo_core::Value::Float(n),
|
||||
Value::Text(t) => limbo_core::Value::from_text(&t),
|
||||
Value::Blob(items) => limbo_core::Value::from_blob(items),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,10 +165,10 @@ impl Statement {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_js_value(value: &limbo_core::OwnedValue) -> JsValue {
|
||||
fn to_js_value(value: &limbo_core::Value) -> JsValue {
|
||||
match value {
|
||||
limbo_core::OwnedValue::Null => JsValue::null(),
|
||||
limbo_core::OwnedValue::Integer(i) => {
|
||||
limbo_core::Value::Null => JsValue::null(),
|
||||
limbo_core::Value::Integer(i) => {
|
||||
let i = *i;
|
||||
if i >= i32::MIN as i64 && i <= i32::MAX as i64 {
|
||||
JsValue::from(i as i32)
|
||||
@@ -176,9 +176,9 @@ fn to_js_value(value: &limbo_core::OwnedValue) -> JsValue {
|
||||
JsValue::from(i)
|
||||
}
|
||||
}
|
||||
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(),
|
||||
limbo_core::Value::Float(f) => JsValue::from(*f),
|
||||
limbo_core::Value::Text(t) => JsValue::from_str(t.as_str()),
|
||||
limbo_core::Value::Blob(b) => js_sys::Uint8Array::from(b.as_slice()).into(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
20
cli/app.rs
20
cli/app.rs
@@ -10,7 +10,7 @@ use crate::{
|
||||
HISTORY_FILE,
|
||||
};
|
||||
use comfy_table::{Attribute, Cell, CellAlignment, Color, ContentArrangement, Row, Table};
|
||||
use limbo_core::{Database, LimboError, OwnedValue, Statement, StepResult};
|
||||
use limbo_core::{Database, LimboError, Statement, StepResult, Value};
|
||||
use tracing_appender::non_blocking::WorkerGuard;
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
|
||||
|
||||
@@ -684,7 +684,7 @@ impl Limbo {
|
||||
if i > 0 {
|
||||
let _ = self.writer.write(b"|");
|
||||
}
|
||||
if matches!(value, OwnedValue::Null) {
|
||||
if matches!(value, Value::Null) {
|
||||
let _ = self.writer.write(self.opts.null_value.as_bytes())?;
|
||||
} else {
|
||||
let _ = self.writer.write(format!("{}", value).as_bytes())?;
|
||||
@@ -755,19 +755,19 @@ impl Limbo {
|
||||
row.max_height(1);
|
||||
for (idx, value) in record.get_values().enumerate() {
|
||||
let (content, alignment) = match value {
|
||||
OwnedValue::Null => {
|
||||
Value::Null => {
|
||||
(self.opts.null_value.clone(), CellAlignment::Left)
|
||||
}
|
||||
OwnedValue::Integer(_) => {
|
||||
Value::Integer(_) => {
|
||||
(format!("{}", value), CellAlignment::Right)
|
||||
}
|
||||
OwnedValue::Float(_) => {
|
||||
Value::Float(_) => {
|
||||
(format!("{}", value), CellAlignment::Right)
|
||||
}
|
||||
OwnedValue::Text(_) => {
|
||||
Value::Text(_) => {
|
||||
(format!("{}", value), CellAlignment::Left)
|
||||
}
|
||||
OwnedValue::Blob(_) => {
|
||||
Value::Blob(_) => {
|
||||
(format!("{}", value), CellAlignment::Left)
|
||||
}
|
||||
};
|
||||
@@ -883,7 +883,7 @@ impl Limbo {
|
||||
match rows.step()? {
|
||||
StepResult::Row => {
|
||||
let row = rows.row().unwrap();
|
||||
if let Ok(OwnedValue::Text(schema)) = row.get::<&OwnedValue>(0) {
|
||||
if let Ok(Value::Text(schema)) = row.get::<&Value>(0) {
|
||||
let _ = self.write_fmt(format_args!("{};", schema.as_str()));
|
||||
found = true;
|
||||
}
|
||||
@@ -939,7 +939,7 @@ impl Limbo {
|
||||
match rows.step()? {
|
||||
StepResult::Row => {
|
||||
let row = rows.row().unwrap();
|
||||
if let Ok(OwnedValue::Text(idx)) = row.get::<&OwnedValue>(0) {
|
||||
if let Ok(Value::Text(idx)) = row.get::<&Value>(0) {
|
||||
indexes.push_str(idx.as_str());
|
||||
indexes.push(' ');
|
||||
}
|
||||
@@ -990,7 +990,7 @@ impl Limbo {
|
||||
match rows.step()? {
|
||||
StepResult::Row => {
|
||||
let row = rows.row().unwrap();
|
||||
if let Ok(OwnedValue::Text(table)) = row.get::<&OwnedValue>(0) {
|
||||
if let Ok(Value::Text(table)) = row.get::<&Value>(0) {
|
||||
tables.push_str(table.as_str());
|
||||
tables.push(' ');
|
||||
}
|
||||
|
||||
@@ -1,40 +1,37 @@
|
||||
use crate::LimboError::InvalidModifier;
|
||||
use crate::Result;
|
||||
use crate::{types::OwnedValue, vdbe::Register};
|
||||
use crate::{types::Value, 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: &[Register]) -> OwnedValue {
|
||||
pub fn exec_date(values: &[Register]) -> Value {
|
||||
exec_datetime(values, DateTimeOutput::Date)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn exec_time(values: &[Register]) -> OwnedValue {
|
||||
pub fn exec_time(values: &[Register]) -> Value {
|
||||
exec_datetime(values, DateTimeOutput::Time)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn exec_datetime_full(values: &[Register]) -> OwnedValue {
|
||||
pub fn exec_datetime_full(values: &[Register]) -> Value {
|
||||
exec_datetime(values, DateTimeOutput::DateTime)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn exec_strftime(values: &[Register]) -> OwnedValue {
|
||||
pub fn exec_strftime(values: &[Register]) -> Value {
|
||||
if values.is_empty() {
|
||||
return OwnedValue::Null;
|
||||
return Value::Null;
|
||||
}
|
||||
|
||||
let value = &values[0].get_owned_value();
|
||||
let format_str = if matches!(
|
||||
value,
|
||||
OwnedValue::Text(_) | OwnedValue::Integer(_) | OwnedValue::Float(_)
|
||||
) {
|
||||
let format_str = if matches!(value, Value::Text(_) | Value::Integer(_) | Value::Float(_)) {
|
||||
format!("{}", value)
|
||||
} else {
|
||||
return OwnedValue::Null;
|
||||
return Value::Null;
|
||||
};
|
||||
|
||||
exec_datetime(&values[1..], DateTimeOutput::StrfTime(format_str))
|
||||
@@ -49,9 +46,9 @@ enum DateTimeOutput {
|
||||
JuliaDay,
|
||||
}
|
||||
|
||||
fn exec_datetime(values: &[Register], output_type: DateTimeOutput) -> OwnedValue {
|
||||
fn exec_datetime(values: &[Register], output_type: DateTimeOutput) -> Value {
|
||||
if values.is_empty() {
|
||||
let now = parse_naive_date_time(&OwnedValue::build_text("now")).unwrap();
|
||||
let now = parse_naive_date_time(&Value::build_text("now")).unwrap();
|
||||
return format_dt(now, output_type, false);
|
||||
}
|
||||
if let Some(mut dt) = parse_naive_date_time(values[0].get_owned_value()) {
|
||||
@@ -64,38 +61,38 @@ fn exec_datetime(values: &[Register], output_type: DateTimeOutput) -> OwnedValue
|
||||
}
|
||||
}
|
||||
|
||||
fn modify_dt(dt: &mut NaiveDateTime, mods: &[Register], output_type: DateTimeOutput) -> OwnedValue {
|
||||
fn modify_dt(dt: &mut NaiveDateTime, mods: &[Register], output_type: DateTimeOutput) -> Value {
|
||||
let mut subsec_requested = false;
|
||||
|
||||
for modifier in mods {
|
||||
if let OwnedValue::Text(ref text_rc) = modifier.get_owned_value() {
|
||||
if let Value::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()) {
|
||||
Ok(true) => subsec_requested = true,
|
||||
Ok(false) => {}
|
||||
Err(_) => return OwnedValue::build_text(""),
|
||||
Err(_) => return Value::build_text(""),
|
||||
}
|
||||
} else {
|
||||
return OwnedValue::build_text("");
|
||||
return Value::build_text("");
|
||||
}
|
||||
}
|
||||
if is_leap_second(dt) || *dt > get_max_datetime_exclusive() {
|
||||
return OwnedValue::build_text("");
|
||||
return Value::build_text("");
|
||||
}
|
||||
format_dt(*dt, output_type, subsec_requested)
|
||||
}
|
||||
|
||||
fn format_dt(dt: NaiveDateTime, output_type: DateTimeOutput, subsec: bool) -> OwnedValue {
|
||||
fn format_dt(dt: NaiveDateTime, output_type: DateTimeOutput, subsec: bool) -> Value {
|
||||
match output_type {
|
||||
DateTimeOutput::Date => OwnedValue::from_text(dt.format("%Y-%m-%d").to_string().as_str()),
|
||||
DateTimeOutput::Date => Value::from_text(dt.format("%Y-%m-%d").to_string().as_str()),
|
||||
DateTimeOutput::Time => {
|
||||
let t = if subsec {
|
||||
dt.format("%H:%M:%S%.3f").to_string()
|
||||
} else {
|
||||
dt.format("%H:%M:%S").to_string()
|
||||
};
|
||||
OwnedValue::from_text(t.as_str())
|
||||
Value::from_text(t.as_str())
|
||||
}
|
||||
DateTimeOutput::DateTime => {
|
||||
let t = if subsec {
|
||||
@@ -103,12 +100,12 @@ fn format_dt(dt: NaiveDateTime, output_type: DateTimeOutput, subsec: bool) -> Ow
|
||||
} else {
|
||||
dt.format("%Y-%m-%d %H:%M:%S").to_string()
|
||||
};
|
||||
OwnedValue::from_text(t.as_str())
|
||||
Value::from_text(t.as_str())
|
||||
}
|
||||
DateTimeOutput::StrfTime(format_str) => {
|
||||
OwnedValue::from_text(strftime_format(&dt, &format_str).as_str())
|
||||
Value::from_text(strftime_format(&dt, &format_str).as_str())
|
||||
}
|
||||
DateTimeOutput::JuliaDay => OwnedValue::Float(to_julian_day_exact(&dt)),
|
||||
DateTimeOutput::JuliaDay => Value::Float(to_julian_day_exact(&dt)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +318,7 @@ fn last_day_in_month(year: i32, month: u32) -> u32 {
|
||||
28
|
||||
}
|
||||
|
||||
pub fn exec_julianday(values: &[Register]) -> OwnedValue {
|
||||
pub fn exec_julianday(values: &[Register]) -> Value {
|
||||
exec_datetime(values, DateTimeOutput::JuliaDay)
|
||||
}
|
||||
|
||||
@@ -352,7 +349,7 @@ fn to_julian_day_exact(dt: &NaiveDateTime) -> f64 {
|
||||
jd_days + jd_fraction
|
||||
}
|
||||
|
||||
pub fn exec_unixepoch(time_value: &OwnedValue) -> Result<String> {
|
||||
pub fn exec_unixepoch(time_value: &Value) -> Result<String> {
|
||||
let dt = parse_naive_date_time(time_value);
|
||||
match dt {
|
||||
Some(dt) => Ok(get_unixepoch_from_naive_datetime(dt)),
|
||||
@@ -367,11 +364,11 @@ fn get_unixepoch_from_naive_datetime(value: NaiveDateTime) -> String {
|
||||
value.and_utc().timestamp().to_string()
|
||||
}
|
||||
|
||||
fn parse_naive_date_time(time_value: &OwnedValue) -> Option<NaiveDateTime> {
|
||||
fn parse_naive_date_time(time_value: &Value) -> Option<NaiveDateTime> {
|
||||
match time_value {
|
||||
OwnedValue::Text(s) => get_date_time_from_time_value_string(s.as_str()),
|
||||
OwnedValue::Integer(i) => get_date_time_from_time_value_integer(*i),
|
||||
OwnedValue::Float(f) => get_date_time_from_time_value_float(*f),
|
||||
Value::Text(s) => get_date_time_from_time_value_string(s.as_str()),
|
||||
Value::Integer(i) => get_date_time_from_time_value_integer(*i),
|
||||
Value::Float(f) => get_date_time_from_time_value_float(*f),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -646,9 +643,9 @@ fn parse_modifier(modifier: &str) -> Result<Modifier> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exec_timediff(values: &[Register]) -> OwnedValue {
|
||||
pub fn exec_timediff(values: &[Register]) -> Value {
|
||||
if values.len() < 2 {
|
||||
return OwnedValue::Null;
|
||||
return Value::Null;
|
||||
}
|
||||
|
||||
let start = parse_naive_date_time(values[0].get_owned_value());
|
||||
@@ -659,12 +656,12 @@ pub fn exec_timediff(values: &[Register]) -> OwnedValue {
|
||||
let duration = start.signed_duration_since(end);
|
||||
format_time_duration(&duration)
|
||||
}
|
||||
_ => OwnedValue::Null,
|
||||
_ => Value::Null,
|
||||
}
|
||||
}
|
||||
|
||||
/// Format the time duration as +/-YYYY-MM-DD HH:MM:SS.SSS as per SQLite's timediff() function
|
||||
fn format_time_duration(duration: &chrono::Duration) -> OwnedValue {
|
||||
fn format_time_duration(duration: &chrono::Duration) -> Value {
|
||||
let is_negative = duration.num_seconds() < 0;
|
||||
|
||||
let abs_duration = if is_negative {
|
||||
@@ -698,7 +695,7 @@ fn format_time_duration(duration: &chrono::Duration) -> OwnedValue {
|
||||
millis
|
||||
);
|
||||
|
||||
OwnedValue::build_text(&result)
|
||||
Value::build_text(&result)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -715,145 +712,109 @@ mod tests {
|
||||
|
||||
let test_cases = vec![
|
||||
// Format 1: YYYY-MM-DD (no timezone applicable)
|
||||
(OwnedValue::build_text("2024-07-21"), test_date_str),
|
||||
(Value::build_text("2024-07-21"), test_date_str),
|
||||
// Format 2: YYYY-MM-DD HH:MM
|
||||
(OwnedValue::build_text("2024-07-21 22:30"), test_date_str),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30+02:00"),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30-05:00"),
|
||||
next_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 01:30+05:00"),
|
||||
prev_date_str,
|
||||
),
|
||||
(OwnedValue::build_text("2024-07-21 22:30Z"), test_date_str),
|
||||
(Value::build_text("2024-07-21 22:30"), test_date_str),
|
||||
(Value::build_text("2024-07-21 22:30+02:00"), test_date_str),
|
||||
(Value::build_text("2024-07-21 22:30-05:00"), next_date_str),
|
||||
(Value::build_text("2024-07-21 01:30+05:00"), prev_date_str),
|
||||
(Value::build_text("2024-07-21 22:30Z"), test_date_str),
|
||||
// Format 3: YYYY-MM-DD HH:MM:SS
|
||||
(OwnedValue::build_text("2024-07-21 22:30:45"), test_date_str),
|
||||
(Value::build_text("2024-07-21 22:30:45"), test_date_str),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45+02:00"),
|
||||
Value::build_text("2024-07-21 22:30:45+02:00"),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45-05:00"),
|
||||
Value::build_text("2024-07-21 22:30:45-05:00"),
|
||||
next_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 01:30:45+05:00"),
|
||||
Value::build_text("2024-07-21 01:30:45+05:00"),
|
||||
prev_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45Z"),
|
||||
test_date_str,
|
||||
),
|
||||
(Value::build_text("2024-07-21 22:30:45Z"), test_date_str),
|
||||
// Format 4: YYYY-MM-DD HH:MM:SS.SSS
|
||||
(Value::build_text("2024-07-21 22:30:45.123"), test_date_str),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45.123"),
|
||||
Value::build_text("2024-07-21 22:30:45.123+02:00"),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45.123+02:00"),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45.123-05:00"),
|
||||
Value::build_text("2024-07-21 22:30:45.123-05:00"),
|
||||
next_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 01:30:45.123+05:00"),
|
||||
Value::build_text("2024-07-21 01:30:45.123+05:00"),
|
||||
prev_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45.123Z"),
|
||||
test_date_str,
|
||||
),
|
||||
(Value::build_text("2024-07-21 22:30:45.123Z"), test_date_str),
|
||||
// Format 5: YYYY-MM-DDTHH:MM
|
||||
(OwnedValue::build_text("2024-07-21T22:30"), test_date_str),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30+02:00"),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30-05:00"),
|
||||
next_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T01:30+05:00"),
|
||||
prev_date_str,
|
||||
),
|
||||
(OwnedValue::build_text("2024-07-21T22:30Z"), test_date_str),
|
||||
(Value::build_text("2024-07-21T22:30"), test_date_str),
|
||||
(Value::build_text("2024-07-21T22:30+02:00"), test_date_str),
|
||||
(Value::build_text("2024-07-21T22:30-05:00"), next_date_str),
|
||||
(Value::build_text("2024-07-21T01:30+05:00"), prev_date_str),
|
||||
(Value::build_text("2024-07-21T22:30Z"), test_date_str),
|
||||
// Format 6: YYYY-MM-DDTHH:MM:SS
|
||||
(OwnedValue::build_text("2024-07-21T22:30:45"), test_date_str),
|
||||
(Value::build_text("2024-07-21T22:30:45"), test_date_str),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45+02:00"),
|
||||
Value::build_text("2024-07-21T22:30:45+02:00"),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45-05:00"),
|
||||
Value::build_text("2024-07-21T22:30:45-05:00"),
|
||||
next_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T01:30:45+05:00"),
|
||||
Value::build_text("2024-07-21T01:30:45+05:00"),
|
||||
prev_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45Z"),
|
||||
test_date_str,
|
||||
),
|
||||
(Value::build_text("2024-07-21T22:30:45Z"), test_date_str),
|
||||
// Format 7: YYYY-MM-DDTHH:MM:SS.SSS
|
||||
(Value::build_text("2024-07-21T22:30:45.123"), test_date_str),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45.123"),
|
||||
Value::build_text("2024-07-21T22:30:45.123+02:00"),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45.123+02:00"),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45.123-05:00"),
|
||||
Value::build_text("2024-07-21T22:30:45.123-05:00"),
|
||||
next_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T01:30:45.123+05:00"),
|
||||
Value::build_text("2024-07-21T01:30:45.123+05:00"),
|
||||
prev_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45.123Z"),
|
||||
test_date_str,
|
||||
),
|
||||
(Value::build_text("2024-07-21T22:30:45.123Z"), test_date_str),
|
||||
// Format 8: HH:MM
|
||||
(OwnedValue::build_text("22:30"), "2000-01-01"),
|
||||
(OwnedValue::build_text("22:30+02:00"), "2000-01-01"),
|
||||
(OwnedValue::build_text("22:30-05:00"), "2000-01-02"),
|
||||
(OwnedValue::build_text("01:30+05:00"), "1999-12-31"),
|
||||
(OwnedValue::build_text("22:30Z"), "2000-01-01"),
|
||||
(Value::build_text("22:30"), "2000-01-01"),
|
||||
(Value::build_text("22:30+02:00"), "2000-01-01"),
|
||||
(Value::build_text("22:30-05:00"), "2000-01-02"),
|
||||
(Value::build_text("01:30+05:00"), "1999-12-31"),
|
||||
(Value::build_text("22:30Z"), "2000-01-01"),
|
||||
// Format 9: HH:MM:SS
|
||||
(OwnedValue::build_text("22:30:45"), "2000-01-01"),
|
||||
(OwnedValue::build_text("22:30:45+02:00"), "2000-01-01"),
|
||||
(OwnedValue::build_text("22:30:45-05:00"), "2000-01-02"),
|
||||
(OwnedValue::build_text("01:30:45+05:00"), "1999-12-31"),
|
||||
(OwnedValue::build_text("22:30:45Z"), "2000-01-01"),
|
||||
(Value::build_text("22:30:45"), "2000-01-01"),
|
||||
(Value::build_text("22:30:45+02:00"), "2000-01-01"),
|
||||
(Value::build_text("22:30:45-05:00"), "2000-01-02"),
|
||||
(Value::build_text("01:30:45+05:00"), "1999-12-31"),
|
||||
(Value::build_text("22:30:45Z"), "2000-01-01"),
|
||||
// Format 10: HH:MM:SS.SSS
|
||||
(OwnedValue::build_text("22:30:45.123"), "2000-01-01"),
|
||||
(OwnedValue::build_text("22:30:45.123+02:00"), "2000-01-01"),
|
||||
(OwnedValue::build_text("22:30:45.123-05:00"), "2000-01-02"),
|
||||
(OwnedValue::build_text("01:30:45.123+05:00"), "1999-12-31"),
|
||||
(OwnedValue::build_text("22:30:45.123Z"), "2000-01-01"),
|
||||
(Value::build_text("22:30:45.123"), "2000-01-01"),
|
||||
(Value::build_text("22:30:45.123+02:00"), "2000-01-01"),
|
||||
(Value::build_text("22:30:45.123-05:00"), "2000-01-02"),
|
||||
(Value::build_text("01:30:45.123+05:00"), "1999-12-31"),
|
||||
(Value::build_text("22:30:45.123Z"), "2000-01-01"),
|
||||
// Test Format 11: 'now'
|
||||
(OwnedValue::build_text("now"), &now),
|
||||
(Value::build_text("now"), &now),
|
||||
// Format 12: DDDDDDDDDD (Julian date as float or integer)
|
||||
(OwnedValue::Float(2460512.5), test_date_str),
|
||||
(OwnedValue::Integer(2460513), test_date_str),
|
||||
(Value::Float(2460512.5), test_date_str),
|
||||
(Value::Integer(2460513), test_date_str),
|
||||
];
|
||||
|
||||
for (input, expected) in test_cases {
|
||||
let result = exec_date(&[Register::OwnedValue(input.clone())]);
|
||||
let result = exec_date(&[Register::Value(input.clone())]);
|
||||
assert_eq!(
|
||||
result,
|
||||
OwnedValue::build_text(expected),
|
||||
Value::build_text(expected),
|
||||
"Failed for input: {:?}",
|
||||
input
|
||||
);
|
||||
@@ -863,37 +824,37 @@ mod tests {
|
||||
#[test]
|
||||
fn test_invalid_get_date_from_time_value() {
|
||||
let invalid_cases = vec![
|
||||
OwnedValue::build_text("2024-07-21 25:00"), // Invalid hour
|
||||
OwnedValue::build_text("2024-07-21 24:00:00"), // Invalid hour
|
||||
OwnedValue::build_text("2024-07-21 23:60:00"), // Invalid minute
|
||||
OwnedValue::build_text("2024-07-21 22:58:60"), // Invalid second
|
||||
OwnedValue::build_text("2024-07-32"), // Invalid day
|
||||
OwnedValue::build_text("2024-13-01"), // Invalid month
|
||||
OwnedValue::build_text("invalid_date"), // Completely invalid string
|
||||
OwnedValue::build_text(""), // Empty string
|
||||
OwnedValue::Integer(i64::MAX), // Large Julian day
|
||||
OwnedValue::Integer(-1), // Negative Julian day
|
||||
OwnedValue::Float(f64::MAX), // Large float
|
||||
OwnedValue::Float(-1.0), // Negative Julian day as float
|
||||
OwnedValue::Float(f64::NAN), // NaN
|
||||
OwnedValue::Float(f64::INFINITY), // Infinity
|
||||
OwnedValue::Null, // Null value
|
||||
OwnedValue::Blob(vec![1, 2, 3].into()), // Blob (unsupported type)
|
||||
Value::build_text("2024-07-21 25:00"), // Invalid hour
|
||||
Value::build_text("2024-07-21 24:00:00"), // Invalid hour
|
||||
Value::build_text("2024-07-21 23:60:00"), // Invalid minute
|
||||
Value::build_text("2024-07-21 22:58:60"), // Invalid second
|
||||
Value::build_text("2024-07-32"), // Invalid day
|
||||
Value::build_text("2024-13-01"), // Invalid month
|
||||
Value::build_text("invalid_date"), // Completely invalid string
|
||||
Value::build_text(""), // Empty string
|
||||
Value::Integer(i64::MAX), // Large Julian day
|
||||
Value::Integer(-1), // Negative Julian day
|
||||
Value::Float(f64::MAX), // Large float
|
||||
Value::Float(-1.0), // Negative Julian day as float
|
||||
Value::Float(f64::NAN), // NaN
|
||||
Value::Float(f64::INFINITY), // Infinity
|
||||
Value::Null, // Null value
|
||||
Value::Blob(vec![1, 2, 3].into()), // Blob (unsupported type)
|
||||
// Invalid timezone tests
|
||||
OwnedValue::build_text("2024-07-21T12:00:00+24:00"), // Invalid timezone offset (too large)
|
||||
OwnedValue::build_text("2024-07-21T12:00:00-24:00"), // Invalid timezone offset (too small)
|
||||
OwnedValue::build_text("2024-07-21T12:00:00+00:60"), // Invalid timezone minutes
|
||||
OwnedValue::build_text("2024-07-21T12:00:00+00:00:00"), // Invalid timezone format (extra seconds)
|
||||
OwnedValue::build_text("2024-07-21T12:00:00+"), // Incomplete timezone
|
||||
OwnedValue::build_text("2024-07-21T12:00:00+Z"), // Invalid timezone format
|
||||
OwnedValue::build_text("2024-07-21T12:00:00+00:00Z"), // Mixing offset and Z
|
||||
OwnedValue::build_text("2024-07-21T12:00:00UTC"), // Named timezone (not supported)
|
||||
Value::build_text("2024-07-21T12:00:00+24:00"), // Invalid timezone offset (too large)
|
||||
Value::build_text("2024-07-21T12:00:00-24:00"), // Invalid timezone offset (too small)
|
||||
Value::build_text("2024-07-21T12:00:00+00:60"), // Invalid timezone minutes
|
||||
Value::build_text("2024-07-21T12:00:00+00:00:00"), // Invalid timezone format (extra seconds)
|
||||
Value::build_text("2024-07-21T12:00:00+"), // Incomplete timezone
|
||||
Value::build_text("2024-07-21T12:00:00+Z"), // Invalid timezone format
|
||||
Value::build_text("2024-07-21T12:00:00+00:00Z"), // Mixing offset and Z
|
||||
Value::build_text("2024-07-21T12:00:00UTC"), // Named timezone (not supported)
|
||||
];
|
||||
|
||||
for case in invalid_cases.iter() {
|
||||
let result = exec_date(&[Register::OwnedValue(case.clone())]);
|
||||
let result = exec_date(&[Register::Value(case.clone())]);
|
||||
match result {
|
||||
OwnedValue::Text(ref result_str) if result_str.value.is_empty() => (),
|
||||
Value::Text(ref result_str) if result_str.value.is_empty() => (),
|
||||
_ => panic!(
|
||||
"Expected empty string for input: {:?}, but got: {:?}",
|
||||
case, result
|
||||
@@ -910,105 +871,87 @@ mod tests {
|
||||
|
||||
let test_cases = vec![
|
||||
// Format 1: YYYY-MM-DD (no timezone applicable)
|
||||
(OwnedValue::build_text("2024-07-21"), "00:00:00"),
|
||||
(Value::build_text("2024-07-21"), "00:00:00"),
|
||||
// Format 2: YYYY-MM-DD HH:MM
|
||||
(OwnedValue::build_text("2024-07-21 22:30"), "22:30:00"),
|
||||
(OwnedValue::build_text("2024-07-21 22:30+02:00"), "20:30:00"),
|
||||
(OwnedValue::build_text("2024-07-21 22:30-05:00"), "03:30:00"),
|
||||
(OwnedValue::build_text("2024-07-21 22:30Z"), "22:30:00"),
|
||||
(Value::build_text("2024-07-21 22:30"), "22:30:00"),
|
||||
(Value::build_text("2024-07-21 22:30+02:00"), "20:30:00"),
|
||||
(Value::build_text("2024-07-21 22:30-05:00"), "03:30:00"),
|
||||
(Value::build_text("2024-07-21 22:30Z"), "22:30:00"),
|
||||
// Format 3: YYYY-MM-DD HH:MM:SS
|
||||
(OwnedValue::build_text("2024-07-21 22:30:45"), test_time_str),
|
||||
(Value::build_text("2024-07-21 22:30:45"), test_time_str),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45+02:00"),
|
||||
Value::build_text("2024-07-21 22:30:45+02:00"),
|
||||
prev_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45-05:00"),
|
||||
Value::build_text("2024-07-21 22:30:45-05:00"),
|
||||
next_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45Z"),
|
||||
test_time_str,
|
||||
),
|
||||
(Value::build_text("2024-07-21 22:30:45Z"), test_time_str),
|
||||
// Format 4: YYYY-MM-DD HH:MM:SS.SSS
|
||||
(Value::build_text("2024-07-21 22:30:45.123"), test_time_str),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45.123"),
|
||||
test_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45.123+02:00"),
|
||||
Value::build_text("2024-07-21 22:30:45.123+02:00"),
|
||||
prev_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45.123-05:00"),
|
||||
Value::build_text("2024-07-21 22:30:45.123-05:00"),
|
||||
next_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21 22:30:45.123Z"),
|
||||
test_time_str,
|
||||
),
|
||||
(Value::build_text("2024-07-21 22:30:45.123Z"), test_time_str),
|
||||
// Format 5: YYYY-MM-DDTHH:MM
|
||||
(OwnedValue::build_text("2024-07-21T22:30"), "22:30:00"),
|
||||
(OwnedValue::build_text("2024-07-21T22:30+02:00"), "20:30:00"),
|
||||
(OwnedValue::build_text("2024-07-21T22:30-05:00"), "03:30:00"),
|
||||
(OwnedValue::build_text("2024-07-21T22:30Z"), "22:30:00"),
|
||||
(Value::build_text("2024-07-21T22:30"), "22:30:00"),
|
||||
(Value::build_text("2024-07-21T22:30+02:00"), "20:30:00"),
|
||||
(Value::build_text("2024-07-21T22:30-05:00"), "03:30:00"),
|
||||
(Value::build_text("2024-07-21T22:30Z"), "22:30:00"),
|
||||
// Format 6: YYYY-MM-DDTHH:MM:SS
|
||||
(OwnedValue::build_text("2024-07-21T22:30:45"), test_time_str),
|
||||
(Value::build_text("2024-07-21T22:30:45"), test_time_str),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45+02:00"),
|
||||
Value::build_text("2024-07-21T22:30:45+02:00"),
|
||||
prev_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45-05:00"),
|
||||
Value::build_text("2024-07-21T22:30:45-05:00"),
|
||||
next_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45Z"),
|
||||
test_time_str,
|
||||
),
|
||||
(Value::build_text("2024-07-21T22:30:45Z"), test_time_str),
|
||||
// Format 7: YYYY-MM-DDTHH:MM:SS.SSS
|
||||
(Value::build_text("2024-07-21T22:30:45.123"), test_time_str),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45.123"),
|
||||
test_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45.123+02:00"),
|
||||
Value::build_text("2024-07-21T22:30:45.123+02:00"),
|
||||
prev_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45.123-05:00"),
|
||||
Value::build_text("2024-07-21T22:30:45.123-05:00"),
|
||||
next_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text("2024-07-21T22:30:45.123Z"),
|
||||
test_time_str,
|
||||
),
|
||||
(Value::build_text("2024-07-21T22:30:45.123Z"), test_time_str),
|
||||
// Format 8: HH:MM
|
||||
(OwnedValue::build_text("22:30"), "22:30:00"),
|
||||
(OwnedValue::build_text("22:30+02:00"), "20:30:00"),
|
||||
(OwnedValue::build_text("22:30-05:00"), "03:30:00"),
|
||||
(OwnedValue::build_text("22:30Z"), "22:30:00"),
|
||||
(Value::build_text("22:30"), "22:30:00"),
|
||||
(Value::build_text("22:30+02:00"), "20:30:00"),
|
||||
(Value::build_text("22:30-05:00"), "03:30:00"),
|
||||
(Value::build_text("22:30Z"), "22:30:00"),
|
||||
// Format 9: HH:MM:SS
|
||||
(OwnedValue::build_text("22:30:45"), test_time_str),
|
||||
(OwnedValue::build_text("22:30:45+02:00"), prev_time_str),
|
||||
(OwnedValue::build_text("22:30:45-05:00"), next_time_str),
|
||||
(OwnedValue::build_text("22:30:45Z"), test_time_str),
|
||||
(Value::build_text("22:30:45"), test_time_str),
|
||||
(Value::build_text("22:30:45+02:00"), prev_time_str),
|
||||
(Value::build_text("22:30:45-05:00"), next_time_str),
|
||||
(Value::build_text("22:30:45Z"), test_time_str),
|
||||
// Format 10: HH:MM:SS.SSS
|
||||
(OwnedValue::build_text("22:30:45.123"), test_time_str),
|
||||
(OwnedValue::build_text("22:30:45.123+02:00"), prev_time_str),
|
||||
(OwnedValue::build_text("22:30:45.123-05:00"), next_time_str),
|
||||
(OwnedValue::build_text("22:30:45.123Z"), test_time_str),
|
||||
(Value::build_text("22:30:45.123"), test_time_str),
|
||||
(Value::build_text("22:30:45.123+02:00"), prev_time_str),
|
||||
(Value::build_text("22:30:45.123-05:00"), next_time_str),
|
||||
(Value::build_text("22:30:45.123Z"), test_time_str),
|
||||
// Format 12: DDDDDDDDDD (Julian date as float or integer)
|
||||
(OwnedValue::Float(2460082.1), "14:24:00"),
|
||||
(OwnedValue::Integer(2460082), "12:00:00"),
|
||||
(Value::Float(2460082.1), "14:24:00"),
|
||||
(Value::Integer(2460082), "12:00:00"),
|
||||
];
|
||||
|
||||
for (input, expected) in test_cases {
|
||||
let result = exec_time(&[Register::OwnedValue(input)]);
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
let result = exec_time(&[Register::Value(input)]);
|
||||
if let Value::Text(result_str) = result {
|
||||
assert_eq!(result_str.as_str(), expected);
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text, but got: {:?}", result);
|
||||
panic!("Expected Value::Text, but got: {:?}", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1016,37 +959,37 @@ mod tests {
|
||||
#[test]
|
||||
fn test_invalid_get_time_from_datetime_value() {
|
||||
let invalid_cases = vec![
|
||||
OwnedValue::build_text("2024-07-21 25:00"), // Invalid hour
|
||||
OwnedValue::build_text("2024-07-21 24:00:00"), // Invalid hour
|
||||
OwnedValue::build_text("2024-07-21 23:60:00"), // Invalid minute
|
||||
OwnedValue::build_text("2024-07-21 22:58:60"), // Invalid second
|
||||
OwnedValue::build_text("2024-07-32"), // Invalid day
|
||||
OwnedValue::build_text("2024-13-01"), // Invalid month
|
||||
OwnedValue::build_text("invalid_date"), // Completely invalid string
|
||||
OwnedValue::build_text(""), // Empty string
|
||||
OwnedValue::Integer(i64::MAX), // Large Julian day
|
||||
OwnedValue::Integer(-1), // Negative Julian day
|
||||
OwnedValue::Float(f64::MAX), // Large float
|
||||
OwnedValue::Float(-1.0), // Negative Julian day as float
|
||||
OwnedValue::Float(f64::NAN), // NaN
|
||||
OwnedValue::Float(f64::INFINITY), // Infinity
|
||||
OwnedValue::Null, // Null value
|
||||
OwnedValue::Blob(vec![1, 2, 3].into()), // Blob (unsupported type)
|
||||
Value::build_text("2024-07-21 25:00"), // Invalid hour
|
||||
Value::build_text("2024-07-21 24:00:00"), // Invalid hour
|
||||
Value::build_text("2024-07-21 23:60:00"), // Invalid minute
|
||||
Value::build_text("2024-07-21 22:58:60"), // Invalid second
|
||||
Value::build_text("2024-07-32"), // Invalid day
|
||||
Value::build_text("2024-13-01"), // Invalid month
|
||||
Value::build_text("invalid_date"), // Completely invalid string
|
||||
Value::build_text(""), // Empty string
|
||||
Value::Integer(i64::MAX), // Large Julian day
|
||||
Value::Integer(-1), // Negative Julian day
|
||||
Value::Float(f64::MAX), // Large float
|
||||
Value::Float(-1.0), // Negative Julian day as float
|
||||
Value::Float(f64::NAN), // NaN
|
||||
Value::Float(f64::INFINITY), // Infinity
|
||||
Value::Null, // Null value
|
||||
Value::Blob(vec![1, 2, 3].into()), // Blob (unsupported type)
|
||||
// Invalid timezone tests
|
||||
OwnedValue::build_text("2024-07-21T12:00:00+24:00"), // Invalid timezone offset (too large)
|
||||
OwnedValue::build_text("2024-07-21T12:00:00-24:00"), // Invalid timezone offset (too small)
|
||||
OwnedValue::build_text("2024-07-21T12:00:00+00:60"), // Invalid timezone minutes
|
||||
OwnedValue::build_text("2024-07-21T12:00:00+00:00:00"), // Invalid timezone format (extra seconds)
|
||||
OwnedValue::build_text("2024-07-21T12:00:00+"), // Incomplete timezone
|
||||
OwnedValue::build_text("2024-07-21T12:00:00+Z"), // Invalid timezone format
|
||||
OwnedValue::build_text("2024-07-21T12:00:00+00:00Z"), // Mixing offset and Z
|
||||
OwnedValue::build_text("2024-07-21T12:00:00UTC"), // Named timezone (not supported)
|
||||
Value::build_text("2024-07-21T12:00:00+24:00"), // Invalid timezone offset (too large)
|
||||
Value::build_text("2024-07-21T12:00:00-24:00"), // Invalid timezone offset (too small)
|
||||
Value::build_text("2024-07-21T12:00:00+00:60"), // Invalid timezone minutes
|
||||
Value::build_text("2024-07-21T12:00:00+00:00:00"), // Invalid timezone format (extra seconds)
|
||||
Value::build_text("2024-07-21T12:00:00+"), // Incomplete timezone
|
||||
Value::build_text("2024-07-21T12:00:00+Z"), // Invalid timezone format
|
||||
Value::build_text("2024-07-21T12:00:00+00:00Z"), // Mixing offset and Z
|
||||
Value::build_text("2024-07-21T12:00:00UTC"), // Named timezone (not supported)
|
||||
];
|
||||
|
||||
for case in invalid_cases {
|
||||
let result = exec_time(&[Register::OwnedValue(case.clone())]);
|
||||
let result = exec_time(&[Register::Value(case.clone())]);
|
||||
match result {
|
||||
OwnedValue::Text(ref result_str) if result_str.value.is_empty() => (),
|
||||
Value::Text(ref result_str) if result_str.value.is_empty() => (),
|
||||
_ => panic!(
|
||||
"Expected empty string for input: {:?}, but got: {:?}",
|
||||
case, result
|
||||
@@ -1347,7 +1290,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn text(value: &str) -> Register {
|
||||
Register::OwnedValue(OwnedValue::build_text(value))
|
||||
Register::Value(Value::build_text(value))
|
||||
}
|
||||
|
||||
fn format(dt: NaiveDateTime) -> String {
|
||||
@@ -1690,64 +1633,64 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_exec_timediff() {
|
||||
let start = OwnedValue::build_text("12:00:00");
|
||||
let end = OwnedValue::build_text("14:30:45");
|
||||
let expected = OwnedValue::build_text("-0000-00-00 02:30:45.000");
|
||||
let start = Value::build_text("12:00:00");
|
||||
let end = Value::build_text("14:30:45");
|
||||
let expected = Value::build_text("-0000-00-00 02:30:45.000");
|
||||
assert_eq!(
|
||||
exec_timediff(&[Register::OwnedValue(start), Register::OwnedValue(end)]),
|
||||
exec_timediff(&[Register::Value(start), Register::Value(end)]),
|
||||
expected
|
||||
);
|
||||
|
||||
let start = OwnedValue::build_text("14:30:45");
|
||||
let end = OwnedValue::build_text("12:00:00");
|
||||
let expected = OwnedValue::build_text("+0000-00-00 02:30:45.000");
|
||||
let start = Value::build_text("14:30:45");
|
||||
let end = Value::build_text("12:00:00");
|
||||
let expected = Value::build_text("+0000-00-00 02:30:45.000");
|
||||
assert_eq!(
|
||||
exec_timediff(&[Register::OwnedValue(start), Register::OwnedValue(end)]),
|
||||
exec_timediff(&[Register::Value(start), Register::Value(end)]),
|
||||
expected
|
||||
);
|
||||
|
||||
let start = OwnedValue::build_text("12:00:01.300");
|
||||
let end = OwnedValue::build_text("12:00:00.500");
|
||||
let expected = OwnedValue::build_text("+0000-00-00 00:00:00.800");
|
||||
let start = Value::build_text("12:00:01.300");
|
||||
let end = Value::build_text("12:00:00.500");
|
||||
let expected = Value::build_text("+0000-00-00 00:00:00.800");
|
||||
assert_eq!(
|
||||
exec_timediff(&[Register::OwnedValue(start), Register::OwnedValue(end)]),
|
||||
exec_timediff(&[Register::Value(start), Register::Value(end)]),
|
||||
expected
|
||||
);
|
||||
|
||||
let start = OwnedValue::build_text("13:30:00");
|
||||
let end = OwnedValue::build_text("16:45:30");
|
||||
let expected = OwnedValue::build_text("-0000-00-00 03:15:30.000");
|
||||
let start = Value::build_text("13:30:00");
|
||||
let end = Value::build_text("16:45:30");
|
||||
let expected = Value::build_text("-0000-00-00 03:15:30.000");
|
||||
assert_eq!(
|
||||
exec_timediff(&[Register::OwnedValue(start), Register::OwnedValue(end)]),
|
||||
exec_timediff(&[Register::Value(start), Register::Value(end)]),
|
||||
expected
|
||||
);
|
||||
|
||||
let start = OwnedValue::build_text("2023-05-10 23:30:00");
|
||||
let end = OwnedValue::build_text("2023-05-11 01:15:00");
|
||||
let expected = OwnedValue::build_text("-0000-00-00 01:45:00.000");
|
||||
let start = Value::build_text("2023-05-10 23:30:00");
|
||||
let end = Value::build_text("2023-05-11 01:15:00");
|
||||
let expected = Value::build_text("-0000-00-00 01:45:00.000");
|
||||
assert_eq!(
|
||||
exec_timediff(&[Register::OwnedValue(start), Register::OwnedValue(end)]),
|
||||
exec_timediff(&[Register::Value(start), Register::Value(end)]),
|
||||
expected
|
||||
);
|
||||
|
||||
let start = OwnedValue::Null;
|
||||
let end = OwnedValue::build_text("12:00:00");
|
||||
let expected = OwnedValue::Null;
|
||||
let start = Value::Null;
|
||||
let end = Value::build_text("12:00:00");
|
||||
let expected = Value::Null;
|
||||
assert_eq!(
|
||||
exec_timediff(&[Register::OwnedValue(start), Register::OwnedValue(end)]),
|
||||
exec_timediff(&[Register::Value(start), Register::Value(end)]),
|
||||
expected
|
||||
);
|
||||
|
||||
let start = OwnedValue::build_text("not a time");
|
||||
let end = OwnedValue::build_text("12:00:00");
|
||||
let expected = OwnedValue::Null;
|
||||
let start = Value::build_text("not a time");
|
||||
let end = Value::build_text("12:00:00");
|
||||
let expected = Value::Null;
|
||||
assert_eq!(
|
||||
exec_timediff(&[Register::OwnedValue(start), Register::OwnedValue(end)]),
|
||||
exec_timediff(&[Register::Value(start), Register::Value(end)]),
|
||||
expected
|
||||
);
|
||||
|
||||
let start = OwnedValue::build_text("12:00:00");
|
||||
let expected = OwnedValue::Null;
|
||||
assert_eq!(exec_timediff(&[Register::OwnedValue(start)]), expected);
|
||||
let start = Value::build_text("12:00:00");
|
||||
let expected = Value::Null;
|
||||
assert_eq!(exec_timediff(&[Register::Value(start)]), expected);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
use crate::types::OwnedValue;
|
||||
use crate::types::Value;
|
||||
use crate::vdbe::Register;
|
||||
use crate::LimboError;
|
||||
|
||||
// TODO: Support %!.3s %i, %x, %X, %o, %e, %E, %c. flags: - + 0 ! ,
|
||||
#[inline(always)]
|
||||
pub fn exec_printf(values: &[Register]) -> crate::Result<OwnedValue> {
|
||||
pub fn exec_printf(values: &[Register]) -> crate::Result<Value> {
|
||||
if values.is_empty() {
|
||||
return Ok(OwnedValue::Null);
|
||||
return Ok(Value::Null);
|
||||
}
|
||||
let format_str = match &values[0].get_owned_value() {
|
||||
OwnedValue::Text(t) => t.as_str(),
|
||||
_ => return Ok(OwnedValue::Null),
|
||||
Value::Text(t) => t.as_str(),
|
||||
_ => return Ok(Value::Null),
|
||||
};
|
||||
|
||||
let mut result = String::new();
|
||||
@@ -34,8 +34,8 @@ pub fn exec_printf(values: &[Register]) -> crate::Result<OwnedValue> {
|
||||
}
|
||||
let value = &values[args_index].get_owned_value();
|
||||
match value {
|
||||
OwnedValue::Integer(_) => result.push_str(&format!("{}", value)),
|
||||
OwnedValue::Float(_) => result.push_str(&format!("{}", value)),
|
||||
Value::Integer(_) => result.push_str(&format!("{}", value)),
|
||||
Value::Float(_) => result.push_str(&format!("{}", value)),
|
||||
_ => result.push_str("0".into()),
|
||||
}
|
||||
args_index += 1;
|
||||
@@ -45,8 +45,8 @@ pub fn exec_printf(values: &[Register]) -> crate::Result<OwnedValue> {
|
||||
return Err(LimboError::InvalidArgument("not enough arguments".into()));
|
||||
}
|
||||
match &values[args_index].get_owned_value() {
|
||||
OwnedValue::Text(t) => result.push_str(t.as_str()),
|
||||
OwnedValue::Null => result.push_str("(null)"),
|
||||
Value::Text(t) => result.push_str(t.as_str()),
|
||||
Value::Null => result.push_str("(null)"),
|
||||
v => result.push_str(&format!("{}", v)),
|
||||
}
|
||||
args_index += 1;
|
||||
@@ -57,8 +57,8 @@ pub fn exec_printf(values: &[Register]) -> crate::Result<OwnedValue> {
|
||||
}
|
||||
let value = &values[args_index].get_owned_value();
|
||||
match value {
|
||||
OwnedValue::Float(f) => result.push_str(&format!("{:.6}", f)),
|
||||
OwnedValue::Integer(i) => result.push_str(&format!("{:.6}", *i as f64)),
|
||||
Value::Float(f) => result.push_str(&format!("{:.6}", f)),
|
||||
Value::Integer(i) => result.push_str(&format!("{:.6}", *i as f64)),
|
||||
_ => result.push_str("0.0".into()),
|
||||
}
|
||||
args_index += 1;
|
||||
@@ -75,7 +75,7 @@ pub fn exec_printf(values: &[Register]) -> crate::Result<OwnedValue> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(OwnedValue::build_text(&result))
|
||||
Ok(Value::build_text(&result))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -83,20 +83,20 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
fn text(value: &str) -> Register {
|
||||
Register::OwnedValue(OwnedValue::build_text(value))
|
||||
Register::Value(Value::build_text(value))
|
||||
}
|
||||
|
||||
fn integer(value: i64) -> Register {
|
||||
Register::OwnedValue(OwnedValue::Integer(value))
|
||||
Register::Value(Value::Integer(value))
|
||||
}
|
||||
|
||||
fn float(value: f64) -> Register {
|
||||
Register::OwnedValue(OwnedValue::Float(value))
|
||||
Register::Value(Value::Float(value))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_printf_no_args() {
|
||||
assert_eq!(exec_printf(&[]).unwrap(), OwnedValue::Null);
|
||||
assert_eq!(exec_printf(&[]).unwrap(), Value::Null);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -122,7 +122,7 @@ mod tests {
|
||||
),
|
||||
// String with null value
|
||||
(
|
||||
vec![text("Hello, %s!"), Register::OwnedValue(OwnedValue::Null)],
|
||||
vec![text("Hello, %s!"), Register::Value(Value::Null)],
|
||||
text("Hello, (null)!"),
|
||||
),
|
||||
// String with number conversion
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::cell::{Cell, UnsafeCell};
|
||||
|
||||
use crate::OwnedValue;
|
||||
use crate::Value;
|
||||
|
||||
use super::jsonb::Jsonb;
|
||||
|
||||
@@ -8,7 +8,7 @@ const JSON_CACHE_SIZE: usize = 4;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct JsonCache {
|
||||
entries: [Option<(OwnedValue, Jsonb)>; JSON_CACHE_SIZE],
|
||||
entries: [Option<(Value, Jsonb)>; JSON_CACHE_SIZE],
|
||||
age: [usize; JSON_CACHE_SIZE],
|
||||
used: usize,
|
||||
counter: usize,
|
||||
@@ -38,7 +38,7 @@ impl JsonCache {
|
||||
oldest_idx
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, key: &OwnedValue, value: &Jsonb) {
|
||||
pub fn insert(&mut self, key: &Value, value: &Jsonb) {
|
||||
if self.used < JSON_CACHE_SIZE {
|
||||
self.entries[self.used] = Some((key.clone(), value.clone()));
|
||||
self.age[self.used] = self.counter;
|
||||
@@ -53,7 +53,7 @@ impl JsonCache {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lookup(&mut self, key: &OwnedValue) -> Option<Jsonb> {
|
||||
pub fn lookup(&mut self, key: &Value) -> Option<Jsonb> {
|
||||
for i in (0..self.used).rev() {
|
||||
if let Some((stored_key, value)) = &self.entries[i] {
|
||||
if key == stored_key {
|
||||
@@ -89,7 +89,7 @@ impl JsonCacheCell {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn lookup(&self, key: &OwnedValue) -> Option<Jsonb> {
|
||||
pub fn lookup(&self, key: &Value) -> Option<Jsonb> {
|
||||
assert_eq!(self.accessed.get(), false);
|
||||
|
||||
self.accessed.set(true);
|
||||
@@ -113,8 +113,8 @@ impl JsonCacheCell {
|
||||
|
||||
pub fn get_or_insert_with(
|
||||
&self,
|
||||
key: &OwnedValue,
|
||||
value: impl Fn(&OwnedValue) -> crate::Result<Jsonb>,
|
||||
key: &Value,
|
||||
value: impl Fn(&Value) -> crate::Result<Jsonb>,
|
||||
) -> crate::Result<Jsonb> {
|
||||
assert_eq!(self.accessed.get(), false);
|
||||
|
||||
@@ -171,10 +171,10 @@ mod tests {
|
||||
use super::*;
|
||||
use std::str::FromStr;
|
||||
|
||||
// Helper function to create test OwnedValue and Jsonb from JSON string
|
||||
fn create_test_pair(json_str: &str) -> (OwnedValue, Jsonb) {
|
||||
// Create OwnedValue as text representation of JSON
|
||||
let key = OwnedValue::build_text(json_str);
|
||||
// Helper function to create test Value and Jsonb from JSON string
|
||||
fn create_test_pair(json_str: &str) -> (Value, Jsonb) {
|
||||
// Create Value as text representation of JSON
|
||||
let key = Value::build_text(json_str);
|
||||
|
||||
// Create Jsonb from the same JSON string
|
||||
let value = Jsonb::from_str(json_str).unwrap();
|
||||
|
||||
601
core/json/mod.rs
601
core/json/mod.rs
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
use crate::{types::OwnedValue, vdbe::Register};
|
||||
use crate::{types::Value, vdbe::Register};
|
||||
|
||||
use super::{
|
||||
convert_dbtype_to_jsonb, curry_convert_dbtype_to_jsonb, json_path_from_owned_value,
|
||||
@@ -12,13 +12,9 @@ use super::{
|
||||
/// * If the patch contains a scalar value, the target is replaced with that value
|
||||
/// * If both target and patch are objects, the patch is recursively applied
|
||||
/// * null values in the patch result in property removal from the target
|
||||
pub fn json_patch(
|
||||
target: &OwnedValue,
|
||||
patch: &OwnedValue,
|
||||
cache: &JsonCacheCell,
|
||||
) -> crate::Result<OwnedValue> {
|
||||
pub fn json_patch(target: &Value, patch: &Value, cache: &JsonCacheCell) -> crate::Result<Value> {
|
||||
match (target, patch) {
|
||||
(OwnedValue::Blob(_), _) | (_, OwnedValue::Blob(_)) => {
|
||||
(Value::Blob(_), _) | (_, Value::Blob(_)) => {
|
||||
crate::bail_constraint_error!("blob is not supported!");
|
||||
}
|
||||
_ => (),
|
||||
@@ -34,13 +30,9 @@ pub fn json_patch(
|
||||
json_string_to_db_type(target, element_type, OutputVariant::ElementType)
|
||||
}
|
||||
|
||||
pub fn jsonb_patch(
|
||||
target: &OwnedValue,
|
||||
patch: &OwnedValue,
|
||||
cache: &JsonCacheCell,
|
||||
) -> crate::Result<OwnedValue> {
|
||||
pub fn jsonb_patch(target: &Value, patch: &Value, cache: &JsonCacheCell) -> crate::Result<Value> {
|
||||
match (target, patch) {
|
||||
(OwnedValue::Blob(_), _) | (_, OwnedValue::Blob(_)) => {
|
||||
(Value::Blob(_), _) | (_, Value::Blob(_)) => {
|
||||
crate::bail_constraint_error!("blob is not supported!");
|
||||
}
|
||||
_ => (),
|
||||
@@ -56,9 +48,9 @@ pub fn jsonb_patch(
|
||||
json_string_to_db_type(target, element_type, OutputVariant::Binary)
|
||||
}
|
||||
|
||||
pub fn json_remove(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> {
|
||||
pub fn json_remove(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<Value> {
|
||||
if args.is_empty() {
|
||||
return Ok(OwnedValue::Null);
|
||||
return Ok(Value::Null);
|
||||
}
|
||||
|
||||
let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict);
|
||||
@@ -75,9 +67,9 @@ pub fn json_remove(args: &[Register], json_cache: &JsonCacheCell) -> crate::Resu
|
||||
json_string_to_db_type(json, el_type, OutputVariant::String)
|
||||
}
|
||||
|
||||
pub fn jsonb_remove(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> {
|
||||
pub fn jsonb_remove(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<Value> {
|
||||
if args.is_empty() {
|
||||
return Ok(OwnedValue::Null);
|
||||
return Ok(Value::Null);
|
||||
}
|
||||
|
||||
let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict);
|
||||
@@ -89,12 +81,12 @@ pub fn jsonb_remove(args: &[Register], json_cache: &JsonCacheCell) -> crate::Res
|
||||
}
|
||||
}
|
||||
|
||||
Ok(OwnedValue::Blob(json.data()))
|
||||
Ok(Value::Blob(json.data()))
|
||||
}
|
||||
|
||||
pub fn json_replace(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> {
|
||||
pub fn json_replace(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<Value> {
|
||||
if args.is_empty() {
|
||||
return Ok(OwnedValue::Null);
|
||||
return Ok(Value::Null);
|
||||
}
|
||||
|
||||
let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict);
|
||||
@@ -116,9 +108,9 @@ pub fn json_replace(args: &[Register], json_cache: &JsonCacheCell) -> crate::Res
|
||||
json_string_to_db_type(json, el_type, super::OutputVariant::String)
|
||||
}
|
||||
|
||||
pub fn jsonb_replace(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> {
|
||||
pub fn jsonb_replace(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<Value> {
|
||||
if args.is_empty() {
|
||||
return Ok(OwnedValue::Null);
|
||||
return Ok(Value::Null);
|
||||
}
|
||||
|
||||
let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict);
|
||||
@@ -139,9 +131,9 @@ pub fn jsonb_replace(args: &[Register], json_cache: &JsonCacheCell) -> crate::Re
|
||||
json_string_to_db_type(json, el_type, OutputVariant::Binary)
|
||||
}
|
||||
|
||||
pub fn json_insert(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> {
|
||||
pub fn json_insert(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<Value> {
|
||||
if args.is_empty() {
|
||||
return Ok(OwnedValue::Null);
|
||||
return Ok(Value::Null);
|
||||
}
|
||||
|
||||
let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict);
|
||||
@@ -162,9 +154,9 @@ pub fn json_insert(args: &[Register], json_cache: &JsonCacheCell) -> crate::Resu
|
||||
json_string_to_db_type(json, el_type, OutputVariant::String)
|
||||
}
|
||||
|
||||
pub fn jsonb_insert(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<OwnedValue> {
|
||||
pub fn jsonb_insert(args: &[Register], json_cache: &JsonCacheCell) -> crate::Result<Value> {
|
||||
if args.is_empty() {
|
||||
return Ok(OwnedValue::Null);
|
||||
return Ok(Value::Null);
|
||||
}
|
||||
|
||||
let make_jsonb_fn = curry_convert_dbtype_to_jsonb(Conv::Strict);
|
||||
@@ -191,12 +183,12 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
fn create_text(s: &str) -> OwnedValue {
|
||||
OwnedValue::Text(Text::from_str(s))
|
||||
fn create_text(s: &str) -> Value {
|
||||
Value::Text(Text::from_str(s))
|
||||
}
|
||||
|
||||
fn create_json(s: &str) -> OwnedValue {
|
||||
OwnedValue::Text(Text::json(s.to_string()))
|
||||
fn create_json(s: &str) -> Value {
|
||||
Value::Text(Text::json(s.to_string()))
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -237,7 +229,7 @@ mod tests {
|
||||
#[test]
|
||||
#[should_panic(expected = "blob is not supported!")]
|
||||
fn test_blob_not_supported() {
|
||||
let target = OwnedValue::Blob(vec![1, 2, 3]);
|
||||
let target = Value::Blob(vec![1, 2, 3]);
|
||||
let patch = create_text("{}");
|
||||
let cache = JsonCacheCell::new();
|
||||
|
||||
@@ -292,20 +284,20 @@ mod tests {
|
||||
fn test_json_remove_empty_args() {
|
||||
let args = vec![];
|
||||
let json_cache = JsonCacheCell::new();
|
||||
assert_eq!(json_remove(&args, &json_cache).unwrap(), OwnedValue::Null);
|
||||
assert_eq!(json_remove(&args, &json_cache).unwrap(), Value::Null);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_json_remove_array_element() {
|
||||
let args = vec![
|
||||
Register::OwnedValue(create_json(r#"[1,2,3,4,5]"#)),
|
||||
Register::OwnedValue(create_text("$[2]")),
|
||||
Register::Value(create_json(r#"[1,2,3,4,5]"#)),
|
||||
Register::Value(create_text("$[2]")),
|
||||
];
|
||||
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_remove(&args, &json_cache).unwrap();
|
||||
match result {
|
||||
OwnedValue::Text(t) => assert_eq!(t.as_str(), "[1,2,4,5]"),
|
||||
Value::Text(t) => assert_eq!(t.as_str(), "[1,2,4,5]"),
|
||||
_ => panic!("Expected Text value"),
|
||||
}
|
||||
}
|
||||
@@ -313,15 +305,15 @@ mod tests {
|
||||
#[test]
|
||||
fn test_json_remove_multiple_paths() {
|
||||
let args = vec![
|
||||
Register::OwnedValue(create_json(r#"{"a": 1, "b": 2, "c": 3}"#)),
|
||||
Register::OwnedValue(create_text("$.a")),
|
||||
Register::OwnedValue(create_text("$.c")),
|
||||
Register::Value(create_json(r#"{"a": 1, "b": 2, "c": 3}"#)),
|
||||
Register::Value(create_text("$.a")),
|
||||
Register::Value(create_text("$.c")),
|
||||
];
|
||||
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_remove(&args, &json_cache).unwrap();
|
||||
match result {
|
||||
OwnedValue::Text(t) => assert_eq!(t.as_str(), r#"{"b":2}"#),
|
||||
Value::Text(t) => assert_eq!(t.as_str(), r#"{"b":2}"#),
|
||||
_ => panic!("Expected Text value"),
|
||||
}
|
||||
}
|
||||
@@ -329,14 +321,14 @@ mod tests {
|
||||
#[test]
|
||||
fn test_json_remove_nested_paths() {
|
||||
let args = vec![
|
||||
Register::OwnedValue(create_json(r#"{"a": {"b": {"c": 1, "d": 2}}}"#)),
|
||||
Register::OwnedValue(create_text("$.a.b.c")),
|
||||
Register::Value(create_json(r#"{"a": {"b": {"c": 1, "d": 2}}}"#)),
|
||||
Register::Value(create_text("$.a.b.c")),
|
||||
];
|
||||
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_remove(&args, &json_cache).unwrap();
|
||||
match result {
|
||||
OwnedValue::Text(t) => assert_eq!(t.as_str(), r#"{"a":{"b":{"d":2}}}"#),
|
||||
Value::Text(t) => assert_eq!(t.as_str(), r#"{"a":{"b":{"d":2}}}"#),
|
||||
_ => panic!("Expected Text value"),
|
||||
}
|
||||
}
|
||||
@@ -344,14 +336,14 @@ mod tests {
|
||||
#[test]
|
||||
fn test_json_remove_duplicate_keys() {
|
||||
let args = vec![
|
||||
Register::OwnedValue(create_json(r#"{"a": 1, "a": 2, "a": 3}"#)),
|
||||
Register::OwnedValue(create_text("$.a")),
|
||||
Register::Value(create_json(r#"{"a": 1, "a": 2, "a": 3}"#)),
|
||||
Register::Value(create_text("$.a")),
|
||||
];
|
||||
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_remove(&args, &json_cache).unwrap();
|
||||
match result {
|
||||
OwnedValue::Text(t) => assert_eq!(t.as_str(), r#"{"a":2,"a":3}"#),
|
||||
Value::Text(t) => assert_eq!(t.as_str(), r#"{"a":2,"a":3}"#),
|
||||
_ => panic!("Expected Text value"),
|
||||
}
|
||||
}
|
||||
@@ -359,8 +351,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_json_remove_invalid_path() {
|
||||
let args = vec![
|
||||
Register::OwnedValue(create_json(r#"{"a": 1}"#)),
|
||||
Register::OwnedValue(OwnedValue::Integer(42)), // Invalid path type
|
||||
Register::Value(create_json(r#"{"a": 1}"#)),
|
||||
Register::Value(Value::Integer(42)), // Invalid path type
|
||||
];
|
||||
|
||||
let json_cache = JsonCacheCell::new();
|
||||
@@ -370,18 +362,18 @@ mod tests {
|
||||
#[test]
|
||||
fn test_json_remove_complex_case() {
|
||||
let args = vec![
|
||||
Register::OwnedValue(create_json(
|
||||
Register::Value(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")),
|
||||
Register::Value(create_text("$.a[1]")),
|
||||
Register::Value(create_text("$.b.x")),
|
||||
Register::Value(create_text("$.c[0].y")),
|
||||
];
|
||||
|
||||
let json_cache = JsonCacheCell::new();
|
||||
let result = json_remove(&args, &json_cache).unwrap();
|
||||
match result {
|
||||
OwnedValue::Text(t) => {
|
||||
Value::Text(t) => {
|
||||
let value = t.as_str();
|
||||
assert!(value.contains(r#"[1,3]"#));
|
||||
assert!(value.contains(r#"{"x":2}"#));
|
||||
|
||||
10
core/lib.rs
10
core/lib.rs
@@ -71,8 +71,8 @@ use storage::{
|
||||
sqlite3_ondisk::{DatabaseHeader, DATABASE_HEADER_SIZE},
|
||||
};
|
||||
use translate::select::prepare_select_plan;
|
||||
pub use types::OwnedValue;
|
||||
pub use types::RefValue;
|
||||
pub use types::Value;
|
||||
use util::{columns_from_create_table_body, parse_schema_rows};
|
||||
use vdbe::{builder::QueryMode, VTabOpaqueCursor};
|
||||
pub type Result<T, E = LimboError> = std::result::Result<T, E>;
|
||||
@@ -638,7 +638,7 @@ impl Statement {
|
||||
self.program.parameters.count()
|
||||
}
|
||||
|
||||
pub fn bind_at(&mut self, index: NonZero<usize>, value: OwnedValue) {
|
||||
pub fn bind_at(&mut self, index: NonZero<usize>, value: Value) {
|
||||
self.state.bind_at(index, value);
|
||||
}
|
||||
|
||||
@@ -771,9 +771,9 @@ impl VirtualTable {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn column(&self, cursor: &VTabOpaqueCursor, column: usize) -> Result<OwnedValue> {
|
||||
pub fn column(&self, cursor: &VTabOpaqueCursor, column: usize) -> Result<Value> {
|
||||
let val = unsafe { (self.implementation.column)(cursor.as_ptr(), column as u32) };
|
||||
OwnedValue::from_ffi(val)
|
||||
Value::from_ffi(val)
|
||||
}
|
||||
|
||||
pub fn next(&self, cursor: &VTabOpaqueCursor) -> Result<bool> {
|
||||
@@ -785,7 +785,7 @@ impl VirtualTable {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&self, args: &[OwnedValue]) -> Result<Option<i64>> {
|
||||
pub fn update(&self, args: &[Value]) -> Result<Option<i64>> {
|
||||
let arg_count = args.len();
|
||||
let ext_args = args.iter().map(|arg| arg.to_ffi()).collect::<Vec<_>>();
|
||||
let newrowid = 0i64;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::OwnedValue;
|
||||
use crate::Value;
|
||||
|
||||
mod nonnan;
|
||||
|
||||
@@ -66,12 +66,12 @@ impl From<Numeric> for NullableInteger {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Numeric> for OwnedValue {
|
||||
impl From<Numeric> for Value {
|
||||
fn from(value: Numeric) -> Self {
|
||||
match value {
|
||||
Numeric::Null => OwnedValue::Null,
|
||||
Numeric::Integer(v) => OwnedValue::Integer(v),
|
||||
Numeric::Float(v) => OwnedValue::Float(v.into()),
|
||||
Numeric::Null => Value::Null,
|
||||
Numeric::Integer(v) => Value::Integer(v),
|
||||
Numeric::Float(v) => Value::Float(v.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,22 +96,22 @@ impl<T: AsRef<str>> From<T> for Numeric {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedValue> for Numeric {
|
||||
fn from(value: OwnedValue) -> Self {
|
||||
impl From<Value> for Numeric {
|
||||
fn from(value: Value) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
impl From<&OwnedValue> for Numeric {
|
||||
fn from(value: &OwnedValue) -> Self {
|
||||
impl From<&Value> for Numeric {
|
||||
fn from(value: &Value) -> Self {
|
||||
match value {
|
||||
OwnedValue::Null => Self::Null,
|
||||
OwnedValue::Integer(v) => Self::Integer(*v),
|
||||
OwnedValue::Float(v) => match NonNan::new(*v) {
|
||||
Value::Null => Self::Null,
|
||||
Value::Integer(v) => Self::Integer(*v),
|
||||
Value::Float(v) => match NonNan::new(*v) {
|
||||
Some(v) => Self::Float(v),
|
||||
None => Self::Null,
|
||||
},
|
||||
OwnedValue::Text(text) => Numeric::from(text.as_str()),
|
||||
OwnedValue::Blob(blob) => {
|
||||
Value::Text(text) => Numeric::from(text.as_str()),
|
||||
Value::Blob(blob) => {
|
||||
let text = String::from_utf8_lossy(blob.as_slice());
|
||||
Numeric::from(&text)
|
||||
}
|
||||
@@ -220,11 +220,11 @@ pub enum NullableInteger {
|
||||
Integer(i64),
|
||||
}
|
||||
|
||||
impl From<NullableInteger> for OwnedValue {
|
||||
impl From<NullableInteger> for Value {
|
||||
fn from(value: NullableInteger) -> Self {
|
||||
match value {
|
||||
NullableInteger::Null => OwnedValue::Null,
|
||||
NullableInteger::Integer(v) => OwnedValue::Integer(v),
|
||||
NullableInteger::Null => Value::Null,
|
||||
NullableInteger::Integer(v) => Value::Integer(v),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,20 +235,20 @@ impl<T: AsRef<str>> From<T> for NullableInteger {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedValue> for NullableInteger {
|
||||
fn from(value: OwnedValue) -> Self {
|
||||
impl From<Value> for NullableInteger {
|
||||
fn from(value: Value) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&OwnedValue> for NullableInteger {
|
||||
fn from(value: &OwnedValue) -> Self {
|
||||
impl From<&Value> for NullableInteger {
|
||||
fn from(value: &Value) -> Self {
|
||||
match value {
|
||||
OwnedValue::Null => Self::Null,
|
||||
OwnedValue::Integer(v) => Self::Integer(*v),
|
||||
OwnedValue::Float(v) => Self::Integer(*v as i64),
|
||||
OwnedValue::Text(text) => Self::from(text.as_str()),
|
||||
OwnedValue::Blob(blob) => {
|
||||
Value::Null => Self::Null,
|
||||
Value::Integer(v) => Self::Integer(*v),
|
||||
Value::Float(v) => Self::Integer(*v as i64),
|
||||
Value::Text(text) => Self::from(text.as_str()),
|
||||
Value::Blob(blob) => {
|
||||
let text = String::from_utf8_lossy(blob.as_slice());
|
||||
Self::from(text)
|
||||
}
|
||||
|
||||
@@ -14,9 +14,7 @@ use crate::{
|
||||
|
||||
use crate::{
|
||||
return_corrupt,
|
||||
types::{
|
||||
compare_immutable, CursorResult, ImmutableRecord, OwnedValue, RefValue, SeekKey, SeekOp,
|
||||
},
|
||||
types::{compare_immutable, CursorResult, ImmutableRecord, RefValue, SeekKey, SeekOp, Value},
|
||||
LimboError, Result,
|
||||
};
|
||||
|
||||
@@ -3882,10 +3880,10 @@ impl BTreeCursor {
|
||||
Ok(CursorResult::Ok(false)) // not a duplicate
|
||||
}
|
||||
|
||||
pub fn exists(&mut self, key: &OwnedValue) -> Result<CursorResult<bool>> {
|
||||
pub fn exists(&mut self, key: &Value) -> Result<CursorResult<bool>> {
|
||||
assert!(self.mv_cursor.is_none());
|
||||
let int_key = match key {
|
||||
OwnedValue::Integer(i) => i,
|
||||
Value::Integer(i) => i,
|
||||
_ => unreachable!("btree tables are indexed by integers!"),
|
||||
};
|
||||
let _ = return_if_io!(self.move_to(SeekKey::TableRowId(*int_key as u64), SeekOp::EQ));
|
||||
@@ -3897,7 +3895,7 @@ impl BTreeCursor {
|
||||
|
||||
// find cell
|
||||
let int_key = match key {
|
||||
OwnedValue::Integer(i) => *i as u64,
|
||||
Value::Integer(i) => *i as u64,
|
||||
_ => unreachable!("btree tables are indexed by integers!"),
|
||||
};
|
||||
let cell_idx = self.find_cell(contents, &BTreeKey::new_table_rowid(int_key, None));
|
||||
@@ -5457,7 +5455,7 @@ mod tests {
|
||||
pager::PageRef,
|
||||
sqlite3_ondisk::{BTreeCell, PageContent, PageType},
|
||||
},
|
||||
types::OwnedValue,
|
||||
types::Value,
|
||||
Database, Page, Pager, PlatformIO,
|
||||
};
|
||||
|
||||
@@ -5537,8 +5535,7 @@ mod tests {
|
||||
let page = get_page(2);
|
||||
let page = page.get_contents();
|
||||
let header_size = 8;
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(1))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(1))]);
|
||||
let payload = add_record(1, 0, page, record, &conn);
|
||||
assert_eq!(page.cell_count(), 1);
|
||||
let free = compute_free_space(page, 4096);
|
||||
@@ -5566,9 +5563,8 @@ mod tests {
|
||||
let mut cells = Vec::new();
|
||||
let usable_space = 4096;
|
||||
for i in 0..3 {
|
||||
let record = ImmutableRecord::from_registers(&[Register::OwnedValue(
|
||||
OwnedValue::Integer(i as i64),
|
||||
)]);
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::Value(Value::Integer(i as i64))]);
|
||||
let payload = add_record(i, i, page, record, &conn);
|
||||
assert_eq!(page.cell_count(), i + 1);
|
||||
let free = compute_free_space(page, usable_space);
|
||||
@@ -5819,9 +5815,10 @@ mod tests {
|
||||
pager.deref(),
|
||||
)
|
||||
.unwrap();
|
||||
let value = ImmutableRecord::from_registers(&[Register::OwnedValue(
|
||||
OwnedValue::Blob(vec![0; *size]),
|
||||
)]);
|
||||
let value = ImmutableRecord::from_registers(&[Register::Value(Value::Blob(vec![
|
||||
0;
|
||||
*size
|
||||
]))]);
|
||||
tracing::info!("insert key:{}", key);
|
||||
run_until_done(
|
||||
|| cursor.insert(&BTreeKey::new_table_rowid(*key, Some(&value)), true),
|
||||
@@ -5900,9 +5897,8 @@ mod tests {
|
||||
pager.deref(),
|
||||
)
|
||||
.unwrap();
|
||||
let value = ImmutableRecord::from_registers(&[Register::OwnedValue(
|
||||
OwnedValue::Blob(vec![0; size]),
|
||||
)]);
|
||||
let value =
|
||||
ImmutableRecord::from_registers(&[Register::Value(Value::Blob(vec![0; size]))]);
|
||||
let btree_before = format_btree(pager.clone(), root_page, 0);
|
||||
run_until_done(
|
||||
|| cursor.insert(&BTreeKey::new_table_rowid(key as u64, Some(&value)), true),
|
||||
@@ -5991,7 +5987,7 @@ mod tests {
|
||||
keys.push(key.clone());
|
||||
let value = ImmutableRecord::from_registers(
|
||||
&key.iter()
|
||||
.map(|col| Register::OwnedValue(OwnedValue::Integer(*col)))
|
||||
.map(|col| Register::Value(Value::Integer(*col)))
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
run_until_done(
|
||||
@@ -6041,9 +6037,8 @@ mod tests {
|
||||
let usable_space = 4096;
|
||||
let total_cells = 10;
|
||||
for i in 0..total_cells {
|
||||
let record = ImmutableRecord::from_registers(&[Register::OwnedValue(
|
||||
OwnedValue::Integer(i as i64),
|
||||
)]);
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::Value(Value::Integer(i as i64))]);
|
||||
let payload = add_record(i, i, page, record, &conn);
|
||||
assert_eq!(page.cell_count(), i + 1);
|
||||
let free = compute_free_space(page, usable_space);
|
||||
@@ -6402,9 +6397,8 @@ mod tests {
|
||||
let mut cells = Vec::new();
|
||||
let usable_space = 4096;
|
||||
for i in 0..3 {
|
||||
let record = ImmutableRecord::from_registers(&[Register::OwnedValue(
|
||||
OwnedValue::Integer(i as i64),
|
||||
)]);
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::Value(Value::Integer(i as i64))]);
|
||||
let payload = add_record(i, i, page, record, &conn);
|
||||
assert_eq!(page.cell_count(), i + 1);
|
||||
let free = compute_free_space(page, usable_space);
|
||||
@@ -6444,9 +6438,8 @@ mod tests {
|
||||
let usable_space = 4096;
|
||||
let total_cells = 10;
|
||||
for i in 0..total_cells {
|
||||
let record = ImmutableRecord::from_registers(&[Register::OwnedValue(
|
||||
OwnedValue::Integer(i as i64),
|
||||
)]);
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::Value(Value::Integer(i as i64))]);
|
||||
let payload = add_record(i, i, page, record, &conn);
|
||||
assert_eq!(page.cell_count(), i + 1);
|
||||
let free = compute_free_space(page, usable_space);
|
||||
@@ -6500,8 +6493,8 @@ mod tests {
|
||||
// allow appends with extra place to insert
|
||||
let cell_idx = rng.next_u64() as usize % (page.cell_count() + 1);
|
||||
let free = compute_free_space(page, usable_space);
|
||||
let record = ImmutableRecord::from_registers(&[Register::OwnedValue(
|
||||
OwnedValue::Integer(i as i64),
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(
|
||||
Value::Integer(i as i64),
|
||||
)]);
|
||||
let mut payload: Vec<u8> = Vec::new();
|
||||
fill_cell_payload(
|
||||
@@ -6578,8 +6571,8 @@ mod tests {
|
||||
// allow appends with extra place to insert
|
||||
let cell_idx = rng.next_u64() as usize % (page.cell_count() + 1);
|
||||
let free = compute_free_space(page, usable_space);
|
||||
let record = ImmutableRecord::from_registers(&[Register::OwnedValue(
|
||||
OwnedValue::Integer(i as i64),
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(
|
||||
Value::Integer(i as i64),
|
||||
)]);
|
||||
let mut payload: Vec<u8> = Vec::new();
|
||||
fill_cell_payload(
|
||||
@@ -6734,8 +6727,7 @@ mod tests {
|
||||
let header_size = 8;
|
||||
let usable_space = 4096;
|
||||
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(0))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(0))]);
|
||||
let payload = add_record(0, 0, page, record, &conn);
|
||||
let free = compute_free_space(page, usable_space);
|
||||
assert_eq!(free, 4096 - payload.len() as u16 - 2 - header_size);
|
||||
@@ -6750,8 +6742,7 @@ mod tests {
|
||||
let page = page.get_contents();
|
||||
let usable_space = 4096;
|
||||
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(0))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(0))]);
|
||||
let payload = add_record(0, 0, page, record, &conn);
|
||||
|
||||
assert_eq!(page.cell_count(), 1);
|
||||
@@ -6777,8 +6768,8 @@ mod tests {
|
||||
let usable_space = 4096;
|
||||
|
||||
let record = ImmutableRecord::from_registers(&[
|
||||
Register::OwnedValue(OwnedValue::Integer(0)),
|
||||
Register::OwnedValue(OwnedValue::Text(Text::new("aaaaaaaa"))),
|
||||
Register::Value(Value::Integer(0)),
|
||||
Register::Value(Value::Text(Text::new("aaaaaaaa"))),
|
||||
]);
|
||||
let _ = add_record(0, 0, page, record, &conn);
|
||||
|
||||
@@ -6786,8 +6777,7 @@ mod tests {
|
||||
drop_cell(page, 0, usable_space).unwrap();
|
||||
assert_eq!(page.cell_count(), 0);
|
||||
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(0))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(0))]);
|
||||
let payload = add_record(0, 0, page, record, &conn);
|
||||
assert_eq!(page.cell_count(), 1);
|
||||
|
||||
@@ -6811,8 +6801,8 @@ mod tests {
|
||||
let usable_space = 4096;
|
||||
|
||||
let record = ImmutableRecord::from_registers(&[
|
||||
Register::OwnedValue(OwnedValue::Integer(0)),
|
||||
Register::OwnedValue(OwnedValue::Text(Text::new("aaaaaaaa"))),
|
||||
Register::Value(Value::Integer(0)),
|
||||
Register::Value(Value::Text(Text::new("aaaaaaaa"))),
|
||||
]);
|
||||
let _ = add_record(0, 0, page, record, &conn);
|
||||
|
||||
@@ -6821,8 +6811,7 @@ mod tests {
|
||||
drop_cell(page, 0, usable_space).unwrap();
|
||||
assert_eq!(page.cell_count(), 0);
|
||||
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(0))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(0))]);
|
||||
let payload = add_record(0, 0, page, record, &conn);
|
||||
assert_eq!(page.cell_count(), 1);
|
||||
|
||||
@@ -6846,14 +6835,11 @@ mod tests {
|
||||
let page = page.get_contents();
|
||||
let usable_space = 4096;
|
||||
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(0))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(0))]);
|
||||
let payload = add_record(0, 0, page, record, &conn);
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(1))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(1))]);
|
||||
let _ = add_record(1, 1, page, record, &conn);
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(2))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(2))]);
|
||||
let _ = add_record(2, 2, page, record, &conn);
|
||||
|
||||
drop_cell(page, 1, usable_space).unwrap();
|
||||
@@ -6871,25 +6857,21 @@ mod tests {
|
||||
let page = page.get_contents();
|
||||
let usable_space = 4096;
|
||||
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(0))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(0))]);
|
||||
let _ = add_record(0, 0, page, record, &conn);
|
||||
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(0))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(0))]);
|
||||
let _ = add_record(0, 0, page, record, &conn);
|
||||
drop_cell(page, 0, usable_space).unwrap();
|
||||
|
||||
defragment_page(page, usable_space);
|
||||
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(0))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(0))]);
|
||||
let _ = add_record(0, 1, page, record, &conn);
|
||||
|
||||
drop_cell(page, 0, usable_space).unwrap();
|
||||
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(0))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(0))]);
|
||||
let _ = add_record(0, 1, page, record, &conn);
|
||||
}
|
||||
|
||||
@@ -6901,8 +6883,7 @@ mod tests {
|
||||
let page = get_page(2);
|
||||
let usable_space = 4096;
|
||||
let insert = |pos, page| {
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(0))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(0))]);
|
||||
let _ = add_record(0, pos, page, record, &conn);
|
||||
};
|
||||
let drop = |pos, page| {
|
||||
@@ -6941,8 +6922,7 @@ mod tests {
|
||||
let page = get_page(2);
|
||||
let usable_space = 4096;
|
||||
let insert = |pos, page| {
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(0))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(0))]);
|
||||
let _ = add_record(0, pos, page, record, &conn);
|
||||
};
|
||||
let drop = |pos, page| {
|
||||
@@ -6951,8 +6931,7 @@ mod tests {
|
||||
let defragment = |page| {
|
||||
defragment_page(page, usable_space);
|
||||
};
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(0))]);
|
||||
let record = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(0))]);
|
||||
let mut payload: Vec<u8> = Vec::new();
|
||||
fill_cell_payload(
|
||||
page.get_contents().page_type(),
|
||||
@@ -6985,8 +6964,7 @@ mod tests {
|
||||
for i in 0..10000 {
|
||||
let mut cursor = BTreeCursor::new(None, pager.clone(), root_page);
|
||||
tracing::info!("INSERT INTO t VALUES ({});", i,);
|
||||
let value =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Integer(i))]);
|
||||
let value = ImmutableRecord::from_registers(&[Register::Value(Value::Integer(i))]);
|
||||
tracing::trace!("before insert {}", i);
|
||||
run_until_done(
|
||||
|| {
|
||||
@@ -7012,7 +6990,7 @@ mod tests {
|
||||
);
|
||||
for key in keys.iter() {
|
||||
let mut cursor = BTreeCursor::new(None, pager.clone(), root_page);
|
||||
let key = OwnedValue::Integer(*key);
|
||||
let key = Value::Integer(*key);
|
||||
let exists = run_until_done(|| cursor.exists(&key), pager.deref()).unwrap();
|
||||
assert!(exists, "key not found {}", key);
|
||||
}
|
||||
@@ -7026,10 +7004,7 @@ mod tests {
|
||||
let page = get_page(2);
|
||||
let usable_space = 4096;
|
||||
let record =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Blob(vec![
|
||||
0;
|
||||
3600
|
||||
]))]);
|
||||
ImmutableRecord::from_registers(&[Register::Value(Value::Blob(vec![0; 3600]))]);
|
||||
let mut payload: Vec<u8> = Vec::new();
|
||||
fill_cell_payload(
|
||||
page.get_contents().page_type(),
|
||||
@@ -7064,7 +7039,7 @@ mod tests {
|
||||
// Insert 10,000 records in to the BTree.
|
||||
for i in 1..=10000 {
|
||||
let mut cursor = BTreeCursor::new(None, pager.clone(), root_page);
|
||||
let value = ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Text(
|
||||
let value = ImmutableRecord::from_registers(&[Register::Value(Value::Text(
|
||||
Text::new("hello world"),
|
||||
))]);
|
||||
|
||||
@@ -7109,7 +7084,7 @@ mod tests {
|
||||
}
|
||||
|
||||
let mut cursor = BTreeCursor::new(None, pager.clone(), root_page);
|
||||
let key = OwnedValue::Integer(i);
|
||||
let key = Value::Integer(i);
|
||||
let exists = run_until_done(|| cursor.exists(&key), pager.deref()).unwrap();
|
||||
assert!(exists, "Key {} should exist but doesn't", i);
|
||||
}
|
||||
@@ -7117,7 +7092,7 @@ mod tests {
|
||||
// Verify the deleted records don't exist.
|
||||
for i in 500..=3500 {
|
||||
let mut cursor = BTreeCursor::new(None, pager.clone(), root_page);
|
||||
let key = OwnedValue::Integer(i);
|
||||
let key = Value::Integer(i);
|
||||
let exists = run_until_done(|| cursor.exists(&key), pager.deref()).unwrap();
|
||||
assert!(!exists, "Deleted key {} still exists", i);
|
||||
}
|
||||
@@ -7140,11 +7115,10 @@ mod tests {
|
||||
for i in 0..iterations {
|
||||
let mut cursor = BTreeCursor::new(None, pager.clone(), root_page);
|
||||
tracing::info!("INSERT INTO t VALUES ({});", i,);
|
||||
let value =
|
||||
ImmutableRecord::from_registers(&[Register::OwnedValue(OwnedValue::Text(Text {
|
||||
value: huge_texts[i].as_bytes().to_vec(),
|
||||
subtype: crate::types::TextSubtype::Text,
|
||||
}))]);
|
||||
let value = ImmutableRecord::from_registers(&[Register::Value(Value::Text(Text {
|
||||
value: huge_texts[i].as_bytes().to_vec(),
|
||||
subtype: crate::types::TextSubtype::Text,
|
||||
}))]);
|
||||
tracing::trace!("before insert {}", i);
|
||||
tracing::debug!(
|
||||
"=========== btree before ===========\n{}\n\n",
|
||||
|
||||
@@ -1616,42 +1616,42 @@ pub fn read_u32(buf: &[u8], pos: usize) -> u32 {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::OwnedValue;
|
||||
use crate::Value;
|
||||
|
||||
use super::*;
|
||||
use rstest::rstest;
|
||||
|
||||
#[rstest]
|
||||
#[case(&[], SerialType::null(), OwnedValue::Null)]
|
||||
#[case(&[255], SerialType::i8(), OwnedValue::Integer(-1))]
|
||||
#[case(&[0x12, 0x34], SerialType::i16(), OwnedValue::Integer(0x1234))]
|
||||
#[case(&[0xFE], SerialType::i8(), OwnedValue::Integer(-2))]
|
||||
#[case(&[0x12, 0x34, 0x56], SerialType::i24(), OwnedValue::Integer(0x123456))]
|
||||
#[case(&[0x12, 0x34, 0x56, 0x78], SerialType::i32(), OwnedValue::Integer(0x12345678))]
|
||||
#[case(&[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC], SerialType::i48(), OwnedValue::Integer(0x123456789ABC))]
|
||||
#[case(&[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF], SerialType::i64(), OwnedValue::Integer(0x123456789ABCDEFF))]
|
||||
#[case(&[0x40, 0x09, 0x21, 0xFB, 0x54, 0x44, 0x2D, 0x18], SerialType::f64(), OwnedValue::Float(std::f64::consts::PI))]
|
||||
#[case(&[1, 2], SerialType::const_int0(), OwnedValue::Integer(0))]
|
||||
#[case(&[65, 66], SerialType::const_int1(), OwnedValue::Integer(1))]
|
||||
#[case(&[1, 2, 3], SerialType::blob(3), OwnedValue::Blob(vec![1, 2, 3].into()))]
|
||||
#[case(&[], SerialType::blob(0), OwnedValue::Blob(vec![].into()))] // empty blob
|
||||
#[case(&[65, 66, 67], SerialType::text(3), OwnedValue::build_text("ABC"))]
|
||||
#[case(&[0x80], SerialType::i8(), OwnedValue::Integer(-128))]
|
||||
#[case(&[0x80, 0], SerialType::i16(), OwnedValue::Integer(-32768))]
|
||||
#[case(&[0x80, 0, 0], SerialType::i24(), OwnedValue::Integer(-8388608))]
|
||||
#[case(&[0x80, 0, 0, 0], SerialType::i32(), OwnedValue::Integer(-2147483648))]
|
||||
#[case(&[0x80, 0, 0, 0, 0, 0], SerialType::i48(), OwnedValue::Integer(-140737488355328))]
|
||||
#[case(&[0x80, 0, 0, 0, 0, 0, 0, 0], SerialType::i64(), OwnedValue::Integer(-9223372036854775808))]
|
||||
#[case(&[0x7f], SerialType::i8(), OwnedValue::Integer(127))]
|
||||
#[case(&[0x7f, 0xff], SerialType::i16(), OwnedValue::Integer(32767))]
|
||||
#[case(&[0x7f, 0xff, 0xff], SerialType::i24(), OwnedValue::Integer(8388607))]
|
||||
#[case(&[0x7f, 0xff, 0xff, 0xff], SerialType::i32(), OwnedValue::Integer(2147483647))]
|
||||
#[case(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff], SerialType::i48(), OwnedValue::Integer(140737488355327))]
|
||||
#[case(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], SerialType::i64(), OwnedValue::Integer(9223372036854775807))]
|
||||
#[case(&[], SerialType::null(), Value::Null)]
|
||||
#[case(&[255], SerialType::i8(), Value::Integer(-1))]
|
||||
#[case(&[0x12, 0x34], SerialType::i16(), Value::Integer(0x1234))]
|
||||
#[case(&[0xFE], SerialType::i8(), Value::Integer(-2))]
|
||||
#[case(&[0x12, 0x34, 0x56], SerialType::i24(), Value::Integer(0x123456))]
|
||||
#[case(&[0x12, 0x34, 0x56, 0x78], SerialType::i32(), Value::Integer(0x12345678))]
|
||||
#[case(&[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC], SerialType::i48(), Value::Integer(0x123456789ABC))]
|
||||
#[case(&[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF], SerialType::i64(), Value::Integer(0x123456789ABCDEFF))]
|
||||
#[case(&[0x40, 0x09, 0x21, 0xFB, 0x54, 0x44, 0x2D, 0x18], SerialType::f64(), Value::Float(std::f64::consts::PI))]
|
||||
#[case(&[1, 2], SerialType::const_int0(), Value::Integer(0))]
|
||||
#[case(&[65, 66], SerialType::const_int1(), Value::Integer(1))]
|
||||
#[case(&[1, 2, 3], SerialType::blob(3), Value::Blob(vec![1, 2, 3].into()))]
|
||||
#[case(&[], SerialType::blob(0), Value::Blob(vec![].into()))] // empty blob
|
||||
#[case(&[65, 66, 67], SerialType::text(3), Value::build_text("ABC"))]
|
||||
#[case(&[0x80], SerialType::i8(), Value::Integer(-128))]
|
||||
#[case(&[0x80, 0], SerialType::i16(), Value::Integer(-32768))]
|
||||
#[case(&[0x80, 0, 0], SerialType::i24(), Value::Integer(-8388608))]
|
||||
#[case(&[0x80, 0, 0, 0], SerialType::i32(), Value::Integer(-2147483648))]
|
||||
#[case(&[0x80, 0, 0, 0, 0, 0], SerialType::i48(), Value::Integer(-140737488355328))]
|
||||
#[case(&[0x80, 0, 0, 0, 0, 0, 0, 0], SerialType::i64(), Value::Integer(-9223372036854775808))]
|
||||
#[case(&[0x7f], SerialType::i8(), Value::Integer(127))]
|
||||
#[case(&[0x7f, 0xff], SerialType::i16(), Value::Integer(32767))]
|
||||
#[case(&[0x7f, 0xff, 0xff], SerialType::i24(), Value::Integer(8388607))]
|
||||
#[case(&[0x7f, 0xff, 0xff, 0xff], SerialType::i32(), Value::Integer(2147483647))]
|
||||
#[case(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff], SerialType::i48(), Value::Integer(140737488355327))]
|
||||
#[case(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], SerialType::i64(), Value::Integer(9223372036854775807))]
|
||||
fn test_read_value(
|
||||
#[case] buf: &[u8],
|
||||
#[case] serial_type: SerialType,
|
||||
#[case] expected: OwnedValue,
|
||||
#[case] expected: Value,
|
||||
) {
|
||||
let result = read_value(buf, serial_type).unwrap();
|
||||
assert_eq!(result.0.to_owned(), expected);
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::vdbe::{
|
||||
insn::{CmpInsFlags, Insn},
|
||||
BranchOffset,
|
||||
};
|
||||
use crate::{OwnedValue, Result};
|
||||
use crate::{Result, Value};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ConditionMetadata {
|
||||
@@ -1983,13 +1983,13 @@ pub fn translate_expr(
|
||||
ast::Expr::Literal(lit) => match lit {
|
||||
ast::Literal::Numeric(val) => {
|
||||
match parse_numeric_literal(val)? {
|
||||
OwnedValue::Integer(int_value) => {
|
||||
Value::Integer(int_value) => {
|
||||
program.emit_insn(Insn::Integer {
|
||||
value: int_value,
|
||||
dest: target_register,
|
||||
});
|
||||
}
|
||||
OwnedValue::Float(real_value) => {
|
||||
Value::Float(real_value) => {
|
||||
program.emit_insn(Insn::Real {
|
||||
value: real_value,
|
||||
dest: target_register,
|
||||
@@ -2104,13 +2104,13 @@ pub fn translate_expr(
|
||||
(UnaryOperator::Negative, ast::Expr::Literal(ast::Literal::Numeric(numeric_value))) => {
|
||||
let numeric_value = "-".to_owned() + numeric_value;
|
||||
match parse_numeric_literal(&numeric_value)? {
|
||||
OwnedValue::Integer(int_value) => {
|
||||
Value::Integer(int_value) => {
|
||||
program.emit_insn(Insn::Integer {
|
||||
value: int_value,
|
||||
dest: target_register,
|
||||
});
|
||||
}
|
||||
OwnedValue::Float(real_value) => {
|
||||
Value::Float(real_value) => {
|
||||
program.emit_insn(Insn::Real {
|
||||
value: real_value,
|
||||
dest: target_register,
|
||||
@@ -2140,13 +2140,13 @@ pub fn translate_expr(
|
||||
}
|
||||
(UnaryOperator::BitwiseNot, ast::Expr::Literal(ast::Literal::Numeric(num_val))) => {
|
||||
match parse_numeric_literal(num_val)? {
|
||||
OwnedValue::Integer(int_value) => {
|
||||
Value::Integer(int_value) => {
|
||||
program.emit_insn(Insn::Integer {
|
||||
value: !int_value,
|
||||
dest: target_register,
|
||||
});
|
||||
}
|
||||
OwnedValue::Float(real_value) => {
|
||||
Value::Float(real_value) => {
|
||||
program.emit_insn(Insn::Integer {
|
||||
value: !(real_value as i64),
|
||||
dest: target_register,
|
||||
|
||||
@@ -146,7 +146,7 @@ fn to_ext_constraint_op(op: &Operator) -> Option<ConstraintOp> {
|
||||
/// back to it as arguments for the VFilter operation.
|
||||
/// is going to be filtered against: e.g:
|
||||
/// 'SELECT key, value FROM vtab WHERE key = 'some_key';
|
||||
/// we need to send the OwnedValue('some_key') as an argument to VFilter, and possibly omit it from
|
||||
/// we need to send the Value('some_key') as an argument to VFilter, and possibly omit it from
|
||||
/// the filtration in the vdbe layer.
|
||||
pub fn convert_where_to_vtab_constraint(
|
||||
term: &WhereTerm,
|
||||
|
||||
214
core/types.rs
214
core/types.rs
@@ -16,7 +16,7 @@ use std::fmt::Display;
|
||||
const MAX_REAL_SIZE: u8 = 15;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum OwnedValueType {
|
||||
pub enum ValueType {
|
||||
Null,
|
||||
Integer,
|
||||
Float,
|
||||
@@ -25,7 +25,7 @@ pub enum OwnedValueType {
|
||||
Error,
|
||||
}
|
||||
|
||||
impl Display for OwnedValueType {
|
||||
impl Display for ValueType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let value = match self {
|
||||
Self::Null => "NULL",
|
||||
@@ -107,7 +107,7 @@ impl TextRef {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum OwnedValue {
|
||||
pub enum Value {
|
||||
Null,
|
||||
Integer(i64),
|
||||
Float(f64),
|
||||
@@ -130,8 +130,8 @@ pub enum RefValue {
|
||||
Blob(RawSlice),
|
||||
}
|
||||
|
||||
impl OwnedValue {
|
||||
// A helper function that makes building a text OwnedValue easier.
|
||||
impl Value {
|
||||
// A helper function that makes building a text Value easier.
|
||||
pub fn build_text(text: impl AsRef<str>) -> Self {
|
||||
Self::Text(Text::new(text.as_ref()))
|
||||
}
|
||||
@@ -144,33 +144,33 @@ impl OwnedValue {
|
||||
}
|
||||
|
||||
pub fn from_blob(data: Vec<u8>) -> Self {
|
||||
OwnedValue::Blob(data)
|
||||
Value::Blob(data)
|
||||
}
|
||||
|
||||
pub fn to_text(&self) -> Option<&str> {
|
||||
match self {
|
||||
OwnedValue::Text(t) => Some(t.as_str()),
|
||||
Value::Text(t) => Some(t.as_str()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_text(text: &str) -> Self {
|
||||
OwnedValue::Text(Text::new(text))
|
||||
Value::Text(Text::new(text))
|
||||
}
|
||||
|
||||
pub fn value_type(&self) -> OwnedValueType {
|
||||
pub fn value_type(&self) -> ValueType {
|
||||
match self {
|
||||
OwnedValue::Null => OwnedValueType::Null,
|
||||
OwnedValue::Integer(_) => OwnedValueType::Integer,
|
||||
OwnedValue::Float(_) => OwnedValueType::Float,
|
||||
OwnedValue::Text(_) => OwnedValueType::Text,
|
||||
OwnedValue::Blob(_) => OwnedValueType::Blob,
|
||||
Value::Null => ValueType::Null,
|
||||
Value::Integer(_) => ValueType::Integer,
|
||||
Value::Float(_) => ValueType::Float,
|
||||
Value::Text(_) => ValueType::Text,
|
||||
Value::Blob(_) => ValueType::Blob,
|
||||
}
|
||||
}
|
||||
pub fn serialize_serial(&self, out: &mut Vec<u8>) {
|
||||
match self {
|
||||
OwnedValue::Null => {}
|
||||
OwnedValue::Integer(i) => {
|
||||
Value::Null => {}
|
||||
Value::Integer(i) => {
|
||||
let serial_type = SerialType::from(self);
|
||||
match serial_type.kind() {
|
||||
SerialTypeKind::I8 => out.extend_from_slice(&(*i as i8).to_be_bytes()),
|
||||
@@ -182,9 +182,9 @@ impl OwnedValue {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
OwnedValue::Float(f) => out.extend_from_slice(&f.to_be_bytes()),
|
||||
OwnedValue::Text(t) => out.extend_from_slice(&t.value),
|
||||
OwnedValue::Blob(b) => out.extend_from_slice(b),
|
||||
Value::Float(f) => out.extend_from_slice(&f.to_be_bytes()),
|
||||
Value::Text(t) => out.extend_from_slice(&t.value),
|
||||
Value::Blob(b) => out.extend_from_slice(b),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -195,11 +195,11 @@ pub struct ExternalAggState {
|
||||
pub argc: usize,
|
||||
pub step_fn: StepFunction,
|
||||
pub finalize_fn: FinalizeFunction,
|
||||
pub finalized_value: Option<OwnedValue>,
|
||||
pub finalized_value: Option<Value>,
|
||||
}
|
||||
|
||||
impl ExternalAggState {
|
||||
pub fn cache_final_value(&mut self, value: OwnedValue) -> &OwnedValue {
|
||||
pub fn cache_final_value(&mut self, value: Value) -> &Value {
|
||||
self.finalized_value = Some(value);
|
||||
self.finalized_value.as_ref().unwrap()
|
||||
}
|
||||
@@ -211,11 +211,11 @@ impl ExternalAggState {
|
||||
/// format!("{}", value);
|
||||
/// ---BAD---
|
||||
/// match value {
|
||||
/// OwnedValue::Integer(i) => *i.as_str(),
|
||||
/// OwnedValue::Float(f) => *f.as_str(),
|
||||
/// Value::Integer(i) => *i.as_str(),
|
||||
/// Value::Float(f) => *f.as_str(),
|
||||
/// ....
|
||||
/// }
|
||||
impl Display for OwnedValue {
|
||||
impl Display for Value {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Null => write!(f, ""),
|
||||
@@ -331,7 +331,7 @@ impl Display for OwnedValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnedValue {
|
||||
impl Value {
|
||||
pub fn to_ffi(&self) -> ExtValue {
|
||||
match self {
|
||||
Self::Null => ExtValue::null(),
|
||||
@@ -344,38 +344,38 @@ impl OwnedValue {
|
||||
|
||||
pub fn from_ffi(v: ExtValue) -> Result<Self> {
|
||||
let res = match v.value_type() {
|
||||
ExtValueType::Null => Ok(OwnedValue::Null),
|
||||
ExtValueType::Null => Ok(Value::Null),
|
||||
ExtValueType::Integer => {
|
||||
let Some(int) = v.to_integer() else {
|
||||
return Ok(OwnedValue::Null);
|
||||
return Ok(Value::Null);
|
||||
};
|
||||
Ok(OwnedValue::Integer(int))
|
||||
Ok(Value::Integer(int))
|
||||
}
|
||||
ExtValueType::Float => {
|
||||
let Some(float) = v.to_float() else {
|
||||
return Ok(OwnedValue::Null);
|
||||
return Ok(Value::Null);
|
||||
};
|
||||
Ok(OwnedValue::Float(float))
|
||||
Ok(Value::Float(float))
|
||||
}
|
||||
ExtValueType::Text => {
|
||||
let Some(text) = v.to_text() else {
|
||||
return Ok(OwnedValue::Null);
|
||||
return Ok(Value::Null);
|
||||
};
|
||||
#[cfg(feature = "json")]
|
||||
if v.is_json() {
|
||||
return Ok(OwnedValue::Text(Text::json(text.to_string())));
|
||||
return Ok(Value::Text(Text::json(text.to_string())));
|
||||
}
|
||||
Ok(OwnedValue::build_text(text))
|
||||
Ok(Value::build_text(text))
|
||||
}
|
||||
ExtValueType::Blob => {
|
||||
let Some(blob) = v.to_blob() else {
|
||||
return Ok(OwnedValue::Null);
|
||||
return Ok(Value::Null);
|
||||
};
|
||||
Ok(OwnedValue::Blob(blob))
|
||||
Ok(Value::Blob(blob))
|
||||
}
|
||||
ExtValueType::Error => {
|
||||
let Some(err) = v.to_error_details() else {
|
||||
return Ok(OwnedValue::Null);
|
||||
return Ok(Value::Null);
|
||||
};
|
||||
match err {
|
||||
(_, Some(msg)) => Err(LimboError::ExtensionError(msg)),
|
||||
@@ -390,29 +390,29 @@ impl OwnedValue {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum AggContext {
|
||||
Avg(OwnedValue, OwnedValue), // acc and count
|
||||
Sum(OwnedValue),
|
||||
Count(OwnedValue),
|
||||
Max(Option<OwnedValue>),
|
||||
Min(Option<OwnedValue>),
|
||||
GroupConcat(OwnedValue),
|
||||
Avg(Value, Value), // acc and count
|
||||
Sum(Value),
|
||||
Count(Value),
|
||||
Max(Option<Value>),
|
||||
Min(Option<Value>),
|
||||
GroupConcat(Value),
|
||||
External(ExternalAggState),
|
||||
}
|
||||
|
||||
const NULL: OwnedValue = OwnedValue::Null;
|
||||
const NULL: Value = Value::Null;
|
||||
|
||||
impl AggContext {
|
||||
pub fn compute_external(&mut self) -> Result<()> {
|
||||
if let Self::External(ext_state) = self {
|
||||
if ext_state.finalized_value.is_none() {
|
||||
let final_value = unsafe { (ext_state.finalize_fn)(ext_state.state) };
|
||||
ext_state.cache_final_value(OwnedValue::from_ffi(final_value)?);
|
||||
ext_state.cache_final_value(Value::from_ffi(final_value)?);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn final_value(&self) -> &OwnedValue {
|
||||
pub fn final_value(&self) -> &Value {
|
||||
match self {
|
||||
Self::Avg(acc, _count) => acc,
|
||||
Self::Sum(acc) => acc,
|
||||
@@ -425,8 +425,8 @@ impl AggContext {
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<OwnedValue> for OwnedValue {
|
||||
fn eq(&self, other: &OwnedValue) -> bool {
|
||||
impl PartialEq<Value> for Value {
|
||||
fn eq(&self, other: &Value) -> bool {
|
||||
match (self, other) {
|
||||
(Self::Integer(int_left), Self::Integer(int_right)) => int_left == int_right,
|
||||
(Self::Integer(int_left), Self::Float(float_right)) => {
|
||||
@@ -447,13 +447,13 @@ impl PartialEq<OwnedValue> for OwnedValue {
|
||||
}
|
||||
}
|
||||
|
||||
fn ne(&self, other: &OwnedValue) -> bool {
|
||||
fn ne(&self, other: &Value) -> bool {
|
||||
!self.eq(other)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::non_canonical_partial_ord_impl)]
|
||||
impl PartialOrd<OwnedValue> for OwnedValue {
|
||||
impl PartialOrd<Value> for Value {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
match (self, other) {
|
||||
(Self::Integer(int_left), Self::Integer(int_right)) => int_left.partial_cmp(int_right),
|
||||
@@ -503,16 +503,16 @@ impl PartialOrd<AggContext> for AggContext {
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for OwnedValue {}
|
||||
impl Eq for Value {}
|
||||
|
||||
impl Ord for OwnedValue {
|
||||
impl Ord for Value {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Add<OwnedValue> for OwnedValue {
|
||||
type Output = OwnedValue;
|
||||
impl std::ops::Add<Value> for Value {
|
||||
type Output = Value;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
@@ -552,8 +552,8 @@ impl std::ops::Add<OwnedValue> for OwnedValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Add<f64> for OwnedValue {
|
||||
type Output = OwnedValue;
|
||||
impl std::ops::Add<f64> for Value {
|
||||
type Output = Value;
|
||||
|
||||
fn add(self, rhs: f64) -> Self::Output {
|
||||
match self {
|
||||
@@ -564,8 +564,8 @@ impl std::ops::Add<f64> for OwnedValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Add<i64> for OwnedValue {
|
||||
type Output = OwnedValue;
|
||||
impl std::ops::Add<i64> for Value {
|
||||
type Output = Value;
|
||||
|
||||
fn add(self, rhs: i64) -> Self::Output {
|
||||
match self {
|
||||
@@ -576,28 +576,28 @@ impl std::ops::Add<i64> for OwnedValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::AddAssign for OwnedValue {
|
||||
impl std::ops::AddAssign for Value {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
*self = self.clone() + rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::AddAssign<i64> for OwnedValue {
|
||||
impl std::ops::AddAssign<i64> for Value {
|
||||
fn add_assign(&mut self, rhs: i64) {
|
||||
*self = self.clone() + rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::AddAssign<f64> for OwnedValue {
|
||||
impl std::ops::AddAssign<f64> for Value {
|
||||
fn add_assign(&mut self, rhs: f64) {
|
||||
*self = self.clone() + rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Div<OwnedValue> for OwnedValue {
|
||||
type Output = OwnedValue;
|
||||
impl std::ops::Div<Value> for Value {
|
||||
type Output = Value;
|
||||
|
||||
fn div(self, rhs: OwnedValue) -> Self::Output {
|
||||
fn div(self, rhs: Value) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(Self::Integer(int_left), Self::Integer(int_right)) => {
|
||||
Self::Integer(int_left / int_right)
|
||||
@@ -616,8 +616,8 @@ impl std::ops::Div<OwnedValue> for OwnedValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DivAssign<OwnedValue> for OwnedValue {
|
||||
fn div_assign(&mut self, rhs: OwnedValue) {
|
||||
impl std::ops::DivAssign<Value> for Value {
|
||||
fn div_assign(&mut self, rhs: Value) {
|
||||
*self = self.clone() / rhs;
|
||||
}
|
||||
}
|
||||
@@ -671,7 +671,7 @@ pub struct ImmutableRecord {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Record {
|
||||
values: Vec<OwnedValue>,
|
||||
values: Vec<Value>,
|
||||
}
|
||||
|
||||
impl Record {
|
||||
@@ -684,15 +684,15 @@ impl Record {
|
||||
self.values.len()
|
||||
}
|
||||
|
||||
pub fn last_value(&self) -> Option<&OwnedValue> {
|
||||
pub fn last_value(&self) -> Option<&Value> {
|
||||
self.values.last()
|
||||
}
|
||||
|
||||
pub fn get_values(&self) -> &Vec<OwnedValue> {
|
||||
pub fn get_values(&self) -> &Vec<Value> {
|
||||
&self.values
|
||||
}
|
||||
|
||||
pub fn get_value(&self, idx: usize) -> &OwnedValue {
|
||||
pub fn get_value(&self, idx: usize) -> &Value {
|
||||
&self.values[idx]
|
||||
}
|
||||
|
||||
@@ -828,10 +828,10 @@ impl ImmutableRecord {
|
||||
let value = value.get_owned_value();
|
||||
let start_offset = writer.pos;
|
||||
match value {
|
||||
OwnedValue::Null => {
|
||||
Value::Null => {
|
||||
values.push(RefValue::Null);
|
||||
}
|
||||
OwnedValue::Integer(i) => {
|
||||
Value::Integer(i) => {
|
||||
values.push(RefValue::Integer(*i));
|
||||
let serial_type = SerialType::from(value);
|
||||
match serial_type.kind() {
|
||||
@@ -847,11 +847,11 @@ impl ImmutableRecord {
|
||||
other => panic!("Serial type is not an integer: {:?}", other),
|
||||
}
|
||||
}
|
||||
OwnedValue::Float(f) => {
|
||||
Value::Float(f) => {
|
||||
values.push(RefValue::Float(*f));
|
||||
writer.extend_from_slice(&f.to_be_bytes())
|
||||
}
|
||||
OwnedValue::Text(t) => {
|
||||
Value::Text(t) => {
|
||||
writer.extend_from_slice(&t.value);
|
||||
let end_offset = writer.pos;
|
||||
let len = end_offset - start_offset;
|
||||
@@ -862,7 +862,7 @@ impl ImmutableRecord {
|
||||
});
|
||||
values.push(value);
|
||||
}
|
||||
OwnedValue::Blob(b) => {
|
||||
Value::Blob(b) => {
|
||||
writer.extend_from_slice(b);
|
||||
let end_offset = writer.pos;
|
||||
let len = end_offset - start_offset;
|
||||
@@ -977,16 +977,16 @@ impl RefValue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_owned(&self) -> OwnedValue {
|
||||
pub fn to_owned(&self) -> Value {
|
||||
match self {
|
||||
RefValue::Null => OwnedValue::Null,
|
||||
RefValue::Integer(i) => OwnedValue::Integer(*i),
|
||||
RefValue::Float(f) => OwnedValue::Float(*f),
|
||||
RefValue::Text(text_ref) => OwnedValue::Text(Text {
|
||||
RefValue::Null => Value::Null,
|
||||
RefValue::Integer(i) => Value::Integer(*i),
|
||||
RefValue::Float(f) => Value::Float(*f),
|
||||
RefValue::Text(text_ref) => Value::Text(Text {
|
||||
value: text_ref.value.to_slice().to_vec(),
|
||||
subtype: text_ref.subtype.clone(),
|
||||
}),
|
||||
RefValue::Blob(b) => OwnedValue::Blob(b.to_slice().to_vec()),
|
||||
RefValue::Blob(b) => Value::Blob(b.to_slice().to_vec()),
|
||||
}
|
||||
}
|
||||
pub fn to_blob(&self) -> Option<&[u8]> {
|
||||
@@ -1255,11 +1255,11 @@ impl SerialType {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&OwnedValue> for SerialType {
|
||||
fn from(value: &OwnedValue) -> Self {
|
||||
impl From<&Value> for SerialType {
|
||||
fn from(value: &Value) -> Self {
|
||||
match value {
|
||||
OwnedValue::Null => SerialType::null(),
|
||||
OwnedValue::Integer(i) => match i {
|
||||
Value::Null => SerialType::null(),
|
||||
Value::Integer(i) => match i {
|
||||
0 => SerialType::const_int0(),
|
||||
1 => SerialType::const_int1(),
|
||||
i if *i >= I8_LOW && *i <= I8_HIGH => SerialType::i8(),
|
||||
@@ -1269,9 +1269,9 @@ impl From<&OwnedValue> for SerialType {
|
||||
i if *i >= I48_LOW && *i <= I48_HIGH => SerialType::i48(),
|
||||
_ => SerialType::i64(),
|
||||
},
|
||||
OwnedValue::Float(_) => SerialType::f64(),
|
||||
OwnedValue::Text(t) => SerialType::text(t.value.len() as u64),
|
||||
OwnedValue::Blob(b) => SerialType::blob(b.len() as u64),
|
||||
Value::Float(_) => SerialType::f64(),
|
||||
Value::Text(t) => SerialType::text(t.value.len() as u64),
|
||||
Value::Blob(b) => SerialType::blob(b.len() as u64),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1297,7 +1297,7 @@ impl TryFrom<u64> for SerialType {
|
||||
}
|
||||
|
||||
impl Record {
|
||||
pub fn new(values: Vec<OwnedValue>) -> Self {
|
||||
pub fn new(values: Vec<Value>) -> Self {
|
||||
Self { values }
|
||||
}
|
||||
|
||||
@@ -1317,8 +1317,8 @@ impl Record {
|
||||
// write content
|
||||
for value in &self.values {
|
||||
match value {
|
||||
OwnedValue::Null => {}
|
||||
OwnedValue::Integer(i) => {
|
||||
Value::Null => {}
|
||||
Value::Integer(i) => {
|
||||
let serial_type = SerialType::from(value);
|
||||
match serial_type.kind() {
|
||||
SerialTypeKind::I8 => buf.extend_from_slice(&(*i as i8).to_be_bytes()),
|
||||
@@ -1332,9 +1332,9 @@ impl Record {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
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),
|
||||
Value::Float(f) => buf.extend_from_slice(&f.to_be_bytes()),
|
||||
Value::Text(t) => buf.extend_from_slice(&t.value),
|
||||
Value::Blob(b) => buf.extend_from_slice(b),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1475,7 +1475,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_serialize_null() {
|
||||
let record = Record::new(vec![OwnedValue::Null]);
|
||||
let record = Record::new(vec![Value::Null]);
|
||||
let mut buf = Vec::new();
|
||||
record.serialize(&mut buf);
|
||||
|
||||
@@ -1492,12 +1492,12 @@ mod tests {
|
||||
#[test]
|
||||
fn test_serialize_integers() {
|
||||
let record = Record::new(vec![
|
||||
OwnedValue::Integer(42), // Should use SERIAL_TYPE_I8
|
||||
OwnedValue::Integer(1000), // Should use SERIAL_TYPE_I16
|
||||
OwnedValue::Integer(1_000_000), // Should use SERIAL_TYPE_I24
|
||||
OwnedValue::Integer(1_000_000_000), // Should use SERIAL_TYPE_I32
|
||||
OwnedValue::Integer(1_000_000_000_000), // Should use SERIAL_TYPE_I48
|
||||
OwnedValue::Integer(i64::MAX), // Should use SERIAL_TYPE_I64
|
||||
Value::Integer(42), // Should use SERIAL_TYPE_I8
|
||||
Value::Integer(1000), // Should use SERIAL_TYPE_I16
|
||||
Value::Integer(1_000_000), // Should use SERIAL_TYPE_I24
|
||||
Value::Integer(1_000_000_000), // Should use SERIAL_TYPE_I32
|
||||
Value::Integer(1_000_000_000_000), // Should use SERIAL_TYPE_I48
|
||||
Value::Integer(i64::MAX), // Should use SERIAL_TYPE_I64
|
||||
]);
|
||||
let mut buf = Vec::new();
|
||||
record.serialize(&mut buf);
|
||||
@@ -1567,7 +1567,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_serialize_float() {
|
||||
#[warn(clippy::approx_constant)]
|
||||
let record = Record::new(vec![OwnedValue::Float(3.15555)]);
|
||||
let record = Record::new(vec![Value::Float(3.15555)]);
|
||||
let mut buf = Vec::new();
|
||||
record.serialize(&mut buf);
|
||||
|
||||
@@ -1588,7 +1588,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_serialize_text() {
|
||||
let text = "hello";
|
||||
let record = Record::new(vec![OwnedValue::Text(Text::new(text))]);
|
||||
let record = Record::new(vec![Value::Text(Text::new(text))]);
|
||||
let mut buf = Vec::new();
|
||||
record.serialize(&mut buf);
|
||||
|
||||
@@ -1607,7 +1607,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_serialize_blob() {
|
||||
let blob = vec![1, 2, 3, 4, 5];
|
||||
let record = Record::new(vec![OwnedValue::Blob(blob.clone())]);
|
||||
let record = Record::new(vec![Value::Blob(blob.clone())]);
|
||||
let mut buf = Vec::new();
|
||||
record.serialize(&mut buf);
|
||||
|
||||
@@ -1627,10 +1627,10 @@ mod tests {
|
||||
fn test_serialize_mixed_types() {
|
||||
let text = "test";
|
||||
let record = Record::new(vec![
|
||||
OwnedValue::Null,
|
||||
OwnedValue::Integer(42),
|
||||
OwnedValue::Float(3.15),
|
||||
OwnedValue::Text(Text::new(text)),
|
||||
Value::Null,
|
||||
Value::Integer(42),
|
||||
Value::Float(3.15),
|
||||
Value::Text(Text::new(text)),
|
||||
]);
|
||||
let mut buf = Vec::new();
|
||||
record.serialize(&mut buf);
|
||||
|
||||
340
core/util.rs
340
core/util.rs
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
function::Func,
|
||||
schema::{self, Column, Schema, Type},
|
||||
types::{OwnedValue, OwnedValueType},
|
||||
types::{Value, ValueType},
|
||||
LimboError, OpenFlags, Result, Statement, StepResult, SymbolTable, IO,
|
||||
};
|
||||
use limbo_sqlite3_parser::ast::{self, CreateTableBody, Expr, FunctionTail, Literal};
|
||||
@@ -827,13 +827,13 @@ pub fn decode_percent(uri: &str) -> String {
|
||||
/// When casting to INTEGER, if the text looks like a floating point value with an exponent, the exponent will be ignored
|
||||
/// because it is no part of the integer prefix. For example, "CAST('123e+5' AS INTEGER)" results in 123, not in 12300000.
|
||||
/// The CAST operator understands decimal integers only — conversion of hexadecimal integers stops at the "x" in the "0x" prefix of the hexadecimal integer string and thus result of the CAST is always zero.
|
||||
pub fn cast_text_to_integer(text: &str) -> OwnedValue {
|
||||
pub fn cast_text_to_integer(text: &str) -> Value {
|
||||
let text = text.trim();
|
||||
if text.is_empty() {
|
||||
return OwnedValue::Integer(0);
|
||||
return Value::Integer(0);
|
||||
}
|
||||
if let Ok(i) = text.parse::<i64>() {
|
||||
return OwnedValue::Integer(i);
|
||||
return Value::Integer(i);
|
||||
}
|
||||
let bytes = text.as_bytes();
|
||||
let mut end = 0;
|
||||
@@ -845,23 +845,22 @@ pub fn cast_text_to_integer(text: &str) -> OwnedValue {
|
||||
}
|
||||
text[..end]
|
||||
.parse::<i64>()
|
||||
.map_or(OwnedValue::Integer(0), OwnedValue::Integer)
|
||||
.map_or(Value::Integer(0), Value::Integer)
|
||||
}
|
||||
|
||||
/// When casting a TEXT value to REAL, the longest possible prefix of the value that can be interpreted
|
||||
/// as a real number is extracted from the TEXT value and the remainder ignored. Any leading spaces in
|
||||
/// the TEXT value are ignored when converging from TEXT to REAL.
|
||||
/// If there is no prefix that can be interpreted as a real number, the result of the conversion is 0.0.
|
||||
pub fn cast_text_to_real(text: &str) -> OwnedValue {
|
||||
pub fn cast_text_to_real(text: &str) -> Value {
|
||||
let trimmed = text.trim();
|
||||
if trimmed.is_empty() {
|
||||
return OwnedValue::Float(0.0);
|
||||
return Value::Float(0.0);
|
||||
}
|
||||
let Ok((_, text)) = parse_numeric_str(trimmed) else {
|
||||
return OwnedValue::Float(0.0);
|
||||
return Value::Float(0.0);
|
||||
};
|
||||
text.parse::<f64>()
|
||||
.map_or(OwnedValue::Float(0.0), OwnedValue::Float)
|
||||
text.parse::<f64>().map_or(Value::Float(0.0), Value::Float)
|
||||
}
|
||||
|
||||
/// NUMERIC Casting a TEXT or BLOB value into NUMERIC yields either an INTEGER or a REAL result.
|
||||
@@ -874,14 +873,14 @@ pub fn cast_text_to_real(text: &str) -> OwnedValue {
|
||||
/// IEEE 754 64-bit float and thus provides a 1-bit of margin for the text-to-float conversion operation.)
|
||||
/// Any text input that describes a value outside the range of a 64-bit signed integer yields a REAL result.
|
||||
/// Casting a REAL or INTEGER value to NUMERIC is a no-op, even if a real value could be losslessly converted to an integer.
|
||||
pub fn checked_cast_text_to_numeric(text: &str) -> std::result::Result<OwnedValue, ()> {
|
||||
pub fn checked_cast_text_to_numeric(text: &str) -> std::result::Result<Value, ()> {
|
||||
// sqlite will parse the first N digits of a string to numeric value, then determine
|
||||
// whether _that_ value is more likely a real or integer value. e.g.
|
||||
// '-100234-2344.23e14' evaluates to -100234 instead of -100234.0
|
||||
let (kind, text) = parse_numeric_str(text)?;
|
||||
match kind {
|
||||
OwnedValueType::Integer => match text.parse::<i64>() {
|
||||
Ok(i) => Ok(OwnedValue::Integer(i)),
|
||||
ValueType::Integer => match text.parse::<i64>() {
|
||||
Ok(i) => Ok(Value::Integer(i)),
|
||||
Err(e) => {
|
||||
if matches!(
|
||||
e.kind(),
|
||||
@@ -891,20 +890,18 @@ pub fn checked_cast_text_to_numeric(text: &str) -> std::result::Result<OwnedValu
|
||||
// we have to match sqlite exactly here, so we match sqlite3AtoF
|
||||
let value = text.parse::<f64>().unwrap_or_default();
|
||||
let factor = 10f64.powi(15 - value.abs().log10().ceil() as i32);
|
||||
Ok(OwnedValue::Float((value * factor).round() / factor))
|
||||
Ok(Value::Float((value * factor).round() / factor))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
},
|
||||
OwnedValueType::Float => Ok(text
|
||||
.parse::<f64>()
|
||||
.map_or(OwnedValue::Float(0.0), OwnedValue::Float)),
|
||||
ValueType::Float => Ok(text.parse::<f64>().map_or(Value::Float(0.0), Value::Float)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_numeric_str(text: &str) -> Result<(OwnedValueType, &str), ()> {
|
||||
fn parse_numeric_str(text: &str) -> Result<(ValueType, &str), ()> {
|
||||
let text = text.trim();
|
||||
let bytes = text.as_bytes();
|
||||
|
||||
@@ -945,23 +942,23 @@ fn parse_numeric_str(text: &str) -> Result<(OwnedValueType, &str), ()> {
|
||||
// edge case: if it ends with exponent, strip and cast valid digits as float
|
||||
let last = bytes[end - 1];
|
||||
if last.eq_ignore_ascii_case(&b'e') {
|
||||
return Ok((OwnedValueType::Float, &text[0..end - 1]));
|
||||
return Ok((ValueType::Float, &text[0..end - 1]));
|
||||
// edge case: ends with extponent / sign
|
||||
} else if has_exponent && (last == b'-' || last == b'+') {
|
||||
return Ok((OwnedValueType::Float, &text[0..end - 2]));
|
||||
return Ok((ValueType::Float, &text[0..end - 2]));
|
||||
}
|
||||
Ok((
|
||||
if !has_decimal && !has_exponent {
|
||||
OwnedValueType::Integer
|
||||
ValueType::Integer
|
||||
} else {
|
||||
OwnedValueType::Float
|
||||
ValueType::Float
|
||||
},
|
||||
&text[..end],
|
||||
))
|
||||
}
|
||||
|
||||
pub fn cast_text_to_numeric(txt: &str) -> OwnedValue {
|
||||
checked_cast_text_to_numeric(txt).unwrap_or(OwnedValue::Integer(0))
|
||||
pub fn cast_text_to_numeric(txt: &str) -> Value {
|
||||
checked_cast_text_to_numeric(txt).unwrap_or(Value::Integer(0))
|
||||
}
|
||||
|
||||
// Check if float can be losslessly converted to 51-bit integer
|
||||
@@ -974,27 +971,27 @@ pub fn cast_real_to_integer(float: f64) -> std::result::Result<i64, ()> {
|
||||
}
|
||||
|
||||
// we don't need to verify the numeric literal here, as it is already verified by the parser
|
||||
pub fn parse_numeric_literal(text: &str) -> Result<OwnedValue> {
|
||||
pub fn parse_numeric_literal(text: &str) -> Result<Value> {
|
||||
// a single extra underscore ("_") character can exist between any two digits
|
||||
let text = text.replace("_", "");
|
||||
|
||||
if text.starts_with("0x") || text.starts_with("0X") {
|
||||
let value = u64::from_str_radix(&text[2..], 16)? as i64;
|
||||
return Ok(OwnedValue::Integer(value));
|
||||
return Ok(Value::Integer(value));
|
||||
} else if text.starts_with("-0x") || text.starts_with("-0X") {
|
||||
let value = u64::from_str_radix(&text[3..], 16)? as i64;
|
||||
if value == i64::MIN {
|
||||
return Err(LimboError::IntegerOverflow);
|
||||
}
|
||||
return Ok(OwnedValue::Integer(-value));
|
||||
return Ok(Value::Integer(-value));
|
||||
}
|
||||
|
||||
if let Ok(int_value) = text.parse::<i64>() {
|
||||
return Ok(OwnedValue::Integer(int_value));
|
||||
return Ok(Value::Integer(int_value));
|
||||
}
|
||||
|
||||
let float_value = text.parse::<f64>()?;
|
||||
Ok(OwnedValue::Float(float_value))
|
||||
Ok(Value::Float(float_value))
|
||||
}
|
||||
|
||||
// for TVF's we need these at planning time so we cannot emit translate_expr
|
||||
@@ -1597,178 +1594,151 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_text_to_integer() {
|
||||
assert_eq!(cast_text_to_integer("1"), OwnedValue::Integer(1),);
|
||||
assert_eq!(cast_text_to_integer("-1"), OwnedValue::Integer(-1),);
|
||||
assert_eq!(cast_text_to_integer("1"), Value::Integer(1),);
|
||||
assert_eq!(cast_text_to_integer("-1"), Value::Integer(-1),);
|
||||
assert_eq!(
|
||||
cast_text_to_integer("1823400-00000"),
|
||||
OwnedValue::Integer(1823400),
|
||||
Value::Integer(1823400),
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_integer("-10000000"),
|
||||
OwnedValue::Integer(-10000000),
|
||||
);
|
||||
assert_eq!(cast_text_to_integer("123xxx"), OwnedValue::Integer(123),);
|
||||
assert_eq!(cast_text_to_integer("-10000000"), Value::Integer(-10000000),);
|
||||
assert_eq!(cast_text_to_integer("123xxx"), Value::Integer(123),);
|
||||
assert_eq!(
|
||||
cast_text_to_integer("9223372036854775807"),
|
||||
OwnedValue::Integer(i64::MAX),
|
||||
Value::Integer(i64::MAX),
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_integer("9223372036854775808"),
|
||||
OwnedValue::Integer(0),
|
||||
Value::Integer(0),
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_integer("-9223372036854775808"),
|
||||
OwnedValue::Integer(i64::MIN),
|
||||
Value::Integer(i64::MIN),
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_integer("-9223372036854775809"),
|
||||
OwnedValue::Integer(0),
|
||||
Value::Integer(0),
|
||||
);
|
||||
assert_eq!(cast_text_to_integer("-"), OwnedValue::Integer(0),);
|
||||
assert_eq!(cast_text_to_integer("-"), Value::Integer(0),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_text_to_real() {
|
||||
assert_eq!(cast_text_to_real("1"), OwnedValue::Float(1.0));
|
||||
assert_eq!(cast_text_to_real("-1"), OwnedValue::Float(-1.0));
|
||||
assert_eq!(cast_text_to_real("1.0"), OwnedValue::Float(1.0));
|
||||
assert_eq!(cast_text_to_real("-1.0"), OwnedValue::Float(-1.0));
|
||||
assert_eq!(cast_text_to_real("1e10"), OwnedValue::Float(1e10));
|
||||
assert_eq!(cast_text_to_real("-1e10"), OwnedValue::Float(-1e10));
|
||||
assert_eq!(cast_text_to_real("1e-10"), OwnedValue::Float(1e-10));
|
||||
assert_eq!(cast_text_to_real("-1e-10"), OwnedValue::Float(-1e-10));
|
||||
assert_eq!(cast_text_to_real("1.123e10"), OwnedValue::Float(1.123e10));
|
||||
assert_eq!(cast_text_to_real("-1.123e10"), OwnedValue::Float(-1.123e10));
|
||||
assert_eq!(cast_text_to_real("1.123e-10"), OwnedValue::Float(1.123e-10));
|
||||
assert_eq!(cast_text_to_real("-1.123-e-10"), OwnedValue::Float(-1.123));
|
||||
assert_eq!(cast_text_to_real("1-282584294928"), OwnedValue::Float(1.0));
|
||||
assert_eq!(cast_text_to_real("1"), Value::Float(1.0));
|
||||
assert_eq!(cast_text_to_real("-1"), Value::Float(-1.0));
|
||||
assert_eq!(cast_text_to_real("1.0"), Value::Float(1.0));
|
||||
assert_eq!(cast_text_to_real("-1.0"), Value::Float(-1.0));
|
||||
assert_eq!(cast_text_to_real("1e10"), Value::Float(1e10));
|
||||
assert_eq!(cast_text_to_real("-1e10"), Value::Float(-1e10));
|
||||
assert_eq!(cast_text_to_real("1e-10"), Value::Float(1e-10));
|
||||
assert_eq!(cast_text_to_real("-1e-10"), Value::Float(-1e-10));
|
||||
assert_eq!(cast_text_to_real("1.123e10"), Value::Float(1.123e10));
|
||||
assert_eq!(cast_text_to_real("-1.123e10"), Value::Float(-1.123e10));
|
||||
assert_eq!(cast_text_to_real("1.123e-10"), Value::Float(1.123e-10));
|
||||
assert_eq!(cast_text_to_real("-1.123-e-10"), Value::Float(-1.123));
|
||||
assert_eq!(cast_text_to_real("1-282584294928"), Value::Float(1.0));
|
||||
assert_eq!(
|
||||
cast_text_to_real("1.7976931348623157e309"),
|
||||
OwnedValue::Float(f64::INFINITY),
|
||||
Value::Float(f64::INFINITY),
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_real("-1.7976931348623157e308"),
|
||||
OwnedValue::Float(f64::MIN),
|
||||
Value::Float(f64::MIN),
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_real("-1.7976931348623157e309"),
|
||||
OwnedValue::Float(f64::NEG_INFINITY),
|
||||
Value::Float(f64::NEG_INFINITY),
|
||||
);
|
||||
assert_eq!(cast_text_to_real("1E"), OwnedValue::Float(1.0));
|
||||
assert_eq!(cast_text_to_real("1EE"), OwnedValue::Float(1.0));
|
||||
assert_eq!(cast_text_to_real("-1E"), OwnedValue::Float(-1.0));
|
||||
assert_eq!(cast_text_to_real("1."), OwnedValue::Float(1.0));
|
||||
assert_eq!(cast_text_to_real("-1."), OwnedValue::Float(-1.0));
|
||||
assert_eq!(cast_text_to_real("1.23E"), OwnedValue::Float(1.23));
|
||||
assert_eq!(cast_text_to_real(".1.23E-"), OwnedValue::Float(0.1));
|
||||
assert_eq!(cast_text_to_real("0"), OwnedValue::Float(0.0));
|
||||
assert_eq!(cast_text_to_real("-0"), OwnedValue::Float(0.0));
|
||||
assert_eq!(cast_text_to_real("-0"), OwnedValue::Float(0.0));
|
||||
assert_eq!(cast_text_to_real("-0.0"), OwnedValue::Float(0.0));
|
||||
assert_eq!(cast_text_to_real("0.0"), OwnedValue::Float(0.0));
|
||||
assert_eq!(cast_text_to_real("-"), OwnedValue::Float(0.0));
|
||||
assert_eq!(cast_text_to_real("1E"), Value::Float(1.0));
|
||||
assert_eq!(cast_text_to_real("1EE"), Value::Float(1.0));
|
||||
assert_eq!(cast_text_to_real("-1E"), Value::Float(-1.0));
|
||||
assert_eq!(cast_text_to_real("1."), Value::Float(1.0));
|
||||
assert_eq!(cast_text_to_real("-1."), Value::Float(-1.0));
|
||||
assert_eq!(cast_text_to_real("1.23E"), Value::Float(1.23));
|
||||
assert_eq!(cast_text_to_real(".1.23E-"), Value::Float(0.1));
|
||||
assert_eq!(cast_text_to_real("0"), Value::Float(0.0));
|
||||
assert_eq!(cast_text_to_real("-0"), Value::Float(0.0));
|
||||
assert_eq!(cast_text_to_real("-0"), Value::Float(0.0));
|
||||
assert_eq!(cast_text_to_real("-0.0"), Value::Float(0.0));
|
||||
assert_eq!(cast_text_to_real("0.0"), Value::Float(0.0));
|
||||
assert_eq!(cast_text_to_real("-"), Value::Float(0.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_text_to_numeric() {
|
||||
assert_eq!(cast_text_to_numeric("1"), OwnedValue::Integer(1));
|
||||
assert_eq!(cast_text_to_numeric("-1"), OwnedValue::Integer(-1));
|
||||
assert_eq!(cast_text_to_numeric("1"), Value::Integer(1));
|
||||
assert_eq!(cast_text_to_numeric("-1"), Value::Integer(-1));
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("1823400-00000"),
|
||||
OwnedValue::Integer(1823400)
|
||||
Value::Integer(1823400)
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("-10000000"),
|
||||
OwnedValue::Integer(-10000000)
|
||||
);
|
||||
assert_eq!(cast_text_to_numeric("123xxx"), OwnedValue::Integer(123));
|
||||
assert_eq!(cast_text_to_numeric("-10000000"), Value::Integer(-10000000));
|
||||
assert_eq!(cast_text_to_numeric("123xxx"), Value::Integer(123));
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("9223372036854775807"),
|
||||
OwnedValue::Integer(i64::MAX)
|
||||
Value::Integer(i64::MAX)
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("9223372036854775808"),
|
||||
OwnedValue::Float(9.22337203685478e18)
|
||||
Value::Float(9.22337203685478e18)
|
||||
); // Exceeds i64, becomes float
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("-9223372036854775808"),
|
||||
OwnedValue::Integer(i64::MIN)
|
||||
Value::Integer(i64::MIN)
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("-9223372036854775809"),
|
||||
OwnedValue::Float(-9.22337203685478e18)
|
||||
Value::Float(-9.22337203685478e18)
|
||||
); // Exceeds i64, becomes float
|
||||
|
||||
assert_eq!(cast_text_to_numeric("1.0"), OwnedValue::Float(1.0));
|
||||
assert_eq!(cast_text_to_numeric("-1.0"), OwnedValue::Float(-1.0));
|
||||
assert_eq!(cast_text_to_numeric("1e10"), OwnedValue::Float(1e10));
|
||||
assert_eq!(cast_text_to_numeric("-1e10"), OwnedValue::Float(-1e10));
|
||||
assert_eq!(cast_text_to_numeric("1e-10"), OwnedValue::Float(1e-10));
|
||||
assert_eq!(cast_text_to_numeric("-1e-10"), OwnedValue::Float(-1e-10));
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("1.123e10"),
|
||||
OwnedValue::Float(1.123e10)
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("-1.123e10"),
|
||||
OwnedValue::Float(-1.123e10)
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("1.123e-10"),
|
||||
OwnedValue::Float(1.123e-10)
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("-1.123-e-10"),
|
||||
OwnedValue::Float(-1.123)
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("1-282584294928"),
|
||||
OwnedValue::Integer(1)
|
||||
);
|
||||
assert_eq!(cast_text_to_numeric("xxx"), OwnedValue::Integer(0));
|
||||
assert_eq!(cast_text_to_numeric("1.0"), Value::Float(1.0));
|
||||
assert_eq!(cast_text_to_numeric("-1.0"), Value::Float(-1.0));
|
||||
assert_eq!(cast_text_to_numeric("1e10"), Value::Float(1e10));
|
||||
assert_eq!(cast_text_to_numeric("-1e10"), Value::Float(-1e10));
|
||||
assert_eq!(cast_text_to_numeric("1e-10"), Value::Float(1e-10));
|
||||
assert_eq!(cast_text_to_numeric("-1e-10"), Value::Float(-1e-10));
|
||||
assert_eq!(cast_text_to_numeric("1.123e10"), Value::Float(1.123e10));
|
||||
assert_eq!(cast_text_to_numeric("-1.123e10"), Value::Float(-1.123e10));
|
||||
assert_eq!(cast_text_to_numeric("1.123e-10"), Value::Float(1.123e-10));
|
||||
assert_eq!(cast_text_to_numeric("-1.123-e-10"), Value::Float(-1.123));
|
||||
assert_eq!(cast_text_to_numeric("1-282584294928"), Value::Integer(1));
|
||||
assert_eq!(cast_text_to_numeric("xxx"), Value::Integer(0));
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("1.7976931348623157e309"),
|
||||
OwnedValue::Float(f64::INFINITY)
|
||||
Value::Float(f64::INFINITY)
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("-1.7976931348623157e308"),
|
||||
OwnedValue::Float(f64::MIN)
|
||||
Value::Float(f64::MIN)
|
||||
);
|
||||
assert_eq!(
|
||||
cast_text_to_numeric("-1.7976931348623157e309"),
|
||||
OwnedValue::Float(f64::NEG_INFINITY)
|
||||
Value::Float(f64::NEG_INFINITY)
|
||||
);
|
||||
|
||||
assert_eq!(cast_text_to_numeric("1E"), OwnedValue::Float(1.0));
|
||||
assert_eq!(cast_text_to_numeric("1EE"), OwnedValue::Float(1.0));
|
||||
assert_eq!(cast_text_to_numeric("-1E"), OwnedValue::Float(-1.0));
|
||||
assert_eq!(cast_text_to_numeric("1."), OwnedValue::Float(1.0));
|
||||
assert_eq!(cast_text_to_numeric("-1."), OwnedValue::Float(-1.0));
|
||||
assert_eq!(cast_text_to_numeric("1.23E"), OwnedValue::Float(1.23));
|
||||
assert_eq!(cast_text_to_numeric("1.23E-"), OwnedValue::Float(1.23));
|
||||
assert_eq!(cast_text_to_numeric("1E"), Value::Float(1.0));
|
||||
assert_eq!(cast_text_to_numeric("1EE"), Value::Float(1.0));
|
||||
assert_eq!(cast_text_to_numeric("-1E"), Value::Float(-1.0));
|
||||
assert_eq!(cast_text_to_numeric("1."), Value::Float(1.0));
|
||||
assert_eq!(cast_text_to_numeric("-1."), Value::Float(-1.0));
|
||||
assert_eq!(cast_text_to_numeric("1.23E"), Value::Float(1.23));
|
||||
assert_eq!(cast_text_to_numeric("1.23E-"), Value::Float(1.23));
|
||||
|
||||
assert_eq!(cast_text_to_numeric("0"), OwnedValue::Integer(0));
|
||||
assert_eq!(cast_text_to_numeric("-0"), OwnedValue::Integer(0));
|
||||
assert_eq!(cast_text_to_numeric("-0.0"), OwnedValue::Float(0.0));
|
||||
assert_eq!(cast_text_to_numeric("0.0"), OwnedValue::Float(0.0));
|
||||
assert_eq!(cast_text_to_numeric("-"), OwnedValue::Integer(0));
|
||||
assert_eq!(cast_text_to_numeric("-e"), OwnedValue::Integer(0));
|
||||
assert_eq!(cast_text_to_numeric("-E"), OwnedValue::Integer(0));
|
||||
assert_eq!(cast_text_to_numeric("0"), Value::Integer(0));
|
||||
assert_eq!(cast_text_to_numeric("-0"), Value::Integer(0));
|
||||
assert_eq!(cast_text_to_numeric("-0.0"), Value::Float(0.0));
|
||||
assert_eq!(cast_text_to_numeric("0.0"), Value::Float(0.0));
|
||||
assert_eq!(cast_text_to_numeric("-"), Value::Integer(0));
|
||||
assert_eq!(cast_text_to_numeric("-e"), Value::Integer(0));
|
||||
assert_eq!(cast_text_to_numeric("-E"), Value::Integer(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_numeric_str_valid_integer() {
|
||||
assert_eq!(
|
||||
parse_numeric_str("123"),
|
||||
Ok((OwnedValueType::Integer, "123"))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_str("-456"),
|
||||
Ok((OwnedValueType::Integer, "-456"))
|
||||
);
|
||||
assert_eq!(parse_numeric_str("123"), Ok((ValueType::Integer, "123")));
|
||||
assert_eq!(parse_numeric_str("-456"), Ok((ValueType::Integer, "-456")));
|
||||
assert_eq!(
|
||||
parse_numeric_str("000789"),
|
||||
Ok((OwnedValueType::Integer, "000789"))
|
||||
Ok((ValueType::Integer, "000789"))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1776,37 +1746,31 @@ pub mod tests {
|
||||
fn test_parse_numeric_str_valid_float() {
|
||||
assert_eq!(
|
||||
parse_numeric_str("123.456"),
|
||||
Ok((OwnedValueType::Float, "123.456"))
|
||||
Ok((ValueType::Float, "123.456"))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_str("-0.789"),
|
||||
Ok((OwnedValueType::Float, "-0.789"))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_str("1e10"),
|
||||
Ok((OwnedValueType::Float, "1e10"))
|
||||
Ok((ValueType::Float, "-0.789"))
|
||||
);
|
||||
assert_eq!(parse_numeric_str("1e10"), Ok((ValueType::Float, "1e10")));
|
||||
assert_eq!(
|
||||
parse_numeric_str("-1.23e-4"),
|
||||
Ok((OwnedValueType::Float, "-1.23e-4"))
|
||||
Ok((ValueType::Float, "-1.23e-4"))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_str("1.23E+4"),
|
||||
Ok((OwnedValueType::Float, "1.23E+4"))
|
||||
Ok((ValueType::Float, "1.23E+4"))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_str("1.2.3"),
|
||||
Ok((OwnedValueType::Float, "1.2"))
|
||||
)
|
||||
assert_eq!(parse_numeric_str("1.2.3"), Ok((ValueType::Float, "1.2")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_numeric_str_edge_cases() {
|
||||
assert_eq!(parse_numeric_str("1e"), Ok((OwnedValueType::Float, "1")));
|
||||
assert_eq!(parse_numeric_str("1e-"), Ok((OwnedValueType::Float, "1")));
|
||||
assert_eq!(parse_numeric_str("1e+"), Ok((OwnedValueType::Float, "1")));
|
||||
assert_eq!(parse_numeric_str("-1e"), Ok((OwnedValueType::Float, "-1")));
|
||||
assert_eq!(parse_numeric_str("-1e-"), Ok((OwnedValueType::Float, "-1")));
|
||||
assert_eq!(parse_numeric_str("1e"), Ok((ValueType::Float, "1")));
|
||||
assert_eq!(parse_numeric_str("1e-"), Ok((ValueType::Float, "1")));
|
||||
assert_eq!(parse_numeric_str("1e+"), Ok((ValueType::Float, "1")));
|
||||
assert_eq!(parse_numeric_str("-1e"), Ok((ValueType::Float, "-1")));
|
||||
assert_eq!(parse_numeric_str("-1e-"), Ok((ValueType::Float, "-1")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1820,17 +1784,14 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_numeric_str_with_whitespace() {
|
||||
assert_eq!(
|
||||
parse_numeric_str(" 123"),
|
||||
Ok((OwnedValueType::Integer, "123"))
|
||||
);
|
||||
assert_eq!(parse_numeric_str(" 123"), Ok((ValueType::Integer, "123")));
|
||||
assert_eq!(
|
||||
parse_numeric_str(" -456.78 "),
|
||||
Ok((OwnedValueType::Float, "-456.78"))
|
||||
Ok((ValueType::Float, "-456.78"))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_str(" 1.23e4 "),
|
||||
Ok((OwnedValueType::Float, "1.23e4"))
|
||||
Ok((ValueType::Float, "1.23e4"))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1838,31 +1799,28 @@ pub mod tests {
|
||||
fn test_parse_numeric_str_leading_zeros() {
|
||||
assert_eq!(
|
||||
parse_numeric_str("000123"),
|
||||
Ok((OwnedValueType::Integer, "000123"))
|
||||
Ok((ValueType::Integer, "000123"))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_str("000.456"),
|
||||
Ok((OwnedValueType::Float, "000.456"))
|
||||
Ok((ValueType::Float, "000.456"))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_str("0001e3"),
|
||||
Ok((OwnedValueType::Float, "0001e3"))
|
||||
Ok((ValueType::Float, "0001e3"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_numeric_str_trailing_characters() {
|
||||
assert_eq!(
|
||||
parse_numeric_str("123abc"),
|
||||
Ok((OwnedValueType::Integer, "123"))
|
||||
);
|
||||
assert_eq!(parse_numeric_str("123abc"), Ok((ValueType::Integer, "123")));
|
||||
assert_eq!(
|
||||
parse_numeric_str("456.78xyz"),
|
||||
Ok((OwnedValueType::Float, "456.78"))
|
||||
Ok((ValueType::Float, "456.78"))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_str("1.23e4extra"),
|
||||
Ok((OwnedValueType::Float, "1.23e4"))
|
||||
Ok((ValueType::Float, "1.23e4"))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1954,32 +1912,32 @@ pub mod tests {
|
||||
fn test_parse_numeric_literal_hex() {
|
||||
assert_eq!(
|
||||
parse_numeric_literal("0x1234").unwrap(),
|
||||
OwnedValue::Integer(4660)
|
||||
Value::Integer(4660)
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_literal("0xFFFFFFFF").unwrap(),
|
||||
OwnedValue::Integer(4294967295)
|
||||
Value::Integer(4294967295)
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_literal("0x7FFFFFFF").unwrap(),
|
||||
OwnedValue::Integer(2147483647)
|
||||
Value::Integer(2147483647)
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_literal("0x7FFFFFFFFFFFFFFF").unwrap(),
|
||||
OwnedValue::Integer(9223372036854775807)
|
||||
Value::Integer(9223372036854775807)
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_literal("0xFFFFFFFFFFFFFFFF").unwrap(),
|
||||
OwnedValue::Integer(-1)
|
||||
Value::Integer(-1)
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_literal("0x8000000000000000").unwrap(),
|
||||
OwnedValue::Integer(-9223372036854775808)
|
||||
Value::Integer(-9223372036854775808)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
parse_numeric_literal("-0x1234").unwrap(),
|
||||
OwnedValue::Integer(-4660)
|
||||
Value::Integer(-4660)
|
||||
);
|
||||
// too big hex
|
||||
assert!(parse_numeric_literal("-0x8000000000000000").is_err());
|
||||
@@ -1987,13 +1945,10 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_numeric_literal_integer() {
|
||||
assert_eq!(
|
||||
parse_numeric_literal("123").unwrap(),
|
||||
OwnedValue::Integer(123)
|
||||
);
|
||||
assert_eq!(parse_numeric_literal("123").unwrap(), Value::Integer(123));
|
||||
assert_eq!(
|
||||
parse_numeric_literal("9_223_372_036_854_775_807").unwrap(),
|
||||
OwnedValue::Integer(9223372036854775807)
|
||||
Value::Integer(9223372036854775807)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2001,38 +1956,29 @@ pub mod tests {
|
||||
fn test_parse_numeric_literal_float() {
|
||||
assert_eq!(
|
||||
parse_numeric_literal("123.456").unwrap(),
|
||||
OwnedValue::Float(123.456)
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_literal(".123").unwrap(),
|
||||
OwnedValue::Float(0.123)
|
||||
Value::Float(123.456)
|
||||
);
|
||||
assert_eq!(parse_numeric_literal(".123").unwrap(), Value::Float(0.123));
|
||||
assert_eq!(
|
||||
parse_numeric_literal("1.23e10").unwrap(),
|
||||
OwnedValue::Float(1.23e10)
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_literal("1e-10").unwrap(),
|
||||
OwnedValue::Float(1e-10)
|
||||
Value::Float(1.23e10)
|
||||
);
|
||||
assert_eq!(parse_numeric_literal("1e-10").unwrap(), Value::Float(1e-10));
|
||||
assert_eq!(
|
||||
parse_numeric_literal("1.23E+10").unwrap(),
|
||||
OwnedValue::Float(1.23e10)
|
||||
);
|
||||
assert_eq!(
|
||||
parse_numeric_literal("1.1_1").unwrap(),
|
||||
OwnedValue::Float(1.11)
|
||||
Value::Float(1.23e10)
|
||||
);
|
||||
assert_eq!(parse_numeric_literal("1.1_1").unwrap(), Value::Float(1.11));
|
||||
|
||||
// > i64::MAX, convert to float
|
||||
assert_eq!(
|
||||
parse_numeric_literal("9223372036854775808").unwrap(),
|
||||
OwnedValue::Float(9.223372036854775808e+18)
|
||||
Value::Float(9.223372036854775808e+18)
|
||||
);
|
||||
// < i64::MIN, convert to float
|
||||
assert_eq!(
|
||||
parse_numeric_literal("-9223372036854775809").unwrap(),
|
||||
OwnedValue::Float(-9.223372036854775809e+18)
|
||||
Value::Float(-9.223372036854775809e+18)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
2305
core/vdbe/execute.rs
2305
core/vdbe/execute.rs
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@ use limbo_sqlite3_parser::ast::SortOrder;
|
||||
|
||||
use crate::vdbe::{builder::CursorType, insn::RegisterOrLiteral};
|
||||
|
||||
use super::{Insn, InsnReference, OwnedValue, Program};
|
||||
use super::{Insn, InsnReference, Program, Value};
|
||||
use crate::function::{Func, ScalarFunc};
|
||||
|
||||
pub fn insn_to_str(
|
||||
@@ -12,14 +12,14 @@ pub fn insn_to_str(
|
||||
indent: String,
|
||||
manual_comment: Option<&'static str>,
|
||||
) -> String {
|
||||
let (opcode, p1, p2, p3, p4, p5, comment): (&str, i32, i32, i32, OwnedValue, u16, String) =
|
||||
let (opcode, p1, p2, p3, p4, p5, comment): (&str, i32, i32, i32, Value, u16, String) =
|
||||
match insn {
|
||||
Insn::Init { target_pc } => (
|
||||
"Init",
|
||||
0,
|
||||
target_pc.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("Start at {}", target_pc.to_debug_int()),
|
||||
),
|
||||
@@ -28,7 +28,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=r[{}]+r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -37,7 +37,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=r[{}]-r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -46,7 +46,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=r[{}]*r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -55,7 +55,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=r[{}]/r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -64,7 +64,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=r[{}]&r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -73,7 +73,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=r[{}]|r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -82,7 +82,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=~r[{}]", dest, reg),
|
||||
),
|
||||
@@ -95,7 +95,7 @@ pub fn insn_to_str(
|
||||
*database as i32,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=~r[{}]", dest, database),
|
||||
),
|
||||
@@ -104,7 +104,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=r[{}]%r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -113,7 +113,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*dest as i32,
|
||||
dest_end.map_or(0, |end| end as i32),
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
dest_end.map_or(format!("r[{}]=NULL", dest), |end| {
|
||||
format!("r[{}..{}]=NULL", dest, end)
|
||||
@@ -124,7 +124,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("Set cursor {} to a (pseudo) NULL row", cursor_id),
|
||||
),
|
||||
@@ -133,7 +133,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
target_pc.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]!=NULL -> goto {}", reg, target_pc.to_debug_int()),
|
||||
),
|
||||
@@ -146,7 +146,7 @@ pub fn insn_to_str(
|
||||
*start_reg_a as i32,
|
||||
*start_reg_b as i32,
|
||||
*count as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"r[{}..{}]==r[{}..{}]",
|
||||
@@ -165,7 +165,7 @@ pub fn insn_to_str(
|
||||
target_pc_lt.to_debug_int(),
|
||||
target_pc_eq.to_debug_int(),
|
||||
target_pc_gt.to_debug_int(),
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -178,7 +178,7 @@ pub fn insn_to_str(
|
||||
*source_reg as i32,
|
||||
*dest_reg as i32,
|
||||
*count as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"r[{}..{}]=r[{}..{}]",
|
||||
@@ -197,7 +197,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
target_pc.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"r[{}]>0 -> r[{}]-={}, goto {}",
|
||||
@@ -217,7 +217,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
target_pc.to_debug_int(),
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"if r[{}]==r[{}] goto {}",
|
||||
@@ -236,7 +236,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
target_pc.to_debug_int(),
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"if r[{}]!=r[{}] goto {}",
|
||||
@@ -255,7 +255,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
target_pc.to_debug_int(),
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("if r[{}]<r[{}] goto {}", lhs, rhs, target_pc.to_debug_int()),
|
||||
),
|
||||
@@ -269,7 +269,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
target_pc.to_debug_int(),
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"if r[{}]<=r[{}] goto {}",
|
||||
@@ -288,7 +288,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
target_pc.to_debug_int(),
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("if r[{}]>r[{}] goto {}", lhs, rhs, target_pc.to_debug_int()),
|
||||
),
|
||||
@@ -302,7 +302,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
target_pc.to_debug_int(),
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"if r[{}]>=r[{}] goto {}",
|
||||
@@ -320,7 +320,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
target_pc.to_debug_int(),
|
||||
*jump_if_null as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("if r[{}] goto {}", reg, target_pc.to_debug_int()),
|
||||
),
|
||||
@@ -333,7 +333,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
target_pc.to_debug_int(),
|
||||
*jump_if_null as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("if !r[{}] goto {}", reg, target_pc.to_debug_int()),
|
||||
),
|
||||
@@ -345,7 +345,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*root_page as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"table={}, root={}",
|
||||
@@ -361,7 +361,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -374,7 +374,7 @@ pub fn insn_to_str(
|
||||
*table_name as i32,
|
||||
*module_name as i32,
|
||||
args_reg.unwrap_or(0) as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("table={}, module={}", table_name, module_name),
|
||||
),
|
||||
@@ -388,7 +388,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
pc_if_empty.to_debug_int(),
|
||||
*arg_count as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -401,7 +401,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*column as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -416,7 +416,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*arg_count as i32,
|
||||
*start_reg as i32,
|
||||
OwnedValue::build_text(&format!("vtab:{}", vtab_ptr)),
|
||||
Value::build_text(&format!("vtab:{}", vtab_ptr)),
|
||||
*conflict_action,
|
||||
format!("args=r[{}..{}]", start_reg, start_reg + arg_count - 1),
|
||||
),
|
||||
@@ -428,7 +428,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
pc_if_next.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -437,7 +437,7 @@ pub fn insn_to_str(
|
||||
*db as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(table_name),
|
||||
Value::build_text(table_name),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -450,7 +450,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*content_reg as i32,
|
||||
*num_fields as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("{} columns in r[{}]", num_fields, content_reg),
|
||||
),
|
||||
@@ -462,7 +462,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
pc_if_empty.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"Rewind {}",
|
||||
@@ -499,7 +499,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*column as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"r[{}]={}.{}",
|
||||
@@ -521,7 +521,7 @@ pub fn insn_to_str(
|
||||
*start_reg as i32,
|
||||
*count as i32,
|
||||
*check_generated as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
String::from(""),
|
||||
),
|
||||
@@ -537,7 +537,7 @@ pub fn insn_to_str(
|
||||
*start_reg as i32,
|
||||
*count as i32,
|
||||
*dest_reg as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"r[{}]=mkrec(r[{}..{}]){}",
|
||||
@@ -553,7 +553,7 @@ pub fn insn_to_str(
|
||||
*start_reg as i32,
|
||||
*count as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
if *count == 1 {
|
||||
format!("output=r[{}]", start_reg)
|
||||
@@ -569,7 +569,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
pc_if_next.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -581,7 +581,7 @@ pub fn insn_to_str(
|
||||
*err_code as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(&description),
|
||||
Value::build_text(&description),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -590,7 +590,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*write as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("write={}", write),
|
||||
),
|
||||
@@ -599,7 +599,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
target_pc.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -611,7 +611,7 @@ pub fn insn_to_str(
|
||||
*return_reg as i32,
|
||||
target_pc.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -620,7 +620,7 @@ pub fn insn_to_str(
|
||||
*return_reg as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -629,7 +629,7 @@ pub fn insn_to_str(
|
||||
*value as i32,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]={}", dest, value),
|
||||
),
|
||||
@@ -638,7 +638,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::Float(*value),
|
||||
Value::Float(*value),
|
||||
0,
|
||||
format!("r[{}]={}", dest, value),
|
||||
),
|
||||
@@ -647,7 +647,7 @@ pub fn insn_to_str(
|
||||
*register as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -656,7 +656,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::build_text(value),
|
||||
Value::build_text(value),
|
||||
0,
|
||||
format!("r[{}]='{}'", dest, value),
|
||||
),
|
||||
@@ -665,7 +665,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::Blob(value.clone()),
|
||||
Value::Blob(value.clone()),
|
||||
0,
|
||||
format!(
|
||||
"r[{}]={} (len={})",
|
||||
@@ -679,7 +679,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"r[{}]={}.rowid",
|
||||
@@ -695,7 +695,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"r[{}]={}.rowid",
|
||||
@@ -715,7 +715,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*src_reg as i32,
|
||||
target_pc.to_debug_int(),
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"if (r[{}]!={}.rowid) goto {}",
|
||||
@@ -735,7 +735,7 @@ pub fn insn_to_str(
|
||||
*index_cursor_id as i32,
|
||||
*table_cursor_id as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -777,7 +777,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
target_pc.to_debug_int(),
|
||||
*start_reg as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("key=[{}..{}]", start_reg, start_reg + num_regs - 1),
|
||||
),
|
||||
@@ -786,7 +786,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -801,7 +801,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*record_reg as i32,
|
||||
unpacked_start.unwrap_or(0) as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
flags.0 as u16,
|
||||
format!("key=r[{}]", record_reg),
|
||||
),
|
||||
@@ -839,7 +839,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
target_pc.to_debug_int(),
|
||||
*start_reg as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("key=[{}..{}]", start_reg, start_reg + num_regs - 1),
|
||||
),
|
||||
@@ -848,7 +848,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
target_pc.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("if (--r[{}]==0) goto {}", reg, target_pc.to_debug_int()),
|
||||
),
|
||||
@@ -862,7 +862,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*col as i32,
|
||||
*acc_reg as i32,
|
||||
OwnedValue::build_text(func.to_string()),
|
||||
Value::build_text(func.to_string()),
|
||||
0,
|
||||
format!("accum=r[{}] step(r[{}])", *acc_reg, *col),
|
||||
),
|
||||
@@ -871,7 +871,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*register as i32,
|
||||
0,
|
||||
OwnedValue::build_text(func.to_string()),
|
||||
Value::build_text(func.to_string()),
|
||||
0,
|
||||
format!("accum=r[{}]", *register),
|
||||
),
|
||||
@@ -893,7 +893,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*columns as i32,
|
||||
0,
|
||||
OwnedValue::build_text(&(format!("k({},{})", order.len(), to_print.join(",")))),
|
||||
Value::build_text(&(format!("k({},{})", order.len(), to_print.join(",")))),
|
||||
0,
|
||||
format!("cursor={}", cursor_id),
|
||||
)
|
||||
@@ -907,7 +907,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*dest_reg as i32,
|
||||
*pseudo_cursor as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=data", dest_reg),
|
||||
),
|
||||
@@ -919,7 +919,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*record_reg as i32,
|
||||
0,
|
||||
OwnedValue::Integer(0),
|
||||
Value::Integer(0),
|
||||
0,
|
||||
format!("key=r[{}]", record_reg),
|
||||
),
|
||||
@@ -931,7 +931,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
pc_if_empty.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -943,7 +943,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
pc_if_next.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -963,7 +963,7 @@ pub fn insn_to_str(
|
||||
} else {
|
||||
func.func.to_string()
|
||||
};
|
||||
OwnedValue::build_text(&s)
|
||||
Value::build_text(&s)
|
||||
},
|
||||
0,
|
||||
if func.arg_count == 0 {
|
||||
@@ -988,7 +988,7 @@ pub fn insn_to_str(
|
||||
*yield_reg as i32,
|
||||
jump_on_definition.to_debug_int(),
|
||||
start_offset.to_debug_int(),
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -997,7 +997,7 @@ pub fn insn_to_str(
|
||||
*yield_reg as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -1009,7 +1009,7 @@ pub fn insn_to_str(
|
||||
*yield_reg as i32,
|
||||
end_offset.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -1024,7 +1024,7 @@ pub fn insn_to_str(
|
||||
*cursor as i32,
|
||||
*record_reg as i32,
|
||||
*key_reg as i32,
|
||||
OwnedValue::build_text(&table_name),
|
||||
Value::build_text(&table_name),
|
||||
*flag as u16,
|
||||
format!("intkey=r[{}] data=r[{}]", key_reg, record_reg),
|
||||
),
|
||||
@@ -1033,7 +1033,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -1046,7 +1046,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*start_reg as i32,
|
||||
*num_regs as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -1059,7 +1059,7 @@ pub fn insn_to_str(
|
||||
*cursor as i32,
|
||||
*rowid_reg as i32,
|
||||
*prev_largest_reg as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=rowid", rowid_reg),
|
||||
),
|
||||
@@ -1068,7 +1068,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -1077,7 +1077,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -1097,7 +1097,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
target_pc.to_debug_int(),
|
||||
*record_reg as i32,
|
||||
OwnedValue::build_text(&format!("{num_regs}")),
|
||||
Value::build_text(&format!("{num_regs}")),
|
||||
0,
|
||||
key,
|
||||
)
|
||||
@@ -1111,7 +1111,7 @@ pub fn insn_to_str(
|
||||
*cursor as i32,
|
||||
target_pc.to_debug_int(),
|
||||
*rowid_reg as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -1124,7 +1124,7 @@ pub fn insn_to_str(
|
||||
*limit_reg as i32,
|
||||
*combined_reg as i32,
|
||||
*offset_reg as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"if r[{}]>0 then r[{}]=r[{}]+max(0,r[{}]) else r[{}]=(-1)",
|
||||
@@ -1144,7 +1144,7 @@ pub fn insn_to_str(
|
||||
RegisterOrLiteral::Register(i) => *i as _,
|
||||
},
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("root={}; {}", root_page, name),
|
||||
),
|
||||
@@ -1157,7 +1157,7 @@ pub fn insn_to_str(
|
||||
*src_reg as i32,
|
||||
*dst_reg as i32,
|
||||
*amount as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=r[{}]", dst_reg, src_reg),
|
||||
),
|
||||
@@ -1166,7 +1166,7 @@ pub fn insn_to_str(
|
||||
*db as i32,
|
||||
*root as i32,
|
||||
flags.get_flags() as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=root iDb={} flags={}", root, db, flags.get_flags()),
|
||||
),
|
||||
@@ -1179,7 +1179,7 @@ pub fn insn_to_str(
|
||||
*root as i32,
|
||||
*former_root_reg as i32,
|
||||
*is_temp as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"root iDb={} former_root={} is_temp={}",
|
||||
@@ -1196,7 +1196,7 @@ pub fn insn_to_str(
|
||||
*db as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(table_name),
|
||||
Value::build_text(table_name),
|
||||
0,
|
||||
format!("DROP TABLE {}", table_name),
|
||||
),
|
||||
@@ -1205,7 +1205,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(index.name.clone()),
|
||||
Value::build_text(index.name.clone()),
|
||||
0,
|
||||
format!("DROP INDEX {}", index.name),
|
||||
),
|
||||
@@ -1214,7 +1214,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -1226,7 +1226,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
pc_if_empty.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -1235,7 +1235,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
target_pc.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("if (r[{}]==NULL) goto {}", reg, target_pc.to_debug_int()),
|
||||
),
|
||||
@@ -1244,7 +1244,7 @@ pub fn insn_to_str(
|
||||
*db as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(where_clause.clone().unwrap_or("NULL".to_string())),
|
||||
Value::build_text(where_clause.clone().unwrap_or("NULL".to_string())),
|
||||
0,
|
||||
where_clause.clone().unwrap_or("NULL".to_string()),
|
||||
),
|
||||
@@ -1256,7 +1256,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
pc_if_prev.to_debug_int(),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -1265,7 +1265,7 @@ pub fn insn_to_str(
|
||||
*rhs as i32,
|
||||
*lhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=r[{}] >> r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -1274,7 +1274,7 @@ pub fn insn_to_str(
|
||||
*rhs as i32,
|
||||
*lhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=r[{}] << r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -1283,7 +1283,7 @@ pub fn insn_to_str(
|
||||
usize::from(*index) as i32,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=parameter({})", *dest, *index),
|
||||
),
|
||||
@@ -1292,7 +1292,7 @@ pub fn insn_to_str(
|
||||
*rg1 as i32,
|
||||
*dest as i32,
|
||||
*rg2 as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"((r[{}]=NULL)|(r[{}]=NULL)) ? r[{}]=NULL : r[{}]=0",
|
||||
@@ -1304,7 +1304,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=!r[{}]", dest, reg),
|
||||
),
|
||||
@@ -1313,7 +1313,7 @@ pub fn insn_to_str(
|
||||
*rhs as i32,
|
||||
*lhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=r[{}] + r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -1322,7 +1322,7 @@ pub fn insn_to_str(
|
||||
*rhs as i32,
|
||||
*lhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=(r[{}] && r[{}])", dest, lhs, rhs),
|
||||
),
|
||||
@@ -1331,25 +1331,17 @@ pub fn insn_to_str(
|
||||
*rhs as i32,
|
||||
*lhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("r[{}]=(r[{}] || r[{}])", dest, lhs, rhs),
|
||||
),
|
||||
Insn::Noop => (
|
||||
"Noop",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
0,
|
||||
String::new(),
|
||||
),
|
||||
Insn::Noop => ("Noop", 0, 0, 0, Value::build_text(""), 0, String::new()),
|
||||
Insn::PageCount { db, dest } => (
|
||||
"Pagecount",
|
||||
*db as i32,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -1358,7 +1350,7 @@ pub fn insn_to_str(
|
||||
*db as i32,
|
||||
*dest as i32,
|
||||
*cookie as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -1370,7 +1362,7 @@ pub fn insn_to_str(
|
||||
*auto_commit as i32,
|
||||
*rollback as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("auto_commit={}, rollback={}", auto_commit, rollback),
|
||||
),
|
||||
@@ -1382,7 +1374,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*is_table as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"cursor={} is_table={}",
|
||||
@@ -1395,7 +1387,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("cursor={}", cursor_id),
|
||||
),
|
||||
@@ -1406,7 +1398,7 @@ pub fn insn_to_str(
|
||||
target_pc_when_reentered.to_debug_int(),
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!("goto {}", target_pc_when_reentered.to_debug_int()),
|
||||
),
|
||||
@@ -1415,7 +1407,7 @@ pub fn insn_to_str(
|
||||
*dest as i32,
|
||||
dest_end.map_or(0, |end| end as i32),
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
dest_end.map_or(format!("r[{}]=NULL", dest), |end| {
|
||||
format!("r[{}..{}]=NULL", dest, end)
|
||||
@@ -1431,7 +1423,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
target_pc.to_debug_int(),
|
||||
*record_reg as i32,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"if (r[{}] != NULL) goto {}",
|
||||
@@ -1448,7 +1440,7 @@ pub fn insn_to_str(
|
||||
*start_reg as i32,
|
||||
count.get() as i32,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
format!(
|
||||
"r[{}..{}] = {}",
|
||||
@@ -1470,7 +1462,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*target_reg as i32,
|
||||
if *exact { 0 } else { 1 },
|
||||
OwnedValue::build_text(""),
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
|
||||
@@ -2,11 +2,11 @@ use std::collections::HashMap;
|
||||
|
||||
use regex::{Regex, RegexBuilder};
|
||||
|
||||
use crate::{types::OwnedValue, LimboError};
|
||||
use crate::{types::Value, LimboError};
|
||||
|
||||
pub fn construct_like_escape_arg(escape_value: &OwnedValue) -> Result<char, LimboError> {
|
||||
pub fn construct_like_escape_arg(escape_value: &Value) -> Result<char, LimboError> {
|
||||
match escape_value {
|
||||
OwnedValue::Text(text) => {
|
||||
Value::Text(text) => {
|
||||
let mut escape_chars = text.as_str().chars();
|
||||
match (escape_chars.next(), escape_chars.next()) {
|
||||
(Some(escape), None) => Ok(escape),
|
||||
|
||||
@@ -34,7 +34,7 @@ use crate::{
|
||||
use crate::{
|
||||
storage::{btree::BTreeCursor, pager::Pager, sqlite3_ondisk::DatabaseHeader},
|
||||
translate::plan::{ResultSetColumn, TableReference},
|
||||
types::{AggContext, Cursor, CursorResult, ImmutableRecord, OwnedValue, SeekKey, SeekOp},
|
||||
types::{AggContext, Cursor, CursorResult, ImmutableRecord, SeekKey, SeekOp, Value},
|
||||
vdbe::{builder::CursorType, insn::Insn},
|
||||
};
|
||||
|
||||
@@ -241,7 +241,7 @@ enum HaltState {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Register {
|
||||
OwnedValue(OwnedValue),
|
||||
Value(Value),
|
||||
Aggregate(AggContext),
|
||||
Record(ImmutableRecord),
|
||||
}
|
||||
@@ -268,7 +268,7 @@ pub struct ProgramState {
|
||||
regex_cache: RegexCache,
|
||||
pub(crate) mv_tx_id: Option<crate::mvcc::database::TxID>,
|
||||
interrupted: bool,
|
||||
parameters: HashMap<NonZero<usize>, OwnedValue>,
|
||||
parameters: HashMap<NonZero<usize>, Value>,
|
||||
halt_state: Option<HaltState>,
|
||||
#[cfg(feature = "json")]
|
||||
json_cache: JsonCacheCell,
|
||||
@@ -279,7 +279,7 @@ impl ProgramState {
|
||||
pub fn new(max_registers: usize, max_cursors: usize) -> Self {
|
||||
let cursors: RefCell<Vec<Option<Cursor>>> =
|
||||
RefCell::new((0..max_cursors).map(|_| None).collect());
|
||||
let registers = vec![Register::OwnedValue(OwnedValue::Null); max_registers];
|
||||
let registers = vec![Register::Value(Value::Null); max_registers];
|
||||
Self {
|
||||
pc: 0,
|
||||
cursors,
|
||||
@@ -316,15 +316,12 @@ impl ProgramState {
|
||||
self.interrupted
|
||||
}
|
||||
|
||||
pub fn bind_at(&mut self, index: NonZero<usize>, value: OwnedValue) {
|
||||
pub fn bind_at(&mut self, index: NonZero<usize>, value: Value) {
|
||||
self.parameters.insert(index, value);
|
||||
}
|
||||
|
||||
pub fn get_parameter(&self, index: NonZero<usize>) -> OwnedValue {
|
||||
self.parameters
|
||||
.get(&index)
|
||||
.cloned()
|
||||
.unwrap_or(OwnedValue::Null)
|
||||
pub fn get_parameter(&self, index: NonZero<usize>) -> Value {
|
||||
self.parameters.get(&index).cloned().unwrap_or(Value::Null)
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
@@ -332,7 +329,7 @@ impl ProgramState {
|
||||
self.cursors.borrow_mut().iter_mut().for_each(|c| *c = None);
|
||||
self.registers
|
||||
.iter_mut()
|
||||
.for_each(|r| *r = Register::OwnedValue(OwnedValue::Null));
|
||||
.for_each(|r| *r = Register::Value(Value::Null));
|
||||
self.last_compare = None;
|
||||
self.deferred_seek = None;
|
||||
self.ended_coroutine.0 = [0; 4];
|
||||
@@ -355,9 +352,9 @@ impl ProgramState {
|
||||
}
|
||||
|
||||
impl Register {
|
||||
pub fn get_owned_value(&self) -> &OwnedValue {
|
||||
pub fn get_owned_value(&self) -> &Value {
|
||||
match self {
|
||||
Register::OwnedValue(v) => v,
|
||||
Register::Value(v) => v,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
@@ -624,49 +621,49 @@ fn get_indent_count(indent_count: usize, curr_insn: &Insn, prev_insn: Option<&In
|
||||
}
|
||||
|
||||
pub trait FromValueRow<'a> {
|
||||
fn from_value(value: &'a OwnedValue) -> Result<Self>
|
||||
fn from_value(value: &'a Value) -> Result<Self>
|
||||
where
|
||||
Self: Sized + 'a;
|
||||
}
|
||||
|
||||
impl<'a> FromValueRow<'a> for i64 {
|
||||
fn from_value(value: &'a OwnedValue) -> Result<Self> {
|
||||
fn from_value(value: &'a Value) -> Result<Self> {
|
||||
match value {
|
||||
OwnedValue::Integer(i) => Ok(*i),
|
||||
Value::Integer(i) => Ok(*i),
|
||||
_ => Err(LimboError::ConversionError("Expected integer value".into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromValueRow<'a> for f64 {
|
||||
fn from_value(value: &'a OwnedValue) -> Result<Self> {
|
||||
fn from_value(value: &'a Value) -> Result<Self> {
|
||||
match value {
|
||||
OwnedValue::Float(f) => Ok(*f),
|
||||
Value::Float(f) => Ok(*f),
|
||||
_ => Err(LimboError::ConversionError("Expected integer value".into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromValueRow<'a> for String {
|
||||
fn from_value(value: &'a OwnedValue) -> Result<Self> {
|
||||
fn from_value(value: &'a Value) -> Result<Self> {
|
||||
match value {
|
||||
OwnedValue::Text(s) => Ok(s.as_str().to_string()),
|
||||
Value::Text(s) => Ok(s.as_str().to_string()),
|
||||
_ => Err(LimboError::ConversionError("Expected text value".into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromValueRow<'a> for &'a str {
|
||||
fn from_value(value: &'a OwnedValue) -> Result<Self> {
|
||||
fn from_value(value: &'a Value) -> Result<Self> {
|
||||
match value {
|
||||
OwnedValue::Text(s) => Ok(s.as_str()),
|
||||
Value::Text(s) => Ok(s.as_str()),
|
||||
_ => Err(LimboError::ConversionError("Expected text value".into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromValueRow<'a> for &'a OwnedValue {
|
||||
fn from_value(value: &'a OwnedValue) -> Result<Self> {
|
||||
impl<'a> FromValueRow<'a> for &'a Value {
|
||||
fn from_value(value: &'a Value) -> Result<Self> {
|
||||
Ok(value)
|
||||
}
|
||||
}
|
||||
@@ -675,21 +672,21 @@ impl Row {
|
||||
pub fn get<'a, T: FromValueRow<'a> + 'a>(&'a self, idx: usize) -> Result<T> {
|
||||
let value = unsafe { self.values.add(idx).as_ref().unwrap() };
|
||||
let value = match value {
|
||||
Register::OwnedValue(owned_value) => owned_value,
|
||||
Register::Value(owned_value) => owned_value,
|
||||
_ => unreachable!("a row should be formed of values only"),
|
||||
};
|
||||
T::from_value(value)
|
||||
}
|
||||
|
||||
pub fn get_value<'a>(&'a self, idx: usize) -> &'a OwnedValue {
|
||||
pub fn get_value<'a>(&'a self, idx: usize) -> &'a Value {
|
||||
let value = unsafe { self.values.add(idx).as_ref().unwrap() };
|
||||
match value {
|
||||
Register::OwnedValue(owned_value) => owned_value,
|
||||
Register::Value(owned_value) => owned_value,
|
||||
_ => unreachable!("a row should be formed of values only"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_values(&self) -> impl Iterator<Item = &OwnedValue> {
|
||||
pub fn get_values(&self) -> impl Iterator<Item = &Value> {
|
||||
let values = unsafe { std::slice::from_raw_parts(self.values, self.count) };
|
||||
// This should be ownedvalues
|
||||
// TODO: add check for this
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::types::OwnedValue;
|
||||
use crate::types::Value;
|
||||
use crate::vdbe::Register;
|
||||
use crate::LimboError;
|
||||
use crate::Result;
|
||||
@@ -6,16 +6,16 @@ use crate::Result;
|
||||
pub mod vector_types;
|
||||
use vector_types::*;
|
||||
|
||||
pub fn vector32(args: &[Register]) -> Result<OwnedValue> {
|
||||
pub fn vector32(args: &[Register]) -> Result<Value> {
|
||||
if args.len() != 1 {
|
||||
return Err(LimboError::ConversionError(
|
||||
"vector32 requires exactly one argument".to_string(),
|
||||
));
|
||||
}
|
||||
let x = parse_vector(&args[0], Some(VectorType::Float32))?;
|
||||
// Extract the Vec<u8> from OwnedValue
|
||||
if let OwnedValue::Blob(data) = vector_serialize_f32(x) {
|
||||
Ok(OwnedValue::Blob(data))
|
||||
// Extract the Vec<u8> from Value
|
||||
if let Value::Blob(data) = vector_serialize_f32(x) {
|
||||
Ok(Value::Blob(data))
|
||||
} else {
|
||||
Err(LimboError::ConversionError(
|
||||
"Failed to serialize vector".to_string(),
|
||||
@@ -23,16 +23,16 @@ pub fn vector32(args: &[Register]) -> Result<OwnedValue> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vector64(args: &[Register]) -> Result<OwnedValue> {
|
||||
pub fn vector64(args: &[Register]) -> Result<Value> {
|
||||
if args.len() != 1 {
|
||||
return Err(LimboError::ConversionError(
|
||||
"vector64 requires exactly one argument".to_string(),
|
||||
));
|
||||
}
|
||||
let x = parse_vector(&args[0], Some(VectorType::Float64))?;
|
||||
// Extract the Vec<u8> from OwnedValue
|
||||
if let OwnedValue::Blob(data) = vector_serialize_f64(x) {
|
||||
Ok(OwnedValue::Blob(data))
|
||||
// Extract the Vec<u8> from Value
|
||||
if let Value::Blob(data) = vector_serialize_f64(x) {
|
||||
Ok(Value::Blob(data))
|
||||
} else {
|
||||
Err(LimboError::ConversionError(
|
||||
"Failed to serialize vector".to_string(),
|
||||
@@ -40,7 +40,7 @@ pub fn vector64(args: &[Register]) -> Result<OwnedValue> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vector_extract(args: &[Register]) -> Result<OwnedValue> {
|
||||
pub fn vector_extract(args: &[Register]) -> Result<Value> {
|
||||
if args.len() != 1 {
|
||||
return Err(LimboError::ConversionError(
|
||||
"vector_extract requires exactly one argument".to_string(),
|
||||
@@ -48,7 +48,7 @@ pub fn vector_extract(args: &[Register]) -> Result<OwnedValue> {
|
||||
}
|
||||
|
||||
let blob = match &args[0].get_owned_value() {
|
||||
OwnedValue::Blob(b) => b,
|
||||
Value::Blob(b) => b,
|
||||
_ => {
|
||||
return Err(LimboError::ConversionError(
|
||||
"Expected blob value".to_string(),
|
||||
@@ -57,15 +57,15 @@ pub fn vector_extract(args: &[Register]) -> Result<OwnedValue> {
|
||||
};
|
||||
|
||||
if blob.is_empty() {
|
||||
return Ok(OwnedValue::build_text("[]"));
|
||||
return Ok(Value::build_text("[]"));
|
||||
}
|
||||
|
||||
let vector_type = vector_type(blob)?;
|
||||
let vector = vector_deserialize(vector_type, blob)?;
|
||||
Ok(OwnedValue::build_text(&vector_to_text(&vector)))
|
||||
Ok(Value::build_text(&vector_to_text(&vector)))
|
||||
}
|
||||
|
||||
pub fn vector_distance_cos(args: &[Register]) -> Result<OwnedValue> {
|
||||
pub fn vector_distance_cos(args: &[Register]) -> Result<Value> {
|
||||
if args.len() != 2 {
|
||||
return Err(LimboError::ConversionError(
|
||||
"vector_distance_cos requires exactly two arguments".to_string(),
|
||||
@@ -75,5 +75,5 @@ pub fn vector_distance_cos(args: &[Register]) -> Result<OwnedValue> {
|
||||
let x = parse_vector(&args[0], None)?;
|
||||
let y = parse_vector(&args[1], None)?;
|
||||
let dist = do_vector_distance_cos(&x, &y)?;
|
||||
Ok(OwnedValue::Float(dist))
|
||||
Ok(Value::Float(dist))
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::types::{OwnedValue, OwnedValueType};
|
||||
use crate::types::{Value, ValueType};
|
||||
use crate::vdbe::Register;
|
||||
use crate::{LimboError, Result};
|
||||
|
||||
@@ -41,7 +41,7 @@ impl Vector {
|
||||
/// ```console
|
||||
/// [1.0, 2.0, 3.0]
|
||||
/// ```
|
||||
pub fn parse_string_vector(vector_type: VectorType, value: &OwnedValue) -> Result<Vector> {
|
||||
pub fn parse_string_vector(vector_type: VectorType, value: &Value) -> Result<Vector> {
|
||||
let Some(text) = value.to_text() else {
|
||||
return Err(LimboError::ConversionError(
|
||||
"Invalid vector value".to_string(),
|
||||
@@ -106,11 +106,11 @@ pub fn parse_string_vector(vector_type: VectorType, value: &OwnedValue) -> Resul
|
||||
|
||||
pub fn parse_vector(value: &Register, vec_ty: Option<VectorType>) -> Result<Vector> {
|
||||
match value.get_owned_value().value_type() {
|
||||
OwnedValueType::Text => parse_string_vector(
|
||||
ValueType::Text => parse_string_vector(
|
||||
vec_ty.unwrap_or(VectorType::Float32),
|
||||
value.get_owned_value(),
|
||||
),
|
||||
OwnedValueType::Blob => {
|
||||
ValueType::Blob => {
|
||||
let Some(blob) = value.get_owned_value().to_blob() else {
|
||||
return Err(LimboError::ConversionError(
|
||||
"Invalid vector value".to_string(),
|
||||
@@ -166,11 +166,11 @@ pub fn vector_deserialize(vector_type: VectorType, blob: &[u8]) -> Result<Vector
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vector_serialize_f64(x: Vector) -> OwnedValue {
|
||||
pub fn vector_serialize_f64(x: Vector) -> Value {
|
||||
let mut blob = Vec::with_capacity(x.dims * 8 + 1);
|
||||
blob.extend_from_slice(&x.data);
|
||||
blob.push(2);
|
||||
OwnedValue::from_blob(blob)
|
||||
Value::from_blob(blob)
|
||||
}
|
||||
|
||||
pub fn vector_deserialize_f64(blob: &[u8]) -> Result<Vector> {
|
||||
@@ -181,8 +181,8 @@ pub fn vector_deserialize_f64(blob: &[u8]) -> Result<Vector> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn vector_serialize_f32(x: Vector) -> OwnedValue {
|
||||
OwnedValue::from_blob(x.data)
|
||||
pub fn vector_serialize_f32(x: Vector) -> Value {
|
||||
Value::from_blob(x.data)
|
||||
}
|
||||
|
||||
pub fn vector_deserialize_f32(blob: &[u8]) -> Result<Vector> {
|
||||
@@ -566,7 +566,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn parse_string_vector_zero_length() {
|
||||
let value = OwnedValue::from_text("[]");
|
||||
let value = Value::from_text("[]");
|
||||
let vector = parse_string_vector(VectorType::Float32, &value).unwrap();
|
||||
assert_eq!(vector.dims, 0);
|
||||
assert_eq!(vector.vector_type, VectorType::Float32);
|
||||
@@ -574,7 +574,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_string_vector_valid_whitespace() {
|
||||
let value = OwnedValue::from_text(" [ 1.0 , 2.0 , 3.0 ] ");
|
||||
let value = Value::from_text(" [ 1.0 , 2.0 , 3.0 ] ");
|
||||
let vector = parse_string_vector(VectorType::Float32, &value).unwrap();
|
||||
assert_eq!(vector.dims, 3);
|
||||
assert_eq!(vector.vector_type, VectorType::Float32);
|
||||
@@ -582,7 +582,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_string_vector_valid() {
|
||||
let value = OwnedValue::from_text("[1.0, 2.0, 3.0]");
|
||||
let value = Value::from_text("[1.0, 2.0, 3.0]");
|
||||
let vector = parse_string_vector(VectorType::Float32, &value).unwrap();
|
||||
assert_eq!(vector.dims, 3);
|
||||
assert_eq!(vector.vector_type, VectorType::Float32);
|
||||
@@ -619,7 +619,7 @@ mod tests {
|
||||
let text = vector_to_text(&v);
|
||||
|
||||
// Parse back from text
|
||||
let value = OwnedValue::from_text(&text);
|
||||
let value = Value::from_text(&text);
|
||||
let parsed = parse_string_vector(v.vector_type.clone(), &value);
|
||||
|
||||
match parsed {
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::{error::Error, num::NonZero, sync::Arc};
|
||||
|
||||
use arbitrary::Arbitrary;
|
||||
use libfuzzer_sys::{fuzz_target, Corpus};
|
||||
use limbo_core::{OwnedValue, IO as _};
|
||||
use limbo_core::{Value, IO as _};
|
||||
|
||||
macro_rules! str_enum {
|
||||
($vis:vis enum $name:ident { $($variant:ident => $value:literal),*, }) => {
|
||||
@@ -72,20 +72,20 @@ enum Value {
|
||||
Blob(Vec<u8>),
|
||||
}
|
||||
|
||||
impl From<Value> for limbo_core::OwnedValue {
|
||||
fn from(value: Value) -> limbo_core::OwnedValue {
|
||||
impl From<Value> for limbo_core::Value {
|
||||
fn from(value: Value) -> limbo_core::Value {
|
||||
match value {
|
||||
Value::Null => limbo_core::OwnedValue::Null,
|
||||
Value::Integer(v) => limbo_core::OwnedValue::Integer(v),
|
||||
Value::Null => limbo_core::Value::Null,
|
||||
Value::Integer(v) => limbo_core::Value::Integer(v),
|
||||
Value::Real(v) => {
|
||||
if v.is_nan() {
|
||||
limbo_core::OwnedValue::Null
|
||||
limbo_core::Value::Null
|
||||
} else {
|
||||
limbo_core::OwnedValue::Float(v)
|
||||
limbo_core::Value::Float(v)
|
||||
}
|
||||
}
|
||||
Value::Text(v) => limbo_core::OwnedValue::from_text(&v),
|
||||
Value::Blob(v) => limbo_core::OwnedValue::from_blob(v.to_owned()),
|
||||
Value::Text(v) => limbo_core::Value::from_text(&v),
|
||||
Value::Blob(v) => limbo_core::Value::from_blob(v.to_owned()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,7 +206,7 @@ fn do_fuzz(expr: Expr) -> Result<Corpus, Box<dyn Error>> {
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
OwnedValue::from(expected.clone()),
|
||||
Value::from(expected.clone()),
|
||||
found.clone(),
|
||||
"with expression {:?}",
|
||||
expr,
|
||||
|
||||
@@ -493,13 +493,11 @@ impl Interaction {
|
||||
let mut r = Vec::new();
|
||||
for v in row.get_values() {
|
||||
let v = match v {
|
||||
limbo_core::OwnedValue::Null => Value::Null,
|
||||
limbo_core::OwnedValue::Integer(i) => Value::Integer(*i),
|
||||
limbo_core::OwnedValue::Float(f) => Value::Float(*f),
|
||||
limbo_core::OwnedValue::Text(t) => {
|
||||
Value::Text(t.as_str().to_string())
|
||||
}
|
||||
limbo_core::OwnedValue::Blob(b) => Value::Blob(b.to_vec()),
|
||||
limbo_core::Value::Null => Value::Null,
|
||||
limbo_core::Value::Integer(i) => Value::Integer(*i),
|
||||
limbo_core::Value::Float(f) => Value::Float(*f),
|
||||
limbo_core::Value::Text(t) => Value::Text(t.as_str().to_string()),
|
||||
limbo_core::Value::Blob(b) => Value::Blob(b.to_vec()),
|
||||
};
|
||||
r.push(v);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#![allow(clippy::missing_safety_doc)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use limbo_core::OwnedValue;
|
||||
use limbo_core::Value;
|
||||
use log::trace;
|
||||
use std::ffi::{self, CStr, CString};
|
||||
|
||||
@@ -565,63 +565,63 @@ pub unsafe extern "C" fn sqlite3_column_bytes(
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_value_type(value: *mut ffi::c_void) -> ffi::c_int {
|
||||
let value = value as *mut limbo_core::OwnedValue;
|
||||
let value = value as *mut limbo_core::Value;
|
||||
let value = &*value;
|
||||
match value {
|
||||
limbo_core::OwnedValue::Null => 0,
|
||||
limbo_core::OwnedValue::Integer(_) => 1,
|
||||
limbo_core::OwnedValue::Float(_) => 2,
|
||||
limbo_core::OwnedValue::Text(_) => 3,
|
||||
limbo_core::OwnedValue::Blob(_) => 4,
|
||||
limbo_core::Value::Null => 0,
|
||||
limbo_core::Value::Integer(_) => 1,
|
||||
limbo_core::Value::Float(_) => 2,
|
||||
limbo_core::Value::Text(_) => 3,
|
||||
limbo_core::Value::Blob(_) => 4,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_value_int64(value: *mut ffi::c_void) -> i64 {
|
||||
let value = value as *mut limbo_core::OwnedValue;
|
||||
let value = value as *mut limbo_core::Value;
|
||||
let value = &*value;
|
||||
match value {
|
||||
limbo_core::OwnedValue::Integer(i) => *i,
|
||||
limbo_core::Value::Integer(i) => *i,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_value_double(value: *mut ffi::c_void) -> f64 {
|
||||
let value = value as *mut limbo_core::OwnedValue;
|
||||
let value = value as *mut limbo_core::Value;
|
||||
let value = &*value;
|
||||
match value {
|
||||
limbo_core::OwnedValue::Float(f) => *f,
|
||||
limbo_core::Value::Float(f) => *f,
|
||||
_ => 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_value_text(value: *mut ffi::c_void) -> *const ffi::c_uchar {
|
||||
let value = value as *mut limbo_core::OwnedValue;
|
||||
let value = value as *mut limbo_core::Value;
|
||||
let value = &*value;
|
||||
match value {
|
||||
limbo_core::OwnedValue::Text(text) => text.as_str().as_ptr(),
|
||||
limbo_core::Value::Text(text) => text.as_str().as_ptr(),
|
||||
_ => std::ptr::null(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_value_blob(value: *mut ffi::c_void) -> *const ffi::c_void {
|
||||
let value = value as *mut limbo_core::OwnedValue;
|
||||
let value = value as *mut limbo_core::Value;
|
||||
let value = &*value;
|
||||
match value {
|
||||
limbo_core::OwnedValue::Blob(blob) => blob.as_ptr() as *const ffi::c_void,
|
||||
limbo_core::Value::Blob(blob) => blob.as_ptr() as *const ffi::c_void,
|
||||
_ => std::ptr::null(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_value_bytes(value: *mut ffi::c_void) -> ffi::c_int {
|
||||
let value = value as *mut limbo_core::OwnedValue;
|
||||
let value = value as *mut limbo_core::Value;
|
||||
let value = &*value;
|
||||
match value {
|
||||
limbo_core::OwnedValue::Blob(blob) => blob.len() as ffi::c_int,
|
||||
limbo_core::Value::Blob(blob) => blob.len() as ffi::c_int,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
@@ -637,8 +637,8 @@ pub unsafe extern "C" fn sqlite3_column_text(
|
||||
Some(row) => row,
|
||||
None => return std::ptr::null(),
|
||||
};
|
||||
match row.get::<&OwnedValue>(idx as usize) {
|
||||
Ok(limbo_core::OwnedValue::Text(text)) => text.as_str().as_ptr(),
|
||||
match row.get::<&Value>(idx as usize) {
|
||||
Ok(limbo_core::Value::Text(text)) => text.as_str().as_ptr(),
|
||||
_ => std::ptr::null(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,13 +179,11 @@ pub(crate) fn limbo_exec_rows(
|
||||
let row = row
|
||||
.get_values()
|
||||
.map(|x| match x {
|
||||
limbo_core::OwnedValue::Null => rusqlite::types::Value::Null,
|
||||
limbo_core::OwnedValue::Integer(x) => rusqlite::types::Value::Integer(*x),
|
||||
limbo_core::OwnedValue::Float(x) => rusqlite::types::Value::Real(*x),
|
||||
limbo_core::OwnedValue::Text(x) => {
|
||||
rusqlite::types::Value::Text(x.as_str().to_string())
|
||||
}
|
||||
limbo_core::OwnedValue::Blob(x) => rusqlite::types::Value::Blob(x.to_vec()),
|
||||
limbo_core::Value::Null => rusqlite::types::Value::Null,
|
||||
limbo_core::Value::Integer(x) => rusqlite::types::Value::Integer(*x),
|
||||
limbo_core::Value::Float(x) => rusqlite::types::Value::Real(*x),
|
||||
limbo_core::Value::Text(x) => rusqlite::types::Value::Text(x.as_str().to_string()),
|
||||
limbo_core::Value::Blob(x) => rusqlite::types::Value::Blob(x.to_vec()),
|
||||
})
|
||||
.collect();
|
||||
rows.push(row);
|
||||
|
||||
@@ -30,7 +30,7 @@ fn test_last_insert_rowid_basic() -> anyhow::Result<()> {
|
||||
match rows.step()? {
|
||||
StepResult::Row => {
|
||||
let row = rows.row().unwrap();
|
||||
if let limbo_core::OwnedValue::Integer(id) = row.get_value(0) {
|
||||
if let limbo_core::Value::Integer(id) = row.get_value(0) {
|
||||
assert_eq!(*id, 1, "First insert should have rowid 1");
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ fn test_last_insert_rowid_basic() -> anyhow::Result<()> {
|
||||
match rows.step()? {
|
||||
StepResult::Row => {
|
||||
let row = rows.row().unwrap();
|
||||
if let limbo_core::OwnedValue::Integer(id) = row.get_value(0) {
|
||||
if let limbo_core::Value::Integer(id) = row.get_value(0) {
|
||||
last_id = *id;
|
||||
}
|
||||
}
|
||||
@@ -112,7 +112,7 @@ fn test_integer_primary_key() -> anyhow::Result<()> {
|
||||
match select_query.step()? {
|
||||
StepResult::Row => {
|
||||
let row = select_query.row().unwrap();
|
||||
if let limbo_core::OwnedValue::Integer(id) = row.get_value(0) {
|
||||
if let limbo_core::Value::Integer(id) = row.get_value(0) {
|
||||
rowids.push(*id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::common::TempDatabase;
|
||||
use limbo_core::{OwnedValue, StepResult};
|
||||
use limbo_core::{StepResult, Value};
|
||||
|
||||
#[test]
|
||||
fn test_statement_reset_bind() -> anyhow::Result<()> {
|
||||
@@ -8,15 +8,15 @@ fn test_statement_reset_bind() -> anyhow::Result<()> {
|
||||
|
||||
let mut stmt = conn.prepare("select ?")?;
|
||||
|
||||
stmt.bind_at(1.try_into()?, OwnedValue::Integer(1));
|
||||
stmt.bind_at(1.try_into()?, Value::Integer(1));
|
||||
|
||||
loop {
|
||||
match stmt.step()? {
|
||||
StepResult::Row => {
|
||||
let row = stmt.row().unwrap();
|
||||
assert_eq!(
|
||||
*row.get::<&OwnedValue>(0).unwrap(),
|
||||
limbo_core::OwnedValue::Integer(1)
|
||||
*row.get::<&Value>(0).unwrap(),
|
||||
limbo_core::Value::Integer(1)
|
||||
);
|
||||
}
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
@@ -26,15 +26,15 @@ fn test_statement_reset_bind() -> anyhow::Result<()> {
|
||||
|
||||
stmt.reset();
|
||||
|
||||
stmt.bind_at(1.try_into()?, OwnedValue::Integer(2));
|
||||
stmt.bind_at(1.try_into()?, Value::Integer(2));
|
||||
|
||||
loop {
|
||||
match stmt.step()? {
|
||||
StepResult::Row => {
|
||||
let row = stmt.row().unwrap();
|
||||
assert_eq!(
|
||||
*row.get::<&OwnedValue>(0).unwrap(),
|
||||
limbo_core::OwnedValue::Integer(2)
|
||||
*row.get::<&Value>(0).unwrap(),
|
||||
limbo_core::Value::Integer(2)
|
||||
);
|
||||
}
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
@@ -52,14 +52,14 @@ fn test_statement_bind() -> anyhow::Result<()> {
|
||||
|
||||
let mut stmt = conn.prepare("select ?, ?1, :named, ?3, ?4")?;
|
||||
|
||||
stmt.bind_at(1.try_into()?, OwnedValue::build_text("hello"));
|
||||
stmt.bind_at(1.try_into()?, Value::build_text("hello"));
|
||||
|
||||
let i = stmt.parameters().index(":named").unwrap();
|
||||
stmt.bind_at(i, OwnedValue::Integer(42));
|
||||
stmt.bind_at(i, Value::Integer(42));
|
||||
|
||||
stmt.bind_at(3.try_into()?, OwnedValue::from_blob(vec![0x1, 0x2, 0x3]));
|
||||
stmt.bind_at(3.try_into()?, Value::from_blob(vec![0x1, 0x2, 0x3]));
|
||||
|
||||
stmt.bind_at(4.try_into()?, OwnedValue::Float(0.5));
|
||||
stmt.bind_at(4.try_into()?, Value::Float(0.5));
|
||||
|
||||
assert_eq!(stmt.parameters().count(), 4);
|
||||
|
||||
@@ -67,23 +67,23 @@ fn test_statement_bind() -> anyhow::Result<()> {
|
||||
match stmt.step()? {
|
||||
StepResult::Row => {
|
||||
let row = stmt.row().unwrap();
|
||||
if let limbo_core::OwnedValue::Text(s) = row.get::<&OwnedValue>(0).unwrap() {
|
||||
if let limbo_core::Value::Text(s) = row.get::<&Value>(0).unwrap() {
|
||||
assert_eq!(s.as_str(), "hello")
|
||||
}
|
||||
|
||||
if let limbo_core::OwnedValue::Text(s) = row.get::<&OwnedValue>(1).unwrap() {
|
||||
if let limbo_core::Value::Text(s) = row.get::<&Value>(1).unwrap() {
|
||||
assert_eq!(s.as_str(), "hello")
|
||||
}
|
||||
|
||||
if let limbo_core::OwnedValue::Integer(i) = row.get::<&OwnedValue>(2).unwrap() {
|
||||
if let limbo_core::Value::Integer(i) = row.get::<&Value>(2).unwrap() {
|
||||
assert_eq!(*i, 42)
|
||||
}
|
||||
|
||||
if let limbo_core::OwnedValue::Blob(v) = row.get::<&OwnedValue>(3).unwrap() {
|
||||
if let limbo_core::Value::Blob(v) = row.get::<&Value>(3).unwrap() {
|
||||
assert_eq!(v.as_slice(), &vec![0x1 as u8, 0x2, 0x3])
|
||||
}
|
||||
|
||||
if let limbo_core::OwnedValue::Float(f) = row.get::<&OwnedValue>(4).unwrap() {
|
||||
if let limbo_core::Value::Float(f) = row.get::<&Value>(4).unwrap() {
|
||||
assert_eq!(*f, 0.5)
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,7 @@ fn test_insert_parameter_remap() -> anyhow::Result<()> {
|
||||
|
||||
// prepare INSERT with re-ordered columns and constants
|
||||
let mut ins = conn.prepare("insert into test (d, c, a, b) values (22, ?, 7, ?);")?;
|
||||
let args = [OwnedValue::Integer(111), OwnedValue::Integer(222)];
|
||||
let args = [Value::Integer(111), Value::Integer(222)];
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
let idx = i + 1;
|
||||
ins.bind_at(idx.try_into()?, arg.clone());
|
||||
@@ -138,22 +138,16 @@ fn test_insert_parameter_remap() -> anyhow::Result<()> {
|
||||
let row = sel.row().unwrap();
|
||||
// insert_index = 3
|
||||
// A = 7
|
||||
assert_eq!(row.get::<&OwnedValue>(0).unwrap(), &OwnedValue::Integer(7));
|
||||
assert_eq!(row.get::<&Value>(0).unwrap(), &Value::Integer(7));
|
||||
// insert_index = 4
|
||||
// B = 222
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(1).unwrap(),
|
||||
&OwnedValue::Integer(222)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(1).unwrap(), &Value::Integer(222));
|
||||
// insert_index = 2
|
||||
// C = 111
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(2).unwrap(),
|
||||
&OwnedValue::Integer(111)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(2).unwrap(), &Value::Integer(111));
|
||||
// insert_index = 1
|
||||
// D = 22
|
||||
assert_eq!(row.get::<&OwnedValue>(3).unwrap(), &OwnedValue::Integer(22));
|
||||
assert_eq!(row.get::<&Value>(3).unwrap(), &Value::Integer(22));
|
||||
}
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
StepResult::Done | StepResult::Interrupt => break,
|
||||
@@ -187,10 +181,10 @@ fn test_insert_parameter_remap_all_params() -> anyhow::Result<()> {
|
||||
let mut ins = conn.prepare("insert into test (d, a, c, b) values (?, ?, ?, ?);")?;
|
||||
|
||||
let values = [
|
||||
OwnedValue::Integer(999), // ?1 → d
|
||||
OwnedValue::Integer(111), // ?2 → a
|
||||
OwnedValue::Integer(333), // ?3 → c
|
||||
OwnedValue::Integer(444), // ?4 → b
|
||||
Value::Integer(999), // ?1 → d
|
||||
Value::Integer(111), // ?2 → a
|
||||
Value::Integer(333), // ?3 → c
|
||||
Value::Integer(444), // ?4 → b
|
||||
];
|
||||
for (i, value) in values.iter().enumerate() {
|
||||
let idx = i + 1;
|
||||
@@ -215,28 +209,16 @@ fn test_insert_parameter_remap_all_params() -> anyhow::Result<()> {
|
||||
|
||||
// insert_index = 2
|
||||
// A = 111
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(0).unwrap(),
|
||||
&OwnedValue::Integer(111)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(0).unwrap(), &Value::Integer(111));
|
||||
// insert_index = 4
|
||||
// B = 444
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(1).unwrap(),
|
||||
&OwnedValue::Integer(444)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(1).unwrap(), &Value::Integer(444));
|
||||
// insert_index = 3
|
||||
// C = 333
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(2).unwrap(),
|
||||
&OwnedValue::Integer(333)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(2).unwrap(), &Value::Integer(333));
|
||||
// insert_index = 1
|
||||
// D = 999
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(3).unwrap(),
|
||||
&OwnedValue::Integer(999)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(3).unwrap(), &Value::Integer(999));
|
||||
}
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
StepResult::Done | StepResult::Interrupt => break,
|
||||
@@ -266,10 +248,10 @@ fn test_insert_parameter_multiple_remap_backwards() -> anyhow::Result<()> {
|
||||
let mut ins = conn.prepare("insert into test (d,c,b,a) values (?, ?, ?, ?);")?;
|
||||
|
||||
let values = [
|
||||
OwnedValue::Integer(444), // ?1 → d
|
||||
OwnedValue::Integer(333), // ?2 → c
|
||||
OwnedValue::Integer(222), // ?3 → b
|
||||
OwnedValue::Integer(111), // ?4 → a
|
||||
Value::Integer(444), // ?1 → d
|
||||
Value::Integer(333), // ?2 → c
|
||||
Value::Integer(222), // ?3 → b
|
||||
Value::Integer(111), // ?4 → a
|
||||
];
|
||||
for (i, value) in values.iter().enumerate() {
|
||||
let idx = i + 1;
|
||||
@@ -294,28 +276,16 @@ fn test_insert_parameter_multiple_remap_backwards() -> anyhow::Result<()> {
|
||||
|
||||
// insert_index = 2
|
||||
// A = 111
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(0).unwrap(),
|
||||
&OwnedValue::Integer(111)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(0).unwrap(), &Value::Integer(111));
|
||||
// insert_index = 4
|
||||
// B = 444
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(1).unwrap(),
|
||||
&OwnedValue::Integer(222)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(1).unwrap(), &Value::Integer(222));
|
||||
// insert_index = 3
|
||||
// C = 333
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(2).unwrap(),
|
||||
&OwnedValue::Integer(333)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(2).unwrap(), &Value::Integer(333));
|
||||
// insert_index = 1
|
||||
// D = 999
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(3).unwrap(),
|
||||
&OwnedValue::Integer(444)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(3).unwrap(), &Value::Integer(444));
|
||||
}
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
StepResult::Done | StepResult::Interrupt => break,
|
||||
@@ -344,10 +314,10 @@ fn test_insert_parameter_multiple_no_remap() -> anyhow::Result<()> {
|
||||
let mut ins = conn.prepare("insert into test (a,b,c,d) values (?, ?, ?, ?);")?;
|
||||
|
||||
let values = [
|
||||
OwnedValue::Integer(111), // ?1 → a
|
||||
OwnedValue::Integer(222), // ?2 → b
|
||||
OwnedValue::Integer(333), // ?3 → c
|
||||
OwnedValue::Integer(444), // ?4 → d
|
||||
Value::Integer(111), // ?1 → a
|
||||
Value::Integer(222), // ?2 → b
|
||||
Value::Integer(333), // ?3 → c
|
||||
Value::Integer(444), // ?4 → d
|
||||
];
|
||||
for (i, value) in values.iter().enumerate() {
|
||||
let idx = i + 1;
|
||||
@@ -372,28 +342,16 @@ fn test_insert_parameter_multiple_no_remap() -> anyhow::Result<()> {
|
||||
|
||||
// insert_index = 2
|
||||
// A = 111
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(0).unwrap(),
|
||||
&OwnedValue::Integer(111)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(0).unwrap(), &Value::Integer(111));
|
||||
// insert_index = 4
|
||||
// B = 444
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(1).unwrap(),
|
||||
&OwnedValue::Integer(222)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(1).unwrap(), &Value::Integer(222));
|
||||
// insert_index = 3
|
||||
// C = 333
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(2).unwrap(),
|
||||
&OwnedValue::Integer(333)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(2).unwrap(), &Value::Integer(333));
|
||||
// insert_index = 1
|
||||
// D = 999
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(3).unwrap(),
|
||||
&OwnedValue::Integer(444)
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(3).unwrap(), &Value::Integer(444));
|
||||
}
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
StepResult::Done | StepResult::Interrupt => break,
|
||||
@@ -422,14 +380,14 @@ fn test_insert_parameter_multiple_row() -> anyhow::Result<()> {
|
||||
let mut ins = conn.prepare("insert into test (b,a,d,c) values (?, ?, ?, ?), (?, ?, ?, ?);")?;
|
||||
|
||||
let values = [
|
||||
OwnedValue::Integer(222), // ?1 → b
|
||||
OwnedValue::Integer(111), // ?2 → a
|
||||
OwnedValue::Integer(444), // ?3 → d
|
||||
OwnedValue::Integer(333), // ?4 → c
|
||||
OwnedValue::Integer(666), // ?1 → b
|
||||
OwnedValue::Integer(555), // ?2 → a
|
||||
OwnedValue::Integer(888), // ?3 → d
|
||||
OwnedValue::Integer(777), // ?4 → c
|
||||
Value::Integer(222), // ?1 → b
|
||||
Value::Integer(111), // ?2 → a
|
||||
Value::Integer(444), // ?3 → d
|
||||
Value::Integer(333), // ?4 → c
|
||||
Value::Integer(666), // ?1 → b
|
||||
Value::Integer(555), // ?2 → a
|
||||
Value::Integer(888), // ?3 → d
|
||||
Value::Integer(777), // ?4 → c
|
||||
];
|
||||
for (i, value) in values.iter().enumerate() {
|
||||
let idx = i + 1;
|
||||
@@ -454,20 +412,20 @@ fn test_insert_parameter_multiple_row() -> anyhow::Result<()> {
|
||||
let row = sel.row().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(0).unwrap(),
|
||||
&OwnedValue::Integer(if i == 0 { 111 } else { 555 })
|
||||
row.get::<&Value>(0).unwrap(),
|
||||
&Value::Integer(if i == 0 { 111 } else { 555 })
|
||||
);
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(1).unwrap(),
|
||||
&OwnedValue::Integer(if i == 0 { 222 } else { 666 })
|
||||
row.get::<&Value>(1).unwrap(),
|
||||
&Value::Integer(if i == 0 { 222 } else { 666 })
|
||||
);
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(2).unwrap(),
|
||||
&OwnedValue::Integer(if i == 0 { 333 } else { 777 })
|
||||
row.get::<&Value>(2).unwrap(),
|
||||
&Value::Integer(if i == 0 { 333 } else { 777 })
|
||||
);
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(3).unwrap(),
|
||||
&OwnedValue::Integer(if i == 0 { 444 } else { 888 })
|
||||
row.get::<&Value>(3).unwrap(),
|
||||
&Value::Integer(if i == 0 { 444 } else { 888 })
|
||||
);
|
||||
i += 1;
|
||||
}
|
||||
@@ -494,8 +452,8 @@ fn test_bind_parameters_update_query() -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
let mut ins = conn.prepare("update test set a = ? where b = ?;")?;
|
||||
ins.bind_at(1.try_into()?, OwnedValue::Integer(222));
|
||||
ins.bind_at(2.try_into()?, OwnedValue::build_text("test1"));
|
||||
ins.bind_at(1.try_into()?, Value::Integer(222));
|
||||
ins.bind_at(2.try_into()?, Value::build_text("test1"));
|
||||
loop {
|
||||
match ins.step()? {
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
@@ -510,14 +468,8 @@ fn test_bind_parameters_update_query() -> anyhow::Result<()> {
|
||||
match sel.step()? {
|
||||
StepResult::Row => {
|
||||
let row = sel.row().unwrap();
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(0).unwrap(),
|
||||
&OwnedValue::Integer(222)
|
||||
);
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(1).unwrap(),
|
||||
&OwnedValue::build_text("test1"),
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(0).unwrap(), &Value::Integer(222));
|
||||
assert_eq!(row.get::<&Value>(1).unwrap(), &Value::build_text("test1"),);
|
||||
}
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
StepResult::Done | StepResult::Interrupt => break,
|
||||
@@ -544,9 +496,9 @@ fn test_bind_parameters_update_query_multiple_where() -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
let mut ins = conn.prepare("update test set a = ? where b = ? and c = 4 and d = ?;")?;
|
||||
ins.bind_at(1.try_into()?, OwnedValue::Integer(222));
|
||||
ins.bind_at(2.try_into()?, OwnedValue::build_text("test1"));
|
||||
ins.bind_at(3.try_into()?, OwnedValue::Integer(5));
|
||||
ins.bind_at(1.try_into()?, Value::Integer(222));
|
||||
ins.bind_at(2.try_into()?, Value::build_text("test1"));
|
||||
ins.bind_at(3.try_into()?, Value::Integer(5));
|
||||
loop {
|
||||
match ins.step()? {
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
@@ -561,16 +513,10 @@ fn test_bind_parameters_update_query_multiple_where() -> anyhow::Result<()> {
|
||||
match sel.step()? {
|
||||
StepResult::Row => {
|
||||
let row = sel.row().unwrap();
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(0).unwrap(),
|
||||
&OwnedValue::Integer(222)
|
||||
);
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(1).unwrap(),
|
||||
&OwnedValue::build_text("test1"),
|
||||
);
|
||||
assert_eq!(row.get::<&OwnedValue>(2).unwrap(), &OwnedValue::Integer(4));
|
||||
assert_eq!(row.get::<&OwnedValue>(3).unwrap(), &OwnedValue::Integer(5));
|
||||
assert_eq!(row.get::<&Value>(0).unwrap(), &Value::Integer(222));
|
||||
assert_eq!(row.get::<&Value>(1).unwrap(), &Value::build_text("test1"),);
|
||||
assert_eq!(row.get::<&Value>(2).unwrap(), &Value::Integer(4));
|
||||
assert_eq!(row.get::<&Value>(3).unwrap(), &Value::Integer(5));
|
||||
}
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
StepResult::Done | StepResult::Interrupt => break,
|
||||
@@ -601,11 +547,8 @@ fn test_bind_parameters_update_rowid_alias() -> anyhow::Result<()> {
|
||||
match sel.step()? {
|
||||
StepResult::Row => {
|
||||
let row = sel.row().unwrap();
|
||||
assert_eq!(row.get::<&OwnedValue>(0).unwrap(), &OwnedValue::Integer(1));
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(1).unwrap(),
|
||||
&OwnedValue::build_text("test"),
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(0).unwrap(), &Value::Integer(1));
|
||||
assert_eq!(row.get::<&Value>(1).unwrap(), &Value::build_text("test"),);
|
||||
}
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
StepResult::Done | StepResult::Interrupt => break,
|
||||
@@ -613,8 +556,8 @@ fn test_bind_parameters_update_rowid_alias() -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
let mut ins = conn.prepare("update test set name = ? where id = ?;")?;
|
||||
ins.bind_at(1.try_into()?, OwnedValue::build_text("updated"));
|
||||
ins.bind_at(2.try_into()?, OwnedValue::Integer(1));
|
||||
ins.bind_at(1.try_into()?, Value::build_text("updated"));
|
||||
ins.bind_at(2.try_into()?, Value::Integer(1));
|
||||
loop {
|
||||
match ins.step()? {
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
@@ -629,11 +572,8 @@ fn test_bind_parameters_update_rowid_alias() -> anyhow::Result<()> {
|
||||
match sel.step()? {
|
||||
StepResult::Row => {
|
||||
let row = sel.row().unwrap();
|
||||
assert_eq!(row.get::<&OwnedValue>(0).unwrap(), &OwnedValue::Integer(1));
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(1).unwrap(),
|
||||
&OwnedValue::build_text("updated"),
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(0).unwrap(), &Value::Integer(1));
|
||||
assert_eq!(row.get::<&Value>(1).unwrap(), &Value::build_text("updated"),);
|
||||
}
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
StepResult::Done | StepResult::Interrupt => break,
|
||||
@@ -660,16 +600,13 @@ fn test_bind_parameters_update_rowid_alias_seek_rowid() -> anyhow::Result<()> {
|
||||
StepResult::Row => {
|
||||
let row = sel.row().unwrap();
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(0).unwrap(),
|
||||
&OwnedValue::Integer(if i == 0 { 1 } else { 2 })
|
||||
row.get::<&Value>(0).unwrap(),
|
||||
&Value::Integer(if i == 0 { 1 } else { 2 })
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(1).unwrap(), &Value::build_text("test"),);
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(1).unwrap(),
|
||||
&OwnedValue::build_text("test"),
|
||||
);
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(2).unwrap(),
|
||||
&OwnedValue::Integer(if i == 0 { 4 } else { 11 })
|
||||
row.get::<&Value>(2).unwrap(),
|
||||
&Value::Integer(if i == 0 { 4 } else { 11 })
|
||||
);
|
||||
}
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
@@ -679,10 +616,10 @@ fn test_bind_parameters_update_rowid_alias_seek_rowid() -> anyhow::Result<()> {
|
||||
i += 1;
|
||||
}
|
||||
let mut ins = conn.prepare("update test set name = ? where id < ? AND age between ? and ?;")?;
|
||||
ins.bind_at(1.try_into()?, OwnedValue::build_text("updated"));
|
||||
ins.bind_at(2.try_into()?, OwnedValue::Integer(2));
|
||||
ins.bind_at(3.try_into()?, OwnedValue::Integer(3));
|
||||
ins.bind_at(4.try_into()?, OwnedValue::Integer(5));
|
||||
ins.bind_at(1.try_into()?, Value::build_text("updated"));
|
||||
ins.bind_at(2.try_into()?, Value::Integer(2));
|
||||
ins.bind_at(3.try_into()?, Value::Integer(3));
|
||||
ins.bind_at(4.try_into()?, Value::Integer(5));
|
||||
loop {
|
||||
match ins.step()? {
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
@@ -699,8 +636,8 @@ fn test_bind_parameters_update_rowid_alias_seek_rowid() -> anyhow::Result<()> {
|
||||
StepResult::Row => {
|
||||
let row = sel.row().unwrap();
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(0).unwrap(),
|
||||
&OwnedValue::build_text(if i == 0 { "updated" } else { "test" }),
|
||||
row.get::<&Value>(0).unwrap(),
|
||||
&Value::build_text(if i == 0 { "updated" } else { "test" }),
|
||||
);
|
||||
}
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
@@ -725,10 +662,10 @@ fn test_bind_parameters_delete_rowid_alias_seek_out_of_order() -> anyhow::Result
|
||||
|
||||
let mut ins =
|
||||
conn.prepare("delete from test where age between ? and ? AND id > ? AND name = ?;")?;
|
||||
ins.bind_at(1.try_into()?, OwnedValue::Integer(10));
|
||||
ins.bind_at(2.try_into()?, OwnedValue::Integer(12));
|
||||
ins.bind_at(3.try_into()?, OwnedValue::Integer(4));
|
||||
ins.bind_at(4.try_into()?, OwnedValue::build_text("test"));
|
||||
ins.bind_at(1.try_into()?, Value::Integer(10));
|
||||
ins.bind_at(2.try_into()?, Value::Integer(12));
|
||||
ins.bind_at(3.try_into()?, Value::Integer(4));
|
||||
ins.bind_at(4.try_into()?, Value::build_text("test"));
|
||||
loop {
|
||||
match ins.step()? {
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
@@ -744,10 +681,7 @@ fn test_bind_parameters_delete_rowid_alias_seek_out_of_order() -> anyhow::Result
|
||||
match sel.step()? {
|
||||
StepResult::Row => {
|
||||
let row = sel.row().unwrap();
|
||||
assert_eq!(
|
||||
row.get::<&OwnedValue>(0).unwrap(),
|
||||
&OwnedValue::build_text("correct"),
|
||||
);
|
||||
assert_eq!(row.get::<&Value>(0).unwrap(), &Value::build_text("correct"),);
|
||||
}
|
||||
StepResult::IO => tmp_db.io.run_once()?,
|
||||
StepResult::Done | StepResult::Interrupt => break,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::common::{self, maybe_setup_tracing};
|
||||
use crate::common::{compare_string, do_flush, TempDatabase};
|
||||
use limbo_core::{Connection, OwnedValue, Row, StepResult};
|
||||
use limbo_core::{Connection, Row, StepResult, Value};
|
||||
use log::debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
@@ -157,10 +157,10 @@ fn test_sequential_write() -> anyhow::Result<()> {
|
||||
|
||||
let mut current_read_index = 0;
|
||||
run_query_on_row(&tmp_db, &conn, &list_query, |row: &Row| {
|
||||
let first_value = row.get::<&OwnedValue>(0).expect("missing id");
|
||||
let first_value = row.get::<&Value>(0).expect("missing id");
|
||||
let id = match first_value {
|
||||
limbo_core::OwnedValue::Integer(i) => *i as i32,
|
||||
limbo_core::OwnedValue::Float(f) => *f as i32,
|
||||
limbo_core::Value::Integer(i) => *i as i32,
|
||||
limbo_core::Value::Float(f) => *f as i32,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
assert_eq!(current_read_index, id);
|
||||
@@ -190,9 +190,9 @@ fn test_regression_multi_row_insert() -> anyhow::Result<()> {
|
||||
let expected_ids = vec![-3, -2, -1];
|
||||
let mut actual_ids = Vec::new();
|
||||
run_query_on_row(&tmp_db, &conn, list_query, |row: &Row| {
|
||||
let first_value = row.get::<&OwnedValue>(0).expect("missing id");
|
||||
let first_value = row.get::<&Value>(0).expect("missing id");
|
||||
let id = match first_value {
|
||||
OwnedValue::Float(f) => *f as i32,
|
||||
Value::Float(f) => *f as i32,
|
||||
_ => panic!("expected float"),
|
||||
};
|
||||
actual_ids.push(id);
|
||||
@@ -222,8 +222,8 @@ fn test_statement_reset() -> anyhow::Result<()> {
|
||||
StepResult::Row => {
|
||||
let row = stmt.row().unwrap();
|
||||
assert_eq!(
|
||||
*row.get::<&OwnedValue>(0).unwrap(),
|
||||
limbo_core::OwnedValue::Integer(1)
|
||||
*row.get::<&Value>(0).unwrap(),
|
||||
limbo_core::Value::Integer(1)
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -239,8 +239,8 @@ fn test_statement_reset() -> anyhow::Result<()> {
|
||||
StepResult::Row => {
|
||||
let row = stmt.row().unwrap();
|
||||
assert_eq!(
|
||||
*row.get::<&OwnedValue>(0).unwrap(),
|
||||
limbo_core::OwnedValue::Integer(1)
|
||||
*row.get::<&Value>(0).unwrap(),
|
||||
limbo_core::Value::Integer(1)
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -362,10 +362,10 @@ fn test_write_delete_with_index() -> anyhow::Result<()> {
|
||||
println!("listing after deleting {} ", i);
|
||||
let mut current_read_index = i + 1;
|
||||
run_query_on_row(&tmp_db, &conn, list_query, |row: &Row| {
|
||||
let first_value = row.get::<&OwnedValue>(0).expect("missing id");
|
||||
let first_value = row.get::<&Value>(0).expect("missing id");
|
||||
let id = match first_value {
|
||||
limbo_core::OwnedValue::Integer(i) => *i as i32,
|
||||
limbo_core::OwnedValue::Float(f) => *f as i32,
|
||||
limbo_core::Value::Integer(i) => *i as i32,
|
||||
limbo_core::Value::Float(f) => *f as i32,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
assert_eq!(current_read_index, id);
|
||||
@@ -378,10 +378,10 @@ fn test_write_delete_with_index() -> anyhow::Result<()> {
|
||||
&conn,
|
||||
&format!("select * from test where x = {}", i),
|
||||
|row| {
|
||||
let first_value = row.get::<&OwnedValue>(0).expect("missing id");
|
||||
let first_value = row.get::<&Value>(0).expect("missing id");
|
||||
let id = match first_value {
|
||||
limbo_core::OwnedValue::Integer(i) => *i as i32,
|
||||
limbo_core::OwnedValue::Float(f) => *f as i32,
|
||||
limbo_core::Value::Integer(i) => *i as i32,
|
||||
limbo_core::Value::Float(f) => *f as i32,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
assert_eq!(i, id);
|
||||
|
||||
@@ -154,7 +154,7 @@ pub(crate) fn execute_and_get_ints(
|
||||
let row = stmt.row().unwrap();
|
||||
for value in row.get_values() {
|
||||
let out = match value {
|
||||
limbo_core::OwnedValue::Integer(i) => i,
|
||||
limbo_core::Value::Integer(i) => i,
|
||||
_ => {
|
||||
return Err(LimboError::ConversionError(format!(
|
||||
"cannot convert {value} to int"
|
||||
|
||||
Reference in New Issue
Block a user