diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 57539d3b..56310b70 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -

  Contributing

+# Contributing We would    for you to contribute to SurrealDB and help make it better! We want contributing to SurrealDB to be fun, enjoyable, and educational for anyone and everyone. All contributions are welcome, including features, bugfixes, and documentation changes, as well as updates and tweaks, blog posts, workshops, and everything else. @@ -169,7 +169,7 @@ Pull requests are great, but there are many other areas where you can help. ### Blogging and speaking -Blogging, speaking about, or creating tutorials about one of SurrealDB's many features. Mention [@surrealdb](https://twitter.com/surrealdb) on Twitter, and email team@surrealdb.com so we can give pointers and tips and help you spread the word by promoting your content on the different SurrealDB communication channels. Please add your blog posts and videos of talks to our [showcase](https://github.com/surrealdb/showcase) repo on GitHub. +Blogging, speaking about, or creating tutorials about one of SurrealDB's many features. Mention [@surrealdb](https://twitter.com/surrealdb) on Twitter, and email community@surrealdb.com so we can give pointers and tips and help you spread the word by promoting your content on the different SurrealDB communication channels. Please add your blog posts and videos of talks to our [showcase](https://github.com/surrealdb/showcase) repo on GitHub. ### Presenting at meetups @@ -187,9 +187,11 @@ Submitting documentation updates, enhancements, designs, or bug fixes, and fixin Join our growing community around the world, for help, ideas, and discussions regarding SurrealDB. -- View our official [Blog](https://medium.com/surrealdb) +- View our official [Blog](https://surrealdb.com/blog) - Follow us on [Twitter](https://twitter.com/surrealdb) - Connect with us on [LinkedIn](https://www.linkedin.com/company/surrealdb/) - Join our [Dev community](https://dev.to/surrealdb) - Chat live with us on [Discord](https://discord.gg/surrealdb) +- Get involved on [Reddit](http://reddit.com/r/surrealdb/) +- Read our blog posts on [Medium](https://medium.com/surrealdb) - Questions tagged #surrealdb on [StackOverflow](https://stackoverflow.com/questions/tagged/surrealdb) diff --git a/doc/DRIVERS.md b/doc/DRIVERS.md index 18365ab1..4a512872 100644 --- a/doc/DRIVERS.md +++ b/doc/DRIVERS.md @@ -28,7 +28,7 @@ We absolutely agree! We intend to have a uniform, long-term approach with regard ### We need ORM support -We absolutely agree! We don’t currently have ORM support in the drivers themselves, and aren’t likely to implemented this, as there are many ORM libraries and integrations with which to integrate. We are, however, very excited to discover what the community creates. We encourage both newcomers and existing members to explore various projects that address their needs - these can be found in the [awesome-surreal](https://github.com/surrealdb/awesome-surreal) repository. To add more projects to the list, simply open a pull-request! +We absolutely agree! We don’t currently have ORM support in the drivers themselves, and aren’t likely to implement this, as there are many ORM libraries and integrations with which to integrate. We are, however, very excited to discover what the community creates. We encourage both newcomers and existing members to explore various projects that address their needs - these can be found in the [awesome-surreal](https://github.com/surrealdb/awesome-surreal) repository. To add more projects to the list, simply open a pull-request! ### Do you support language X? diff --git a/lib/src/cf/writer.rs b/lib/src/cf/writer.rs index 6aebb76c..d3e2dd8c 100644 --- a/lib/src/cf/writer.rs +++ b/lib/src/cf/writer.rs @@ -1,6 +1,5 @@ use crate::cf::{TableMutation, TableMutations}; use crate::kvs::Key; -use crate::sql::ident::Ident; use crate::sql::thing::Thing; use crate::sql::value::Value; use std::borrow::Cow; @@ -59,16 +58,16 @@ impl Writer { } } - pub(crate) fn update(&mut self, ns: &str, db: &str, tb: Ident, id: Thing, v: Cow<'_, Value>) { + pub(crate) fn update(&mut self, ns: &str, db: &str, tb: &str, id: Thing, v: Cow<'_, Value>) { if v.is_some() { self.buf.push( ns.to_string(), db.to_string(), - tb.0, + tb.to_string(), TableMutation::Set(id, v.into_owned()), ); } else { - self.buf.push(ns.to_string(), db.to_string(), tb.0, TableMutation::Del(id)); + self.buf.push(ns.to_string(), db.to_string(), tb.to_string(), TableMutation::Del(id)); } } @@ -118,16 +117,16 @@ mod tests { let ts = crate::sql::Datetime::default(); let ns = "myns"; let db = "mydb"; - let tb = super::Ident("mytb".to_string()); + let tb = "mytb"; let mut dns = DefineNamespaceStatement::default(); - dns.name = super::Ident(ns.to_string()); + dns.name = crate::sql::Ident(ns.to_string()); let mut ddb = DefineDatabaseStatement::default(); - ddb.name = super::Ident(db.to_string()); + ddb.name = crate::sql::Ident(db.to_string()); ddb.changefeed = Some(ChangeFeed { expiry: Duration::from_secs(10), }); let mut dtb = DefineTableStatement::default(); - dtb.name = tb.clone(); + dtb.name = tb.into(); dtb.changefeed = Some(ChangeFeed { expiry: Duration::from_secs(10), }); @@ -156,38 +155,38 @@ mod tests { let mut tx1 = ds.transaction(true, false).await.unwrap(); let thing_a = Thing { - tb: tb.clone().0, + tb: tb.to_owned(), id: Id::String("A".to_string()), }; let value_a: super::Value = "a".into(); - tx1.record_change(ns, db, &dtb, &thing_a, Cow::Borrowed(&value_a)); + tx1.record_change(ns, db, tb, &thing_a, Cow::Borrowed(&value_a)); tx1.complete_changes(true).await.unwrap(); let _r1 = tx1.commit().await.unwrap(); let mut tx2 = ds.transaction(true, false).await.unwrap(); let thing_c = Thing { - tb: tb.clone().0, + tb: tb.to_owned(), id: Id::String("C".to_string()), }; let value_c: Value = "c".into(); - tx2.record_change(ns, db, &dtb, &thing_c, Cow::Borrowed(&value_c)); + tx2.record_change(ns, db, tb, &thing_c, Cow::Borrowed(&value_c)); tx2.complete_changes(true).await.unwrap(); let _r2 = tx2.commit().await.unwrap(); let x = ds.transaction(true, false).await; let mut tx3 = x.unwrap(); let thing_b = Thing { - tb: tb.clone().0, + tb: tb.to_owned(), id: Id::String("B".to_string()), }; let value_b: Value = "b".into(); - tx3.record_change(ns, db, &dtb, &thing_b, Cow::Borrowed(&value_b)); + tx3.record_change(ns, db, tb, &thing_b, Cow::Borrowed(&value_b)); let thing_c2 = Thing { - tb: tb.clone().0, + tb: tb.to_owned(), id: Id::String("C".to_string()), }; let value_c2: Value = "c2".into(); - tx3.record_change(ns, db, &dtb, &thing_c2, Cow::Borrowed(&value_c2)); + tx3.record_change(ns, db, tb, &thing_c2, Cow::Borrowed(&value_c2)); tx3.complete_changes(true).await.unwrap(); tx3.commit().await.unwrap(); @@ -199,16 +198,10 @@ mod tests { let mut tx4 = ds.transaction(true, false).await.unwrap(); let tb = tb.clone(); - let r = crate::cf::read( - &mut tx4, - ns, - db, - Some(tb.0.as_ref()), - ShowSince::Versionstamp(start), - Some(10), - ) - .await - .unwrap(); + let r = + crate::cf::read(&mut tx4, ns, db, Some(tb), ShowSince::Versionstamp(start), Some(10)) + .await + .unwrap(); tx4.commit().await.unwrap(); let mut want: Vec = Vec::new(); @@ -260,16 +253,10 @@ mod tests { // Now we should see the gc_all results let mut tx6 = ds.transaction(true, false).await.unwrap(); let tb = tb.clone(); - let r = crate::cf::read( - &mut tx6, - ns, - db, - Some(tb.0.as_ref()), - ShowSince::Versionstamp(start), - Some(10), - ) - .await - .unwrap(); + let r = + crate::cf::read(&mut tx6, ns, db, Some(tb), ShowSince::Versionstamp(start), Some(10)) + .await + .unwrap(); tx6.commit().await.unwrap(); let mut want: Vec = Vec::new(); @@ -295,16 +282,9 @@ mod tests { ds.tick_at((ts.0.timestamp() + 5).try_into().unwrap()).await.unwrap(); let mut tx7 = ds.transaction(true, false).await.unwrap(); - let r = crate::cf::read( - &mut tx7, - ns, - db, - Some(tb.0.as_ref()), - ShowSince::Timestamp(ts), - Some(10), - ) - .await - .unwrap(); + let r = crate::cf::read(&mut tx7, ns, db, Some(tb), ShowSince::Timestamp(ts), Some(10)) + .await + .unwrap(); tx7.commit().await.unwrap(); assert_eq!(r, want); } diff --git a/lib/src/dbs/executor.rs b/lib/src/dbs/executor.rs index 736f6923..fd76b3a3 100644 --- a/lib/src/dbs/executor.rs +++ b/lib/src/dbs/executor.rs @@ -61,10 +61,7 @@ impl<'a> Executor<'a> { } /// Commits the transaction if it is local. - /// This function takes two additional parameters that are not present in the underlying kvs::Transaction::commit() function: - /// ns: The namespace of the transaction - /// db: The database of the transaction - /// These parameters are used updating the changefeed. + /// /// # Return /// /// An `Err` if the transaction could not be commited; diff --git a/lib/src/dbs/options.rs b/lib/src/dbs/options.rs index b27607c9..733be207 100644 --- a/lib/src/dbs/options.rs +++ b/lib/src/dbs/options.rs @@ -6,6 +6,7 @@ use crate::iam::{Action, Auth, ResourceKind, Role}; use crate::sql::Base; use channel::Sender; use std::sync::Arc; +use uuid::Uuid; /// An Options is passed around when processing a set of query /// statements. An Options contains specific information for how @@ -16,7 +17,7 @@ use std::sync::Arc; #[derive(Clone, Debug)] pub struct Options { /// Current Node ID - id: Option, + id: Option, /// Currently selected NS ns: Option>, /// Currently selected DB @@ -119,7 +120,7 @@ impl Options { /// Set the Node ID for subsequent code which uses /// this `Options`, with support for chaining. - pub fn with_id(mut self, id: uuid::Uuid) -> Self { + pub fn with_id(mut self, id: Uuid) -> Self { self.id = Some(id); self } @@ -407,7 +408,7 @@ impl Options { // -------------------------------------------------- /// Get current Node ID - pub fn id(&self) -> Result { + pub fn id(&self) -> Result { self.id.ok_or(Error::Unreachable) } diff --git a/lib/src/doc/changefeeds.rs b/lib/src/doc/changefeeds.rs index ea44e44a..8f645ed4 100644 --- a/lib/src/doc/changefeeds.rs +++ b/lib/src/doc/changefeeds.rs @@ -13,24 +13,25 @@ impl<'a> Document<'a> { txn: &Transaction, _stm: &Statement<'_>, ) -> Result<(), Error> { - // Check if forced - if !opt.force && !self.changed() { + // Check if changed + if !self.changed() { return Ok(()); } - // Get the record id - let _ = self.id.as_ref().unwrap(); - let ns = opt.ns(); - let db = opt.db(); + // Get the table for the record let tb = self.tb(opt, txn).await?; - let tb = tb.as_ref(); + // Check if changefeeds are enabled if tb.changefeed.is_some() { // Clone transaction - let txn = txn.clone(); - let mut txn = txn.lock().await; - - let id = &(*self.id.as_ref().unwrap()).clone(); + let run = txn.clone(); + // Claim transaction + let mut run = run.lock().await; + // Get the arguments + let ns = opt.ns(); + let db = opt.db(); + let tb = tb.name.as_str(); + let id = self.id.as_ref().unwrap(); // Create the changefeed entry - txn.record_change(ns, db, tb, id, self.current.doc.clone()); + run.record_change(ns, db, tb, id, self.current.doc.clone()); } // Carry on Ok(()) diff --git a/lib/src/doc/document.rs b/lib/src/doc/document.rs index dff2974c..19602e91 100644 --- a/lib/src/doc/document.rs +++ b/lib/src/doc/document.rs @@ -150,7 +150,7 @@ impl<'a> Document<'a> { // Get the record id let id = self.id.as_ref().unwrap(); // Get the table definitions - txn.clone().lock().await.all_ft(opt.ns(), opt.db(), &id.tb).await + txn.clone().lock().await.all_tb_views(opt.ns(), opt.db(), &id.tb).await } /// Get the events for this document pub async fn ev( @@ -161,7 +161,7 @@ impl<'a> Document<'a> { // Get the record id let id = self.id.as_ref().unwrap(); // Get the event definitions - txn.clone().lock().await.all_ev(opt.ns(), opt.db(), &id.tb).await + txn.clone().lock().await.all_tb_events(opt.ns(), opt.db(), &id.tb).await } /// Get the fields for this document pub async fn fd( @@ -172,7 +172,7 @@ impl<'a> Document<'a> { // Get the record id let id = self.id.as_ref().unwrap(); // Get the field definitions - txn.clone().lock().await.all_fd(opt.ns(), opt.db(), &id.tb).await + txn.clone().lock().await.all_tb_fields(opt.ns(), opt.db(), &id.tb).await } /// Get the indexes for this document pub async fn ix( @@ -183,7 +183,7 @@ impl<'a> Document<'a> { // Get the record id let id = self.id.as_ref().unwrap(); // Get the index definitions - txn.clone().lock().await.all_ix(opt.ns(), opt.db(), &id.tb).await + txn.clone().lock().await.all_tb_indexes(opt.ns(), opt.db(), &id.tb).await } // Get the lives for this document pub async fn lv( @@ -194,6 +194,6 @@ impl<'a> Document<'a> { // Get the record id let id = self.id.as_ref().unwrap(); // Get the table definition - txn.clone().lock().await.all_lv(opt.ns(), opt.db(), &id.tb).await + txn.clone().lock().await.all_tb_lives(opt.ns(), opt.db(), &id.tb).await } } diff --git a/lib/src/doc/field.rs b/lib/src/doc/field.rs index 5b01cb96..c8a95d32 100644 --- a/lib/src/doc/field.rs +++ b/lib/src/doc/field.rs @@ -125,8 +125,18 @@ impl<'a> Document<'a> { }; // Match the permission clause match perms { + // The field PERMISSIONS clause + // is FULL, enabling this field + // to be updated without checks. Permission::Full => (), + // The field PERMISSIONS clause + // is NONE, meaning that this + // change will be reverted. Permission::None => val = old, + // The field PERMISSIONS clause + // is a custom expression, so + // we check the expression and + // revert the field if denied. Permission::Specific(e) => { // Disable permissions let opt = &opt.new_with_perms(false); diff --git a/lib/src/doc/index.rs b/lib/src/doc/index.rs index 72eb5e06..63270d52 100644 --- a/lib/src/doc/index.rs +++ b/lib/src/doc/index.rs @@ -337,7 +337,7 @@ impl<'a> IndexOperation<'a> { p: &SearchParams, ) -> Result<(), Error> { let ikb = IndexKeyBase::new(self.opt, self.ix); - let az = run.get_az(self.opt.ns(), self.opt.db(), p.az.as_str()).await?; + let az = run.get_db_analyzer(self.opt.ns(), self.opt.db(), p.az.as_str()).await?; let mut ft = FtIndex::new(run, az, ikb, p, TreeStoreType::Write).await?; if let Some(n) = &self.n { ft.index_document(run, self.rid, n).await?; diff --git a/lib/src/fnc/script/into.rs b/lib/src/fnc/script/into.rs index 495df24f..291db789 100644 --- a/lib/src/fnc/script/into.rs +++ b/lib/src/fnc/script/into.rs @@ -1,5 +1,4 @@ use super::classes; -use crate::sql::number::decimal_is_integer; use crate::sql::number::Number; use crate::sql::value::Value; use js::Array; @@ -26,7 +25,7 @@ impl<'js> IntoJs<'js> for &Value { Value::Strand(v) => js::String::from_str(ctx.clone(), v)?.into_js(ctx), Value::Number(Number::Int(v)) => Ok(js::Value::new_int(ctx.clone(), *v as i32)), Value::Number(Number::Float(v)) => Ok(js::Value::new_float(ctx.clone(), *v)), - &Value::Number(Number::Decimal(v)) => match decimal_is_integer(&v) { + &Value::Number(Number::Decimal(v)) => match v.is_integer() { true => Ok(js::Value::new_int(ctx.clone(), v.try_into().unwrap_or_default())), false => Ok(js::Value::new_float(ctx.clone(), v.try_into().unwrap_or_default())), }, diff --git a/lib/src/iam/verify.rs b/lib/src/iam/verify.rs index 207b48c4..0cfa1505 100644 --- a/lib/src/iam/verify.rs +++ b/lib/src/iam/verify.rs @@ -159,7 +159,7 @@ pub async fn token(kvs: &Datastore, session: &mut Session, token: &str) -> Resul None => Value::None, }; // Get the scope token - let de = tx.get_st(&ns, &db, &sc, &tk).await?; + let de = tx.get_sc_token(&ns, &db, &sc, &tk).await?; let cf = config(de.kind, de.code)?; // Verify the token decode::(token, &cf.0, &cf.1)?; @@ -224,7 +224,7 @@ pub async fn token(kvs: &Datastore, session: &mut Session, token: &str) -> Resul // Create a new readonly transaction let mut tx = kvs.transaction(false, false).await?; // Get the database token - let de = tx.get_dt(&ns, &db, &tk).await?; + let de = tx.get_db_token(&ns, &db, &tk).await?; let cf = config(de.kind, de.code)?; // Verify the token decode::(token, &cf.0, &cf.1)?; @@ -293,7 +293,7 @@ pub async fn token(kvs: &Datastore, session: &mut Session, token: &str) -> Resul // Create a new readonly transaction let mut tx = kvs.transaction(false, false).await?; // Get the namespace token - let de = tx.get_nt(&ns, &tk).await?; + let de = tx.get_ns_token(&ns, &tk).await?; let cf = config(de.kind, de.code)?; // Verify the token decode::(token, &cf.0, &cf.1)?; diff --git a/lib/src/idx/planner/executor.rs b/lib/src/idx/planner/executor.rs index 3c959aa1..4db95fa3 100644 --- a/lib/src/idx/planner/executor.rs +++ b/lib/src/idx/planner/executor.rs @@ -55,7 +55,7 @@ impl QueryExecutor { } } else { let ikb = IndexKeyBase::new(opt, io.ix()); - let az = run.get_az(opt.ns(), opt.db(), p.az.as_str()).await?; + let az = run.get_db_analyzer(opt.ns(), opt.db(), p.az.as_str()).await?; let ft = FtIndex::new(&mut run, az, ikb, p, TreeStoreType::Read).await?; let ixn = ixn.to_owned(); if entry.is_none() { diff --git a/lib/src/idx/planner/tree.rs b/lib/src/idx/planner/tree.rs index a72203ad..b0b27230 100644 --- a/lib/src/idx/planner/tree.rs +++ b/lib/src/idx/planner/tree.rs @@ -54,7 +54,7 @@ impl<'a> TreeBuilder<'a> { .clone() .lock() .await - .all_ix(self.opt.ns(), self.opt.db(), &self.table.0) + .all_tb_indexes(self.opt.ns(), self.opt.db(), &self.table.0) .await?; self.indexes = Some(indexes); } diff --git a/lib/src/kvs/cache.rs b/lib/src/kvs/cache.rs index b9f4f699..0e9f5e73 100644 --- a/lib/src/kvs/cache.rs +++ b/lib/src/kvs/cache.rs @@ -20,7 +20,10 @@ use std::sync::Arc; pub enum Entry { // Single definitions Db(Arc), + Fc(Arc), + Ix(Arc), Ns(Arc), + Pa(Arc), Tb(Arc), // Multi definitions Azs(Arc<[DefineAnalyzerStatement]>), @@ -38,9 +41,10 @@ pub enum Entry { Nus(Arc<[DefineUserStatement]>), Pas(Arc<[DefineParamStatement]>), Scs(Arc<[DefineScopeStatement]>), - Seq(U32), Sts(Arc<[DefineTokenStatement]>), Tbs(Arc<[DefineTableStatement]>), + // Sequences + Seq(U32), } #[derive(Default)] diff --git a/lib/src/kvs/ds.rs b/lib/src/kvs/ds.rs index bbd63233..fd7ee963 100644 --- a/lib/src/kvs/ds.rs +++ b/lib/src/kvs/ds.rs @@ -311,7 +311,7 @@ impl Datastore { let stm = DefineUserStatement::from((Base::Root, creds.username, creds.password)); let ctx = Context::default(); let opt = Options::new().with_auth(Arc::new(Auth::for_root(Role::Owner))); - let _result = stm.compute(&ctx, &opt, &txn, None).await?; + let _ = stm.compute(&ctx, &opt, &txn, None).await?; txn.lock().await.commit().await?; Ok(()) } @@ -541,7 +541,8 @@ impl Datastore { trace!("Archiving lqs and found {} LQ entries for {}", lqs.len(), nd); let mut ret = vec![]; for lq in lqs { - let lvs = tx.get_lv(lq.ns.as_str(), lq.db.as_str(), lq.tb.as_str(), &lq.lq).await?; + let lvs = + tx.get_tb_live(lq.ns.as_str(), lq.db.as_str(), lq.tb.as_str(), &lq.lq).await?; let archived_lvs = lvs.clone().archive(this_node_id.clone()); tx.putc_tblq(&lq.ns, &lq.db, &lq.tb, archived_lvs, Some(lvs)).await?; ret.push(lq); diff --git a/lib/src/kvs/tests/cluster_init.rs b/lib/src/kvs/tests/cluster_init.rs index 833d68eb..d5904e13 100644 --- a/lib/src/kvs/tests/cluster_init.rs +++ b/lib/src/kvs/tests/cluster_init.rs @@ -104,8 +104,10 @@ async fn expired_nodes_get_live_queries_archived() { // Now validate lq was removed let mut tx = test.db.transaction(true, false).await.unwrap(); - let scanned = - tx.all_lv(ses.ns().unwrap().as_ref(), ses.db().unwrap().as_ref(), table).await.unwrap(); + let scanned = tx + .all_tb_lives(ses.ns().unwrap().as_ref(), ses.db().unwrap().as_ref(), table) + .await + .unwrap(); assert_eq!(scanned.len(), 0); tx.commit().await.unwrap(); } @@ -180,7 +182,7 @@ async fn single_live_queries_are_garbage_collected() { // Validate trace!("Validating live queries"); let mut tx = test.db.transaction(true, false).await.unwrap(); - let scanned = tx.all_lv(namespace, database, table).await.unwrap(); + let scanned = tx.all_tb_lives(namespace, database, table).await.unwrap(); assert_eq!(scanned.len(), 1, "The scanned values are {:?}", scanned); assert_eq!(&scanned[0].id.0, &live_query_to_keep); let scanned = tx.all_lq(&node_id).await.unwrap(); diff --git a/lib/src/kvs/tests/nq.rs b/lib/src/kvs/tests/nq.rs index 34adc252..944d62f3 100644 --- a/lib/src/kvs/tests/nq.rs +++ b/lib/src/kvs/tests/nq.rs @@ -46,7 +46,7 @@ async fn archive_lv_for_node_archives() { tx.commit().await.unwrap(); let mut tx = test.db.transaction(true, false).await.unwrap(); - let lv = tx.all_lv(namespace, database, table).await.unwrap(); + let lv = tx.all_tb_lives(namespace, database, table).await.unwrap(); assert_eq!(lv.len(), 1, "{:?}", lv); assert_eq!(lv[0].archived, Some(this_node_id)); tx.commit().await.unwrap(); diff --git a/lib/src/kvs/tx.rs b/lib/src/kvs/tx.rs index 7856a075..863b3ea2 100644 --- a/lib/src/kvs/tx.rs +++ b/lib/src/kvs/tx.rs @@ -617,12 +617,7 @@ impl Transaction { K: Into + Debug + Clone, { #[cfg(debug_assertions)] - trace!( - "Scan {:?} - {:?}", - crate::key::debug::sprint_key(&(rng.start).clone().into()), - crate::key::debug::sprint_key(&(rng.end).clone().into()), - // rng.start, rng.end); - ); + trace!("Scan {:?} - {:?}", rng.start, rng.end); match self { #[cfg(feature = "kv-mem")] Transaction { @@ -758,16 +753,12 @@ impl Transaction { /// This function fetches key-value pairs from the underlying datastore in batches of 1000. pub async fn getr(&mut self, rng: Range, limit: u32) -> Result, Error> where - K: Into + Debug + Clone, + K: Into + Debug, { + #[cfg(debug_assertions)] + trace!("Getr {:?}..{:?} (limit: {limit})", rng.start, rng.end); let beg: Key = rng.start.into(); let end: Key = rng.end.into(); - trace!( - "Getr {:?}..{:?} (limit: {})", - crate::key::debug::sprint_key(&beg), - crate::key::debug::sprint_key(&end), - limit - ); let mut nxt: Option = None; let mut num = limit; let mut out: Vec<(Key, Val)> = vec![]; @@ -815,8 +806,10 @@ impl Transaction { /// This function fetches key-value pairs from the underlying datastore in batches of 1000. pub async fn delr(&mut self, rng: Range, limit: u32) -> Result<(), Error> where - K: Into, + K: Into + Debug, { + #[cfg(debug_assertions)] + trace!("Delr {:?}..{:?} (limit: {limit})", rng.start, rng.end); let beg: Key = rng.start.into(); let end: Key = rng.end.into(); let mut nxt: Option = None; @@ -864,8 +857,10 @@ impl Transaction { /// This function fetches key-value pairs from the underlying datastore in batches of 1000. pub async fn getp(&mut self, key: K, limit: u32) -> Result, Error> where - K: Into, + K: Into + Debug, { + #[cfg(debug_assertions)] + trace!("Getp {:?} (limit: {limit})", key); let beg: Key = key.into(); let end: Key = beg.clone().add(0xff); let mut nxt: Option = None; @@ -914,8 +909,10 @@ impl Transaction { /// This function fetches key-value pairs from the underlying datastore in batches of 1000. pub async fn delp(&mut self, key: K, limit: u32) -> Result<(), Error> where - K: Into, + K: Into + Debug, { + #[cfg(debug_assertions)] + trace!("Delp {:?} (limit: {limit})", key); let beg: Key = key.into(); let end: Key = beg.clone().add(0xff); let mut nxt: Option = None; @@ -1180,11 +1177,11 @@ impl Transaction { let tb: String = String::from_utf8(value).unwrap(); trace!("scan_lq Found tb: {:?}", tb); res.push(LqValue { - nd: crate::sql::uuid::Uuid::from(lq.nd), + nd: lq.nd.into(), ns: lq.ns.to_string(), db: lq.db.to_string(), tb, - lq: crate::sql::uuid::Uuid::from(lq.lq), + lq: lq.lq.into(), }); } Ok(res) @@ -1236,6 +1233,15 @@ impl Transaction { self.putc(key_enc, live_stm, expected).await } + /// Retrieve all ROOT users. + pub async fn all_root_users(&mut self) -> Result, Error> { + let beg = crate::key::root::us::prefix(); + let end = crate::key::root::us::suffix(); + let val = self.getr(beg..end, u32::MAX).await?; + let val = val.convert().into(); + Ok(val) + } + /// Retrieve all namespace definitions in a datastore. pub async fn all_ns(&mut self) -> Result, Error> { let key = crate::key::root::ns::prefix(); @@ -1275,7 +1281,7 @@ impl Transaction { } /// Retrieve all namespace token definitions for a specific namespace. - pub async fn all_nt(&mut self, ns: &str) -> Result, Error> { + pub async fn all_ns_tokens(&mut self, ns: &str) -> Result, Error> { let key = crate::key::namespace::tk::prefix(ns); Ok(if let Some(e) = self.cache.get(&key) { if let Entry::Nts(v) = e { @@ -1336,7 +1342,7 @@ impl Transaction { } /// Retrieve all database token definitions for a specific database. - pub async fn all_dt( + pub async fn all_db_tokens( &mut self, ns: &str, db: &str, @@ -1358,8 +1364,31 @@ impl Transaction { }) } + /// Retrieve all analyzer definitions for a specific database. + pub async fn all_db_analyzers( + &mut self, + ns: &str, + db: &str, + ) -> Result, Error> { + let key = crate::key::database::az::prefix(ns, db); + Ok(if let Some(e) = self.cache.get(&key) { + if let Entry::Azs(v) = e { + v + } else { + unreachable!(); + } + } else { + let beg = crate::key::database::az::prefix(ns, db); + let end = crate::key::database::az::suffix(ns, db); + let val = self.getr(beg..end, u32::MAX).await?; + let val = val.convert().into(); + self.cache.set(key, Entry::Azs(Arc::clone(&val))); + val + }) + } + /// Retrieve all function definitions for a specific database. - pub async fn all_fc( + pub async fn all_db_functions( &mut self, ns: &str, db: &str, @@ -1381,6 +1410,29 @@ impl Transaction { }) } + /// Retrieve all param definitions for a specific database. + pub async fn all_db_params( + &mut self, + ns: &str, + db: &str, + ) -> Result, Error> { + let key = crate::key::database::pa::prefix(ns, db); + Ok(if let Some(e) = self.cache.get(&key) { + if let Entry::Pas(v) = e { + v + } else { + unreachable!(); + } + } else { + let beg = crate::key::database::pa::prefix(ns, db); + let end = crate::key::database::pa::suffix(ns, db); + let val = self.getr(beg..end, u32::MAX).await?; + let val = val.convert().into(); + self.cache.set(key, Entry::Pas(Arc::clone(&val))); + val + }) + } + /// Retrieve all scope definitions for a specific database. pub async fn all_sc( &mut self, @@ -1405,7 +1457,7 @@ impl Transaction { } /// Retrieve all scope token definitions for a scope. - pub async fn all_st( + pub async fn all_sc_tokens( &mut self, ns: &str, db: &str, @@ -1428,29 +1480,6 @@ impl Transaction { }) } - /// Retrieve all param definitions for a specific database. - pub async fn all_pa( - &mut self, - ns: &str, - db: &str, - ) -> Result, Error> { - let key = crate::key::database::pa::prefix(ns, db); - Ok(if let Some(e) = self.cache.get(&key) { - if let Entry::Pas(v) = e { - v - } else { - unreachable!(); - } - } else { - let beg = crate::key::database::pa::prefix(ns, db); - let end = crate::key::database::pa::suffix(ns, db); - let val = self.getr(beg..end, u32::MAX).await?; - let val = val.convert().into(); - self.cache.set(key, Entry::Pas(Arc::clone(&val))); - val - }) - } - /// Retrieve all table definitions for a specific database. pub async fn all_tb( &mut self, @@ -1475,7 +1504,7 @@ impl Transaction { } /// Retrieve all event definitions for a specific table. - pub async fn all_ev( + pub async fn all_tb_events( &mut self, ns: &str, db: &str, @@ -1499,7 +1528,7 @@ impl Transaction { } /// Retrieve all field definitions for a specific table. - pub async fn all_fd( + pub async fn all_tb_fields( &mut self, ns: &str, db: &str, @@ -1523,7 +1552,7 @@ impl Transaction { } /// Retrieve all index definitions for a specific table. - pub async fn all_ix( + pub async fn all_tb_indexes( &mut self, ns: &str, db: &str, @@ -1547,7 +1576,7 @@ impl Transaction { } /// Retrieve all view definitions for a specific table. - pub async fn all_ft( + pub async fn all_tb_views( &mut self, ns: &str, db: &str, @@ -1571,7 +1600,7 @@ impl Transaction { } /// Retrieve all live definitions for a specific table. - pub async fn all_lv( + pub async fn all_tb_lives( &mut self, ns: &str, db: &str, @@ -1606,48 +1635,24 @@ impl Transaction { Error::Internal(format!("Failed to decode a value while reading LQ: {}", e)) })?; let lqv = LqValue { - nd: crate::sql::uuid::Uuid::from(*nd), + nd: (*nd).into(), ns: lq_key.ns.to_string(), db: lq_key.db.to_string(), tb: lq_value, - lq: crate::sql::uuid::Uuid::from(lq_key.lq), + lq: lq_key.lq.into(), }; lqs.push(lqv); } Ok(lqs) } - /// Retrieve all analyzer definitions for a specific database. - pub async fn all_az( - &mut self, - ns: &str, - db: &str, - ) -> Result, Error> { - let key = crate::key::database::az::prefix(ns, db); - Ok(if let Some(e) = self.cache.get(&key) { - if let Entry::Azs(v) = e { - v - } else { - unreachable!(); - } - } else { - let beg = crate::key::database::az::prefix(ns, db); - let end = crate::key::database::az::suffix(ns, db); - let val = self.getr(beg..end, u32::MAX).await?; - let val = val.convert().into(); - self.cache.set(key, Entry::Azs(Arc::clone(&val))); - val - }) - } - - /// Retrieve all ROOT users. - pub async fn all_root_users(&mut self) -> Result, Error> { - let beg = crate::key::root::us::prefix(); - let end = crate::key::root::us::suffix(); - - let val = self.getr(beg..end, u32::MAX).await?; - let val = val.convert().into(); - Ok(val) + /// Retrieve a specific user definition from ROOT. + pub async fn get_root_user(&mut self, user: &str) -> Result { + let key = crate::key::root::us::new(user); + let val = self.get(key).await?.ok_or(Error::UserRootNotFound { + value: user.to_owned(), + })?; + Ok(val.into()) } /// Retrieve a specific namespace definition. @@ -1659,8 +1664,26 @@ impl Transaction { Ok(val.into()) } + /// Retrieve a specific user definition from a namespace. + pub async fn get_ns_user( + &mut self, + ns: &str, + user: &str, + ) -> Result { + let key = crate::key::namespace::us::new(ns, user); + let val = self.get(key).await?.ok_or(Error::UserNsNotFound { + value: user.to_owned(), + ns: ns.to_owned(), + })?; + Ok(val.into()) + } + /// Retrieve a specific namespace token definition. - pub async fn get_nt(&mut self, ns: &str, nt: &str) -> Result { + pub async fn get_ns_token( + &mut self, + ns: &str, + nt: &str, + ) -> Result { let key = crate::key::namespace::tk::new(ns, nt); let val = self.get(key).await?.ok_or(Error::NtNotFound { value: nt.to_owned(), @@ -1677,8 +1700,24 @@ impl Transaction { Ok(val.into()) } + /// Retrieve a specific user definition from a database. + pub async fn get_db_user( + &mut self, + ns: &str, + db: &str, + user: &str, + ) -> Result { + let key = crate::key::database::us::new(ns, db, user); + let val = self.get(key).await?.ok_or(Error::UserDbNotFound { + value: user.to_owned(), + ns: ns.to_owned(), + db: db.to_owned(), + })?; + Ok(val.into()) + } + /// Retrieve a specific database token definition. - pub async fn get_dt( + pub async fn get_db_token( &mut self, ns: &str, db: &str, @@ -1691,6 +1730,20 @@ impl Transaction { Ok(val.into()) } + /// Retrieve a specific analyzer definition. + pub async fn get_db_analyzer( + &mut self, + ns: &str, + db: &str, + az: &str, + ) -> Result { + let key = crate::key::database::az::new(ns, db, az); + let val = self.get(key).await?.ok_or(Error::AzNotFound { + value: az.to_owned(), + })?; + Ok(val.into()) + } + /// Retrieve a specific scope definition. pub async fn get_sc( &mut self, @@ -1706,7 +1759,7 @@ impl Transaction { } /// Retrieve a specific scope token definition. - pub async fn get_st( + pub async fn get_sc_token( &mut self, ns: &str, db: &str, @@ -1720,20 +1773,6 @@ impl Transaction { Ok(val.into()) } - /// Retrieve a specific function definition. - pub async fn get_fc( - &mut self, - ns: &str, - db: &str, - fc: &str, - ) -> Result { - let key = crate::key::database::fc::new(ns, db, fc); - let val = self.get(key).await?.ok_or(Error::FcNotFound { - value: fc.to_owned(), - })?; - Ok(val.into()) - } - /// Return the table stored at the lq address pub async fn get_lq( &mut self, @@ -1749,36 +1788,6 @@ impl Transaction { Value::from(val).convert_to_strand() } - pub async fn get_lv( - &mut self, - ns: &str, - db: &str, - tb: &str, - lv: &Uuid, - ) -> Result { - let key = crate::key::table::lq::new(ns, db, tb, *lv); - let key_enc = crate::key::table::lq::Lq::encode(&key)?; - trace!("Getting lv ({:?}) {:?}", lv, crate::key::debug::sprint_key(&key_enc)); - let val = self.get(key_enc).await?.ok_or(Error::LvNotFound { - value: lv.to_string(), - })?; - Ok(val.into()) - } - - /// Retrieve a specific param definition. - pub async fn get_pa( - &mut self, - ns: &str, - db: &str, - pa: &str, - ) -> Result { - let key = crate::key::database::pa::new(ns, db, pa); - let val = self.get(key).await?.ok_or(Error::PaNotFound { - value: pa.to_owned(), - })?; - Ok(val.into()) - } - /// Retrieve a specific table definition. pub async fn get_tb( &mut self, @@ -1792,69 +1801,20 @@ impl Transaction { })?; Ok(val.into()) } - /// Retrieve a specific analyzer definition. - pub async fn get_az( - &mut self, - ns: &str, - db: &str, - az: &str, - ) -> Result { - let key = crate::key::database::az::new(ns, db, az); - let val = self.get(key).await?.ok_or(Error::AzNotFound { - value: az.to_owned(), - })?; - Ok(val.into()) - } - /// Retrieve a specific analyzer definition. - pub async fn get_ix( + + /// Retrieve a live query for a table. + pub async fn get_tb_live( &mut self, ns: &str, db: &str, tb: &str, - ix: &str, - ) -> Result { - let key = crate::key::table::ix::new(ns, db, tb, ix); - let val = self.get(key).await?.ok_or(Error::IxNotFound { - value: ix.to_owned(), - })?; - Ok(val.into()) - } - - /// Retrieve a specific user definition from ROOT. - pub async fn get_root_user(&mut self, user: &str) -> Result { - let key = crate::key::root::us::new(user); - let val = self.get(key).await?.ok_or(Error::UserRootNotFound { - value: user.to_owned(), - })?; - Ok(val.into()) - } - - /// Retrieve a specific user definition from a namespace. - pub async fn get_ns_user( - &mut self, - ns: &str, - user: &str, - ) -> Result { - let key = crate::key::namespace::us::new(ns, user); - let val = self.get(key).await?.ok_or(Error::UserNsNotFound { - value: user.to_owned(), - ns: ns.to_owned(), - })?; - Ok(val.into()) - } - - /// Retrieve a specific user definition from a database. - pub async fn get_db_user( - &mut self, - ns: &str, - db: &str, - user: &str, - ) -> Result { - let key = crate::key::database::us::new(ns, db, user); - let val = self.get(key).await?.ok_or(Error::UserDbNotFound { - value: user.to_owned(), - ns: ns.to_owned(), - db: db.to_owned(), + lv: &Uuid, + ) -> Result { + let key = crate::key::table::lq::new(ns, db, tb, *lv); + let key_enc = crate::key::table::lq::Lq::encode(&key)?; + trace!("Getting lv ({:?}) {:?}", lv, crate::key::debug::sprint_key(&key_enc)); + let val = self.get(key_enc).await?.ok_or(Error::LvNotFound { + value: lv.to_string(), })?; Ok(val.into()) } @@ -2046,6 +2006,79 @@ impl Transaction { }) } + /// Retrieve a specific function definition. + pub async fn get_and_cache_db_function( + &mut self, + ns: &str, + db: &str, + fc: &str, + ) -> Result, Error> { + let key = crate::key::database::fc::new(ns, db, fc).encode()?; + Ok(if let Some(e) = self.cache.get(&key) { + if let Entry::Fc(v) = e { + v + } else { + unreachable!(); + } + } else { + let val = self.get(key.clone()).await?.ok_or(Error::FcNotFound { + value: fc.to_owned(), + })?; + let val: Arc = Arc::new(val.into()); + self.cache.set(key, Entry::Fc(Arc::clone(&val))); + val + }) + } + + /// Retrieve a specific param definition. + pub async fn get_and_cache_db_param( + &mut self, + ns: &str, + db: &str, + pa: &str, + ) -> Result, Error> { + let key = crate::key::database::pa::new(ns, db, pa).encode()?; + Ok(if let Some(e) = self.cache.get(&key) { + if let Entry::Pa(v) = e { + v + } else { + unreachable!(); + } + } else { + let val = self.get(key.clone()).await?.ok_or(Error::PaNotFound { + value: pa.to_owned(), + })?; + let val: Arc = Arc::new(val.into()); + self.cache.set(key, Entry::Pa(Arc::clone(&val))); + val + }) + } + + /// Retrieve a specific table index definition. + pub async fn get_and_cache_tb_index( + &mut self, + ns: &str, + db: &str, + tb: &str, + ix: &str, + ) -> Result, Error> { + let key = crate::key::table::ix::new(ns, db, tb, ix).encode()?; + Ok(if let Some(e) = self.cache.get(&key) { + if let Entry::Ix(v) = e { + v + } else { + unreachable!(); + } + } else { + let val = self.get(key.clone()).await?.ok_or(Error::IxNotFound { + value: ix.to_owned(), + })?; + let val: Arc = Arc::new(val.into()); + self.cache.set(key, Entry::Ix(Arc::clone(&val))); + val + }) + } + /// Add a namespace with a default configuration, only if we are in dynamic mode. pub async fn add_and_cache_ns( &mut self, @@ -2170,20 +2203,6 @@ impl Transaction { chn.send(bytes!("OPTION IMPORT;")).await?; chn.send(bytes!("")).await?; } - // Output FUNCTIONS - { - let fcs = self.all_fc(ns, db).await?; - if !fcs.is_empty() { - chn.send(bytes!("-- ------------------------------")).await?; - chn.send(bytes!("-- FUNCTIONS")).await?; - chn.send(bytes!("-- ------------------------------")).await?; - chn.send(bytes!("")).await?; - for fc in fcs.iter() { - chn.send(bytes!(format!("{fc};"))).await?; - } - chn.send(bytes!("")).await?; - } - } // Output USERS { let dus = self.all_db_users(ns, db).await?; @@ -2200,7 +2219,7 @@ impl Transaction { } // Output TOKENS { - let dts = self.all_dt(ns, db).await?; + let dts = self.all_db_tokens(ns, db).await?; if !dts.is_empty() { chn.send(bytes!("-- ------------------------------")).await?; chn.send(bytes!("-- TOKENS")).await?; @@ -2214,7 +2233,7 @@ impl Transaction { } // Output PARAMS { - let pas = self.all_pa(ns, db).await?; + let pas = self.all_db_params(ns, db).await?; if !pas.is_empty() { chn.send(bytes!("-- ------------------------------")).await?; chn.send(bytes!("-- PARAMS")).await?; @@ -2226,6 +2245,34 @@ impl Transaction { chn.send(bytes!("")).await?; } } + // Output FUNCTIONS + { + let fcs = self.all_db_functions(ns, db).await?; + if !fcs.is_empty() { + chn.send(bytes!("-- ------------------------------")).await?; + chn.send(bytes!("-- FUNCTIONS")).await?; + chn.send(bytes!("-- ------------------------------")).await?; + chn.send(bytes!("")).await?; + for fc in fcs.iter() { + chn.send(bytes!(format!("{fc};"))).await?; + } + chn.send(bytes!("")).await?; + } + } + // Output ANALYZERS + { + let azs = self.all_db_analyzers(ns, db).await?; + if !azs.is_empty() { + chn.send(bytes!("-- ------------------------------")).await?; + chn.send(bytes!("-- ANALYZERS")).await?; + chn.send(bytes!("-- ------------------------------")).await?; + chn.send(bytes!("")).await?; + for az in azs.iter() { + chn.send(bytes!(format!("{az};"))).await?; + } + chn.send(bytes!("")).await?; + } + } // Output SCOPES { let scs = self.all_sc(ns, db).await?; @@ -2239,7 +2286,7 @@ impl Transaction { chn.send(bytes!(format!("{sc};"))).await?; // Output TOKENS { - let sts = self.all_st(ns, db, &sc.name).await?; + let sts = self.all_sc_tokens(ns, db, &sc.name).await?; if !sts.is_empty() { for st in sts.iter() { chn.send(bytes!(format!("{st};"))).await?; @@ -2251,20 +2298,6 @@ impl Transaction { chn.send(bytes!("")).await?; } } - // Output ANALYZERS - { - let azs = self.all_az(ns, db).await?; - if !azs.is_empty() { - chn.send(bytes!("-- ------------------------------")).await?; - chn.send(bytes!("-- ANALYZERS")).await?; - chn.send(bytes!("-- ------------------------------")).await?; - chn.send(bytes!("")).await?; - for az in azs.iter() { - chn.send(bytes!(format!("{az};"))).await?; - } - chn.send(bytes!("")).await?; - } - } // Output TABLES { let tbs = self.all_tb(ns, db).await?; @@ -2278,17 +2311,15 @@ impl Transaction { chn.send(bytes!(format!("{tb};"))).await?; chn.send(bytes!("")).await?; // Output FIELDS - { - let fds = self.all_fd(ns, db, &tb.name).await?; - if !fds.is_empty() { - for fd in fds.iter() { - chn.send(bytes!(format!("{fd};"))).await?; - } - chn.send(bytes!("")).await?; + let fds = self.all_tb_fields(ns, db, &tb.name).await?; + if !fds.is_empty() { + for fd in fds.iter() { + chn.send(bytes!(format!("{fd};"))).await?; } + chn.send(bytes!("")).await?; } // Output INDEXES - let ixs = self.all_ix(ns, db, &tb.name).await?; + let ixs = self.all_tb_indexes(ns, db, &tb.name).await?; if !ixs.is_empty() { for ix in ixs.iter() { chn.send(bytes!(format!("{ix};"))).await?; @@ -2296,7 +2327,7 @@ impl Transaction { chn.send(bytes!("")).await?; } // Output EVENTS - let evs = self.all_ev(ns, db, &tb.name).await?; + let evs = self.all_tb_events(ns, db, &tb.name).await?; if !evs.is_empty() { for ev in evs.iter() { chn.send(bytes!(format!("{ev};"))).await?; @@ -2400,13 +2431,11 @@ impl Transaction { &mut self, ns: &str, db: &str, - tb: &DefineTableStatement, + tb: &str, id: &Thing, v: Cow<'_, Value>, ) { - if tb.changefeed.is_some() { - self.cf.update(ns, db, tb.name.to_owned(), id.clone(), v) - } + self.cf.update(ns, db, tb, id.clone(), v) } pub(crate) async fn get_idg(&mut self, key: Key) -> Result { diff --git a/lib/src/sql/function.rs b/lib/src/sql/function.rs index e8f7d7b5..26962a8d 100644 --- a/lib/src/sql/function.rs +++ b/lib/src/sql/function.rs @@ -178,11 +178,11 @@ impl Function { // Claim transaction let mut run = txn.lock().await; // Get the function definition - run.get_fc(opt.ns(), opt.db(), s).await? + run.get_and_cache_db_function(opt.ns(), opt.db(), s).await? }; // Check permissions if opt.check_perms(Action::View) { - match val.permissions { + match &val.permissions { Permission::Full => (), Permission::None => { return Err(Error::FunctionPermissions { @@ -217,8 +217,8 @@ impl Function { // Duplicate context let mut ctx = Context::new(ctx); // Process the function arguments - for (val, (name, kind)) in a.into_iter().zip(val.args) { - ctx.add_value(name.to_raw(), val.coerce_to(&kind)?); + for (val, (name, kind)) in a.into_iter().zip(&val.args) { + ctx.add_value(name.to_raw(), val.coerce_to(kind)?); } // Run the custom function val.block.compute(&ctx, opt, txn, doc).await diff --git a/lib/src/sql/idiom.rs b/lib/src/sql/idiom.rs index 8de336e8..3b24b4ae 100644 --- a/lib/src/sql/idiom.rs +++ b/lib/src/sql/idiom.rs @@ -110,19 +110,19 @@ impl Idiom { .collect::>() .into() } - /// Check if this expression is an 'id' field + /// Check if this Idiom is an 'id' field pub(crate) fn is_id(&self) -> bool { self.0.len() == 1 && self.0[0].eq(&ID[0]) } - /// Check if this expression is an 'in' field + /// Check if this Idiom is an 'in' field pub(crate) fn is_in(&self) -> bool { self.0.len() == 1 && self.0[0].eq(&IN[0]) } - /// Check if this expression is an 'out' field + /// Check if this Idiom is an 'out' field pub(crate) fn is_out(&self) -> bool { self.0.len() == 1 && self.0[0].eq(&OUT[0]) } - /// Check if this expression is an 'out' field + /// Check if this Idiom is a 'meta' field pub(crate) fn is_meta(&self) -> bool { self.0.len() == 1 && self.0[0].eq(&META[0]) } diff --git a/lib/src/sql/number.rs b/lib/src/sql/number.rs index b477839c..975feec5 100644 --- a/lib/src/sql/number.rs +++ b/lib/src/sql/number.rs @@ -208,7 +208,7 @@ impl Number { match self { Number::Int(_) => true, Number::Float(v) => v.fract() == 0.0, - Number::Decimal(v) => decimal_is_integer(v), + Number::Decimal(v) => v.is_integer(), } } @@ -686,29 +686,12 @@ pub fn integer(i: &str) -> IResult<&str, i64> { Ok((i, v)) } -/// TODO: This slow but temporary (awaiting https://docs.rs/rust_decimal/latest/rust_decimal/ version >1.29.1) -pub(crate) fn decimal_is_integer(decimal: &Decimal) -> bool { - decimal.fract().is_zero() -} - #[cfg(test)] mod tests { use super::*; use std::ops::Div; - #[test] - fn dec_is_integer() { - assert!(decimal_is_integer(&Decimal::MAX)); - assert!(decimal_is_integer(&Decimal::MIN)); - for n in -10..10 { - assert!(decimal_is_integer(&Decimal::from(n))); - assert!(!decimal_is_integer(&(Decimal::from(n) + Decimal::from_f32(0.1).unwrap()))); - } - - assert!(!decimal_is_integer(&Decimal::HALF_PI)); - } - #[test] fn number_nan() { let sql = "NaN"; diff --git a/lib/src/sql/param.rs b/lib/src/sql/param.rs index 02b0d368..133da781 100644 --- a/lib/src/sql/param.rs +++ b/lib/src/sql/param.rs @@ -75,7 +75,7 @@ impl Param { // Claim transaction let mut run = txn.lock().await; // Get the param definition - run.get_pa(opt.ns(), opt.db(), v).await + run.get_and_cache_db_param(opt.ns(), opt.db(), v).await }; // Check if the param has been set globally match val { @@ -83,7 +83,7 @@ impl Param { Ok(val) => { // Check permissions if opt.check_perms(Action::View) { - match val.permissions { + match &val.permissions { Permission::Full => (), Permission::None => { return Err(Error::ParamPermissions { @@ -103,7 +103,7 @@ impl Param { } } // Return the value - Ok(val.value) + Ok(val.value.to_owned()) } // The param has not been set globally Err(_) => Ok(Value::None), diff --git a/lib/src/sql/statements/analyze.rs b/lib/src/sql/statements/analyze.rs index f0432699..8764f60d 100644 --- a/lib/src/sql/statements/analyze.rs +++ b/lib/src/sql/statements/analyze.rs @@ -43,13 +43,15 @@ impl AnalyzeStatement { // Claim transaction let mut run = txn.lock().await; // Read the index - let ix = run.get_ix(opt.ns(), opt.db(), tb.as_str(), idx.as_str()).await?; + let ix = run + .get_and_cache_tb_index(opt.ns(), opt.db(), tb.as_str(), idx.as_str()) + .await?; let ikb = IndexKeyBase::new(opt, &ix); // Index operation dispatching let value: Value = match &ix.index { Index::Search(p) => { - let az = run.get_az(opt.ns(), opt.db(), p.az.as_str()).await?; + let az = run.get_db_analyzer(opt.ns(), opt.db(), p.az.as_str()).await?; let ft = FtIndex::new(&mut run, az, ikb, p, TreeStoreType::Traversal).await?; ft.statistics(&mut run).await?.into() diff --git a/lib/src/sql/statements/info.rs b/lib/src/sql/statements/info.rs index 1edb224f..0212c754 100644 --- a/lib/src/sql/statements/info.rs +++ b/lib/src/sql/statements/info.rs @@ -86,7 +86,7 @@ impl InfoStatement { res.insert("users".to_owned(), tmp.into()); // Process the tokens let mut tmp = Object::default(); - for v in run.all_nt(opt.ns()).await?.iter() { + for v in run.all_ns_tokens(opt.ns()).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("tokens".to_owned(), tmp.into()); @@ -108,19 +108,19 @@ impl InfoStatement { res.insert("users".to_owned(), tmp.into()); // Process the tokens let mut tmp = Object::default(); - for v in run.all_dt(opt.ns(), opt.db()).await?.iter() { + for v in run.all_db_tokens(opt.ns(), opt.db()).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("tokens".to_owned(), tmp.into()); // Process the functions let mut tmp = Object::default(); - for v in run.all_fc(opt.ns(), opt.db()).await?.iter() { + for v in run.all_db_functions(opt.ns(), opt.db()).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("functions".to_owned(), tmp.into()); // Process the params let mut tmp = Object::default(); - for v in run.all_pa(opt.ns(), opt.db()).await?.iter() { + for v in run.all_db_params(opt.ns(), opt.db()).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("params".to_owned(), tmp.into()); @@ -138,7 +138,7 @@ impl InfoStatement { res.insert("tables".to_owned(), tmp.into()); // Process the analyzers let mut tmp = Object::default(); - for v in run.all_az(opt.ns(), opt.db()).await?.iter() { + for v in run.all_db_analyzers(opt.ns(), opt.db()).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("analyzers".to_owned(), tmp.into()); @@ -154,7 +154,7 @@ impl InfoStatement { let mut res = Object::default(); // Process the tokens let mut tmp = Object::default(); - for v in run.all_st(opt.ns(), opt.db(), sc).await?.iter() { + for v in run.all_sc_tokens(opt.ns(), opt.db(), sc).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("tokens".to_owned(), tmp.into()); @@ -170,25 +170,25 @@ impl InfoStatement { let mut res = Object::default(); // Process the events let mut tmp = Object::default(); - for v in run.all_ev(opt.ns(), opt.db(), tb).await?.iter() { + for v in run.all_tb_events(opt.ns(), opt.db(), tb).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("events".to_owned(), tmp.into()); // Process the fields let mut tmp = Object::default(); - for v in run.all_fd(opt.ns(), opt.db(), tb).await?.iter() { + for v in run.all_tb_fields(opt.ns(), opt.db(), tb).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("fields".to_owned(), tmp.into()); // Process the tables let mut tmp = Object::default(); - for v in run.all_ft(opt.ns(), opt.db(), tb).await?.iter() { + for v in run.all_tb_views(opt.ns(), opt.db(), tb).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("tables".to_owned(), tmp.into()); // Process the indexes let mut tmp = Object::default(); - for v in run.all_ix(opt.ns(), opt.db(), tb).await?.iter() { + for v in run.all_tb_indexes(opt.ns(), opt.db(), tb).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("indexes".to_owned(), tmp.into()); diff --git a/lib/src/sql/statements/insert.rs b/lib/src/sql/statements/insert.rs index 06944743..050b6918 100644 --- a/lib/src/sql/statements/insert.rs +++ b/lib/src/sql/statements/insert.rs @@ -110,7 +110,7 @@ impl InsertStatement { _ => unreachable!(), }, v => { - return Err(Error::RelateStatement { + return Err(Error::InsertStatement { value: v.to_string(), }) } diff --git a/lib/src/sql/statements/live.rs b/lib/src/sql/statements/live.rs index 2fc32730..4f981c94 100644 --- a/lib/src/sql/statements/live.rs +++ b/lib/src/sql/statements/live.rs @@ -139,8 +139,7 @@ pub fn live(i: &str) -> IResult<&str, LiveStatement> { what, cond, fetch, - archived: None, - auth: None, // Auth is set via options in compute() + ..Default::default() }, )) })(i) diff --git a/lib/src/sql/value/cut.rs b/lib/src/sql/value/cut.rs index 3b982d2a..82c7c991 100644 --- a/lib/src/sql/value/cut.rs +++ b/lib/src/sql/value/cut.rs @@ -71,7 +71,7 @@ impl Value { }, Part::Index(i) => match path.len() { 1 => { - if v.len().gt(&i.to_usize()) { + if v.len() > i.to_usize() { v.remove(i.to_usize()); } } diff --git a/lib/src/sql/value/del.rs b/lib/src/sql/value/del.rs index 77ea638f..33c7edf6 100644 --- a/lib/src/sql/value/del.rs +++ b/lib/src/sql/value/del.rs @@ -102,7 +102,7 @@ impl Value { }, Part::Index(i) => match path.len() { 1 => { - if v.len().gt(&i.to_usize()) { + if v.len() > i.to_usize() { v.remove(i.to_usize()); } Ok(()) @@ -168,7 +168,7 @@ impl Value { Part::Value(x) => match x.compute(ctx, opt, txn, None).await? { Value::Number(i) => match path.len() { 1 => { - if v.len().gt(&i.to_usize()) { + if v.len() > i.to_usize() { v.remove(i.to_usize()); } Ok(()) diff --git a/lib/src/sql/value/value.rs b/lib/src/sql/value/value.rs index 76200993..f79c9396 100644 --- a/lib/src/sql/value/value.rs +++ b/lib/src/sql/value/value.rs @@ -27,7 +27,6 @@ use crate::sql::id::{Gen, Id}; use crate::sql::idiom::{self, reparse_idiom_start, Idiom}; use crate::sql::kind::Kind; use crate::sql::model::{model, Model}; -use crate::sql::number::decimal_is_integer; use crate::sql::number::{number, Number}; use crate::sql::object::{key, object, Object}; use crate::sql::operation::Operation; @@ -815,7 +814,7 @@ impl Value { /// Check if this Value is a boolean value pub fn is_bool(&self) -> bool { - self.is_true() || self.is_false() + matches!(self, Value::Bool(_)) } /// Check if this Value is TRUE or 'true' @@ -1098,7 +1097,7 @@ impl Value { } // ----------------------------------- - // Simple conversion of value + // Simple conversion of values // ----------------------------------- /// Treat a string as a table name @@ -1225,7 +1224,7 @@ impl Value { // Attempt to convert an float number Value::Number(Number::Float(v)) if v.fract() == 0.0 => Ok(v as i64), // Attempt to convert a decimal number - Value::Number(Number::Decimal(v)) if decimal_is_integer(&v) => match v.try_into() { + Value::Number(Number::Decimal(v)) if v.is_integer() => match v.try_into() { // The Decimal can be represented as an i64 Ok(v) => Ok(v), // The Decimal is out of bounds @@ -1250,7 +1249,7 @@ impl Value { // Attempt to convert an float number Value::Number(Number::Float(v)) if v.fract() == 0.0 => Ok(v as u64), // Attempt to convert a decimal number - Value::Number(Number::Decimal(v)) if decimal_is_integer(&v) => match v.try_into() { + Value::Number(Number::Decimal(v)) if v.is_integer() => match v.try_into() { // The Decimal can be represented as an u64 Ok(v) => Ok(v), // The Decimal is out of bounds @@ -1326,7 +1325,7 @@ impl Value { // Attempt to convert an float number Value::Number(Number::Float(v)) if v.fract() == 0.0 => Ok(Number::Int(v as i64)), // Attempt to convert a decimal number - Value::Number(Number::Decimal(ref v)) if decimal_is_integer(v) => match v.to_i64() { + Value::Number(Number::Decimal(v)) if v.is_integer() => match v.to_i64() { // The Decimal can be represented as an Int Some(v) => Ok(Number::Int(v)), // The Decimal is out of bounds @@ -1800,7 +1799,7 @@ impl Value { // Attempt to convert an float number Value::Number(Number::Float(v)) if v.fract() == 0.0 => Ok(Number::Int(v as i64)), // Attempt to convert a decimal number - Value::Number(Number::Decimal(v)) if decimal_is_integer(&v) => match v.try_into() { + Value::Number(Number::Decimal(v)) if v.is_integer() => match v.try_into() { // The Decimal can be represented as an Int Ok(v) => Ok(Number::Int(v)), // The Decimal is out of bounds