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.
- checksums.yaml +7 -0
- data/lib/google-cloud-spanner.rb +106 -0
- data/lib/google/cloud/spanner.rb +382 -0
- data/lib/google/cloud/spanner/admin/database/v1.rb +17 -0
- data/lib/google/cloud/spanner/admin/database/v1/database_admin_client.rb +703 -0
- data/lib/google/cloud/spanner/admin/database/v1/database_admin_client_config.json +73 -0
- data/lib/google/cloud/spanner/admin/database/v1/doc/google/iam/v1/policy.rb +139 -0
- data/lib/google/cloud/spanner/admin/database/v1/doc/google/protobuf/any.rb +114 -0
- data/lib/google/cloud/spanner/admin/database/v1/doc/google/rpc/status.rb +83 -0
- data/lib/google/cloud/spanner/admin/database/v1/doc/google/spanner/admin/database/v1/spanner_database_admin.rb +188 -0
- data/lib/google/cloud/spanner/admin/instance/v1.rb +17 -0
- data/lib/google/cloud/spanner/admin/instance/v1/doc/google/iam/v1/policy.rb +139 -0
- data/lib/google/cloud/spanner/admin/instance/v1/doc/google/protobuf/any.rb +114 -0
- data/lib/google/cloud/spanner/admin/instance/v1/doc/google/protobuf/field_mask.rb +223 -0
- data/lib/google/cloud/spanner/admin/instance/v1/doc/google/rpc/status.rb +83 -0
- data/lib/google/cloud/spanner/admin/instance/v1/doc/google/spanner/admin/instance/v1/spanner_instance_admin.rb +268 -0
- data/lib/google/cloud/spanner/admin/instance/v1/instance_admin_client.rb +868 -0
- data/lib/google/cloud/spanner/admin/instance/v1/instance_admin_client_config.json +78 -0
- data/lib/google/cloud/spanner/client.rb +1034 -0
- data/lib/google/cloud/spanner/commit.rb +351 -0
- data/lib/google/cloud/spanner/convert.rb +311 -0
- data/lib/google/cloud/spanner/credentials.rb +32 -0
- data/lib/google/cloud/spanner/data.rb +199 -0
- data/lib/google/cloud/spanner/database.rb +377 -0
- data/lib/google/cloud/spanner/database/job.rb +179 -0
- data/lib/google/cloud/spanner/database/list.rb +171 -0
- data/lib/google/cloud/spanner/errors.rb +73 -0
- data/lib/google/cloud/spanner/fields.rb +252 -0
- data/lib/google/cloud/spanner/instance.rb +472 -0
- data/lib/google/cloud/spanner/instance/config.rb +99 -0
- data/lib/google/cloud/spanner/instance/config/list.rb +171 -0
- data/lib/google/cloud/spanner/instance/job.rb +197 -0
- data/lib/google/cloud/spanner/instance/list.rb +167 -0
- data/lib/google/cloud/spanner/policy.rb +201 -0
- data/lib/google/cloud/spanner/pool.rb +279 -0
- data/lib/google/cloud/spanner/project.rb +480 -0
- data/lib/google/cloud/spanner/range.rb +99 -0
- data/lib/google/cloud/spanner/results.rb +280 -0
- data/lib/google/cloud/spanner/service.rb +458 -0
- data/lib/google/cloud/spanner/session.rb +565 -0
- data/lib/google/cloud/spanner/snapshot.rb +260 -0
- data/lib/google/cloud/spanner/transaction.rb +533 -0
- data/lib/google/cloud/spanner/v1.rb +17 -0
- data/lib/google/cloud/spanner/v1/doc/google/protobuf/duration.rb +77 -0
- data/lib/google/cloud/spanner/v1/doc/google/protobuf/struct.rb +73 -0
- data/lib/google/cloud/spanner/v1/doc/google/protobuf/timestamp.rb +81 -0
- data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/keys.rb +148 -0
- data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/mutation.rb +80 -0
- data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/query_plan.rb +120 -0
- data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/result_set.rb +175 -0
- data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/spanner.rb +206 -0
- data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/transaction.rb +351 -0
- data/lib/google/cloud/spanner/v1/spanner_client.rb +850 -0
- data/lib/google/cloud/spanner/v1/spanner_client_config.json +78 -0
- data/lib/google/cloud/spanner/version.rb +22 -0
- data/lib/google/spanner/admin/database/v1/spanner_database_admin_pb.rb +85 -0
- data/lib/google/spanner/admin/database/v1/spanner_database_admin_services_pb.rb +95 -0
- data/lib/google/spanner/admin/instance/v1/spanner_instance_admin_pb.rb +106 -0
- data/lib/google/spanner/admin/instance/v1/spanner_instance_admin_services_pb.rb +180 -0
- data/lib/google/spanner/v1/keys_pb.rb +33 -0
- data/lib/google/spanner/v1/mutation_pb.rb +38 -0
- data/lib/google/spanner/v1/query_plan_pb.rb +47 -0
- data/lib/google/spanner/v1/result_set_pb.rb +43 -0
- data/lib/google/spanner/v1/spanner_pb.rb +90 -0
- data/lib/google/spanner/v1/spanner_services_pb.rb +131 -0
- data/lib/google/spanner/v1/transaction_pb.rb +51 -0
- data/lib/google/spanner/v1/type_pb.rb +43 -0
- metadata +309 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Copyright 2016 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
|
+
module Google
|
|
17
|
+
module Cloud
|
|
18
|
+
module Spanner
|
|
19
|
+
class Database
|
|
20
|
+
##
|
|
21
|
+
# # Job
|
|
22
|
+
#
|
|
23
|
+
# A resource representing the long-running, asynchronous processing of
|
|
24
|
+
# a database create or update operation. The job can be refreshed to
|
|
25
|
+
# retrieve the database object once the operation has been completed.
|
|
26
|
+
#
|
|
27
|
+
# See {Project#create_database} and {Database#update}.
|
|
28
|
+
#
|
|
29
|
+
# @see https://cloud.google.com/spanner/reference/rpc/google.longrunning#google.longrunning.Operation
|
|
30
|
+
# Long-running Operation
|
|
31
|
+
#
|
|
32
|
+
# @example
|
|
33
|
+
# require "google/cloud/spanner"
|
|
34
|
+
#
|
|
35
|
+
# spanner = Google::Cloud::Spanner.new
|
|
36
|
+
#
|
|
37
|
+
# job = spanner.create_database "my-instance",
|
|
38
|
+
# "my-new-database"
|
|
39
|
+
#
|
|
40
|
+
# job.done? #=> false
|
|
41
|
+
# job.reload! # API call
|
|
42
|
+
# job.done? #=> true
|
|
43
|
+
# database = job.database
|
|
44
|
+
#
|
|
45
|
+
class Job
|
|
46
|
+
##
|
|
47
|
+
# @private The Google::Gax::Operation gRPC object.
|
|
48
|
+
attr_accessor :grpc
|
|
49
|
+
|
|
50
|
+
##
|
|
51
|
+
# @private The gRPC Service object.
|
|
52
|
+
attr_accessor :service
|
|
53
|
+
|
|
54
|
+
##
|
|
55
|
+
# @private Creates a new Database::Job instance.
|
|
56
|
+
def initialize
|
|
57
|
+
@grpc = nil
|
|
58
|
+
@service = nil
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
##
|
|
62
|
+
# The database that is the object of the operation.
|
|
63
|
+
#
|
|
64
|
+
# @return [Google::Cloud::Spanner::Database, nil] The database, or
|
|
65
|
+
# `nil` if the operation is not complete.
|
|
66
|
+
#
|
|
67
|
+
# @example
|
|
68
|
+
# require "google/cloud/spanner"
|
|
69
|
+
#
|
|
70
|
+
# spanner = Google::Cloud::Spanner.new
|
|
71
|
+
#
|
|
72
|
+
# job = spanner.create_database "my-instance",
|
|
73
|
+
# "my-new-database"
|
|
74
|
+
#
|
|
75
|
+
# job.done? #=> true
|
|
76
|
+
# database = job.database
|
|
77
|
+
#
|
|
78
|
+
def database
|
|
79
|
+
return nil unless done?
|
|
80
|
+
return nil unless @grpc.grpc_op.result == :response
|
|
81
|
+
Database.from_grpc @grpc.results, service
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
##
|
|
85
|
+
# Checks if the processing of the database operation is complete.
|
|
86
|
+
#
|
|
87
|
+
# @return [boolean] `true` when complete, `false` otherwise.
|
|
88
|
+
#
|
|
89
|
+
# @example
|
|
90
|
+
# require "google/cloud/spanner"
|
|
91
|
+
#
|
|
92
|
+
# spanner = Google::Cloud::Spanner.new
|
|
93
|
+
#
|
|
94
|
+
# job = spanner.create_database "my-instance",
|
|
95
|
+
# "my-new-database"
|
|
96
|
+
#
|
|
97
|
+
# job.done? #=> false
|
|
98
|
+
#
|
|
99
|
+
def done?
|
|
100
|
+
@grpc.done?
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
##
|
|
104
|
+
# Checks if the processing of the database operation has errored.
|
|
105
|
+
#
|
|
106
|
+
# @return [boolean] `true` when errored, `false` otherwise.
|
|
107
|
+
#
|
|
108
|
+
# @example
|
|
109
|
+
# require "google/cloud/spanner"
|
|
110
|
+
#
|
|
111
|
+
# spanner = Google::Cloud::Spanner.new
|
|
112
|
+
#
|
|
113
|
+
# job = spanner.create_database "my-instance",
|
|
114
|
+
# "my-new-database"
|
|
115
|
+
#
|
|
116
|
+
# job.error? #=> false
|
|
117
|
+
#
|
|
118
|
+
def error?
|
|
119
|
+
@grpc.error?
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
##
|
|
123
|
+
# Reloads the job with current data from the long-running,
|
|
124
|
+
# asynchronous processing of a database operation.
|
|
125
|
+
#
|
|
126
|
+
# @return [Google::Cloud::Spanner::Database::Job] The same job
|
|
127
|
+
# instance.
|
|
128
|
+
#
|
|
129
|
+
# @example
|
|
130
|
+
# require "google/cloud/spanner"
|
|
131
|
+
#
|
|
132
|
+
# spanner = Google::Cloud::Spanner.new
|
|
133
|
+
#
|
|
134
|
+
# job = spanner.create_database "my-instance",
|
|
135
|
+
# "my-new-database"
|
|
136
|
+
#
|
|
137
|
+
# job.done? #=> false
|
|
138
|
+
# job.reload! # API call
|
|
139
|
+
# job.done? #=> true
|
|
140
|
+
#
|
|
141
|
+
def reload!
|
|
142
|
+
@grpc.reload!
|
|
143
|
+
self
|
|
144
|
+
end
|
|
145
|
+
alias_method :refresh!, :reload!
|
|
146
|
+
|
|
147
|
+
##
|
|
148
|
+
# Reloads the job until the operation is complete. The delay between
|
|
149
|
+
# reloads will incrementally increase.
|
|
150
|
+
#
|
|
151
|
+
# @example
|
|
152
|
+
# require "google/cloud/spanner"
|
|
153
|
+
#
|
|
154
|
+
# spanner = Google::Cloud::Spanner.new
|
|
155
|
+
#
|
|
156
|
+
# job = spanner.create_database "my-instance",
|
|
157
|
+
# "my-new-database"
|
|
158
|
+
#
|
|
159
|
+
# job.done? #=> false
|
|
160
|
+
# job.wait_until_done!
|
|
161
|
+
# job.done? #=> true
|
|
162
|
+
#
|
|
163
|
+
def wait_until_done!
|
|
164
|
+
@grpc.wait_until_done!
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
##
|
|
168
|
+
# @private New Database::Job from a Google::Gax::Operation object.
|
|
169
|
+
def self.from_grpc grpc, service
|
|
170
|
+
new.tap do |job|
|
|
171
|
+
job.instance_variable_set :@grpc, grpc
|
|
172
|
+
job.instance_variable_set :@service, service
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Copyright 2016 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 "delegate"
|
|
17
|
+
|
|
18
|
+
module Google
|
|
19
|
+
module Cloud
|
|
20
|
+
module Spanner
|
|
21
|
+
class Database
|
|
22
|
+
##
|
|
23
|
+
# Database::List is a special case Array with additional
|
|
24
|
+
# values.
|
|
25
|
+
class List < DelegateClass(::Array)
|
|
26
|
+
##
|
|
27
|
+
# If not empty, indicates that there are more records that match
|
|
28
|
+
# the request and this value should be passed to continue.
|
|
29
|
+
attr_accessor :token
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# @private Create a new Database::List with an array of
|
|
33
|
+
# Database instances.
|
|
34
|
+
def initialize arr = []
|
|
35
|
+
super arr
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# Whether there is a next page of databases.
|
|
40
|
+
#
|
|
41
|
+
# @return [Boolean]
|
|
42
|
+
#
|
|
43
|
+
# @example
|
|
44
|
+
# require "google/cloud/spanner"
|
|
45
|
+
#
|
|
46
|
+
# spanner = Google::Cloud::Spanner.new
|
|
47
|
+
#
|
|
48
|
+
# databases = spanner.databases "my-instance"
|
|
49
|
+
# if databases.next?
|
|
50
|
+
# next_databases = databases.next
|
|
51
|
+
# end
|
|
52
|
+
def next?
|
|
53
|
+
!token.nil?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
##
|
|
57
|
+
# Retrieve the next page of databases.
|
|
58
|
+
#
|
|
59
|
+
# @return [Database::List]
|
|
60
|
+
#
|
|
61
|
+
# @example
|
|
62
|
+
# require "google/cloud/spanner"
|
|
63
|
+
#
|
|
64
|
+
# spanner = Google::Cloud::Spanner.new
|
|
65
|
+
#
|
|
66
|
+
# databases = spanner.databases "my-instance"
|
|
67
|
+
# if databases.next?
|
|
68
|
+
# next_databases = databases.next
|
|
69
|
+
# end
|
|
70
|
+
def next
|
|
71
|
+
return nil unless next?
|
|
72
|
+
ensure_service!
|
|
73
|
+
options = { token: token, max: @max }
|
|
74
|
+
grpc = @service.list_databases @instance_id, options
|
|
75
|
+
self.class.from_grpc grpc, @service, @max
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
# Retrieves remaining results by repeatedly invoking {#next} until
|
|
80
|
+
# {#next?} returns `false`. Calls the given block once for each
|
|
81
|
+
# result, which is passed as the argument to the block.
|
|
82
|
+
#
|
|
83
|
+
# An Enumerator is returned if no block is given.
|
|
84
|
+
#
|
|
85
|
+
# This method will make repeated API calls until all remaining results
|
|
86
|
+
# are retrieved. (Unlike `#each`, for example, which merely iterates
|
|
87
|
+
# over the results returned by a single API call.) Use with caution.
|
|
88
|
+
#
|
|
89
|
+
# @param [Integer] request_limit The upper limit of API requests to
|
|
90
|
+
# make to load all databases. Default is no limit.
|
|
91
|
+
# @yield [database] The block for accessing each database.
|
|
92
|
+
# @yieldparam [Database] database The database object.
|
|
93
|
+
#
|
|
94
|
+
# @return [Enumerator]
|
|
95
|
+
#
|
|
96
|
+
# @example Iterating each database by passing a block:
|
|
97
|
+
# require "google/cloud/spanner"
|
|
98
|
+
#
|
|
99
|
+
# spanner = Google::Cloud::Spanner.new
|
|
100
|
+
#
|
|
101
|
+
# databases = spanner.databases "my-instance"
|
|
102
|
+
# databases.all do |database|
|
|
103
|
+
# puts database.database_id
|
|
104
|
+
# end
|
|
105
|
+
#
|
|
106
|
+
# @example Using the enumerator by not passing a block:
|
|
107
|
+
# require "google/cloud/spanner"
|
|
108
|
+
#
|
|
109
|
+
# spanner = Google::Cloud::Spanner.new
|
|
110
|
+
#
|
|
111
|
+
# databases = spanner.databases "my-instance"
|
|
112
|
+
# all_database_ids = databases.all.map do |database|
|
|
113
|
+
# database.database_id
|
|
114
|
+
# end
|
|
115
|
+
#
|
|
116
|
+
# @example Limit the number of API calls made:
|
|
117
|
+
# require "google/cloud/spanner"
|
|
118
|
+
#
|
|
119
|
+
# spanner = Google::Cloud::Spanner.new
|
|
120
|
+
#
|
|
121
|
+
# databases = spanner.databases "my-instance"
|
|
122
|
+
# databases.all(request_limit: 10) do |database|
|
|
123
|
+
# puts database.database_id
|
|
124
|
+
# end
|
|
125
|
+
#
|
|
126
|
+
def all request_limit: nil
|
|
127
|
+
request_limit = request_limit.to_i if request_limit
|
|
128
|
+
unless block_given?
|
|
129
|
+
return enum_for(:all, request_limit: request_limit)
|
|
130
|
+
end
|
|
131
|
+
results = self
|
|
132
|
+
loop do
|
|
133
|
+
results.each { |r| yield r }
|
|
134
|
+
if request_limit
|
|
135
|
+
request_limit -= 1
|
|
136
|
+
break if request_limit < 0
|
|
137
|
+
end
|
|
138
|
+
break unless results.next?
|
|
139
|
+
results = results.next
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
##
|
|
144
|
+
# @private New Database::List from a
|
|
145
|
+
# Google::Spanner::Admin::Database::V1::ListDatabasesResponse
|
|
146
|
+
# object.
|
|
147
|
+
def self.from_grpc grpc, service, instance_id, max = nil
|
|
148
|
+
databases = List.new(Array(grpc.databases).map do |database|
|
|
149
|
+
Database.from_grpc database, service
|
|
150
|
+
end)
|
|
151
|
+
databases.instance_variable_set :@instance_id, instance_id
|
|
152
|
+
token = grpc.next_page_token
|
|
153
|
+
token = nil if token == ""
|
|
154
|
+
databases.instance_variable_set :@token, token
|
|
155
|
+
databases.instance_variable_set :@service, service
|
|
156
|
+
databases.instance_variable_set :@max, max
|
|
157
|
+
databases
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
protected
|
|
161
|
+
|
|
162
|
+
##
|
|
163
|
+
# Raise an error unless an active service is available.
|
|
164
|
+
def ensure_service!
|
|
165
|
+
fail "Must have active connection" unless @service
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
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/errors"
|
|
17
|
+
|
|
18
|
+
module Google
|
|
19
|
+
module Cloud
|
|
20
|
+
module Spanner
|
|
21
|
+
##
|
|
22
|
+
# # Rollback
|
|
23
|
+
#
|
|
24
|
+
# Used to rollback a transaction without passing on the exception. See
|
|
25
|
+
# {Client#transaction}.
|
|
26
|
+
#
|
|
27
|
+
# @example
|
|
28
|
+
# require "google/cloud/spanner"
|
|
29
|
+
#
|
|
30
|
+
# spanner = Google::Cloud::Spanner.new
|
|
31
|
+
# db = spanner.client "my-instance", "my-database"
|
|
32
|
+
#
|
|
33
|
+
# db.transaction do |tx|
|
|
34
|
+
# c.update "users", [{ id: 1, name: "Charlie", active: false }]
|
|
35
|
+
# c.insert "users", [{ id: 2, name: "Harvey", active: true }]
|
|
36
|
+
#
|
|
37
|
+
# if something_wrong?
|
|
38
|
+
# # Rollback the transaction without passing on the error
|
|
39
|
+
# # outside of the transaction method.
|
|
40
|
+
# raise Google::Cloud::Spanner::Rollback
|
|
41
|
+
# end
|
|
42
|
+
# end
|
|
43
|
+
#
|
|
44
|
+
class Rollback < Google::Cloud::Error
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# # DuplicateNameError
|
|
49
|
+
#
|
|
50
|
+
# Data accessed by name (typically by calling
|
|
51
|
+
# {Google::Cloud::Spanner::Data#[]} with a key or calling
|
|
52
|
+
# {Google::Cloud::Spanner::Data#to_h}) has more than one occurrence of the
|
|
53
|
+
# same name. Such data should be accessed by position rather than by name.
|
|
54
|
+
#
|
|
55
|
+
class DuplicateNameError < Google::Cloud::Error
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
##
|
|
59
|
+
# # SessionLimitError
|
|
60
|
+
#
|
|
61
|
+
# More sessions have been allocated than configured for.
|
|
62
|
+
class SessionLimitError < Google::Cloud::Error
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
##
|
|
66
|
+
# # ClientClosedError
|
|
67
|
+
#
|
|
68
|
+
# The client is closed and can no longer be used.
|
|
69
|
+
class ClientClosedError < Google::Cloud::Error
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,252 @@
|
|
|
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/convert"
|
|
17
|
+
|
|
18
|
+
module Google
|
|
19
|
+
module Cloud
|
|
20
|
+
module Spanner
|
|
21
|
+
##
|
|
22
|
+
# # Fields
|
|
23
|
+
#
|
|
24
|
+
# Represents the field names and types of data returned by Cloud Spanner.
|
|
25
|
+
#
|
|
26
|
+
# See [Data
|
|
27
|
+
# types](https://cloud.google.com/spanner/docs/data-definition-language#data_types).
|
|
28
|
+
#
|
|
29
|
+
# @example
|
|
30
|
+
# require "google/cloud/spanner"
|
|
31
|
+
#
|
|
32
|
+
# spanner = Google::Cloud::Spanner.new
|
|
33
|
+
#
|
|
34
|
+
# db = spanner.client "my-instance", "my-database"
|
|
35
|
+
#
|
|
36
|
+
# results = db.execute "SELECT * FROM users"
|
|
37
|
+
#
|
|
38
|
+
# results.fields.pairs.each do |name, type|
|
|
39
|
+
# puts "Column #{name} is type {type}"
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
class Fields
|
|
43
|
+
##
|
|
44
|
+
# @private
|
|
45
|
+
def initialize types
|
|
46
|
+
@fields = []
|
|
47
|
+
if types.is_a? Array
|
|
48
|
+
types.each do |type|
|
|
49
|
+
@fields << field(type)
|
|
50
|
+
end
|
|
51
|
+
elsif types.is_a? Hash
|
|
52
|
+
types.each do |type|
|
|
53
|
+
@fields << field(type)
|
|
54
|
+
end
|
|
55
|
+
else
|
|
56
|
+
fail ArgumentError, "can only accept Array or Hash"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
##
|
|
61
|
+
# Returns the types of the data.
|
|
62
|
+
#
|
|
63
|
+
# See [Data
|
|
64
|
+
# types](https://cloud.google.com/spanner/docs/data-definition-language#data_types).
|
|
65
|
+
#
|
|
66
|
+
# @return [Array<Symbol>] An array containing the types of the data.
|
|
67
|
+
#
|
|
68
|
+
def types
|
|
69
|
+
@fields.map(&:type).map do |type|
|
|
70
|
+
if type.code == :ARRAY
|
|
71
|
+
if type.array_element_type.code == :STRUCT
|
|
72
|
+
[Fields.from_grpc(type.array_element_type.struct_type.fields)]
|
|
73
|
+
else
|
|
74
|
+
[type.array_element_type.code]
|
|
75
|
+
end
|
|
76
|
+
elsif type.code == :STRUCT
|
|
77
|
+
Fields.from_grpc type.struct_type.fields
|
|
78
|
+
else
|
|
79
|
+
type.code
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
##
|
|
85
|
+
# Returns the names of the data values, or in cases in which values are
|
|
86
|
+
# unnamed, the zero-based index position of values.
|
|
87
|
+
#
|
|
88
|
+
# @return [Array<(String,Integer)>] An array containing the names
|
|
89
|
+
# (String) or position (Integer) for the corresponding values of the
|
|
90
|
+
# data.
|
|
91
|
+
#
|
|
92
|
+
def keys
|
|
93
|
+
@fields.each_with_index.map do |field, index|
|
|
94
|
+
if field.name.empty?
|
|
95
|
+
index
|
|
96
|
+
else
|
|
97
|
+
field.name.to_sym
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
##
|
|
103
|
+
# Detects duplicate names in the keys for the fields.
|
|
104
|
+
#
|
|
105
|
+
# @return [Boolean] Returns `true` if there are duplicate names.
|
|
106
|
+
#
|
|
107
|
+
def duplicate_names?
|
|
108
|
+
keys.count != keys.uniq.count
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
##
|
|
112
|
+
# Returns the names or positions and their corresponding types as an
|
|
113
|
+
# array of arrays.
|
|
114
|
+
#
|
|
115
|
+
# @return [Array<Array>] An array containing name/position and types
|
|
116
|
+
# pairs.
|
|
117
|
+
#
|
|
118
|
+
def pairs
|
|
119
|
+
keys.zip types
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
##
|
|
123
|
+
# Returns the type code for the provided name (String) or index
|
|
124
|
+
# (Integer). Do not pass a name to this method if the data has more than
|
|
125
|
+
# one member with the same name. (See {#duplicate_names?})
|
|
126
|
+
#
|
|
127
|
+
# @param [String, Integer] key The name (String) or zero-based index
|
|
128
|
+
# position (Integer) of the value.
|
|
129
|
+
#
|
|
130
|
+
# @raise [Google::Cloud::Spanner::DuplicateNameError] if the data
|
|
131
|
+
# contains duplicate names.
|
|
132
|
+
#
|
|
133
|
+
# @return [Symbol, nil] The type code, or nil if no value is found.
|
|
134
|
+
#
|
|
135
|
+
def [] key
|
|
136
|
+
return types[key] if key.is_a? Integer
|
|
137
|
+
name_count = @fields.find_all { |f| f.name == String(key) }.count
|
|
138
|
+
return nil if name_count == 0
|
|
139
|
+
fail DuplicateNameError if name_count > 1
|
|
140
|
+
index = @fields.find_index { |f| f.name == String(key) }
|
|
141
|
+
types[index]
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
##
|
|
145
|
+
# Returns the type codes as an array. Do not use this method if the data
|
|
146
|
+
# has more than one member with the same name. (See {#duplicate_names?})
|
|
147
|
+
#
|
|
148
|
+
# @raise [Google::Cloud::Spanner::DuplicateNameError] if the data
|
|
149
|
+
# contains duplicate names.
|
|
150
|
+
#
|
|
151
|
+
# @return [Array<Symbol>] An array containing the type codes.
|
|
152
|
+
#
|
|
153
|
+
def to_a
|
|
154
|
+
keys.count.times.map { |i| self[i] }.map do |field|
|
|
155
|
+
if field.is_a? Fields
|
|
156
|
+
field.to_h
|
|
157
|
+
elsif field.is_a? Array
|
|
158
|
+
field.map { |f| f.is_a?(Fields) ? f.to_h : f }
|
|
159
|
+
else
|
|
160
|
+
field
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
##
|
|
166
|
+
# Returns the names or indexes and corresponding type codes as a hash.
|
|
167
|
+
#
|
|
168
|
+
# @return [Hash<(String,Integer)=>Symbol>] A hash containing the names
|
|
169
|
+
# or indexes and corresponding types.
|
|
170
|
+
#
|
|
171
|
+
def to_h
|
|
172
|
+
fail DuplicateNameError if duplicate_names?
|
|
173
|
+
hashified_pairs = pairs.map do |key, value|
|
|
174
|
+
if value.is_a? Fields
|
|
175
|
+
[key, value.to_h]
|
|
176
|
+
elsif value.is_a? Array
|
|
177
|
+
[key, value.map { |v| v.is_a?(Fields) ? v.to_h : v }]
|
|
178
|
+
else
|
|
179
|
+
[key, value]
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
Hash[hashified_pairs]
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# @private
|
|
186
|
+
def data data
|
|
187
|
+
# TODO: match order of types
|
|
188
|
+
data = data.values if data.is_a?(Hash)
|
|
189
|
+
values = data.map { |datum| Convert.raw_to_value datum }
|
|
190
|
+
Data.from_grpc values, @fields
|
|
191
|
+
end
|
|
192
|
+
alias_method :new, :data
|
|
193
|
+
|
|
194
|
+
# @private
|
|
195
|
+
def == other
|
|
196
|
+
return false unless other.is_a? Fields
|
|
197
|
+
pairs == other.pairs
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# @private
|
|
201
|
+
def to_s
|
|
202
|
+
named_types = pairs.map do |key, type|
|
|
203
|
+
if key.is_a? Integer
|
|
204
|
+
"#{type.inspect}"
|
|
205
|
+
else
|
|
206
|
+
"(#{key})#{type.inspect}"
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
"(#{named_types.join ', '})"
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# @private
|
|
213
|
+
def inspect
|
|
214
|
+
"#<#{self.class.name} #{self}>"
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
##
|
|
218
|
+
# @private Creates a new Fields instance from a
|
|
219
|
+
# Google::Spanner::V1::Metadata::Row_type::Fields.
|
|
220
|
+
def self.from_grpc fields
|
|
221
|
+
new([]).tap do |f|
|
|
222
|
+
f.instance_variable_set :@fields, fields
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
protected
|
|
227
|
+
|
|
228
|
+
def field pair
|
|
229
|
+
if pair.is_a?(Array)
|
|
230
|
+
unless pair.count == 2
|
|
231
|
+
fail ArgumentError, "can only accept pairs of name and type"
|
|
232
|
+
end
|
|
233
|
+
if pair.first.nil? || pair.first.is_a?(Integer)
|
|
234
|
+
Google::Spanner::V1::StructType::Field.new(
|
|
235
|
+
type: Google::Spanner::V1::Type.new(code: pair.last))
|
|
236
|
+
else
|
|
237
|
+
Google::Spanner::V1::StructType::Field.new(
|
|
238
|
+
name: String(pair.first),
|
|
239
|
+
type: Google::Spanner::V1::Type.new(code: pair.last))
|
|
240
|
+
end
|
|
241
|
+
else
|
|
242
|
+
unless pair.is_a?(Symbol)
|
|
243
|
+
fail ArgumentError, "type must be a symbol"
|
|
244
|
+
end
|
|
245
|
+
Google::Spanner::V1::StructType::Field.new(
|
|
246
|
+
type: Google::Spanner::V1::Type.new(code: pair))
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|