pub struct Client { /* private fields */ }
Expand description
Client is a client for reading and writing data to a Cloud Spanner database. A client is safe to use concurrently, except for its Close method.
Implementations§
Source§impl Client
impl Client
Sourcepub async fn new(
database: impl Into<String>,
config: ClientConfig,
) -> Result<Self, Error>
pub async fn new( database: impl Into<String>, config: ClientConfig, ) -> Result<Self, Error>
new creates a client to a database. A valid database name has the form projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID.
Sourcepub async fn close(self)
pub async fn close(self)
Close closes all the sessions gracefully. This method can be called only once.
Sourcepub async fn single(&self) -> Result<ReadOnlyTransaction, Error>
pub async fn single(&self) -> Result<ReadOnlyTransaction, Error>
single provides a read-only snapshot transaction optimized for the case where only a single read or query is needed. This is more efficient than using read_only_transaction for a single read or query.
use google_cloud_spanner::key::Key;
use google_cloud_spanner::statement::ToKind;
use google_cloud_spanner::client::Client;
#[tokio::main]
async fn run(client: Client) {
let mut tx = client.single().await.unwrap();
let iter1 = tx.read("Guild",&["GuildID", "OwnerUserID"], vec![
Key::new(&"pk1"),
Key::new(&"pk2")
]).await.unwrap();
}
Sourcepub async fn single_with_timestamp_bound(
&self,
tb: TimestampBound,
) -> Result<ReadOnlyTransaction, Error>
pub async fn single_with_timestamp_bound( &self, tb: TimestampBound, ) -> Result<ReadOnlyTransaction, Error>
single provides a read-only snapshot transaction optimized for the case where only a single read or query is needed. This is more efficient than using read_only_transaction for a single read or query.
Sourcepub async fn read_only_transaction(&self) -> Result<ReadOnlyTransaction, Error>
pub async fn read_only_transaction(&self) -> Result<ReadOnlyTransaction, Error>
read_only_transaction returns a ReadOnlyTransaction that can be used for multiple reads from the database.
use google_cloud_spanner::client::{Client, Error};
use google_cloud_spanner::statement::Statement;
use google_cloud_spanner::key::Key;
async fn run(client: Client) -> Result<(), Error>{
let mut tx = client.read_only_transaction().await?;
let mut stmt = Statement::new("SELECT * , \
ARRAY (SELECT AS STRUCT * FROM UserItem WHERE UserId = @Param1 ) AS UserItem, \
ARRAY (SELECT AS STRUCT * FROM UserCharacter WHERE UserId = @Param1 ) AS UserCharacter \
FROM User \
WHERE UserId = @Param1");
stmt.add_param("Param1", user_id);
let mut reader = tx.query(stmt).await?;
let mut data = vec![];
while let Some(row) = reader.next().await? {
let user_id= row.column_by_name::<String>("UserId")?;
let user_items= row.column_by_name::<Vec<model::UserItem>>("UserItem")?;
let user_characters = row.column_by_name::<Vec<model::UserCharacter>>("UserCharacter")?;
data.push(user_id);
}
let mut reader2 = tx.read("User", &["UserId"], vec![
Key::new(&"user-1"),
Key::new(&"user-2")
]).await?;
Ok(())
}
Sourcepub async fn read_only_transaction_with_option(
&self,
options: ReadOnlyTransactionOption,
) -> Result<ReadOnlyTransaction, Error>
pub async fn read_only_transaction_with_option( &self, options: ReadOnlyTransactionOption, ) -> Result<ReadOnlyTransaction, Error>
read_only_transaction returns a ReadOnlyTransaction that can be used for multiple reads from the database.
Sourcepub async fn batch_read_only_transaction(
&self,
) -> Result<BatchReadOnlyTransaction, Error>
pub async fn batch_read_only_transaction( &self, ) -> Result<BatchReadOnlyTransaction, Error>
batch_read_only_transaction returns a BatchReadOnlyTransaction that can be used for partitioned reads or queries from a snapshot of the database. This is useful in batch processing pipelines where one wants to divide the work of reading from the database across multiple machines.
Sourcepub async fn batch_read_only_transaction_with_option(
&self,
options: ReadOnlyTransactionOption,
) -> Result<BatchReadOnlyTransaction, Error>
pub async fn batch_read_only_transaction_with_option( &self, options: ReadOnlyTransactionOption, ) -> Result<BatchReadOnlyTransaction, Error>
batch_read_only_transaction returns a BatchReadOnlyTransaction that can be used for partitioned reads or queries from a snapshot of the database. This is useful in batch processing pipelines where one wants to divide the work of reading from the database across multiple machines.
Sourcepub async fn partitioned_update(&self, stmt: Statement) -> Result<i64, Error>
pub async fn partitioned_update(&self, stmt: Statement) -> Result<i64, Error>
partitioned_update executes a DML statement in parallel across the database, using separate, internal transactions that commit independently. The DML statement must be fully partitionable: it must be expressible as the union of many statements each of which accesses only a single row of the table. The statement should also be idempotent, because it may be applied more than once.
PartitionedUpdate returns an estimated count of the number of rows affected. The actual number of affected rows may be greater than the estimate.
Sourcepub async fn partitioned_update_with_option(
&self,
stmt: Statement,
options: PartitionedUpdateOption,
) -> Result<i64, Error>
pub async fn partitioned_update_with_option( &self, stmt: Statement, options: PartitionedUpdateOption, ) -> Result<i64, Error>
partitioned_update executes a DML statement in parallel across the database, using separate, internal transactions that commit independently. The DML statement must be fully partitionable: it must be expressible as the union of many statements each of which accesses only a single row of the table. The statement should also be idempotent, because it may be applied more than once.
PartitionedUpdate returns an estimated count of the number of rows affected. The actual number of affected rows may be greater than the estimate.
Sourcepub async fn apply_at_least_once(
&self,
ms: Vec<Mutation>,
) -> Result<Option<CommitResult>, Error>
pub async fn apply_at_least_once( &self, ms: Vec<Mutation>, ) -> Result<Option<CommitResult>, Error>
apply_at_least_once may attempt to apply mutations more than once; if the mutations are not idempotent, this may lead to a failure being reported when the mutation was applied more than once. For example, an insert may fail with ALREADY_EXISTS even though the row did not exist before Apply was called. For this reason, most users of the library will prefer not to use this option. However, apply_at_least_once requires only a single RPC, whereas apply’s default replay protection may require an additional RPC. So this method may be appropriate for latency sensitive and/or high throughput blind writing.
Sourcepub async fn apply_at_least_once_with_option(
&self,
ms: Vec<Mutation>,
options: CommitOptions,
) -> Result<Option<CommitResult>, Error>
pub async fn apply_at_least_once_with_option( &self, ms: Vec<Mutation>, options: CommitOptions, ) -> Result<Option<CommitResult>, Error>
apply_at_least_once may attempt to apply mutations more than once; if the mutations are not idempotent, this may lead to a failure being reported when the mutation was applied more than once. For example, an insert may fail with ALREADY_EXISTS even though the row did not exist before Apply was called. For this reason, most users of the library will prefer not to use this option. However, apply_at_least_once requires only a single RPC, whereas apply’s default replay protection may require an additional RPC. So this method may be appropriate for latency sensitive and/or high throughput blind writing.
Sourcepub async fn apply(&self, ms: Vec<Mutation>) -> Result<CommitResult, Error>
pub async fn apply(&self, ms: Vec<Mutation>) -> Result<CommitResult, Error>
Apply applies a list of mutations atomically to the database.
use google_cloud_spanner::mutation::insert;
use google_cloud_spanner::mutation::delete;
use google_cloud_spanner::key::all_keys;
use google_cloud_spanner::statement::ToKind;
use google_cloud_spanner::client::{Client, Error};
use google_cloud_spanner::value::CommitTimestamp;
async fn run(client: Client) -> Result<(), Error>{
let m1 = delete("Guild", all_keys());
let m2 = insert("Guild", &["GuildID", "OwnerUserID", "UpdatedAt"], &[&"1", &"2", &CommitTimestamp::new()]);
let commit_timestamp = client.apply(vec![m1,m2]).await?;
Ok(())
}
Sourcepub async fn apply_with_option(
&self,
ms: Vec<Mutation>,
options: ReadWriteTransactionOption,
) -> Result<CommitResult, Error>
pub async fn apply_with_option( &self, ms: Vec<Mutation>, options: ReadWriteTransactionOption, ) -> Result<CommitResult, Error>
Apply applies a list of mutations atomically to the database.
Sourcepub async fn read_write_transaction<'a, T, E, F>(
&self,
f: F,
) -> Result<(CommitResult, T), E>
pub async fn read_write_transaction<'a, T, E, F>( &self, f: F, ) -> Result<(CommitResult, T), E>
ReadWriteTransaction executes a read-write transaction, with retries as necessary.
The function f will be called one or more times. It must not maintain any state between calls.
If the transaction cannot be committed or if f returns an ABORTED error, ReadWriteTransaction will call f again. It will continue to call f until the transaction can be committed or the Context times out or is cancelled. If f returns an error other than ABORTED, ReadWriteTransaction will abort the transaction and return the error.
To limit the number of retries, set a deadline on the Context rather than using a fixed limit on the number of attempts. ReadWriteTransaction will retry as needed until that deadline is met.
See https://godoc.org/cloud.google.com/go/spanner#ReadWriteTransaction for more details.
use google_cloud_spanner::mutation::update;
use google_cloud_spanner::key::{Key, all_keys};
use google_cloud_spanner::value::Timestamp;
use google_cloud_spanner::client::Error;
use google_cloud_spanner::client::Client;
#[tokio::main]
async fn run(client: Client) -> Result<(Option<Timestamp>,()), Error>{
client.read_write_transaction(|tx| {
Box::pin(async move {
// The transaction function will be called again if the error code
// of this error is Aborted. The backend may automatically abort
// any read/write transaction if it detects a deadlock or other problems.
let key = all_keys();
let mut reader = tx.read("UserItem", &["UserId", "ItemId", "Quantity"], key).await?;
let mut ms = vec![];
while let Some(row) = reader.next().await? {
let user_id = row.column_by_name::<String>("UserId")?;
let item_id = row.column_by_name::<i64>("ItemId")?;
let quantity = row.column_by_name::<i64>("Quantity")? + 1;
let m = update("UserItem", &["Quantity"], &[&user_id, &item_id, &quantity]);
ms.push(m);
}
// The buffered mutation will be committed. If the commit
// fails with an Aborted error, this function will be called again
tx.buffer_write(ms);
Ok(())
})
}).await
}
Sourcepub async fn read_write_transaction_with_option<'a, T, E, F>(
&'a self,
f: F,
options: ReadWriteTransactionOption,
) -> Result<(CommitResult, T), E>
pub async fn read_write_transaction_with_option<'a, T, E, F>( &'a self, f: F, options: ReadWriteTransactionOption, ) -> Result<(CommitResult, T), E>
ReadWriteTransaction executes a read-write transaction, with retries as necessary.
The function f will be called one or more times. It must not maintain any state between calls.
If the transaction cannot be committed or if f returns an ABORTED error, ReadWriteTransaction will call f again. It will continue to call f until the transaction can be committed or the Context times out or is cancelled. If f returns an error other than ABORTED, ReadWriteTransaction will abort the transaction and return the error.
To limit the number of retries, set a deadline on the Context rather than using a fixed limit on the number of attempts. ReadWriteTransaction will retry as needed until that deadline is met.
See https://godoc.org/cloud.google.com/go/spanner#ReadWriteTransaction for more details.
Sourcepub async fn begin_read_write_transaction(
&self,
) -> Result<ReadWriteTransaction, Error>
pub async fn begin_read_write_transaction( &self, ) -> Result<ReadWriteTransaction, Error>
begin_read_write_transaction creates new ReadWriteTransaction.
use google_cloud_spanner::mutation::update;
use google_cloud_spanner::key::{Key, all_keys};
use google_cloud_spanner::value::Timestamp;
use google_cloud_spanner::client::Error;
use google_cloud_spanner::client::Client;
use google_cloud_spanner::transaction_rw::ReadWriteTransaction;
use google_cloud_googleapis::spanner::v1::execute_batch_dml_request::Statement;
use google_cloud_spanner::retry::TransactionRetry;
async fn run(client: Client) -> Result<(), Error>{
let retry = &mut TransactionRetry::new();
loop {
let tx = &mut client.begin_read_write_transaction().await?;
let result = run_in_transaction(tx).await;
// try to commit or rollback transaction.
match tx.end(result, None).await {
Ok((_commit_timestamp, success)) => return Ok(success),
Err(err) => retry.next(err).await? // check retry
}
}
}
async fn run_in_transaction(tx: &mut ReadWriteTransaction) -> Result<(), Error> {
let key = all_keys();
let mut reader = tx.read("UserItem", &["UserId", "ItemId", "Quantity"], key).await?;
let mut ms = vec![];
while let Some(row) = reader.next().await? {
let user_id = row.column_by_name::<String>("UserId")?;
let item_id = row.column_by_name::<i64>("ItemId")?;
let quantity = row.column_by_name::<i64>("Quantity")? + 1;
let m = update("UserItem", &["UserId", "ItemId", "Quantity"], &[&user_id, &item_id, &quantity]);
ms.push(m);
}
tx.buffer_write(ms);
Ok(())
}
Sourcepub fn session_count(&self) -> usize
pub fn session_count(&self) -> usize
Get open session count.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Client
impl !RefUnwindSafe for Client
impl Send for Client
impl Sync for Client
impl Unpin for Client
impl !UnwindSafe for Client
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T
in a tonic::Request