Merge 'Implement the UnixEpoch function' from Rajiv Harlalka

Adds the UnixEpoch function. #158  (without modifiers)

Closes #273
This commit is contained in:
Pekka Enberg
2024-08-30 18:26:06 +03:00
7 changed files with 84 additions and 4 deletions

View File

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

View File

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

View File

@@ -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 => {

View File

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

View File

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

View File

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

View File

@@ -441,4 +441,4 @@ do_execsql_test quote-null {
do_execsql_test quote-integer {
SELECT quote(123)
} {123}
} {123}