google-cloud-spanner 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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