Class: Google::Cloud::Spanner::Session

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

Overview

Session

A session can be used to perform transactions that read and/or modify data in a Cloud Spanner database. Sessions are meant to be reused for many consecutive transactions.

Sessions can only execute one transaction at a time. To execute multiple concurrent read-write/write-only transactions, create multiple sessions. Note that standalone reads and queries use a transaction internally, and count toward the one transaction limit.

Cloud Spanner limits the number of sessions that can exist at any given time; thus, it is a good idea to delete idle and/or unneeded sessions. Aside from explicit deletes, Cloud Spanner can delete sessions for which no operations are sent for more than an hour.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(grpc, service) ⇒ Session

Returns a new instance of Session.



52
53
54
55
# File 'lib/google/cloud/spanner/session.rb', line 52

def initialize grpc, service
  @grpc = grpc
  @service = service
end

Instance Attribute Details

#grpc ⇒ Object



45
46
47
# File 'lib/google/cloud/spanner/session.rb', line 45

def grpc
  @grpc
end

#service ⇒ Object



49
50
51
# File 'lib/google/cloud/spanner/session.rb', line 49

def service
  @service
end

Class Method Details

.from_grpc(grpc, service) ⇒ Object

Google::Spanner::V1::Session.



580
581
582
# File 'lib/google/cloud/spanner/session.rb', line 580

def self.from_grpc grpc, service
  new grpc, service
end

Instance Method Details

#commit(transaction_id: nil) {|commit| ... } ⇒ Time

Creates changes to be applied to rows in the database.

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

Parameters:

  • transaction_id (String) (defaults to: nil) —

    The identifier of previously-started transaction to be used instead of starting a new transaction. Optional.

Yields:

  • (commit) —

    The block for mutating the data.

Yield Parameters:

Returns:

  • (Time) —

    The timestamp at which the operation committed.



296
297
298
299
300
301
302
303
304
# File 'lib/google/cloud/spanner/session.rb', line 296

def commit transaction_id: nil
  ensure_service!
  commit = Commit.new
  yield commit
  commit_resp = service.commit path, commit.mutations,
                               transaction_id: transaction_id
  @last_updated_at = Time.now
  Convert.timestamp_to_time commit_resp.commit_timestamp
end

#create_transaction ⇒ Object

Creates a new transaction object every time.



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

def create_transaction
  tx_grpc = service.begin_transaction path
  Transaction.from_grpc(tx_grpc, self)
end

#database_id ⇒ String

The unique identifier for the database.

Returns:

  • (String)


71
72
73
# File 'lib/google/cloud/spanner/session.rb', line 71

def database_id
  @grpc.name.split("/")[5]
end

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

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

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.



507
508
509
510
511
# File 'lib/google/cloud/spanner/session.rb', line 507

def delete table, keys = [], transaction_id: nil
  commit transaction_id: transaction_id do |c|
    c.delete table, keys
  end
end

#execute(sql, params: nil, types: nil, transaction: nil, partition_token: nil) ⇒ Google::Cloud::Spanner::Results

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"

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.

    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.

  • transaction (Google::Spanner::V1::TransactionSelector) (defaults to: nil) —

    The transaction selector value to send. Only used for single-use transactions.

Returns:



183
184
185
186
187
188
189
190
191
192
193
# File 'lib/google/cloud/spanner/session.rb', line 183

def execute sql, params: nil, types: nil, transaction: nil,
            partition_token: nil
  ensure_service!

  results = Results.execute service, path, sql,
                            params: params, types: types,
                            transaction: transaction,
                            partition_token: partition_token
  @last_updated_at = Time.now
  results
end

#idle_since?(duration) ⇒ Boolean

Determines if the session has been idle longer than the given duration.

Returns:

  • (Boolean)


572
573
574
575
# File 'lib/google/cloud/spanner/session.rb', line 572

def idle_since? duration
  return true if @last_updated_at.nil?
  Time.now > @last_updated_at + duration
end

#insert(table, *rows, transaction_id: nil) ⇒ Time

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

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.

Returns:

  • (Time) —

    The timestamp at which the operation committed.



390
391
392
393
394
# File 'lib/google/cloud/spanner/session.rb', line 390

def insert table, *rows, transaction_id: nil
  commit transaction_id: transaction_id do |c|
    c.insert table, rows
  end
end

#instance_id ⇒ String

The unique identifier for the instance.

Returns:

  • (String)


65
66
67
# File 'lib/google/cloud/spanner/session.rb', line 65

def instance_id
  @grpc.name.split("/")[3]
end

#keepalive! ⇒ Object

Keeps the session alive by executing "SELECT 1".



549
550
551
552
553
554
555
556
557
558
559
# File 'lib/google/cloud/spanner/session.rb', line 549

def keepalive!
  ensure_service!
  execute "SELECT 1"
  return true
