Class: Google::Cloud::Spanner::Transaction

Inherits:
Object
  • Object
show all
Defined in:
lib/google/cloud/spanner/transaction.rb

Overview

Transaction

A transaction in Cloud Spanner is a set of reads and writes that execute atomically at a single logical point in time across columns, rows, and tables in a database.

All changes are accumulated in memory until the block passed to Client#transaction completes. Transactions will be automatically retried when possible. See Client#transaction.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"

db.transaction do |tx|
  # Read the second album budget.
  second_album_result = tx.read "Albums", ["marketing_budget"],
                                keys: [[2, 2]], limit: 1
  second_album_row = second_album_result.rows.first
  second_album_budget = second_album_row.values.first

  transfer_amount = 200000

  if second_album_budget < 300000
    # Raising an exception will automatically roll back the
    # transaction.
    raise "The second album doesn't have enough funds to transfer"
  end

  # Read the first album's budget.
  first_album_result = tx.read "Albums", ["marketing_budget"],
                                keys: [[1, 1]], limit: 1
  first_album_row = first_album_result.rows.first
  first_album_budget = first_album_row.values.first

  # Update the budgets.
  second_album_budget -= transfer_amount
  first_album_budget += transfer_amount
  puts "Setting first album's budget to #{first_album_budget} and " \
       "the second album's budget to #{second_album_budget}."

  # Update the rows.
  rows = [
    {singer_id: 1, album_id: 1, marketing_budget: first_album_budget},
    {singer_id: 2, album_id: 2, marketing_budget: second_album_budget}
  ]
  tx.update "Albums", rows
end

Instance Method Summary collapse

Constructor Details

#initializeTransaction

Returns a new instance of Transaction



80
81
82
# File 'lib/google/cloud/spanner/transaction.rb', line 80

def initialize
  @commit = Commit.new
end

Instance Method Details

#commit_timestampColumnValue

Creates a column value object representing setting a field's value to the timestamp of the commit. (See Client#commit_timestamp)

This placeholder value can only be used for timestamp columns that have set the option "(allow_commit_timestamp=true)" in the schema.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

db = spanner.client "my-instance", "my-database"

db.transaction do |tx|
  tx.insert "users", [
    { id: 5, name: "Murphy", updated_at: tx.commit_timestamp }
  ]
end

Returns:

  • (ColumnValue)

    The commit timestamp column value object.



528
529
530
# File 'lib/google/cloud/spanner/transaction.rb', line 528

def commit_timestamp
  ColumnValue.commit_timestamp
end

#delete(table, keys = []) ⇒ Object

Deletes rows from a table. Succeeds whether or not the specified rows were present.

All changes are accumulated in memory until the block passed to Client#transaction completes.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"

db.transaction { |tx| tx.delete "users", [1, 2, 3] }

Parameters:

  • table (String)

    The name of the table in the database to be modified.

  • keys (Object, Array<Object>) (defaults to: [])

    A single, or list of keys or key ranges to match returned data to. Values should have exactly as many elements as there are columns in the primary key.



439
440
441
442
# File 'lib/google/cloud/spanner/transaction.rb', line 439

def delete table, keys = []
  ensure_session!
  @commit.delete table, keys
end

#execute(sql, params: nil, types: nil) ⇒ Google::Cloud::Spanner::Results Also known as: query

Executes a SQL query.

Arguments can be passed using params, Ruby types are mapped to Spanner types as follows:

Spanner Ruby Notes
BOOL true/false
INT64 Integer
FLOAT64 Float
STRING String
DATE Date
TIMESTAMP Time, DateTime
BYTES File, IO, StringIO, or similar
ARRAY Array Nested arrays are not supported.

See Data types.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"

db.transaction do |tx|
  results = tx.execute "SELECT * FROM users"

  results.rows.each do |row|
    puts "User #{row[:id]} is #{row[:name]}"
  end
end

Query using query parameters:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"

db.transaction do |tx|
  results = tx.execute "SELECT * FROM users WHERE active = @active",
                       params: { active: true }

  results.rows.each do |row|
    puts "User #{row[:id]} is #{row[:name]}"
  end
end

