diff --git a/google/cloud/spanner/doc/spanner-main.dox b/google/cloud/spanner/doc/spanner-main.dox index fa936026d09a7..38379fb78fe7c 100644 --- a/google/cloud/spanner/doc/spanner-main.dox +++ b/google/cloud/spanner/doc/spanner-main.dox @@ -34,6 +34,7 @@ into your project. - @ref spanner-auth-example - @ref spanner-universe-domain-example - @ref spanner-mocking +- @ref spanner-isolation-level-example - The [Setting up your development environment] guide describes how to set up a C++ development environment in various platforms, including the Google Cloud C++ client libraries. @@ -65,6 +66,19 @@ Follow these links to find examples for other `*Client` classes: */ +/** +@page spanner-isolation-level-example Support Isolation Level + +Cloud Spanner supports different isolation levels for read-write transactions. +You can specify a default isolation level at the client-level, or override it +at the transaction-level. + +The following example shows how to set the isolation level: + +@snippet samples.cc spanner-isolation-level-setting-sample + +*/ + /** @page spanner-auth-example Override the authentication configuration diff --git a/google/cloud/spanner/samples/samples.cc b/google/cloud/spanner/samples/samples.cc index 1b677c184dda1..1ed50384ea708 100644 --- a/google/cloud/spanner/samples/samples.cc +++ b/google/cloud/spanner/samples/samples.cc @@ -22,6 +22,7 @@ #include "google/cloud/spanner/backoff_policy.h" #include "google/cloud/spanner/backup.h" #include "google/cloud/spanner/create_instance_request_builder.h" +#include "google/cloud/spanner/options.h" #include "google/cloud/spanner/row.h" #include "google/cloud/spanner/testing/debug_log.h" // TODO(#4758): remove #include "google/cloud/spanner/testing/instance_location.h" @@ -3472,6 +3473,71 @@ void ReadWriteTransaction(google::cloud::spanner::Client client) { } //! [END spanner_read_write_transaction] +//! [START spanner_isolation_level] [spanner-isolation-level-setting-sample] +void IsolationLevelSetting(std::string const& project_id, + std::string const& instance_id, + std::string const& database_id) { + namespace spanner = ::google::cloud::spanner; + using ::google::cloud::Options; + using ::google::cloud::StatusOr; + + auto db = spanner::Database(project_id, instance_id, database_id); + + // The isolation level specified at the client-level will be applied + // to all RW transactions. + auto options = Options{}.set( + spanner::Transaction::IsolationLevel::kSerializable); + auto client = spanner::Client(spanner::MakeConnection(db, options)); + + auto commit = client.Commit( + [&client]( + spanner::Transaction const& txn) -> StatusOr { + // Read an AlbumTitle. + auto sql = spanner::SqlStatement( + "SELECT AlbumTitle from Albums WHERE SingerId = @SingerId and " + "AlbumId = @AlbumId", + {{"SingerId", spanner::Value(1)}, {"AlbumId", spanner::Value(1)}}); + auto rows = client.ExecuteQuery(txn, std::move(sql)); + for (auto const& row : + spanner::StreamOf>(rows)) { + if (!row) return row.status(); + std::cout << "Current album title: " << std::get<0>(*row) << "\n"; + } + + // Update the title. + auto update_sql = spanner::SqlStatement( + "UPDATE Albums " + "SET AlbumTitle = @AlbumTitle " + "WHERE SingerId = @SingerId and AlbumId = @AlbumId", + {{"AlbumTitle", spanner::Value("New Album Title")}, + {"SingerId", spanner::Value(1)}, + {"AlbumId", spanner::Value(1)}}); + auto result = client.ExecuteDml(txn, std::move(update_sql)); + if (!result) return result.status(); + std::cout << result->RowsModified() << " record updated.\n"; + + return spanner::Mutations{}; + }, + // The isolation level specified at the transaction-level takes + // precedence over the isolation level configured at the client-level. + // kRepeatableRead is used here to demonstrate overriding the client-level + // setting. + Options{}.set( + spanner::Transaction::IsolationLevel::kRepeatableRead)); + + if (!commit) throw std::move(commit).status(); + std::cout << "Update was successful [spanner_isolation_level_setting]\n"; +} +//! [END spanner_isolation_level] [spanner-isolation-level-setting-sample], + +void IsolationLevelSettingCommand(std::vector argv) { + if (argv.size() != 3) { + throw std::runtime_error( + "isolation-level-setting "); + } + IsolationLevelSetting(argv[0], argv[1], argv[2]); +} + //! [START spanner_get_commit_stats] void GetCommitStatistics(google::cloud::spanner::Client client) { namespace spanner = ::google::cloud::spanner; @@ -5190,6 +5256,7 @@ int RunOneCommand(std::vector argv) { make_command_entry("read-data-with-storing-index", ReadDataWithStoringIndex), make_command_entry("read-write-transaction", ReadWriteTransaction), + {"isolation-level-setting", IsolationLevelSettingCommand}, make_command_entry("get-commit-stats", GetCommitStatistics), make_command_entry("dml-standard-insert", DmlStandardInsert), make_command_entry("dml-standard-update", DmlStandardUpdate), @@ -5888,6 +5955,9 @@ void RunAll(bool emulator) { SampleBanner("spanner_directed_read"); DirectedRead(project_id, instance_id, database_id); + SampleBanner("isolation-level-setting"); + IsolationLevelSetting(project_id, instance_id, database_id); + SampleBanner("spanner_batch_client"); UsePartitionQuery(client);