rescue Google::Cloud::NotFoundError
  @grpc = service.create_session \
    Admin::Database::V1::DatabaseAdminClient.database_path(
      project_id, instance_id, database_id
    )
  return false
end

#partition_query(sql, transaction, params: nil, types: nil, partition_size_bytes: nil, max_partitions: nil) ⇒ Object



243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/google/cloud/spanner/session.rb', line 243

def partition_query sql, transaction, params: nil, types: nil,
                    partition_size_bytes: nil, max_partitions: nil
  ensure_service!

  results = service.partition_query \
    path, sql, transaction, params: params, types: types,
                            partition_size_bytes: partition_size_bytes,
                            max_partitions: max_partitions

  @last_updated_at = Time.now

  results
end

#partition_read(table, columns, transaction, keys: nil, index: nil, partition_size_bytes: nil, max_partitions: nil) ⇒ Object



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/google/cloud/spanner/session.rb', line 257

def partition_read table, columns, transaction, keys: nil,
                   index: nil, partition_size_bytes: nil,
                   max_partitions: nil
  ensure_service!

  results = service.partition_read \
    path, table, columns, transaction,
    keys: keys, index: index,
    partition_size_bytes: partition_size_bytes,
    max_partitions: max_partitions

  @last_updated_at = Time.now

  results
end

#path ⇒ String

The full path for the session resource. Values are of the form projects/<project_id>/instances/<instance_id>/databases/<database_id>/sessions/<session_id>.

Returns:

  • (String)


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

def path
  @grpc.name
end

#project_id ⇒ String

The unique identifier for the project.

Returns:

  • (String)


59
60
61
# File 'lib/google/cloud/spanner/session.rb', line 59

def project_id
  @grpc.name.split("/")[1]
end

#read(table, columns, keys: nil, index: nil, limit: nil, transaction: nil, partition_token: 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

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.

  • transaction (Google::Spanner::V1::TransactionSelector) (defaults to: nil) —

    The transaction selector value to send. Only used for single-use transactions.

Returns:



231
232
233
234
235
236
237
238
239
240
241
# File 'lib/google/cloud/spanner/session.rb', line 231

def read table, columns, keys: nil, index: nil, limit: nil,
         transaction: nil, partition_token: nil
  ensure_service!

  results = Results.read service, path, table, columns,
                         keys: keys, index: index, limit: limit,
                         transaction: transaction,
                         partition_token: partition_token
  @last_updated_at = Time.now
  results
end

#release! ⇒ Object

Permanently deletes the session.



563
564
565
566
# File 'lib/google/cloud/spanner/session.rb', line 563

def release!
  ensure_service!
  service.delete_session path
end

#reload! ⇒ Object

Reloads the session resource. Useful for determining if the session is still valid on the Spanner API.



532
533
534
535
536
537
538
539
540
541
542
543
544
# File 'lib/google/cloud/spanner/session.rb', line 532

def reload!
  ensure_service!
  @grpc = service.get_session path
  @last_updated_at = Time.now
  return self
rescue Google::Cloud::NotFoundError
  @grpc = service.create_session \
    Admin::Database::V1::DatabaseAdminClient.database_path(
      project_id, instance_id, database_id
    )
  @last_updated_at = Time.now
  return self
end

#replace(table, *rows, transaction_id: nil) ⇒ 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.

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.

Returns:

  • (Time) —

    The timestamp at which the operation committed.



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

def replace table, *rows, transaction_id: nil
  commit transaction_id: transaction_id do |c|
    c.replace table, rows
  end
end

#rollback(transaction_id) ⇒ Object

Rolls back the transaction, releasing any locks it holds.



515
516
517
518
519
# File 'lib/google/cloud/spanner/session.rb', line 515

def rollback transaction_id
  service.rollback path, transaction_id
  @last_updated_at = Time.now
  true
end

#session ⇒ Object



586
587
588
# File 'lib/google/cloud/spanner/session.rb', line 586

def session
  self
end

#session_id ⇒ String

The unique identifier for the session.

Returns:

  • (String)


77
78
79
# File 'lib/google/cloud/spanner/session.rb', line 77

def session_id
  @grpc.name.split("/")[7]
end

#update(table, *rows, transaction_id: nil) ⇒ Time

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

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.

Returns:

  • (Time) —

    The timestamp at which the operation committed.



434
435
436
437
438
# File 'lib/google/cloud/spanner/session.rb', line 434

def update table, *rows, transaction_id: nil
  commit transaction_id: transaction_id do |c|
    c.update table, rows
  end
end

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

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.

Returns:

  • (Time) —

    The timestamp at which the operation committed.



345
346
347
348
349
# File 'lib/google/cloud/spanner/session.rb', line 345

def upsert table, *rows, transaction_id: nil
  commit transaction_id: transaction_id do |c|
    c.upsert table, rows
  end
end