Improve comments in public library package

This commit is contained in:
Tobie Morgan Hitchcock 2022-05-04 00:38:16 +01:00
parent 65d0e3138a
commit c5960a028e
6 changed files with 94 additions and 22 deletions

View file

@ -7,12 +7,18 @@ pub enum Level {
Sc, Sc,
} }
/// Specifies the authentication level for the datastore execution context.
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd)]
pub enum Auth { pub enum Auth {
/// Specifies that the user is not authenticated
No, No,
/// Specifies that the user is authenticated with full root permissions
Kv, Kv,
/// Specifies that the user is has full permissions for a particular Namespace
Ns(String), Ns(String),
/// Specifies that the user is has full permissions for a particular Namespace and Database
Db(String, String), Db(String, String),
/// Specifies that the user is has full permissions for a particular Namespace, Database, and Scope
Sc(String, String, String), Sc(String, String, String),
} }
@ -23,7 +29,8 @@ impl Default for Auth {
} }
impl Auth { impl Auth {
pub fn perms(&self) -> bool { /// Checks whether permissions clauses need to be processed
pub(crate) fn perms(&self) -> bool {
match self { match self {
Auth::No => true, Auth::No => true,
Auth::Sc(_, _, _) => true, Auth::Sc(_, _, _) => true,
@ -32,7 +39,8 @@ impl Auth {
Auth::Kv => false, Auth::Kv => false,
} }
} }
pub fn check(&self, level: Level) -> bool { /// Checks whether the current authentication matches the required level
pub(crate) fn check(&self, level: Level) -> bool {
match self { match self {
Auth::No => matches!(level, Level::No), Auth::No => matches!(level, Level::No),
Auth::Sc(_, _, _) => matches!(level, Level::No | Level::Sc), Auth::Sc(_, _, _) => matches!(level, Level::No | Level::Sc),

View file

@ -4,6 +4,7 @@ use serde::ser::SerializeStruct;
use serde::Serialize; use serde::Serialize;
use std::time::Duration; use std::time::Duration;
/// The return value when running a query set on the database.
#[derive(Debug)] #[derive(Debug)]
pub struct Response { pub struct Response {
pub sql: Option<String>, pub sql: Option<String>,
@ -12,11 +13,11 @@ pub struct Response {
} }
impl Response { impl Response {
// Return the transaction speed /// Return the transaction duration as a string
pub fn speed(&self) -> String { pub fn speed(&self) -> String {
format!("{:?}", self.time) format!("{:?}", self.time)
} }
// Retrieve the response as a result /// Retrieve the response as a result by reference
pub fn output(&self) -> Result<&Value, &Error> { pub fn output(&self) -> Result<&Value, &Error> {
match &self.result { match &self.result {
Ok(v) => Ok(v), Ok(v) => Ok(v),

View file

@ -3,29 +3,38 @@ use crate::dbs::Auth;
use crate::sql::value::Value; use crate::sql::value::Value;
use std::sync::Arc; use std::sync::Arc;
/// Specifies the current session information when processing a query.
#[derive(Clone, Debug, Default, Eq, PartialEq)] #[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Session { pub struct Session {
pub au: Arc<Auth>, // Authentication info /// The current [`Auth`] information
pub ip: Option<String>, // Session ip address pub au: Arc<Auth>,
pub or: Option<String>, // Session origin /// The current connection IP address
pub id: Option<String>, // Session id pub ip: Option<String>,
pub ns: Option<String>, // Namespace /// The current connection origin
pub db: Option<String>, // Database pub or: Option<String>,
pub sc: Option<String>, // Scope /// The current connection ID
pub sd: Option<Value>, // Scope auth data pub id: Option<String>,
/// THe currently selected namespace
pub ns: Option<String>,
/// THe currently selected database
pub db: Option<String>,
/// The currently selected authentication scope
pub sc: Option<String>,
/// The current scope authentication data
pub sd: Option<Value>,
} }
impl Session { impl Session {
// Retrieves the selected namespace // Retrieves the selected namespace
pub fn ns(&self) -> Option<Arc<String>> { pub(crate) fn ns(&self) -> Option<Arc<String>> {
self.ns.to_owned().map(Arc::new) self.ns.to_owned().map(Arc::new)
} }
// Retrieves the selected database // Retrieves the selected database
pub fn db(&self) -> Option<Arc<String>> { pub(crate) fn db(&self) -> Option<Arc<String>> {
self.db.to_owned().map(Arc::new) self.db.to_owned().map(Arc::new)
} }
// Convert a session into a runtime // Convert a session into a runtime
pub fn context(&self, mut ctx: Context) -> Context { pub(crate) fn context(&self, mut ctx: Context) -> Context {
// Add session value // Add session value
let key = String::from("session"); let key = String::from("session");
let val: Value = self.into(); let val: Value = self.into();

View file

@ -20,35 +20,47 @@ use indxdb::err::Error as IndxDBError;
#[cfg(feature = "parallel")] #[cfg(feature = "parallel")]
use tokio::sync::mpsc::error::SendError as TokioError; use tokio::sync::mpsc::error::SendError as TokioError;
/// An error originating from the SurrealDB client library.
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum Error { pub enum Error {
/// This error is used for ignoring a document when processing a query
#[doc(hidden)]
#[error("Conditional clause is not truthy")] #[error("Conditional clause is not truthy")]
Ignore, Ignore,
/// There was an error when connecting to the underlying datastore
#[error("Couldn't setup connection to underlying datastore")] #[error("Couldn't setup connection to underlying datastore")]
Ds, Ds,
/// There was an error when starting a new transaction
#[error("Couldn't create a database transaction")] #[error("Couldn't create a database transaction")]
Tx, Tx,
/// The transaction was already cancelled or committed
#[error("Couldn't update a finished transaction")] #[error("Couldn't update a finished transaction")]
TxFinished, TxFinished,
/// The current transaction was created as read-only
#[error("Couldn't write to a read only transaction")] #[error("Couldn't write to a read only transaction")]
TxReadonly, TxReadonly,
/// The conditional value in the request was not equal
#[error("Value being checked was not correct")] #[error("Value being checked was not correct")]
TxConditionNotMet, TxConditionNotMet,
/// No namespace has been selected
#[error("Specify a namespace to use")] #[error("Specify a namespace to use")]
NsEmpty, NsEmpty,
/// No database has been selected
#[error("Specify a database to use")] #[error("Specify a database to use")]
DbEmpty, DbEmpty,
/// No SQL query has been specified
#[error("Specify some SQL code to execute")] #[error("Specify some SQL code to execute")]
QueryEmpty, QueryEmpty,
/// There was an error with the SQL query
#[error("Parse error on line {line} at character {char} when parsing '{sql}'")] #[error("Parse error on line {line} at character {char} when parsing '{sql}'")]
InvalidQuery { InvalidQuery {
line: usize, line: usize,
@ -56,125 +68,154 @@ pub enum Error {
sql: String, sql: String,
}, },
/// There was an error with the provided JSON Patch
#[error("The JSON Patch contains invalid operations. {message}")] #[error("The JSON Patch contains invalid operations. {message}")]
InvalidPatch { InvalidPatch {
message: String, message: String,
}, },
/// There was an error with the provided JavaScript code
#[error("Problem with embedded script function. {message}")] #[error("Problem with embedded script function. {message}")]
InvalidScript { InvalidScript {
message: String, message: String,
}, },
/// The wrong number of arguments was given for the specified function
#[error("Incorrect arguments for function {name}(). {message}")] #[error("Incorrect arguments for function {name}(). {message}")]
InvalidArguments { InvalidArguments {
name: String, name: String,
message: String, message: String,
}, },
/// The query timedout
#[error("Query timeout of {timer:?} exceeded")] #[error("Query timeout of {timer:?} exceeded")]
QueryTimeout { QueryTimeout {
timer: Duration, timer: Duration,
}, },
/// The query did not execute, because the transaction was cancelled
#[error("Query not executed due to cancelled transaction")] #[error("Query not executed due to cancelled transaction")]
QueryCancelled, QueryCancelled,
/// The query did not execute, because the transaction has failed
#[error("Query not executed due to failed transaction")] #[error("Query not executed due to failed transaction")]
QueryNotExecuted, QueryNotExecuted,
/// The permissions do not allow for performing the specified query
#[error("You don't have permission to perform this query type")] #[error("You don't have permission to perform this query type")]
QueryPermissions, QueryPermissions,
/// The permissions do not allow for changing to the specified namespace
#[error("You don't have permission to change to the {ns} namespace")] #[error("You don't have permission to change to the {ns} namespace")]
NsNotAllowed { NsNotAllowed {
ns: String, ns: String,
}, },
/// The permissions do not allow for changing to the specified database
#[error("You don't have permission to change to the {db} database")] #[error("You don't have permission to change to the {db} database")]
DbNotAllowed { DbNotAllowed {
db: String, db: String,
}, },
/// The requested namespace does not exist
#[error("The namespace does not exist")] #[error("The namespace does not exist")]
NsNotFound, NsNotFound,
/// The requested namespace token does not exist
#[error("The namespace token does not exist")] #[error("The namespace token does not exist")]
NtNotFound, NtNotFound,
/// The requested namespace login does not exist
#[error("The namespace login does not exist")] #[error("The namespace login does not exist")]
NlNotFound, NlNotFound,
/// The requested database does not exist
#[error("The database does not exist")] #[error("The database does not exist")]
DbNotFound, DbNotFound,
/// The requested database token does not exist
#[error("The database token does not exist")] #[error("The database token does not exist")]
DtNotFound, DtNotFound,
/// The requested database login does not exist
#[error("The database login does not exist")] #[error("The database login does not exist")]
DlNotFound, DlNotFound,
/// The requested scope does not exist
#[error("The scope does not exist")] #[error("The scope does not exist")]
ScNotFound, ScNotFound,
/// The requested scope token does not exist
#[error("The scope token does not exist")] #[error("The scope token does not exist")]
StNotFound, StNotFound,
/// The requested table does not exist
#[error("The table does not exist")] #[error("The table does not exist")]
TbNotFound, TbNotFound,
#[error("Too many recursive subqueries have been set")] /// Too many recursive subqueries have been processed
#[error("Too many recursive subqueries have been processed")]
TooManySubqueries { TooManySubqueries {
limit: usize, limit: usize,
}, },
/// Can not execute CREATE query using the specified value
#[error("Can not execute CREATE query using value '{value}'")] #[error("Can not execute CREATE query using value '{value}'")]
CreateStatement { CreateStatement {
value: Value, value: Value,
}, },
/// Can not execute UPDATE query using the specified value
#[error("Can not execute UPDATE query using value '{value}'")] #[error("Can not execute UPDATE query using value '{value}'")]
UpdateStatement { UpdateStatement {
value: Value, value: Value,
}, },
/// Can not execute RELATE query using the specified value
#[error("Can not execute RELATE query using value '{value}'")] #[error("Can not execute RELATE query using value '{value}'")]
RelateStatement { RelateStatement {
value: Value, value: Value,
}, },
/// Can not execute DELETE query using the specified value
#[error("Can not execute DELETE query using value '{value}'")] #[error("Can not execute DELETE query using value '{value}'")]
DeleteStatement { DeleteStatement {
value: Value, value: Value,
}, },
/// Can not execute INSERT query using the specified value
#[error("Can not execute INSERT query using value '{value}'")] #[error("Can not execute INSERT query using value '{value}'")]
InsertStatement { InsertStatement {
value: Value, value: Value,
}, },
/// The permissions do not allow this query to be run on this table
#[error("You don't have permission to run the `{query}` query on the `{table}` table")] #[error("You don't have permission to run the `{query}` query on the `{table}` table")]
TablePermissions { TablePermissions {
query: String, query: String,
table: String, table: String,
}, },
/// The specified table can not be written as it is setup as a foreign table view
#[error("Unable to write to the `{table}` table while setup as a view")] #[error("Unable to write to the `{table}` table while setup as a view")]
TableIsView { TableIsView {
table: String, table: String,
}, },
/// A database entry for the specified record already exists
#[error("Database record `{thing}` already exists")] #[error("Database record `{thing}` already exists")]
RecordExists { RecordExists {
thing: Thing, thing: Thing,
}, },
/// A database index entry for the specified record already exists
#[error("Database index `{index}` already contains `{thing}`")] #[error("Database index `{index}` already contains `{thing}`")]
IndexExists { IndexExists {
index: String, index: String,
thing: Thing, thing: Thing,
}, },
/// The specified field did not conform to the field ASSERT clause
#[error("Found '{value}' for field '{field}' but field must conform to: {check}")] #[error("Found '{value}' for field '{field}' but field must conform to: {check}")]
FieldValue { FieldValue {
value: Value, value: Value,
@ -182,27 +223,34 @@ pub enum Error {
check: Value, check: Value,
}, },
/// Represents an underlying error with Serde encoding / decoding
#[error("Serde error: {0}")] #[error("Serde error: {0}")]
Serde(#[from] SerdeError), Serde(#[from] SerdeError),
/// Represents an underlying error from the EchoDB instance
#[error("Key encoding error: {0}")] #[error("Key encoding error: {0}")]
Encode(#[from] EncodeError), Encode(#[from] EncodeError),
/// Represents an underlying error from the EchoDB instance
#[error("Key decoding error: {0}")] #[error("Key decoding error: {0}")]
Decode(#[from] DecodeError), Decode(#[from] DecodeError),
/// Represents an underlying error from the EchoDB instance
#[cfg(feature = "kv-echodb")] #[cfg(feature = "kv-echodb")]
#[error("Datastore error: {0}")] #[error("Datastore error: {0}")]
EchoDB(#[from] EchoDBError), EchoDB(#[from] EchoDBError),
/// Represents an underlying error from the IndxDB instance
#[cfg(feature = "kv-indxdb")] #[cfg(feature = "kv-indxdb")]
#[error("Datastore error: {0}")] #[error("Datastore error: {0}")]
IndxDB(#[from] IndxDBError), IndxDB(#[from] IndxDBError),
/// Represents an underlying error from the TiKV instance
#[cfg(feature = "kv-tikv")] #[cfg(feature = "kv-tikv")]
#[error("Datastore error: {0}")] #[error("Datastore error: {0}")]
TiKV(#[from] TiKVError), TiKV(#[from] TiKVError),
/// Represents an underlying error with Tokio message channels
#[cfg(feature = "parallel")] #[cfg(feature = "parallel")]
#[error("Tokio Error: {0}")] #[error("Tokio Error: {0}")]
Tokio(#[from] TokioError<(Option<Thing>, Value)>), Tokio(#[from] TokioError<(Option<Thing>, Value)>),

View file

@ -98,7 +98,7 @@ impl Datastore {
_ => unreachable!(), _ => unreachable!(),
} }
} }
/// Create a new transaction /// Create a new transaction on this datastore
pub async fn transaction(&self, write: bool, lock: bool) -> Result<Transaction, Error> { pub async fn transaction(&self, write: bool, lock: bool) -> Result<Transaction, Error> {
match &self.inner { match &self.inner {
#[cfg(feature = "kv-echodb")] #[cfg(feature = "kv-echodb")]
@ -131,7 +131,7 @@ impl Datastore {
} }
} }
} }
/// Execute a query /// Parse and execute an SQL query
pub async fn execute( pub async fn execute(
&self, &self,
txt: &str, txt: &str,
@ -158,7 +158,7 @@ impl Datastore {
opt.db = sess.db(); opt.db = sess.db();
exe.execute(ctx, opt, ast).await exe.execute(ctx, opt, ast).await
} }
/// Execute a query /// Execute a pre-parsed SQL query
pub async fn process( pub async fn process(
&self, &self,
ast: Query, ast: Query,

View file

@ -1,3 +1,11 @@
//! This library provides an easy-to-use client for [SurrealDB](https://surrealdb.com),
//! the ultimate cloud database for tomorrow's applications. SurrealDB is a scalable,
//! distributed, collaborative, document-graph database for the realtime web.
//!
//! This library can be used to start an embedded in-memory datastore, an embedded
//! datastore persisted to disk, or for connecting to a distributed [TiKV](https://tikv.org)
//! key-value store.
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
#[macro_use] #[macro_use]
@ -17,12 +25,10 @@ mod kvs;
pub mod sql; pub mod sql;
pub use err::Error;
pub use dbs::Auth; pub use dbs::Auth;
pub use dbs::Response; pub use dbs::Response;
pub use dbs::Session; pub use dbs::Session;
pub use err::Error;
pub use kvs::Datastore; pub use kvs::Datastore;
pub use kvs::Key; pub use kvs::Key;
pub use kvs::Transaction; pub use kvs::Transaction;