mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-23 08:55:40 +01:00
core: Parse UTF-8 strings lazily
This commit is contained in:
@@ -164,7 +164,7 @@ pub fn json_remove(args: &[OwnedValue]) -> crate::Result<OwnedValue> {
|
||||
.iter()
|
||||
.map(|path| {
|
||||
if let OwnedValue::Text(path) = path {
|
||||
json_path(&path.value)
|
||||
json_path(path.as_str())
|
||||
} else {
|
||||
crate::bail_constraint_error!("bad JSON path: {:?}", path.to_string())
|
||||
}
|
||||
@@ -514,7 +514,7 @@ mod tests {
|
||||
|
||||
let result = json_remove(&args).unwrap();
|
||||
match result {
|
||||
OwnedValue::Text(t) => assert_eq!(t.value.as_str(), "[1,2,4,5]"),
|
||||
OwnedValue::Text(t) => assert_eq!(t.as_str(), "[1,2,4,5]"),
|
||||
_ => panic!("Expected Text value"),
|
||||
}
|
||||
}
|
||||
@@ -529,7 +529,7 @@ mod tests {
|
||||
|
||||
let result = json_remove(&args).unwrap();
|
||||
match result {
|
||||
OwnedValue::Text(t) => assert_eq!(t.value.as_str(), r#"{"b":2}"#),
|
||||
OwnedValue::Text(t) => assert_eq!(t.as_str(), r#"{"b":2}"#),
|
||||
_ => panic!("Expected Text value"),
|
||||
}
|
||||
}
|
||||
@@ -543,7 +543,7 @@ mod tests {
|
||||
|
||||
let result = json_remove(&args).unwrap();
|
||||
match result {
|
||||
OwnedValue::Text(t) => assert_eq!(t.value.as_str(), r#"{"a":{"b":{"d":2}}}"#),
|
||||
OwnedValue::Text(t) => assert_eq!(t.as_str(), r#"{"a":{"b":{"d":2}}}"#),
|
||||
_ => panic!("Expected Text value"),
|
||||
}
|
||||
}
|
||||
@@ -557,7 +557,7 @@ mod tests {
|
||||
|
||||
let result = json_remove(&args).unwrap();
|
||||
match result {
|
||||
OwnedValue::Text(t) => assert_eq!(t.value.as_str(), r#"{"a":2,"a":3}"#),
|
||||
OwnedValue::Text(t) => assert_eq!(t.as_str(), r#"{"a":2,"a":3}"#),
|
||||
_ => panic!("Expected Text value"),
|
||||
}
|
||||
}
|
||||
@@ -584,7 +584,7 @@ mod tests {
|
||||
let result = json_remove(&args).unwrap();
|
||||
match result {
|
||||
OwnedValue::Text(t) => {
|
||||
let value = t.value.as_str();
|
||||
let value = t.as_str();
|
||||
assert!(value.contains(r#"[1,3]"#));
|
||||
assert!(value.contains(r#"{"x":2}"#));
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ pub fn get_json(json_value: &OwnedValue, indent: Option<&str>) -> crate::Result<
|
||||
|
||||
fn get_json_value(json_value: &OwnedValue) -> crate::Result<Val> {
|
||||
match json_value {
|
||||
OwnedValue::Text(ref t) => match from_str::<Val>(&t.value) {
|
||||
OwnedValue::Text(ref t) => match from_str::<Val>(t.as_str()) {
|
||||
Ok(json) => Ok(json),
|
||||
Err(_) => {
|
||||
crate::bail_parse_error!("malformed JSON")
|
||||
@@ -104,9 +104,9 @@ pub fn json_array(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
|
||||
OwnedValue::Blob(_) => crate::bail_constraint_error!("JSON cannot hold BLOB values"),
|
||||
OwnedValue::Text(t) => {
|
||||
if t.subtype == TextSubtype::Json {
|
||||
s.push_str(&t.value);
|
||||
s.push_str(t.as_str());
|
||||
} else {
|
||||
match to_string(&*t.value) {
|
||||
match to_string(&t.as_str().to_string()) {
|
||||
Ok(json) => s.push_str(&json),
|
||||
Err(_) => crate::bail_parse_error!("malformed JSON"),
|
||||
}
|
||||
@@ -166,10 +166,12 @@ pub fn json_set(json: &OwnedValue, values: &[OwnedValue]) -> crate::Result<Owned
|
||||
|
||||
if let Some(path) = path {
|
||||
let new_value = match value {
|
||||
OwnedValue::Text(Text {
|
||||
value,
|
||||
subtype: TextSubtype::Text,
|
||||
}) => Val::String(value.to_string()),
|
||||
OwnedValue::Text(
|
||||
t @ Text {
|
||||
subtype: TextSubtype::Text,
|
||||
..
|
||||
},
|
||||
) => Val::String(t.as_str().to_string()),
|
||||
_ => get_json_value(value)?,
|
||||
};
|
||||
|
||||
@@ -323,7 +325,7 @@ fn convert_db_type_to_json(value: &OwnedValue) -> crate::Result<Val> {
|
||||
OwnedValue::Text(t) => match t.subtype {
|
||||
// Convert only to json if the subtype is json (if we got it from another json function)
|
||||
TextSubtype::Json => get_json_value(value)?,
|
||||
TextSubtype::Text => Val::String(t.value.to_string()),
|
||||
TextSubtype::Text => Val::String(t.as_str().to_string()),
|
||||
},
|
||||
OwnedValue::Blob(_) => crate::bail_constraint_error!("JSON cannot hold BLOB values"),
|
||||
unsupported_value => crate::bail_constraint_error!(
|
||||
@@ -431,18 +433,21 @@ fn json_extract_single<'a>(
|
||||
fn json_path_from_owned_value(path: &OwnedValue, strict: bool) -> crate::Result<Option<JsonPath>> {
|
||||
let json_path = if strict {
|
||||
match path {
|
||||
OwnedValue::Text(t) => json_path(t.value.as_str())?,
|
||||
OwnedValue::Text(t) => json_path(t.as_str())?,
|
||||
OwnedValue::Null => return Ok(None),
|
||||
_ => crate::bail_constraint_error!("JSON path error near: {:?}", path.to_string()),
|
||||
}
|
||||
} else {
|
||||
match path {
|
||||
OwnedValue::Text(t) => {
|
||||
if t.value.starts_with("$") {
|
||||
json_path(t.value.as_str())?
|
||||
if t.as_str().starts_with("$") {
|
||||
json_path(t.as_str())?
|
||||
} else {
|
||||
JsonPath {
|
||||
elements: vec![PathElement::Root(), PathElement::Key(t.value.to_string())],
|
||||
elements: vec![
|
||||
PathElement::Root(),
|
||||
PathElement::Key(t.as_str().to_string()),
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -606,7 +611,7 @@ fn find_or_create_target<'a>(json: &'a mut Val, path: &JsonPath) -> Option<Targe
|
||||
|
||||
pub fn json_error_position(json: &OwnedValue) -> crate::Result<OwnedValue> {
|
||||
match json {
|
||||
OwnedValue::Text(t) => match from_str::<Val>(&t.value) {
|
||||
OwnedValue::Text(t) => match from_str::<Val>(t.as_str()) {
|
||||
Ok(_) => Ok(OwnedValue::Integer(0)),
|
||||
Err(JsonError::Message { location, .. }) => {
|
||||
if let Some(loc) = location {
|
||||
@@ -639,7 +644,7 @@ pub fn json_object(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
|
||||
.map(|chunk| match chunk {
|
||||
[key, value] => {
|
||||
let key = match key {
|
||||
OwnedValue::Text(t) => t.value.to_string(),
|
||||
OwnedValue::Text(t) => t.as_str().to_string(),
|
||||
_ => crate::bail_constraint_error!("labels must be TEXT"),
|
||||
};
|
||||
let json_val = convert_db_type_to_json(value)?;
|
||||
@@ -656,7 +661,7 @@ pub fn json_object(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
|
||||
|
||||
pub fn is_json_valid(json_value: &OwnedValue) -> crate::Result<OwnedValue> {
|
||||
match json_value {
|
||||
OwnedValue::Text(ref t) => match from_str::<Val>(&t.value) {
|
||||
OwnedValue::Text(ref t) => match from_str::<Val>(t.as_str()) {
|
||||
Ok(_) => Ok(OwnedValue::Integer(1)),
|
||||
Err(_) => Ok(OwnedValue::Integer(0)),
|
||||
},
|
||||
@@ -679,7 +684,7 @@ mod tests {
|
||||
let input = OwnedValue::build_text(Rc::new("{ key: 'value' }".to_string()));
|
||||
let result = get_json(&input, None).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.value.contains("\"key\":\"value\""));
|
||||
assert!(result_str.as_str().contains("\"key\":\"value\""));
|
||||
assert_eq!(result_str.subtype, TextSubtype::Json);
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
@@ -691,7 +696,7 @@ mod tests {
|
||||
let input = OwnedValue::build_text(Rc::new("{ key: ''value'' }".to_string()));
|
||||
let result = get_json(&input, None).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.value.contains("\"key\":\"value\""));
|
||||
assert!(result_str.as_str().contains("\"key\":\"value\""));
|
||||
assert_eq!(result_str.subtype, TextSubtype::Json);
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
@@ -703,7 +708,7 @@ mod tests {
|
||||
let input = OwnedValue::build_text(Rc::new("{ \"key\": Infinity }".to_string()));
|
||||
let result = get_json(&input, None).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.value.contains("{\"key\":9e999}"));
|
||||
assert!(result_str.as_str().contains("{\"key\":9e999}"));
|
||||
assert_eq!(result_str.subtype, TextSubtype::Json);
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
@@ -715,7 +720,7 @@ mod tests {
|
||||
let input = OwnedValue::build_text(Rc::new("{ \"key\": -Infinity }".to_string()));
|
||||
let result = get_json(&input, None).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.value.contains("{\"key\":-9e999}"));
|
||||
assert!(result_str.as_str().contains("{\"key\":-9e999}"));
|
||||
assert_eq!(result_str.subtype, TextSubtype::Json);
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
@@ -727,7 +732,7 @@ mod tests {
|
||||
let input = OwnedValue::build_text(Rc::new("{ \"key\": NaN }".to_string()));
|
||||
let result = get_json(&input, None).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.value.contains("{\"key\":null}"));
|
||||
assert!(result_str.as_str().contains("{\"key\":null}"));
|
||||
assert_eq!(result_str.subtype, TextSubtype::Json);
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
@@ -749,7 +754,7 @@ mod tests {
|
||||
let input = OwnedValue::build_text(Rc::new("{\"key\":\"value\"}".to_string()));
|
||||
let result = get_json(&input, None).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.value.contains("\"key\":\"value\""));
|
||||
assert!(result_str.as_str().contains("\"key\":\"value\""));
|
||||
assert_eq!(result_str.subtype, TextSubtype::Json);
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
@@ -772,7 +777,7 @@ mod tests {
|
||||
let input = OwnedValue::Blob(Rc::new(binary_json));
|
||||
let result = get_json(&input, None).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.value.contains("\"asd\":\"adf\""));
|
||||
assert!(result_str.as_str().contains("\"asd\":\"adf\""));
|
||||
assert_eq!(result_str.subtype, TextSubtype::Json);
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
@@ -809,7 +814,7 @@ mod tests {
|
||||
|
||||
let result = json_array(&input).unwrap();
|
||||
if let OwnedValue::Text(res) = result {
|
||||
assert_eq!(res.value.as_str(), "[\"value1\",\"value2\",1,1.1]");
|
||||
assert_eq!(res.as_str(), "[\"value1\",\"value2\",1,1.1]");
|
||||
assert_eq!(res.subtype, TextSubtype::Json);
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
@@ -822,7 +827,7 @@ mod tests {
|
||||
|
||||
let result = json_array(&input).unwrap();
|
||||
if let OwnedValue::Text(res) = result {
|
||||
assert_eq!(res.value.as_str(), "[]");
|
||||
assert_eq!(res.as_str(), "[]");
|
||||
assert_eq!(res.subtype, TextSubtype::Json);
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
@@ -1064,7 +1069,7 @@ mod tests {
|
||||
let OwnedValue::Text(json_text) = result else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
};
|
||||
assert_eq!(json_text.value.as_str(), r#"{"key":"value"}"#);
|
||||
assert_eq!(json_text.as_str(), r#"{"key":"value"}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1100,7 +1105,7 @@ mod tests {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
};
|
||||
assert_eq!(
|
||||
json_text.value.as_str(),
|
||||
json_text.as_str(),
|
||||
r#"{"text_key":"text_value","json_key":{"json":"value","number":1},"integer_key":1,"float_key":1.1,"null_key":null}"#
|
||||
);
|
||||
}
|
||||
@@ -1115,7 +1120,7 @@ mod tests {
|
||||
let OwnedValue::Text(json_text) = result else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
};
|
||||
assert_eq!(json_text.value.as_str(), r#"{"key":{"json":"value"}}"#);
|
||||
assert_eq!(json_text.as_str(), r#"{"key":{"json":"value"}}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1128,10 +1133,7 @@ mod tests {
|
||||
let OwnedValue::Text(json_text) = result else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
};
|
||||
assert_eq!(
|
||||
json_text.value.as_str(),
|
||||
r#"{"key":"{\"json\":\"value\"}"}"#
|
||||
);
|
||||
assert_eq!(json_text.as_str(), r#"{"key":"{\"json\":\"value\"}"}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1149,10 +1151,7 @@ mod tests {
|
||||
let OwnedValue::Text(json_text) = result else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
};
|
||||
assert_eq!(
|
||||
json_text.value.as_str(),
|
||||
r#"{"parent_key":{"key":"value"}}"#
|
||||
);
|
||||
assert_eq!(json_text.as_str(), r#"{"parent_key":{"key":"value"}}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1165,7 +1164,7 @@ mod tests {
|
||||
let OwnedValue::Text(json_text) = result else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
};
|
||||
assert_eq!(json_text.value.as_str(), r#"{"key":"value"}"#);
|
||||
assert_eq!(json_text.as_str(), r#"{"key":"value"}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1176,7 +1175,7 @@ mod tests {
|
||||
let OwnedValue::Text(json_text) = result else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
};
|
||||
assert_eq!(json_text.value.as_str(), r#"{}"#);
|
||||
assert_eq!(json_text.as_str(), r#"{}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1301,10 +1300,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_json_path_from_owned_value_root_strict() {
|
||||
let path = OwnedValue::Text(Text {
|
||||
value: Rc::new("$".to_string()),
|
||||
subtype: TextSubtype::Text,
|
||||
});
|
||||
let path = OwnedValue::Text(Text::new(Rc::new("$".to_string())));
|
||||
|
||||
let result = json_path_from_owned_value(&path, true);
|
||||
assert!(result.is_ok());
|
||||
@@ -1321,10 +1317,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_json_path_from_owned_value_root_non_strict() {
|
||||
let path = OwnedValue::Text(Text {
|
||||
value: Rc::new("$".to_string()),
|
||||
subtype: TextSubtype::Text,
|
||||
});
|
||||
let path = OwnedValue::Text(Text::new(Rc::new("$".to_string())));
|
||||
|
||||
let result = json_path_from_owned_value(&path, false);
|
||||
assert!(result.is_ok());
|
||||
@@ -1341,20 +1334,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_json_path_from_owned_value_named_strict() {
|
||||
let path = OwnedValue::Text(Text {
|
||||
value: Rc::new("field".to_string()),
|
||||
subtype: TextSubtype::Text,
|
||||
});
|
||||
let path = OwnedValue::Text(Text::new(Rc::new("field".to_string())));
|
||||
|
||||
assert!(json_path_from_owned_value(&path, true).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_json_path_from_owned_value_named_non_strict() {
|
||||
let path = OwnedValue::Text(Text {
|
||||
value: Rc::new("field".to_string()),
|
||||
subtype: TextSubtype::Text,
|
||||
});
|
||||
let path = OwnedValue::Text(Text::new(Rc::new("field".to_string())));
|
||||
|
||||
let result = json_path_from_owned_value(&path, false);
|
||||
assert!(result.is_ok());
|
||||
|
||||
@@ -46,7 +46,7 @@ use crate::io::{Buffer, Completion, ReadCompletion, SyncCompletion, WriteComplet
|
||||
use crate::storage::buffer_pool::BufferPool;
|
||||
use crate::storage::database::DatabaseStorage;
|
||||
use crate::storage::pager::Pager;
|
||||
use crate::types::{OwnedRecord, OwnedValue};
|
||||
use crate::types::{OwnedRecord, OwnedValue, Text, TextSubtype};
|
||||
use crate::{File, Result};
|
||||
use log::trace;
|
||||
use parking_lot::RwLock;
|
||||
@@ -1059,8 +1059,13 @@ pub fn read_value(buf: &[u8], serial_type: &SerialType) -> Result<(OwnedValue, u
|
||||
);
|
||||
}
|
||||
let bytes = buf[0..n].to_vec();
|
||||
let value = unsafe { String::from_utf8_unchecked(bytes) };
|
||||
Ok((OwnedValue::build_text(value.into()), n))
|
||||
Ok((
|
||||
OwnedValue::Text(Text {
|
||||
value: Rc::new(bytes),
|
||||
subtype: TextSubtype::Text,
|
||||
}),
|
||||
n,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ pub enum TextSubtype {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Text {
|
||||
pub value: Rc<String>,
|
||||
pub value: Rc<Vec<u8>>,
|
||||
pub subtype: TextSubtype,
|
||||
}
|
||||
|
||||
@@ -60,17 +60,21 @@ impl Text {
|
||||
|
||||
pub fn new(value: Rc<String>) -> Self {
|
||||
Self {
|
||||
value,
|
||||
value: Rc::new(value.as_bytes().to_vec()),
|
||||
subtype: TextSubtype::Text,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn json(value: Rc<String>) -> Self {
|
||||
Self {
|
||||
value,
|
||||
value: Rc::new(value.as_bytes().to_vec()),
|
||||
subtype: TextSubtype::Json,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
unsafe { std::str::from_utf8_unchecked(self.value.as_ref()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@@ -103,7 +107,7 @@ impl OwnedValue {
|
||||
|
||||
pub fn to_text(&self) -> Option<&str> {
|
||||
match self {
|
||||
OwnedValue::Text(t) => Some(&t.value),
|
||||
OwnedValue::Text(t) => Some(t.as_str()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -129,7 +133,7 @@ impl OwnedValue {
|
||||
OwnedValue::Null => Value::Null,
|
||||
OwnedValue::Integer(i) => Value::Integer(*i),
|
||||
OwnedValue::Float(f) => Value::Float(*f),
|
||||
OwnedValue::Text(s) => Value::Text(&s.value),
|
||||
OwnedValue::Text(s) => Value::Text(s.as_str()),
|
||||
OwnedValue::Blob(b) => Value::Blob(b),
|
||||
OwnedValue::Agg(a) => match a.as_ref() {
|
||||
AggContext::Avg(acc, _count) => match acc {
|
||||
@@ -187,7 +191,7 @@ impl Display for OwnedValue {
|
||||
Self::Null => write!(f, "NULL"),
|
||||
Self::Integer(i) => write!(f, "{}", i),
|
||||
Self::Float(fl) => write!(f, "{:?}", fl),
|
||||
Self::Text(s) => write!(f, "{}", s.value),
|
||||
Self::Text(s) => write!(f, "{}", s.as_str()),
|
||||
Self::Blob(b) => write!(f, "{}", String::from_utf8_lossy(b)),
|
||||
Self::Agg(a) => match a.as_ref() {
|
||||
AggContext::Avg(acc, _count) => write!(f, "{}", acc),
|
||||
@@ -211,7 +215,7 @@ impl OwnedValue {
|
||||
Self::Null => ExtValue::null(),
|
||||
Self::Integer(i) => ExtValue::from_integer(*i),
|
||||
Self::Float(fl) => ExtValue::from_float(*fl),
|
||||
Self::Text(text) => ExtValue::from_text(text.value.to_string()),
|
||||
Self::Text(text) => ExtValue::from_text(text.as_str().to_string()),
|
||||
Self::Blob(blob) => ExtValue::from_blob(blob.to_vec()),
|
||||
Self::Agg(_) => todo!(),
|
||||
Self::Record(_) => todo!("Record values not yet supported"),
|
||||
@@ -377,21 +381,21 @@ impl std::ops::Add<OwnedValue> for OwnedValue {
|
||||
Self::Float(float_left + float_right)
|
||||
}
|
||||
(Self::Text(string_left), Self::Text(string_right)) => Self::build_text(Rc::new(
|
||||
string_left.value.to_string() + &string_right.value.to_string(),
|
||||
string_left.as_str().to_string() + &string_right.as_str(),
|
||||
)),
|
||||
(Self::Text(string_left), Self::Integer(int_right)) => Self::build_text(Rc::new(
|
||||
string_left.value.to_string() + &int_right.to_string(),
|
||||
)),
|
||||
(Self::Integer(int_left), Self::Text(string_right)) => Self::build_text(Rc::new(
|
||||
int_left.to_string() + &string_right.value.to_string(),
|
||||
string_left.as_str().to_string() + &int_right.to_string(),
|
||||
)),
|
||||
(Self::Integer(int_left), Self::Text(string_right)) => {
|
||||
Self::build_text(Rc::new(int_left.to_string() + &string_right.as_str()))
|
||||
}
|
||||
(Self::Text(string_left), Self::Float(float_right)) => {
|
||||
let string_right = Self::Float(float_right).to_string();
|
||||
Self::build_text(Rc::new(string_left.value.to_string() + &string_right))
|
||||
Self::build_text(Rc::new(string_left.as_str().to_string() + &string_right))
|
||||
}
|
||||
(Self::Float(float_left), Self::Text(string_right)) => {
|
||||
let string_left = Self::Float(float_left).to_string();
|
||||
Self::build_text(Rc::new(string_left + &string_right.value.to_string()))
|
||||
Self::build_text(Rc::new(string_left + &string_right.as_str()))
|
||||
}
|
||||
(lhs, Self::Null) => lhs,
|
||||
(Self::Null, rhs) => rhs,
|
||||
@@ -500,7 +504,7 @@ impl<'a> FromValue<'a> for i64 {
|
||||
impl<'a> FromValue<'a> for String {
|
||||
fn from_value(value: &'a OwnedValue) -> Result<Self> {
|
||||
match value {
|
||||
OwnedValue::Text(s) => Ok(s.value.to_string()),
|
||||
OwnedValue::Text(s) => Ok(s.as_str().to_string()),
|
||||
_ => Err(LimboError::ConversionError("Expected text value".into())),
|
||||
}
|
||||
}
|
||||
@@ -509,7 +513,7 @@ impl<'a> FromValue<'a> for String {
|
||||
impl<'a> FromValue<'a> for &'a str {
|
||||
fn from_value(value: &'a OwnedValue) -> Result<Self> {
|
||||
match value {
|
||||
OwnedValue::Text(s) => Ok(s.value.as_str()),
|
||||
OwnedValue::Text(s) => Ok(s.as_str()),
|
||||
_ => Err(LimboError::ConversionError("Expected text value".into())),
|
||||
}
|
||||
}
|
||||
@@ -635,7 +639,7 @@ impl OwnedRecord {
|
||||
}
|
||||
}
|
||||
OwnedValue::Float(f) => buf.extend_from_slice(&f.to_be_bytes()),
|
||||
OwnedValue::Text(t) => buf.extend_from_slice(t.value.as_bytes()),
|
||||
OwnedValue::Text(t) => buf.extend_from_slice(&t.value),
|
||||
OwnedValue::Blob(b) => buf.extend_from_slice(b),
|
||||
// non serializable
|
||||
OwnedValue::Agg(_) => unreachable!(),
|
||||
|
||||
@@ -29,7 +29,7 @@ pub fn exec_strftime(values: &[OwnedValue]) -> OwnedValue {
|
||||
}
|
||||
|
||||
let format_str = match &values[0] {
|
||||
OwnedValue::Text(text) => text.value.to_string(),
|
||||
OwnedValue::Text(text) => text.as_str().to_string(),
|
||||
OwnedValue::Integer(num) => num.to_string(),
|
||||
OwnedValue::Float(num) => format!("{:.14}", num),
|
||||
_ => return OwnedValue::Null,
|
||||
@@ -82,7 +82,7 @@ fn modify_dt(
|
||||
if let OwnedValue::Text(ref text_rc) = modifier {
|
||||
// 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.value) {
|
||||
match apply_modifier(dt, text_rc.as_str()) {
|
||||
Ok(true) => subsec_requested = true,
|
||||
Ok(false) => {}
|
||||
Err(_) => return OwnedValue::build_text(Rc::new(String::new())),
|
||||
@@ -382,7 +382,7 @@ fn get_unixepoch_from_naive_datetime(value: NaiveDateTime) -> String {
|
||||
|
||||
fn parse_naive_date_time(time_value: &OwnedValue) -> Option<NaiveDateTime> {
|
||||
match time_value {
|
||||
OwnedValue::Text(s) => get_date_time_from_time_value_string(&s.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),
|
||||
_ => None,
|
||||
@@ -1100,7 +1100,7 @@ mod tests {
|
||||
for (input, expected) in test_cases {
|
||||
let result = exec_time(&[input]);
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert_eq!(result_str.value.as_str(), expected);
|
||||
assert_eq!(result_str.as_str(), expected);
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text, but got: {:?}", result);
|
||||
}
|
||||
|
||||
@@ -643,11 +643,11 @@ pub fn exec_add(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
| (OwnedValue::Integer(i), OwnedValue::Float(f)) => OwnedValue::Float(*f + *i as f64),
|
||||
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
|
||||
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_add(
|
||||
&cast_text_to_numerical(&lhs.value),
|
||||
&cast_text_to_numerical(&rhs.value),
|
||||
&cast_text_to_numerical(lhs.as_str()),
|
||||
&cast_text_to_numerical(rhs.as_str()),
|
||||
),
|
||||
(OwnedValue::Text(text), other) | (other, OwnedValue::Text(text)) => {
|
||||
exec_add(&cast_text_to_numerical(&text.value), other)
|
||||
exec_add(&cast_text_to_numerical(text.as_str()), other)
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
@@ -674,14 +674,14 @@ pub fn exec_subtract(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(*lhs as f64 - rhs),
|
||||
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
|
||||
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_subtract(
|
||||
&cast_text_to_numerical(&lhs.value),
|
||||
&cast_text_to_numerical(&rhs.value),
|
||||
&cast_text_to_numerical(lhs.as_str()),
|
||||
&cast_text_to_numerical(rhs.as_str()),
|
||||
),
|
||||
(OwnedValue::Text(text), other) => {
|
||||
exec_subtract(&cast_text_to_numerical(&text.value), other)
|
||||
exec_subtract(&cast_text_to_numerical(text.as_str()), other)
|
||||
}
|
||||
(other, OwnedValue::Text(text)) => {
|
||||
exec_subtract(other, &cast_text_to_numerical(&text.value))
|
||||
exec_subtract(other, &cast_text_to_numerical(text.as_str()))
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
@@ -707,11 +707,11 @@ pub fn exec_multiply(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
| (OwnedValue::Float(f), OwnedValue::Integer(i)) => OwnedValue::Float(*i as f64 * { *f }),
|
||||
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
|
||||
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_multiply(
|
||||
&cast_text_to_numerical(&lhs.value),
|
||||
&cast_text_to_numerical(&rhs.value),
|
||||
&cast_text_to_numerical(lhs.as_str()),
|
||||
&cast_text_to_numerical(rhs.as_str()),
|
||||
),
|
||||
(OwnedValue::Text(text), other) | (other, OwnedValue::Text(text)) => {
|
||||
exec_multiply(&cast_text_to_numerical(&text.value), other)
|
||||
exec_multiply(&cast_text_to_numerical(text.as_str()), other)
|
||||
}
|
||||
|
||||
_ => todo!(),
|
||||
@@ -740,11 +740,15 @@ pub fn exec_divide(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(*lhs as f64 / rhs),
|
||||
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
|
||||
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_divide(
|
||||
&cast_text_to_numerical(&lhs.value),
|
||||
&cast_text_to_numerical(&rhs.value),
|
||||
&cast_text_to_numerical(lhs.as_str()),
|
||||
&cast_text_to_numerical(rhs.as_str()),
|
||||
),
|
||||
(OwnedValue::Text(text), other) => exec_divide(&cast_text_to_numerical(&text.value), other),
|
||||
(other, OwnedValue::Text(text)) => exec_divide(other, &cast_text_to_numerical(&text.value)),
|
||||
(OwnedValue::Text(text), other) => {
|
||||
exec_divide(&cast_text_to_numerical(text.as_str()), other)
|
||||
}
|
||||
(other, OwnedValue::Text(text)) => {
|
||||
exec_divide(other, &cast_text_to_numerical(text.as_str()))
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
@@ -769,11 +773,11 @@ pub fn exec_bit_and(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
(OwnedValue::Float(lh), OwnedValue::Integer(rh)) => OwnedValue::Integer(*lh as i64 & rh),
|
||||
(OwnedValue::Integer(lh), OwnedValue::Float(rh)) => OwnedValue::Integer(lh & *rh as i64),
|
||||
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_bit_and(
|
||||
&cast_text_to_numerical(&lhs.value),
|
||||
&cast_text_to_numerical(&rhs.value),
|
||||
&cast_text_to_numerical(lhs.as_str()),
|
||||
&cast_text_to_numerical(rhs.as_str()),
|
||||
),
|
||||
(OwnedValue::Text(text), other) | (other, OwnedValue::Text(text)) => {
|
||||
exec_bit_and(&cast_text_to_numerical(&text.value), other)
|
||||
exec_bit_and(&cast_text_to_numerical(text.as_str()), other)
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
@@ -795,11 +799,11 @@ pub fn exec_bit_or(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
OwnedValue::Integer(*lh as i64 | *rh as i64)
|
||||
}
|
||||
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_bit_or(
|
||||
&cast_text_to_numerical(&lhs.value),
|
||||
&cast_text_to_numerical(&rhs.value),
|
||||
&cast_text_to_numerical(lhs.as_str()),
|
||||
&cast_text_to_numerical(rhs.as_str()),
|
||||
),
|
||||
(OwnedValue::Text(text), other) | (other, OwnedValue::Text(text)) => {
|
||||
exec_bit_or(&cast_text_to_numerical(&text.value), other)
|
||||
exec_bit_or(&cast_text_to_numerical(text.as_str()), other)
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
@@ -839,7 +843,7 @@ pub fn exec_bit_not(mut reg: &OwnedValue) -> OwnedValue {
|
||||
OwnedValue::Null => OwnedValue::Null,
|
||||
OwnedValue::Integer(i) => OwnedValue::Integer(!i),
|
||||
OwnedValue::Float(f) => OwnedValue::Integer(!(*f as i64)),
|
||||
OwnedValue::Text(text) => exec_bit_not(&cast_text_to_numerical(&text.value)),
|
||||
OwnedValue::Text(text) => exec_bit_not(&cast_text_to_numerical(text.as_str())),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
@@ -866,14 +870,14 @@ pub fn exec_shift_left(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue
|
||||
OwnedValue::Integer(compute_shl(*lh as i64, *rh as i64))
|
||||
}
|
||||
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_shift_left(
|
||||
&cast_text_to_numerical(&lhs.value),
|
||||
&cast_text_to_numerical(&rhs.value),
|
||||
&cast_text_to_numerical(lhs.as_str()),
|
||||
&cast_text_to_numerical(rhs.as_str()),
|
||||
),
|
||||
(OwnedValue::Text(text), other) => {
|
||||
exec_shift_left(&cast_text_to_numerical(&text.value), other)
|
||||
exec_shift_left(&cast_text_to_numerical(text.as_str()), other)
|
||||
}
|
||||
(other, OwnedValue::Text(text)) => {
|
||||
exec_shift_left(other, &cast_text_to_numerical(&text.value))
|
||||
exec_shift_left(other, &cast_text_to_numerical(text.as_str()))
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
@@ -905,14 +909,14 @@ pub fn exec_shift_right(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValu
|
||||
OwnedValue::Integer(compute_shr(*lh as i64, *rh as i64))
|
||||
}
|
||||
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_shift_right(
|
||||
&cast_text_to_numerical(&lhs.value),
|
||||
&cast_text_to_numerical(&rhs.value),
|
||||
&cast_text_to_numerical(lhs.as_str()),
|
||||
&cast_text_to_numerical(rhs.as_str()),
|
||||
),
|
||||
(OwnedValue::Text(text), other) => {
|
||||
exec_shift_right(&cast_text_to_numerical(&text.value), other)
|
||||
exec_shift_right(&cast_text_to_numerical(text.as_str()), other)
|
||||
}
|
||||
(other, OwnedValue::Text(text)) => {
|
||||
exec_shift_right(other, &cast_text_to_numerical(&text.value))
|
||||
exec_shift_right(other, &cast_text_to_numerical(text.as_str()))
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
@@ -943,7 +947,7 @@ pub fn exec_boolean_not(mut reg: &OwnedValue) -> OwnedValue {
|
||||
OwnedValue::Null => OwnedValue::Null,
|
||||
OwnedValue::Integer(i) => OwnedValue::Integer((*i == 0) as i64),
|
||||
OwnedValue::Float(f) => OwnedValue::Integer((*f == 0.0) as i64),
|
||||
OwnedValue::Text(text) => exec_boolean_not(&cast_text_to_numerical(&text.value)),
|
||||
OwnedValue::Text(text) => exec_boolean_not(&cast_text_to_numerical(text.as_str())),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
@@ -951,20 +955,20 @@ pub fn exec_boolean_not(mut reg: &OwnedValue) -> OwnedValue {
|
||||
pub fn exec_concat(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Text(lhs_text), OwnedValue::Text(rhs_text)) => {
|
||||
OwnedValue::build_text(Rc::new(lhs_text.value.as_ref().clone() + &rhs_text.value))
|
||||
OwnedValue::build_text(Rc::new(lhs_text.as_str().to_string() + &rhs_text.as_str()))
|
||||
}
|
||||
(OwnedValue::Text(lhs_text), OwnedValue::Integer(rhs_int)) => OwnedValue::build_text(
|
||||
Rc::new(lhs_text.value.as_ref().clone() + &rhs_int.to_string()),
|
||||
Rc::new(lhs_text.as_str().to_string() + &rhs_int.to_string()),
|
||||
),
|
||||
(OwnedValue::Text(lhs_text), OwnedValue::Float(rhs_float)) => OwnedValue::build_text(
|
||||
Rc::new(lhs_text.value.as_ref().clone() + &rhs_float.to_string()),
|
||||
Rc::new(lhs_text.as_str().to_string() + &rhs_float.to_string()),
|
||||
),
|
||||
(OwnedValue::Text(lhs_text), OwnedValue::Agg(rhs_agg)) => OwnedValue::build_text(Rc::new(
|
||||
lhs_text.value.as_ref().clone() + &rhs_agg.final_value().to_string(),
|
||||
lhs_text.as_str().to_string() + &rhs_agg.final_value().to_string(),
|
||||
)),
|
||||
|
||||
(OwnedValue::Integer(lhs_int), OwnedValue::Text(rhs_text)) => {
|
||||
OwnedValue::build_text(Rc::new(lhs_int.to_string() + &rhs_text.value))
|
||||
OwnedValue::build_text(Rc::new(lhs_int.to_string() + rhs_text.as_str()))
|
||||
}
|
||||
(OwnedValue::Integer(lhs_int), OwnedValue::Integer(rhs_int)) => {
|
||||
OwnedValue::build_text(Rc::new(lhs_int.to_string() + &rhs_int.to_string()))
|
||||
@@ -977,7 +981,7 @@ pub fn exec_concat(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
),
|
||||
|
||||
(OwnedValue::Float(lhs_float), OwnedValue::Text(rhs_text)) => {
|
||||
OwnedValue::build_text(Rc::new(lhs_float.to_string() + &rhs_text.value))
|
||||
OwnedValue::build_text(Rc::new(lhs_float.to_string() + rhs_text.as_str()))
|
||||
}
|
||||
(OwnedValue::Float(lhs_float), OwnedValue::Integer(rhs_int)) => {
|
||||
OwnedValue::build_text(Rc::new(lhs_float.to_string() + &rhs_int.to_string()))
|
||||
@@ -989,9 +993,9 @@ pub fn exec_concat(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
Rc::new(lhs_float.to_string() + &rhs_agg.final_value().to_string()),
|
||||
),
|
||||
|
||||
(OwnedValue::Agg(lhs_agg), OwnedValue::Text(rhs_text)) => {
|
||||
OwnedValue::build_text(Rc::new(lhs_agg.final_value().to_string() + &rhs_text.value))
|
||||
}
|
||||
(OwnedValue::Agg(lhs_agg), OwnedValue::Text(rhs_text)) => OwnedValue::build_text(Rc::new(
|
||||
lhs_agg.final_value().to_string() + rhs_text.as_str(),
|
||||
)),
|
||||
(OwnedValue::Agg(lhs_agg), OwnedValue::Integer(rhs_int)) => OwnedValue::build_text(
|
||||
Rc::new(lhs_agg.final_value().to_string() + &rhs_int.to_string()),
|
||||
),
|
||||
@@ -1025,11 +1029,11 @@ pub fn exec_and(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
| (OwnedValue::Float(0.0), _) => OwnedValue::Integer(0),
|
||||
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
|
||||
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_and(
|
||||
&cast_text_to_numerical(&lhs.value),
|
||||
&cast_text_to_numerical(&rhs.value),
|
||||
&cast_text_to_numerical(lhs.as_str()),
|
||||
&cast_text_to_numerical(rhs.as_str()),
|
||||
),
|
||||
(OwnedValue::Text(text), other) | (other, OwnedValue::Text(text)) => {
|
||||
exec_and(&cast_text_to_numerical(&text.value), other)
|
||||
exec_and(&cast_text_to_numerical(text.as_str()), other)
|
||||
}
|
||||
_ => OwnedValue::Integer(1),
|
||||
}
|
||||
@@ -1054,11 +1058,11 @@ pub fn exec_or(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
| (OwnedValue::Float(0.0), OwnedValue::Float(0.0))
|
||||
| (OwnedValue::Integer(0), OwnedValue::Integer(0)) => OwnedValue::Integer(0),
|
||||
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_or(
|
||||
&cast_text_to_numerical(&lhs.value),
|
||||
&cast_text_to_numerical(&rhs.value),
|
||||
&cast_text_to_numerical(lhs.as_str()),
|
||||
&cast_text_to_numerical(rhs.as_str()),
|
||||
),
|
||||
(OwnedValue::Text(text), other) | (other, OwnedValue::Text(text)) => {
|
||||
exec_or(&cast_text_to_numerical(&text.value), other)
|
||||
exec_or(&cast_text_to_numerical(text.as_str()), other)
|
||||
}
|
||||
_ => OwnedValue::Integer(1),
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{types::OwnedValue, LimboError};
|
||||
pub fn construct_like_escape_arg(escape_value: &OwnedValue) -> Result<char, LimboError> {
|
||||
match escape_value {
|
||||
OwnedValue::Text(text) => {
|
||||
let mut escape_chars = text.value.chars();
|
||||
let mut escape_chars = text.as_str().chars();
|
||||
match (escape_chars.next(), escape_chars.next()) {
|
||||
(Some(escape), None) => Ok(escape),
|
||||
_ => Err(LimboError::Constraint(
|
||||
|
||||
109
core/vdbe/mod.rs
109
core/vdbe/mod.rs
@@ -1840,12 +1840,12 @@ impl Program {
|
||||
// To the way blobs are parsed here in SQLite.
|
||||
let indent = match indent {
|
||||
Some(value) => match value {
|
||||
OwnedValue::Text(text) => text.value.as_str(),
|
||||
OwnedValue::Text(text) => text.as_str(),
|
||||
OwnedValue::Integer(val) => &val.to_string(),
|
||||
OwnedValue::Float(val) => &val.to_string(),
|
||||
OwnedValue::Blob(val) => &String::from_utf8_lossy(val),
|
||||
OwnedValue::Agg(ctx) => match ctx.final_value() {
|
||||
OwnedValue::Text(text) => text.value.as_str(),
|
||||
OwnedValue::Text(text) => text.as_str(),
|
||||
OwnedValue::Integer(val) => &val.to_string(),
|
||||
OwnedValue::Float(val) => &val.to_string(),
|
||||
OwnedValue::Blob(val) => &String::from_utf8_lossy(val),
|
||||
@@ -1883,7 +1883,8 @@ impl Program {
|
||||
else {
|
||||
unreachable!("Cast with non-text type");
|
||||
};
|
||||
let result = exec_cast(®_value_argument, ®_value_type.value);
|
||||
let result =
|
||||
exec_cast(®_value_argument, ®_value_type.as_str());
|
||||
state.registers[*dest] = result;
|
||||
}
|
||||
ScalarFunc::Changes => {
|
||||
@@ -1921,8 +1922,8 @@ impl Program {
|
||||
};
|
||||
OwnedValue::Integer(exec_glob(
|
||||
cache,
|
||||
&pattern.value,
|
||||
&text.value,
|
||||
&pattern.as_str(),
|
||||
&text.as_str(),
|
||||
)
|
||||
as i64)
|
||||
}
|
||||
@@ -1964,8 +1965,8 @@ impl Program {
|
||||
};
|
||||
|
||||
OwnedValue::Integer(exec_like_with_escape(
|
||||
&pattern.value,
|
||||
&text.value,
|
||||
&pattern.as_str(),
|
||||
&text.as_str(),
|
||||
escape,
|
||||
)
|
||||
as i64)
|
||||
@@ -1978,8 +1979,8 @@ impl Program {
|
||||
};
|
||||
OwnedValue::Integer(exec_like(
|
||||
cache,
|
||||
&pattern.value,
|
||||
&text.value,
|
||||
&pattern.as_str(),
|
||||
&text.as_str(),
|
||||
)
|
||||
as i64)
|
||||
}
|
||||
@@ -2408,14 +2409,16 @@ impl Program {
|
||||
"MustBeInt: the value in register cannot be cast to integer"
|
||||
),
|
||||
},
|
||||
OwnedValue::Text(text) => match checked_cast_text_to_numeric(&text.value) {
|
||||
Ok(OwnedValue::Integer(i)) => {
|
||||
state.registers[*reg] = OwnedValue::Integer(i)
|
||||
OwnedValue::Text(text) => {
|
||||
match checked_cast_text_to_numeric(&text.as_str()) {
|
||||
Ok(OwnedValue::Integer(i)) => {
|
||||
state.registers[*reg] = OwnedValue::Integer(i)
|
||||
}
|
||||
_ => crate::bail_parse_error!(
|
||||
"MustBeInt: the value in register cannot be cast to integer"
|
||||
),
|
||||
}
|
||||
_ => crate::bail_parse_error!(
|
||||
"MustBeInt: the value in register cannot be cast to integer"
|
||||
),
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
crate::bail_parse_error!(
|
||||
"MustBeInt: the value in register cannot be cast to integer"
|
||||
@@ -2513,7 +2516,7 @@ impl Program {
|
||||
}
|
||||
Insn::CreateBtree { db, root, flags } => {
|
||||
if *db > 0 {
|
||||
// TODO: implement temp datbases
|
||||
// TODO: implement temp databases
|
||||
todo!("temp databases not implemented yet");
|
||||
}
|
||||
let mut cursor = Box::new(BTreeCursor::new(pager.clone(), 0));
|
||||
@@ -2717,7 +2720,7 @@ fn get_indent_count(indent_count: usize, curr_insn: &Insn, prev_insn: Option<&In
|
||||
|
||||
fn exec_lower(reg: &OwnedValue) -> Option<OwnedValue> {
|
||||
match reg {
|
||||
OwnedValue::Text(t) => Some(OwnedValue::build_text(Rc::new(t.value.to_lowercase()))),
|
||||
OwnedValue::Text(t) => Some(OwnedValue::build_text(Rc::new(t.as_str().to_lowercase()))),
|
||||
t => Some(t.to_owned()),
|
||||
}
|
||||
}
|
||||
@@ -2746,7 +2749,7 @@ fn exec_octet_length(reg: &OwnedValue) -> OwnedValue {
|
||||
|
||||
fn exec_upper(reg: &OwnedValue) -> Option<OwnedValue> {
|
||||
match reg {
|
||||
OwnedValue::Text(t) => Some(OwnedValue::build_text(Rc::new(t.value.to_uppercase()))),
|
||||
OwnedValue::Text(t) => Some(OwnedValue::build_text(Rc::new(t.as_str().to_uppercase()))),
|
||||
t => Some(t.to_owned()),
|
||||
}
|
||||
}
|
||||
@@ -2755,7 +2758,7 @@ fn exec_concat_strings(registers: &[OwnedValue]) -> OwnedValue {
|
||||
let mut result = String::new();
|
||||
for reg in registers {
|
||||
match reg {
|
||||
OwnedValue::Text(text) => result.push_str(&text.value),
|
||||
OwnedValue::Text(text) => result.push_str(text.as_str()),
|
||||
OwnedValue::Integer(i) => result.push_str(&i.to_string()),
|
||||
OwnedValue::Float(f) => result.push_str(&f.to_string()),
|
||||
OwnedValue::Agg(aggctx) => result.push_str(&aggctx.final_value().to_string()),
|
||||
@@ -2773,9 +2776,9 @@ fn exec_concat_ws(registers: &[OwnedValue]) -> OwnedValue {
|
||||
}
|
||||
|
||||
let separator = match ®isters[0] {
|
||||
OwnedValue::Text(text) => text.value.clone(),
|
||||
OwnedValue::Integer(i) => Rc::new(i.to_string()),
|
||||
OwnedValue::Float(f) => Rc::new(f.to_string()),
|
||||
OwnedValue::Text(text) => text.as_str().to_string(),
|
||||
OwnedValue::Integer(i) => i.to_string(),
|
||||
OwnedValue::Float(f) => f.to_string(),
|
||||
_ => return OwnedValue::Null,
|
||||
};
|
||||
|
||||
@@ -2785,7 +2788,7 @@ fn exec_concat_ws(registers: &[OwnedValue]) -> OwnedValue {
|
||||
result.push_str(&separator);
|
||||
}
|
||||
match reg {
|
||||
OwnedValue::Text(text) => result.push_str(&text.value),
|
||||
OwnedValue::Text(text) => result.push_str(text.as_str()),
|
||||
OwnedValue::Integer(i) => result.push_str(&i.to_string()),
|
||||
OwnedValue::Float(f) => result.push_str(&f.to_string()),
|
||||
_ => continue,
|
||||
@@ -2800,9 +2803,9 @@ fn exec_sign(reg: &OwnedValue) -> Option<OwnedValue> {
|
||||
OwnedValue::Integer(i) => *i as f64,
|
||||
OwnedValue::Float(f) => *f,
|
||||
OwnedValue::Text(s) => {
|
||||
if let Ok(i) = s.value.parse::<i64>() {
|
||||
if let Ok(i) = s.as_str().parse::<i64>() {
|
||||
i as f64
|
||||
} else if let Ok(f) = s.value.parse::<f64>() {
|
||||
} else if let Ok(f) = s.as_str().parse::<f64>() {
|
||||
f
|
||||
} else {
|
||||
return Some(OwnedValue::Null);
|
||||
@@ -2840,7 +2843,7 @@ pub fn exec_soundex(reg: &OwnedValue) -> OwnedValue {
|
||||
OwnedValue::Null => return OwnedValue::build_text(Rc::new("?000".to_string())),
|
||||
OwnedValue::Text(s) => {
|
||||
// return ?000 if non ASCII alphabet character is found
|
||||
if !s.value.chars().all(|c| c.is_ascii_alphabetic()) {
|
||||
if !s.as_str().chars().all(|c| c.is_ascii_alphabetic()) {
|
||||
return OwnedValue::build_text(Rc::new("?000".to_string()));
|
||||
}
|
||||
s.clone()
|
||||
@@ -2850,7 +2853,7 @@ pub fn exec_soundex(reg: &OwnedValue) -> OwnedValue {
|
||||
|
||||
// Remove numbers and spaces
|
||||
let word: String = s
|
||||
.value
|
||||
.as_str()
|
||||
.chars()
|
||||
.filter(|c| !c.is_ascii_digit())
|
||||
.collect::<String>()
|
||||
@@ -2958,7 +2961,7 @@ fn exec_randomblob(reg: &OwnedValue) -> OwnedValue {
|
||||
let length = match reg {
|
||||
OwnedValue::Integer(i) => *i,
|
||||
OwnedValue::Float(f) => *f as i64,
|
||||
OwnedValue::Text(t) => t.value.parse().unwrap_or(1),
|
||||
OwnedValue::Text(t) => t.as_str().parse().unwrap_or(1),
|
||||
_ => 1,
|
||||
}
|
||||
.max(1) as usize;
|
||||
@@ -2974,9 +2977,9 @@ fn exec_quote(value: &OwnedValue) -> OwnedValue {
|
||||
OwnedValue::Integer(_) | OwnedValue::Float(_) => value.to_owned(),
|
||||
OwnedValue::Blob(_) => todo!(),
|
||||
OwnedValue::Text(s) => {
|
||||
let mut quoted = String::with_capacity(s.value.len() + 2);
|
||||
let mut quoted = String::with_capacity(s.as_str().len() + 2);
|
||||
quoted.push('\'');
|
||||
for c in s.value.chars() {
|
||||
for c in s.as_str().chars() {
|
||||
if c == '\0' {
|
||||
break;
|
||||
} else {
|
||||
@@ -3081,7 +3084,7 @@ fn exec_substring(
|
||||
(str_value, start_value, length_value)
|
||||
{
|
||||
let start = *start as usize;
|
||||
let str_len = str.value.len();
|
||||
let str_len = str.as_str().len();
|
||||
|
||||
if start > str_len {
|
||||
return OwnedValue::build_text(Rc::new("".to_string()));
|
||||
@@ -3093,19 +3096,19 @@ fn exec_substring(
|
||||
} else {
|
||||
str_len
|
||||
};
|
||||
let substring = &str.value[start_idx..end.min(str_len)];
|
||||
let substring = &str.as_str()[start_idx..end.min(str_len)];
|
||||
|
||||
OwnedValue::build_text(Rc::new(substring.to_string()))
|
||||
} else if let (OwnedValue::Text(str), OwnedValue::Integer(start)) = (str_value, start_value) {
|
||||
let start = *start as usize;
|
||||
let str_len = str.value.len();
|
||||
let str_len = str.as_str().len();
|
||||
|
||||
if start > str_len {
|
||||
return OwnedValue::build_text(Rc::new("".to_string()));
|
||||
}
|
||||
|
||||
let start_idx = start - 1;
|
||||
let substring = &str.value[start_idx..str_len];
|
||||
let substring = &str.as_str()[start_idx..str_len];
|
||||
|
||||
OwnedValue::build_text(Rc::new(substring.to_string()))
|
||||
} else {
|
||||
@@ -3128,7 +3131,7 @@ fn exec_instr(reg: &OwnedValue, pattern: &OwnedValue) -> OwnedValue {
|
||||
|
||||
let reg_str;
|
||||
let reg = match reg {
|
||||
OwnedValue::Text(s) => s.value.as_str(),
|
||||
OwnedValue::Text(s) => s.as_str(),
|
||||
_ => {
|
||||
reg_str = reg.to_string();
|
||||
reg_str.as_str()
|
||||
@@ -3137,7 +3140,7 @@ fn exec_instr(reg: &OwnedValue, pattern: &OwnedValue) -> OwnedValue {
|
||||
|
||||
let pattern_str;
|
||||
let pattern = match pattern {
|
||||
OwnedValue::Text(s) => s.value.as_str(),
|
||||
OwnedValue::Text(s) => s.as_str(),
|
||||
_ => {
|
||||
pattern_str = pattern.to_string();
|
||||
pattern_str.as_str()
|
||||
@@ -3221,7 +3224,7 @@ fn exec_unicode(reg: &OwnedValue) -> OwnedValue {
|
||||
|
||||
fn _to_float(reg: &OwnedValue) -> f64 {
|
||||
match reg {
|
||||
OwnedValue::Text(x) => x.value.parse().unwrap_or(0.0),
|
||||
OwnedValue::Text(x) => x.as_str().parse().unwrap_or(0.0),
|
||||
OwnedValue::Integer(x) => *x as f64,
|
||||
OwnedValue::Float(x) => *x,
|
||||
_ => 0.0,
|
||||
@@ -3230,7 +3233,7 @@ fn _to_float(reg: &OwnedValue) -> f64 {
|
||||
|
||||
fn exec_round(reg: &OwnedValue, precision: Option<OwnedValue>) -> OwnedValue {
|
||||
let precision = match precision {
|
||||
Some(OwnedValue::Text(x)) => x.value.parse().unwrap_or(0.0),
|
||||
Some(OwnedValue::Text(x)) => x.as_str().parse().unwrap_or(0.0),
|
||||
Some(OwnedValue::Integer(x)) => x as f64,
|
||||
Some(OwnedValue::Float(x)) => x,
|
||||
Some(OwnedValue::Null) => return OwnedValue::Null,
|
||||
@@ -3259,7 +3262,9 @@ fn exec_trim(reg: &OwnedValue, pattern: Option<OwnedValue>) -> OwnedValue {
|
||||
}
|
||||
_ => reg.to_owned(),
|
||||
},
|
||||
(OwnedValue::Text(t), None) => OwnedValue::build_text(Rc::new(t.value.trim().to_string())),
|
||||
(OwnedValue::Text(t), None) => {
|
||||
OwnedValue::build_text(Rc::new(t.as_str().trim().to_string()))
|
||||
}
|
||||
(reg, _) => reg.to_owned(),
|
||||
}
|
||||
}
|
||||
@@ -3279,7 +3284,7 @@ fn exec_ltrim(reg: &OwnedValue, pattern: Option<OwnedValue>) -> OwnedValue {
|
||||
_ => reg.to_owned(),
|
||||
},
|
||||
(OwnedValue::Text(t), None) => {
|
||||
OwnedValue::build_text(Rc::new(t.value.trim_start().to_string()))
|
||||
OwnedValue::build_text(Rc::new(t.as_str().trim_start().to_string()))
|
||||
}
|
||||
(reg, _) => reg.to_owned(),
|
||||
}
|
||||
@@ -3300,7 +3305,7 @@ fn exec_rtrim(reg: &OwnedValue, pattern: Option<OwnedValue>) -> OwnedValue {
|
||||
_ => reg.to_owned(),
|
||||
},
|
||||
(OwnedValue::Text(t), None) => {
|
||||
OwnedValue::build_text(Rc::new(t.value.trim_end().to_string()))
|
||||
OwnedValue::build_text(Rc::new(t.as_str().trim_end().to_string()))
|
||||
}
|
||||
(reg, _) => reg.to_owned(),
|
||||
}
|
||||
@@ -3310,7 +3315,7 @@ fn exec_zeroblob(req: &OwnedValue) -> OwnedValue {
|
||||
let length: i64 = match req {
|
||||
OwnedValue::Integer(i) => *i,
|
||||
OwnedValue::Float(f) => *f as i64,
|
||||
OwnedValue::Text(s) => s.value.parse().unwrap_or(0),
|
||||
OwnedValue::Text(s) => s.as_str().parse().unwrap_or(0),
|
||||
_ => 0,
|
||||
};
|
||||
OwnedValue::Blob(Rc::new(vec![0; length.max(0) as usize]))
|
||||
@@ -3352,7 +3357,7 @@ fn exec_cast(value: &OwnedValue, datatype: &str) -> OwnedValue {
|
||||
let text = String::from_utf8_lossy(b);
|
||||
cast_text_to_real(&text)
|
||||
}
|
||||
OwnedValue::Text(t) => cast_text_to_real(&t.value),
|
||||
OwnedValue::Text(t) => cast_text_to_real(t.as_str()),
|
||||
OwnedValue::Integer(i) => OwnedValue::Float(*i as f64),
|
||||
OwnedValue::Float(f) => OwnedValue::Float(*f),
|
||||
_ => OwnedValue::Float(0.0),
|
||||
@@ -3363,7 +3368,7 @@ fn exec_cast(value: &OwnedValue, datatype: &str) -> OwnedValue {
|
||||
let text = String::from_utf8_lossy(b);
|
||||
cast_text_to_integer(&text)
|
||||
}
|
||||
OwnedValue::Text(t) => cast_text_to_integer(&t.value),
|
||||
OwnedValue::Text(t) => cast_text_to_integer(t.as_str()),
|
||||
OwnedValue::Integer(i) => OwnedValue::Integer(*i),
|
||||
// A cast of a REAL value into an INTEGER results in the integer between the REAL value and zero
|
||||
// that is closest to the REAL value. If a REAL is greater than the greatest possible signed integer (+9223372036854775807)
|
||||
@@ -3386,7 +3391,7 @@ fn exec_cast(value: &OwnedValue, datatype: &str) -> OwnedValue {
|
||||
let text = String::from_utf8_lossy(b);
|
||||
cast_text_to_numeric(&text)
|
||||
}
|
||||
OwnedValue::Text(t) => cast_text_to_numeric(&t.value),
|
||||
OwnedValue::Text(t) => cast_text_to_numeric(t.as_str()),
|
||||
OwnedValue::Integer(i) => OwnedValue::Integer(*i),
|
||||
OwnedValue::Float(f) => OwnedValue::Float(*f),
|
||||
_ => value.clone(), // TODO probably wrong
|
||||
@@ -3414,13 +3419,13 @@ fn exec_replace(source: &OwnedValue, pattern: &OwnedValue, replacement: &OwnedVa
|
||||
// If any of the casts failed, panic as text casting is not expected to fail.
|
||||
match (&source, &pattern, &replacement) {
|
||||
(OwnedValue::Text(source), OwnedValue::Text(pattern), OwnedValue::Text(replacement)) => {
|
||||
if pattern.value.is_empty() {
|
||||
return OwnedValue::build_text(source.value.clone());
|
||||
if pattern.as_str().is_empty() {
|
||||
return OwnedValue::Text(source.clone());
|
||||
}
|
||||
|
||||
let result = source
|
||||
.value
|
||||
.replace(pattern.value.as_str(), &replacement.value);
|
||||
.as_str()
|
||||
.replace(pattern.as_str(), replacement.as_str());
|
||||
OwnedValue::build_text(Rc::new(result))
|
||||
}
|
||||
_ => unreachable!("text cast should never fail"),
|
||||
@@ -3567,7 +3572,7 @@ fn to_f64(reg: &OwnedValue) -> Option<f64> {
|
||||
match reg {
|
||||
OwnedValue::Integer(i) => Some(*i as f64),
|
||||
OwnedValue::Float(f) => Some(*f),
|
||||
OwnedValue::Text(t) => t.value.parse::<f64>().ok(),
|
||||
OwnedValue::Text(t) => t.as_str().parse::<f64>().ok(),
|
||||
OwnedValue::Agg(ctx) => to_f64(ctx.final_value()),
|
||||
_ => None,
|
||||
}
|
||||
@@ -3934,7 +3939,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_unhex() {
|
||||
let input = OwnedValue::build_text(Rc::new(String::from("6F")));
|
||||
let input = OwnedValue::build_text(Rc::new(String::from("6f")));
|
||||
let expected = OwnedValue::Blob(Rc::new(vec![0x6f]));
|
||||
assert_eq!(exec_unhex(&input, None), expected);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn exec_printf(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
|
||||
return Ok(OwnedValue::Null);
|
||||
}
|
||||
let format_str = match &values[0] {
|
||||
OwnedValue::Text(t) => &t.value,
|
||||
OwnedValue::Text(t) => t.as_str(),
|
||||
_ => return Ok(OwnedValue::Null),
|
||||
};
|
||||
|
||||
@@ -44,7 +44,7 @@ pub fn exec_printf(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
|
||||
return Err(LimboError::InvalidArgument("not enough arguments".into()));
|
||||
}
|
||||
match &values[args_index] {
|
||||
OwnedValue::Text(t) => result.push_str(&t.value),
|
||||
OwnedValue::Text(t) => result.push_str(t.as_str()),
|
||||
OwnedValue::Null => result.push_str("(null)"),
|
||||
v => result.push_str(&v.to_string()),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user