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;