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
119#[macro_use]
120mod mac;
121
122mod api;
123
124#[doc(inline)]
125pub use api::engine;
126#[cfg(feature = "protocol-http")]
127#[doc(hidden)]
128pub use api::headers;
129#[doc(inline)]
130pub use api::method;
131#[doc(inline)]
132pub use api::opt;
133#[doc(inline)]
134pub use api::Connect;
135#[doc(inline)]
136pub use api::Connection;
137#[doc(inline)]
138pub use api::Response;
139#[doc(inline)]
140pub use api::Result;
141#[doc(inline)]
142pub use api::Surreal;
143#[doc(inline)]
144pub use surrealdb_core::*;
145
146use uuid::Uuid;
147
148#[doc(hidden)]
149/// Channels for receiving a SurrealQL database export
150pub mod channel {
151	pub use channel::bounded;
152	pub use channel::unbounded;
153	pub use channel::Receiver;
154	pub use channel::Sender;
155}
156
157/// Different error types for embedded and remote databases
158pub mod error {
159	pub use crate::api::err::Error as Api;
160	pub use crate::err::Error as Db;
161}
162
163/// The action performed on a record
164///
165/// This is used in live query notifications.
166#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
167#[non_exhaustive]
168pub enum Action {
169	Create,
170	Update,
171	Delete,
172}
173
174impl From<dbs::Action> for Action {
175	fn from(action: dbs::Action) -> Self {
176		match action {
177			dbs::Action::Create => Self::Create,
178			dbs::Action::Update => Self::Update,
179			dbs::Action::Delete => Self::Delete,
180			_ => unreachable!(),
181		}
182	}
183}
184
185/// A live query notification
186///
187/// Live queries return a stream of notifications. The notification contains an `action` that triggered the change in the database record and `data` itself.
188/// 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
189/// the action is create or update.
190#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
191#[non_exhaustive]
192pub struct Notification<R> {
193	pub query_id: Uuid,
194	pub action: Action,
195	pub data: R,
196}
197
198/// An error originating from the SurrealDB client library
199#[derive(Debug, thiserror::Error, serde::Serialize)]
200pub enum Error {
201	/// An error with an embedded storage engine
202	#[error("{0}")]
203	Db(#[from] crate::error::Db),
204	/// An error with a remote database instance
205	#[error("{0}")]
206	Api(#[from] crate::error::Api),
207}