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}