google-cloud-spanner 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/lib/google-cloud-spanner.rb +106 -0
  3. data/lib/google/cloud/spanner.rb +382 -0
  4. data/lib/google/cloud/spanner/admin/database/v1.rb +17 -0
  5. data/lib/google/cloud/spanner/admin/database/v1/database_admin_client.rb +703 -0
  6. data/lib/google/cloud/spanner/admin/database/v1/database_admin_client_config.json +73 -0
  7. data/lib/google/cloud/spanner/admin/database/v1/doc/google/iam/v1/policy.rb +139 -0
  8. data/lib/google/cloud/spanner/admin/database/v1/doc/google/protobuf/any.rb +114 -0
  9. data/lib/google/cloud/spanner/admin/database/v1/doc/google/rpc/status.rb +83 -0
  10. data/lib/google/cloud/spanner/admin/database/v1/doc/google/spanner/admin/database/v1/spanner_database_admin.rb +188 -0
  11. data/lib/google/cloud/spanner/admin/instance/v1.rb +17 -0
  12. data/lib/google/cloud/spanner/admin/instance/v1/doc/google/iam/v1/policy.rb +139 -0
  13. data/lib/google/cloud/spanner/admin/instance/v1/doc/google/protobuf/any.rb +114 -0
  14. data/lib/google/cloud/spanner/admin/instance/v1/doc/google/protobuf/field_mask.rb +223 -0
  15. data/lib/google/cloud/spanner/admin/instance/v1/doc/google/rpc/status.rb +83 -0
  16. data/lib/google/cloud/spanner/admin/instance/v1/doc/google/spanner/admin/instance/v1/spanner_instance_admin.rb +268 -0
  17. data/lib/google/cloud/spanner/admin/instance/v1/instance_admin_client.rb +868 -0
  18. data/lib/google/cloud/spanner/admin/instance/v1/instance_admin_client_config.json +78 -0
  19. data/lib/google/cloud/spanner/client.rb +1034 -0
  20. data/lib/google/cloud/spanner/commit.rb +351 -0
  21. data/lib/google/cloud/spanner/convert.rb +311 -0
  22. data/lib/google/cloud/spanner/credentials.rb +32 -0
  23. data/lib/google/cloud/spanner/data.rb +199 -0
  24. data/lib/google/cloud/spanner/database.rb +377 -0
  25. data/lib/google/cloud/spanner/database/job.rb +179 -0
  26. data/lib/google/cloud/spanner/database/list.rb +171 -0
  27. data/lib/google/cloud/spanner/errors.rb +73 -0
  28. data/lib/google/cloud/spanner/fields.rb +252 -0
  29. data/lib/google/cloud/spanner/instance.rb +472 -0
  30. data/lib/google/cloud/spanner/instance/config.rb +99 -0
  31. data/lib/google/cloud/spanner/instance/config/list.rb +171 -0
  32. data/lib/google/cloud/spanner/instance/job.rb +197 -0
  33. data/lib/google/cloud/spanner/instance/list.rb +167 -0
  34. data/lib/google/cloud/spanner/policy.rb +201 -0
  35. data/lib/google/cloud/spanner/pool.rb +279 -0
  36. data/lib/google/cloud/spanner/project.rb +480 -0
  37. data/lib/google/cloud/spanner/range.rb +99 -0
  38. data/lib/google/cloud/spanner/results.rb +280 -0
  39. data/lib/google/cloud/spanner/service.rb +458 -0
  40. data/lib/google/cloud/spanner/session.rb +565 -0
  41. data/lib/google/cloud/spanner/snapshot.rb +260 -0
  42. data/lib/google/cloud/spanner/transaction.rb +533 -0
  43. data/lib/google/cloud/spanner/v1.rb +17 -0
  44. data/lib/google/cloud/spanner/v1/doc/google/protobuf/duration.rb +77 -0
  45. data/lib/google/cloud/spanner/v1/doc/google/protobuf/struct.rb +73 -0
  46. data/lib/google/cloud/spanner/v1/doc/google/protobuf/timestamp.rb +81 -0
  47. data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/keys.rb +148 -0
  48. data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/mutation.rb +80 -0
  49. data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/query_plan.rb +120 -0
  50. data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/result_set.rb +175 -0
  51. data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/spanner.rb +206 -0
  52. data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/transaction.rb +351 -0
  53. data/lib/google/cloud/spanner/v1/spanner_client.rb +850 -0
  54. data/lib/google/cloud/spanner/v1/spanner_client_config.json +78 -0
  55. data/lib/google/cloud/spanner/version.rb +22 -0
  56. data/lib/google/spanner/admin/database/v1/spanner_database_admin_pb.rb +85 -0
  57. data/lib/google/spanner/admin/database/v1/spanner_database_admin_services_pb.rb +95 -0
  58. data/lib/google/spanner/admin/instance/v1/spanner_instance_admin_pb.rb +106 -0
  59. data/lib/google/spanner/admin/instance/v1/spanner_instance_admin_services_pb.rb +180 -0
  60. data/lib/google/spanner/v1/keys_pb.rb +33 -0
  61. data/lib/google/spanner/v1/mutation_pb.rb +38 -0
  62. data/lib/google/spanner/v1/query_plan_pb.rb +47 -0
  63. data/lib/google/spanner/v1/result_set_pb.rb +43 -0
  64. data/lib/google/spanner/v1/spanner_pb.rb +90 -0
  65. data/lib/google/spanner/v1/spanner_services_pb.rb +131 -0
  66. data/lib/google/spanner/v1/transaction_pb.rb +51 -0
  67. data/lib/google/spanner/v1/type_pb.rb +43 -0
  68. metadata +309 -0
