#![allow(clippy::unwrap_used)]
use std::sync::Arc;
use crate::catalog::DatabaseDefinition;
use crate::catalog::providers::CatalogProvider;
use crate::dbs::{Capabilities, Session};
use crate::kvs::{Datastore, TransactionType};
use crate::val::TableName;
async fn new_ds() -> Arc<Datastore> {
Datastore::builder()
.with_capabilities(Capabilities::all())
.with_auth(false)
.build_with_path("memory")
.await
.unwrap()
}
async fn ensure_test_db(ds: &Datastore) -> Arc<DatabaseDefinition> {
let tx = ds.transaction(TransactionType::Write).await.unwrap();
let db = tx.ensure_ns_db(None, "test", "test").await.unwrap();
tx.commit().await.unwrap();
db
}
#[tokio::test]
async fn reference_targets_are_derived_from_the_stored_catalog() {
let ds = new_ds().await;
let db = ensure_test_db(&ds).await;
let ses = Session::owner().with_ns("test").with_db("test");
let mut res = ds
.execute(
"DEFINE FIELD author ON comment TYPE record<person> REFERENCE;
DEFINE FIELD title ON comment TYPE string;",
&ses,
None,
)
.await
.unwrap();
for r in res.drain(..) {
r.result.unwrap();
}
let tx = ds.transaction(TransactionType::Read).await.unwrap();
let (ns, db) = (db.namespace_id, db.database_id);
assert!(
tx.table_may_have_incoming_references(ns, db, &TableName::from("person")).await.unwrap(),
"`record<person> REFERENCE` can target `person`"
);
assert!(
!tx.table_may_have_incoming_references(ns, db, &TableName::from("comment")).await.unwrap(),
"no reference field can target `comment`"
);
tx.cancel().await.unwrap();
}
#[tokio::test]
async fn live_registered_mid_transaction_is_notified_by_a_later_write() {
let (send, recv) = crate::channel::bounded(100);
let ds = Datastore::builder()
.with_capabilities(Capabilities::all())
.with_auth(false)
.with_notify(send)
.build_with_path("memory")
.await
.unwrap();
ensure_test_db(&ds).await;
let ses = Session::owner().with_ns("test").with_db("test").with_rt(true);
ds.execute("DEFINE TABLE person", &ses, None).await.unwrap().remove(0).result.unwrap();
let mut res = ds
.execute(
"BEGIN; CREATE person:0; LIVE SELECT * FROM person; CREATE person:1; COMMIT;",
&ses,
None,
)
.await
.unwrap();
for r in res.drain(..) {
r.result.unwrap();
}
let notification = tokio::time::timeout(std::time::Duration::from_secs(5), recv.recv()).await;
let notification = notification.expect("the mid-transaction LIVE was not notified").unwrap();
assert_eq!(
notification.record,
crate::types::PublicValue::RecordId(crate::types::PublicRecordId {
table: "person".to_string().into(),
key: crate::types::PublicRecordIdKey::Number(1),
})
);
}