Class: Google::Cloud::Spanner::Client

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

Overview

# Client

A client is used to read and/or modify data in a Cloud Spanner database.

See Project#client.

Examples:

require "google/cloud"

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

Instance Method Summary collapse

Constructor Details

#initialize(project, instance_id, database_id, opts = {}) ⇒ Client

Returns a new instance of Client.



54
55
56
57
58
59
# File 'lib/google/cloud/spanner/client.rb', line 54

def initialize project, instance_id, database_id, opts = {}
  @project = project
  @instance_id = instance_id
  @database_id = database_id
  @pool = Pool.new self, opts
end

Instance Method Details

#closeObject

Closes the client connection and releases resources.



937
938
939
# File 'lib/google/cloud/spanner/client.rb', line 937

def close
  @pool.close
end

#commit {|commit| ... } ⇒ Time

Creates and commits a transaction for 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 completes. Unlike #transaction, which can also perform reads, this operation accepts only mutations and makes a single API request.

Note: This method does not feature replay protection present in Transaction#commit (See #transaction). This method makes a single RPC, whereas Transaction#commit requires two RPCs (one of which may be performed in advance), and so this method may be appropriate for latency sensitive and/or high throughput blind changes.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

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

Yields:

  • (commit)

    The block for mutating the data.

Yield Parameters:

Returns:

  • (Time)

    The timestamp at which the operation committed.



656
657
658
659
660
661
662
# File 'lib/google/cloud/spanner/client.rb', line 656

def commit &block
  fail ArgumentError, "Must provide a block" unless block_given?

  @pool.with_session do |session|
    session.commit(&block)
  end
end

#create_new_sessionObject

Creates a new session object every time.



944
945
946
947
948
949
950
# File 'lib/google/cloud/spanner/client.rb', line 944

def create_new_session
  ensure_service!
  grpc = @project.service.create_session \
    Admin::Database::V1::DatabaseAdminClient.database_path(
      project_id, instance_id, database_id)
  Session.from_grpc(grpc, @project.service)
end

#databaseDatabase

The Spanner database connected to.

Returns:



93
94
95
# File 'lib/google/cloud/spanner/client.rb', line 93

def database
  @project.database instance_id, database_id
end

#database_idString

The unique identifier for the database.

Returns:

  • (String)


75
76
77
# File 'lib/google/cloud/spanner/client.rb', line 75

def database_id
  @database_id
end

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

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

Changes are made immediately upon calling this method using a single-use transaction. To make multiple changes in the same single-use transaction use #commit. To make changes in a transaction that supports reads and automatic retry protection use #transaction.

Note: This method does not feature replay protection present in Transaction#delete (See #transaction). This method makes a single RPC, whereas Transaction#delete requires two RPCs (one of which may be performed in advance), and so this method may be appropriate for latency sensitive and/or high throughput blind deletions.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

db.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.

Returns:

  • (Time)

    The timestamp at which the operation committed.



618
619
620
621
622
# File 'lib/google/cloud/spanner/client.rb', line 618

def delete table, keys = []
  @pool.with_session do |session|
    session.delete table, keys
  end
end

#execute(sql, params: nil, types: nil, single_use: 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](cloud.google.com/spanner/docs/data-definition-language#data_types).

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

results = db.execute "SELECT * FROM users"

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

Query using query parameters:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

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

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

