surrealdb/api/method/mod.rs
1//! Methods to use when interacting with a SurrealDB instance
2use self::query::ValidQuery;
3use crate::api::opt;
4use crate::api::opt::auth;
5use crate::api::opt::auth::Credentials;
6use crate::api::opt::auth::Jwt;
7use crate::api::opt::IntoEndpoint;
8use crate::api::Connect;
9use crate::api::Connection;
10use crate::api::OnceLockExt;
11use crate::api::Surreal;
12use crate::opt::IntoExportDestination;
13use crate::opt::WaitFor;
14use serde::Serialize;
15use std::borrow::Cow;
16use std::marker::PhantomData;
17use std::path::Path;
18use std::pin::Pin;
19use std::sync::Arc;
20use std::sync::OnceLock;
21use std::time::Duration;
22use surrealdb_core::sql::to_value as to_core_value;
23
24pub(crate) mod live;
25pub(crate) mod query;
26
27mod authenticate;
28mod begin;
29mod cancel;
30mod commit;
31mod content;
32mod create;
33mod delete;
34mod export;
35mod health;
36mod import;
37mod insert;
38mod insert_relation;
39mod invalidate;
40mod merge;
41mod patch;
42mod run;
43mod select;
44mod set;
45mod signin;
46mod signup;
47mod unset;
48mod update;
49mod upsert;
50mod use_db;
51mod use_ns;
52mod version;
53
54#[cfg(test)]
55mod tests;
56
57pub use authenticate::Authenticate;
58#[doc(hidden)] // Not supported yet
59pub use begin::Begin;
60#[doc(hidden)] // Not supported yet
61pub use begin::Transaction;
62#[doc(hidden)] // Not supported yet
63pub use cancel::Cancel;
64#[doc(hidden)] // Not supported yet
65pub use commit::Commit;
66pub use content::Content;
67pub use create::Create;
68pub use delete::Delete;
69pub use export::{Backup, Export};
70use futures::Future;
71pub use health::Health;
72pub use import::Import;
73pub use insert::Insert;
74pub use invalidate::Invalidate;
75pub use live::Stream;
76pub use merge::Merge;
77pub use patch::Patch;
78pub use query::Query;
79pub use query::QueryStream;
80pub use run::IntoFn;
81pub use run::Run;
82pub use select::Select;
83use serde_content::Serializer;
84pub use set::Set;
85pub use signin::Signin;
86pub use signup::Signup;
87use tokio::sync::watch;
88pub use unset::Unset;
89pub use update::Update;
90pub use upsert::Upsert;
91pub use use_db::UseDb;
92pub use use_ns::UseNs;
93pub use version::Version;
94
95use super::opt::IntoResource;
96
97/// A alias for an often used type of future returned by async methods in this library.
98pub(crate) type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + Sync + 'a>>;
99
100/// Query statistics
101#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
102#[non_exhaustive]
103pub struct Stats {
104 /// The time taken to execute the query
105 pub execution_time: Option<Duration>,
106}
107
108/// Machine learning model marker type for import and export types
109pub struct Model;
110
111/// Live query marker type
112pub struct Live;
113
114/// Responses returned with statistics
115#[derive(Debug)]
116pub struct WithStats<T>(pub T);
117
118impl<C> Surreal<C>
119where
120 C: Connection,
121{
122 /// Initialises a new unconnected instance of the client
123 ///
124 /// This makes it easy to create a static singleton of the client. The static singleton
125 /// pattern in the example below ensures that a single database instance is available
126 /// across very large or complicated applications. With the singleton, only one connection
127 /// to the database is instantiated, and the database connection does not have to be shared
128 /// across components or controllers.
129 ///
130 /// # Examples
131 ///
132 /// Using a static, compile-time scheme
133 ///
134 /// ```no_run
135 /// use std::sync::LazyLock;
136 /// use serde::{Serialize, Deserialize};
137 /// use surrealdb::Surreal;
138 /// use surrealdb::opt::auth::Root;
139 /// use surrealdb::engine::remote::ws::Ws;
140 /// use surrealdb::engine::remote::ws::Client;
141 ///
142 /// // Creates a new static instance of the client
143 /// static DB: LazyLock<Surreal<Client>> = LazyLock::new(Surreal::init);
144 ///
145 /// #[derive(Serialize, Deserialize)]
146 /// struct Person {
147 /// name: String,
148 /// }
149 ///
150 /// #[tokio::main]
151 /// async fn main() -> surrealdb::Result<()> {
152 /// // Connect to the database
153 /// DB.connect::<Ws>("localhost:8000").await?;
154 ///
155 /// // Log into the database
156 /// DB.signin(Root {
157 /// username: "root",
158 /// password: "root",
159 /// }).await?;
160 ///
161 /// // Select a namespace/database
162 /// DB.use_ns("namespace").use_db("database").await?;
163 ///
164 /// // Create or update a specific record
165 /// let tobie: Option<Person> = DB.update(("person", "tobie"))
166 /// .content(Person {
167 /// name: "Tobie".into(),
168 /// }).await?;
169 ///
170 /// Ok(())
171 /// }
172 /// ```
173 ///
174 /// Using a dynamic, run-time scheme
175 ///
176 /// ```no_run
177 /// use std::sync::LazyLock;
178 /// use serde::{Serialize, Deserialize};
179 /// use surrealdb::Surreal;
180 /// use surrealdb::engine::any::Any;
181 /// use surrealdb::opt::auth::Root;
182 ///
183 /// // Creates a new static instance of the client
184 /// static DB: LazyLock<Surreal<Any>> = LazyLock::new(Surreal::init);
185 ///
186 /// #[derive(Serialize, Deserialize)]
187 /// struct Person {
188 /// name: String,
189 /// }
190 ///
191 /// #[tokio::main]
192 /// async fn main() -> surrealdb::Result<()> {
193 /// // Connect to the database
194 /// DB.connect("ws://localhost:8000").await?;
195 ///
196 /// // Log into the database
197 /// DB.signin(Root {
198 /// username: "root",
199 /// password: "root",
200 /// }).await?;
201 ///
202 /// // Select a namespace/database
203 /// DB.use_ns("namespace").use_db("database").await?;
204 ///
205 /// // Create or update a specific record
206 /// let tobie: Option<Person> = DB.update(("person", "tobie"))
207 /// .content(Person {
208 /// name: "Tobie".into(),
209 /// }).await?;
210 ///
211 /// Ok(())
212 /// }
213 /// ```
214 pub fn init() -> Self {
215 Self {
216 router: Arc::new(OnceLock::new()),
217 waiter: Arc::new(watch::channel(None)),
218 engine: PhantomData,
219 }
220 }
221
222 /// Connects to a local or remote database endpoint
223 ///
224 /// # Examples
225 ///
226 /// ```no_run
227 /// use surrealdb::Surreal;
228 /// use surrealdb::engine::remote::ws::{Ws, Wss};
229 ///
230 /// # #[tokio::main]
231 /// # async fn main() -> surrealdb::Result<()> {
232 /// // Connect to a local endpoint
233 /// let db = Surreal::new::<Ws>("localhost:8000").await?;
234 ///
235 /// // Connect to a remote endpoint
236 /// let db = Surreal::new::<Wss>("cloud.surrealdb.com").await?;
237 /// #
238 /// # Ok(())
239 /// # }
240 /// ```
241 pub fn new<P>(address: impl IntoEndpoint<P, Client = C>) -> Connect<C, Self> {
242 Connect {
243 router: Arc::new(OnceLock::new()),
244 engine: PhantomData,
245 address: address.into_endpoint(),
246 capacity: 0,
247 waiter: Arc::new(watch::channel(None)),
248 response_type: PhantomData,
249 }
250 }
251
252 #[doc(hidden)] // Not supported yet
253 pub fn transaction(self) -> Begin<C> {
254 Begin {
255 client: self,
256 }
257 }
258
259 /// Switch to a specific namespace
260 ///
261 /// # Examples
262 ///
263 /// ```no_run
264 /// # #[tokio::main]
265 /// # async fn main() -> surrealdb::Result<()> {
266 /// # let db = surrealdb::engine::any::connect("mem://").await?;
267 /// db.use_ns("namespace").await?;
268 /// # Ok(())
269 /// # }
270 /// ```
271 pub fn use_ns(&self, ns: impl Into<String>) -> UseNs<C> {
272 UseNs {
273 client: Cow::Borrowed(self),
274 ns: ns.into(),
275 }
276 }
277
278 /// Switch to a specific database
279 ///
280 /// # Examples
281 ///
282 /// ```no_run
283 /// # #[tokio::main]
284 /// # async fn main() -> surrealdb::Result<()> {
285 /// # let db = surrealdb::engine::any::connect("mem://").await?;
286 /// db.use_db("database").await?;
287 /// # Ok(())
288 /// # }
289 /// ```
290 pub fn use_db(&self, db: impl Into<String>) -> UseDb<C> {
291 UseDb {
292 client: Cow::Borrowed(self),
293 ns: None,
294 db: db.into(),
295 }
296 }
297
298 /// Assigns a value as a parameter for this connection
299 ///
300 /// # Examples
301 ///
302 /// ```no_run
303 /// use serde::Serialize;
304 ///
305 /// #[derive(Serialize)]
306 /// struct Name {
307 /// first: String,
308 /// last: String,
309 /// }
310 ///
311 /// # #[tokio::main]
312 /// # async fn main() -> surrealdb::Result<()> {
313 /// # let db = surrealdb::engine::any::connect("mem://").await?;
314 /// #
315 /// // Assign the variable on the connection
316 /// db.set("name", Name {
317 /// first: "Tobie".into(),
318 /// last: "Morgan Hitchcock".into(),
319 /// }).await?;
320 ///
321 /// // Use the variable in a subsequent query
322 /// db.query("CREATE person SET name = $name").await?;
323 ///
324 /// // Use the variable in a subsequent query
325 /// db.query("SELECT * FROM person WHERE name.first = $name.first").await?;
326 /// #
327 /// # Ok(())
328 /// # }
329 /// ```
330 pub fn set(&self, key: impl Into<String>, value: impl Serialize + 'static) -> Set<C> {
331 Set {
332 client: Cow::Borrowed(self),
333 key: key.into(),
334 value: to_core_value(value).map_err(Into::into),
335 }
336 }
337
338 /// Removes a parameter from this connection
339 ///
340 /// # Examples
341 ///
342 /// ```no_run
343 /// use serde::Serialize;
344 ///
345 /// #[derive(Serialize)]
346 /// struct Name {
347 /// first: String,
348 /// last: String,
349 /// }
350 ///
351 /// # #[tokio::main]
352 /// # async fn main() -> surrealdb::Result<()> {
353 /// # let db = surrealdb::engine::any::connect("mem://").await?;
354 /// #
355 /// // Assign the variable on the connection
356 /// db.set("name", Name {
357 /// first: "Tobie".into(),
358 /// last: "Morgan Hitchcock".into(),
359 /// }).await?;
360 ///
361 /// // Use the variable in a subsequent query
362 /// db.query("CREATE person SET name = $name").await?;
363 ///
364 /// // Remove the variable from the connection
365 /// db.unset("name").await?;
366 /// #
367 /// # Ok(())
368 /// # }
369 /// ```
370 pub fn unset(&self, key: impl Into<String>) -> Unset<C> {
371 Unset {
372 client: Cow::Borrowed(self),
373 key: key.into(),
374 }
375 }
376
377 /// Signs up a user with a specific record access method
378 ///
379 /// # Examples
380 ///
381 /// ```no_run
382 /// use serde::Serialize;
383 /// use surrealdb::sql;
384 /// use surrealdb::opt::auth::Root;
385 /// use surrealdb::opt::auth::Record;
386 ///
387 /// #[derive(Debug, Serialize)]
388 /// struct AuthParams {
389 /// email: String,
390 /// password: String,
391 /// }
392 ///
393 /// # #[tokio::main]
394 /// # async fn main() -> surrealdb::Result<()> {
395 /// # let db = surrealdb::engine::any::connect("mem://").await?;
396 /// #
397 /// // Sign in as root
398 /// db.signin(Root {
399 /// username: "root",
400 /// password: "root",
401 /// })
402 /// .await?;
403 ///
404 /// // Select the namespace/database to use
405 /// db.use_ns("namespace").use_db("database").await?;
406 ///
407 /// // Define the user record access
408 /// let sql = r#"
409 /// DEFINE ACCESS user_access ON DATABASE TYPE RECORD DURATION 24h
410 /// SIGNUP ( CREATE user SET email = $email, password = crypto::argon2::generate($password) )
411 /// SIGNIN ( SELECT * FROM user WHERE email = $email AND crypto::argon2::compare(password, $password) )
412 /// "#;
413 /// db.query(sql).await?.check()?;
414 ///
415 /// // Sign a user up
416 /// db.signup(Record {
417 /// namespace: "namespace",
418 /// database: "database",
419 /// access: "user_access",
420 /// params: AuthParams {
421 /// email: "john.doe@example.com".into(),
422 /// password: "password123".into(),
423 /// },
424 /// }).await?;
425 /// #
426 /// # Ok(())
427 /// # }
428 /// ```
429 pub fn signup<R>(&self, credentials: impl Credentials<auth::Signup, R>) -> Signup<C, R> {
430 Signup {
431 client: Cow::Borrowed(self),
432 credentials: Serializer::new().serialize(credentials),
433 response_type: PhantomData,
434 }
435 }
436
437 /// Signs this connection in to a specific authentication level
438 ///
439 /// # Examples
440 ///
441 /// Namespace signin
442 ///
443 /// ```no_run
444 /// use surrealdb::sql;
445 /// use surrealdb::opt::auth::Root;
446 /// use surrealdb::opt::auth::Namespace;
447 ///
448 /// # #[tokio::main]
449 /// # async fn main() -> surrealdb::Result<()> {
450 /// # let db = surrealdb::engine::any::connect("mem://").await?;
451 /// #
452 /// // Sign in as root
453 /// db.signin(Root {
454 /// username: "root",
455 /// password: "root",
456 /// })
457 /// .await?;
458 ///
459 /// // Select the namespace/database to use
460 /// db.use_ns("namespace").use_db("database").await?;
461 ///
462 /// // Define the user
463 /// let sql = "DEFINE USER johndoe ON NAMESPACE PASSWORD 'password123'";
464 /// db.query(sql).await?.check()?;
465 ///
466 /// // Sign a user in
467 /// db.signin(Namespace {
468 /// namespace: "namespace",
469 /// username: "johndoe",
470 /// password: "password123",
471 /// }).await?;
472 /// #
473 /// # Ok(())
474 /// # }
475 /// ```
476 ///
477 /// Database signin
478 ///
479 /// ```no_run
480 /// use surrealdb::sql;
481 /// use surrealdb::opt::auth::Root;
482 /// use surrealdb::opt::auth::Database;
483 ///
484 /// # #[tokio::main]
485 /// # async fn main() -> surrealdb::Result<()> {
486 /// # let db = surrealdb::engine::any::connect("mem://").await?;
487 /// #
488 /// // Sign in as root
489 /// db.signin(Root {
490 /// username: "root",
491 /// password: "root",
492 /// })
493 /// .await?;
494 ///
495 /// // Select the namespace/database to use
496 /// db.use_ns("namespace").use_db("database").await?;
497 ///
498 /// // Define the user
499 /// let sql = "DEFINE USER johndoe ON DATABASE PASSWORD 'password123'";
500 /// db.query(sql).await?.check()?;
501 ///
502 /// // Sign a user in
503 /// db.signin(Database {
504 /// namespace: "namespace",
505 /// database: "database",
506 /// username: "johndoe",
507 /// password: "password123",
508 /// }).await?;
509 /// #
510 /// # Ok(())
511 /// # }
512 /// ```
513 ///
514 /// Record signin
515 ///
516 /// ```no_run
517 /// use serde::Serialize;
518 /// use surrealdb::opt::auth::Root;
519 /// use surrealdb::opt::auth::Record;
520 ///
521 /// #[derive(Debug, Serialize)]
522 /// struct AuthParams {
523 /// email: String,
524 /// password: String,
525 /// }
526 ///
527 /// # #[tokio::main]
528 /// # async fn main() -> surrealdb::Result<()> {
529 /// # let db = surrealdb::engine::any::connect("mem://").await?;
530 /// #
531 /// // Select the namespace/database to use
532 /// db.use_ns("namespace").use_db("database").await?;
533 ///
534 /// // Sign a user in
535 /// db.signin(Record {
536 /// namespace: "namespace",
537 /// database: "database",
538 /// access: "user_access",
539 /// params: AuthParams {
540 /// email: "john.doe@example.com".into(),
541 /// password: "password123".into(),
542 /// },
543 /// }).await?;
544 /// #
545 /// # Ok(())
546 /// # }
547 /// ```
548 pub fn signin<R>(&self, credentials: impl Credentials<auth::Signin, R>) -> Signin<C, R> {
549 Signin {
550 client: Cow::Borrowed(self),
551 credentials: Serializer::new().serialize(credentials),
552 response_type: PhantomData,
553 }
554 }
555
556 /// Invalidates the authentication for the current connection
557 ///
558 /// # Examples
559 ///
560 /// ```no_run
561 /// # #[tokio::main]
562 /// # async fn main() -> surrealdb::Result<()> {
563 /// # let db = surrealdb::engine::any::connect("mem://").await?;
564 /// db.invalidate().await?;
565 /// # Ok(())
566 /// # }
567 /// ```
568 pub fn invalidate(&self) -> Invalidate<C> {
569 Invalidate {
570 client: Cow::Borrowed(self),
571 }
572 }
573
574 /// Authenticates the current connection with a JWT token
575 ///
576 /// # Examples
577 ///
578 /// ```no_run
579 /// # #[tokio::main]
580 /// # async fn main() -> surrealdb::Result<()> {
581 /// # let db = surrealdb::engine::any::connect("mem://").await?;
582 /// # let token = String::new();
583 /// db.authenticate(token).await?;
584 /// # Ok(())
585 /// # }
586 /// ```
587 pub fn authenticate(&self, token: impl Into<Jwt>) -> Authenticate<C> {
588 Authenticate {
589 client: Cow::Borrowed(self),
590 token: token.into(),
591 }
592 }
593
594 /// Runs a set of SurrealQL statements against the database
595 ///
596 /// # Examples
597 ///
598 /// ```no_run
599 /// use surrealdb::sql;
600 ///
601 /// # #[derive(serde::Deserialize)]
602 /// # struct Person;
603 /// # #[tokio::main]
604 /// # async fn main() -> surrealdb::Result<()> {
605 /// # let db = surrealdb::engine::any::connect("mem://").await?;
606 /// #
607 /// // Select the namespace/database to use
608 /// db.use_ns("namespace").use_db("database").await?;
609 ///
610 /// // Run queries
611 /// let mut result = db
612 /// .query("CREATE person")
613 /// .query("SELECT * FROM type::table($table)")
614 /// .bind(("table", "person"))
615 /// .await?;
616 ///
617 /// // Get the first result from the first query
618 /// let created: Option<Person> = result.take(0)?;
619 ///
620 /// // Get all of the results from the second query
621 /// let people: Vec<Person> = result.take(1)?;
622 ///
623 /// #[derive(serde::Deserialize)]
624 /// struct Country {
625 /// name: String
626 /// }
627 ///
628 /// // The .take() method can be used for error handling
629 ///
630 /// // If the table has no defined schema, this query will
631 /// // create a `country` on the SurrealDB side, but...
632 /// let mut result = db
633 /// .query("CREATE country")
634 /// .await?;
635 ///
636 /// // It won't deserialize into a Country struct
637 /// if let Err(e) = result.take::<Option<Country>>(0) {
638 /// println!("Failed to make a country: {e:#?}");
639 /// assert!(e.to_string().contains("missing field `name`"));
640 /// }
641 /// #
642 /// # Ok(())
643 /// # }
644 /// ```
645 pub fn query(&self, query: impl opt::IntoQuery) -> Query<C> {
646 let inner = query.into_query().map(|x| ValidQuery {
647 client: Cow::Borrowed(self),
648 query: x,
649 bindings: Default::default(),
650 register_live_queries: true,
651 });
652
653 Query {
654 inner,
655 }
656 }
657
658 /// Selects all records in a table, or a specific record
659 ///
660 /// # Examples
661 ///
662 /// ```no_run
663 /// # use futures::StreamExt;
664 /// # use surrealdb::opt::Resource;
665 /// # #[derive(serde::Deserialize)]
666 /// # struct Person;
667 /// #
668 /// # #[tokio::main]
669 /// # async fn main() -> surrealdb::Result<()> {
670 /// # let db = surrealdb::engine::any::connect("mem://").await?;
671 /// #
672 /// // Select the namespace/database to use
673 /// db.use_ns("namespace").use_db("database").await?;
674 ///
675 /// // Select all records from a table
676 /// let people: Vec<Person> = db.select("person").await?;
677 ///
678 /// // Select a range of records from a table
679 /// let people: Vec<Person> = db.select("person").range("jane".."john").await?;
680 ///
681 /// // Select a specific record from a table
682 /// let person: Option<Person> = db.select(("person", "h5wxrf2ewk8xjxosxtyc")).await?;
683 ///
684 /// // To listen for updates as they happen on a record, a range of records
685 /// // or entire table use a live query. This is done by simply calling `.live()`
686 /// // after this method. That gives you a stream of notifications you can listen on.
687 /// # let resource = Resource::from("person");
688 /// let mut stream = db.select(resource).live().await?;
689 ///
690 /// while let Some(notification) = stream.next().await {
691 /// // Use the notification
692 /// }
693 /// #
694 /// # Ok(())
695 /// # }
696 /// ```
697 pub fn select<O>(&self, resource: impl IntoResource<O>) -> Select<C, O> {
698 Select {
699 client: Cow::Borrowed(self),
700 resource: resource.into_resource(),
701 response_type: PhantomData,
702 query_type: PhantomData,
703 }
704 }
705
706 /// Creates a record in the database
707 ///
708 /// # Examples
709 ///
710 /// ```no_run
711 /// use serde::Serialize;
712 ///
713 /// # #[derive(serde::Deserialize)]
714 /// # struct Person;
715 /// #
716 /// #[derive(Serialize)]
717 /// struct Settings {
718 /// active: bool,
719 /// marketing: bool,
720 /// }
721 ///
722 /// #[derive(Serialize)]
723 /// struct User {
724 /// name: &'static str,
725 /// settings: Settings,
726 /// }
727 ///
728 /// # #[tokio::main]
729 /// # async fn main() -> surrealdb::Result<()> {
730 /// # let db = surrealdb::engine::any::connect("mem://").await?;
731 /// #
732 /// // Select the namespace/database to use
733 /// db.use_ns("namespace").use_db("database").await?;
734 ///
735 /// // Create a record with a random ID
736 /// let person: Option<Person> = db.create("person").await?;
737 ///
738 /// // Create a record with a specific ID
739 /// let record: Option<Person> = db.create(("person", "tobie"))
740 /// .content(User {
741 /// name: "Tobie",
742 /// settings: Settings {
743 /// active: true,
744 /// marketing: true,
745 /// },
746 /// })
747 /// .await?;
748 /// #
749 /// # Ok(())
750 /// # }
751 /// ```
752 pub fn create<R>(&self, resource: impl IntoResource<R>) -> Create<C, R> {
753 Create {
754 client: Cow::Borrowed(self),
755 resource: resource.into_resource(),
756 response_type: PhantomData,
757 }
758 }
759
760 /// Insert a record or records into a table
761 ///
762 /// # Examples
763 ///
764 /// ```no_run
765 /// use serde::{Serialize, Deserialize};
766 /// use surrealdb::sql;
767 ///
768 /// # #[derive(Deserialize)]
769 /// # struct Person;
770 /// #
771 /// #[derive(Serialize)]
772 /// struct Settings {
773 /// active: bool,
774 /// marketing: bool,
775 /// }
776 ///
777 /// #[derive(Serialize)]
778 /// struct User<'a> {
779 /// name: &'a str,
780 /// settings: Settings,
781 /// }
782 ///
783 /// # #[tokio::main]
784 /// # async fn main() -> surrealdb::Result<()> {
785 /// # let db = surrealdb::engine::any::connect("mem://").await?;
786 /// #
787 /// // Select the namespace/database to use
788 /// db.use_ns("namespace").use_db("database").await?;
789 ///
790 /// // Insert a record with a specific ID
791 /// let person: Option<Person> = db.insert(("person", "tobie"))
792 /// .content(User {
793 /// name: "Tobie",
794 /// settings: Settings {
795 /// active: true,
796 /// marketing: true,
797 /// },
798 /// })
799 /// .await?;
800 ///
801 /// // Insert multiple records into the table
802 /// let people: Vec<Person> = db.insert("person")
803 /// .content(vec![
804 /// User {
805 /// name: "Tobie",
806 /// settings: Settings {
807 /// active: true,
808 /// marketing: false,
809 /// },
810 /// },
811 /// User {
812 /// name: "Jaime",
813 /// settings: Settings {
814 /// active: true,
815 /// marketing: true,
816 /// },
817 /// },
818 /// ])
819 /// .await?;
820 ///
821 /// // Insert multiple records with pre-defined IDs
822 /// #[derive(Serialize)]
823 /// struct UserWithId<'a> {
824 /// id: sql::Thing,
825 /// name: &'a str,
826 /// settings: Settings,
827 /// }
828 ///
829 /// let people: Vec<Person> = db.insert("person")
830 /// .content(vec![
831 /// UserWithId {
832 /// id: sql::thing("person:tobie")?,
833 /// name: "Tobie",
834 /// settings: Settings {
835 /// active: true,
836 /// marketing: false,
837 /// },
838 /// },
839 /// UserWithId {
840 /// id: sql::thing("person:jaime")?,
841 /// name: "Jaime",
842 /// settings: Settings {
843 /// active: true,
844 /// marketing: true,
845 /// },
846 /// },
847 /// ])
848 /// .await?;
849 ///
850 /// // Insert multiple records into different tables
851 /// #[derive(Serialize)]
852 /// struct WithId<'a> {
853 /// id: sql::Thing,
854 /// name: &'a str,
855 /// }
856 ///
857 /// let people: Vec<Person> = db.insert(())
858 /// .content(vec![
859 /// WithId {
860 /// id: sql::thing("person:tobie")?,
861 /// name: "Tobie",
862 /// },
863 /// WithId {
864 /// id: sql::thing("company:surrealdb")?,
865 /// name: "SurrealDB",
866 /// },
867 /// ])
868 /// .await?;
869 ///
870 ///
871 /// // Insert relations
872 /// #[derive(Serialize, Deserialize)]
873 /// struct Founded {
874 /// #[serde(rename = "in")]
875 /// founder: sql::Thing,
876 /// #[serde(rename = "out")]
877 /// company: sql::Thing,
878 /// }
879 ///
880 /// let founded: Vec<Founded> = db.insert("founded")
881 /// .relation(vec![
882 /// Founded {
883 /// founder: sql::thing("person:tobie")?,
884 /// company: sql::thing("company:surrealdb")?,
885 /// },
886 /// Founded {
887 /// founder: sql::thing("person:jaime")?,
888 /// company: sql::thing("company:surrealdb")?,
889 /// },
890 /// ])
891 /// .await?;
892 ///
893 /// #
894 /// # Ok(())
895 /// # }
896 /// ```
897 pub fn insert<O>(&self, resource: impl IntoResource<O>) -> Insert<C, O> {
898 Insert {
899 client: Cow::Borrowed(self),
900 resource: resource.into_resource(),
901 response_type: PhantomData,
902 }
903 }
904
905 /// Updates all records in a table, or a specific record
906 ///
907 /// # Examples
908 ///
909 /// Replace the current document / record data with the specified data.
910 ///
911 /// ```no_run
912 /// use serde::Serialize;
913 ///
914 /// # #[derive(serde::Deserialize)]
915 /// # struct Person;
916 /// #
917 /// #[derive(Serialize)]
918 /// struct Settings {
919 /// active: bool,
920 /// marketing: bool,
921 /// }
922 ///
923 /// #[derive(Serialize)]
924 /// struct User {
925 /// name: &'static str,
926 /// settings: Settings,
927 /// }
928 ///
929 /// # #[tokio::main]
930 /// # async fn main() -> surrealdb::Result<()> {
931 /// # let db = surrealdb::engine::any::connect("mem://").await?;
932 /// #
933 /// // Select the namespace/database to use
934 /// db.use_ns("namespace").use_db("database").await?;
935 ///
936 /// // Update all records in a table
937 /// let people: Vec<Person> = db.upsert("person").await?;
938 ///
939 /// // Update a record with a specific ID
940 /// let person: Option<Person> = db.upsert(("person", "tobie"))
941 /// .content(User {
942 /// name: "Tobie",
943 /// settings: Settings {
944 /// active: true,
945 /// marketing: true,
946 /// },
947 /// })
948 /// .await?;
949 /// #
950 /// # Ok(())
951 /// # }
952 /// ```
953 ///
954 /// Merge the current document / record data with the specified data.
955 ///
956 /// ```no_run
957 /// use serde::Serialize;
958 /// use time::OffsetDateTime;
959 ///
960 /// # #[derive(serde::Deserialize)]
961 /// # struct Person;
962 /// #
963 /// #[derive(Serialize)]
964 /// struct UpdatedAt {
965 /// updated_at: OffsetDateTime,
966 /// }
967 ///
968 /// #[derive(Serialize)]
969 /// struct Settings {
970 /// active: bool,
971 /// }
972 ///
973 /// #[derive(Serialize)]
974 /// struct User {
975 /// updated_at: OffsetDateTime,
976 /// settings: Settings,
977 /// }
978 ///
979 /// # #[tokio::main]
980 /// # async fn main() -> surrealdb::Result<()> {
981 /// # let db = surrealdb::engine::any::connect("mem://").await?;
982 /// #
983 /// // Select the namespace/database to use
984 /// db.use_ns("namespace").use_db("database").await?;
985 ///
986 /// // Update all records in a table
987 /// let people: Vec<Person> = db.upsert("person")
988 /// .merge(UpdatedAt {
989 /// updated_at: OffsetDateTime::now_utc(),
990 /// })
991 /// .await?;
992 ///
993 /// // Update a record with a specific ID
994 /// let person: Option<Person> = db.upsert(("person", "tobie"))
995 /// .merge(User {
996 /// updated_at: OffsetDateTime::now_utc(),
997 /// settings: Settings {
998 /// active: true,
999 /// },
1000 /// })
1001 /// .await?;
1002 /// #
1003 /// # Ok(())
1004 /// # }
1005 /// ```
1006 ///
1007 /// Apply [JSON Patch](https://jsonpatch.com) changes to all records, or a specific record, in the database.
1008 ///
1009 /// ```no_run
1010 /// use serde::Serialize;
1011 /// use surrealdb::opt::PatchOp;
1012 /// use time::OffsetDateTime;
1013 ///
1014 /// # #[derive(serde::Deserialize)]
1015 /// # struct Person;
1016 /// #
1017 /// #[derive(Serialize)]
1018 /// struct UpdatedAt {
1019 /// updated_at: OffsetDateTime,
1020 /// }
1021 ///
1022 /// #[derive(Serialize)]
1023 /// struct Settings {
1024 /// active: bool,
1025 /// }
1026 ///
1027 /// #[derive(Serialize)]
1028 /// struct User {
1029 /// updated_at: OffsetDateTime,
1030 /// settings: Settings,
1031 /// }
1032 ///
1033 /// # #[tokio::main]
1034 /// # async fn main() -> surrealdb::Result<()> {
1035 /// # let db = surrealdb::engine::any::connect("mem://").await?;
1036 /// #
1037 /// // Select the namespace/database to use
1038 /// db.use_ns("namespace").use_db("database").await?;
1039 ///
1040 /// // Update all records in a table
1041 /// let people: Vec<Person> = db.upsert("person")
1042 /// .patch(PatchOp::replace("/created_at", OffsetDateTime::now_utc()))
1043 /// .await?;
1044 ///
1045 /// // Update a record with a specific ID
1046 /// let person: Option<Person> = db.upsert(("person", "tobie"))
1047 /// .patch(PatchOp::replace("/settings/active", false))
1048 /// .patch(PatchOp::add("/tags", ["developer", "engineer"]))
1049 /// .patch(PatchOp::remove("/temp"))
1050 /// .await?;
1051 /// #
1052 /// # Ok(())
1053 /// # }
1054 /// ```
1055 pub fn upsert<O>(&self, resource: impl IntoResource<O>) -> Upsert<C, O> {
1056 Upsert {
1057 client: Cow::Borrowed(self),
1058 resource: resource.into_resource(),
1059 response_type: PhantomData,
1060 }
1061 }
1062
1063 /// Updates all records in a table, or a specific record
1064 ///
1065 /// # Examples
1066 ///
1067 /// Replace the current document / record data with the specified data.
1068 ///
1069 /// ```no_run
1070 /// use serde::Serialize;
1071 ///
1072 /// # #[derive(serde::Deserialize)]
1073 /// # struct Person;
1074 /// #
1075 /// #[derive(Serialize)]
1076 /// struct Settings {
1077 /// active: bool,
1078 /// marketing: bool,
1079 /// }
1080 ///
1081 /// #[derive(Serialize)]
1082 /// struct User {
1083 /// name: &'static str,
1084 /// settings: Settings,
1085 /// }
1086 ///
1087 /// # #[tokio::main]
1088 /// # async fn main() -> surrealdb::Result<()> {
1089 /// # let db = surrealdb::engine::any::connect("mem://").await?;
1090 /// #
1091 /// // Select the namespace/database to use
1092 /// db.use_ns("namespace").use_db("database").await?;
1093 ///
1094 /// // Update all records in a table
1095 /// let people: Vec<Person> = db.update("person").await?;
1096 ///
1097 /// // Update a record with a specific ID
1098 /// let person: Option<Person> = db.update(("person", "tobie"))
1099 /// .content(User {
1100 /// name: "Tobie",
1101 /// settings: Settings {
1102 /// active: true,
1103 /// marketing: true,
1104 /// },
1105 /// })
1106 /// .await?;
1107 /// #
1108 /// # Ok(())
1109 /// # }
1110 /// ```
1111 ///
1112 /// Merge the current document / record data with the specified data.
1113 ///
1114 /// ```no_run
1115 /// use serde::Serialize;
1116 /// use time::OffsetDateTime;
1117 ///
1118 /// # #[derive(serde::Deserialize)]
1119 /// # struct Person;
1120 /// #
1121 /// #[derive(Serialize)]
1122 /// struct UpdatedAt {
1123 /// updated_at: OffsetDateTime,
1124 /// }
1125 ///
1126 /// #[derive(Serialize)]
1127 /// struct Settings {
1128 /// active: bool,
1129 /// }
1130 ///
1131 /// #[derive(Serialize)]
1132 /// struct User {
1133 /// updated_at: OffsetDateTime,
1134 /// settings: Settings,
1135 /// }
1136 ///
1137 /// # #[tokio::main]
1138 /// # async fn main() -> surrealdb::Result<()> {
1139 /// # let db = surrealdb::engine::any::connect("mem://").await?;
1140 /// #
1141 /// // Select the namespace/database to use
1142 /// db.use_ns("namespace").use_db("database").await?;
1143 ///
1144 /// // Update all records in a table
1145 /// let people: Vec<Person> = db.update("person")
1146 /// .merge(UpdatedAt {
1147 /// updated_at: OffsetDateTime::now_utc(),
1148 /// })
1149 /// .await?;
1150 ///
1151 /// // Update a record with a specific ID
1152 /// let person: Option<Person> = db.update(("person", "tobie"))
1153 /// .merge(User {
1154 /// updated_at: OffsetDateTime::now_utc(),
1155 /// settings: Settings {
1156 /// active: true,
1157 /// },
1158 /// })
1159 /// .await?;
1160 /// #
1161 /// # Ok(())
1162 /// # }
1163 /// ```
1164 ///
1165 /// Apply [JSON Patch](https://jsonpatch.com) changes to all records, or a specific record, in the database.
1166 ///
1167 /// ```no_run
1168 /// use serde::Serialize;
1169 /// use surrealdb::opt::PatchOp;
1170 /// use time::OffsetDateTime;
1171 ///
1172 /// # #[derive(serde::Deserialize)]
1173 /// # struct Person;
1174 /// #
1175 /// #[derive(Serialize)]
1176 /// struct UpdatedAt {
1177 /// updated_at: OffsetDateTime,
1178 /// }
1179 ///
1180 /// #[derive(Serialize)]
1181 /// struct Settings {
1182 /// active: bool,
1183 /// }
1184 ///
1185 /// #[derive(Serialize)]
1186 /// struct User {
1187 /// updated_at: OffsetDateTime,
1188 /// settings: Settings,
1189 /// }
1190 ///
1191 /// # #[tokio::main]
1192 /// # async fn main() -> surrealdb::Result<()> {
1193 /// # let db = surrealdb::engine::any::connect("mem://").await?;
1194 /// #
1195 /// // Select the namespace/database to use
1196 /// db.use_ns("namespace").use_db("database").await?;
1197 ///
1198 /// // Update all records in a table
1199 /// let people: Vec<Person> = db.update("person")
1200 /// .patch(PatchOp::replace("/created_at", OffsetDateTime::now_utc()))
1201 /// .await?;
1202 ///
1203 /// // Update a record with a specific ID
1204 /// let person: Option<Person> = db.update(("person", "tobie"))
1205 /// .patch(PatchOp::replace("/settings/active", false))
1206 /// .patch(PatchOp::add("/tags", ["developer", "engineer"]))
1207 /// .patch(PatchOp::remove("/temp"))
1208 /// .await?;
1209 /// #
1210 /// # Ok(())
1211 /// # }
1212 /// ```
1213 pub fn update<O>(&self, resource: impl IntoResource<O>) -> Update<C, O> {
1214 Update {
1215 client: Cow::Borrowed(self),
1216 resource: resource.into_resource(),
1217 response_type: PhantomData,
1218 }
1219 }
1220
1221 /// Deletes all records, or a specific record
1222 ///
1223 /// # Examples
1224 ///
1225 /// ```no_run
1226 /// # #[derive(serde::Deserialize)]
1227 /// # struct Person;
1228 /// #
1229 /// # #[tokio::main]
1230 /// # async fn main() -> surrealdb::Result<()> {
1231 /// # let db = surrealdb::engine::any::connect("mem://").await?;
1232 /// #
1233 /// // Select the namespace/database to use
1234 /// db.use_ns("namespace").use_db("database").await?;
1235 ///
1236 /// // Delete all records from a table
1237 /// let people: Vec<Person> = db.delete("person").await?;
1238 ///
1239 /// // Delete a specific record from a table
1240 /// let person: Option<Person> = db.delete(("person", "h5wxrf2ewk8xjxosxtyc")).await?;
1241 /// #
1242 /// # Ok(())
1243 /// # }
1244 /// ```
1245 pub fn delete<O>(&self, resource: impl IntoResource<O>) -> Delete<C, O> {
1246 Delete {
1247 client: Cow::Borrowed(self),
1248 resource: resource.into_resource(),
1249 response_type: PhantomData,
1250 }
1251 }
1252
1253 /// Returns the version of the server
1254 ///
1255 /// # Examples
1256 ///
1257 /// ```no_run
1258 /// # #[tokio::main]
1259 /// # async fn main() -> surrealdb::Result<()> {
1260 /// # let db = surrealdb::engine::any::connect("mem://").await?;
1261 /// let version = db.version().await?;
1262 /// # Ok(())
1263 /// # }
1264 /// ```
1265 pub fn version(&self) -> Version<C> {
1266 Version {
1267 client: Cow::Borrowed(self),
1268 }
1269 }
1270
1271 /// Runs a function
1272 ///
1273 /// # Examples
1274 ///
1275 /// ```no_run
1276 /// # #[tokio::main]
1277 /// # async fn main() -> surrealdb::Result<()> {
1278 /// # let db = surrealdb::engine::any::connect("mem://").await?;
1279 /// // Specify no args by not calling `.args()`
1280 /// let foo = db.run("fn::foo").await?; // fn::foo()
1281 /// // A single value will be turned into one argument
1282 /// let bar = db.run("fn::bar").args(42).await?; // fn::bar(42)
1283 /// // Arrays are treated as single arguments
1284 /// let count = db.run("count").args(vec![1,2,3]).await?;
1285 /// // Specify multiple args using a tuple
1286 /// let two = db.run("math::log").args((100, 10)).await?; // math::log(100, 10)
1287 ///
1288 /// # Ok(())
1289 /// # }
1290 /// ```
1291 ///
1292 pub fn run<R>(&self, function: impl IntoFn) -> Run<C, R> {
1293 Run {
1294 client: Cow::Borrowed(self),
1295 function: function.into_fn(),
1296 args: Ok(serde_content::Value::Tuple(vec![])),
1297 response_type: PhantomData,
1298 }
1299 }
1300
1301 /// Checks whether the server is healthy or not
1302 ///
1303 /// # Examples
1304 ///
1305 /// ```no_run
1306 /// # #[tokio::main]
1307 /// # async fn main() -> surrealdb::Result<()> {
1308 /// # let db = surrealdb::engine::any::connect("mem://").await?;
1309 /// db.health().await?;
1310 /// # Ok(())
1311 /// # }
1312 /// ```
1313 pub fn health(&self) -> Health<C> {
1314 Health {
1315 client: Cow::Borrowed(self),
1316 }
1317 }
1318
1319 /// Wait for the selected event to happen before proceeding
1320 pub async fn wait_for(&self, event: WaitFor) {
1321 let mut rx = self.waiter.0.subscribe();
1322 rx.wait_for(|current| match current {
1323 // The connection hasn't been initialised yet.
1324 None => false,
1325 // The connection has been initialised. Only the connection even matches.
1326 Some(WaitFor::Connection) => matches!(event, WaitFor::Connection),
1327 // The database has been selected. Connection and database events both match.
1328 Some(WaitFor::Database) => matches!(event, WaitFor::Connection | WaitFor::Database),
1329 })
1330 .await
1331 .ok();
1332 }
1333
1334 /// Dumps the database contents to a file
1335 ///
1336 /// # Support
1337 ///
1338 /// Currently only supported by HTTP and the local engines. *Not* supported on WebAssembly.
1339 ///
1340 /// # Examples
1341 ///
1342 /// ```no_run
1343 /// # use futures::StreamExt;
1344 /// # #[tokio::main]
1345 /// # async fn main() -> surrealdb::Result<()> {
1346 /// # let db = surrealdb::engine::any::connect("mem://").await?;
1347 /// // Select the namespace/database to use
1348 /// db.use_ns("namespace").use_db("database").await?;
1349 ///
1350 /// // Export to a file
1351 /// db.export("backup.sql").await?;
1352 ///
1353 /// // Export to a stream of bytes
1354 /// let mut backup = db.export(()).await?;
1355 /// while let Some(result) = backup.next().await {
1356 /// match result {
1357 /// Ok(bytes) => {
1358 /// // Do something with the bytes received...
1359 /// }
1360 /// Err(error) => {
1361 /// // Handle the export error
1362 /// }
1363 /// }
1364 /// }
1365 /// # Ok(())
1366 /// # }
1367 /// ```
1368 pub fn export<R>(&self, target: impl IntoExportDestination<R>) -> Export<C, R> {
1369 Export {
1370 client: Cow::Borrowed(self),
1371 target: target.into_export_destination(),
1372 ml_config: None,
1373 response: PhantomData,
1374 export_type: PhantomData,
1375 }
1376 }
1377
1378 /// Restores the database from a file
1379 ///
1380 /// # Support
1381 ///
1382 /// Currently only supported by HTTP and the local engines. *Not* supported on WebAssembly.
1383 ///
1384 /// # Examples
1385 ///
1386 /// ```no_run
1387 /// # #[tokio::main]
1388 /// # async fn main() -> surrealdb::Result<()> {
1389 /// # let db = surrealdb::engine::any::connect("mem://").await?;
1390 /// // Select the namespace/database to use
1391 /// db.use_ns("namespace").use_db("database").await?;
1392 ///
1393 /// db.import("backup.sql").await?;
1394 /// # Ok(())
1395 /// # }
1396 /// ```
1397 pub fn import<P>(&self, file: P) -> Import<C>
1398 where
1399 P: AsRef<Path>,
1400 {
1401 Import {
1402 client: Cow::Borrowed(self),
1403 file: file.as_ref().to_owned(),
1404 is_ml: false,
1405 import_type: PhantomData,
1406 }
1407 }
1408}