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.



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

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.



1082
1083
1084
# File 'lib/google/cloud/spanner/client.rb', line 1082

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.

Raises:

  • (ArgumentError)


724
725
726
727
728
729
730
# File 'lib/google/cloud/spanner/client.rb', line 724

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

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

#commit_timestampColumnValue

Creates a column value object representing setting a field’s value to the timestamp of the commit. (See Google::Cloud::Spanner::ColumnValue.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"

# create column value object
commit_timestamp = db.commit_timestamp

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

Returns:

  • (ColumnValue)

    The commit timestamp column value object.



1075
1076
1077
# File 'lib/google/cloud/spanner/client.rb', line 1075

def commit_timestamp
  ColumnValue.commit_timestamp
end

#create_new_sessionObject

Creates a new session object every time.



1089
1090
1091
1092
1093
1094
1095
1096
# File 'lib/google/cloud/spanner/client.rb', line 1089

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:



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

def database
  @project.database instance_id, database_id
end

#database_idString

The unique identifier for the database.

Returns:

  • (String)


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

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.



686
687
688
689
690
# File 'lib/google/cloud/spanner/client.rb', line 686

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.

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

Query with a SQL STRUCT query parameter as a Hash:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

user_hash = { id: 1, name: "Charlie", active: false }

results = db.execute "SELECT * FROM users WHERE " \
                     "ID = @user_struct.id " \
                     "AND name = @user_struct.name " \
                     "AND active = @user_struct.active",
                     params: { user_struct: user_hash }

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

Specify the SQL STRUCT type using Fields object:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

user_type = db.fields id: :INT64, name: :STRING, active: :BOOL
user_hash = { id: 1, name: nil, active: false }

results = db.execute "SELECT * FROM users WHERE " \
                     "ID = @user_struct.id " \
                     "AND name = @user_struct.name " \
                     "AND active = @user_struct.active",
                     params: { user_struct: user_hash },
                     types: { user_struct: user_type }

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

Or, query with a SQL STRUCT as a typed Data object:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

user_type = db.fields id: :INT64, name: :STRING, active: :BOOL
user_data = user_type.struct id: 1, name: nil, active: false

results = db.execute "SELECT * FROM users WHERE " \
                     "ID = @user_struct.id " \
                     "AND name = @user_struct.name " \
                     "AND active = @user_struct.active",
                     params: { user_struct: user_data }

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

    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. | | `STRUCT` | `Hash`, Data | |

    See [Data types](cloud.google.com/spanner/docs/data-definition-language#data_types).

    See [Data Types - Constructing a STRUCT](cloud.google.com/spanner/docs/data-types#constructing-a-struct).

  • 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 must be used to specify the SQL type for these values.

    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`

    • ‘Array` - Lists are specified by providing the type code in an array. For example, an array of integers are specified as `[:INT64]`.

    • Fields - Types for STRUCT values (‘Hash`/Data objects) are specified using a Fields object.

    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:



299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/google/cloud/spanner/client.rb', line 299

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

  params, types = Convert.to_input_params_and_types params, types

  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 a configuration object (Fields) that may be provided to queries or used to create STRUCT objects. (The STRUCT will be represented by the Data class.) See #execute and/or Fields#struct.

For more information, see [Data Types - Constructing a STRUCT](cloud.google.com/spanner/docs/data-types#constructing-a-struct).

Examples:

Create a STRUCT value with named fields using Fields object:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

named_type = db.fields(
  { id: :INT64, name: :STRING, active: :BOOL }
)
named_data = named_type.struct(
  { id: 42, name: nil, active: false }
)

Create a STRUCT value with anonymous field names:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

anon_type = db.fields [:INT64, :STRING, :BOOL]
anon_data = anon_type.struct [42, nil, false]

Create a STRUCT value with duplicate field names:

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new

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

dup_type = db.fields [[:x, :INT64], [:x, :STRING], [:x, :BOOL]]
dup_data = dup_type.struct [42, nil, false]

Parameters:

  • types (Array, Hash)

    Accepts an array or hash types.

    Arrays can contain just the type value, or a sub-array of the field’s name and type value. Hash keys must contain the field name as a ‘Symbol` or `String`, or the field position as an `Integer`. Hash values must contain the type value. If a Hash is used the fields will be created using the same order as the Hash keys.

    Supported type values incude:

    • ‘:BOOL`

    • ‘:BYTES`

    • ‘:DATE`

    • ‘:FLOAT64`

    • ‘:INT64`

    • ‘:STRING`

    • ‘:TIMESTAMP`

    • ‘Array` - Lists are specified by providing the type code in an array. For example, an array of integers are specified as `[:INT64]`.

    • Fields - Nested Structs are specified by providing a Fields object.

Returns:

  • (Fields)

    The fields of the given types.



987
988
989
# File 'lib/google/cloud/spanner/client.rb', line 987

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.



1012
1013
1014
# File 'lib/google/cloud/spanner/client.rb', line 1012

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.



536
537
538
539
540
# File 'lib/google/cloud/spanner/client.rb', line 536

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

#inspectObject



1105
1106
1107
# File 'lib/google/cloud/spanner/client.rb', line 1105

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

#instanceInstance

The Spanner instance connected to.

Returns:



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

def instance
  @project.instance instance_id
end

#instance_idString

The unique identifier for the instance.

Returns:

  • (String)


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

def instance_id
  @instance_id
end

#projectProject

The Spanner project connected to.

Returns:



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

def project
  @project
end

#project_idString

The unique identifier for the project.

Returns:

  • (String)


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

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:



1044
1045
1046
1047
1048
# File 'lib/google/cloud/spanner/client.rb', line 1044

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:



412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
# File 'lib/google/cloud/spanner/client.rb', line 412

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

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

  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.



648
649
650
651
652
# File 'lib/google/cloud/spanner/client.rb', line 648

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` seconds old. For example, the number 10.1 is translated to 10 seconds and 100 milliseconds.

    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:



891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
# File 'lib/google/cloud/spanner/client.rb', line 891

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?
    raise "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



1099
1100
1101
1102
# File 'lib/google/cloud/spanner/client.rb', line 1099

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.



792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
# File 'lib/google/cloud/spanner/client.rb', line 792

def transaction deadline: 120
  ensure_service!
  unless Thread.current[:transaction_id].nil?
    raise "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
      yield 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 StandardError => 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.



591
592
593
594
595
# File 'lib/google/cloud/spanner/client.rb', line 591

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.



480
481
482
483
484
# File 'lib/google/cloud/spanner/client.rb', line 480

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