Parameters:

  • sql (String)

    The SQL query string. See [Query syntax](cloud.google.com/spanner/docs/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) (defaults to: nil)

    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) (defaults to: nil)

    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.

  • single_use (Hash) (defaults to: nil)

    Perform the read with a single-use snapshot (read-only transaction). (See [TransactionOptions](cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#transactionoptions).) The snapshot can be created by providing exactly one of the following options in the hash:

    • Strong

      • ‘:strong` (true, false) Read at a timestamp where all previously committed transactions are visible.

    • Exact

      • ‘:timestamp`/`:read_timestamp` (Time, DateTime) Executes all reads at the given timestamp. Unlike other modes, reads at a specific timestamp are repeatable; the same read at the same timestamp always returns the same data. If the timestamp is in the future, the read will block until the specified timestamp, modulo the read’s deadline.

        Useful for large scale consistent reads such as mapreduces, or for coordinating many reads against a consistent snapshot of the data.

      • ‘:staleness`/`:exact_staleness` (Numeric) Executes all reads at a timestamp that is exactly the number of seconds provided old. The timestamp is chosen soon after the read is started.

        Guarantees that all writes that have committed more than the specified number of seconds ago are visible. Because Cloud Spanner chooses the exact timestamp, this mode works even if the client’s local clock is substantially skewed from Cloud Spanner commit timestamps.

        Useful for reading at nearby replicas without the distributed timestamp negotiation overhead of single-use ‘bounded_staleness`.

    • Bounded

      • ‘:bounded_timestamp`/`:min_read_timestamp` (Time, DateTime) Executes all reads at a timestamp greater than the value provided.

        This is useful for requesting fresher data than some previous read, or data that is fresh enough to observe the effects of some previously committed transaction whose timestamp is known.

      • ‘:bounded_staleness`/`:max_staleness` (Numeric) Read data at a timestamp greater than or equal to the number of seconds provided. Guarantees that all writes that have committed more than the specified number of seconds ago are visible. Because Cloud Spanner chooses the exact timestamp, this mode works even if the client’s local clock is substantially skewed from Cloud Spanner commit timestamps.

        Useful for reading the freshest data available at a nearby replica, while bounding the possible staleness if the local replica has fallen behind.

Returns:



236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/google/cloud/spanner/client.rb', line 236

def execute sql, params: nil, types: nil, single_use: nil
  validate_single_use_args! single_use
  ensure_service!

  single_use_tx = single_use_transaction single_use
  results = nil
  @pool.with_session do |session|
    results = session.execute \
      sql, params: params, types: types, transaction: single_use_tx
  end
  results
end

#fields(types) ⇒ Fields

Creates fields object from types.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

db = spanner.client "my-instance", "my-database"
user_fields = db.fields id: :INT64, name: :STRING, active: :BOOL

db.update "users", [user_fields.data(1, "Charlie", false),
                    user_fields.data(2, "Harvey", true)]

Parameters:

  • types (Array, Hash)

    Accepts an array of types, array of type pairs, hash of positional types, hash of named types.

Returns:

  • (Fields)

    The fields of the given types.



871
872
873
# File 'lib/google/cloud/spanner/client.rb', line 871

def fields types
  Fields.new types
end

#fields_for(table) ⇒ Fields

Executes a query to retrieve the field names and types for a table.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

users_types = db.fields_for "users"
db.insert "users", [{ id: 1, name: "Charlie", active: false },
                    { id: 2, name: "Harvey",  active: true }],
          types: users_types

Parameters:

  • table (String)

    The name of the table in the database to retrieve fields for.

Returns:

  • (Fields)

    The fields of the given table.



896
897
898
# File 'lib/google/cloud/spanner/client.rb', line 896

def fields_for table
  execute("SELECT * FROM #{table} WHERE 1 = 0").fields
end

#insert(table, *rows) ⇒ Time

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

Changes are made immediately upon calling this method using a single-use transaction. To make multiple changes in the same single-use transaction use #commit. To make changes in a transaction that supports reads and automatic retry protection use #transaction.

Note: This method does not feature replay protection present in Transaction#insert (See #transaction). This method makes a single RPC, whereas Transaction#insert requires two RPCs (one of which may be performed in advance), and so this method may be appropriate for latency sensitive and/or high throughput blind inserts.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

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

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](cloud.google.com/spanner/docs/data-definition-language#data_types).

Returns:

  • (Time)

    The timestamp at which the operation committed.



468
469
470
471
472
# File 'lib/google/cloud/spanner/client.rb', line 468

def insert table, *rows
  @pool.with_session do |session|
    session.insert table, rows
  end
end

#inspectObject



959
960
961
# File 'lib/google/cloud/spanner/client.rb', line 959

def inspect
  "#<#{self.class.name} #{self}>"
end

#instanceInstance

The Spanner instance connected to.

Returns:



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

def instance
  @project.instance instance_id
end

#instance_idString

The unique identifier for the instance.

Returns:

  • (String)


69
70
71
# File 'lib/google/cloud/spanner/client.rb', line 69

def instance_id
  @instance_id
end

#projectProject

The Spanner project connected to.

Returns:



81
82
83
# File 'lib/google/cloud/spanner/client.rb', line 81

def project
  @project
end

#project_idString

The unique identifier for the project.

Returns:

  • (String)


63
64
65
# File 'lib/google/cloud/spanner/client.rb', line 63

def project_id
  @project.service.project
end

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

Creates a 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"

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

results.rows.each do |row|
  puts "User #{row[:id]} is #{row[:name]}"
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) (defaults to: false)

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

  • exclude_end (Boolean) (defaults to: false)

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

Returns:



928
929
930
931
932
# File 'lib/google/cloud/spanner/client.rb', line 928

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, single_use: 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"

results = db.read "users", [:id, :name]

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

Use the ‘keys` option to pass keys and/or key ranges to read.

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

results = db.read "users", [:id, :name], keys: 1..5

results.rows.each do |row|
  puts "User #{row[:id]} is #{row[:name]}"
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>) (defaults to: nil)

    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) (defaults to: nil)

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

  • limit (Integer) (defaults to: nil)

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

  • single_use (Hash) (defaults to: nil)

    Perform the read with a single-use snapshot (read-only transaction). (See [TransactionOptions](cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#transactionoptions).) The snapshot can be created by providing exactly one of the following options in the hash:

    • Strong

      • ‘:strong` (true, false) Read at a timestamp where all previously committed transactions are visible.

    • Exact

      • ‘:timestamp`/`:read_timestamp` (Time, DateTime) Executes all reads at the given timestamp. Unlike other modes, reads at a specific timestamp are repeatable; the same read at the same timestamp always returns the same data. If the timestamp is in the future, the read will block until the specified timestamp, modulo the read’s deadline.

        Useful for large scale consistent reads such as mapreduces, or for coordinating many reads against a consistent snapshot of the data.

      • ‘:staleness`/`:exact_staleness` (Numeric) Executes all reads at a timestamp that is exactly the number of seconds provided old. The timestamp is chosen soon after the read is started.

        Guarantees that all writes that have committed more than the specified number of seconds ago are visible. Because Cloud Spanner chooses the exact timestamp, this mode works even if the client’s local clock is substantially skewed from Cloud Spanner commit timestamps.

        Useful for reading at nearby replicas without the distributed timestamp negotiation overhead of single-use ‘bounded_staleness`.

    • Bounded

      • ‘:bounded_timestamp`/`:min_read_timestamp` (Time, DateTime) Executes all reads at a timestamp greater than the value provided.

        This is useful for requesting fresher data than some previous read, or data that is fresh enough to observe the effects of some previously committed transaction whose timestamp is known.

      • ‘:bounded_staleness`/`:max_staleness` (Numeric) Read data at a timestamp greater than or equal to the number of seconds provided. Guarantees that all writes that have committed more than the specified number of seconds ago are visible. Because Cloud Spanner chooses the exact timestamp, this mode works even if the client’s local clock is substantially skewed from Cloud Spanner commit timestamps.

        Useful for reading the freshest data available at a nearby replica, while bounding the possible staleness if the local replica has fallen behind.

Returns:



347
348
349
350
351
352
353
354
355
356
357
358
359
360
# File 'lib/google/cloud/spanner/client.rb', line 347

def read table, columns, keys: nil, index: nil, limit: nil,
         single_use: nil
  validate_single_use_args! single_use
  ensure_service!

  single_use_tx = single_use_transaction single_use
  results = nil
  @pool.with_session do |session|
    results = session.read \
      table, columns, keys: keys, index: index, limit: limit,
                      transaction: single_use_tx
  end
  results
end

#replace(table, *rows) ⇒ Time

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`.

Changes are made immediately upon calling this method using a single-use transaction. To make multiple changes in the same single-use transaction use #commit. To make changes in a transaction that supports reads and automatic retry protection use #transaction.

Note: This method does not feature replay protection present in Transaction#replace (See #transaction). This method makes a single RPC, whereas Transaction#replace requires two RPCs (one of which may be performed in advance), and so this method may be appropriate for latency sensitive and/or high throughput blind replaces.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

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

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](cloud.google.com/spanner/docs/data-definition-language#data_types).

Returns:

  • (Time)

    The timestamp at which the operation committed.



580
581
582
583
584
# File 'lib/google/cloud/spanner/client.rb', line 580

def replace table, *rows
  @pool.with_session do |session|
    session.replace table, rows
  end
end

#snapshot(strong: nil, timestamp: nil, read_timestamp: nil, staleness: nil, exact_staleness: nil) {|snapshot| ... } ⇒ Object

Creates a snapshot read-only transaction for reads that execute atomically at a single logical point in time across columns, rows, and tables in a database. For transactions that only read, snapshot read-only transactions provide simpler semantics and are almost always faster than read-write transactions.

Examples:

require "google/cloud/spanner"

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

db.snapshot do |snp|
  results = snp.execute "SELECT * FROM users"

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

Parameters:

  • strong (true, false) (defaults to: nil)

    Read at a timestamp where all previously committed transactions are visible.

  • timestamp (Time, DateTime) (defaults to: nil)

    Executes all reads at the given timestamp. Unlike other modes, reads at a specific timestamp are repeatable; the same read at the same timestamp always returns the same data. If the timestamp is in the future, the read will block until the specified timestamp, modulo the read’s deadline.

    Useful for large scale consistent reads such as mapreduces, or for coordinating many reads against a consistent snapshot of the data. (See [TransactionOptions](cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#transactionoptions).)

  • read_timestamp (Time, DateTime) (defaults to: nil)

    Same as ‘timestamp`.

  • staleness (Numeric) (defaults to: nil)

    Executes all reads at a timestamp that is staleness old. The timestamp is chosen soon after the read is started.

    Guarantees that all writes that have committed more than the specified number of seconds ago are visible. Because Cloud Spanner chooses the exact timestamp, this mode works even if the client’s local clock is substantially skewed from Cloud Spanner commit timestamps.

    Useful for reading at nearby replicas without the distributed timestamp negotiation overhead of single-use staleness. (See [TransactionOptions](cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#transactionoptions).)

  • exact_staleness (Numeric) (defaults to: nil)

    Same as ‘staleness`.

Yields:

  • (snapshot)

    The block for reading and writing data.

Yield Parameters:



823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
# File 'lib/google/cloud/spanner/client.rb', line 823

def snapshot strong: nil, timestamp: nil, read_timestamp: nil,
             staleness: nil, exact_staleness: nil
  validate_snapshot_args! strong: strong, timestamp: timestamp,
                          read_timestamp: read_timestamp,
                          staleness: staleness,
                          exact_staleness: exact_staleness

  ensure_service!
  unless Thread.current[:transaction_id].nil?
    fail "Nested snapshots are not allowed"
  end

  @pool.with_session do |session|
    begin
      snp_grpc = @project.service.create_snapshot \
        session.path, strong: strong,
                      timestamp: (timestamp || read_timestamp),
                      staleness: (staleness || exact_staleness)
      Thread.current[:transaction_id] = snp_grpc.id
      snp = Snapshot.from_grpc(snp_grpc, session)
      yield snp if block_given?
    ensure
      Thread.current[:transaction_id] = nil
    end
  end
  nil
end

#to_sObject



953
954
955
956
# File 'lib/google/cloud/spanner/client.rb', line 953

def to_s
  "(project_id: #{project_id}, instance_id: #{instance_id}, " \
    "database_id: #{database_id})"
end

#transaction(deadline: 120) {|transaction| ... } ⇒ Time

Creates a transaction for reads and writes that execute atomically at a single logical point in time across columns, rows, and tables in a database.

The transaction will always commit unless an error is raised. If the error raised is Rollback the transaction method will return without passing on the error. All other errors will be passed on.

All changes are accumulated in memory until the block completes. Transactions will be automatically retried when possible, until ‘deadline` is reached. This operation makes separate API requests to begin and commit the transaction.

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

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

Manually rollback the transaction using Rollback:

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 }]
  tx.insert "users", [{ id: 2, name: "Harvey",  active: true }]

  if something_wrong?
    # Rollback the transaction without passing on the error
    # outside of the transaction method.
    raise Google::Cloud::Spanner::Rollback
  end
end

Parameters:

  • deadline (Numeric) (defaults to: 120)

    The total amount of time in seconds the transaction has to succeed. The default is ‘120`.

Yields:

  • (transaction)

    The block for reading and writing data.

Yield Parameters:

Returns:

  • (Time)

    The timestamp at which the transaction committed.



724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
# File 'lib/google/cloud/spanner/client.rb', line 724

def transaction deadline: 120, &block
  ensure_service!
  unless Thread.current[:transaction_id].nil?
    fail "Nested transactions are not allowed"
  end

  deadline = validate_deadline deadline
  backoff = 1.0
  start_time = current_time

  @pool.with_transaction do |tx|
    begin
      Thread.current[:transaction_id] = tx.transaction_id
      block.call tx
      commit_resp = @project.service.commit \
        tx.session.path, tx.mutations, transaction_id: tx.transaction_id
      return Convert.timestamp_to_time commit_resp.commit_timestamp
    rescue GRPC::Aborted, Google::Cloud::AbortedError => err
      # Re-raise if deadline has passed
      if current_time - start_time > deadline
        if err.is_a? GRPC::BadStatus
          err = Google::Cloud::Error.from_error err
        end
        raise err
      end
      # Sleep the amount from RetryDelay, or incremental backoff
      sleep(delay_from_aborted(err) || backoff *= 1.3)
      # Create new transaction on the session and retry the block
      tx = tx.session.create_transaction
      retry
    rescue => err
      # Rollback transaction when handling unexpected error
      tx.session.rollback tx.transaction_id
      # Return nil if raised with rollback.
      return nil if err.is_a? Rollback
      # Re-raise error.
      raise err
    ensure
      Thread.current[:transaction_id] = nil
    end
  end
end

#update(table, *rows) ⇒ Time

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

Changes are made immediately upon calling this method using a single-use transaction. To make multiple changes in the same single-use transaction use #commit. To make changes in a transaction that supports reads and automatic retry protection use #transaction.

Note: This method does not feature replay protection present in Transaction#update (See #transaction). This method makes a single RPC, whereas Transaction#update requires two RPCs (one of which may be performed in advance), and so this method may be appropriate for latency sensitive and/or high throughput blind updates.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

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

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](cloud.google.com/spanner/docs/data-definition-language#data_types).

Returns:

  • (Time)

    The timestamp at which the operation committed.



523
524
525
526
527
# File 'lib/google/cloud/spanner/client.rb', line 523

def update table, *rows
  @pool.with_session do |session|
    session.update table, rows
  end
end

#upsert(table, *rows) ⇒ Time 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.

Changes are made immediately upon calling this method using a single-use transaction. To make multiple changes in the same single-use transaction use #commit. To make changes in a transaction that supports reads and automatic retry protection use #transaction.

Note: This method does not feature replay protection present in Transaction#upsert (See #transaction). This method makes a single RPC, whereas Transaction#upsert requires two RPCs (one of which may be performed in advance), and so this method may be appropriate for latency sensitive and/or high throughput blind upserts.

Examples:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

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

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](cloud.google.com/spanner/docs/data-definition-language#data_types).

Returns:

  • (Time)

    The timestamp at which the operation committed.



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

def upsert table, *rows
  @pool.with_session do |session|
    session.upsert table, rows
  end
end