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