time functions for WASM

main
Ziyang Hu 2 years ago
parent 54623cb4d0
commit 5d41f028ea

1
Cargo.lock generated

@ -494,6 +494,7 @@ dependencies = [
"either", "either",
"env_logger", "env_logger",
"itertools 0.10.5", "itertools 0.10.5",
"js-sys",
"lazy_static", "lazy_static",
"log", "log",
"miette", "miette",

@ -1,5 +1,5 @@
[profile.release] #[profile.release]
lto = true #lto = true
[workspace] [workspace]
members = ["cozorocks", "cozo-lib-c", "cozo-lib-java", "cozo-core", "cozoserver", "cozo-lib-wasm"] members = ["cozorocks", "cozo-lib-c", "cozo-lib-java", "cozo-core", "cozoserver", "cozo-lib-wasm"]

@ -38,7 +38,7 @@ jemalloc = ["dep:tikv-jemallocator-global", "cozorocks?/jemalloc"]
## Enables io-uring option for the RocksDB storage ## Enables io-uring option for the RocksDB storage
io-uring = ["cozorocks?/io-uring"] io-uring = ["cozorocks?/io-uring"]
## Enables the WASM target ## Enables the WASM target
wasm = ["uuid/js"] wasm = ["uuid/js", "dep:js-sys"]
## Allows threading and enables the use of the `rayon` library for parallelizing algorithms ## Allows threading and enables the use of the `rayon` library for parallelizing algorithms
rayon = ["dep:rayon"] rayon = ["dep:rayon"]
## Disallows the use of threads ## Disallows the use of threads
@ -94,5 +94,6 @@ sled = { version = "0.34.7", optional = true }
tikv-client = { version = "0.1.0", optional = true } tikv-client = { version = "0.1.0", optional = true }
tokio = { version = "1.21.2", optional = true } tokio = { version = "1.21.2", optional = true }
sqlite = { version = "0.30.1", optional = true } sqlite = { version = "0.30.1", optional = true }
js-sys = { version = "0.3.60", optional = true }
#redb = "0.9.0" #redb = "0.9.0"
#ouroboros = "0.15.5" #ouroboros = "0.15.5"

@ -13,6 +13,8 @@ use std::time::{SystemTime, UNIX_EPOCH};
use chrono::{DateTime, TimeZone, Utc}; use chrono::{DateTime, TimeZone, Utc};
use itertools::Itertools; use itertools::Itertools;
#[cfg(feature = "wasm")]
use js_sys::Date;
use miette::{bail, ensure, miette, Result}; use miette::{bail, ensure, miette, Result};
use num_traits::FloatConst; use num_traits::FloatConst;
use rand::prelude::*; use rand::prelude::*;
@ -1434,7 +1436,8 @@ pub(crate) fn op_to_uuid(args: &[DataValue]) -> Result<DataValue> {
define_op!(OP_NOW, 0, false); define_op!(OP_NOW, 0, false);
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
pub(crate) fn op_now(_args: &[DataValue]) -> Result<DataValue> { pub(crate) fn op_now(_args: &[DataValue]) -> Result<DataValue> {
bail!("`op_now` is not supported under WASM runtime") let d: f64 = Date::now() / 1000.;
Ok(DataValue::from(d))
} }
#[cfg(not(feature = "wasm"))] #[cfg(not(feature = "wasm"))]
pub(crate) fn op_now(_args: &[DataValue]) -> Result<DataValue> { pub(crate) fn op_now(_args: &[DataValue]) -> Result<DataValue> {
@ -1445,20 +1448,22 @@ pub(crate) fn op_now(_args: &[DataValue]) -> Result<DataValue> {
} }
define_op!(OP_FORMAT_TIMESTAMP, 1, true); define_op!(OP_FORMAT_TIMESTAMP, 1, true);
#[cfg(feature = "wasm")]
pub(crate) fn op_format_timestamp(_args: &[DataValue]) -> Result<DataValue> {
bail!("`format_timestamp` is not supported under WASM")
}
#[cfg(not(feature = "wasm"))]
pub(crate) fn op_format_timestamp(args: &[DataValue]) -> Result<DataValue> { pub(crate) fn op_format_timestamp(args: &[DataValue]) -> Result<DataValue> {
let f = args[0] #[cfg(feature = "wasm")]
.get_float()
.ok_or_else(|| miette!("'format_timestamp' expects a number"))?;
let millis = (f * 1000.) as i64;
let dt = Utc let dt = Utc
.timestamp_millis_opt(millis) .timestamp_millis_opt(Date::now() as i64)
.latest() .latest()
.ok_or_else(|| miette!("bad time: {}", f))?; .ok_or_else(|| miette!("bad time input"))?;
#[cfg(not(feature = "wasm"))]
let dt = {
let f = args[0]
.get_float()
.ok_or_else(|| miette!("'format_timestamp' expects a number"))?;
let millis = (f * 1000.) as i64;
Utc.timestamp_millis_opt(millis)
.latest()
.ok_or_else(|| miette!("bad time: {}", f))?
};
match args.get(1) { match args.get(1) {
Some(tz_v) => { Some(tz_v) => {
let tz_s = tz_v.get_string().ok_or_else(|| { let tz_s = tz_v.get_string().ok_or_else(|| {
@ -1478,11 +1483,6 @@ pub(crate) fn op_format_timestamp(args: &[DataValue]) -> Result<DataValue> {
} }
define_op!(OP_PARSE_TIMESTAMP, 1, false); define_op!(OP_PARSE_TIMESTAMP, 1, false);
#[cfg(feature = "wasm")]
pub(crate) fn op_parse_timestamp(_args: &[DataValue]) -> Result<DataValue> {
bail!("`parse_timestamp` is not supported under WASM")
}
#[cfg(not(feature = "wasm"))]
pub(crate) fn op_parse_timestamp(args: &[DataValue]) -> Result<DataValue> { pub(crate) fn op_parse_timestamp(args: &[DataValue]) -> Result<DataValue> {
let s = args[0] let s = args[0]
.get_string() .get_string()
@ -1495,17 +1495,22 @@ pub(crate) fn op_parse_timestamp(args: &[DataValue]) -> Result<DataValue> {
} }
define_op!(OP_RAND_UUID_V1, 0, false); define_op!(OP_RAND_UUID_V1, 0, false);
#[cfg(feature = "wasm")]
pub(crate) fn op_rand_uuid_v1(_args: &[DataValue]) -> Result<DataValue> {
bail!("`rand_uuid_v1` is not supported under WASM")
}
#[cfg(not(feature = "wasm"))]
pub(crate) fn op_rand_uuid_v1(_args: &[DataValue]) -> Result<DataValue> { pub(crate) fn op_rand_uuid_v1(_args: &[DataValue]) -> Result<DataValue> {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let uuid_ctx = uuid::v1::Context::new(rng.gen()); let uuid_ctx = uuid::v1::Context::new(rng.gen());
let now = SystemTime::now(); #[cfg(feature = "wasm")]
let since_epoch = now.duration_since(UNIX_EPOCH).unwrap(); let ts = {
let ts = Timestamp::from_unix(uuid_ctx, since_epoch.as_secs(), since_epoch.subsec_nanos()); let since_epoch: f64 = Date::now();
let seconds = since_epoch.floor();
let fractional = (since_epoch - seconds) * 1.0e9;
Timestamp::from_unix(uuid_ctx, seconds as u64, fractional as u32)
};
#[cfg(not(feature = "wasm"))]
let ts = {
let now = SystemTime::now();
let since_epoch = now.duration_since(UNIX_EPOCH).unwrap();
Timestamp::from_unix(uuid_ctx, since_epoch.as_secs(), since_epoch.subsec_nanos())
};
let mut rand_vals = [0u8; 6]; let mut rand_vals = [0u8; 6];
rng.fill(&mut rand_vals); rng.fill(&mut rand_vals);
let id = uuid::Uuid::new_v1(ts, &rand_vals); let id = uuid::Uuid::new_v1(ts, &rand_vals);

@ -8,8 +8,8 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::{Arc, Mutex};
use std::thread; use std::thread;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
@ -17,7 +17,7 @@ use either::{Left, Right};
use itertools::Itertools; use itertools::Itertools;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use miette::{ use miette::{
bail, Diagnostic, ensure, GraphicalReportHandler, GraphicalTheme, IntoDiagnostic, bail, ensure, Diagnostic, GraphicalReportHandler, GraphicalTheme, IntoDiagnostic,
JSONReportHandler, Result, WrapErr, JSONReportHandler, Result, WrapErr,
}; };
use serde_json::{json, Map}; use serde_json::{json, Map};
@ -28,8 +28,8 @@ use crate::data::json::JsonValue;
use crate::data::program::{InputProgram, QueryAssertion, RelationOp}; use crate::data::program::{InputProgram, QueryAssertion, RelationOp};
use crate::data::tuple::Tuple; use crate::data::tuple::Tuple;
use crate::data::value::{DataValue, LARGEST_UTF_CHAR}; use crate::data::value::{DataValue, LARGEST_UTF_CHAR};
use crate::parse::{CozoScript, parse_script, SourceSpan};
use crate::parse::sys::SysOp; use crate::parse::sys::SysOp;
use crate::parse::{parse_script, CozoScript, SourceSpan};
use crate::query::compile::{CompiledProgram, CompiledRule, CompiledRuleSet}; use crate::query::compile::{CompiledProgram, CompiledRule, CompiledRuleSet};
use crate::query::relation::{ use crate::query::relation::{
FilteredRA, InMemRelationRA, InnerJoin, NegJoin, RelAlgebra, ReorderRA, StoredRA, UnificationRA, FilteredRA, InMemRelationRA, InnerJoin, NegJoin, RelAlgebra, ReorderRA, StoredRA, UnificationRA,
@ -573,7 +573,7 @@ impl<'s, S: Storage<'s>> Db<S> {
.as_secs_f64(); .as_secs_f64();
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
let since_the_epoch = 0.; let since_the_epoch = js_sys::Date::now();
let handle = RunningQueryHandle { let handle = RunningQueryHandle {
started_at: since_the_epoch, started_at: since_the_epoch,

@ -61,6 +61,10 @@ query(`
?[loved_by_e_not_b] := *love['eve', loved_by_e_not_b], not *love['bob', loved_by_e_not_b] ?[loved_by_e_not_b] := *love['eve', loved_by_e_not_b], not *love['bob', loved_by_e_not_b]
`); `);
query(`
?[] <- [[parse_timestamp(format_timestamp(now(), 'Asia/Shanghai')),]]
`);
query(` query(`
?[] <- [[rand_uuid_v1()]] ?[] <- [[rand_uuid_v1()]]
`); `);
Loading…
Cancel
Save