Parameters:

  • sql (String)

    The SQL query string. See Query syntax.

    The SQL query string can contain parameter placeholders. A parameter placeholder consists of "@" followed by the parameter name. Parameter names consist of any combination of letters, numbers, and underscores.

  • params (Hash)

    SQL parameters for the query string. The parameter placeholders, minus the "@", are the the hash keys, and the literal values are the hash values. If the query string contains something like "WHERE id > @msg_id", then the params must contain something like :msg_id => 1.

  • types (Hash)

    Types of the SQL parameters in params. It is not always possible for Cloud Spanner to infer the right SQL type from a value in params. In these cases, the types hash can be used to specify the exact SQL type for some or all of the SQL query parameters.

    The keys of the hash should be query string parameter placeholders, minus the "@". The values of the hash should be Cloud Spanner type codes from the following list:

    • :BOOL
    • :BYTES
    • :DATE
    • :FLOAT64
    • :INT64
    • :STRING
    • :TIMESTAMP

    Arrays are specified by providing the type code in an array. For example, an array of integers are specified as [:INT64].

    Structs are not yet supported in query parameters.

    Types are optional.

Returns:



180
181
182
183
184
185
186
187
# File 'lib/google/cloud/spanner/transaction.rb', line 180

def execute sql, params: nil, types: nil
  ensure_session!

  params, types = Convert.to_input_params_and_types params, types

  session.execute sql, params: params, types: types,
                       transaction: tx_selector
end

#insert(table, *rows) ⇒ Object

Inserts new rows in a table. If any of the rows already exist, the write or request fails with error AlreadyExistsError.

All changes are accumulated in memory until the block passed to Client#transaction completes.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"

db.transaction do |tx|
  tx.insert "users", [{ id: 1, name: "Charlie", active: false },
                      { id: 2, name: "Harvey",  active: true }]
end

Parameters:

  • table (String)

    The name of the table in the database to be modified.

  • rows (Array<Hash>)

    One or more hash objects with the hash keys matching the table's columns, and the hash values matching the table's values.

    Ruby types are mapped to Spanner types as follows:

    Spanner Ruby Notes
    BOOL true/false
    INT64 Integer
    FLOAT64 Float
    STRING String
    DATE Date
    TIMESTAMP Time, DateTime
    BYTES File, IO, StringIO, or similar
    ARRAY Array Nested arrays are not supported.

    See Data types.



321
322
323
324
# File 'lib/google/cloud/spanner/transaction.rb', line 321

def insert table, *rows
  ensure_session!
  @commit.insert table, rows
end

#range(beginning, ending, exclude_begin: false, exclude_end: false) ⇒ Google::Cloud::Spanner::Range

Creates a Cloud Spanner Range. This can be used in place of a Ruby Range when needing to exclude the beginning value.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"

db.transaction do |tx|
  key_range = tx.range 1, 100
  results = tx.read "users", [:id, :name], keys: key_range

  results.rows.each do |row|
    puts "User #{row[:id]} is #{row[:name]}"
  end
end

Parameters:

  • beginning (Object)

    The object that defines the beginning of the range.

  • ending (Object)

    The object that defines the end of the range.

  • exclude_begin (Boolean)

    Determines if the range excludes its beginning value. Default is false.

  • exclude_end (Boolean)

    Determines if the range excludes its ending value. Default is false.

Returns:



500
501
502
503
504
# File 'lib/google/cloud/spanner/transaction.rb', line 500

def range beginning, ending, exclude_begin: false, exclude_end: false
  Range.new beginning, ending,
            exclude_begin: exclude_begin,
            exclude_end: exclude_end
end

#read(table, columns, keys: nil, index: nil, limit: nil) ⇒ Google::Cloud::Spanner::Results

Read rows from a database table, as a simple alternative to #execute.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"

db.transaction do |tx|
  results = tx.read "users", [:id, :name]

  results.rows.each do |row|
    puts "User #{row[:id]} is #{row[:name]}"
  end
end

Parameters:

  • table (String)

    The name of the table in the database to be read.

  • columns (Array<String, Symbol>)

    The columns of table to be returned for each row matching this request.

  • keys (Object, Array<Object>)

    A single, or list of keys or key ranges to match returned data to. Values should have exactly as many elements as there are columns in the primary key.

  • index (String)

    The name of an index to use instead of the table's primary key when interpreting id and sorting result rows. Optional.

  • limit (Integer)

    If greater than zero, no more than this number of rows will be returned. The default is no limit.

