1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
//! An asynchronous client for the Cloud Spanner database.
//!
//! # Example
//!
//! ```no_run
//! use spanner_rs::{Client, Error};
//!
//! #[tokio::main]
//! fn main() -> Result<(), Error> {
//! let mut client = Client::configure()
//! .project("my-gcp-project")
//! .instance("my-instance")
//! .database("my-database")
//! .connect()
//! .await?;
//!
//! // assuming the following table:
//! // person(id INT64, name STRING(MAX), data BYTES(MAX))
//! client
//! .read_write()
//! .run(|tx| {
//! tx.execute_update(
//! "INSERT INTO person(id, name, data) VALUES(@id, @name, NULL)",
//! &[("id", &42), ("name", &"ferris")],
//! )
//! })
//! .await?;
//!
//! let result_set = client
//! .read_only()
//! .execute_sql("SELECT * FROM person", &[])
//! .await?;
//!
//! for row in result_set.iter() {
//! let id: u32 = row.get_by_name("id")?;
//! let name: &str = row.get_by_name("name")?;
//! let data: Option<&[u8]> = row.get_by_name("data")?;
//!
//! println!("found person: {} {} {:?}", id, name, data);
//! }
//!
//! Ok(())
//! }
//! ```
//!
//! # Transactions
//!
//! Cloud Spanner [supports](https://cloud.google.com/spanner/docs/transactions) several transaction "modes":
//!
//! * read-only: provides guaranteed consistency between several reads, cannot write;
//! * read-write: the only way to write into Cloud Spanner they use a combination of locking and retries and are typically more expensive;
//! * partitioned DML: these are unsupported by this client at the moment.
//!
//! ## Read Only
//!
//! Reads are done within "single-use" transactions and can be bounded to determine what data is visible to them, see [TimestampBound].
//! Reading is done using [ReadContext] which can be obtained using [Client::read_only()] or [Client::read_only_with_bound()].
//!
//! Example
//! ```rust
//! let result_set = client
//! .read_only()
//! .execute_sql("SELECT COUNT(*) AS people FROM person", &[])
//! .await?;
//! let people: u32 = result_set.iter().next().unwrap().get_by_name("people")?;
//! ```
//!
//! ## Read Write
//!
//! Read / write transactions are done through [TransactionContext] which extends [ReadContext] to allow writes.
//! When a transaction that conflicts with another tries to commit, Cloud Spanner will reject one of them let the client know it may retry.
//! This client encapsulates the necessary retry logic such that applications do not need to implement it themselves.
//!
//! Example:
//! ```rust
//! client.read_write().run(|tx| {
//! // this closure may be invoked more than once
//! Box::pin(async move {
//! // read
//! let rs = tx.execute_sql("...", &[]).await?;
//! // write
//! tx.execute_update("...", &[]).await?;
//! })
//! })
//! ```
pub use crate::client::*;
pub use crate::config::*;
pub(crate) use crate::connection::Connection;
pub use crate::error::Error;
pub use crate::from_spanner::*;
pub use crate::resource::*;
pub use crate::result_set::*;
pub(crate) use crate::session::*;
pub use crate::to_spanner::*;
pub use crate::transaction::TimestampBound;
pub(crate) use crate::transaction::*;
pub use crate::types::*;
pub use crate::value::*;
mod auth;
mod client;
mod config;
mod connection;
mod error;
mod from_spanner;
mod proto;
mod resource;
mod result_set;
mod session;
mod to_spanner;
mod transaction;
mod types;
mod value;