mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-06 09:44:21 +01:00
Implement json_array
This commit is contained in:
@@ -5,6 +5,7 @@ use std::fmt::Display;
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum JsonFunc {
|
||||
Json,
|
||||
JsonArray,
|
||||
}
|
||||
|
||||
#[cfg(feature = "json")]
|
||||
@@ -15,6 +16,7 @@ impl Display for JsonFunc {
|
||||
"{}",
|
||||
match self {
|
||||
JsonFunc::Json => "json".to_string(),
|
||||
JsonFunc::JsonArray => "json_array".to_string(),
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -328,6 +330,8 @@ impl Func {
|
||||
"replace" => Ok(Func::Scalar(ScalarFunc::Replace)),
|
||||
#[cfg(feature = "json")]
|
||||
"json" => Ok(Func::Json(JsonFunc::Json)),
|
||||
#[cfg(feature = "json")]
|
||||
"json_array" => Ok(Func::Json(JsonFunc::JsonArray)),
|
||||
"unixepoch" => Ok(Func::Scalar(ScalarFunc::UnixEpoch)),
|
||||
"hex" => Ok(Func::Scalar(ScalarFunc::Hex)),
|
||||
"unhex" => Ok(Func::Scalar(ScalarFunc::Unhex)),
|
||||
|
||||
125
core/json/mod.rs
125
core/json/mod.rs
@@ -6,7 +6,7 @@ use std::rc::Rc;
|
||||
|
||||
pub use crate::json::de::from_str;
|
||||
pub use crate::json::ser::to_string;
|
||||
use crate::types::OwnedValue;
|
||||
use crate::types::{LimboText, OwnedValue, TextSubtype};
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -24,18 +24,24 @@ pub enum Val {
|
||||
|
||||
pub fn get_json(json_value: &OwnedValue) -> crate::Result<OwnedValue> {
|
||||
match json_value {
|
||||
OwnedValue::Text(ref t) => match crate::json::from_str::<Val>(t) {
|
||||
Ok(json) => {
|
||||
let json = crate::json::to_string(&json).unwrap();
|
||||
Ok(OwnedValue::Text(Rc::new(json)))
|
||||
OwnedValue::Text(ref t) => {
|
||||
if t.subtype == TextSubtype::Json {
|
||||
return Ok(json_value.to_owned());
|
||||
}
|
||||
Err(_) => {
|
||||
crate::bail_parse_error!("malformed JSON")
|
||||
|
||||
match crate::json::from_str::<Val>(&t.value) {
|
||||
Ok(json) => {
|
||||
let json = crate::json::to_string(&json).unwrap();
|
||||
Ok(OwnedValue::Text(LimboText::json(Rc::new(json))))
|
||||
}
|
||||
Err(_) => {
|
||||
crate::bail_parse_error!("malformed JSON")
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
OwnedValue::Blob(b) => {
|
||||
if let Ok(json) = jsonb::from_slice(b) {
|
||||
Ok(OwnedValue::Text(Rc::new(json.to_string())))
|
||||
Ok(OwnedValue::Text(LimboText::json(Rc::new(json.to_string()))))
|
||||
} else {
|
||||
crate::bail_parse_error!("malformed JSON");
|
||||
}
|
||||
@@ -44,6 +50,37 @@ pub fn get_json(json_value: &OwnedValue) -> crate::Result<OwnedValue> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn json_array(values: Vec<OwnedValue>) -> crate::Result<OwnedValue> {
|
||||
let mut s = String::new();
|
||||
s.push('[');
|
||||
|
||||
for (idx, value) in values.iter().enumerate() {
|
||||
match value {
|
||||
OwnedValue::Blob(_) => crate::bail_parse_error!("JSON cannot hold BLOB values"),
|
||||
OwnedValue::Text(t) => {
|
||||
if t.subtype == TextSubtype::Json {
|
||||
s.push_str(&t.value);
|
||||
} else {
|
||||
match crate::json::to_string(&*t.value) {
|
||||
Ok(json) => s.push_str(&json),
|
||||
Err(_) => crate::bail_parse_error!("malformed JSON"),
|
||||
}
|
||||
}
|
||||
}
|
||||
OwnedValue::Integer(i) => s.push_str(&i.to_string()),
|
||||
OwnedValue::Float(f) => s.push_str(&f.to_string()),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
if idx < values.len() - 1 {
|
||||
s.push(',');
|
||||
}
|
||||
}
|
||||
|
||||
s.push(']');
|
||||
Ok(OwnedValue::build_text(Rc::new(s)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -51,10 +88,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_json_valid_json5() {
|
||||
let input = OwnedValue::Text(Rc::new("{ key: 'value' }".to_string()));
|
||||
let input = OwnedValue::build_text(Rc::new("{ key: 'value' }".to_string()));
|
||||
let result = get_json(&input).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.contains("\"key\":\"value\""));
|
||||
assert!(result_str.value.contains("\"key\":\"value\""));
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
}
|
||||
@@ -62,10 +99,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_json_valid_json5_double_single_quotes() {
|
||||
let input = OwnedValue::Text(Rc::new("{ key: ''value'' }".to_string()));
|
||||
let input = OwnedValue::build_text(Rc::new("{ key: ''value'' }".to_string()));
|
||||
let result = get_json(&input).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.contains("\"key\":\"value\""));
|
||||
assert!(result_str.value.contains("\"key\":\"value\""));
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
}
|
||||
@@ -73,10 +110,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_json_valid_json5_infinity() {
|
||||
let input = OwnedValue::Text(Rc::new("{ \"key\": Infinity }".to_string()));
|
||||
let input = OwnedValue::build_text(Rc::new("{ \"key\": Infinity }".to_string()));
|
||||
let result = get_json(&input).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.contains("{\"key\":9e999}"));
|
||||
assert!(result_str.value.contains("{\"key\":9e999}"));
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
}
|
||||
@@ -84,10 +121,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_json_valid_json5_negative_infinity() {
|
||||
let input = OwnedValue::Text(Rc::new("{ \"key\": -Infinity }".to_string()));
|
||||
let input = OwnedValue::build_text(Rc::new("{ \"key\": -Infinity }".to_string()));
|
||||
let result = get_json(&input).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.contains("{\"key\":-9e999}"));
|
||||
assert!(result_str.value.contains("{\"key\":-9e999}"));
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
}
|
||||
@@ -95,10 +132,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_json_valid_json5_nan() {
|
||||
let input = OwnedValue::Text(Rc::new("{ \"key\": NaN }".to_string()));
|
||||
let input = OwnedValue::build_text(Rc::new("{ \"key\": NaN }".to_string()));
|
||||
let result = get_json(&input).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.contains("{\"key\":null}"));
|
||||
assert!(result_str.value.contains("{\"key\":null}"));
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
}
|
||||
@@ -106,7 +143,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_json_invalid_json5() {
|
||||
let input = OwnedValue::Text(Rc::new("{ key: value }".to_string()));
|
||||
let input = OwnedValue::build_text(Rc::new("{ key: value }".to_string()));
|
||||
let result = get_json(&input);
|
||||
match result {
|
||||
Ok(_) => panic!("Expected error for malformed JSON"),
|
||||
@@ -116,10 +153,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_json_valid_jsonb() {
|
||||
let input = OwnedValue::Text(Rc::new("{\"key\":\"value\"}".to_string()));
|
||||
let input = OwnedValue::build_text(Rc::new("{\"key\":\"value\"}".to_string()));
|
||||
let result = get_json(&input).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.contains("\"key\":\"value\""));
|
||||
assert!(result_str.value.contains("\"key\":\"value\""));
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
}
|
||||
@@ -127,7 +164,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_json_invalid_jsonb() {
|
||||
let input = OwnedValue::Text(Rc::new("{key:\"value\"".to_string()));
|
||||
let input = OwnedValue::build_text(Rc::new("{key:\"value\"".to_string()));
|
||||
let result = get_json(&input);
|
||||
match result {
|
||||
Ok(_) => panic!("Expected error for malformed JSON"),
|
||||
@@ -141,7 +178,7 @@ mod tests {
|
||||
let input = OwnedValue::Blob(Rc::new(binary_json));
|
||||
let result = get_json(&input).unwrap();
|
||||
if let OwnedValue::Text(result_str) = result {
|
||||
assert!(result_str.contains("\"asd\":\"adf\""));
|
||||
assert!(result_str.value.contains("\"asd\":\"adf\""));
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
}
|
||||
@@ -168,4 +205,44 @@ mod tests {
|
||||
panic!("Expected OwnedValue::Null");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_json_array_simple() {
|
||||
let text = OwnedValue::build_text(Rc::new("value1".to_string()));
|
||||
let json = OwnedValue::Text(LimboText::json(Rc::new("\"value2\"".to_string())));
|
||||
let input = vec![text, json, OwnedValue::Integer(1), OwnedValue::Float(1.1)];
|
||||
|
||||
let result = json_array(input).unwrap();
|
||||
if let OwnedValue::Text(res) = result {
|
||||
assert_eq!(res.value.as_str(), "[\"value1\",\"value2\",1,1.1]");
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_json_array_empty() {
|
||||
let input = vec![];
|
||||
|
||||
let result = json_array(input).unwrap();
|
||||
if let OwnedValue::Text(res) = result {
|
||||
assert_eq!(res.value.as_str(), "[]");
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_json_array_blob_invalid() {
|
||||
let blob = OwnedValue::Blob(Rc::new("1".as_bytes().to_vec()));
|
||||
|
||||
let input = vec![blob];
|
||||
|
||||
let result = json_array(input);
|
||||
|
||||
match result {
|
||||
Ok(_) => panic!("Expected error for blob input"),
|
||||
Err(e) => assert!(e.to_string().contains("JSON cannot hold BLOB values")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -934,7 +934,7 @@ 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::Text(value.into()), n))
|
||||
Ok((OwnedValue::build_text(value.into()), n))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1271,7 +1271,7 @@ mod tests {
|
||||
#[case(&[], SerialType::ConstInt0, OwnedValue::Integer(0))]
|
||||
#[case(&[], SerialType::ConstInt1, OwnedValue::Integer(1))]
|
||||
#[case(&[1, 2, 3], SerialType::Blob(3), OwnedValue::Blob(vec![1, 2, 3].into()))]
|
||||
#[case(&[65, 66, 67], SerialType::String(3), OwnedValue::Text("ABC".to_string().into()))]
|
||||
#[case(&[65, 66, 67], SerialType::String(3), OwnedValue::build_text("ABC".to_string().into()))]
|
||||
fn test_read_value(
|
||||
#[case] buf: &[u8],
|
||||
#[case] serial_type: SerialType,
|
||||
|
||||
@@ -898,6 +898,22 @@ pub fn translate_expr(
|
||||
});
|
||||
Ok(target_register)
|
||||
}
|
||||
JsonFunc::JsonArray => {
|
||||
allocate_registers(
|
||||
program,
|
||||
args,
|
||||
referenced_tables,
|
||||
precomputed_exprs_to_registers,
|
||||
)?;
|
||||
|
||||
program.emit_insn(Insn::Function {
|
||||
constant_mask: 0,
|
||||
start_reg: target_register + 1,
|
||||
dest: target_register,
|
||||
func: func_ctx,
|
||||
});
|
||||
Ok(target_register)
|
||||
}
|
||||
},
|
||||
Func::Scalar(srf) => {
|
||||
match srf {
|
||||
@@ -905,18 +921,12 @@ pub fn translate_expr(
|
||||
unreachable!("this is always ast::Expr::Cast")
|
||||
}
|
||||
ScalarFunc::Char => {
|
||||
let args = args.clone().unwrap_or_else(Vec::new);
|
||||
|
||||
for arg in args.iter() {
|
||||
let reg = program.alloc_register();
|
||||
translate_expr(
|
||||
program,
|
||||
referenced_tables,
|
||||
arg,
|
||||
reg,
|
||||
precomputed_exprs_to_registers,
|
||||
)?;
|
||||
}
|
||||
allocate_registers(
|
||||
program,
|
||||
args,
|
||||
referenced_tables,
|
||||
precomputed_exprs_to_registers,
|
||||
)?;
|
||||
|
||||
program.emit_insn(Insn::Function {
|
||||
constant_mask: 0,
|
||||
@@ -1942,6 +1952,28 @@ pub fn translate_expr(
|
||||
}
|
||||
}
|
||||
|
||||
fn allocate_registers(
|
||||
program: &mut ProgramBuilder,
|
||||
args: &Option<Vec<ast::Expr>>,
|
||||
referenced_tables: Option<&[BTreeTableReference]>,
|
||||
precomputed_exprs_to_registers: Option<&Vec<(&ast::Expr, usize)>>,
|
||||
) -> Result<()> {
|
||||
let args = args.clone().unwrap_or_else(Vec::new);
|
||||
|
||||
for arg in args.iter() {
|
||||
let reg = program.alloc_register();
|
||||
translate_expr(
|
||||
program,
|
||||
referenced_tables,
|
||||
arg,
|
||||
reg,
|
||||
precomputed_exprs_to_registers,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn wrap_eval_jump_expr(
|
||||
program: &mut ProgramBuilder,
|
||||
insn: Insn,
|
||||
|
||||
@@ -27,24 +27,59 @@ impl<'a> Display for Value<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum TextSubtype {
|
||||
Text,
|
||||
Json,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct LimboText {
|
||||
pub value: Rc<String>,
|
||||
pub subtype: TextSubtype,
|
||||
}
|
||||
|
||||
impl LimboText {
|
||||
pub fn new(value: Rc<String>) -> Self {
|
||||
Self {
|
||||
value,
|
||||
subtype: TextSubtype::Text,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn json(value: Rc<String>) -> Self {
|
||||
Self {
|
||||
value,
|
||||
subtype: TextSubtype::Json,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum OwnedValue {
|
||||
Null,
|
||||
Integer(i64),
|
||||
Float(f64),
|
||||
Text(Rc<String>),
|
||||
Text(LimboText),
|
||||
Blob(Rc<Vec<u8>>),
|
||||
Agg(Box<AggContext>), // TODO(pere): make this without Box. Currently this might cause cache miss but let's leave it for future analysis
|
||||
Record(OwnedRecord),
|
||||
}
|
||||
|
||||
impl OwnedValue {
|
||||
// A helper function that makes building a text OwnedValue easier.
|
||||
pub fn build_text(text: Rc<String>) -> Self {
|
||||
OwnedValue::Text(LimboText::new(text))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for OwnedValue {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
OwnedValue::Null => write!(f, "NULL"),
|
||||
OwnedValue::Integer(i) => write!(f, "{}", i),
|
||||
OwnedValue::Float(fl) => write!(f, "{:?}", fl),
|
||||
OwnedValue::Text(s) => write!(f, "{}", s),
|
||||
OwnedValue::Text(s) => write!(f, "{}", s.value),
|
||||
OwnedValue::Blob(b) => write!(f, "{}", String::from_utf8_lossy(b)),
|
||||
OwnedValue::Agg(a) => match a.as_ref() {
|
||||
AggContext::Avg(acc, _count) => write!(f, "{}", acc),
|
||||
@@ -111,7 +146,7 @@ impl PartialOrd<OwnedValue> for OwnedValue {
|
||||
) => Some(std::cmp::Ordering::Greater),
|
||||
|
||||
(OwnedValue::Text(text_left), OwnedValue::Text(text_right)) => {
|
||||
text_left.partial_cmp(text_right)
|
||||
text_left.value.partial_cmp(&text_right.value)
|
||||
}
|
||||
// Text vs Blob
|
||||
(OwnedValue::Text(_), OwnedValue::Blob(_)) => Some(std::cmp::Ordering::Less),
|
||||
@@ -171,21 +206,27 @@ impl std::ops::Add<OwnedValue> for OwnedValue {
|
||||
OwnedValue::Float(float_left + float_right)
|
||||
}
|
||||
(OwnedValue::Text(string_left), OwnedValue::Text(string_right)) => {
|
||||
OwnedValue::Text(Rc::new(string_left.to_string() + &string_right.to_string()))
|
||||
OwnedValue::build_text(Rc::new(
|
||||
string_left.value.to_string() + &string_right.value.to_string(),
|
||||
))
|
||||
}
|
||||
(OwnedValue::Text(string_left), OwnedValue::Integer(int_right)) => {
|
||||
OwnedValue::Text(Rc::new(string_left.to_string() + &int_right.to_string()))
|
||||
OwnedValue::build_text(Rc::new(
|
||||
string_left.value.to_string() + &int_right.to_string(),
|
||||
))
|
||||
}
|
||||
(OwnedValue::Integer(int_left), OwnedValue::Text(string_right)) => {
|
||||
OwnedValue::Text(Rc::new(int_left.to_string() + &string_right.to_string()))
|
||||
OwnedValue::build_text(Rc::new(
|
||||
int_left.to_string() + &string_right.value.to_string(),
|
||||
))
|
||||
}
|
||||
(OwnedValue::Text(string_left), OwnedValue::Float(float_right)) => {
|
||||
let string_right = OwnedValue::Float(float_right).to_string();
|
||||
OwnedValue::Text(Rc::new(string_left.to_string() + &string_right))
|
||||
OwnedValue::build_text(Rc::new(string_left.value.to_string() + &string_right))
|
||||
}
|
||||
(OwnedValue::Float(float_left), OwnedValue::Text(string_right)) => {
|
||||
let string_left = OwnedValue::Float(float_left).to_string();
|
||||
OwnedValue::Text(Rc::new(string_left + &string_right.to_string()))
|
||||
OwnedValue::build_text(Rc::new(string_left + &string_right.value.to_string()))
|
||||
}
|
||||
(lhs, OwnedValue::Null) => lhs,
|
||||
(OwnedValue::Null, rhs) => rhs,
|
||||
@@ -269,7 +310,7 @@ pub fn to_value(value: &OwnedValue) -> Value<'_> {
|
||||
OwnedValue::Null => Value::Null,
|
||||
OwnedValue::Integer(i) => Value::Integer(*i),
|
||||
OwnedValue::Float(f) => Value::Float(*f),
|
||||
OwnedValue::Text(s) => Value::Text(s),
|
||||
OwnedValue::Text(s) => Value::Text(&s.value),
|
||||
OwnedValue::Blob(b) => Value::Blob(b),
|
||||
OwnedValue::Agg(a) => match a.as_ref() {
|
||||
AggContext::Avg(acc, _count) => match acc {
|
||||
@@ -359,7 +400,7 @@ impl OwnedRecord {
|
||||
OwnedValue::Null => 0,
|
||||
OwnedValue::Integer(_) => 6, // for now let's only do i64
|
||||
OwnedValue::Float(_) => 7,
|
||||
OwnedValue::Text(t) => (t.len() * 2 + 13) as u64,
|
||||
OwnedValue::Text(t) => (t.value.len() * 2 + 13) as u64,
|
||||
OwnedValue::Blob(b) => (b.len() * 2 + 12) as u64,
|
||||
// not serializable values
|
||||
OwnedValue::Agg(_) => unreachable!(),
|
||||
@@ -380,7 +421,7 @@ impl OwnedRecord {
|
||||
OwnedValue::Null => {}
|
||||
OwnedValue::Integer(i) => buf.extend_from_slice(&i.to_be_bytes()),
|
||||
OwnedValue::Float(f) => buf.extend_from_slice(&f.to_be_bytes()),
|
||||
OwnedValue::Text(t) => buf.extend_from_slice(t.as_bytes()),
|
||||
OwnedValue::Text(t) => buf.extend_from_slice(t.value.as_bytes()),
|
||||
OwnedValue::Blob(b) => buf.extend_from_slice(b),
|
||||
// non serializable
|
||||
OwnedValue::Agg(_) => unreachable!(),
|
||||
|
||||
@@ -10,53 +10,53 @@ use crate::Result;
|
||||
/// Implementation of the date() SQL function.
|
||||
pub fn exec_date(values: &[OwnedValue]) -> OwnedValue {
|
||||
let maybe_dt = match values.first() {
|
||||
None => parse_naive_date_time(&OwnedValue::Text(Rc::new("now".to_string()))),
|
||||
None => parse_naive_date_time(&OwnedValue::build_text(Rc::new("now".to_string()))),
|
||||
Some(value) => parse_naive_date_time(value),
|
||||
};
|
||||
// early return, no need to look at modifiers if result invalid
|
||||
if maybe_dt.is_none() {
|
||||
return OwnedValue::Text(Rc::new(String::new()));
|
||||
return OwnedValue::build_text(Rc::new(String::new()));
|
||||
}
|
||||
|
||||
// apply modifiers if result is valid
|
||||
let mut dt = maybe_dt.unwrap();
|
||||
for modifier in values.iter().skip(1) {
|
||||
if let OwnedValue::Text(modifier_str) = modifier {
|
||||
if apply_modifier(&mut dt, modifier_str).is_err() {
|
||||
return OwnedValue::Text(Rc::new(String::new()));
|
||||
if apply_modifier(&mut dt, &modifier_str.value).is_err() {
|
||||
return OwnedValue::build_text(Rc::new(String::new()));
|
||||
}
|
||||
} else {
|
||||
return OwnedValue::Text(Rc::new(String::new()));
|
||||
return OwnedValue::build_text(Rc::new(String::new()));
|
||||
}
|
||||
}
|
||||
|
||||
OwnedValue::Text(Rc::new(get_date_from_naive_datetime(dt)))
|
||||
OwnedValue::build_text(Rc::new(get_date_from_naive_datetime(dt)))
|
||||
}
|
||||
|
||||
/// Implementation of the time() SQL function.
|
||||
pub fn exec_time(time_value: &[OwnedValue]) -> OwnedValue {
|
||||
let maybe_dt = match time_value.first() {
|
||||
None => parse_naive_date_time(&OwnedValue::Text(Rc::new("now".to_string()))),
|
||||
None => parse_naive_date_time(&OwnedValue::build_text(Rc::new("now".to_string()))),
|
||||
Some(value) => parse_naive_date_time(value),
|
||||
};
|
||||
// early return, no need to look at modifiers if result invalid
|
||||
if maybe_dt.is_none() {
|
||||
return OwnedValue::Text(Rc::new(String::new()));
|
||||
return OwnedValue::build_text(Rc::new(String::new()));
|
||||
}
|
||||
|
||||
// apply modifiers if result is valid
|
||||
let mut dt = maybe_dt.unwrap();
|
||||
for modifier in time_value.iter().skip(1) {
|
||||
if let OwnedValue::Text(modifier_str) = modifier {
|
||||
if apply_modifier(&mut dt, modifier_str).is_err() {
|
||||
return OwnedValue::Text(Rc::new(String::new()));
|
||||
if apply_modifier(&mut dt, &modifier_str.value).is_err() {
|
||||
return OwnedValue::build_text(Rc::new(String::new()));
|
||||
}
|
||||
} else {
|
||||
return OwnedValue::Text(Rc::new(String::new()));
|
||||
return OwnedValue::build_text(Rc::new(String::new()));
|
||||
}
|
||||
}
|
||||
|
||||
OwnedValue::Text(Rc::new(get_time_from_naive_datetime(dt)))
|
||||
OwnedValue::build_text(Rc::new(get_time_from_naive_datetime(dt)))
|
||||
}
|
||||
|
||||
fn apply_modifier(dt: &mut NaiveDateTime, modifier: &str) -> Result<()> {
|
||||
@@ -125,7 +125,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),
|
||||
OwnedValue::Text(s) => get_date_time_from_time_value_string(&s.value),
|
||||
OwnedValue::Integer(i) => get_date_time_from_time_value_integer(*i),
|
||||
OwnedValue::Float(f) => get_date_time_from_time_value_float(*f),
|
||||
_ => None,
|
||||
@@ -410,197 +410,200 @@ mod tests {
|
||||
let test_cases = vec![
|
||||
// Format 1: YYYY-MM-DD (no timezone applicable)
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
// Format 2: YYYY-MM-DD HH:MM
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30+02:00".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30-05:00".to_string())),
|
||||
next_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 01:30+05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 01:30+05:00".to_string())),
|
||||
prev_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30Z".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
// Format 3: YYYY-MM-DD HH:MM:SS
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45+02:00".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45-05:00".to_string())),
|
||||
next_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 01:30:45+05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 01:30:45+05:00".to_string())),
|
||||
prev_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45Z".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
// Format 4: YYYY-MM-DD HH:MM:SS.SSS
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45.123".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45.123".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45.123+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45.123+02:00".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45.123-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45.123-05:00".to_string())),
|
||||
next_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 01:30:45.123+05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 01:30:45.123+05:00".to_string())),
|
||||
prev_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45.123Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45.123Z".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
// Format 5: YYYY-MM-DDTHH:MM
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30+02:00".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30-05:00".to_string())),
|
||||
next_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T01:30+05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T01:30+05:00".to_string())),
|
||||
prev_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30Z".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
// Format 6: YYYY-MM-DDTHH:MM:SS
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45+02:00".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45-05:00".to_string())),
|
||||
next_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T01:30:45+05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T01:30:45+05:00".to_string())),
|
||||
prev_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45Z".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
// Format 7: YYYY-MM-DDTHH:MM:SS.SSS
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45.123".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45.123".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45.123+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45.123+02:00".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45.123-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45.123-05:00".to_string())),
|
||||
next_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T01:30:45.123+05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T01:30:45.123+05:00".to_string())),
|
||||
prev_date_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45.123Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45.123Z".to_string())),
|
||||
test_date_str,
|
||||
),
|
||||
// Format 8: HH:MM
|
||||
(OwnedValue::Text(Rc::new("22:30".to_string())), "2000-01-01"),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30".to_string())),
|
||||
"2000-01-01",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30+02:00".to_string())),
|
||||
"2000-01-01",
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text(Rc::new("22:30-05:00".to_string())),
|
||||
"2000-01-02",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("01:30+05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("01:30+05:00".to_string())),
|
||||
"1999-12-31",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30Z".to_string())),
|
||||
"2000-01-01",
|
||||
),
|
||||
// Format 9: HH:MM:SS
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45".to_string())),
|
||||
"2000-01-01",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45+02:00".to_string())),
|
||||
"2000-01-01",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45-05:00".to_string())),
|
||||
"2000-01-02",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("01:30:45+05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("01:30:45+05:00".to_string())),
|
||||
"1999-12-31",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45Z".to_string())),
|
||||
"2000-01-01",
|
||||
),
|
||||
// Format 10: HH:MM:SS.SSS
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45.123".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45.123".to_string())),
|
||||
"2000-01-01",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45.123+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45.123+02:00".to_string())),
|
||||
"2000-01-01",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45.123-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45.123-05:00".to_string())),
|
||||
"2000-01-02",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("01:30:45.123+05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("01:30:45.123+05:00".to_string())),
|
||||
"1999-12-31",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45.123Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45.123Z".to_string())),
|
||||
"2000-01-01",
|
||||
),
|
||||
// Test Format 11: 'now'
|
||||
(OwnedValue::Text(Rc::new("now".to_string())), &now),
|
||||
(OwnedValue::build_text(Rc::new("now".to_string())), &now),
|
||||
// Format 12: DDDDDDDDDD (Julian date as float or integer)
|
||||
(OwnedValue::Float(2460512.5), test_date_str),
|
||||
(OwnedValue::Integer(2460513), test_date_str),
|
||||
@@ -610,7 +613,7 @@ mod tests {
|
||||
let result = exec_date(&[input.clone()]);
|
||||
assert_eq!(
|
||||
result,
|
||||
OwnedValue::Text(Rc::new(expected.to_string())),
|
||||
OwnedValue::build_text(Rc::new(expected.to_string())),
|
||||
"Failed for input: {:?}",
|
||||
input
|
||||
);
|
||||
@@ -620,37 +623,37 @@ mod tests {
|
||||
#[test]
|
||||
fn test_invalid_get_date_from_time_value() {
|
||||
let invalid_cases = vec![
|
||||
OwnedValue::Text(Rc::new("2024-07-21 25:00".to_string())), // Invalid hour
|
||||
OwnedValue::Text(Rc::new("2024-07-21 24:00:00".to_string())), // Invalid hour
|
||||
OwnedValue::Text(Rc::new("2024-07-21 23:60:00".to_string())), // Invalid minute
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:58:60".to_string())), // Invalid second
|
||||
OwnedValue::Text(Rc::new("2024-07-32".to_string())), // Invalid day
|
||||
OwnedValue::Text(Rc::new("2024-13-01".to_string())), // Invalid month
|
||||
OwnedValue::Text(Rc::new("invalid_date".to_string())), // Completely invalid string
|
||||
OwnedValue::Text(Rc::new("".to_string())), // Empty string
|
||||
OwnedValue::Integer(i64::MAX), // Large Julian day
|
||||
OwnedValue::Integer(-1), // Negative Julian day
|
||||
OwnedValue::Float(f64::MAX), // Large float
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 25:00".to_string())), // Invalid hour
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 24:00:00".to_string())), // Invalid hour
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 23:60:00".to_string())), // Invalid minute
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:58:60".to_string())), // Invalid second
|
||||
OwnedValue::build_text(Rc::new("2024-07-32".to_string())), // Invalid day
|
||||
OwnedValue::build_text(Rc::new("2024-13-01".to_string())), // Invalid month
|
||||
OwnedValue::build_text(Rc::new("invalid_date".to_string())), // Completely invalid string
|
||||
OwnedValue::build_text(Rc::new("".to_string())), // Empty string
|
||||
OwnedValue::Integer(i64::MAX), // Large Julian day
|
||||
OwnedValue::Integer(-1), // Negative Julian day
|
||||
OwnedValue::Float(f64::MAX), // Large float
|
||||
OwnedValue::Float(-1.0), // Negative Julian day as float
|
||||
OwnedValue::Float(f64::NAN), // NaN
|
||||
OwnedValue::Float(f64::INFINITY), // Infinity
|
||||
OwnedValue::Null, // Null value
|
||||
OwnedValue::Blob(vec![1, 2, 3].into()), // Blob (unsupported type)
|
||||
// Invalid timezone tests
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00+24:00".to_string())), // Invalid timezone offset (too large)
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00-24:00".to_string())), // Invalid timezone offset (too small)
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00+00:60".to_string())), // Invalid timezone minutes
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00+00:00:00".to_string())), // Invalid timezone format (extra seconds)
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00+".to_string())), // Incomplete timezone
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00+Z".to_string())), // Invalid timezone format
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00+00:00Z".to_string())), // Mixing offset and Z
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00UTC".to_string())), // Named timezone (not supported)
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00+24:00".to_string())), // Invalid timezone offset (too large)
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00-24:00".to_string())), // Invalid timezone offset (too small)
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00+00:60".to_string())), // Invalid timezone minutes
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00+00:00:00".to_string())), // Invalid timezone format (extra seconds)
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00+".to_string())), // Incomplete timezone
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00+Z".to_string())), // Invalid timezone format
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00+00:00Z".to_string())), // Mixing offset and Z
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00UTC".to_string())), // Named timezone (not supported)
|
||||
];
|
||||
|
||||
for case in invalid_cases.iter() {
|
||||
let result = exec_date(&[case.clone()]);
|
||||
match result {
|
||||
OwnedValue::Text(ref result_str) if result_str.is_empty() => (),
|
||||
OwnedValue::Text(ref result_str) if result_str.value.is_empty() => (),
|
||||
_ => panic!(
|
||||
"Expected empty string for input: {:?}, but got: {:?}",
|
||||
case, result
|
||||
@@ -670,158 +673,164 @@ mod tests {
|
||||
let test_cases = vec![
|
||||
// Format 1: YYYY-MM-DD (no timezone applicable)
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21".to_string())),
|
||||
"00:00:00",
|
||||
),
|
||||
// Format 2: YYYY-MM-DD HH:MM
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30".to_string())),
|
||||
"22:30:00",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30+02:00".to_string())),
|
||||
"20:30:00",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30-05:00".to_string())),
|
||||
"03:30:00",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30Z".to_string())),
|
||||
"22:30:00",
|
||||
),
|
||||
// Format 3: YYYY-MM-DD HH:MM:SS
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45".to_string())),
|
||||
test_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45+02:00".to_string())),
|
||||
prev_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45-05:00".to_string())),
|
||||
next_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45Z".to_string())),
|
||||
test_time_str,
|
||||
),
|
||||
// Format 4: YYYY-MM-DD HH:MM:SS.SSS
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45.123".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45.123".to_string())),
|
||||
test_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45.123+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45.123+02:00".to_string())),
|
||||
prev_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45.123-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45.123-05:00".to_string())),
|
||||
next_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:30:45.123Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:30:45.123Z".to_string())),
|
||||
test_time_str,
|
||||
),
|
||||
// Format 5: YYYY-MM-DDTHH:MM
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30".to_string())),
|
||||
"22:30:00",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30+02:00".to_string())),
|
||||
"20:30:00",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30-05:00".to_string())),
|
||||
"03:30:00",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30Z".to_string())),
|
||||
"22:30:00",
|
||||
),
|
||||
// Format 6: YYYY-MM-DDTHH:MM:SS
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45".to_string())),
|
||||
test_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45+02:00".to_string())),
|
||||
prev_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45-05:00".to_string())),
|
||||
next_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45Z".to_string())),
|
||||
test_time_str,
|
||||
),
|
||||
// Format 7: YYYY-MM-DDTHH:MM:SS.SSS
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45.123".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45.123".to_string())),
|
||||
test_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45.123+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45.123+02:00".to_string())),
|
||||
prev_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45.123-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45.123-05:00".to_string())),
|
||||
next_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("2024-07-21T22:30:45.123Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T22:30:45.123Z".to_string())),
|
||||
test_time_str,
|
||||
),
|
||||
// Format 8: HH:MM
|
||||
(OwnedValue::Text(Rc::new("22:30".to_string())), "22:30:00"),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30".to_string())),
|
||||
"22:30:00",
|
||||
),
|
||||
(
|
||||
OwnedValue::build_text(Rc::new("22:30+02:00".to_string())),
|
||||
"20:30:00",
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30-05:00".to_string())),
|
||||
"03:30:00",
|
||||
),
|
||||
(OwnedValue::Text(Rc::new("22:30Z".to_string())), "22:30:00"),
|
||||
(
|
||||
OwnedValue::build_text(Rc::new("22:30Z".to_string())),
|
||||
"22:30:00",
|
||||
),
|
||||
// Format 9: HH:MM:SS
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45".to_string())),
|
||||
test_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45+02:00".to_string())),
|
||||
prev_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45-05:00".to_string())),
|
||||
next_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45Z".to_string())),
|
||||
test_time_str,
|
||||
),
|
||||
// Format 10: HH:MM:SS.SSS
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45.123".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45.123".to_string())),
|
||||
test_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45.123+02:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45.123+02:00".to_string())),
|
||||
prev_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45.123-05:00".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45.123-05:00".to_string())),
|
||||
next_time_str,
|
||||
),
|
||||
(
|
||||
OwnedValue::Text(Rc::new("22:30:45.123Z".to_string())),
|
||||
OwnedValue::build_text(Rc::new("22:30:45.123Z".to_string())),
|
||||
test_time_str,
|
||||
),
|
||||
// Test Format 11: 'now'
|
||||
(OwnedValue::Text(Rc::new("now".to_string())), &now),
|
||||
(OwnedValue::build_text(Rc::new("now".to_string())), &now),
|
||||
// Format 12: DDDDDDDDDD (Julian date as float or integer)
|
||||
(OwnedValue::Float(2460082.1), "14:24:00"),
|
||||
(OwnedValue::Integer(2460082), "12:00:00"),
|
||||
@@ -830,7 +839,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.as_str(), expected);
|
||||
assert_eq!(result_str.value.as_str(), expected);
|
||||
} else {
|
||||
panic!("Expected OwnedValue::Text, but got: {:?}", result);
|
||||
}
|
||||
@@ -840,37 +849,37 @@ mod tests {
|
||||
#[test]
|
||||
fn test_invalid_get_time_from_datetime_value() {
|
||||
let invalid_cases = vec![
|
||||
OwnedValue::Text(Rc::new("2024-07-21 25:00".to_string())), // Invalid hour
|
||||
OwnedValue::Text(Rc::new("2024-07-21 24:00:00".to_string())), // Invalid hour
|
||||
OwnedValue::Text(Rc::new("2024-07-21 23:60:00".to_string())), // Invalid minute
|
||||
OwnedValue::Text(Rc::new("2024-07-21 22:58:60".to_string())), // Invalid second
|
||||
OwnedValue::Text(Rc::new("2024-07-32".to_string())), // Invalid day
|
||||
OwnedValue::Text(Rc::new("2024-13-01".to_string())), // Invalid month
|
||||
OwnedValue::Text(Rc::new("invalid_date".to_string())), // Completely invalid string
|
||||
OwnedValue::Text(Rc::new("".to_string())), // Empty string
|
||||
OwnedValue::Integer(i64::MAX), // Large Julian day
|
||||
OwnedValue::Integer(-1), // Negative Julian day
|
||||
OwnedValue::Float(f64::MAX), // Large float
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 25:00".to_string())), // Invalid hour
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 24:00:00".to_string())), // Invalid hour
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 23:60:00".to_string())), // Invalid minute
|
||||
OwnedValue::build_text(Rc::new("2024-07-21 22:58:60".to_string())), // Invalid second
|
||||
OwnedValue::build_text(Rc::new("2024-07-32".to_string())), // Invalid day
|
||||
OwnedValue::build_text(Rc::new("2024-13-01".to_string())), // Invalid month
|
||||
OwnedValue::build_text(Rc::new("invalid_date".to_string())), // Completely invalid string
|
||||
OwnedValue::build_text(Rc::new("".to_string())), // Empty string
|
||||
OwnedValue::Integer(i64::MAX), // Large Julian day
|
||||
OwnedValue::Integer(-1), // Negative Julian day
|
||||
OwnedValue::Float(f64::MAX), // Large float
|
||||
OwnedValue::Float(-1.0), // Negative Julian day as float
|
||||
OwnedValue::Float(f64::NAN), // NaN
|
||||
OwnedValue::Float(f64::INFINITY), // Infinity
|
||||
OwnedValue::Null, // Null value
|
||||
OwnedValue::Blob(vec![1, 2, 3].into()), // Blob (unsupported type)
|
||||
// Invalid timezone tests
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00+24:00".to_string())), // Invalid timezone offset (too large)
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00-24:00".to_string())), // Invalid timezone offset (too small)
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00+00:60".to_string())), // Invalid timezone minutes
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00+00:00:00".to_string())), // Invalid timezone format (extra seconds)
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00+".to_string())), // Incomplete timezone
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00+Z".to_string())), // Invalid timezone format
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00+00:00Z".to_string())), // Mixing offset and Z
|
||||
OwnedValue::Text(Rc::new("2024-07-21T12:00:00UTC".to_string())), // Named timezone (not supported)
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00+24:00".to_string())), // Invalid timezone offset (too large)
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00-24:00".to_string())), // Invalid timezone offset (too small)
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00+00:60".to_string())), // Invalid timezone minutes
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00+00:00:00".to_string())), // Invalid timezone format (extra seconds)
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00+".to_string())), // Incomplete timezone
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00+Z".to_string())), // Invalid timezone format
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00+00:00Z".to_string())), // Mixing offset and Z
|
||||
OwnedValue::build_text(Rc::new("2024-07-21T12:00:00UTC".to_string())), // Named timezone (not supported)
|
||||
];
|
||||
|
||||
for case in invalid_cases {
|
||||
let result = exec_time(&[case.clone()]);
|
||||
match result {
|
||||
OwnedValue::Text(ref result_str) if result_str.is_empty() => (),
|
||||
OwnedValue::Text(ref result_str) if result_str.value.is_empty() => (),
|
||||
_ => panic!(
|
||||
"Expected empty string for input: {:?}, but got: {:?}",
|
||||
case, result
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use super::{Insn, InsnReference, OwnedValue, Program};
|
||||
use crate::types::LimboText;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn insn_to_str(
|
||||
@@ -15,7 +16,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*target_pc as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("Start at {}", target_pc),
|
||||
),
|
||||
@@ -24,7 +25,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]=r[{}]+r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -33,7 +34,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]=r[{}]-r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -42,7 +43,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]=r[{}]*r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -51,7 +52,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]=r[{}]/r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -60,7 +61,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]=r[{}]&r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -69,7 +70,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]=r[{}]|r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
@@ -78,7 +79,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]=~r[{}]", dest, reg),
|
||||
),
|
||||
@@ -87,7 +88,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*dest as i32,
|
||||
dest_end.map_or(0, |end| end as i32),
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
dest_end.map_or(format!("r[{}]=NULL", dest), |end| {
|
||||
format!("r[{}..{}]=NULL", dest, end)
|
||||
@@ -98,7 +99,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("Set cursor {} to a (pseudo) NULL row", cursor_id),
|
||||
),
|
||||
@@ -107,7 +108,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
*target_pc as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]!=NULL -> goto {}", reg, target_pc),
|
||||
),
|
||||
@@ -120,7 +121,7 @@ pub fn insn_to_str(
|
||||
*start_reg_a as i32,
|
||||
*start_reg_b as i32,
|
||||
*count as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!(
|
||||
"r[{}..{}]==r[{}..{}]",
|
||||
@@ -139,7 +140,7 @@ pub fn insn_to_str(
|
||||
*target_pc_lt as i32,
|
||||
*target_pc_eq as i32,
|
||||
*target_pc_gt as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -152,7 +153,7 @@ pub fn insn_to_str(
|
||||
*source_reg as i32,
|
||||
*dest_reg as i32,
|
||||
*count as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!(
|
||||
"r[{}..{}]=r[{}..{}]",
|
||||
@@ -171,7 +172,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
*target_pc as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!(
|
||||
"r[{}]>0 -> r[{}]-={}, goto {}",
|
||||
@@ -187,7 +188,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*target_pc as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("if r[{}]==r[{}] goto {}", lhs, rhs, target_pc),
|
||||
),
|
||||
@@ -200,7 +201,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*target_pc as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("if r[{}]!=r[{}] goto {}", lhs, rhs, target_pc),
|
||||
),
|
||||
@@ -213,7 +214,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*target_pc as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("if r[{}]<r[{}] goto {}", lhs, rhs, target_pc),
|
||||
),
|
||||
@@ -226,7 +227,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*target_pc as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("if r[{}]<=r[{}] goto {}", lhs, rhs, target_pc),
|
||||
),
|
||||
@@ -239,7 +240,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*target_pc as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("if r[{}]>r[{}] goto {}", lhs, rhs, target_pc),
|
||||
),
|
||||
@@ -252,7 +253,7 @@ pub fn insn_to_str(
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*target_pc as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("if r[{}]>=r[{}] goto {}", lhs, rhs, target_pc),
|
||||
),
|
||||
@@ -265,7 +266,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
*target_pc as i32,
|
||||
*null_reg as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("if r[{}] goto {}", reg, target_pc),
|
||||
),
|
||||
@@ -278,7 +279,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
*target_pc as i32,
|
||||
*null_reg as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("if !r[{}] goto {}", reg, target_pc),
|
||||
),
|
||||
@@ -290,7 +291,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*root_page as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!(
|
||||
"table={}, root={}",
|
||||
@@ -306,7 +307,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -319,7 +320,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*content_reg as i32,
|
||||
*num_fields as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("{} columns in r[{}]", num_fields, content_reg),
|
||||
),
|
||||
@@ -328,7 +329,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -340,7 +341,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*pc_if_empty as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!(
|
||||
"Rewind table {}",
|
||||
@@ -361,7 +362,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*column as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!(
|
||||
"r[{}]={}.{}",
|
||||
@@ -385,7 +386,7 @@ pub fn insn_to_str(
|
||||
*start_reg as i32,
|
||||
*count as i32,
|
||||
*dest_reg as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!(
|
||||
"r[{}]=mkrec(r[{}..{}])",
|
||||
@@ -399,7 +400,7 @@ pub fn insn_to_str(
|
||||
*start_reg as i32,
|
||||
*count as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
if *count == 1 {
|
||||
format!("output=r[{}]", start_reg)
|
||||
@@ -412,7 +413,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -424,7 +425,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*pc_if_next as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -436,7 +437,7 @@ pub fn insn_to_str(
|
||||
*err_code as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -445,7 +446,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*write as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -454,7 +455,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*target_pc as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -466,7 +467,7 @@ pub fn insn_to_str(
|
||||
*return_reg as i32,
|
||||
*target_pc as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -475,7 +476,7 @@ pub fn insn_to_str(
|
||||
*return_reg as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -484,7 +485,7 @@ pub fn insn_to_str(
|
||||
*value as i32,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]={}", dest, value),
|
||||
),
|
||||
@@ -502,7 +503,7 @@ pub fn insn_to_str(
|
||||
*register as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -511,7 +512,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new(value.clone())),
|
||||
OwnedValue::build_text(Rc::new(value.clone())),
|
||||
0,
|
||||
format!("r[{}]='{}'", dest, value),
|
||||
),
|
||||
@@ -534,7 +535,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!(
|
||||
"r[{}]={}.rowid",
|
||||
@@ -554,7 +555,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*src_reg as i32,
|
||||
*target_pc as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!(
|
||||
"if (r[{}]!={}.rowid) goto {}",
|
||||
@@ -574,7 +575,7 @@ pub fn insn_to_str(
|
||||
*index_cursor_id as i32,
|
||||
*table_cursor_id as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -589,7 +590,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*target_pc as i32,
|
||||
*start_reg as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -604,7 +605,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*target_pc as i32,
|
||||
*start_reg as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -618,7 +619,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*target_pc as i32,
|
||||
*start_reg as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -632,7 +633,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*target_pc as i32,
|
||||
*start_reg as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -641,7 +642,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
*target_pc as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("if (--r[{}]==0) goto {}", reg, target_pc),
|
||||
),
|
||||
@@ -655,7 +656,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*col as i32,
|
||||
*acc_reg as i32,
|
||||
OwnedValue::Text(Rc::new(func.to_string().into())),
|
||||
OwnedValue::build_text(Rc::new(func.to_string().into())),
|
||||
0,
|
||||
format!("accum=r[{}] step(r[{}])", *acc_reg, *col),
|
||||
),
|
||||
@@ -664,7 +665,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
*register as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new(func.to_string().into())),
|
||||
OwnedValue::build_text(Rc::new(func.to_string().into())),
|
||||
0,
|
||||
format!("accum=r[{}]", *register),
|
||||
),
|
||||
@@ -693,7 +694,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*columns as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new(format!(
|
||||
OwnedValue::build_text(Rc::new(format!(
|
||||
"k({},{})",
|
||||
order.values.len(),
|
||||
to_print.join(",")
|
||||
@@ -711,7 +712,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*dest_reg as i32,
|
||||
*pseudo_cursor as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]=data", dest_reg),
|
||||
),
|
||||
@@ -735,7 +736,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*pc_if_empty as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -747,7 +748,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*pc_if_next as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -761,7 +762,7 @@ pub fn insn_to_str(
|
||||
*constant_mask,
|
||||
*start_reg as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::Text(Rc::new(func.func.to_string())),
|
||||
OwnedValue::build_text(Rc::new(func.func.to_string())),
|
||||
0,
|
||||
if func.arg_count == 0 {
|
||||
format!("r[{}]=func()", dest)
|
||||
@@ -785,7 +786,7 @@ pub fn insn_to_str(
|
||||
*yield_reg as i32,
|
||||
*jump_on_definition as i32,
|
||||
*start_offset as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -794,7 +795,7 @@ pub fn insn_to_str(
|
||||
*yield_reg as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -806,7 +807,7 @@ pub fn insn_to_str(
|
||||
*yield_reg as i32,
|
||||
*end_offset as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -820,7 +821,7 @@ pub fn insn_to_str(
|
||||
*cursor as i32,
|
||||
*record_reg as i32,
|
||||
*key_reg as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
*flag as u16,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -829,7 +830,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -842,7 +843,7 @@ pub fn insn_to_str(
|
||||
*cursor as i32,
|
||||
*rowid_reg as i32,
|
||||
*prev_largest_reg as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -851,7 +852,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -860,7 +861,7 @@ pub fn insn_to_str(
|
||||
*reg as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -873,7 +874,7 @@ pub fn insn_to_str(
|
||||
*cursor as i32,
|
||||
*target_pc as i32,
|
||||
*rowid_reg as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -885,7 +886,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
*root_page as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -894,7 +895,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -907,7 +908,7 @@ pub fn insn_to_str(
|
||||
*src_reg as i32,
|
||||
*dst_reg as i32,
|
||||
*amount as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]=r[{}]", dst_reg, src_reg),
|
||||
),
|
||||
@@ -916,7 +917,7 @@ pub fn insn_to_str(
|
||||
*db as i32,
|
||||
*root as i32,
|
||||
*flags as i32,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]=root iDb={} flags={}", root, db, flags),
|
||||
),
|
||||
@@ -925,7 +926,7 @@ pub fn insn_to_str(
|
||||
*cursor_id as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -934,7 +935,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -943,7 +944,7 @@ pub fn insn_to_str(
|
||||
*src as i32,
|
||||
*target_pc as i32,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("if (r[{}]==NULL) goto {}", src, target_pc),
|
||||
),
|
||||
@@ -952,7 +953,7 @@ pub fn insn_to_str(
|
||||
*db as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new(where_clause.clone())),
|
||||
OwnedValue::build_text(Rc::new(where_clause.clone())),
|
||||
0,
|
||||
where_clause.clone(),
|
||||
),
|
||||
@@ -961,7 +962,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -970,7 +971,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
@@ -979,7 +980,7 @@ pub fn insn_to_str(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
|
||||
514
core/vdbe/mod.rs
514
core/vdbe/mod.rs
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user