[Feat] Add TEMPFILES clause to the SELECT statement (#4084)
This commit is contained in:
parent
948666e33a
commit
23653e5fce
22 changed files with 124 additions and 125 deletions
|
@ -24,7 +24,7 @@ resolver = "2"
|
||||||
[features]
|
[features]
|
||||||
# Public features
|
# Public features
|
||||||
default = ["kv-mem"]
|
default = ["kv-mem"]
|
||||||
kv-mem = ["dep:echodb", "tokio/time"]
|
kv-mem = ["dep:echodb", "tokio/time", "dep:tempfile", "dep:ext-sort"]
|
||||||
kv-indxdb = ["dep:indxdb"]
|
kv-indxdb = ["dep:indxdb"]
|
||||||
kv-speedb = ["dep:speedb", "tokio/time", "dep:tempfile", "dep:ext-sort"]
|
kv-speedb = ["dep:speedb", "tokio/time", "dep:tempfile", "dep:ext-sort"]
|
||||||
kv-rocksdb = ["dep:rocksdb", "tokio/time", "dep:tempfile", "dep:ext-sort"]
|
kv-rocksdb = ["dep:rocksdb", "tokio/time", "dep:tempfile", "dep:ext-sort"]
|
||||||
|
|
|
@ -40,6 +40,7 @@ pub static INSECURE_FORWARD_RECORD_ACCESS_ERRORS: Lazy<bool> =
|
||||||
lazy_env_parse!("SURREAL_INSECURE_FORWARD_RECORD_ACCESS_ERRORS", bool, false);
|
lazy_env_parse!("SURREAL_INSECURE_FORWARD_RECORD_ACCESS_ERRORS", bool, false);
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
|
|
@ -14,6 +14,7 @@ use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::{self, Debug};
|
use std::fmt::{self, Debug};
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -64,16 +65,7 @@ pub struct Context<'a> {
|
||||||
// Capabilities
|
// Capabilities
|
||||||
capabilities: Arc<Capabilities>,
|
capabilities: Arc<Capabilities>,
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-mem",
|
||||||
feature = "kv-file",
|
|
||||||
feature = "kv-rocksdb",
|
|
||||||
feature = "kv-fdb",
|
|
||||||
feature = "kv-tikv",
|
|
||||||
feature = "kv-speedb"
|
|
||||||
))]
|
|
||||||
// Is the datastore in memory? (KV-MEM, WASM)
|
|
||||||
is_memory: bool,
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -108,15 +100,7 @@ impl<'a> Context<'a> {
|
||||||
capabilities: Capabilities,
|
capabilities: Capabilities,
|
||||||
index_stores: IndexStores,
|
index_stores: IndexStores,
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-mem",
|
||||||
feature = "kv-file",
|
|
||||||
feature = "kv-rocksdb",
|
|
||||||
feature = "kv-fdb",
|
|
||||||
feature = "kv-tikv",
|
|
||||||
feature = "kv-speedb"
|
|
||||||
))]
|
|
||||||
is_memory: bool,
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -138,15 +122,7 @@ impl<'a> Context<'a> {
|
||||||
capabilities: Arc::new(capabilities),
|
capabilities: Arc::new(capabilities),
|
||||||
index_stores,
|
index_stores,
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-mem",
|
||||||
feature = "kv-file",
|
|
||||||
feature = "kv-rocksdb",
|
|
||||||
feature = "kv-fdb",
|
|
||||||
feature = "kv-tikv",
|
|
||||||
feature = "kv-speedb"
|
|
||||||
))]
|
|
||||||
is_memory,
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -175,15 +151,7 @@ impl<'a> Context<'a> {
|
||||||
capabilities: Arc::new(Capabilities::default()),
|
capabilities: Arc::new(Capabilities::default()),
|
||||||
index_stores: IndexStores::default(),
|
index_stores: IndexStores::default(),
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-mem",
|
||||||
feature = "kv-file",
|
|
||||||
feature = "kv-rocksdb",
|
|
||||||
feature = "kv-fdb",
|
|
||||||
feature = "kv-tikv",
|
|
||||||
feature = "kv-speedb"
|
|
||||||
))]
|
|
||||||
is_memory: false,
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -209,15 +177,7 @@ impl<'a> Context<'a> {
|
||||||
capabilities: parent.capabilities.clone(),
|
capabilities: parent.capabilities.clone(),
|
||||||
index_stores: parent.index_stores.clone(),
|
index_stores: parent.index_stores.clone(),
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-mem",
|
||||||
feature = "kv-file",
|
|
||||||
feature = "kv-rocksdb",
|
|
||||||
feature = "kv-fdb",
|
|
||||||
feature = "kv-tikv",
|
|
||||||
feature = "kv-speedb"
|
|
||||||
))]
|
|
||||||
is_memory: parent.is_memory,
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -342,19 +302,7 @@ impl<'a> Context<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-mem",
|
||||||
feature = "kv-file",
|
|
||||||
feature = "kv-rocksdb",
|
|
||||||
feature = "kv-fdb",
|
|
||||||
feature = "kv-tikv",
|
|
||||||
feature = "kv-speedb"
|
|
||||||
))]
|
|
||||||
/// Return true if the underlying Datastore is KV-MEM (Or WASM)
|
|
||||||
pub fn is_memory(&self) -> bool {
|
|
||||||
self.is_memory
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
|
|
@ -299,6 +299,7 @@ impl Iterator {
|
||||||
// Prepare the results with possible optimisations on groups
|
// Prepare the results with possible optimisations on groups
|
||||||
self.results = self.results.prepare(
|
self.results = self.results.prepare(
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::ctx::Context;
|
||||||
use crate::dbs::group::GroupsCollector;
|
use crate::dbs::group::GroupsCollector;
|
||||||
use crate::dbs::plan::Explanation;
|
use crate::dbs::plan::Explanation;
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -20,6 +21,7 @@ pub(super) enum Results {
|
||||||
None,
|
None,
|
||||||
Memory(MemoryCollector),
|
Memory(MemoryCollector),
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -35,6 +37,7 @@ impl Results {
|
||||||
pub(super) fn prepare(
|
pub(super) fn prepare(
|
||||||
&mut self,
|
&mut self,
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -49,6 +52,7 @@ impl Results {
|
||||||
return Ok(Self::Groups(GroupsCollector::new(stm)));
|
return Ok(Self::Groups(GroupsCollector::new(stm)));
|
||||||
}
|
}
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -56,7 +60,7 @@ impl Results {
|
||||||
feature = "kv-tikv",
|
feature = "kv-tikv",
|
||||||
feature = "kv-speedb"
|
feature = "kv-speedb"
|
||||||
))]
|
))]
|
||||||
if !ctx.is_memory() {
|
if stm.tempfiles() {
|
||||||
if let Some(temp_dir) = ctx.temporary_directory() {
|
if let Some(temp_dir) = ctx.temporary_directory() {
|
||||||
return Ok(Self::File(Box::new(FileCollector::new(temp_dir)?)));
|
return Ok(Self::File(Box::new(FileCollector::new(temp_dir)?)));
|
||||||
}
|
}
|
||||||
|
@ -79,6 +83,7 @@ impl Results {
|
||||||
s.push(val);
|
s.push(val);
|
||||||
}
|
}
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -100,6 +105,7 @@ impl Results {
|
||||||
match self {
|
match self {
|
||||||
Self::Memory(m) => m.sort(orders),
|
Self::Memory(m) => m.sort(orders),
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -117,6 +123,7 @@ impl Results {
|
||||||
Self::None => {}
|
Self::None => {}
|
||||||
Self::Memory(m) => m.start_limit(start, limit),
|
Self::Memory(m) => m.start_limit(start, limit),
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -134,6 +141,7 @@ impl Results {
|
||||||
Self::None => 0,
|
Self::None => 0,
|
||||||
Self::Memory(s) => s.len(),
|
Self::Memory(s) => s.len(),
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -150,6 +158,7 @@ impl Results {
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
Self::Memory(m) => m.take_vec(),
|
Self::Memory(m) => m.take_vec(),
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -169,6 +178,7 @@ impl Results {
|
||||||
s.explain(exp);
|
s.explain(exp);
|
||||||
}
|
}
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
|
|
@ -207,7 +207,7 @@ impl<'a> Statement<'a> {
|
||||||
}
|
}
|
||||||
/// Returns any PARALLEL clause if specified
|
/// Returns any PARALLEL clause if specified
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub fn parallel(&self) -> bool {
|
pub fn parallel(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Statement::Select(v) => v.parallel,
|
Statement::Select(v) => v.parallel,
|
||||||
|
@ -219,6 +219,25 @@ impl<'a> Statement<'a> {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns any TEMPFILES clause if specified
|
||||||
|
#[inline]
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
|
feature = "kv-surrealkv",
|
||||||
|
feature = "kv-file",
|
||||||
|
feature = "kv-rocksdb",
|
||||||
|
feature = "kv-fdb",
|
||||||
|
feature = "kv-tikv",
|
||||||
|
feature = "kv-speedb"
|
||||||
|
))]
|
||||||
|
pub fn tempfiles(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Statement::Select(v) => v.tempfiles,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns any EXPLAIN clause if specified
|
/// Returns any EXPLAIN clause if specified
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn explain(&self) -> Option<&Explain> {
|
pub fn explain(&self) -> Option<&Explain> {
|
||||||
|
|
|
@ -50,6 +50,7 @@ impl From<Vec<Value>> for MemoryCollector {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
|
|
@ -12,6 +12,7 @@ use crate::vs::Error as VersionstampError;
|
||||||
use base64::DecodeError as Base64Error;
|
use base64::DecodeError as Base64Error;
|
||||||
use bincode::Error as BincodeError;
|
use bincode::Error as BincodeError;
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -1070,6 +1071,7 @@ impl From<reqwest::Error> for Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -93,6 +94,7 @@ pub struct Datastore {
|
||||||
// The JWKS object cache
|
// The JWKS object cache
|
||||||
jwks_cache: Arc<RwLock<JwksCache>>,
|
jwks_cache: Arc<RwLock<JwksCache>>,
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -376,6 +378,7 @@ impl Datastore {
|
||||||
#[cfg(feature = "jwks")]
|
#[cfg(feature = "jwks")]
|
||||||
jwks_cache: Arc::new(RwLock::new(JwksCache::new())),
|
jwks_cache: Arc::new(RwLock::new(JwksCache::new())),
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -438,6 +441,7 @@ impl Datastore {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -465,22 +469,6 @@ impl Datastore {
|
||||||
self.auth_enabled
|
self.auth_enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "kv-surrealkv",
|
|
||||||
feature = "kv-file",
|
|
||||||
feature = "kv-rocksdb",
|
|
||||||
feature = "kv-fdb",
|
|
||||||
feature = "kv-tikv",
|
|
||||||
feature = "kv-speedb"
|
|
||||||
))]
|
|
||||||
pub(crate) fn is_memory(&self) -> bool {
|
|
||||||
#[cfg(feature = "kv-mem")]
|
|
||||||
if matches!(self.inner, Inner::Mem(_)) {
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Is authentication level enabled for this Datastore?
|
/// Is authentication level enabled for this Datastore?
|
||||||
/// TODO(gguillemas): Remove this method once the legacy authentication is deprecated in v2.0.0
|
/// TODO(gguillemas): Remove this method once the legacy authentication is deprecated in v2.0.0
|
||||||
pub fn is_auth_level_enabled(&self) -> bool {
|
pub fn is_auth_level_enabled(&self) -> bool {
|
||||||
|
@ -1188,15 +1176,7 @@ impl Datastore {
|
||||||
self.capabilities.clone(),
|
self.capabilities.clone(),
|
||||||
self.index_stores.clone(),
|
self.index_stores.clone(),
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-mem",
|
||||||
feature = "kv-file",
|
|
||||||
feature = "kv-rocksdb",
|
|
||||||
feature = "kv-fdb",
|
|
||||||
feature = "kv-tikv",
|
|
||||||
feature = "kv-speedb"
|
|
||||||
))]
|
|
||||||
self.is_memory(),
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
|
|
@ -13,7 +13,7 @@ use revision::revisioned;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[revisioned(revision = 2)]
|
#[revisioned(revision = 3)]
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
|
||||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
@ -35,6 +35,8 @@ pub struct SelectStatement {
|
||||||
pub timeout: Option<Timeout>,
|
pub timeout: Option<Timeout>,
|
||||||
pub parallel: bool,
|
pub parallel: bool,
|
||||||
pub explain: Option<Explain>,
|
pub explain: Option<Explain>,
|
||||||
|
#[revision(start = 3)]
|
||||||
|
pub tempfiles: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SelectStatement {
|
impl SelectStatement {
|
||||||
|
|
|
@ -66,6 +66,7 @@ pub struct SerializeSelectStatement {
|
||||||
timeout: Option<Timeout>,
|
timeout: Option<Timeout>,
|
||||||
parallel: Option<bool>,
|
parallel: Option<bool>,
|
||||||
explain: Option<Explain>,
|
explain: Option<Explain>,
|
||||||
|
tempfiles: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl serde::ser::SerializeStruct for SerializeSelectStatement {
|
impl serde::ser::SerializeStruct for SerializeSelectStatement {
|
||||||
|
@ -122,6 +123,9 @@ impl serde::ser::SerializeStruct for SerializeSelectStatement {
|
||||||
"parallel" => {
|
"parallel" => {
|
||||||
self.parallel = Some(value.serialize(ser::primitive::bool::Serializer.wrap())?);
|
self.parallel = Some(value.serialize(ser::primitive::bool::Serializer.wrap())?);
|
||||||
}
|
}
|
||||||
|
"tempfiles" => {
|
||||||
|
self.tempfiles = Some(value.serialize(ser::primitive::bool::Serializer.wrap())?);
|
||||||
|
}
|
||||||
"explain" => {
|
"explain" => {
|
||||||
self.explain = value.serialize(ser::explain::opt::Serializer.wrap())?;
|
self.explain = value.serialize(ser::explain::opt::Serializer.wrap())?;
|
||||||
}
|
}
|
||||||
|
@ -133,14 +137,15 @@ impl serde::ser::SerializeStruct for SerializeSelectStatement {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Error> {
|
fn end(self) -> Result<Self::Ok, Error> {
|
||||||
match (self.expr, self.what, self.parallel) {
|
match (self.expr, self.what, self.parallel, self.tempfiles) {
|
||||||
(Some(expr), Some(what), Some(parallel)) => Ok(SelectStatement {
|
(Some(expr), Some(what), Some(parallel), Some(tempfiles)) => Ok(SelectStatement {
|
||||||
expr,
|
expr,
|
||||||
omit: self.omit,
|
omit: self.omit,
|
||||||
only: self.only.is_some_and(|v| v),
|
only: self.only.is_some_and(|v| v),
|
||||||
what,
|
what,
|
||||||
with: self.with,
|
with: self.with,
|
||||||
parallel,
|
parallel,
|
||||||
|
tempfiles,
|
||||||
explain: self.explain,
|
explain: self.explain,
|
||||||
cond: self.cond,
|
cond: self.cond,
|
||||||
split: self.split,
|
split: self.split,
|
||||||
|
|
|
@ -204,6 +204,7 @@ pub(crate) static KEYWORDS: phf::Map<UniCase<&'static str>, TokenKind> = phf_map
|
||||||
UniCase::ascii("STRUCTURE") => TokenKind::Keyword(Keyword::Structure),
|
UniCase::ascii("STRUCTURE") => TokenKind::Keyword(Keyword::Structure),
|
||||||
UniCase::ascii("TABLE") => TokenKind::Keyword(Keyword::Table),
|
UniCase::ascii("TABLE") => TokenKind::Keyword(Keyword::Table),
|
||||||
UniCase::ascii("TB") => TokenKind::Keyword(Keyword::Table),
|
UniCase::ascii("TB") => TokenKind::Keyword(Keyword::Table),
|
||||||
|
UniCase::ascii("TEMPFILES") => TokenKind::Keyword(Keyword::TempFiles),
|
||||||
UniCase::ascii("TERMS_CACHE") => TokenKind::Keyword(Keyword::TermsCache),
|
UniCase::ascii("TERMS_CACHE") => TokenKind::Keyword(Keyword::TermsCache),
|
||||||
UniCase::ascii("TERMS_ORDER") => TokenKind::Keyword(Keyword::TermsOrder),
|
UniCase::ascii("TERMS_ORDER") => TokenKind::Keyword(Keyword::TermsOrder),
|
||||||
UniCase::ascii("THEN") => TokenKind::Keyword(Keyword::Then),
|
UniCase::ascii("THEN") => TokenKind::Keyword(Keyword::Then),
|
||||||
|
|
|
@ -58,6 +58,7 @@ impl Parser<'_> {
|
||||||
let version = self.try_parse_version()?;
|
let version = self.try_parse_version()?;
|
||||||
let timeout = self.try_parse_timeout()?;
|
let timeout = self.try_parse_timeout()?;
|
||||||
let parallel = self.eat(t!("PARALLEL"));
|
let parallel = self.eat(t!("PARALLEL"));
|
||||||
|
let tempfiles = self.eat(t!("TEMPFILES"));
|
||||||
let explain = self.eat(t!("EXPLAIN")).then(|| Explain(self.eat(t!("FULL"))));
|
let explain = self.eat(t!("EXPLAIN")).then(|| Explain(self.eat(t!("FULL"))));
|
||||||
|
|
||||||
Ok(SelectStatement {
|
Ok(SelectStatement {
|
||||||
|
@ -76,6 +77,7 @@ impl Parser<'_> {
|
||||||
version,
|
version,
|
||||||
timeout,
|
timeout,
|
||||||
parallel,
|
parallel,
|
||||||
|
tempfiles,
|
||||||
explain,
|
explain,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1444,6 +1444,7 @@ SELECT bar as foo,[1,2],bar OMIT bar FROM ONLY a,1
|
||||||
version: Some(Version(Datetime(expected_datetime))),
|
version: Some(Version(Datetime(expected_datetime))),
|
||||||
timeout: None,
|
timeout: None,
|
||||||
parallel: false,
|
parallel: false,
|
||||||
|
tempfiles: false,
|
||||||
explain: Some(Explain(true)),
|
explain: Some(Explain(true)),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
|
@ -498,6 +498,7 @@ fn statements() -> Vec<Statement> {
|
||||||
version: Some(Version(Datetime(expected_datetime))),
|
version: Some(Version(Datetime(expected_datetime))),
|
||||||
timeout: None,
|
timeout: None,
|
||||||
parallel: false,
|
parallel: false,
|
||||||
|
tempfiles: false,
|
||||||
explain: Some(Explain(true)),
|
explain: Some(Explain(true)),
|
||||||
}),
|
}),
|
||||||
Statement::Set(SetStatement {
|
Statement::Set(SetStatement {
|
||||||
|
|
|
@ -159,6 +159,7 @@ keyword! {
|
||||||
Start => "START",
|
Start => "START",
|
||||||
Structure => "STRUCTURE",
|
Structure => "STRUCTURE",
|
||||||
Table => "TABLE",
|
Table => "TABLE",
|
||||||
|
TempFiles => "TEMPFILES",
|
||||||
TermsCache => "TERMS_CACHE",
|
TermsCache => "TERMS_CACHE",
|
||||||
TermsOrder => "TERMS_ORDER",
|
TermsOrder => "TERMS_ORDER",
|
||||||
Then => "THEN",
|
Then => "THEN",
|
||||||
|
|
|
@ -147,6 +147,7 @@ pub(crate) fn router(
|
||||||
.with_capabilities(address.config.capabilities);
|
.with_capabilities(address.config.capabilities);
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{dbs::Capabilities, iam::Level};
|
use crate::{dbs::Capabilities, iam::Level};
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -27,6 +28,7 @@ pub struct Config {
|
||||||
pub(crate) tick_interval: Option<Duration>,
|
pub(crate) tick_interval: Option<Duration>,
|
||||||
pub(crate) capabilities: Capabilities,
|
pub(crate) capabilities: Capabilities,
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
@ -122,7 +124,9 @@ impl Config {
|
||||||
self.capabilities = capabilities;
|
self.capabilities = capabilities;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
feature = "kv-mem",
|
||||||
feature = "kv-surrealkv",
|
feature = "kv-surrealkv",
|
||||||
feature = "kv-file",
|
feature = "kv-file",
|
||||||
feature = "kv-rocksdb",
|
feature = "kv-rocksdb",
|
||||||
|
|
|
@ -38,13 +38,6 @@ pub(crate) fn file_exists(path: &str) -> Result<PathBuf, String> {
|
||||||
Ok(path)
|
Ok(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "storage-surrealkv",
|
|
||||||
feature = "storage-rocksdb",
|
|
||||||
feature = "storage-fdb",
|
|
||||||
feature = "storage-tikv",
|
|
||||||
feature = "storage-speedb"
|
|
||||||
))]
|
|
||||||
pub(crate) fn dir_exists(path: &str) -> Result<PathBuf, String> {
|
pub(crate) fn dir_exists(path: &str) -> Result<PathBuf, String> {
|
||||||
let path = path_exists(path)?;
|
let path = path_exists(path)?;
|
||||||
if !path.is_dir() {
|
if !path.is_dir() {
|
||||||
|
|
|
@ -1,13 +1,6 @@
|
||||||
use crate::cli::CF;
|
use crate::cli::CF;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
#[cfg(any(
|
|
||||||
feature = "storage-surrealkv",
|
|
||||||
feature = "storage-rocksdb",
|
|
||||||
feature = "storage-fdb",
|
|
||||||
feature = "storage-tikv",
|
|
||||||
feature = "storage-speedb"
|
|
||||||
))]
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::{Arc, OnceLock};
|
use std::sync::{Arc, OnceLock};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -45,13 +38,6 @@ pub struct StartCommandDbsOptions {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
#[command(next_help_heading = "Capabilities")]
|
#[command(next_help_heading = "Capabilities")]
|
||||||
caps: DbsCapabilities,
|
caps: DbsCapabilities,
|
||||||
#[cfg(any(
|
|
||||||
feature = "storage-surrealkv",
|
|
||||||
feature = "storage-speedb",
|
|
||||||
feature = "storage-rocksdb",
|
|
||||||
feature = "storage-fdb",
|
|
||||||
feature = "storage-tikv",
|
|
||||||
))]
|
|
||||||
#[arg(help = "Sets the directory for storing temporary database files")]
|
#[arg(help = "Sets the directory for storing temporary database files")]
|
||||||
#[arg(env = "SURREAL_TEMPORARY_DIRECTORY", long = "temporary-directory")]
|
#[arg(env = "SURREAL_TEMPORARY_DIRECTORY", long = "temporary-directory")]
|
||||||
#[arg(value_parser = super::cli::validator::dir_exists)]
|
#[arg(value_parser = super::cli::validator::dir_exists)]
|
||||||
|
@ -233,13 +219,6 @@ pub async fn init(
|
||||||
// TODO(gguillemas): Remove this field once the legacy authentication is deprecated in v2.0.0
|
// TODO(gguillemas): Remove this field once the legacy authentication is deprecated in v2.0.0
|
||||||
auth_level_enabled,
|
auth_level_enabled,
|
||||||
caps,
|
caps,
|
||||||
#[cfg(any(
|
|
||||||
feature = "storage-surrealkv",
|
|
||||||
feature = "storage-rocksdb",
|
|
||||||
feature = "storage-fdb",
|
|
||||||
feature = "storage-tikv",
|
|
||||||
feature = "storage-speedb"
|
|
||||||
))]
|
|
||||||
temporary_directory,
|
temporary_directory,
|
||||||
}: StartCommandDbsOptions,
|
}: StartCommandDbsOptions,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
@ -280,13 +259,6 @@ pub async fn init(
|
||||||
.with_auth_level_enabled(auth_level_enabled)
|
.with_auth_level_enabled(auth_level_enabled)
|
||||||
.with_capabilities(caps);
|
.with_capabilities(caps);
|
||||||
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "storage-surrealkv",
|
|
||||||
feature = "storage-rocksdb",
|
|
||||||
feature = "storage-fdb",
|
|
||||||
feature = "storage-tikv",
|
|
||||||
feature = "storage-speedb"
|
|
||||||
))]
|
|
||||||
let mut dbs = match temporary_directory {
|
let mut dbs = match temporary_directory {
|
||||||
Some(tmp_dir) => dbs.with_temporary_directory(tmp_dir),
|
Some(tmp_dir) => dbs.with_temporary_directory(tmp_dir),
|
||||||
_ => dbs,
|
_ => dbs,
|
||||||
|
|
|
@ -191,6 +191,16 @@ pub async fn start_server_with_defaults() -> Result<(String, Child), Box<dyn Err
|
||||||
start_server(StartServerArguments::default()).await
|
start_server(StartServerArguments::default()).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn start_server_with_temporary_directory(
|
||||||
|
path: &str,
|
||||||
|
) -> Result<(String, Child), Box<dyn Error>> {
|
||||||
|
start_server(StartServerArguments {
|
||||||
|
temporary_directory: Some(path.to_string()),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn start_server(
|
pub async fn start_server(
|
||||||
StartServerArguments {
|
StartServerArguments {
|
||||||
path,
|
path,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use super::common::{self, Format, Socket, DB, NS, PASS, USER};
|
use super::common::{self, Format, Socket, DB, NS, PASS, USER};
|
||||||
|
use assert_fs::TempDir;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
@ -1539,3 +1540,46 @@ async fn relate_rpc() {
|
||||||
// Test passed
|
// Test passed
|
||||||
server.finish().unwrap();
|
server.finish().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test(tokio::test)]
|
||||||
|
async fn temporary_directory() {
|
||||||
|
// Setup database server
|
||||||
|
let temp_dir = TempDir::new().unwrap();
|
||||||
|
let (addr, mut server) =
|
||||||
|
common::start_server_with_temporary_directory(temp_dir.to_string_lossy().as_ref())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
// Connect to WebSocket
|
||||||
|
let mut socket = Socket::connect(&addr, SERVER, FORMAT).await.unwrap();
|
||||||
|
// Authenticate the connection
|
||||||
|
socket.send_message_signin(USER, PASS, None, None, None).await.unwrap();
|
||||||
|
// Specify a namespace and database
|
||||||
|
socket.send_message_use(Some(NS), Some(DB)).await.unwrap();
|
||||||
|
// create records
|
||||||
|
socket.send_message_query("CREATE test:a, test:b").await.unwrap();
|
||||||
|
// These selects use the memory collector
|
||||||
|
let mut res =
|
||||||
|
socket.send_message_query("SELECT * FROM test ORDER BY id DESC EXPLAIN").await.unwrap();
|
||||||
|
let expected = json!([{"detail": { "table": "test" }, "operation": "Iterate Table" }, { "detail": { "type": "Memory" }, "operation": "Collector" }]);
|
||||||
|
assert_eq!(res.remove(0)["result"], expected);
|
||||||
|
// And return the correct result
|
||||||
|
let mut res = socket.send_message_query("SELECT * FROM test ORDER BY id DESC").await.unwrap();
|
||||||
|
let expected = json!([{"id": "test:b" }, { "id": "test:a" }]);
|
||||||
|
assert_eq!(res.remove(0)["result"], expected);
|
||||||
|
// This one should the file collector
|
||||||
|
let mut res = socket
|
||||||
|
.send_message_query("SELECT * FROM test ORDER BY id DESC TEMPFILES EXPLAIN")
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let expected = json!([{"detail": { "table": "test" }, "operation": "Iterate Table" }, { "detail": { "type": "TempFiles" }, "operation": "Collector" }]);
|
||||||
|
assert_eq!(res.remove(0)["result"], expected);
|
||||||
|
// And return the correct result
|
||||||
|
let mut res =
|
||||||
|
socket.send_message_query("SELECT * FROM test ORDER BY id DESC TEMPFILES").await.unwrap();
|
||||||
|
let expected = json!([{"id": "test:b" }, { "id": "test:a" }]);
|
||||||
|
assert_eq!(res.remove(0)["result"], expected);
|
||||||
|
// Test passed
|
||||||
|
server.finish().unwrap();
|
||||||
|
// Cleanup
|
||||||
|
temp_dir.close().unwrap();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue