mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-18 07:34:19 +01:00
Merge 'Implement the UnixEpoch function' from Rajiv Harlalka
Adds the UnixEpoch function. #158 (without modifiers) Closes #273
This commit is contained in:
@@ -143,7 +143,7 @@ This document describes the SQLite compatibility status of Limbo:
|
||||
| time() | Partial | partially supports modifiers |
|
||||
| datetime() | No | |
|
||||
| julianday() | No | |
|
||||
| unixepoch() | No | |
|
||||
| unixepoch() | Partial | does not support modifiers |
|
||||
| strftime() | No | |
|
||||
| timediff() | No | |
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ pub enum ScalarFunc {
|
||||
Time,
|
||||
Unicode,
|
||||
Quote,
|
||||
UnixEpoch,
|
||||
}
|
||||
|
||||
impl ToString for ScalarFunc {
|
||||
@@ -91,6 +92,7 @@ impl ToString for ScalarFunc {
|
||||
ScalarFunc::Time => "time".to_string(),
|
||||
ScalarFunc::Unicode => "unicode".to_string(),
|
||||
ScalarFunc::Quote => "quote".to_string(),
|
||||
ScalarFunc::UnixEpoch => "unixepoch".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,6 +139,7 @@ impl Func {
|
||||
"unicode" => Ok(Func::Scalar(ScalarFunc::Unicode)),
|
||||
"quote" => Ok(Func::Scalar(ScalarFunc::Quote)),
|
||||
"json" => Ok(Func::Json(JsonFunc::JSON)),
|
||||
"unixepoch" => Ok(Func::Scalar(ScalarFunc::UnixEpoch)),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -941,7 +941,30 @@ pub fn translate_expr(
|
||||
dest: target_register,
|
||||
func: crate::vdbe::Func::Scalar(ScalarFunc::Substring),
|
||||
});
|
||||
|
||||
Ok(target_register)
|
||||
}
|
||||
ScalarFunc::UnixEpoch => {
|
||||
let mut start_reg = 0;
|
||||
if let Some(args) = args {
|
||||
if args.len() > 1 {
|
||||
crate::bail_parse_error!("epoch function with > 1 arguments. Modifiers are not yet supported.");
|
||||
} else if args.len() == 1 {
|
||||
let arg_reg = program.alloc_register();
|
||||
let _ = translate_expr(
|
||||
program,
|
||||
referenced_tables,
|
||||
&args[0],
|
||||
arg_reg,
|
||||
cursor_hint,
|
||||
)?;
|
||||
start_reg = arg_reg;
|
||||
}
|
||||
}
|
||||
program.emit_insn(Insn::Function {
|
||||
start_reg,
|
||||
dest: target_register,
|
||||
func: crate::vdbe::Func::Scalar(srf),
|
||||
});
|
||||
Ok(target_register)
|
||||
}
|
||||
ScalarFunc::Time => {
|
||||
|
||||
@@ -94,6 +94,18 @@ fn apply_modifier(dt: &mut NaiveDateTime, modifier: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn exec_unixepoch(time_value: &OwnedValue) -> Result<String> {
|
||||
let dt = parse_naive_date_time(time_value);
|
||||
match dt {
|
||||
Some(dt) => Ok(get_unixepoch_from_naive_datetime(dt)),
|
||||
None => Ok(String::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_unixepoch_from_naive_datetime(value: NaiveDateTime) -> String {
|
||||
return value.and_utc().timestamp().to_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),
|
||||
|
||||
@@ -33,7 +33,7 @@ use crate::storage::{btree::BTreeCursor, pager::Pager};
|
||||
use crate::types::{AggContext, Cursor, CursorResult, OwnedRecord, OwnedValue, Record};
|
||||
use crate::Result;
|
||||
|
||||
use datetime::{exec_date, exec_time};
|
||||
use datetime::{exec_date, exec_time, exec_unixepoch};
|
||||
|
||||
use rand::distributions::{Distribution, Uniform};
|
||||
use rand::{thread_rng, Rng};
|
||||
@@ -1365,6 +1365,28 @@ impl Program {
|
||||
state.registers[*dest] = result;
|
||||
state.pc += 1;
|
||||
}
|
||||
Func::Scalar(ScalarFunc::UnixEpoch) => {
|
||||
if *start_reg == 0 {
|
||||
let unixepoch: String =
|
||||
exec_unixepoch(&OwnedValue::Text(Rc::new("now".to_string())))?;
|
||||
state.registers[*dest] = OwnedValue::Text(Rc::new(unixepoch));
|
||||
} else {
|
||||
let datetime_value = &state.registers[*start_reg];
|
||||
let unixepoch = exec_unixepoch(datetime_value);
|
||||
match unixepoch {
|
||||
Ok(time) => {
|
||||
state.registers[*dest] = OwnedValue::Text(Rc::new(time))
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(LimboError::ParseError(format!(
|
||||
"Error encountered while parsing datetime value: {}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
state.pc += 1
|
||||
}
|
||||
Func::Scalar(ScalarFunc::Unicode) => {
|
||||
let reg_value = state.registers[*start_reg].borrow_mut();
|
||||
state.registers[*dest] = exec_unicode(reg_value);
|
||||
|
||||
@@ -123,3 +123,23 @@ do_execsql_test time-with-invalid-modifier {
|
||||
SELECT time('2023-05-18 15:30:45', '+1 hour', 'invalid modifier');
|
||||
} {{}}
|
||||
|
||||
|
||||
do_execsql_test unixepoch-at-start {
|
||||
SELECT unixepoch('1970-01-01');
|
||||
} {0}
|
||||
|
||||
do_execsql_test unixepoch-at-1-second-before-epochtime {
|
||||
SELECT unixepoch('1969-12-31 23:59:59');
|
||||
} {-1}
|
||||
|
||||
do_execsql_test unixepoch-at-future {
|
||||
SELECT unixepoch('9999-12-31 23:59:59');
|
||||
} {253402300799}
|
||||
|
||||
do_execsql_test unixepoch-at-start-of-time {
|
||||
SELECT unixepoch('0000-01-01 00:00:00');
|
||||
} {-62167219200}
|
||||
|
||||
do_execsql_test unixepoch-at-millisecond-precision-input-produces-seconds-precision-output {
|
||||
SELECT unixepoch('2022-01-27 12:59:28.052');
|
||||
} {1643288368}
|
||||
@@ -441,4 +441,4 @@ do_execsql_test quote-null {
|
||||
|
||||
do_execsql_test quote-integer {
|
||||
SELECT quote(123)
|
||||
} {123}
|
||||
} {123}
|
||||
Reference in New Issue
Block a user