@@ -0,0 +1,260 @@
1
+ # Copyright 2017 Google Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ require "google/cloud/spanner/results"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Spanner
21
+ ##
22
+ # # Snapshot
23
+ #
24
+ # A snapshot in Cloud Spanner is a set of reads that execute atomically at
25
+ # a single logical point in time across columns, rows, and tables in a
26
+ # database.
27
+ #
28
+ # @example
29
+ # require "google/cloud/spanner"
30
+ #
31
+ # spanner = Google::Cloud::Spanner.new
32
+ # db = spanner.client "my-instance", "my-database"
33
+ #
34
+ # db.snapshot do |snp|
35
+ # results = snp.execute "SELECT * FROM users"
36
+ #
37
+ # results.rows.each do |row|
38
+ # puts "User #{row[:id]} is #{row[:name]}"
39
+ # end
40
+ # end
41
+ #
42
+ class Snapshot
43
+ # @private The Session object.
44
+ attr_accessor :session
45
+
46
+ ##
47
+ # Identifier of the transaction results were run in.
48
+ # @return [String] The transaction id.
49
+ def transaction_id
50
+ return nil if @grpc.nil?
51
+ @grpc.id
52
+ end
53
+
54
+ ##
55
+ # The read timestamp chosen for snapshots.
56
+ # @return [Time] The chosen timestamp.
57
+ def timestamp
58
+ return nil if @grpc.nil?
59
+ Convert.timestamp_to_time @grpc.read_timestamp
60
+ end
61
+
62
+ ##
63
+ # Executes a SQL query.
64
+ #
65
+ # Arguments can be passed using `params`, Ruby types are mapped to
66
+ # Spanner types as follows:
67
+ #
68
+ # | Spanner | Ruby | Notes |
69
+ # |-------------|----------------|---|
70
+ # | `BOOL` | `true`/`false` | |
71
+ # | `INT64` | `Integer` | |
72
+ # | `FLOAT64` | `Float` | |
73
+ # | `STRING` | `String` | |
74
+ # | `DATE` | `Date` | |
75
+ # | `TIMESTAMP` | `Time`, `DateTime` | |
76
+ # | `BYTES` | `File`, `IO`, `StringIO`, or similar | |
77
+ # | `ARRAY` | `Array` | Nested arrays are not supported. |
78
+ #
79
+ # See [Data
80
+ # types](https://cloud.google.com/spanner/docs/data-definition-language#data_types).
81
+ #
82
+ # @param [String] sql The SQL query string. See [Query
83
+ # syntax](https://cloud.google.com/spanner/docs/query-syntax).
84
+ #
85
+ # The SQL query string can contain parameter placeholders. A parameter
86
+ # placeholder consists of "@" followed by the parameter name.
87
+ # Parameter names consist of any combination of letters, numbers, and
88
+ # underscores.
89
+ # @param [Hash] params SQL parameters for the query string. The
90
+ # parameter placeholders, minus the "@", are the the hash keys, and
91
+ # the literal values are the hash values. If the query string contains
92
+ # something like "WHERE id > @msg_id", then the params must contain
93
+ # something like `:msg_id => 1`.
94
+ # @param [Hash] types Types of the SQL parameters in `params`. It is not
95
+ # always possible for Cloud Spanner to infer the right SQL type from a
96
+ # value in `params`. In these cases, the `types` hash can be used to
97
+ # specify the exact SQL type for some or all of the SQL query
98
+ # parameters.
99
+ #
100
+ # The keys of the hash should be query string parameter placeholders,
101
+ # minus the "@". The values of the hash should be Cloud Spanner type
102
+ # codes from the following list:
103
+ #
104
+ # * `:BOOL`
105
+ # * `:BYTES`
106
+ # * `:DATE`
107
+ # * `:FLOAT64`
108
+ # * `:INT64`
109
+ # * `:STRING`
110
+ # * `:TIMESTAMP`
111
+ #
112
+ # Arrays are specified by providing the type code in an array. For
113
+ # example, an array of integers are specified as `[:INT64]`.
114
+ #
115
+ # Structs are not yet supported in query parameters.
116
+ #
117
+ # Types are optional.
118
+ # @return [Google::Cloud::Spanner::Results] The results of the query
119
+ # execution.
120
+ #
121
+ # @example
122
+ # require "google/cloud/spanner"
123
+ #
124
+ # spanner = Google::Cloud::Spanner.new
125
+ # db = spanner.client "my-instance", "my-database"
126
+ #
127
+ # db.snapshot do |snp|
128
+ # results = snp.execute "SELECT * FROM users"
129
+ #
130
+ # results.rows.each do |row|
131
+ # puts "User #{row[:id]} is #{row[:name]}"
132
+ # end
133
+ # end
134
+ #
135
+ # @example Query using query parameters:
136
+ # require "google/cloud/spanner"
137
+ #
138
+ # spanner = Google::Cloud::Spanner.new
139
+ # db = spanner.client "my-instance", "my-database"
140
+ #
141
+ # db.snapshot do |snp|
142
+ # results = snp.execute "SELECT * FROM users " \
143
+ # "WHERE active = @active",
144
+ # params: { active: true }
145
+ #
146
+ # results.rows.each do |row|
147
+ # puts "User #{row[:id]} is #{row[:name]}"
148
+ # end
149
+ # end
150
+ #
151
+ def execute sql, params: nil, types: nil
152
+ ensure_session!
153
+ session.execute sql, params: params, types: types,
154
+ transaction: tx_selector
155
+ end
156
+ alias_method :query, :execute
157
+
158
+ ##
159
+ # Read rows from a database table, as a simple alternative to
160
+ # {#execute}.
161
+ #
162
+ # @param [String] table The name of the table in the database to be
163
+ # read.
164
+ # @param [Array<String, Symbol>] columns The columns of table to be
165
+ # returned for each row matching this request.
166
+ # @param [Object, Array<Object>] keys A single, or list of keys or key
167
+ # ranges to match returned data to. Values should have exactly as many
168
+ # elements as there are columns in the primary key.
169
+ # @param [String] index The name of an index to use instead of the
170
+ # table's primary key when interpreting `id` and sorting result rows.
171
+ # Optional.
172
+ # @param [Integer] limit If greater than zero, no more than this number
173
+ # of rows will be returned. The default is no limit.
174
+ #
175
+ # @return [Google::Cloud::Spanner::Results] The results of the read
176
+ # operation.
177
+ #
178
+ # @example
179
+ # require "google/cloud/spanner"
180
+ #
181
+ # spanner = Google::Cloud::Spanner.new
182
+ # db = spanner.client "my-instance", "my-database"
183
+ #
184
+ # db.snapshot do |snp|
185
+ # results = snp.read "users", [:id, :name]
186
+ #
187
+ # results.rows.each do |row|
188
+ # puts "User #{row[:id]} is #{row[:name]}"
189
+ # end
190
+ # end
191
+ #
192
+ def read table, columns, keys: nil, index: nil, limit: nil
193
+ ensure_session!
194
+ session.read table, columns, keys: keys, index: index, limit: limit,
195
+ transaction: tx_selector
196
+ end
197
+
198
+ ##
199
+ # Creates a Cloud Spanner Range. This can be used in place of a Ruby
200
+ # Range when needing to exclude the beginning value.
201
+ #
202
+ # @param [Object] beginning The object that defines the beginning of the
203
+ # range.
204
+ # @param [Object] ending The object that defines the end of the range.
205
+ # @param [Boolean] exclude_begin Determines if the range excludes its
206
+ # beginning value. Default is `false`.
207
+ # @param [Boolean] exclude_end Determines if the range excludes its
208
+ # ending value. Default is `false`.
209
+ #
210
+ # @return [Google::Cloud::Spanner::Range] The new Range instance.
211
+ #
212
+ # @example
213
+ # require "google/cloud/spanner"
214
+ #
215
+ # spanner = Google::Cloud::Spanner.new
216
+ # db = spanner.client "my-instance", "my-database"
217
+ #
218
+ # db.snapshot do |snp|
219
+ # key_range = db.range 1, 100
220
+ # results = snp.read "users", [:id, :name], keys: key_range
221
+ #
222
+ # results.rows.each do |row|
223
+ # puts "User #{row[:id]} is #{row[:name]}"
224
+ # end
225
+ # end
226
+ #
227
+ def range beginning, ending, exclude_begin: false, exclude_end: false
228
+ Range.new beginning, ending,
229
+ exclude_begin: exclude_begin,
230
+ exclude_end: exclude_end
231
+ end
232
+
233
+ ##
234
+ # @private Creates a new Snapshot instance from a
235
+ # Google::Spanner::V1::Transaction.
236
+ def self.from_grpc grpc, session
237
+ new.tap do |s|
238
+ s.instance_variable_set :@grpc, grpc
239
+ s.instance_variable_set :@session, session
240
+ end
241
+ end
242
+
243
+ protected
244
+
245
+ # The TransactionSelector to be used for queries
246
+ def tx_selector
247
+ return nil if transaction_id.nil?
248
+ Google::Spanner::V1::TransactionSelector.new id: transaction_id
249
+ end
250
+
251
+ ##
252
+ # @private Raise an error unless an active connection to the service is
253
+ # available.
254
+ def ensure_session!
255
+ fail "Must have active connection to service" unless session
256
+ end
257
+ end
258
+ end
259
+ end
260
+ end
@@ -0,0 +1,533 @@
1
+ # Copyright 2017 Google Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ require "google/cloud/spanner/errors"
17
+ require "google/cloud/spanner/results"
18
+ require "google/cloud/spanner/commit"
19
+
20
+ module Google
21
+ module Cloud
22
+ module Spanner
23
+ ##
24
+ # # Transaction
25
+ #
26
+ # A transaction in Cloud Spanner is a set of reads and writes that execute
27
+ # atomically at a single logical point in time across columns, rows, and
28
+ # tables in a database.
29
+ #
30
+ # All changes are accumulated in memory until the block passed to
31
+ # {Client#transaction} completes. Transactions will be automatically
32
+ # retried when possible. See {Client#transaction}.
33
+ #
34
+ # @example
35
+ # require "google/cloud/spanner"
36
+ #
37
+ # spanner = Google::Cloud::Spanner.new
38
+ # db = spanner.client "my-instance", "my-database"
39
+ #
40
+ # db.transaction do |tx|
41
+ # results = tx.execute "SELECT * FROM users"
42
+ #
43
+ # results.rows.each do |row|
44
+ # puts "User #{row[:id]} is #{row[:name]}"
45
+ # end
46
+ # end
47
+ #
48
+ class Transaction
49
+ # @private The Session object.
50
+ attr_accessor :session
51
+
52
+ def initialize
53
+ @commit = Commit.new
54
+ end
55
+
56
+ ##
57
+ # Identifier of the transaction results were run in.
58
+ # @return [String] The transaction id.
59
+ def transaction_id
60
+ return nil if @grpc.nil?
61
+ @grpc.id
62
+ end
63
+
64
+ ##
65
+ # Executes a SQL query.
66
+ #
67
+ # Arguments can be passed using `params`, Ruby types are mapped to
68
+ # Spanner types as follows:
69
+ #
70
+ # | Spanner | Ruby | Notes |
71
+ # |-------------|----------------|---|
72
+ # | `BOOL` | `true`/`false` | |
73
+ # | `INT64` | `Integer` | |
74
+ # | `FLOAT64` | `Float` | |
75
+ # | `STRING` | `String` | |
76
+ # | `DATE` | `Date` | |
77
+ # | `TIMESTAMP` | `Time`, `DateTime` | |
78
+ # | `BYTES` | `File`, `IO`, `StringIO`, or similar | |
79
+ # | `ARRAY` | `Array` | Nested arrays are not supported. |
80
+ #
81
+ # See [Data
82
+ # types](https://cloud.google.com/spanner/docs/data-definition-language#data_types).
83
+ #
84
+ # @param [String] sql The SQL query string. See [Query
85
+ # syntax](https://cloud.google.com/spanner/docs/query-syntax).
86
+ #
87
+ # The SQL query string can contain parameter placeholders. A parameter
88
+ # placeholder consists of "@" followed by the parameter name.
89
+ # Parameter names consist of any combination of letters, numbers, and
90
+ # underscores.
91
+ # @param [Hash] params SQL parameters for the query string. The
92
+ # parameter placeholders, minus the "@", are the the hash keys, and
93
+ # the literal values are the hash values. If the query string contains
94
+ # something like "WHERE id > @msg_id", then the params must contain
95
+ # something like `:msg_id => 1`.
96
+ # @param [Hash] types Types of the SQL parameters in `params`. It is not
97
+ # always possible for Cloud Spanner to infer the right SQL type from a
98
+ # value in `params`. In these cases, the `types` hash can be used to
99
+ # specify the exact SQL type for some or all of the SQL query
100
+ # parameters.
101
+ #
102
+ # The keys of the hash should be query string parameter placeholders,
103
+ # minus the "@". The values of the hash should be Cloud Spanner type
104
+ # codes from the following list:
105
+ #
106
+ # * `:BOOL`
107
+ # * `:BYTES`
108
+ # * `:DATE`
109
+ # * `:FLOAT64`
110
+ # * `:INT64`
111
+ # * `:STRING`
112
+ # * `:TIMESTAMP`
113
+ #
114
+ # Arrays are specified by providing the type code in an array. For
115
+ # example, an array of integers are specified as `[:INT64]`.
116
+ #
117
+ # Structs are not yet supported in query parameters.
118
+ #
119
+ # Types are optional.
120
+ # @return [Google::Cloud::Spanner::Results] The results of the query
121
+ # execution.
122
+ #
123
+ # @example
124
+ # require "google/cloud/spanner"
125
+ #
126
+ # spanner = Google::Cloud::Spanner.new
127
+ # db = spanner.client "my-instance", "my-database"
128
+ #
129
+ # db.transaction do |tx|
130
+ # results = tx.execute "SELECT * FROM users"
131
+ #
132
+ # results.rows.each do |row|
133
+ # puts "User #{row[:id]} is #{row[:name]}"
134
+ # end
135
+ # end
136
+ #
137
+ # @example Query using query parameters:
138
+ # require "google/cloud/spanner"
139
+ #
140
+ # spanner = Google::Cloud::Spanner.new
141
+ # db = spanner.client "my-instance", "my-database"
142
+ #
143
+ # db.transaction do |tx|
144
+ # results = tx.execute "SELECT * FROM users WHERE active = @active",
145
+ # params: { active: true }
146
+ #
147
+ # results.rows.each do |row|
148
+ # puts "User #{row[:id]} is #{row[:name]}"
149
+ # end
150
+ # end
151
+ #
152
+ def execute sql, params: nil, types: nil
153
+ ensure_session!
154
+ session.execute sql, params: params, types: types,
155
+ transaction: tx_selector
156
+ end
157
+ alias_method :query, :execute
158
+
159
+ ##
160
+ # Read rows from a database table, as a simple alternative to
161
+ # {#execute}.
162
+ #
163
+ # @param [String] table The name of the table in the database to be
164
+ # read.
165
+ # @param [Array<String, Symbol>] columns The columns of table to be
166
+ # returned for each row matching this request.
167
+ # @param [Object, Array<Object>] keys A single, or list of keys or key
168
+ # ranges to match returned data to. Values should have exactly as many
169
+ # elements as there are columns in the primary key.
170
+ # @param [String] index The name of an index to use instead of the
171
+ # table's primary key when interpreting `id` and sorting result rows.
172
+ # Optional.
173
+ # @param [Integer] limit If greater than zero, no more than this number
174
+ # of rows will be returned. The default is no limit.
175
+ #
176
+ # @return [Google::Cloud::Spanner::Results] The results of the read
177
+ # operation.
178
+ #
179
+ # @example
180
+ # require "google/cloud/spanner"
181
+ #
182
+ # spanner = Google::Cloud::Spanner.new
183
+ # db = spanner.client "my-instance", "my-database"
184
+ #
185
+ # db.transaction do |tx|
186
+ # results = tx.read "users", [:id, :name]
187
+ #
188
+ # results.rows.each do |row|
189
+ # puts "User #{row[:id]} is #{row[:name]}"
190
+ # end
191
+ # end
192
+ #
193
+ def read table, columns, keys: nil, index: nil, limit: nil
194
+ ensure_session!
195
+ session.read table, columns, keys: keys, index: index, limit: limit,
196
+ transaction: tx_selector
197
+ end
198
+
199
+ ##
200
+ # Inserts or updates rows in a table. If any of the rows already exist,
201
+ # then its column values are overwritten with the ones provided. Any
202
+ # column values not explicitly written are preserved.
203
+ #
204
+ # All changes are accumulated in memory until the block passed to
205
+ # {Client#transaction} completes.
206
+ #
207
+ # @param [String] table The name of the table in the database to be
208
+ # modified.
209
+ # @param [Array<Hash>] rows One or more hash objects with the hash keys
210
+ # matching the table's columns, and the hash values matching the
211
+ # table's values.
212
+ #
213
+ # Ruby types are mapped to Spanner types as follows:
214
+ #
215
+ # | Spanner | Ruby | Notes |
216
+ # |-------------|----------------|---|
217
+ # | `BOOL` | `true`/`false` | |
218
+ # | `INT64` | `Integer` | |
219
+ # | `FLOAT64` | `Float` | |
220
+ # | `STRING` | `String` | |
221
+ # | `DATE` | `Date` | |
222
+ # | `TIMESTAMP` | `Time`, `DateTime` | |
223
+ # | `BYTES` | `File`, `IO`, `StringIO`, or similar | |
224
+ # | `ARRAY` | `Array` | Nested arrays are not supported. |
225
+ #
226
+ # See [Data
227
+ # types](https://cloud.google.com/spanner/docs/data-definition-language#data_types).
228
+ #
229
+ # @example
230
+ # require "google/cloud/spanner"
231
+ #
232
+ # spanner = Google::Cloud::Spanner.new
233
+ # db = spanner.client "my-instance", "my-database"
234
+ #
235
+ # db.transaction do |tx|
236
+ # tx.upsert "users", [{ id: 1, name: "Charlie", active: false },
237
+ # { id: 2, name: "Harvey", active: true }]
238
+ # end
239
+ #
240
+ def upsert table, *rows
241
+ ensure_session!
242
+ @commit.upsert table, rows
243
+ end
244
+ alias_method :save, :upsert
245
+
246
+ ##
247
+ # Inserts new rows in a table. If any of the rows already exist, the
248
+ # write or request fails with error {Google::Cloud::AlreadyExistsError}.
249
+ #
250
+ # All changes are accumulated in memory until the block passed to
251
+ # {Client#transaction} completes.
252
+ #
253
+ # @param [String] table The name of the table in the database to be
254
+ # modified.
255
+ # @param [Array<Hash>] rows One or more hash objects with the hash keys
256
+ # matching the table's columns, and the hash values matching the
257
+ # table's values.
258
+ #
259
+ # Ruby types are mapped to Spanner types as follows:
260
+ #
261
+ # | Spanner | Ruby | Notes |
262
+ # |-------------|----------------|---|
263
+ # | `BOOL` | `true`/`false` | |
264
+ # | `INT64` | `Integer` | |
265
+ # | `FLOAT64` | `Float` | |
266
+ # | `STRING` | `String` | |
267
+ # | `DATE` | `Date` | |
268
+ # | `TIMESTAMP` | `Time`, `DateTime` | |
269
+ # | `BYTES` | `File`, `IO`, `StringIO`, or similar | |
270
+ # | `ARRAY` | `Array` | Nested arrays are not supported. |
271
+ #
272
+ # See [Data
273
+ # types](https://cloud.google.com/spanner/docs/data-definition-language#data_types).
274
+ #
275
+ # @example
276
+ # require "google/cloud/spanner"
277
+ #
278
+ # spanner = Google::Cloud::Spanner.new
279
+ # db = spanner.client "my-instance", "my-database"
280
+ #
281
+ # db.transaction do |tx|
282
+ # tx.insert "users", [{ id: 1, name: "Charlie", active: false },
283
+ # { id: 2, name: "Harvey", active: true }]
284
+ # end
285
+ #
286
+ def insert table, *rows
287
+ ensure_session!
288
+ @commit.insert table, rows
289
+ end
290
+
291
+ ##
292
+ # Updates existing rows in a table. If any of the rows does not already
293
+ # exist, the request fails with error {Google::Cloud::NotFoundError}.
294
+ #
295
+ # All changes are accumulated in memory until the block passed to
296
+ # {Client#transaction} completes.
297
+ #
298
+ # @param [String] table The name of the table in the database to be
299
+ # modified.
300
+ # @param [Array<Hash>] rows One or more hash objects with the hash keys
301
+ # matching the table's columns, and the hash values matching the
302
+ # table's values.
303
+ #
304
+ # Ruby types are mapped to Spanner types as follows:
305
+ #
306
+ # | Spanner | Ruby | Notes |
307
+ # |-------------|----------------|---|
308
+ # | `BOOL` | `true`/`false` | |
309
+ # | `INT64` | `Integer` | |
310
+ # | `FLOAT64` | `Float` | |
311
+ # | `STRING` | `String` | |
312
+ # | `DATE` | `Date` | |
313
+ # | `TIMESTAMP` | `Time`, `DateTime` | |
314
+ # | `BYTES` | `File`, `IO`, `StringIO`, or similar | |
315
+ # | `ARRAY` | `Array` | Nested arrays are not supported. |
316
+ #
317
+ # See [Data
318
+ # types](https://cloud.google.com/spanner/docs/data-definition-language#data_types).
319
+ #
320
+ # @example
321
+ # require "google/cloud/spanner"
322
+ #
323
+ # spanner = Google::Cloud::Spanner.new
324
+ # db = spanner.client "my-instance", "my-database"
325
+ #
326
+ # db.transaction do |tx|
327
+ # tx.update "users", [{ id: 1, name: "Charlie", active: false },
328
+ # { id: 2, name: "Harvey", active: true }]
329
+ # end
330
+ #
331
+ def update table, *rows
332
+ ensure_session!
333
+ @commit.update table, rows
334
+ end
335
+
336
+ ##
337
+ # Inserts or replaces rows in a table. If any of the rows already exist,
338
+ # it is deleted, and the column values provided are inserted instead.
339
+ # Unlike #upsert, this means any values not explicitly written become
340
+ # `NULL`.
341
+ #
342
+ # All changes are accumulated in memory until the block passed to
343
+ # {Client#transaction} completes.
344
+ #
345
+ # @param [String] table The name of the table in the database to be
346
+ # modified.
347
+ # @param [Array<Hash>] rows One or more hash objects with the hash keys
348
+ # matching the table's columns, and the hash values matching the
349
+ # table's values.
350
+ #
351
+ # Ruby types are mapped to Spanner types as follows:
352
+ #
353
+ # | Spanner | Ruby | Notes |
354
+ # |-------------|----------------|---|
355
+ # | `BOOL` | `true`/`false` | |
356
+ # | `INT64` | `Integer` | |
357
+ # | `FLOAT64` | `Float` | |
358
+ # | `STRING` | `String` | |
359
+ # | `DATE` | `Date` | |
360
+ # | `TIMESTAMP` | `Time`, `DateTime` | |
361
+ # | `BYTES` | `File`, `IO`, `StringIO`, or similar | |
362
+ # | `ARRAY` | `Array` | Nested arrays are not supported. |
363
+ #
364
+ # See [Data
365
+ # types](https://cloud.google.com/spanner/docs/data-definition-language#data_types).
366
+ #
367
+ # @example
368
+ # require "google/cloud/spanner"
369
+ #
370
+ # spanner = Google::Cloud::Spanner.new
371
+ # db = spanner.client "my-instance", "my-database"
372
+ #
373
+ # db.transaction do |tx|
374
+ # tx.replace "users", [{ id: 1, name: "Charlie", active: false },
375
+ # { id: 2, name: "Harvey", active: true }]
376
+ # end
377
+ #
378
+ def replace table, *rows
379
+ ensure_session!
380
+ @commit.replace table, rows
381
+ end
382
+
383
+ ##
384
+ # Deletes rows from a table. Succeeds whether or not the specified rows
385
+ # were present.
386
+ #
387
+ # All changes are accumulated in memory until the block passed to
388
+ # {Client#transaction} completes.
389
+ #
390
+ # @param [String] table The name of the table in the database to be
391
+ # modified.
392
+ # @param [Object, Array<Object>] keys A single, or list of keys or key
393
+ # ranges to match returned data to. Values should have exactly as many
394
+ # elements as there are columns in the primary key.
395
+ #
396
+ # @example
397
+ # require "google/cloud/spanner"
398
+ #
399
+ # spanner = Google::Cloud::Spanner.new
400
+ # db = spanner.client "my-instance", "my-database"
401
+ #
402
+ # db.transaction { |tx| tx.delete "users", [1, 2, 3] }
403
+ #
404
+ def delete table, keys = []
405
+ ensure_session!
406
+ @commit.delete table, keys
407
+ end
408
+
409
+ ##
410
+ # @private
411
+ # Returns the field names and types for a table.
412
+ #
413
+ # @param [String] table The name of the table in the database to
414
+ # retrieve types for
415
+ #
416
+ # @return [Hash, Array] The types of the returned data. The default is a
417
+ # Hash. Is a nested Array of Arrays when `pairs` is specified.
418
+ #
419
+ # @example
420
+ # require "google/cloud/spanner"
421
+ #
422
+ # spanner = Google::Cloud::Spanner.new
423
+ # db = spanner.client "my-instance", "my-database"
424
+ #
425
+ # db.transaction do |tx|
426
+ # users_types = rx.fields_for "users"
427
+ # tx.insert "users", [{ id: 1, name: "Charlie", active: false },
428
+ # { id: 2, name: "Harvey", active: true }],
429
+ # types: users_types
430
+ # end
431
+ #
432
+ def fields_for table
433
+ execute("SELECT * FROM #{table} WHERE 1 = 0").fields
434
+ end
435
+
436
+ ##
437
+ # Creates a Cloud Spanner Range. This can be used in place of a Ruby
438
+ # Range when needing to exclude the beginning value.
439
+ #
440
+ # @param [Object] beginning The object that defines the beginning of the
441
+ # range.
442
+ # @param [Object] ending The object that defines the end of the range.
443
+ # @param [Boolean] exclude_begin Determines if the range excludes its
444
+ # beginning value. Default is `false`.
445
+ # @param [Boolean] exclude_end Determines if the range excludes its
446
+ # ending value. Default is `false`.
447
+ #
448
+ # @return [Google::Cloud::Spanner::Range] The new Range instance.
449
+ #
450
+ # @example
451
+ # require "google/cloud/spanner"
452
+ #
453
+ # spanner = Google::Cloud::Spanner.new
454
+ # db = spanner.client "my-instance", "my-database"
455
+ #
456
+ # db.transaction do |tx|
457
+ # key_range = tx.range 1, 100
458
+ # results = tx.read "users", [:id, :name], keys: key_range
459
+ #
460
+ # results.rows.each do |row|
461
+ # puts "User #{row[:id]} is #{row[:name]}"
462
+ # end
463
+ # end
464
+ #
465
+ def range beginning, ending, exclude_begin: false, exclude_end: false
466
+ Range.new beginning, ending,
467
+ exclude_begin: exclude_begin,
468
+ exclude_end: exclude_end
469
+ end
470
+
471
+ ##
472
+ # @private
473
+ # Keeps the transaction current by creating a new transaction.
474
+ def keepalive!
475
+ ensure_session!
476
+ @grpc = session.create_transaction.instance_variable_get :@grpc
477
+ end
478
+
479
+ ##
480
+ # @private
481
+ # Permanently deletes the transaction and session.
482
+ def release!
483
+ ensure_session!
484
+ session.release!
485
+ end
486
+
487
+ ##
488
+ # @private
489
+ # Determines if the transaction has been idle longer than the given
490
+ # duration.
491
+ def idle_since? duration
492
+ session.idle_since? duration
493
+ end
494
+
495
+ ##
496
+ # @private
497
+ # All of the mutations created in the transaction block.
498
+ def mutations
499
+ @commit.mutations
500
+ end
501
+
502
+ ##
503
+ # @private Creates a new Transaction instance from a
504
+ # Google::Spanner::V1::Transaction.
505
+ def self.from_grpc grpc, session
506
+ new.tap do |s|
507
+ s.instance_variable_set :@grpc, grpc
508
+ s.instance_variable_set :@session, session
509
+ end
510
+ end
511
+
512
+ protected
513
+
514
+ # The TransactionSelector to be used for queries
515
+ def tx_selector
516
+ return nil if transaction_id.nil?
517
+ Google::Spanner::V1::TransactionSelector.new id: transaction_id
518
+ end
519
+
520
+ ##
521
+ # @private Raise an error unless an active connection to the service is
522
+ # available.
523
+ def ensure_session!
524
+ fail "Must have active connection to service" unless session
525
+ end
526
+
527
+ def service
528
+ session.service
529
+ end
530
+ end
531
+ end
532
+ end
533
+ end