Delay Record ID generation when using functions (#2469)
This commit is contained in:
parent
1fd6d991ae
commit
f01da5f577
6 changed files with 86 additions and 12 deletions
|
@ -17,7 +17,7 @@ resolver = "2"
|
|||
|
||||
[features]
|
||||
# Public features
|
||||
default = ["protocol-ws", "rustls"]
|
||||
default = ["protocol-ws", "rustls", "kv-mem"]
|
||||
protocol-http = ["dep:reqwest", "dep:tokio-util"]
|
||||
protocol-ws = ["dep:tokio-tungstenite", "tokio/time"]
|
||||
kv-mem = ["dep:echodb", "tokio/time"]
|
||||
|
|
|
@ -11,6 +11,7 @@ mod tls;
|
|||
|
||||
use crate::api::err::Error;
|
||||
use crate::sql::constant::ConstantValue;
|
||||
use crate::sql::id::Gen;
|
||||
use crate::sql::to_value;
|
||||
use crate::sql::Thing;
|
||||
use crate::sql::Value;
|
||||
|
@ -325,6 +326,11 @@ fn into_json(value: Value, simplify: bool) -> JsonValue {
|
|||
sql::Id::String(s) => Id::String(s),
|
||||
sql::Id::Array(arr) => Id::Array((arr, simplify).into()),
|
||||
sql::Id::Object(obj) => Id::Object((obj, simplify).into()),
|
||||
sql::Id::Generate(v) => match v {
|
||||
Gen::Rand => Id::from((sql::Id::rand(), simplify)),
|
||||
Gen::Ulid => Id::from((sql::Id::ulid(), simplify)),
|
||||
Gen::Uuid => Id::from((sql::Id::uuid(), simplify)),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,14 @@ use serde::{Deserialize, Serialize};
|
|||
use std::fmt::{self, Display, Formatter};
|
||||
use ulid::Ulid;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
|
||||
#[revisioned(revision = 1)]
|
||||
pub enum Gen {
|
||||
Rand,
|
||||
Ulid,
|
||||
Uuid,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
|
||||
#[revisioned(revision = 1)]
|
||||
pub enum Id {
|
||||
|
@ -29,6 +37,7 @@ pub enum Id {
|
|||
String(String),
|
||||
Array(Array),
|
||||
Object(Object),
|
||||
Generate(Gen),
|
||||
}
|
||||
|
||||
impl From<i64> for Id {
|
||||
|
@ -149,8 +158,13 @@ impl Id {
|
|||
match self {
|
||||
Self::Number(v) => v.to_string(),
|
||||
Self::String(v) => v.to_string(),
|
||||
Self::Object(v) => v.to_string(),
|
||||
Self::Array(v) => v.to_string(),
|
||||
Self::Object(v) => v.to_string(),
|
||||
Self::Generate(v) => match v {
|
||||
Gen::Rand => "rand()".to_string(),
|
||||
Gen::Ulid => "ulid()".to_string(),
|
||||
Gen::Uuid => "uuid()".to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -160,8 +174,13 @@ impl Display for Id {
|
|||
match self {
|
||||
Self::Number(v) => Display::fmt(v, f),
|
||||
Self::String(v) => Display::fmt(&escape_rid(v), f),
|
||||
Self::Object(v) => Display::fmt(v, f),
|
||||
Self::Array(v) => Display::fmt(v, f),
|
||||
Self::Object(v) => Display::fmt(v, f),
|
||||
Self::Generate(v) => match v {
|
||||
Gen::Rand => Display::fmt("rand()", f),
|
||||
Gen::Ulid => Display::fmt("ulid()", f),
|
||||
Gen::Uuid => Display::fmt("uuid()", f),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,13 +197,18 @@ impl Id {
|
|||
match self {
|
||||
Id::Number(v) => Ok(Id::Number(*v)),
|
||||
Id::String(v) => Ok(Id::String(v.clone())),
|
||||
Id::Array(v) => match v.compute(ctx, opt, txn, doc).await? {
|
||||
Value::Array(v) => Ok(Id::Array(v)),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Id::Object(v) => match v.compute(ctx, opt, txn, doc).await? {
|
||||
Value::Object(v) => Ok(Id::Object(v)),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Id::Array(v) => match v.compute(ctx, opt, txn, doc).await? {
|
||||
Value::Array(v) => Ok(Id::Array(v)),
|
||||
_ => unreachable!(),
|
||||
Id::Generate(v) => match v {
|
||||
Gen::Rand => Ok(Self::rand()),
|
||||
Gen::Ulid => Ok(Self::ulid()),
|
||||
Gen::Uuid => Ok(Self::uuid()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::doc::CursorDoc;
|
|||
use crate::err::Error;
|
||||
use crate::sql::error::IResult;
|
||||
use crate::sql::escape::escape_rid;
|
||||
use crate::sql::id::{id, Id};
|
||||
use crate::sql::id::{id, Gen, Id};
|
||||
use crate::sql::ident::ident_raw;
|
||||
use crate::sql::strand::Strand;
|
||||
use crate::sql::value::Value;
|
||||
|
@ -135,9 +135,9 @@ fn thing_raw(i: &str) -> IResult<&str, Thing> {
|
|||
let (i, t) = ident_raw(i)?;
|
||||
let (i, _) = char(':')(i)?;
|
||||
let (i, v) = alt((
|
||||
map(tag("rand()"), |_| Id::rand()),
|
||||
map(tag("ulid()"), |_| Id::ulid()),
|
||||
map(tag("uuid()"), |_| Id::uuid()),
|
||||
map(tag("rand()"), |_| Id::Generate(Gen::Rand)),
|
||||
map(tag("ulid()"), |_| Id::Generate(Gen::Ulid)),
|
||||
map(tag("uuid()"), |_| Id::Generate(Gen::Uuid)),
|
||||
id,
|
||||
))(i)?;
|
||||
Ok((
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::sql::fmt::{Fmt, Pretty};
|
|||
use crate::sql::function::{self, function, Function};
|
||||
use crate::sql::future::{future, Future};
|
||||
use crate::sql::geometry::{geometry, Geometry};
|
||||
use crate::sql::id::Id;
|
||||
use crate::sql::id::{Gen, Id};
|
||||
use crate::sql::idiom::{self, Idiom};
|
||||
use crate::sql::kind::Kind;
|
||||
use crate::sql::model::{model, Model};
|
||||
|
@ -531,8 +531,13 @@ impl From<Id> for Value {
|
|||
match v {
|
||||
Id::Number(v) => v.into(),
|
||||
Id::String(v) => v.into(),
|
||||
Id::Object(v) => v.into(),
|
||||
Id::Array(v) => v.into(),
|
||||
Id::Object(v) => v.into(),
|
||||
Id::Generate(v) => match v {
|
||||
Gen::Rand => Id::rand().into(),
|
||||
Gen::Ulid => Id::ulid().into(),
|
||||
Gen::Uuid => Id::uuid().into(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use surrealdb::dbs::Session;
|
|||
use surrealdb::err::Error;
|
||||
use surrealdb::iam::Role;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Part;
|
||||
use surrealdb::sql::Thing;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
|
@ -136,6 +137,44 @@ async fn create_with_id() -> Result<(), Error> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn create_with_custom_function() -> Result<(), Error> {
|
||||
let sql = "
|
||||
DEFINE FUNCTION fn::record::create($data: any) {
|
||||
RETURN CREATE person:ulid() CONTENT { data: $data } RETURN AFTER;
|
||||
};
|
||||
RETURN fn::record::create({ test: true, name: 'Tobie' });
|
||||
RETURN fn::record::create({ test: true, name: 'Jaime' });
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(tmp.is_ok());
|
||||
//
|
||||
let tmp = res.remove(0).result?.pick(&[Part::from("data")]);
|
||||
let val = Value::parse(
|
||||
"{
|
||||
test: true,
|
||||
name: 'Tobie'
|
||||
}",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?.pick(&[Part::from("data")]);
|
||||
let val = Value::parse(
|
||||
"{
|
||||
test: true,
|
||||
name: 'Jaime'
|
||||
}",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn create_or_insert_with_permissions() -> Result<(), Error> {
|
||||
let sql = "
|
||||
|
|
Loading…
Reference in a new issue