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:
Pekka Enberg
2025-05-15 09:41:59 +03:00
parent d3e7dd2224
commit e3f71259d8
36 changed files with 2440 additions and 2808 deletions

View File

@@ -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();
}
}

View File

@@ -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,
}
}
}

View File

@@ -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
}

View File

@@ -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()?,
)))
}

View File

@@ -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: {}",

View File

@@ -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())),
}
}

View File

@@ -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),
}
}
}

View File

@@ -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(),
}
}

View File

@@ -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(' ');
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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();

File diff suppressed because it is too large Load Diff

View File

@@ -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}"#));

View File

@@ -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;

View File

@@ -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)
}

View File

@@ -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",

View File

@@ -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);

View File

@@ -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,

View File

@@ -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,

View File

@@ -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);

View File

@@ -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)
);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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(),
),

View File

@@ -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),

View File

@@ -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

View File

@@ -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))
}

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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(),
}
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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,

View File

@@ -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);

View File

@@ -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"