Performs database client operations on Spanner.
Applications use this class to perform operations on Spanner Databases.
Performance
Client
objects are relatively cheap to create, copy, and move. However, each Client
object must be created with a std::shared_ptr<
Connection
>
, which itself is relatively expensive to create. Therefore, connection instances should be shared when possible. See the MakeConnection()
method and the Connection
interface for more details.
Thread Safety
Instances of this class created via copy-construction or copy-assignment share the underlying pool of connections. Access to these copies via multiple threads is guaranteed to work. Two threads operating on the same instance of this class is not guaranteed to work.
Error Handling
This class uses StatusOr
<T>
to report errors. When an operation fails to perform its work the returned StatusOr
<T>
contains the error details. If the ok()
member function in the StatusOr
<T>
returns true
then it contains the expected result. For more information, see the Error Handling Guide.
namespace spanner = ::google::cloud::spanner;
auto db = spanner::Database("my_project", "my_instance", "my_db_id"));
auto conn = spanner::MakeConnection(db);
auto client = spanner::Client(conn);
auto rows = client.Read(...);
using RowType = std::tuple<std::int64_t, std::string>;
for (auto const& row : spanner::StreamOf<RowType>(rows)) {
// ...
}
Query Options
Most operations that take an SqlStatement
may also be modified with query Options
. These options can be set at various levels, with more specific levels taking precedence over broader ones. For example, Options
that are passed directly to Client::ExecuteQuery()
will take precedence over the Client
-level defaults (if any), which will themselves take precedence over any environment variables. The following table shows the environment variables that may optionally be set and the query Options
setting that they affect.
Environment Variable | Options setting |
---|---|
SPANNER_OPTIMIZER_VERSION | QueryOptimizerVersionOption |
SPANNER_OPTIMIZER_STATISTICS_PACKAGE | QueryOptimizerStatisticsPackageOption |
See Also
https://cloud.google.com/spanner/docs/reference/rest/v1/QueryOptions
See Also
http://cloud/spanner/docs/query-optimizer/manage-query-optimizer
Constructors
Client(Client const &)
Copy and move support
Parameter | |
---|---|
Name | Description |
|
Client const &
|
Client(Client &&)
Copy and move support
Parameter | |
---|---|
Name | Description |
|
Client &&
|
Client(std::shared_ptr< Connection >, ClientOptions const &)
Backwards compatibility for ClientOptions.
Parameters | |
---|---|
Name | Description |
conn |
std::shared_ptr< Connection >
|
opts |
ClientOptions const &
|
Client(std::shared_ptr< Connection >, std::initializer_list< internal::NonConstructible >)
Backwards compatibility for ClientOptions.
Parameters | |
---|---|
Name | Description |
conn |
std::shared_ptr< Connection >
|
|
std::initializer_list< internal::NonConstructible >
|
Client(std::shared_ptr< Connection >, Options)
Constructs a Client
object using the specified conn
and opts
.
See MakeConnection()
for how to create a connection to Spanner. To help with unit testing, callers may create fake/mock Connection
objects that are injected into the Client
.
Parameters | |
---|---|
Name | Description |
conn |
std::shared_ptr< Connection >
|
opts |
Options
|
Client()
No default construction.
Operators
operator=(Client const &)
Copy and move support
Parameter | |
---|---|
Name | Description |
|
Client const &
|
Returns | |
---|---|
Type | Description |
Client & |
operator=(Client &&)
Copy and move support
Parameter | |
---|---|
Name | Description |
|
Client &&
|
Returns | |
---|---|
Type | Description |
Client & |
Functions
Read(std::string, KeySet, std::vector< std::string >, ReadOptions const &)
Reads rows from the database using key lookups and scans, as a simple key/value style alternative to ExecuteQuery()
.
Parameters | |
---|---|
Name | Description |
table |
std::string
|
keys |
KeySet
|
columns |
std::vector< std::string >
|
read_options |
ReadOptions const &
|
Returns | |
---|---|
Type | Description |
RowStream |
Read(std::string, KeySet, std::vector< std::string >, std::initializer_list< internal::NonConstructible >)
Reads rows from the database using key lookups and scans, as a simple key/value style alternative to ExecuteQuery()
.
Parameters | |
---|---|
Name | Description |
table |
std::string
|
keys |
KeySet
|
columns |
std::vector< std::string >
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
RowStream |
Read(Transaction::SingleUseOptions, std::string, KeySet, std::vector< std::string >, ReadOptions const &)
Reads rows from the database using key lookups and scans, as a simple key/value style alternative to ExecuteQuery()
.
Parameters | |
---|---|
Name | Description |
transaction_options |
Transaction::SingleUseOptions
|
table |
std::string
|
keys |
KeySet
|
columns |
std::vector< std::string >
|
read_options |
ReadOptions const &
|
Returns | |
---|---|
Type | Description |
RowStream |
Read(Transaction::SingleUseOptions, std::string, KeySet, std::vector< std::string >, std::initializer_list< internal::NonConstructible >)
Reads rows from the database using key lookups and scans, as a simple key/value style alternative to ExecuteQuery()
.
Parameters | |
---|---|
Name | Description |
transaction_options |
Transaction::SingleUseOptions
|
table |
std::string
|
keys |
KeySet
|
columns |
std::vector< std::string >
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
RowStream |
Read(Transaction, std::string, KeySet, std::vector< std::string >, ReadOptions const &)
Reads rows from the database using key lookups and scans, as a simple key/value style alternative to ExecuteQuery()
.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
table |
std::string
|
keys |
KeySet
|
columns |
std::vector< std::string >
|
read_options |
ReadOptions const &
|
Returns | |
---|---|
Type | Description |
RowStream |
Read(Transaction, std::string, KeySet, std::vector< std::string >, std::initializer_list< internal::NonConstructible >)
Reads rows from the database using key lookups and scans, as a simple key/value style alternative to ExecuteQuery()
.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
table |
std::string
|
keys |
KeySet
|
columns |
std::vector< std::string >
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
RowStream |
PartitionRead(Transaction, std::string, KeySet, std::vector< std::string >, ReadOptions const &, PartitionOptions const &)
Creates a set of partitions that can be used to execute a read operation in parallel.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
table |
std::string
|
keys |
KeySet
|
columns |
std::vector< std::string >
|
read_options |
ReadOptions const &
|
partition_options |
PartitionOptions const &
|
Returns | |
---|---|
Type | Description |
StatusOr< std::vector< ReadPartition > > |
PartitionRead(Transaction, std::string, KeySet, std::vector< std::string >, std::initializer_list< internal::NonConstructible >)
Creates a set of partitions that can be used to execute a read operation in parallel.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
table |
std::string
|
keys |
KeySet
|
columns |
std::vector< std::string >
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
StatusOr< std::vector< ReadPartition > > |
ExecuteQuery(SqlStatement, QueryOptions const &)
Executes a SQL query.
See Also
Parameters | |
---|---|
Name | Description |
statement |
SqlStatement
|
opts |
QueryOptions const &
|
Returns | |
---|---|
Type | Description |
RowStream |
ExecuteQuery(SqlStatement, std::initializer_list< internal::NonConstructible >)
Executes a SQL query.
See Also
Parameters | |
---|---|
Name | Description |
statement |
SqlStatement
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
RowStream |
ExecuteQuery(Transaction::SingleUseOptions, SqlStatement, QueryOptions const &)
Executes a SQL query.
Parameters | |
---|---|
Name | Description |
transaction_options |
Transaction::SingleUseOptions
|
statement |
SqlStatement
|
opts |
QueryOptions const &
|
Returns | |
---|---|
Type | Description |
RowStream |
ExecuteQuery(Transaction::SingleUseOptions, SqlStatement, std::initializer_list< internal::NonConstructible >)
Executes a SQL query.
Parameters | |
---|---|
Name | Description |
transaction_options |
Transaction::SingleUseOptions
|
statement |
SqlStatement
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
RowStream |
ExecuteQuery(Transaction, SqlStatement, QueryOptions const &)
Executes a SQL query.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
statement |
SqlStatement
|
opts |
QueryOptions const &
|
Returns | |
---|---|
Type | Description |
RowStream |
ExecuteQuery(Transaction, SqlStatement, std::initializer_list< internal::NonConstructible >)
Executes a SQL query.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
statement |
SqlStatement
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
RowStream |
ExecuteQuery(QueryPartition const &, QueryOptions const &)
Executes a SQL query on a subset of rows in a database.
Parameters | |
---|---|
Name | Description |
partition |
QueryPartition const &
|
opts |
QueryOptions const &
|
Returns | |
---|---|
Type | Description |
RowStream |
ExecuteQuery(QueryPartition const &, std::initializer_list< internal::NonConstructible >)
Executes a SQL query on a subset of rows in a database.
Parameters | |
---|---|
Name | Description |
partition |
QueryPartition const &
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
RowStream |
ProfileQuery(SqlStatement, QueryOptions const &)
Profiles a SQL query.
See Also
Parameters | |
---|---|
Name | Description |
statement |
SqlStatement
|
opts |
QueryOptions const &
|
Returns | |
---|---|
Type | Description |
ProfileQueryResult |
ProfileQuery(SqlStatement, std::initializer_list< internal::NonConstructible >)
Profiles a SQL query.
See Also
Parameters | |
---|---|
Name | Description |
statement |
SqlStatement
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
ProfileQueryResult |
ProfileQuery(Transaction::SingleUseOptions, SqlStatement, QueryOptions const &)
Profiles a SQL query.
Parameters | |
---|---|
Name | Description |
transaction_options |
Transaction::SingleUseOptions
|
statement |
SqlStatement
|
opts |
QueryOptions const &
|
Returns | |
---|---|
Type | Description |
ProfileQueryResult |
ProfileQuery(Transaction::SingleUseOptions, SqlStatement, std::initializer_list< internal::NonConstructible >)
Profiles a SQL query.
Parameters | |
---|---|
Name | Description |
transaction_options |
Transaction::SingleUseOptions
|
statement |
SqlStatement
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
ProfileQueryResult |
ProfileQuery(Transaction, SqlStatement, QueryOptions const &)
Profiles a SQL query.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
statement |
SqlStatement
|
opts |
QueryOptions const &
|
Returns | |
---|---|
Type | Description |
ProfileQueryResult |
ProfileQuery(Transaction, SqlStatement, std::initializer_list< internal::NonConstructible >)
Profiles a SQL query.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
statement |
SqlStatement
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
ProfileQueryResult |
ExecuteDml(Transaction, SqlStatement, QueryOptions const &)
Executes a SQL DML statement.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
statement |
SqlStatement
|
opts |
QueryOptions const &
|
Returns | |
---|---|
Type | Description |
StatusOr< DmlResult > |
ExecuteDml(Transaction, SqlStatement, std::initializer_list< internal::NonConstructible >)
Executes a SQL DML statement.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
statement |
SqlStatement
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
StatusOr< DmlResult > |
ProfileDml(Transaction, SqlStatement, QueryOptions const &)
Executes a SQL query.
See Also
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
statement |
SqlStatement
|
opts |
QueryOptions const &
|
Returns | |
---|---|
Type | Description |
StatusOr< ProfileDmlResult > |
ProfileDml(Transaction, SqlStatement, std::initializer_list< internal::NonConstructible >)
Executes a SQL query.
See Also
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
statement |
SqlStatement
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
StatusOr< ProfileDmlResult > |
AnalyzeSql(Transaction, SqlStatement, QueryOptions const &)
Analyzes the execution plan of a SQL statement.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
statement |
SqlStatement
|
opts |
QueryOptions const &
|
Returns | |
---|---|
Type | Description |
StatusOr< ExecutionPlan > |
AnalyzeSql(Transaction, SqlStatement, std::initializer_list< internal::NonConstructible >)
Analyzes the execution plan of a SQL statement.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
statement |
SqlStatement
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
StatusOr< ExecutionPlan > |
ExecutePartitionedDml(SqlStatement, QueryOptions const &)
Executes a Partitioned DML SQL query.
Parameters | |
---|---|
Name | Description |
statement |
SqlStatement
|
opts |
QueryOptions const &
|
Returns | |
---|---|
Type | Description |
StatusOr< PartitionedDmlResult > |
ExecutePartitionedDml(SqlStatement, std::initializer_list< internal::NonConstructible >)
Executes a Partitioned DML SQL query.
Parameters | |
---|---|
Name | Description |
statement |
SqlStatement
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
StatusOr< PartitionedDmlResult > |
PartitionQuery(Transaction, SqlStatement, PartitionOptions const &)
Creates a set of partitions that can be used to execute a query operation in parallel.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
statement |
SqlStatement
|
partition_options |
PartitionOptions const &
|
Returns | |
---|---|
Type | Description |
StatusOr< std::vector< QueryPartition > > |
PartitionQuery(Transaction, SqlStatement, std::initializer_list< internal::NonConstructible >)
Creates a set of partitions that can be used to execute a query operation in parallel.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
statement |
SqlStatement
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
StatusOr< std::vector< QueryPartition > > |
Commit(std::function< StatusOr< Mutations >(Transaction)> const &, std::unique_ptr< TransactionRerunPolicy >, std::unique_ptr< BackoffPolicy >, CommitOptions const &)
Commits a read-write transaction.
Parameters | |
---|---|
Name | Description |
mutator |
std::function< StatusOr< Mutations >(Transaction)> const &
|
rerun_policy |
std::unique_ptr< TransactionRerunPolicy >
|
backoff_policy |
std::unique_ptr< BackoffPolicy >
|
commit_options |
CommitOptions const &
|
Returns | |
---|---|
Type | Description |
StatusOr< CommitResult > |
Commit(std::function< StatusOr< Mutations >(Transaction)> const &, std::unique_ptr< TransactionRerunPolicy >, std::unique_ptr< BackoffPolicy >, std::initializer_list< internal::NonConstructible >)
Commits a read-write transaction.
Parameters | |
---|---|
Name | Description |
mutator |
std::function< StatusOr< Mutations >(Transaction)> const &
|
rerun_policy |
std::unique_ptr< TransactionRerunPolicy >
|
backoff_policy |
std::unique_ptr< BackoffPolicy >
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
StatusOr< CommitResult > |
Commit(std::function< StatusOr< Mutations >(Transaction)> const &, CommitOptions const &)
Commits a read-write transaction.
Parameters | |
---|---|
Name | Description |
mutator |
std::function< StatusOr< Mutations >(Transaction)> const &
|
commit_options |
CommitOptions const &
|
Returns | |
---|---|
Type | Description |
StatusOr< CommitResult > |
Commit(std::function< StatusOr< Mutations >(Transaction)> const &, std::initializer_list< internal::NonConstructible >)
Backwards compatibility for CommitOptions.
Parameters | |
---|---|
Name | Description |
mutator |
std::function< StatusOr< Mutations >(Transaction)> const &
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
StatusOr< CommitResult > |
Commit(Mutations, CommitOptions const &)
Commits the mutations
, using the options
, atomically in order.
See Also
Parameters | |
---|---|
Name | Description |
mutations |
Mutations
|
commit_options |
CommitOptions const &
|
Returns | |
---|---|
Type | Description |
StatusOr< CommitResult > |
Commit(Mutations, std::initializer_list< internal::NonConstructible >)
Commits the mutations
, using the options
, atomically in order.
See Also
Parameters | |
---|---|
Name | Description |
mutations |
Mutations
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
StatusOr< CommitResult > |
Commit(Transaction, Mutations, CommitOptions const &)
Commits a read-write transaction.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
mutations |
Mutations
|
commit_options |
CommitOptions const &
|
Returns | |
---|---|
Type | Description |
StatusOr< CommitResult > |
Commit(Transaction, Mutations, std::initializer_list< internal::NonConstructible >)
Commits a read-write transaction.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
|
mutations |
Mutations
|
|
std::initializer_list< internal::NonConstructible >
|
Returns | |
---|---|
Type | Description |
StatusOr< CommitResult > |
Read(std::string, KeySet, std::vector< std::string >, Options)
Reads rows from the database using key lookups and scans, as a simple key/value style alternative to ExecuteQuery()
.
Callers can optionally supply a Transaction
or Transaction::SingleUseOptions
used to create a single-use transaction - or neither, in which case a single-use transaction with default options is used.
Example
void ReadData(google::cloud::spanner::Client client) {
namespace spanner = ::google::cloud::spanner;
auto rows = client.Read("Albums", google::cloud::spanner::KeySet::All(),
{"SingerId", "AlbumId", "AlbumTitle"});
using RowType = std::tuple<std::int64_t, std::int64_t, std::string>;
for (auto& row : spanner::StreamOf<RowType>(rows)) {
if (!row) throw std::move(row).status();
std::cout << "SingerId: " << std::get<0>(*row) << "\t";
std::cout << "AlbumId: " << std::get<1>(*row) << "\t";
std::cout << "AlbumTitle: " << std::get<2>(*row) << "\n";
}
std::cout << "Read completed for [spanner_read_data]\n";
}
Parameters | |
---|---|
Name | Description |
table |
std::string
The name of the table in the database to be read. |
keys |
KeySet
Identifies the rows to be yielded. If |
columns |
std::vector< std::string >
The columns of |
opts |
Options
|
Returns | |
---|---|
Type | Description |
RowStream |
Read(Transaction::SingleUseOptions, std::string, KeySet, std::vector< std::string >, Options)
Reads rows from the database using key lookups and scans, as a simple key/value style alternative to ExecuteQuery()
.
Callers can optionally supply a Transaction
or Transaction::SingleUseOptions
used to create a single-use transaction - or neither, in which case a single-use transaction with default options is used.
Example
void ReadData(google::cloud::spanner::Client client) {
namespace spanner = ::google::cloud::spanner;
auto rows = client.Read("Albums", google::cloud::spanner::KeySet::All(),
{"SingerId", "AlbumId", "AlbumTitle"});
using RowType = std::tuple<std::int64_t, std::int64_t, std::string>;
for (auto& row : spanner::StreamOf<RowType>(rows)) {
if (!row) throw std::move(row).status();
std::cout << "SingerId: " << std::get<0>(*row) << "\t";
std::cout << "AlbumId: " << std::get<1>(*row) << "\t";
std::cout << "AlbumTitle: " << std::get<2>(*row) << "\n";
}
std::cout << "Read completed for [spanner_read_data]\n";
}
Parameters | |
---|---|
Name | Description |
transaction_options |
Transaction::SingleUseOptions
Execute this read in a single-use transaction with these options. |
table |
std::string
The name of the table in the database to be read. |
keys |
KeySet
Identifies the rows to be yielded. If |
columns |
std::vector< std::string >
The columns of |
opts |
Options
|
Returns | |
---|---|
Type | Description |
RowStream |
Read(Transaction, std::string, KeySet, std::vector< std::string >, Options)
Reads rows from the database using key lookups and scans, as a simple key/value style alternative to ExecuteQuery()
.
Callers can optionally supply a Transaction
or Transaction::SingleUseOptions
used to create a single-use transaction - or neither, in which case a single-use transaction with default options is used.
Example
void ReadData(google::cloud::spanner::Client client) {
namespace spanner = ::google::cloud::spanner;
auto rows = client.Read("Albums", google::cloud::spanner::KeySet::All(),
{"SingerId", "AlbumId", "AlbumTitle"});
using RowType = std::tuple<std::int64_t, std::int64_t, std::string>;
for (auto& row : spanner::StreamOf<RowType>(rows)) {
if (!row) throw std::move(row).status();
std::cout << "SingerId: " << std::get<0>(*row) << "\t";
std::cout << "AlbumId: " << std::get<1>(*row) << "\t";
std::cout << "AlbumTitle: " << std::get<2>(*row) << "\n";
}
std::cout << "Read completed for [spanner_read_data]\n";
}
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
Execute this read as part of an existing transaction. |
table |
std::string
The name of the table in the database to be read. |
keys |
KeySet
Identifies the rows to be yielded. If |
columns |
std::vector< std::string >
The columns of |
opts |
Options
|
Returns | |
---|---|
Type | Description |
RowStream |
Read(ReadPartition const &, Options)
Reads rows from a subset of rows in a database.
Requires a prior call to PartitionRead
to obtain the partition information; see the documentation of that method for full details.
Example
google::cloud::StatusOr<spanner::ReadPartition> partition =
remote_connection.ReceiveReadPartitionFromRemoteMachine();
if (!partition) throw std::move(partition).status();
for (auto& row : client.Read(*partition)) {
if (row.status().code() ==
google::cloud::StatusCode::kPermissionDenied) {
continue;
}
if (!row) throw std::move(row).status();
ProcessRow(*row);
}
Parameters | |
---|---|
Name | Description |
partition |
ReadPartition const &
A |
opts |
Options
|
Returns | |
---|---|
Type | Description |
RowStream |
PartitionRead(Transaction, std::string, KeySet, std::vector< std::string >, Options)
Creates a set of partitions that can be used to execute a read operation in parallel.
Each of the returned partitions can be passed to Read
to specify a subset of the read result to read.
There are no ordering guarantees on rows returned among the returned partition, or even within each individual Read
call issued with a given partition.
Partitions become invalid when the session used to create them is deleted, is idle for too long, begins a new transaction, or becomes too old. When any of these happen, it is not possible to resume the read, and the whole operation must be restarted from the beginning.
Example
spanner::Transaction ro_transaction = spanner::MakeReadOnlyTransaction();
google::cloud::StatusOr<std::vector<spanner::ReadPartition>> partitions =
client.PartitionRead(
ro_transaction, "Singers", key_set,
{"SingerId", "FirstName", "LastName"},
google::cloud::Options{}.set<spanner::PartitionDataBoostOption>(
true));
if (!partitions) throw std::move(partitions).status();
for (auto& partition : *partitions) {
remote_connection.SendPartitionToRemoteMachine(partition);
}
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
The transaction to execute the operation in. Must be a read-only snapshot transaction. |
table |
std::string
The name of the table in the database to be read. |
keys |
KeySet
Identifies the rows to be yielded. If |
columns |
std::vector< std::string >
The columns of |
opts |
Options
|
Returns | |
---|---|
Type | Description |
StatusOr< std::vector< ReadPartition > > | A |
ExecuteQuery(SqlStatement, Options)
Executes a SQL query.
Operations inside read-write transactions might return ABORTED
. If this occurs, the application should restart the transaction from the beginning.
Callers can optionally supply a Transaction
or Transaction::SingleUseOptions
used to create a single-use transaction - or neither, in which case a single-use transaction with default options is used.
SELECT * ...
queries are supported, but there's no guarantee about the order, nor number, of returned columns. Therefore, the caller must look up the wanted values in each row by column name. When the desired column names are known in advance, it is better to list them explicitly in the query's SELECT statement, so that unnecessary values are not returned/ignored, and the column order is known. This enables more efficient and simpler code.
Can also execute a DML statement with a returning clause in a read/write transaction.
Example
Query with explicitly selected columns.
void QueryData(google::cloud::spanner::Client client) {
namespace spanner = ::google::cloud::spanner;
spanner::SqlStatement select("SELECT SingerId, LastName FROM Singers");
using RowType = std::tuple<std::int64_t, std::string>;
auto rows = client.ExecuteQuery(std::move(select));
for (auto& row : spanner::StreamOf<RowType>(rows)) {
if (!row) throw std::move(row).status();
std::cout << "SingerId: " << std::get<0>(*row) << "\t";
std::cout << "LastName: " << std::get<1>(*row) << "\n";
}
std::cout << "Query completed for [spanner_query_data]\n";
}
Example
Using SELECT *
.
void QueryDataSelectStar(google::cloud::spanner::Client client) {
namespace spanner = ::google::cloud::spanner;
// With a "SELECT *" query, we don't know the order in which the columns will
// be returned (nor the number of columns). Therefore, we look up each value
// based on the column name rather than its position.
spanner::SqlStatement select_star("SELECT * FROM Singers");
for (auto& row : client.ExecuteQuery(std::move(select_star))) {
if (!row) throw std::move(row).status();
if (auto singer_id = row->get<std::int64_t>("SingerId")) {
std::cout << "SingerId: " << *singer_id << "\t";
} else {
std::cerr << singer_id.status();
}
if (auto last_name = row->get<std::string>("LastName")) {
std::cout << "LastName: " << *last_name;
} else {
std::cerr << last_name.status();
}
std::cout << "\n";
}
std::cout << "Query completed for [spanner_query_data_select_star]\n";
}
Example
Using a DML statement with THEN RETURN
.
void UpdateUsingDmlReturning(google::cloud::spanner::Client client) {
// Update MarketingBudget column for records satisfying a particular
// condition and return the modified MarketingBudget column of the
// updated records using `THEN RETURN MarketingBudget`.
auto commit = client.Commit(
[&client](google::cloud::spanner::Transaction txn)
-> google::cloud::StatusOr<google::cloud::spanner::Mutations> {
auto sql = google::cloud::spanner::SqlStatement(R"""(
UPDATE Albums SET MarketingBudget = MarketingBudget * 2
WHERE SingerId = 1 AND AlbumId = 1
THEN RETURN MarketingBudget
)""");
using RowType = std::tuple<absl::optional<std::int64_t>>;
auto rows = client.ExecuteQuery(std::move(txn), std::move(sql));
// Note: This mutator might be re-run, or its effects discarded, so
// changing non-transactional state (e.g., by producing output) is,
// in general, not something to be imitated.
for (auto& row : google::cloud::spanner::StreamOf<RowType>(rows)) {
if (!row) return std::move(row).status();
std::cout << "MarketingBudget: ";
if (std::get<0>(*row).has_value()) {
std::cout << *std::get<0>(*row);
} else {
std::cout << "NULL";
}
std::cout << "\n";
}
std::cout << "Updated row(s) count: " << rows.RowsModified() << "\n";
return google::cloud::spanner::Mutations{};
});
if (!commit) throw std::move(commit).status();
}
Parameters | |
---|---|
Name | Description |
statement |
SqlStatement
The SQL statement to execute. |
opts |
Options
(optional) The |
Returns | |
---|---|
Type | Description |
RowStream |
ExecuteQuery(Transaction::SingleUseOptions, SqlStatement, Options)
Executes a SQL query.
Operations inside read-write transactions might return ABORTED
. If this occurs, the application should restart the transaction from the beginning.
Callers can optionally supply a Transaction
or Transaction::SingleUseOptions
used to create a single-use transaction - or neither, in which case a single-use transaction with default options is used.
SELECT * ...
queries are supported, but there's no guarantee about the order, nor number, of returned columns. Therefore, the caller must look up the wanted values in each row by column name. When the desired column names are known in advance, it is better to list them explicitly in the query's SELECT statement, so that unnecessary values are not returned/ignored, and the column order is known. This enables more efficient and simpler code.
Can also execute a DML statement with a returning clause in a read/write transaction.
Example
Query with explicitly selected columns.
void QueryData(google::cloud::spanner::Client client) {
namespace spanner = ::google::cloud::spanner;
spanner::SqlStatement select("SELECT SingerId, LastName FROM Singers");
using RowType = std::tuple<std::int64_t, std::string>;
auto rows = client.ExecuteQuery(std::move(select));
for (auto& row : spanner::StreamOf<RowType>(rows)) {
if (!row) throw std::move(row).status();
std::cout << "SingerId: " << std::get<0>(*row) << "\t";
std::cout << "LastName: " << std::get<1>(*row) << "\n";
}
std::cout << "Query completed for [spanner_query_data]\n";
}
Example
Using SELECT *
.
void QueryDataSelectStar(google::cloud::spanner::Client client) {
namespace spanner = ::google::cloud::spanner;
// With a "SELECT *" query, we don't know the order in which the columns will
// be returned (nor the number of columns). Therefore, we look up each value
// based on the column name rather than its position.
spanner::SqlStatement select_star("SELECT * FROM Singers");
for (auto& row : client.ExecuteQuery(std::move(select_star))) {
if (!row) throw std::move(row).status();
if (auto singer_id = row->get<std::int64_t>("SingerId")) {
std::cout << "SingerId: " << *singer_id << "\t";
} else {
std::cerr << singer_id.status();
}
if (auto last_name = row->get<std::string>("LastName")) {
std::cout << "LastName: " << *last_name;
} else {
std::cerr << last_name.status();
}
std::cout << "\n";
}
std::cout << "Query completed for [spanner_query_data_select_star]\n";
}
Example
Using a DML statement with THEN RETURN
.
void UpdateUsingDmlReturning(google::cloud::spanner::Client client) {
// Update MarketingBudget column for records satisfying a particular
// condition and return the modified MarketingBudget column of the
// updated records using `THEN RETURN MarketingBudget`.
auto commit = client.Commit(
[&client](google::cloud::spanner::Transaction txn)
-> google::cloud::StatusOr<google::cloud::spanner::Mutations> {
auto sql = google::cloud::spanner::SqlStatement(R"""(
UPDATE Albums SET MarketingBudget = MarketingBudget * 2
WHERE SingerId = 1 AND AlbumId = 1
THEN RETURN MarketingBudget
)""");
using RowType = std::tuple<absl::optional<std::int64_t>>;
auto rows = client.ExecuteQuery(std::move(txn), std::move(sql));
// Note: This mutator might be re-run, or its effects discarded, so
// changing non-transactional state (e.g., by producing output) is,
// in general, not something to be imitated.
for (auto& row : google::cloud::spanner::StreamOf<RowType>(rows)) {
if (!row) return std::move(row).status();
std::cout << "MarketingBudget: ";
if (std::get<0>(*row).has_value()) {
std::cout << *std::get<0>(*row);
} else {
std::cout << "NULL";
}
std::cout << "\n";
}
std::cout << "Updated row(s) count: " << rows.RowsModified() << "\n";
return google::cloud::spanner::Mutations{};
});
if (!commit) throw std::move(commit).status();
}
Parameters | |
---|---|
Name | Description |
transaction_options |
Transaction::SingleUseOptions
Execute this query in a single-use transaction with these options. |
statement |
SqlStatement
The SQL statement to execute. |
opts |
Options
(optional) The |
Returns | |
---|---|
Type | Description |
RowStream |
ExecuteQuery(Transaction, SqlStatement, Options)
Executes a SQL query.
Operations inside read-write transactions might return ABORTED
. If this occurs, the application should restart the transaction from the beginning.
Callers can optionally supply a Transaction
or Transaction::SingleUseOptions
used to create a single-use transaction - or neither, in which case a single-use transaction with default options is used.
SELECT * ...
queries are supported, but there's no guarantee about the order, nor number, of returned columns. Therefore, the caller must look up the wanted values in each row by column name. When the desired column names are known in advance, it is better to list them explicitly in the query's SELECT statement, so that unnecessary values are not returned/ignored, and the column order is known. This enables more efficient and simpler code.
Can also execute a DML statement with a returning clause in a read/write transaction.
Example
Query with explicitly selected columns.
void QueryData(google::cloud::spanner::Client client) {
namespace spanner = ::google::cloud::spanner;
spanner::SqlStatement select("SELECT SingerId, LastName FROM Singers");
using RowType = std::tuple<std::int64_t, std::string>;
auto rows = client.ExecuteQuery(std::move(select));
for (auto& row : spanner::StreamOf<RowType>(rows)) {
if (!row) throw std::move(row).status();
std::cout << "SingerId: " << std::get<0>(*row) << "\t";
std::cout << "LastName: " << std::get<1>(*row) << "\n";
}
std::cout << "Query completed for [spanner_query_data]\n";
}
Example
Using SELECT *
.
void QueryDataSelectStar(google::cloud::spanner::Client client) {
namespace spanner = ::google::cloud::spanner;
// With a "SELECT *" query, we don't know the order in which the columns will
// be returned (nor the number of columns). Therefore, we look up each value
// based on the column name rather than its position.
spanner::SqlStatement select_star("SELECT * FROM Singers");
for (auto& row : client.ExecuteQuery(std::move(select_star))) {
if (!row) throw std::move(row).status();
if (auto singer_id = row->get<std::int64_t>("SingerId")) {
std::cout << "SingerId: " << *singer_id << "\t";
} else {
std::cerr << singer_id.status();
}
if (auto last_name = row->get<std::string>("LastName")) {
std::cout << "LastName: " << *last_name;
} else {
std::cerr << last_name.status();
}
std::cout << "\n";
}
std::cout << "Query completed for [spanner_query_data_select_star]\n";
}
Example
Using a DML statement with THEN RETURN
.
void UpdateUsingDmlReturning(google::cloud::spanner::Client client) {
// Update MarketingBudget column for records satisfying a particular
// condition and return the modified MarketingBudget column of the
// updated records using `THEN RETURN MarketingBudget`.
auto commit = client.Commit(
[&client](google::cloud::spanner::Transaction txn)
-> google::cloud::StatusOr<google::cloud::spanner::Mutations> {
auto sql = google::cloud::spanner::SqlStatement(R"""(
UPDATE Albums SET MarketingBudget = MarketingBudget * 2
WHERE SingerId = 1 AND AlbumId = 1
THEN RETURN MarketingBudget
)""");
using RowType = std::tuple<absl::optional<std::int64_t>>;
auto rows = client.ExecuteQuery(std::move(txn), std::move(sql));
// Note: This mutator might be re-run, or its effects discarded, so
// changing non-transactional state (e.g., by producing output) is,
// in general, not something to be imitated.
for (auto& row : google::cloud::spanner::StreamOf<RowType>(rows)) {
if (!row) return std::move(row).status();
std::cout << "MarketingBudget: ";
if (std::get<0>(*row).has_value()) {
std::cout << *std::get<0>(*row);
} else {
std::cout << "NULL";
}
std::cout << "\n";
}
std::cout << "Updated row(s) count: " << rows.RowsModified() << "\n";
return google::cloud::spanner::Mutations{};
});
if (!commit) throw std::move(commit).status();
}
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
Execute this query as part of an existing transaction. |
statement |
SqlStatement
The SQL statement to execute. |
opts |
Options
(optional) The |
Returns | |
---|---|
Type | Description |
RowStream |
ExecuteQuery(QueryPartition const &, Options)
Executes a SQL query on a subset of rows in a database.
Requires a prior call to PartitionQuery
to obtain the partition information; see the documentation of that method for full details.
Example
google::cloud::StatusOr<spanner::QueryPartition> partition =
remote_connection.ReceiveQueryPartitionFromRemoteMachine();
if (!partition) throw std::move(partition).status();
for (auto& row : client.ExecuteQuery(*partition)) {
if (row.status().code() ==
google::cloud::StatusCode::kPermissionDenied) {
continue;
}
if (!row) throw std::move(row).status();
ProcessRow(*row);
}
Parameters | |
---|---|
Name | Description |
partition |
QueryPartition const &
A |
opts |
Options
(optional) The |
Returns | |
---|---|
Type | Description |
RowStream |
ProfileQuery(SqlStatement, Options)
Profiles a SQL query.
Profiling executes the query, provides the resulting rows, ExecutionPlan
, and execution statistics.
Operations inside read-write transactions might return kAborted
. If this occurs, the application should restart the transaction from the beginning.
Callers can optionally supply a Transaction
or Transaction::SingleUseOptions
used to create a single-use transaction - or neither, in which case a single-use transaction with default options is used.
Example
namespace spanner = ::google::cloud::spanner;
spanner::SqlStatement select(
"SELECT AlbumId, AlbumTitle, MarketingBudget"
" FROM Albums"
" WHERE AlbumTitle >= 'Aardvark' AND AlbumTitle < 'Goo'");
auto profile_query_result = client.ProfileQuery(std::move(select));
for (auto& row : profile_query_result) {
if (!row) throw std::move(row).status();
// Discard rows for brevity in this example.
}
// Stats are only available after all rows from the result have been read.
auto execution_stats = profile_query_result.ExecutionStats();
if (execution_stats) {
for (auto const& stat : *execution_stats) {
std::cout << stat.first << ":\t" << stat.second << "\n";
}
}
Parameters | |
---|---|
Name | Description |
statement |
SqlStatement
The SQL statement to execute. |
opts |
Options
(optional) The |
Returns | |
---|---|
Type | Description |
ProfileQueryResult |
ProfileQuery(Transaction::SingleUseOptions, SqlStatement, Options)
Profiles a SQL query.
Profiling executes the query, provides the resulting rows, ExecutionPlan
, and execution statistics.
Operations inside read-write transactions might return kAborted
. If this occurs, the application should restart the transaction from the beginning.
Callers can optionally supply a Transaction
or Transaction::SingleUseOptions
used to create a single-use transaction - or neither, in which case a single-use transaction with default options is used.
Example
namespace spanner = ::google::cloud::spanner;
spanner::SqlStatement select(
"SELECT AlbumId, AlbumTitle, MarketingBudget"
" FROM Albums"
" WHERE AlbumTitle >= 'Aardvark' AND AlbumTitle < 'Goo'");
auto profile_query_result = client.ProfileQuery(std::move(select));
for (auto& row : profile_query_result) {
if (!row) throw std::move(row).status();
// Discard rows for brevity in this example.
}
// Stats are only available after all rows from the result have been read.
auto execution_stats = profile_query_result.ExecutionStats();
if (execution_stats) {
for (auto const& stat : *execution_stats) {
std::cout << stat.first << ":\t" << stat.second << "\n";
}
}
Parameters | |
---|---|
Name | Description |
transaction_options |
Transaction::SingleUseOptions
Execute this query in a single-use transaction with these options. |
statement |
SqlStatement
The SQL statement to execute. |
opts |
Options
(optional) The |
Returns | |
---|---|
Type | Description |
ProfileQueryResult |
ProfileQuery(Transaction, SqlStatement, Options)
Profiles a SQL query.
Profiling executes the query, provides the resulting rows, ExecutionPlan
, and execution statistics.
Operations inside read-write transactions might return kAborted
. If this occurs, the application should restart the transaction from the beginning.
Callers can optionally supply a Transaction
or Transaction::SingleUseOptions
used to create a single-use transaction - or neither, in which case a single-use transaction with default options is used.
Example
namespace spanner = ::google::cloud::spanner;
spanner::SqlStatement select(
"SELECT AlbumId, AlbumTitle, MarketingBudget"
" FROM Albums"
" WHERE AlbumTitle >= 'Aardvark' AND AlbumTitle < 'Goo'");
auto profile_query_result = client.ProfileQuery(std::move(select));
for (auto& row : profile_query_result) {
if (!row) throw std::move(row).status();
// Discard rows for brevity in this example.
}
// Stats are only available after all rows from the result have been read.
auto execution_stats = profile_query_result.ExecutionStats();
if (execution_stats) {
for (auto const& stat : *execution_stats) {
std::cout << stat.first << ":\t" << stat.second << "\n";
}
}
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
Execute this query as part of an existing transaction. |
statement |
SqlStatement
The SQL statement to execute. |
opts |
Options
(optional) The |
Returns | |
---|---|
Type | Description |
ProfileQueryResult |
PartitionQuery(Transaction, SqlStatement, Options)
Creates a set of partitions that can be used to execute a query operation in parallel.
Each of the returned partitions can be passed to ExecuteQuery
to specify a subset of the query result to read.
Partitions become invalid when the session used to create them is deleted, is idle for too long, begins a new transaction, or becomes too old. When any of these happen, it is not possible to resume the query, and the whole operation must be restarted from the beginning.
Example
google::cloud::StatusOr<std::vector<spanner::QueryPartition>> partitions =
client.PartitionQuery(
spanner::MakeReadOnlyTransaction(),
spanner::SqlStatement(
"SELECT SingerId, FirstName, LastName FROM Singers"),
google::cloud::Options{}.set<spanner::PartitionDataBoostOption>(
true));
if (!partitions) throw std::move(partitions).status();
for (auto& partition : *partitions) {
remote_connection.SendPartitionToRemoteMachine(partition);
}
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
The transaction to execute the operation in. Must be a read-only snapshot transaction. |
statement |
SqlStatement
The SQL statement to execute. |
opts |
Options
|
Returns | |
---|---|
Type | Description |
StatusOr< std::vector< QueryPartition > > | A |
ExecuteDml(Transaction, SqlStatement, Options)
Executes a SQL DML statement.
Operations inside read-write transactions might return ABORTED
. If this occurs, the application should restart the transaction from the beginning.
Example
using ::google::cloud::StatusOr;
namespace spanner = ::google::cloud::spanner;
std::int64_t rows_inserted;
auto commit_result = client.Commit(
[&client, &rows_inserted](
spanner::Transaction txn) -> StatusOr<spanner::Mutations> {
auto insert = client.ExecuteDml(
std::move(txn),
spanner::SqlStatement(
"INSERT INTO Singers (SingerId, FirstName, LastName)"
" VALUES (10, 'Virginia', 'Watson')"));
if (!insert) return std::move(insert).status();
rows_inserted = insert->RowsModified();
return spanner::Mutations{};
});
if (!commit_result) throw std::move(commit_result).status();
std::cout << "Rows inserted: " << rows_inserted;
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
Execute this query as part of an existing transaction. |
statement |
SqlStatement
The SQL statement to execute. |
opts |
Options
(optional) The |
Returns | |
---|---|
Type | Description |
StatusOr< DmlResult > |
ProfileDml(Transaction, SqlStatement, Options)
Profiles a SQL DML statement.
Profiling executes the DML statement, provides the modified row count, ExecutionPlan
, and execution statistics.
Operations inside read-write transactions might return ABORTED
. If this occurs, the application should restart the transaction from the beginning.
Example
spanner::ProfileDmlResult dml_result;
auto commit_result = client.Commit(
[&client,
&dml_result](spanner::Transaction txn) -> StatusOr<spanner::Mutations> {
auto update = client.ProfileDml(
std::move(txn),
spanner::SqlStatement(
"UPDATE Albums SET MarketingBudget = MarketingBudget * 2"
" WHERE SingerId = 1 AND AlbumId = 1"));
if (!update) return std::move(update).status();
dml_result = *std::move(update);
return spanner::Mutations{};
});
if (!commit_result) throw std::move(commit_result).status();
// Stats only available after statement has been executed.
std::cout << "Rows modified: " << dml_result.RowsModified();
auto execution_stats = dml_result.ExecutionStats();
if (execution_stats) {
for (auto const& stat : *execution_stats) {
std::cout << stat.first << ":\t" << stat.second << "\n";
}
}
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
Execute this query as part of an existing transaction. |
statement |
SqlStatement
The SQL statement to execute. |
opts |
Options
(optional) The |
Returns | |
---|---|
Type | Description |
StatusOr< ProfileDmlResult > |
AnalyzeSql(Transaction, SqlStatement, Options)
Analyzes the execution plan of a SQL statement.
Analyzing provides the ExecutionPlan
, but does not execute the SQL statement.
Operations inside read-write transactions might return ABORTED
. If this occurs, the application should restart the transaction from the beginning.
Example
// Only SQL queries with a Distributed Union as the first operator in the
// `ExecutionPlan` can be partitioned.
auto is_partitionable = [](spanner::ExecutionPlan const& plan) {
return (!plan.plan_nodes().empty() &&
plan.plan_nodes(0).kind() ==
google::spanner::v1::PlanNode::RELATIONAL &&
plan.plan_nodes(0).display_name() == "Distributed Union");
};
google::cloud::StatusOr<spanner::ExecutionPlan> plan = client.AnalyzeSql(
spanner::MakeReadOnlyTransaction(),
spanner::SqlStatement(
"SELECT SingerId, FirstName, LastName FROM Singers"));
if (!plan) throw std::move(plan).status();
if (!is_partitionable(*plan)) {
throw std::runtime_error("Query is not partitionable");
}
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
Execute this query as part of an existing transaction. |
statement |
SqlStatement
The SQL statement to execute. |
opts |
Options
(optional) The |
Returns | |
---|---|
Type | Description |
StatusOr< ExecutionPlan > |
ExecuteBatchDml(Transaction, std::vector< SqlStatement >, Options)
Executes a batch of SQL DML statements.
This method allows many statements to be run with lower latency than submitting them sequentially with ExecuteDml
.
Statements are executed in order, sequentially. Execution will stop at the first failed statement; the remaining statements will not run.
As with all read-write transactions, the results will not be visible outside of the transaction until it is committed. For that reason, it is advisable to run this method from a Commit
mutator.
Example
void DmlStructs(google::cloud::spanner::Client client) {
namespace spanner = ::google::cloud::spanner;
std::int64_t rows_modified = 0;
auto commit_result =
client.Commit([&client, &rows_modified](spanner::Transaction const& txn)
-> google::cloud::StatusOr<spanner::Mutations> {
auto singer_info = std::make_tuple("Marc", "Richards");
auto sql = spanner::SqlStatement(
"UPDATE Singers SET FirstName = 'Keith' WHERE "
"STRUCT<FirstName String, LastName String>(FirstName, LastName) "
"= @name",
{{"name", spanner::Value(std::move(singer_info))}});
auto dml_result = client.ExecuteDml(txn, std::move(sql));
if (!dml_result) return std::move(dml_result).status();
rows_modified = dml_result->RowsModified();
return spanner::Mutations{};
});
if (!commit_result) throw std::move(commit_result).status();
std::cout << rows_modified
<< " update was successful [spanner_dml_structs]\n";
}
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
The read-write transaction to execute the operation in. |
statements |
std::vector< SqlStatement >
The list of statements to execute in this batch. Statements are executed serially, such that the effects of statement i are visible to statement i+1. Each statement must be a DML statement. Execution will stop at the first failed statement; the remaining statements will not run. Must not be empty. |
opts |
Options
(optional) The options to use for this call. Expected options are any of the types in the following option lists.
|
Returns | |
---|---|
Type | Description |
StatusOr< BatchDmlResult > |
Commit(std::function< StatusOr< Mutations >(Transaction)> const &, std::unique_ptr< TransactionRerunPolicy >, std::unique_ptr< BackoffPolicy >, Options)
Commits a read-write transaction.
Calls the mutator
in the context of a new read-write transaction. The mutator
can execute read/write operations using the transaction, and returns any additional Mutations
to commit.
If the mutator
succeeds and the transaction commits, then Commit()
returns the CommitResult
.
If the mutator
returns a non-rerunnable status (according to the rerun_policy
), the transaction is rolled back and that status is returned. Similarly, if the transaction fails to commit with a non- rerunnable status, that status is returned.
Otherwise the whole process repeats (subject to rerun_policy
and backoff_policy
), by building a new transaction and re-running the mutator
. The lock priority of the operation increases after each rerun, meaning that the next attempt has a slightly better chance of success.
Note that the mutator
should only return a rerunnable status when the transaction is no longer usable (e.g., it was aborted). Otherwise the transaction will be leaked.
Example
void CommitWithPolicies(google::cloud::spanner::Client client) {
using ::google::cloud::StatusOr;
namespace spanner = ::google::cloud::spanner;
auto commit = client.Commit(
[&client](spanner::Transaction txn) -> StatusOr<spanner::Mutations> {
auto update = client.ExecuteDml(
std::move(txn),
spanner::SqlStatement(
"UPDATE Albums SET MarketingBudget = MarketingBudget * 2"
" WHERE SingerId = 1 AND AlbumId = 1"));
if (!update) return std::move(update).status();
return spanner::Mutations{};
},
// Retry for up to 42 minutes.
spanner::LimitedTimeTransactionRerunPolicy(std::chrono::minutes(42))
.clone(),
// After a failure backoff for 2 seconds (with jitter), then triple the
// backoff time on each retry, up to 5 minutes.
spanner::ExponentialBackoffPolicy(std::chrono::seconds(2),
std::chrono::minutes(5), 3.0)
.clone());
if (!commit) throw std::move(commit).status();
std::cout << "commit-with-policies was successful\n";
}
Parameters | |
---|---|
Name | Description |
mutator |
std::function< StatusOr< Mutations >(Transaction)> const &
the function called to create mutations |
rerun_policy |
std::unique_ptr< TransactionRerunPolicy >
controls for how long (or how many times) the mutator will be rerun after the transaction aborts. |
backoff_policy |
std::unique_ptr< BackoffPolicy >
controls how long |
opts |
Options
(optional) The options to use for this call. Expected options include any of the following types: |
Exceptions | |
---|---|
Type | Description |
Rethrows | any exception thrown by ``mutator`` (after rolling back the transaction). However, a [`RuntimeStatusError`](xref:classgoogle_1_1cloud_1_1RuntimeStatusError) exception is instead consumed and converted into a `mutator` return value of the enclosed [`Status`](xref:classgoogle_1_1cloud_1_1Status). |
Returns | |
---|---|
Type | Description |
StatusOr< CommitResult > |
Commit(std::function< StatusOr< Mutations >(Transaction)> const &, Options)
Commits a read-write transaction.
Same as above, but uses the default rerun and backoff policies.
Example
using ::google::cloud::StatusOr;
namespace spanner = ::google::cloud::spanner;
auto commit_result = client.Commit(
[&client](spanner::Transaction txn) -> StatusOr<spanner::Mutations> {
auto update = client.ExecuteDml(
std::move(txn),
spanner::SqlStatement(
"UPDATE Albums SET MarketingBudget = MarketingBudget * 2"
" WHERE SingerId = 1 AND AlbumId = 1"));
if (!update) return std::move(update).status();
return spanner::Mutations{};
});
if (!commit_result) throw std::move(commit_result).status();
Parameters | |
---|---|
Name | Description |
mutator |
std::function< StatusOr< Mutations >(Transaction)> const &
the function called to create mutations |
opts |
Options
(optional) The options to use for this call. |
Returns | |
---|---|
Type | Description |
StatusOr< CommitResult > |
Commit(Mutations, Options)
Commits the mutations
, using the options
, atomically in order.
Example
namespace spanner = ::google::cloud::spanner;
auto commit_result = client.Commit(spanner::Mutations{
spanner::UpdateMutationBuilder("Albums",
{"SingerId", "AlbumId", "MarketingBudget"})
.EmplaceRow(1, 1, 100000)
.EmplaceRow(2, 2, 500000)
.Build()});
if (!commit_result) throw std::move(commit_result).status();
This function uses the re-run loop described above with the default policies.
Parameters | |
---|---|
Name | Description |
mutations |
Mutations
|
opts |
Options
|
Returns | |
---|---|
Type | Description |
StatusOr< CommitResult > |
Commit(Transaction, Mutations, Options)
Commits a read-write transaction.
The commit might return a kAborted
error. This can occur at any time. Commonly the cause is conflicts with concurrent transactions, however it can also happen for a variety of other reasons. If Commit
returns kAborted
, the caller may try to reapply the mutations within a new read-write transaction (which should share lock priority with the aborted transaction so that the new attempt has a slightly better chance of success).
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
The transaction to commit. |
mutations |
Mutations
The mutations to be executed when this transaction commits. All mutations are applied atomically, in the order they appear in this list. |
opts |
Options
(optional) The options to use for this call. |
Returns | |
---|---|
Type | Description |
StatusOr< CommitResult > | A |
CommitAtLeastOnce(Transaction::ReadWriteOptions, Mutations, Options)
Commits a write transaction with at-least-once semantics.
Apply the given mutations atomically, using a single RPC, and therefore without replay protection. That is, it is possible that the mutations will be applied more than once. If the mutations are not idempotent, this may lead to a failure (for example, an insert may fail with "already exists" even though the row did not exist before the call was made). Accordingly, this call may only be appropriate for idempotent, latency- sensitive and/or high-throughput blind writing.
Example
namespace spanner = ::google::cloud::spanner;
// Delete the album with key (2,2) without automatic re-run (e.g., if the
// transaction was aborted) or replay protection, but using a single RPC.
auto commit_result = client.CommitAtLeastOnce(
spanner::Transaction::ReadWriteOptions(),
spanner::Mutations{
spanner::DeleteMutationBuilder(
"Albums", spanner::KeySet().AddKey(spanner::MakeKey(2, 2)))
.Build()});
if (commit_result) {
std::cout << "Delete was successful\n";
} else if (commit_result.status().code() ==
google::cloud::StatusCode::kNotFound) {
std::cout << "Delete was successful but seemingly replayed\n";
} else if (commit_result.status().code() ==
google::cloud::StatusCode::kAborted) {
std::cout << "Delete was aborted\n";
} else {
throw std::move(commit_result).status();
}
Parameters | |
---|---|
Name | Description |
transaction_options |
Transaction::ReadWriteOptions
Execute the commit in a temporary transaction with these options. |
mutations |
Mutations
The mutations to be executed when this transaction commits. All mutations are applied atomically, in the order they appear in this list. |
opts |
Options
(optional) The options to use for this call. |
Returns | |
---|---|
Type | Description |
StatusOr< CommitResult > | A |
CommitAtLeastOnce(std::vector< Mutations >, Options)
Commits the mutation groups, batched efficiently into transactions with at-least-once semantics, using a single RPC.
All mutations within a group are committed atomically. There is no atomicity or ordering between groups however, so all groups must be independent of each other.
Partial failure is possible. That is, some groups can commit successfully while others fail. The results of individual batches are returned via the response stream as their transactions complete.
Mutation groups are not replay protected. That is, it is possible that each mutation group may be applied more than once. If the mutations are not idempotent, this may lead to a failure. For example, replays of an insert mutation might produce an "already exists" error, or, if you use generated or commit-timestamp-based keys, might result in additional rows being added to the mutation's table. We recommend structuring your mutation groups to be idempotent to avoid this issue.
Example
namespace spanner = ::google::cloud::spanner;
// Use upserts as mutation groups are not replay protected.
auto commit_results = client.CommitAtLeastOnce({
// group #0
spanner::Mutations{
spanner::InsertOrUpdateMutationBuilder(
"Singers", {"SingerId", "FirstName", "LastName"})
.EmplaceRow(16, "Scarlet", "Terry")
.Build(),
},
// group #1
spanner::Mutations{
spanner::InsertOrUpdateMutationBuilder(
"Singers", {"SingerId", "FirstName", "LastName"})
.EmplaceRow(17, "Marc", "")
.EmplaceRow(18, "Catalina", "Smith")
.Build(),
spanner::InsertOrUpdateMutationBuilder(
"Albums", {"SingerId", "AlbumId", "AlbumTitle"})
.EmplaceRow(17, 1, "Total Junk")
.EmplaceRow(18, 2, "Go, Go, Go")
.Build(),
},
});
for (auto& commit_result : commit_results) {
if (!commit_result) throw std::move(commit_result).status();
std::cout << "Mutation group indexes [";
for (auto index : commit_result->indexes) std::cout << " " << index;
std::cout << " ]: ";
if (commit_result->commit_timestamp) {
auto const& ts = *commit_result->commit_timestamp;
std::cout << "Committed at " << ts.get<absl::Time>().value();
} else {
std::cout << commit_result->commit_timestamp.status();
}
std::cout << "\n";
}
Parameters | |
---|---|
Name | Description |
mutation_groups |
std::vector< Mutations >
The mutation groups to be batched into temporary transactions and committed. |
opts |
Options
(optional) The options to use for this call. Expected options include any of the following types: |
Returns | |
---|---|
Type | Description |
BatchedCommitResultStream |
Rollback(Transaction, Options)
Rolls back a read-write transaction, releasing any locks it holds.
At any time before Commit
, the client can call Rollback
to abort the transaction. It is a good idea to call this for any read-write transaction that includes one or more Read
, ExecuteQuery
, or ExecuteDml
requests and ultimately decides not to commit.
Parameters | |
---|---|
Name | Description |
transaction |
Transaction
The transaction to roll back. |
opts |
Options
(optional) The options to use for this call. |
Returns | |
---|---|
Type | Description |
Status | The error status of the rollback. |
ExecutePartitionedDml(SqlStatement, Options)
Executes a Partitioned DML SQL query.
Example
void DmlPartitionedDelete(google::cloud::spanner::Client client) {
namespace spanner = ::google::cloud::spanner;
auto result = client.ExecutePartitionedDml(
spanner::SqlStatement("DELETE FROM Singers WHERE SingerId > 10"));
if (!result) throw std::move(result).status();
std::cout << "Deleted at least " << result->row_count_lower_bound
<< " row(s) [spanner_dml_partitioned_delete]\n";
}
See Also
Partitioned DML Transactions for an overview of Partitioned DML transactions.
See Also
Partitioned DML for a description of which SQL statements are supported in Partitioned DML transactions.
Parameters | |
---|---|
Name | Description |
statement |
SqlStatement
the SQL statement to execute. Please see the spanner documentation for the restrictions on the SQL statements supported by this function. |
opts |
Options
(optional) The |
Returns | |
---|---|
Type | Description |
StatusOr< PartitionedDmlResult > |