mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-17 00:24:21 +01:00
Change Value::Text to use a Cow<'static, str> instead of Vec<u8>
This commit is contained in:
@@ -12,7 +12,7 @@ impl From<Value> for turso_core::Value {
|
||||
Value::Null => turso_core::Value::Null,
|
||||
Value::Integer(n) => turso_core::Value::Integer(n),
|
||||
Value::Real(n) => turso_core::Value::Float(n),
|
||||
Value::Text(t) => turso_core::Value::from_text(&t),
|
||||
Value::Text(t) => turso_core::Value::from_text(t),
|
||||
Value::Blob(items) => turso_core::Value::from_blob(items),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@ pub extern "system" fn Java_tech_turso_core_TursoStatement_bindText<'local>(
|
||||
|
||||
stmt.stmt.bind_at(
|
||||
NonZero::new(position as usize).unwrap(),
|
||||
Value::build_text(text.as_str()),
|
||||
Value::build_text(text),
|
||||
);
|
||||
SQLITE_OK
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ fn js_value_to_core(value: Either5<Null, i64, f64, String, Vec<u8>>) -> turso_co
|
||||
Either5::A(_) => turso_core::Value::Null,
|
||||
Either5::B(value) => turso_core::Value::Integer(value),
|
||||
Either5::C(value) => turso_core::Value::Float(value),
|
||||
Either5::D(value) => turso_core::Value::Text(turso_core::types::Text::new(&value)),
|
||||
Either5::D(value) => turso_core::Value::Text(turso_core::types::Text::new(value)),
|
||||
Either5::E(value) => turso_core::Value::Blob(value),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ impl From<Value> for turso_core::Value {
|
||||
Value::Null => turso_core::Value::Null,
|
||||
Value::Integer(n) => turso_core::Value::Integer(n),
|
||||
Value::Real(n) => turso_core::Value::Float(n),
|
||||
Value::Text(t) => turso_core::Value::from_text(&t),
|
||||
Value::Text(t) => turso_core::Value::from_text(t),
|
||||
Value::Blob(items) => turso_core::Value::from_blob(items),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1722,7 +1722,7 @@ impl Limbo {
|
||||
Value::Float(f) => write!(out, "{f}").map(|_| ()),
|
||||
Value::Text(s) => {
|
||||
out.write_all(b"'")?;
|
||||
let bytes = &s.value;
|
||||
let bytes = s.value.as_bytes();
|
||||
let mut i = 0;
|
||||
while i < bytes.len() {
|
||||
let b = bytes[i];
|
||||
|
||||
@@ -250,7 +250,7 @@ impl AggFunc {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> &str {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Avg => "avg",
|
||||
Self::Count0 => "count",
|
||||
@@ -617,7 +617,7 @@ pub enum Func {
|
||||
impl Display for Func {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Agg(agg_func) => write!(f, "{}", agg_func.to_string()),
|
||||
Self::Agg(agg_func) => write!(f, "{}", agg_func.as_str()),
|
||||
Self::Scalar(scalar_func) => write!(f, "{scalar_func}"),
|
||||
Self::Math(math_func) => write!(f, "{math_func}"),
|
||||
Self::Vector(vector_func) => write!(f, "{vector_func}"),
|
||||
|
||||
@@ -96,14 +96,14 @@ fn modify_dt(dt: &mut NaiveDateTime, mods: &[Register], output_type: DateTimeOut
|
||||
|
||||
fn format_dt(dt: NaiveDateTime, output_type: DateTimeOutput, subsec: bool) -> Value {
|
||||
match output_type {
|
||||
DateTimeOutput::Date => Value::from_text(dt.format("%Y-%m-%d").to_string().as_str()),
|
||||
DateTimeOutput::Date => Value::from_text(dt.format("%Y-%m-%d").to_string()),
|
||||
DateTimeOutput::Time => {
|
||||
let t = if subsec {
|
||||
dt.format("%H:%M:%S%.3f").to_string()
|
||||
} else {
|
||||
dt.format("%H:%M:%S").to_string()
|
||||
};
|
||||
Value::from_text(t.as_str())
|
||||
Value::from_text(t)
|
||||
}
|
||||
DateTimeOutput::DateTime => {
|
||||
let t = if subsec && dt.nanosecond() != 0 {
|
||||
@@ -111,11 +111,9 @@ fn format_dt(dt: NaiveDateTime, output_type: DateTimeOutput, subsec: bool) -> Va
|
||||
} else {
|
||||
dt.format("%Y-%m-%d %H:%M:%S").to_string()
|
||||
};
|
||||
Value::from_text(t.as_str())
|
||||
}
|
||||
DateTimeOutput::StrfTime(format_str) => {
|
||||
Value::from_text(strftime_format(&dt, &format_str).as_str())
|
||||
Value::from_text(t)
|
||||
}
|
||||
DateTimeOutput::StrfTime(format_str) => Value::from_text(strftime_format(&dt, &format_str)),
|
||||
DateTimeOutput::JuliaDay => Value::Float(to_julian_day_exact(&dt)),
|
||||
}
|
||||
}
|
||||
@@ -832,7 +830,7 @@ mod tests {
|
||||
let test_date_str = "2024-07-21";
|
||||
let next_date_str = "2024-07-22";
|
||||
|
||||
let test_cases = vec![
|
||||
let test_cases: Vec<(Value, &str)> = vec![
|
||||
// Format 1: YYYY-MM-DD (no timezone applicable)
|
||||
(Value::build_text("2024-07-21"), test_date_str),
|
||||
// Format 2: YYYY-MM-DD HH:MM
|
||||
@@ -936,7 +934,7 @@ mod tests {
|
||||
let result = exec_date(&[Register::Value(input.clone())]);
|
||||
assert_eq!(
|
||||
result,
|
||||
Value::build_text(expected),
|
||||
Value::build_text(expected.to_string()),
|
||||
"Failed for input: {input:?}"
|
||||
);
|
||||
}
|
||||
@@ -1428,7 +1426,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn text(value: &str) -> Register {
|
||||
Register::Value(Value::build_text(value))
|
||||
Register::Value(Value::build_text(value.to_string()))
|
||||
}
|
||||
|
||||
fn format(dt: NaiveDateTime) -> String {
|
||||
|
||||
@@ -257,7 +257,7 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
fn text(value: &str) -> Register {
|
||||
Register::Value(Value::build_text(value))
|
||||
Register::Value(Value::build_text(value.to_string()))
|
||||
}
|
||||
|
||||
fn integer(value: i64) -> Register {
|
||||
|
||||
@@ -271,7 +271,7 @@ impl CompiledExpression {
|
||||
}
|
||||
}
|
||||
Literal::String(s) => {
|
||||
let cleaned = s.trim_matches('\'').trim_matches('"');
|
||||
let cleaned = s.trim_matches('\'').trim_matches('"').to_string();
|
||||
Value::Text(Text::new(cleaned))
|
||||
}
|
||||
Literal::Null => Value::Null,
|
||||
|
||||
@@ -691,7 +691,7 @@ mod tests {
|
||||
i,
|
||||
vec![
|
||||
Value::Integer(i),
|
||||
Value::Text(Text::new(&category)),
|
||||
Value::Text(Text::new(category)),
|
||||
Value::Integer(i * 10),
|
||||
],
|
||||
);
|
||||
@@ -4442,7 +4442,7 @@ mod tests {
|
||||
.iter()
|
||||
.map(|(row, _)| {
|
||||
let category = match &row.values[0] {
|
||||
Value::Text(s) => String::from_utf8(s.value.clone()).unwrap(),
|
||||
Value::Text(s) => s.value.clone().into_owned(),
|
||||
_ => panic!("Expected text for category"),
|
||||
};
|
||||
let value = match &row.values[1] {
|
||||
|
||||
@@ -173,7 +173,7 @@ mod tests {
|
||||
// Helper function to create test Value and Jsonb from JSON string
|
||||
fn create_test_pair(json_str: &str) -> (Value, Jsonb) {
|
||||
// Create Value as text representation of JSON
|
||||
let key = Value::build_text(json_str);
|
||||
let key = Value::build_text(json_str.to_string());
|
||||
|
||||
// Create Jsonb from the same JSON string
|
||||
let value = Jsonb::from_str(json_str).unwrap();
|
||||
|
||||
@@ -53,10 +53,7 @@ pub fn get_json(json_value: &Value, indent: Option<&str>) -> crate::Result<Value
|
||||
Value::Blob(b) => {
|
||||
let jsonbin = Jsonb::new(b.len(), Some(b));
|
||||
jsonbin.element_type()?;
|
||||
Ok(Value::Text(Text {
|
||||
value: jsonbin.to_string().into_bytes(),
|
||||
subtype: TextSubtype::Json,
|
||||
}))
|
||||
Ok(Value::Text(Text::json(jsonbin.to_string())))
|
||||
}
|
||||
Value::Null => Ok(Value::Null),
|
||||
_ => {
|
||||
@@ -480,15 +477,9 @@ pub fn json_string_to_db_type(
|
||||
if matches!(flag, OutputVariant::ElementType) {
|
||||
json_string.remove(json_string.len() - 1);
|
||||
json_string.remove(0);
|
||||
Ok(Value::Text(Text {
|
||||
value: json_string.into_bytes(),
|
||||
subtype: TextSubtype::Json,
|
||||
}))
|
||||
Ok(Value::Text(Text::json(json_string)))
|
||||
} else {
|
||||
Ok(Value::Text(Text {
|
||||
value: json_string.into_bytes(),
|
||||
subtype: TextSubtype::Text,
|
||||
}))
|
||||
Ok(Value::Text(Text::new(json_string)))
|
||||
}
|
||||
}
|
||||
ElementType::FLOAT5 | ElementType::FLOAT => Ok(Value::Float(
|
||||
|
||||
@@ -231,7 +231,13 @@ impl InternalVirtualTableCursor for JsonEachCursor {
|
||||
}
|
||||
if args.len() == 2 && matches!(self.traversal_mode, JsonTraversalMode::Tree) {
|
||||
if let Value::Text(ref text) = args[1] {
|
||||
if !text.value.is_empty() && text.value.windows(3).any(|chars| chars == b"[#-") {
|
||||
if !text.value.is_empty()
|
||||
&& text
|
||||
.value
|
||||
.as_bytes()
|
||||
.windows(3)
|
||||
.any(|chars| chars == b"[#-")
|
||||
{
|
||||
return Err(LimboError::InvalidArgument(
|
||||
"Json paths with negative indices in json_tree are not supported yet"
|
||||
.to_owned(),
|
||||
@@ -495,7 +501,7 @@ mod columns {
|
||||
fn key_representation(&self) -> Value {
|
||||
match self {
|
||||
Key::Integer(ref i) => Value::Integer(*i),
|
||||
Key::String(ref s) => Value::Text(Text::new(&s.to_owned().replace("\\\"", "\""))),
|
||||
Key::String(ref s) => Value::Text(Text::new(s.to_owned().replace("\\\"", "\""))),
|
||||
Key::None => Value::Null,
|
||||
}
|
||||
}
|
||||
@@ -572,7 +578,7 @@ mod columns {
|
||||
| jsonb::ElementType::TEXTRAW => {
|
||||
let s = value.to_string();
|
||||
let s = (s[1..s.len() - 1]).to_string();
|
||||
Ok(Value::Text(Text::new(&s)))
|
||||
Ok(Value::Text(Text::new(s)))
|
||||
}
|
||||
jsonb::ElementType::ARRAY => Ok(Value::Null),
|
||||
jsonb::ElementType::OBJECT => Ok(Value::Null),
|
||||
@@ -599,11 +605,11 @@ mod columns {
|
||||
}
|
||||
|
||||
pub(super) fn fullkey(&self) -> Value {
|
||||
Value::Text(Text::new(&self.fullkey))
|
||||
Value::Text(Text::new(self.fullkey.clone()))
|
||||
}
|
||||
|
||||
pub(super) fn path(&self) -> Value {
|
||||
Value::Text(Text::new(&self.innermost_container_path))
|
||||
Value::Text(Text::new(self.innermost_container_path.clone()))
|
||||
}
|
||||
|
||||
pub(super) fn parent(&self) -> Value {
|
||||
|
||||
@@ -104,7 +104,7 @@ impl MvccTestDbNoConn {
|
||||
}
|
||||
|
||||
pub(crate) fn generate_simple_string_row(table_id: MVTableId, id: i64, data: &str) -> Row {
|
||||
let record = ImmutableRecord::from_values(&[Value::Text(Text::new(data))], 1);
|
||||
let record = ImmutableRecord::from_values(&[Value::Text(Text::new(data.to_string()))], 1);
|
||||
Row {
|
||||
id: RowID {
|
||||
table_id,
|
||||
@@ -116,7 +116,7 @@ pub(crate) fn generate_simple_string_row(table_id: MVTableId, id: i64, data: &st
|
||||
}
|
||||
|
||||
pub(crate) fn generate_simple_string_record(data: &str) -> ImmutableRecord {
|
||||
ImmutableRecord::from_values(&[Value::Text(Text::new(data))], 1)
|
||||
ImmutableRecord::from_values(&[Value::Text(Text::new(data.to_string()))], 1)
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -740,7 +740,7 @@ fn setup_test_db() -> (MvccTestDb, u64) {
|
||||
|
||||
for (row_id, data) in test_rows.iter() {
|
||||
let id = RowID::new(table_id, *row_id);
|
||||
let record = ImmutableRecord::from_values(&[Value::Text(Text::new(data))], 1);
|
||||
let record = ImmutableRecord::from_values(&[Value::Text(Text::new(data.to_string()))], 1);
|
||||
let row = Row::new(id, record.as_blob().to_vec(), 1);
|
||||
db.mvcc_store.insert(tx_id, row).unwrap();
|
||||
}
|
||||
@@ -765,7 +765,7 @@ fn setup_lazy_db(initial_keys: &[i64]) -> (MvccTestDb, u64) {
|
||||
for i in initial_keys {
|
||||
let id = RowID::new(table_id.into(), *i);
|
||||
let data = format!("row{i}");
|
||||
let record = ImmutableRecord::from_values(&[Value::Text(Text::new(&data))], 1);
|
||||
let record = ImmutableRecord::from_values(&[Value::Text(Text::new(data))], 1);
|
||||
let row = Row::new(id, record.as_blob().to_vec(), 1);
|
||||
db.mvcc_store.insert(tx_id, row).unwrap();
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ impl PragmaVirtualTableCursor {
|
||||
0 => self
|
||||
.arg
|
||||
.as_ref()
|
||||
.map_or(Value::Null, |arg| Value::from_text(arg)),
|
||||
.map_or(Value::Null, |arg| Value::from_text(arg.to_string())),
|
||||
_ => Value::Null,
|
||||
};
|
||||
Ok(value)
|
||||
|
||||
@@ -10292,10 +10292,7 @@ mod tests {
|
||||
for (i, huge_text) in huge_texts.iter().enumerate().take(iterations) {
|
||||
let mut cursor = BTreeCursor::new_table(pager.clone(), root_page, num_columns);
|
||||
tracing::info!("INSERT INTO t VALUES ({});", i,);
|
||||
let regs = &[Register::Value(Value::Text(Text {
|
||||
value: huge_text.as_bytes().to_vec(),
|
||||
subtype: crate::types::TextSubtype::Text,
|
||||
}))];
|
||||
let regs = &[Register::Value(Value::Text(Text::new(huge_text.clone())))];
|
||||
let value = ImmutableRecord::from_registers(regs, regs.len());
|
||||
tracing::trace!("before insert {}", i);
|
||||
tracing::debug!(
|
||||
|
||||
@@ -241,7 +241,7 @@ fn link_with_window(
|
||||
original_expr: expr.clone(),
|
||||
});
|
||||
} else {
|
||||
crate::bail_parse_error!("misuse of window function: {}()", func.to_string());
|
||||
crate::bail_parse_error!("misuse of window function: {}()", func.as_str());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ use crate::vdbe::sorter::Sorter;
|
||||
use crate::vdbe::Register;
|
||||
use crate::vtab::VirtualTableCursor;
|
||||
use crate::{Completion, CompletionError, Result, IO};
|
||||
use std::borrow::Borrow;
|
||||
use std::borrow::{Borrow, Cow};
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::ops::Deref;
|
||||
use std::task::Waker;
|
||||
@@ -63,7 +63,7 @@ pub enum TextSubtype {
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Text {
|
||||
pub value: Vec<u8>,
|
||||
pub value: Cow<'static, str>,
|
||||
pub subtype: TextSubtype,
|
||||
}
|
||||
|
||||
@@ -74,22 +74,22 @@ impl Display for Text {
|
||||
}
|
||||
|
||||
impl Text {
|
||||
pub fn new(value: &str) -> Self {
|
||||
pub fn new(value: impl Into<Cow<'static, str>>) -> Self {
|
||||
Self {
|
||||
value: value.as_bytes().to_vec(),
|
||||
value: value.into(),
|
||||
subtype: TextSubtype::Text,
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "json")]
|
||||
pub fn json(value: String) -> Self {
|
||||
Self {
|
||||
value: value.into_bytes(),
|
||||
value: value.into(),
|
||||
subtype: TextSubtype::Json,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
unsafe { std::str::from_utf8_unchecked(self.value.as_ref()) }
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,8 +133,9 @@ pub trait Extendable<T> {
|
||||
impl<T: AnyText> Extendable<T> for Text {
|
||||
#[inline(always)]
|
||||
fn do_extend(&mut self, other: &T) {
|
||||
self.value.clear();
|
||||
self.value.extend_from_slice(other.as_ref().as_bytes());
|
||||
let value = self.value.to_mut();
|
||||
value.clear();
|
||||
value.push_str(other.as_ref());
|
||||
self.subtype = other.subtype();
|
||||
}
|
||||
}
|
||||
@@ -188,7 +189,7 @@ impl AsRef<str> for Text {
|
||||
impl From<&str> for Text {
|
||||
fn from(value: &str) -> Self {
|
||||
Text {
|
||||
value: value.as_bytes().to_vec(),
|
||||
value: value.to_owned().into(),
|
||||
subtype: TextSubtype::Text,
|
||||
}
|
||||
}
|
||||
@@ -197,7 +198,7 @@ impl From<&str> for Text {
|
||||
impl From<String> for Text {
|
||||
fn from(value: String) -> Self {
|
||||
Text {
|
||||
value: value.into_bytes(),
|
||||
value: Cow::from(value),
|
||||
subtype: TextSubtype::Text,
|
||||
}
|
||||
}
|
||||
@@ -205,7 +206,7 @@ impl From<String> for Text {
|
||||
|
||||
impl From<Text> for String {
|
||||
fn from(value: Text) -> Self {
|
||||
String::from_utf8(value.value).unwrap()
|
||||
value.value.into_owned()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +360,7 @@ impl Value {
|
||||
Value::Integer(v) => ValueRef::Integer(*v),
|
||||
Value::Float(v) => ValueRef::Float(*v),
|
||||
Value::Text(v) => ValueRef::Text(TextRef {
|
||||
value: &v.value,
|
||||
value: v.value.as_bytes(),
|
||||
subtype: v.subtype,
|
||||
}),
|
||||
Value::Blob(v) => ValueRef::Blob(v.as_slice()),
|
||||
@@ -367,8 +368,8 @@ impl Value {
|
||||
}
|
||||
|
||||
// A helper function that makes building a text Value easier.
|
||||
pub fn build_text(text: impl AsRef<str>) -> Self {
|
||||
Self::Text(Text::new(text.as_ref()))
|
||||
pub fn build_text(text: impl Into<Cow<'static, str>>) -> Self {
|
||||
Self::Text(Text::new(text))
|
||||
}
|
||||
|
||||
pub fn to_blob(&self) -> Option<&[u8]> {
|
||||
@@ -424,7 +425,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_text(text: &str) -> Self {
|
||||
pub fn from_text(text: impl Into<Cow<'static, str>>) -> Self {
|
||||
Value::Text(Text::new(text))
|
||||
}
|
||||
|
||||
@@ -453,7 +454,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
Value::Float(f) => out.extend_from_slice(&f.to_be_bytes()),
|
||||
Value::Text(t) => out.extend_from_slice(&t.value),
|
||||
Value::Text(t) => out.extend_from_slice(t.value.as_bytes()),
|
||||
Value::Blob(b) => out.extend_from_slice(b),
|
||||
};
|
||||
}
|
||||
@@ -535,7 +536,7 @@ impl Value {
|
||||
if v.is_json() {
|
||||
return Ok(Value::Text(Text::json(text.to_string())));
|
||||
}
|
||||
Ok(Value::build_text(text))
|
||||
Ok(Value::build_text(text.to_string()))
|
||||
}
|
||||
ExtValueType::Blob => {
|
||||
let Some(blob) = v.to_blob() else {
|
||||
@@ -828,26 +829,26 @@ impl std::ops::AddAssign for Value {
|
||||
*float_left += float_right;
|
||||
}
|
||||
(Self::Text(string_left), Self::Text(string_right)) => {
|
||||
string_left.value.extend_from_slice(&string_right.value);
|
||||
string_left.value.to_mut().push_str(&string_right.value);
|
||||
string_left.subtype = TextSubtype::Text;
|
||||
}
|
||||
(Self::Text(string_left), Self::Integer(int_right)) => {
|
||||
let string_right = int_right.to_string();
|
||||
string_left.value.extend_from_slice(string_right.as_bytes());
|
||||
string_left.value.to_mut().push_str(&string_right);
|
||||
string_left.subtype = TextSubtype::Text;
|
||||
}
|
||||
(Self::Integer(int_left), Self::Text(string_right)) => {
|
||||
let string_left = int_left.to_string();
|
||||
*self = Self::build_text(&(string_left + string_right.as_str()));
|
||||
*self = Self::build_text(string_left + string_right.as_str());
|
||||
}
|
||||
(Self::Text(string_left), Self::Float(float_right)) => {
|
||||
let string_right = Self::Float(float_right).to_string();
|
||||
string_left.value.extend_from_slice(string_right.as_bytes());
|
||||
string_left.value.to_mut().push_str(&string_right);
|
||||
string_left.subtype = TextSubtype::Text;
|
||||
}
|
||||
(Self::Float(float_left), Self::Text(string_right)) => {
|
||||
let string_left = Self::Float(*float_left).to_string();
|
||||
*self = Self::build_text(&(string_left + string_right.as_str()));
|
||||
*self = Self::build_text(string_left + string_right.as_str());
|
||||
}
|
||||
(_, Self::Null) => {}
|
||||
(Self::Null, rhs) => *self = rhs,
|
||||
@@ -1132,7 +1133,7 @@ impl ImmutableRecord {
|
||||
}
|
||||
Value::Float(f) => writer.extend_from_slice(&f.to_be_bytes()),
|
||||
Value::Text(t) => {
|
||||
writer.extend_from_slice(&t.value);
|
||||
writer.extend_from_slice(t.value.as_bytes());
|
||||
}
|
||||
Value::Blob(b) => {
|
||||
writer.extend_from_slice(b);
|
||||
@@ -1544,7 +1545,7 @@ impl<'a> ValueRef<'a> {
|
||||
ValueRef::Integer(i) => Value::Integer(*i),
|
||||
ValueRef::Float(f) => Value::Float(*f),
|
||||
ValueRef::Text(text) => Value::Text(Text {
|
||||
value: text.value.to_vec(),
|
||||
value: text.as_str().to_string().into(),
|
||||
subtype: text.subtype,
|
||||
}),
|
||||
ValueRef::Blob(b) => Value::Blob(b.to_vec()),
|
||||
@@ -2394,7 +2395,7 @@ impl Record {
|
||||
}
|
||||
}
|
||||
Value::Float(f) => buf.extend_from_slice(&f.to_be_bytes()),
|
||||
Value::Text(t) => buf.extend_from_slice(&t.value),
|
||||
Value::Text(t) => buf.extend_from_slice(t.value.as_bytes()),
|
||||
Value::Blob(b) => buf.extend_from_slice(b),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1743,8 +1743,9 @@ pub fn op_column(
|
||||
// SAFETY: We know the text is valid UTF-8 because we only accept valid UTF-8 and the serial type is TEXT.
|
||||
let text =
|
||||
unsafe { std::str::from_utf8_unchecked(buf) };
|
||||
state.registers[*dest] =
|
||||
Register::Value(Value::Text(Text::new(text)));
|
||||
state.registers[*dest] = Register::Value(Value::Text(
|
||||
Text::new(text.to_string()),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2678,7 +2679,7 @@ pub fn op_string8(
|
||||
mv_store: Option<&Arc<MvStore>>,
|
||||
) -> Result<InsnFunctionStepResult> {
|
||||
load_insn!(String8 { value, dest }, insn);
|
||||
state.registers[*dest] = Register::Value(Value::build_text(value));
|
||||
state.registers[*dest] = Register::Value(Value::build_text(value.clone()));
|
||||
state.pc += 1;
|
||||
Ok(InsnFunctionStepResult::Step)
|
||||
}
|
||||
|
||||
@@ -484,7 +484,7 @@ pub fn insn_to_row(
|
||||
*db as i32,
|
||||
0,
|
||||
0,
|
||||
Value::build_text(table_name),
|
||||
Value::build_text(table_name.clone()),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -659,7 +659,7 @@ pub fn insn_to_row(
|
||||
*err_code as i32,
|
||||
0,
|
||||
0,
|
||||
Value::build_text(description),
|
||||
Value::build_text(description.clone()),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -672,7 +672,7 @@ pub fn insn_to_row(
|
||||
*err_code as i32,
|
||||
0,
|
||||
*target_reg as i32,
|
||||
Value::build_text(description),
|
||||
Value::build_text(description.clone()),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -750,7 +750,7 @@ pub fn insn_to_row(
|
||||
0,
|
||||
*dest as i32,
|
||||
0,
|
||||
Value::build_text(value),
|
||||
Value::build_text(value.clone()),
|
||||
0,
|
||||
format!("r[{dest}]='{value}'"),
|
||||
),
|
||||
@@ -963,7 +963,7 @@ pub fn insn_to_row(
|
||||
0,
|
||||
*col as i32,
|
||||
*acc_reg as i32,
|
||||
Value::build_text(func.to_string()),
|
||||
Value::build_text(func.as_str()),
|
||||
0,
|
||||
format!("accum=r[{}] step(r[{}])", *acc_reg, *col),
|
||||
),
|
||||
@@ -972,7 +972,7 @@ pub fn insn_to_row(
|
||||
0,
|
||||
*register as i32,
|
||||
0,
|
||||
Value::build_text(func.to_string()),
|
||||
Value::build_text(func.as_str()),
|
||||
0,
|
||||
format!("accum=r[{}]", *register),
|
||||
),
|
||||
@@ -981,7 +981,7 @@ pub fn insn_to_row(
|
||||
0,
|
||||
*acc_reg as i32,
|
||||
*dest_reg as i32,
|
||||
Value::build_text(func.to_string()),
|
||||
Value::build_text(func.as_str()),
|
||||
0,
|
||||
format!("accum=r[{}] dest=r[{}]", *acc_reg, *dest_reg),
|
||||
),
|
||||
@@ -1157,7 +1157,7 @@ pub fn insn_to_row(
|
||||
*cursor as i32,
|
||||
*record_reg as i32,
|
||||
*key_reg as i32,
|
||||
Value::build_text(table_name),
|
||||
Value::build_text(table_name.clone()),
|
||||
flag.0 as u16,
|
||||
format!("intkey=r[{key_reg}] data=r[{record_reg}]"),
|
||||
),
|
||||
@@ -1166,7 +1166,7 @@ pub fn insn_to_row(
|
||||
*cursor_id as i32,
|
||||
0,
|
||||
0,
|
||||
Value::build_text(table_name),
|
||||
Value::build_text(table_name.clone()),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -1364,7 +1364,7 @@ pub fn insn_to_row(
|
||||
*db as i32,
|
||||
0,
|
||||
0,
|
||||
Value::build_text(table_name),
|
||||
Value::build_text(table_name.clone()),
|
||||
0,
|
||||
format!("DROP TABLE {table_name}"),
|
||||
),
|
||||
@@ -1373,7 +1373,7 @@ pub fn insn_to_row(
|
||||
*db as i32,
|
||||
0,
|
||||
0,
|
||||
Value::build_text(view_name),
|
||||
Value::build_text(view_name.clone()),
|
||||
0,
|
||||
format!("DROP VIEW {view_name}"),
|
||||
),
|
||||
@@ -1792,7 +1792,7 @@ pub fn insn_to_row(
|
||||
*db as i32,
|
||||
*dest as i32,
|
||||
0,
|
||||
Value::build_text(new_mode.as_ref().unwrap_or(&String::new())),
|
||||
Value::build_text(new_mode.clone().unwrap_or(String::new())),
|
||||
0,
|
||||
format!("r[{dest}]=journal_mode(db[{db}]{})",
|
||||
new_mode.as_ref().map_or(String::new(), |m| format!(",'{m}'"))),
|
||||
@@ -1802,7 +1802,7 @@ pub fn insn_to_row(
|
||||
reg.unwrap_or(0) as i32,
|
||||
0,
|
||||
0,
|
||||
Value::build_text(collation.to_string().as_str()),
|
||||
Value::build_text(collation.to_string()),
|
||||
0,
|
||||
format!("collation={collation}"),
|
||||
),
|
||||
@@ -1820,7 +1820,7 @@ pub fn insn_to_row(
|
||||
*p1 as i32,
|
||||
p2.as_ref().map(|p| *p).unwrap_or(0) as i32,
|
||||
0,
|
||||
Value::build_text(detail.as_str()),
|
||||
Value::build_text(detail.clone()),
|
||||
0,
|
||||
String::new(),
|
||||
),
|
||||
|
||||
@@ -666,7 +666,7 @@ impl Program {
|
||||
state.registers[4] = Register::Value(Value::Integer(p3 as i64));
|
||||
state.registers[5] = Register::Value(p4);
|
||||
state.registers[6] = Register::Value(Value::Integer(p5 as i64));
|
||||
state.registers[7] = Register::Value(Value::from_text(&comment));
|
||||
state.registers[7] = Register::Value(Value::from_text(comment));
|
||||
state.result_row = Some(Row {
|
||||
values: &state.registers[0] as *const Register,
|
||||
count: EXPLAIN_COLUMNS.len(),
|
||||
@@ -712,7 +712,7 @@ impl Program {
|
||||
state.registers[1] =
|
||||
Register::Value(Value::Integer(p2.as_ref().map(|p| *p).unwrap_or(0) as i64));
|
||||
state.registers[2] = Register::Value(Value::Integer(0));
|
||||
state.registers[3] = Register::Value(Value::from_text(detail.as_str()));
|
||||
state.registers[3] = Register::Value(Value::from_text(detail.clone()));
|
||||
state.result_row = Some(Row {
|
||||
values: &state.registers[0] as *const Register,
|
||||
count: EXPLAIN_QUERY_PLAN_COLUMNS.len(),
|
||||
|
||||
@@ -425,7 +425,7 @@ impl Value {
|
||||
end_byte_idx = ceil_char_boundary(s, end_byte_idx + 1);
|
||||
end -= 1;
|
||||
}
|
||||
Value::build_text(&s[start_byte_idx..end_byte_idx])
|
||||
Value::build_text(s[start_byte_idx..end_byte_idx].to_string())
|
||||
} else {
|
||||
Value::Null
|
||||
}
|
||||
@@ -570,9 +570,11 @@ impl Value {
|
||||
(Value::Text(_) | Value::Integer(_) | Value::Float(_), Some(pattern)) => {
|
||||
let pattern_chars: Vec<char> = pattern.to_string().chars().collect();
|
||||
let text = self.to_string();
|
||||
Value::build_text(trim_type.trim(&text, &pattern_chars))
|
||||
Value::build_text(trim_type.trim(&text, &pattern_chars).to_string())
|
||||
}
|
||||
(Value::Text(t), None) => {
|
||||
Value::build_text(trim_type.trim(t.as_str(), &[' ']).to_string())
|
||||
}
|
||||
(Value::Text(t), None) => Value::build_text(trim_type.trim(t.as_str(), &[' '])),
|
||||
(reg, _) => reg.to_owned(),
|
||||
}
|
||||
}
|
||||
@@ -900,9 +902,9 @@ impl Value {
|
||||
|
||||
pub fn exec_concat(&self, rhs: &Value) -> Value {
|
||||
if let (Value::Blob(lhs), Value::Blob(rhs)) = (self, rhs) {
|
||||
return Value::build_text(String::from_utf8_lossy(
|
||||
&[lhs.as_slice(), rhs.as_slice()].concat(),
|
||||
));
|
||||
return Value::build_text(
|
||||
String::from_utf8_lossy(&[lhs.as_slice(), rhs.as_slice()].concat()).into_owned(),
|
||||
);
|
||||
}
|
||||
|
||||
let Some(lhs) = self.cast_text() else {
|
||||
|
||||
@@ -1019,7 +1019,7 @@ pub unsafe extern "C" fn sqlite3_bind_text(
|
||||
};
|
||||
|
||||
if ptr_val == transient_ptr {
|
||||
let val = Value::from_text(&str_value);
|
||||
let val = Value::from_text(str_value);
|
||||
stmt_ref
|
||||
.stmt
|
||||
.bind_at(NonZero::new_unchecked(idx as usize), val);
|
||||
|
||||
@@ -514,7 +514,10 @@ pub async fn has_table<Ctx>(
|
||||
) -> Result<bool> {
|
||||
let mut stmt =
|
||||
conn.prepare("SELECT COUNT(*) FROM sqlite_schema WHERE type = 'table' AND name = ?")?;
|
||||
stmt.bind_at(1.try_into().unwrap(), Value::Text(Text::new(table_name)));
|
||||
stmt.bind_at(
|
||||
1.try_into().unwrap(),
|
||||
Value::Text(Text::new(table_name.to_string())),
|
||||
);
|
||||
|
||||
let count = match run_stmt_expect_one_row(coro, &mut stmt).await? {
|
||||
Some(row) => row[0]
|
||||
@@ -557,7 +560,7 @@ pub async fn update_last_change_id<Ctx>(
|
||||
let mut select_stmt = conn.prepare(TURSO_SYNC_SELECT_LAST_CHANGE_ID)?;
|
||||
select_stmt.bind_at(
|
||||
1.try_into().unwrap(),
|
||||
turso_core::Value::Text(turso_core::types::Text::new(client_id)),
|
||||
turso_core::Value::Text(turso_core::types::Text::new(client_id.to_string())),
|
||||
);
|
||||
let row = run_stmt_expect_one_row(coro, &mut select_stmt).await?;
|
||||
tracing::info!("update_last_change_id(client_id={client_id}): selected client row if any");
|
||||
@@ -568,7 +571,7 @@ pub async fn update_last_change_id<Ctx>(
|
||||
update_stmt.bind_at(2.try_into().unwrap(), turso_core::Value::Integer(change_id));
|
||||
update_stmt.bind_at(
|
||||
3.try_into().unwrap(),
|
||||
turso_core::Value::Text(turso_core::types::Text::new(client_id)),
|
||||
turso_core::Value::Text(turso_core::types::Text::new(client_id.to_string())),
|
||||
);
|
||||
run_stmt_ignore_rows(coro, &mut update_stmt).await?;
|
||||
tracing::info!("update_last_change_id(client_id={client_id}): updated row for the client");
|
||||
@@ -576,7 +579,7 @@ pub async fn update_last_change_id<Ctx>(
|
||||
let mut update_stmt = conn.prepare(TURSO_SYNC_INSERT_LAST_CHANGE_ID)?;
|
||||
update_stmt.bind_at(
|
||||
1.try_into().unwrap(),
|
||||
turso_core::Value::Text(turso_core::types::Text::new(client_id)),
|
||||
turso_core::Value::Text(turso_core::types::Text::new(client_id.to_string())),
|
||||
);
|
||||
update_stmt.bind_at(2.try_into().unwrap(), turso_core::Value::Integer(pull_gen));
|
||||
update_stmt.bind_at(3.try_into().unwrap(), turso_core::Value::Integer(change_id));
|
||||
@@ -603,7 +606,10 @@ pub async fn read_last_change_id<Ctx>(
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
|
||||
select_last_change_id_stmt.bind_at(1.try_into().unwrap(), Value::Text(Text::new(client_id)));
|
||||
select_last_change_id_stmt.bind_at(
|
||||
1.try_into().unwrap(),
|
||||
Value::Text(Text::new(client_id.to_string())),
|
||||
);
|
||||
|
||||
match run_stmt_expect_one_row(coro, &mut select_last_change_id_stmt).await? {
|
||||
Some(row) => {
|
||||
|
||||
@@ -67,7 +67,7 @@ fn record<const N: usize>(values: [Value; N]) -> Vec<u8> {
|
||||
Value::Null => turso_core::Value::Null,
|
||||
Value::Integer(x) => turso_core::Value::Integer(x),
|
||||
Value::Real(x) => turso_core::Value::Float(x),
|
||||
Value::Text(x) => turso_core::Value::Text(turso_core::types::Text::new(&x)),
|
||||
Value::Text(x) => turso_core::Value::Text(turso_core::types::Text::new(x)),
|
||||
Value::Blob(x) => turso_core::Value::Blob(x),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Reference in New Issue
Block a user