surrealdb/
lib.rs

1//! This library provides a low-level database library implementation, a remote client
2//! and a query language definition, for [SurrealDB](https://surrealdb.com), the ultimate cloud database for
3//! tomorrow's applications. SurrealDB is a scalable, distributed, collaborative, document-graph
4//! database for the realtime web.
5//!
6//! This library can be used to start an embedded in-memory datastore, an embedded datastore
7//! persisted to disk, a browser-based embedded datastore backed by IndexedDB, or for connecting
8//! to a distributed [TiKV](https://tikv.org) key-value store.
9//!
10//! It also enables simple and advanced querying of a remote SurrealDB server from
11//! server-side or client-side code. All connections to SurrealDB are made over WebSockets by default,
12//! and automatically reconnect when the connection is terminated.
13//!
14//! # Examples
15//!
16//! ```no_run
17//! use std::borrow::Cow;
18//! use serde::{Serialize, Deserialize};
19//! use serde_json::json;
20//! use surrealdb::{Error, Surreal};
21//! use surrealdb::opt::auth::Root;
22//! use surrealdb::engine::remote::ws::Ws;
23//!
24//! #[derive(Serialize, Deserialize)]
25//! struct Person {
26//!     title: String,
27//!     name: Name,
28//!     marketing: bool,
29//! }
30//!
31//! // Pro tip: Replace String with Cow<'static, str> to
32//! // avoid unnecessary heap allocations when inserting
33//!
34//! #[derive(Serialize, Deserialize)]
35//! struct Name {
36//!     first: Cow<'static, str>,
37//!     last: Cow<'static, str>,
38//! }
39//!
40//! // Install at https://surrealdb.com/install
41//! // and use `surreal start --user root --pass root`
42//! // to start a working database to take the following queries
43
44//! // See the results via `surreal sql --ns namespace --db database --pretty`
45//! // or https://surrealist.app/
46//! // followed by the query `SELECT * FROM person;`
47
48//! #[tokio::main]
49//! async fn main() -> Result<(), Error> {
50//!     let db = Surreal::new::<Ws>("localhost:8000").await?;
51//!
52//!     // Signin as a namespace, database, or root user
53//!     db.signin(Root {
54//!         username: "root",
55//!         password: "root",
56//!     }).await?;
57//!
58//!     // Select a specific namespace / database
59//!     db.use_ns("namespace").use_db("database").await?;
60//!
61//!     // Create a new person with a random ID
62//!     let created: Vec<Person> = db.create("person")
63//!         .content(Person {
64//!             title: "Founder & CEO".into(),
65//!             name: Name {
66//!                 first: "Tobie".into(),
67//!                 last: "Morgan Hitchcock".into(),
68//!             },
69//!             marketing: true,
70//!         })
71//!         .await?;
72//!
73//!     // Create a new person with a specific ID
74//!     let created: Option<Person> = db.create(("person", "jaime"))
75//!         .content(Person {
76//!             title: "Founder & COO".into(),
77//!             name: Name {
78//!                 first: "Jaime".into(),
79//!                 last: "Morgan Hitchcock".into(),
80//!             },
81//!             marketing: false,
82//!         })
83//!         .await?;
84//!
85//!     // Update a person record with a specific ID
86//!     let updated: Option<Person> = db.update(("person", "jaime"))
87//!         .merge(json!({"marketing": true}))
88//!         .await?;
89//!
90//!     // Select all people records
91//!     let people: Vec<Person> = db.select("person").await?;
92//!
93//!     // Perform a custom advanced query
94//!     let query = r#"
95//!         SELECT marketing, count()
96//!         FROM type::table($table)
97//!         GROUP BY marketing
98//!     "#;
99//!
100//!     let groups = db.query(query)
101//!         .bind(("table", "person"))
102//!         .await?;
103//!
104//!     Ok(())
105//! }
106//! ```
107
108#![doc(html_favicon_url = "https://surrealdb.s3.amazonaws.com/favicon.png")]
109#![doc(html_logo_url = "https://surrealdb.s3.amazonaws.com/icon.png")]
110#![cfg_attr(docsrs, feature(doc_cfg))]
111#![cfg_attr(test, deny(warnings))]
112
113#[cfg(all(target_arch = "wasm32", feature = "ml"))]
114compile_error!("The `ml` feature is not supported on the `wasm32` architecture.");
115
116#[macro_use]
117extern crate tracing;
118
119mod api;
120
121#[doc(inline)]
122pub use api::engine;
123#[cfg(feature = "protocol-http")]
124#[doc(hidden)]
125pub use api::headers;
126#[doc(inline)]
127pub use api::method;
128#[doc(inline)]
129pub use api::opt;
130#[doc(inline)]
131pub use api::Connect;
132#[doc(inline)]
133pub use api::Connection;
134#[doc(inline)]
135pub use api::Response;
136#[doc(inline)]
137pub use api::Result;
138#[doc(inline)]
139pub use api::Surreal;
140#[doc(inline)]
141pub use surrealdb_core::*;
142
143use uuid::Uuid;
144
145#[doc(hidden)]
146/// Channels for receiving a SurrealQL database export
147pub mod channel {
148	pub use channel::bounded;
149	pub use channel::unbounded;
150	pub use channel::Receiver;
151	pub use channel::Sender;
152}
153
154/// Different error types for embedded and remote databases
155pub mod error {
156	pub use crate::api::err::Error as Api;
157	pub use crate::err::Error as Db;
158}
159
160/// The action performed on a record
161///
162/// This is used in live query notifications.
163#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
164#[non_exhaustive]
165pub enum Action {
166	Create,
167	Update,
168	Delete,
169}
170
171impl From<dbs::Action> for Action {
172	fn from(action: dbs::Action) -> Self {
173		match action {
174			dbs::Action::Create => Self::Create,
175			dbs::Action::Update => Self::Update,
176			dbs::Action::Delete => Self::Delete,
177			_ => unreachable!(),
178		}
179	}
180}
181
182/// A live query notification
183///
184/// Live queries return a stream of notifications. The notification contains an `action` that triggered the change in the database record and `data` itself.
185/// For deletions the data is the record before it was deleted. For everything else, it's the newly created record or updated record depending on whether
186/// the action is create or update.
187#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
188#[non_exhaustive]
189pub struct Notification<R> {
190	pub query_id: Uuid,
191	pub action: Action,
192	pub data: R,
193}
194
195/// An error originating from the SurrealDB client library
196#[derive(Debug, thiserror::Error, serde::Serialize)]
197pub enum Error {
198	/// An error with an embedded storage engine
199	#[error("{0}")]
200	Db(#[from] crate::error::Db),
201	/// An error with a remote database instance
202	#[error("{0}")]
203	Api(#[from] crate::error::Api),
204}