core: Parse UTF-8 strings lazily

This commit is contained in:
Pekka Enberg
2025-02-06 12:26:25 +02:00
parent c9dcef84a2
commit f9828e0e6f
9 changed files with 188 additions and 183 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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(&reg_value_argument, &reg_value_type.value);
let result =
exec_cast(&reg_value_argument, &reg_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 &registers[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);

View File

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