Update create API (#4688)

This commit is contained in:
Rushmore Mushambi 2024-09-04 13:48:31 +01:00 committed by GitHub
parent ebe8d49ed9
commit 29c6914b04
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 101 additions and 58 deletions

View file

@ -33,7 +33,7 @@ impl super::Routine for Create {
let data = data.clone();
tasks.spawn(async move {
let res: Vec<Record> = criterion::black_box(
let res: Option<Record> = criterion::black_box(
client
.create(table_name)
.content(data)
@ -41,12 +41,7 @@ impl super::Routine for Create {
.expect("[run] record creation failed"),
);
assert_eq!(
res.len(),
1,
"[run] expected record creation to return 1 record, got {}",
res.len()
);
res.expect("[run] record creation should return a result");
});
}

View file

@ -56,7 +56,7 @@ async fn main() -> surrealdb::Result<()> {
db.use_ns("namespace").use_db("database").await?;
// Create a dance class and store the result
let classes: Vec<DanceClass> = db
let classes: Option<DanceClass> = db
.create(DANCE)
.content(DanceClass {
id: Thing::from((DANCE, Id::rand())),

View file

@ -83,18 +83,68 @@ where
Client: Connection,
R: DeserializeOwned,
{
type Output = Result<Vec<R>>;
type Output = Result<Option<R>>;
type IntoFuture = BoxFuture<'r, Self::Output>;
into_future! {execute_vec}
into_future! {execute_opt}
}
impl<'r, C, R> Create<'r, C, R>
impl<'r, C> Create<'r, C, Value>
where
C: Connection,
{
/// Sets content of a record
pub fn content<D>(self, data: D) -> Content<'r, C, R>
pub fn content<D>(self, data: D) -> Content<'r, C, Value>
where
D: Serialize + 'static,
{
Content::from_closure(self.client, || {
let content = to_core_value(data)?;
let data = match content {
CoreValue::None | CoreValue::Null => None,
content => Some(content),
};
Ok(Command::Create {
what: self.resource?,
data,
})
})
}
}
impl<'r, C, R> Create<'r, C, Option<R>>
where
C: Connection,
{
/// Sets content of a record
pub fn content<D>(self, data: D) -> Content<'r, C, Option<R>>
where
D: Serialize + 'static,
{
Content::from_closure(self.client, || {
let content = to_core_value(data)?;
let data = match content {
CoreValue::None | CoreValue::Null => None,
content => Some(content),
};
Ok(Command::Create {
what: self.resource?,
data,
})
})
}
}
impl<'r, C, R> Create<'r, C, Vec<R>>
where
C: Connection,
{
/// Sets content of a record
pub fn content<D>(self, data: D) -> Content<'r, C, Option<R>>
where
D: Serialize + 'static,
{

View file

@ -733,7 +733,7 @@ where
/// db.use_ns("namespace").use_db("database").await?;
///
/// // Create a record with a random ID
/// let person: Vec<Person> = db.create("person").await?;
/// let person: Option<Person> = db.create("person").await?;
///
/// // Create a record with a specific ID
/// let record: Option<Person> = db.create(("person", "tobie"))

View file

@ -111,9 +111,9 @@ async fn api() {
.unwrap();
// create
let _: Vec<User> = DB.create(USER).await.unwrap();
let _: Option<User> = DB.create(USER).await.unwrap();
let _: Option<User> = DB.create((USER, "john")).await.unwrap();
let _: Vec<User> = DB.create(USER).content(User::default()).await.unwrap();
let _: Option<User> = DB.create(USER).content(User::default()).await.unwrap();
let _: Option<User> = DB.create((USER, "john")).content(User::default()).await.unwrap();
// select

View file

@ -10,7 +10,7 @@ async fn export_import() {
let db_name = Ulid::new().to_string();
db.use_ns(NS).use_db(&db_name).await.unwrap();
for i in 0..10 {
let _: Vec<ApiRecordId> = db
let _: Option<ApiRecordId> = db
.create("user")
.content(Record {
name: format!("User {i}"),

View file

@ -35,12 +35,12 @@ async fn live_select_table() {
let mut users = db.select(&table).live().await.unwrap();
// Create a record
let created: Vec<ApiRecordId> = db.create(table).await.unwrap();
let created: Option<ApiRecordId> = db.create(table).await.unwrap();
// Pull the notification
let notification: Notification<ApiRecordId> =
tokio::time::timeout(LQ_TIMEOUT, users.next()).await.unwrap().unwrap().unwrap();
// The returned record should match the created record
assert_eq!(created, vec![notification.data.clone()]);
assert_eq!(created, Some(notification.data.clone()));
// It should be newly created
assert_eq!(notification.action, Action::Create);
@ -291,7 +291,7 @@ async fn live_select_query() {
// Create a record
info!("Creating record");
let created: Vec<ApiRecordId> = db.create(table).await.unwrap();
let created: Option<ApiRecordId> = db.create(table).await.unwrap();
// Pull the notification
let notifications = receive_all_pending_notifications(users.clone(), LQ_TIMEOUT).await;
// It should be newly created
@ -302,7 +302,7 @@ async fn live_select_query() {
notifications
);
// The returned record should match the created record
assert_eq!(created, vec![notifications[0].data.clone()]);
assert_eq!(created, Some(notifications[0].data.clone()));
// Update the record
info!("Updating record");
@ -368,12 +368,12 @@ async fn live_select_query() {
.unwrap();
// Create a record
let created: Vec<ApiRecordId> = db.create(table).await.unwrap();
let created: Option<ApiRecordId> = db.create(table).await.unwrap();
// Pull the notification
let notification: Notification<ApiRecordId> =
tokio::time::timeout(LQ_TIMEOUT, users.next()).await.unwrap().unwrap().unwrap();
// The returned record should match the created record
assert_eq!(created, vec![notification.data.clone()]);
assert_eq!(created, Some(notification.data.clone()));
// It should be newly created
assert_eq!(notification.action, Action::Create, "{:?}", notification);

View file

@ -441,7 +441,7 @@ async fn create_record_no_id() {
let (permit, db) = new_db().await;
db.use_ns(NS).use_db(Ulid::new().to_string()).await.unwrap();
drop(permit);
let _: Vec<ApiRecordId> = db.create("user").await.unwrap();
let _: Option<ApiRecordId> = db.create("user").await.unwrap();
let _: Value = db.create(Resource::from("user")).await.unwrap();
}
@ -460,7 +460,7 @@ async fn create_record_no_id_with_content() {
let (permit, db) = new_db().await;
db.use_ns(NS).use_db(Ulid::new().to_string()).await.unwrap();
drop(permit);
let _: Vec<ApiRecordId> = db
let _: Option<ApiRecordId> = db
.create("user")
.content(Record {
name: "John Doe".to_owned(),
@ -599,8 +599,8 @@ async fn select_table() {
db.use_ns(NS).use_db(Ulid::new().to_string()).await.unwrap();
drop(permit);
let table = "user";
let _: Vec<ApiRecordId> = db.create(table).await.unwrap();
let _: Vec<ApiRecordId> = db.create(table).await.unwrap();
let _: Option<ApiRecordId> = db.create(table).await.unwrap();
let _: Option<ApiRecordId> = db.create(table).await.unwrap();
let _: Value = db.create(Resource::from(table)).await.unwrap();
let users: Vec<ApiRecordId> = db.select(table).await.unwrap();
assert_eq!(users.len(), 3);
@ -827,8 +827,8 @@ async fn update_table() {
db.use_ns(NS).use_db(Ulid::new().to_string()).await.unwrap();
drop(permit);
let table = "user";
let _: Vec<ApiRecordId> = db.create(table).await.unwrap();
let _: Vec<ApiRecordId> = db.create(table).await.unwrap();
let _: Option<ApiRecordId> = db.create(table).await.unwrap();
let _: Option<ApiRecordId> = db.create(table).await.unwrap();
let _: Value = db.update(Resource::from(table)).await.unwrap();
let users: Vec<ApiRecordId> = db.update(table).await.unwrap();
assert_eq!(users.len(), 2);
@ -1072,9 +1072,9 @@ async fn delete_table() {
db.use_ns(NS).use_db(Ulid::new().to_string()).await.unwrap();
drop(permit);
let table = "user";
let _: Vec<ApiRecordId> = db.create(table).await.unwrap();
let _: Vec<ApiRecordId> = db.create(table).await.unwrap();
let _: Vec<ApiRecordId> = db.create(table).await.unwrap();
let _: Option<ApiRecordId> = db.create(table).await.unwrap();
let _: Option<ApiRecordId> = db.create(table).await.unwrap();
let _: Option<ApiRecordId> = db.create(table).await.unwrap();
let users: Vec<ApiRecordId> = db.select(table).await.unwrap();
assert_eq!(users.len(), 3);
let users: Vec<ApiRecordId> = db.delete(table).await.unwrap();

View file

@ -922,39 +922,37 @@ async fn define_statement_index_concurrently_building_status() -> Result<(), Err
let mut r = ds.execute("INFO FOR INDEX test ON user", &session, None).await?;
let tmp = r.remove(0).result?;
if let Value::Object(o) = &tmp {
if let Some(b) = o.get("building") {
if let Value::Object(b) = b {
if let Some(v) = b.get("status") {
if Value::from("started").eq(v) {
continue;
if let Some(Value::Object(b)) = o.get("building") {
if let Some(v) = b.get("status") {
if Value::from("started").eq(v) {
continue;
}
let new_count = b.get("count").cloned();
if Value::from("initial").eq(v) {
if new_count != initial_count {
assert!(new_count > initial_count, "{new_count:?}");
info!("New initial count: {:?}", new_count);
initial_count = new_count;
}
let new_count = b.get("count").cloned();
if Value::from("initial").eq(v) {
if new_count != initial_count {
assert!(new_count > initial_count, "{new_count:?}");
info!("New initial count: {:?}", new_count);
initial_count = new_count;
}
continue;
continue;
}
if Value::from("updates").eq(v) {
if new_count != updates_count {
assert!(new_count > updates_count, "{new_count:?}");
info!("New updates count: {:?}", new_count);
updates_count = new_count;
}
if Value::from("updates").eq(v) {
if new_count != updates_count {
assert!(new_count > updates_count, "{new_count:?}");
info!("New updates count: {:?}", new_count);
updates_count = new_count;
}
continue;
}
let val = Value::parse(
"{
continue;
}
let val = Value::parse(
"{
building: {
status: 'built'
}
}",
);
assert_eq!(format!("{tmp:#}"), format!("{val:#}"));
break;
}
);
assert_eq!(format!("{tmp:#}"), format!("{val:#}"));
break;
}
}
}