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,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