Returns:



224
225
226
227
228
229
230
231
232
# File 'lib/google/cloud/spanner/transaction.rb', line 224

def read table, columns, keys: nil, index: nil, limit: nil
  ensure_session!

  columns = Array(columns).map(&:to_s)
  keys = Convert.to_key_set keys

  session.read table, columns, keys: keys, index: index, limit: limit,
                               transaction: tx_selector
end

#replace(table, *rows) ⇒ Object

Inserts or replaces rows in a table. If any of the rows already exist, it is deleted, and the column values provided are inserted instead. Unlike #upsert, this means any values not explicitly written become NULL.

All changes are accumulated in memory until the block passed to Client#transaction completes.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"

db.transaction do |tx|
  tx.replace "users", [{ id: 1, name: "Charlie", active: false },
                       { id: 2, name: "Harvey",  active: true }]
end

Parameters:

  • table (String)

    The name of the table in the database to be modified.

  • rows (Array<Hash>)

    One or more hash objects with the hash keys matching the table's columns, and the hash values matching the table's values.

    Ruby types are mapped to Spanner types as follows:

    Spanner Ruby Notes
    BOOL true/false
    INT64 Integer
    FLOAT64 Float
    STRING String
    DATE Date
    TIMESTAMP Time, DateTime
    BYTES File, IO, StringIO, or similar
    ARRAY Array Nested arrays are not supported.

    See Data types.



413
414
415
416
# File 'lib/google/cloud/spanner/transaction.rb', line 413

def replace table, *rows
  ensure_session!
  @commit.replace table, rows
end

#transaction_idString

Identifier of the transaction results were run in.

Returns:

  • (String)

    The transaction id.



87
88
89
90
# File 'lib/google/cloud/spanner/transaction.rb', line 87

def transaction_id
  return nil if @grpc.nil?
  @grpc.id
end

#update(table, *rows) ⇒ Object

Updates existing rows in a table. If any of the rows does not already exist, the request fails with error NotFoundError.

All changes are accumulated in memory until the block passed to Client#transaction completes.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"

db.transaction do |tx|
  tx.update "users", [{ id: 1, name: "Charlie", active: false },
                      { id: 2, name: "Harvey",  active: true }]
end

Parameters:

  • table (String)

    The name of the table in the database to be modified.

  • rows (Array<Hash>)

    One or more hash objects with the hash keys matching the table's columns, and the hash values matching the table's values.

    Ruby types are mapped to Spanner types as follows:

    Spanner Ruby Notes
    BOOL true/false
    INT64 Integer
    FLOAT64 Float
    STRING String
    DATE Date
    TIMESTAMP Time, DateTime
    BYTES File, IO, StringIO, or similar
    ARRAY Array Nested arrays are not supported.

    See Data types.



366
367
368
369
# File 'lib/google/cloud/spanner/transaction.rb', line 366

def update table, *rows
  ensure_session!
  @commit.update table, rows
end

#upsert(table, *rows) ⇒ Object Also known as: save

Inserts or updates rows in a table. If any of the rows already exist, then its column values are overwritten with the ones provided. Any column values not explicitly written are preserved.

All changes are accumulated in memory until the block passed to Client#transaction completes.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"

db.transaction do |tx|
  tx.upsert "users", [{ id: 1, name: "Charlie", active: false },
                      { id: 2, name: "Harvey",  active: true }]
end

Parameters:

  • table (String)

    The name of the table in the database to be modified.

  • rows (Array<Hash>)

    One or more hash objects with the hash keys matching the table's columns, and the hash values matching the table's values.

    Ruby types are mapped to Spanner types as follows:

    Spanner Ruby Notes
    BOOL true/false
    INT64 Integer
    FLOAT64 Float
    STRING String
    DATE Date
    TIMESTAMP Time, DateTime
    BYTES File, IO, StringIO, or similar
    ARRAY Array Nested arrays are not supported.

    See Data types.



275
276
277
278
# File 'lib/google/cloud/spanner/transaction.rb', line 275

def upsert table, *rows
  ensure_session!
  @commit.upsert table, rows
end