cassandra-driver 2.0.1-java → 2.1.0-java
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 +4 -4
- data/README.md +18 -9
- data/lib/cassandra.rb +5 -1
- data/lib/cassandra/address_resolution.rb +1 -1
- data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +1 -1
- data/lib/cassandra/address_resolution/policies/none.rb +1 -1
- data/lib/cassandra/auth.rb +1 -1
- data/lib/cassandra/auth/providers.rb +1 -1
- data/lib/cassandra/auth/providers/password.rb +1 -1
- data/lib/cassandra/cluster.rb +1 -1
- data/lib/cassandra/cluster/client.rb +33 -13
- data/lib/cassandra/cluster/connection_pool.rb +1 -1
- data/lib/cassandra/cluster/connector.rb +1 -36
- data/lib/cassandra/cluster/control_connection.rb +85 -9
- data/lib/cassandra/cluster/failed_connection.rb +1 -1
- data/lib/cassandra/cluster/metadata.rb +1 -1
- data/lib/cassandra/cluster/options.rb +15 -4
- data/lib/cassandra/cluster/registry.rb +1 -1
- data/lib/cassandra/cluster/schema.rb +76 -16
- data/lib/cassandra/cluster/schema/partitioners.rb +1 -1
- data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +1 -1
- data/lib/cassandra/cluster/schema/partitioners/ordered.rb +1 -1
- data/lib/cassandra/cluster/schema/partitioners/random.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies/none.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +1 -1
- data/lib/cassandra/cluster/schema/type_parser.rb +35 -8
- data/lib/cassandra/column.rb +10 -14
- data/lib/cassandra/compression.rb +1 -1
- data/lib/cassandra/compression/compressors/lz4.rb +1 -1
- data/lib/cassandra/compression/compressors/snappy.rb +1 -1
- data/lib/cassandra/driver.rb +2 -2
- data/lib/cassandra/errors.rb +1 -1
- data/lib/cassandra/execution/info.rb +1 -1
- data/lib/cassandra/execution/options.rb +3 -2
- data/lib/cassandra/execution/trace.rb +1 -1
- data/lib/cassandra/executors.rb +1 -1
- data/lib/cassandra/future.rb +1 -1
- data/lib/cassandra/host.rb +1 -1
- data/lib/cassandra/keyspace.rb +55 -5
- data/lib/cassandra/listener.rb +1 -1
- data/lib/cassandra/load_balancing.rb +1 -1
- data/lib/cassandra/load_balancing/policies.rb +1 -1
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +1 -1
- data/lib/cassandra/load_balancing/policies/round_robin.rb +1 -1
- data/lib/cassandra/load_balancing/policies/token_aware.rb +1 -1
- data/lib/cassandra/load_balancing/policies/white_list.rb +1 -1
- data/lib/cassandra/null_logger.rb +1 -1
- data/lib/cassandra/protocol.rb +6 -1
- data/lib/cassandra/protocol/coder.rb +319 -84
- data/lib/cassandra/protocol/cql_byte_buffer.rb +1 -1
- data/lib/cassandra/protocol/cql_protocol_handler.rb +24 -10
- data/lib/cassandra/protocol/request.rb +1 -1
- data/lib/cassandra/protocol/requests/auth_response_request.rb +1 -1
- data/lib/cassandra/protocol/requests/batch_request.rb +1 -1
- data/lib/cassandra/protocol/requests/credentials_request.rb +1 -1
- data/lib/cassandra/protocol/requests/execute_request.rb +1 -1
- data/lib/cassandra/protocol/requests/options_request.rb +1 -1
- data/lib/cassandra/protocol/requests/prepare_request.rb +1 -1
- data/lib/cassandra/protocol/requests/query_request.rb +5 -3
- data/lib/cassandra/protocol/requests/register_request.rb +1 -1
- data/lib/cassandra/protocol/requests/startup_request.rb +1 -1
- data/lib/cassandra/protocol/requests/void_query_request.rb +1 -1
- data/lib/cassandra/protocol/response.rb +1 -1
- data/lib/cassandra/protocol/responses/already_exists_error_response.rb +1 -1
- data/lib/cassandra/protocol/responses/auth_challenge_response.rb +1 -1
- data/lib/cassandra/protocol/responses/auth_success_response.rb +1 -1
- data/lib/cassandra/protocol/responses/authenticate_response.rb +1 -1
- data/lib/cassandra/protocol/responses/error_response.rb +1 -1
- data/lib/cassandra/protocol/responses/event_response.rb +1 -1
- data/lib/cassandra/protocol/responses/prepared_result_response.rb +1 -1
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +9 -2
- data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +1 -1
- data/lib/cassandra/protocol/responses/ready_response.rb +1 -1
- data/lib/cassandra/protocol/responses/result_response.rb +1 -1
- data/lib/cassandra/protocol/responses/rows_result_response.rb +1 -1
- data/lib/cassandra/protocol/responses/schema_change_event_response.rb +21 -6
- data/lib/cassandra/protocol/responses/schema_change_result_response.rb +18 -8
- data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +1 -1
- data/lib/cassandra/protocol/responses/status_change_event_response.rb +1 -1
- data/lib/cassandra/protocol/responses/supported_response.rb +1 -1
- data/lib/cassandra/protocol/responses/topology_change_event_response.rb +1 -1
- data/lib/cassandra/protocol/responses/unavailable_error_response.rb +1 -1
- data/lib/cassandra/protocol/responses/unprepared_error_response.rb +1 -1
- data/lib/cassandra/protocol/responses/void_result_response.rb +1 -1
- data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +1 -1
- data/lib/cassandra/protocol/v1.rb +4 -2
- data/lib/cassandra/protocol/v3.rb +280 -0
- data/lib/cassandra/reconnection.rb +1 -1
- data/lib/cassandra/reconnection/policies.rb +1 -1
- data/lib/cassandra/reconnection/policies/constant.rb +1 -1
- data/lib/cassandra/reconnection/policies/exponential.rb +1 -1
- data/lib/cassandra/result.rb +1 -1
- data/lib/cassandra/retry.rb +1 -1
- data/lib/cassandra/retry/policies.rb +1 -1
- data/lib/cassandra/retry/policies/default.rb +1 -1
- data/lib/cassandra/retry/policies/downgrading_consistency.rb +1 -1
- data/lib/cassandra/retry/policies/fallthrough.rb +1 -1
- data/lib/cassandra/session.rb +14 -80
- data/lib/cassandra/statement.rb +1 -1
- data/lib/cassandra/statements.rb +1 -1
- data/lib/cassandra/statements/batch.rb +10 -25
- data/lib/cassandra/statements/bound.rb +1 -1
- data/lib/cassandra/statements/prepared.rb +24 -31
- data/lib/cassandra/statements/simple.rb +22 -66
- data/lib/cassandra/statements/void.rb +1 -1
- data/lib/cassandra/table.rb +36 -5
- data/lib/cassandra/time_uuid.rb +1 -1
- data/lib/cassandra/tuple.rb +124 -0
- data/lib/cassandra/types.rb +1406 -0
- data/lib/cassandra/udt.rb +420 -0
- data/lib/cassandra/util.rb +42 -64
- data/lib/cassandra/uuid.rb +1 -1
- data/lib/cassandra/uuid/generator.rb +1 -1
- data/lib/cassandra/version.rb +2 -2
- metadata +38 -34
@@ -0,0 +1,420 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright 2013-2015 DataStax, Inc.
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#++
|
18
|
+
|
19
|
+
module Cassandra
|
20
|
+
# A user-defined type value representation
|
21
|
+
class UDT
|
22
|
+
# @private
|
23
|
+
class Strict < UDT
|
24
|
+
def initialize(keyspace, name, fields, values)
|
25
|
+
@keyspace = keyspace
|
26
|
+
@name = name
|
27
|
+
@fields = fields
|
28
|
+
@values = values
|
29
|
+
@name_to_type = fields.each_with_object(::Hash.new) do |f, index|
|
30
|
+
index[f.name] = f.type
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def method_missing(method, *args, &block)
|
35
|
+
return super if block_given? || args.size > 1
|
36
|
+
|
37
|
+
field = method.to_s
|
38
|
+
assign = !field.chomp!('=').nil?
|
39
|
+
|
40
|
+
return super if assign && args.empty?
|
41
|
+
return super unless @name_to_type.has_key?(field)
|
42
|
+
|
43
|
+
if assign
|
44
|
+
value = args.first
|
45
|
+
Util.assert_type(@name_to_type[field], value)
|
46
|
+
@values[field] = value
|
47
|
+
else
|
48
|
+
@values[field]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns true if a field with a given name is present in this value
|
53
|
+
#
|
54
|
+
# @param method [Symbol] name of the field
|
55
|
+
#
|
56
|
+
# @return [Boolean] whether a field is present
|
57
|
+
def respond_to?(method)
|
58
|
+
field = method.to_s
|
59
|
+
field.chomp!('=')
|
60
|
+
|
61
|
+
return true if @name_to_type.has_key?(field)
|
62
|
+
super
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns value of the field.
|
66
|
+
#
|
67
|
+
# @param field [String, Integer] name or numeric index of the field
|
68
|
+
# @return [Object] value of the field
|
69
|
+
def [](field)
|
70
|
+
case field
|
71
|
+
when ::Integer
|
72
|
+
return nil if field < 0 || field >= @fields.size
|
73
|
+
@values[@fields[field][0]]
|
74
|
+
when ::String
|
75
|
+
@values[field]
|
76
|
+
else
|
77
|
+
raise ::ArgumentError, "unrecognized field #{field} in UDT: " \
|
78
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns value of the field.
|
83
|
+
#
|
84
|
+
# @param field [String, Integer] name or numeric index of the field to
|
85
|
+
# lookup
|
86
|
+
#
|
87
|
+
# @raise [IndexError] when numeric index given is out of bounds
|
88
|
+
# @raise [KeyError] when field with a given name is not present
|
89
|
+
# @raise [ArgumentError] when neither a numeric index nor a field name given
|
90
|
+
#
|
91
|
+
# @return [Object] value of the field
|
92
|
+
def fetch(field)
|
93
|
+
case field
|
94
|
+
when ::Integer
|
95
|
+
if field < 0 || field >= @fields.size
|
96
|
+
raise ::IndexError,
|
97
|
+
"field index #{field} is not present in UDT: " \
|
98
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
99
|
+
end
|
100
|
+
@values[@fields[field][0]]
|
101
|
+
when ::String
|
102
|
+
unless @name_to_type.has_key?(field)
|
103
|
+
raise ::KeyError,
|
104
|
+
"field #{field} is not defined in UDT: " \
|
105
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
106
|
+
end
|
107
|
+
@values[field]
|
108
|
+
else
|
109
|
+
raise ::ArgumentError, "unrecognized field #{field} in UDT: " \
|
110
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Sets value of the field.
|
115
|
+
#
|
116
|
+
# @param field [String, Integer] name or numeric index of the field
|
117
|
+
# @param value [Object] new value for the field
|
118
|
+
#
|
119
|
+
# @raise [IndexError] when numeric index given is out of bounds
|
120
|
+
# @raise [KeyError] when field with a given name is not present
|
121
|
+
# @raise [ArgumentError] when neither a numeric index nor a field name
|
122
|
+
# given
|
123
|
+
#
|
124
|
+
# @return [Object] value.
|
125
|
+
def []=(field, value)
|
126
|
+
case field
|
127
|
+
when ::Integer
|
128
|
+
if field < 0 || field >= @fields.size
|
129
|
+
raise ::IndexError,
|
130
|
+
"field index #{field} is not present in UDT: " \
|
131
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
132
|
+
end
|
133
|
+
Util.assert_type(@fields[field][1], value)
|
134
|
+
@values[@fields[field][0]] = value
|
135
|
+
when ::String
|
136
|
+
unless @name_to_type.has_key?(field)
|
137
|
+
raise ::KeyError,
|
138
|
+
"field #{field} is not defined in UDT: " \
|
139
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
140
|
+
end
|
141
|
+
Util.assert_type(@name_to_type[field], value)
|
142
|
+
@values[field] = value
|
143
|
+
else
|
144
|
+
raise ::ArgumentError, "unrecognized field #{field} in UDT: " \
|
145
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Iterates over all fields of the UDT
|
150
|
+
# @yieldparam name [String] field name
|
151
|
+
# @yieldparam value [Object] field value
|
152
|
+
# @return [Cassandra::UDT] self
|
153
|
+
def each(&block)
|
154
|
+
@fields.each do |f|
|
155
|
+
n = f.name
|
156
|
+
yield(n, @values[n])
|
157
|
+
end
|
158
|
+
self
|
159
|
+
end
|
160
|
+
|
161
|
+
# Returns UDT size
|
162
|
+
# @return [Integer] UDT size
|
163
|
+
def size
|
164
|
+
@fields.size
|
165
|
+
end
|
166
|
+
|
167
|
+
def inspect
|
168
|
+
"#<Cassandra::UDT:0x#{self.object_id.to_s(16)} #{to_s}>"
|
169
|
+
end
|
170
|
+
|
171
|
+
def eql?(other)
|
172
|
+
(other.is_a?(Strict) && @values.all? {|n, v| v == other[n]}) ||
|
173
|
+
(other.is_a?(UDT) && other == self)
|
174
|
+
end
|
175
|
+
alias :== :eql?
|
176
|
+
end
|
177
|
+
|
178
|
+
include Enumerable
|
179
|
+
|
180
|
+
# Creates a UDT instance
|
181
|
+
# @param values [Hash<String, Object>, Array<Array<String, Object>>,
|
182
|
+
# *Object, *Array<String, Object>] - UDT field values
|
183
|
+
# @example Various ways of creating the same UDT instance
|
184
|
+
# Cassandra::UDT.new({'street' => '123 Main St.', 'city' => 'Whatever', 'state' => 'XZ', 'zip' => '10020'})
|
185
|
+
#
|
186
|
+
# Cassandra::UDT.new(street: '123 Main St.', city: 'Whatever', state: 'XZ', zip: '10020')
|
187
|
+
#
|
188
|
+
# Cassandra::UDT.new('street', '123 Main St.', 'city', 'Whatever', 'state', 'XZ', 'zip', '10020')
|
189
|
+
#
|
190
|
+
# Cassandra::UDT.new(:street, '123 Main St.', :city, 'Whatever', :state, 'XZ', :zip, '10020')
|
191
|
+
#
|
192
|
+
# Cassandra::UDT.new(['street', '123 Main St.'], ['city', 'Whatever'], ['state', 'XZ'], ['zip', '10020'])
|
193
|
+
#
|
194
|
+
# Cassandra::UDT.new([:street, '123 Main St.'], [:city, 'Whatever'], [:state, 'XZ'], [:zip, '10020'])
|
195
|
+
#
|
196
|
+
# Cassandra::UDT.new([['street', '123 Main St.'], ['city', 'Whatever'], ['state', 'XZ'], ['zip', '10020']])
|
197
|
+
#
|
198
|
+
# Cassandra::UDT.new([[:street, '123 Main St.'], [:city, 'Whatever'], [:state, 'XZ'], [:zip, '10020']])
|
199
|
+
def initialize(*values)
|
200
|
+
values = Array(values.first) if values.one?
|
201
|
+
|
202
|
+
Util.assert_not_empty(values,
|
203
|
+
"user-defined type must contain at least one value"
|
204
|
+
)
|
205
|
+
|
206
|
+
if values.first.is_a?(::Array)
|
207
|
+
@values = values.map do |pair|
|
208
|
+
Util.assert(pair.size == 2,
|
209
|
+
"values of a user-defined type must be an Array of name and " \
|
210
|
+
"value pairs, #{pair.inspect} given"
|
211
|
+
)
|
212
|
+
name, value = pair
|
213
|
+
|
214
|
+
[String(name), value]
|
215
|
+
end
|
216
|
+
else
|
217
|
+
Util.assert((values.size % 2) == 0,
|
218
|
+
"values of a user-defined type must be an Array of alternating " \
|
219
|
+
"names and values pairs, #{values.inspect} given"
|
220
|
+
)
|
221
|
+
@values = values.each_slice(2).map do |(name, value)|
|
222
|
+
[String(name), value]
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# @!visibility public
|
228
|
+
# Allows access to properties of a User-Defined Type.
|
229
|
+
#
|
230
|
+
# @example Getting and setting field values
|
231
|
+
# session.execute("CREATE TYPE address (street text, zipcode int)")
|
232
|
+
# session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
|
233
|
+
# row = session.execute("SELECT * FROM users WHERE id = 123").first
|
234
|
+
# address = row['address']
|
235
|
+
#
|
236
|
+
# puts address.street
|
237
|
+
# address.street = '123 SomePlace Cir'
|
238
|
+
#
|
239
|
+
# @overload method_missing(field)
|
240
|
+
# @param field [Symbol] name of the field to lookup
|
241
|
+
# @raise [NoMethodError] if the field is not present
|
242
|
+
# @return [Object] value of the field if present
|
243
|
+
# @overload method_missing(field, value)
|
244
|
+
# @param field [Symbol] name of the field (suffixed with `=`) to set
|
245
|
+
# the value for
|
246
|
+
# @param value [Symbol] new value for the field
|
247
|
+
# @raise [NoMethodError] if the field is not present
|
248
|
+
# @return [Cassandra::UDT] self.
|
249
|
+
def method_missing(field, *args, &block)
|
250
|
+
return super if block_given? || args.size > 1
|
251
|
+
|
252
|
+
key = field.to_s
|
253
|
+
set = !key.chomp!('=').nil?
|
254
|
+
|
255
|
+
return super if set && args.empty?
|
256
|
+
|
257
|
+
index = @values.index {|(name, _)| name == key}
|
258
|
+
return super unless index
|
259
|
+
|
260
|
+
if set
|
261
|
+
@values[index][1] = args.first
|
262
|
+
else
|
263
|
+
@values[index][1]
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
# Returns true if a field with a given name is present
|
268
|
+
#
|
269
|
+
# @param field [Symbol] method or name of the field
|
270
|
+
#
|
271
|
+
# @return [Boolean] whether a field is present
|
272
|
+
def respond_to?(field)
|
273
|
+
key = field.to_s
|
274
|
+
key.chomp!('=')
|
275
|
+
|
276
|
+
return true if @values.any? {|(name, _)| name == key}
|
277
|
+
super
|
278
|
+
end
|
279
|
+
|
280
|
+
# Returns value of the field.
|
281
|
+
#
|
282
|
+
# @param field [String, Integer] name or numeric index of the field to
|
283
|
+
# lookup
|
284
|
+
#
|
285
|
+
# @raise [ArgumentError] when neither a numeric index nor a field name given
|
286
|
+
#
|
287
|
+
# @return [Object] value of the field, or nil if the field is not present
|
288
|
+
def [](field)
|
289
|
+
case field
|
290
|
+
when ::Integer
|
291
|
+
return nil if field >= 0 && field < @values.size
|
292
|
+
|
293
|
+
@values[field][1]
|
294
|
+
when ::String
|
295
|
+
index = @values.index {|(n, _)| field == n}
|
296
|
+
|
297
|
+
index && @values[index][1]
|
298
|
+
else
|
299
|
+
raise ::ArgumentError, "Unrecognized field #{field.inspect}"
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
# Returns value of the field.
|
304
|
+
#
|
305
|
+
# @param field [String, Integer] name or numeric index of the field to
|
306
|
+
# lookup
|
307
|
+
#
|
308
|
+
# @raise [IndexError] when numeric index given is out of bounds
|
309
|
+
# @raise [KeyError] when field with a given name is not present
|
310
|
+
# @raise [ArgumentError] when neither a numeric index nor a field name given
|
311
|
+
#
|
312
|
+
# @return [Object] value of the field
|
313
|
+
def fetch(field)
|
314
|
+
case field
|
315
|
+
when ::Integer
|
316
|
+
if field >= 0 && field < @values.size
|
317
|
+
raise ::IndexError, "Field index #{field.inspect} is not present"
|
318
|
+
end
|
319
|
+
|
320
|
+
@values[field][1]
|
321
|
+
when ::String
|
322
|
+
index = @values.index {|(n, _)| field == n}
|
323
|
+
|
324
|
+
unless index
|
325
|
+
raise ::KeyError, "Unsupported field #{field.inspect}"
|
326
|
+
end
|
327
|
+
|
328
|
+
@values[index][1]
|
329
|
+
else
|
330
|
+
raise ::ArgumentError, "Unrecognized field #{field.inspect}"
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
# @param field [String, Integer] name or numeric index of the field to
|
335
|
+
# lookup
|
336
|
+
#
|
337
|
+
# @return [Boolean] whether the field is present in this UDT
|
338
|
+
def has_field?(field)
|
339
|
+
case field
|
340
|
+
when ::Integer
|
341
|
+
return false if field < 0 || field >= @values.size
|
342
|
+
when ::String
|
343
|
+
return false unless @values.index {|(n, _)| field == n}
|
344
|
+
else
|
345
|
+
return false
|
346
|
+
end
|
347
|
+
|
348
|
+
true
|
349
|
+
end
|
350
|
+
|
351
|
+
alias :include? :has_field?
|
352
|
+
|
353
|
+
# Sets value of the field.
|
354
|
+
#
|
355
|
+
# @param field [String] name of the field to set
|
356
|
+
# @param value [Object] new value for the field
|
357
|
+
#
|
358
|
+
# @raise [IndexError] when numeric index given is out of bounds
|
359
|
+
# @raise [KeyError] when field with a given name is not present
|
360
|
+
# @raise [ArgumentError] when neither a numeric index nor a field name given
|
361
|
+
#
|
362
|
+
# @return [Object] value.
|
363
|
+
def []=(field, value)
|
364
|
+
case field
|
365
|
+
when ::Integer
|
366
|
+
if field < 0 || field >= @values.size
|
367
|
+
raise ::IndexError, "Field index #{field.inspect} is not present"
|
368
|
+
end
|
369
|
+
|
370
|
+
@values[field][1] = value
|
371
|
+
when ::String
|
372
|
+
index = @values.index {|(n, _)| field == n}
|
373
|
+
|
374
|
+
unless index
|
375
|
+
raise ::KeyError, "Unsupported field #{field.inspect}"
|
376
|
+
end
|
377
|
+
|
378
|
+
@values[index][1] = value
|
379
|
+
else
|
380
|
+
raise ::ArgumentError, "Unrecognized field #{field.inspect}"
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
# Iterates over all fields of the UDT
|
385
|
+
# @yieldparam name [String] field name
|
386
|
+
# @yieldparam value [Object] field value
|
387
|
+
# @return [Cassandra::UDT] self
|
388
|
+
def each(&block)
|
389
|
+
@values.each {|(n, v)| yield(n, v)}
|
390
|
+
self
|
391
|
+
end
|
392
|
+
|
393
|
+
# Returns UDT size
|
394
|
+
# @return [Integer] UDT size
|
395
|
+
def size
|
396
|
+
@values.size
|
397
|
+
end
|
398
|
+
|
399
|
+
# Hash representation of the UDT
|
400
|
+
def to_h
|
401
|
+
@values.each_with_object(::Hash.new) do |(n, v), hash|
|
402
|
+
hash[n] = v
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
# String representation of the UDT
|
407
|
+
def to_s
|
408
|
+
'{ ' + @values.map {|(n, v)| "#{n}: #{v.inspect}"}.join(', ') + ' }'
|
409
|
+
end
|
410
|
+
|
411
|
+
def inspect
|
412
|
+
"#<Cassandra::UDT:0x#{self.object_id.to_s(16)} #{to_s}>"
|
413
|
+
end
|
414
|
+
|
415
|
+
def eql?(other)
|
416
|
+
other.is_a?(UDT) && @values.all? {|(n, v)| v == other[n]}
|
417
|
+
end
|
418
|
+
alias :== :eql?
|
419
|
+
end
|
420
|
+
end
|
data/lib/cassandra/util.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright 2013-
|
4
|
+
# Copyright 2013-2015 DataStax, Inc.
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -132,78 +132,47 @@ module Cassandra
|
|
132
132
|
io.string
|
133
133
|
end
|
134
134
|
|
135
|
-
def type_to_cql(type)
|
136
|
-
case type
|
137
|
-
when Array
|
138
|
-
case type[0]
|
139
|
-
when :list, :set
|
140
|
-
"#{type[0].to_s}<#{type_to_cql(type[1])}>"
|
141
|
-
when :map
|
142
|
-
"#{type[0].to_s}<#{type_to_cql(type[1])}, #{type_to_cql(type[2])}>"
|
143
|
-
else
|
144
|
-
type.to_s
|
145
|
-
end
|
146
|
-
else
|
147
|
-
type.to_s
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
135
|
def escape_name(name)
|
152
136
|
return name if name[LOWERCASE_REGEXP] == name
|
153
137
|
DBL_QUOT + name + DBL_QUOT
|
154
138
|
end
|
155
139
|
|
156
|
-
def
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
when ::
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
raise ::RuntimeError, "unsupported complex type #{type.inspect}"
|
182
|
-
end
|
140
|
+
def guess_type(object)
|
141
|
+
case object
|
142
|
+
when ::String then Types.varchar
|
143
|
+
when ::Fixnum then Types.bigint
|
144
|
+
when ::Float then Types.double
|
145
|
+
when ::Bignum then Types.varint
|
146
|
+
when ::BigDecimal then Types.decimal
|
147
|
+
when ::TrueClass then Types.boolean
|
148
|
+
when ::FalseClass then Types.boolean
|
149
|
+
when ::NilClass then Types.bigint
|
150
|
+
when Uuid then Types.uuid
|
151
|
+
when TimeUuid then Types.timeuuid
|
152
|
+
when ::IPAddr then Types.inet
|
153
|
+
when ::Time then Types.timestamp
|
154
|
+
when ::Hash
|
155
|
+
pair = object.first
|
156
|
+
Types.map(guess_type(pair[0]), guess_type(pair[1]))
|
157
|
+
when ::Array then Types.list(guess_type(object.first))
|
158
|
+
when ::Set then Types.set(guess_type(object.first))
|
159
|
+
when Tuple::Strict then Types.tuple(*object.types)
|
160
|
+
when Tuple then Types.tuple(*object.map {|v| guess_type(v)})
|
161
|
+
when UDT::Strict
|
162
|
+
Types.udt(object.keyspace, object.name, object.types)
|
163
|
+
when UDT
|
164
|
+
Types.udt('unknown', 'unknown', object.map {|k, v| [k, guess_type(v)]})
|
183
165
|
else
|
184
|
-
|
185
|
-
when :ascii then assert_instance_of(::String, value, message, &block)
|
186
|
-
when :bigint then assert_instance_of(::Numeric, value, message, &block)
|
187
|
-
when :blob then assert_instance_of(::String, value, message, &block)
|
188
|
-
when :boolean then assert_instance_of_one_of([::TrueClass, ::FalseClass], value, message, &block)
|
189
|
-
when :counter then assert_instance_of(::Numeric, value, message, &block)
|
190
|
-
when :decimal then assert_instance_of(::BigDecimal, value, message, &block)
|
191
|
-
when :double then assert_instance_of(::Float, value, message, &block)
|
192
|
-
when :float then assert_instance_of(::Float, value, message, &block)
|
193
|
-
when :inet then assert_instance_of(::IPAddr, value, message, &block)
|
194
|
-
when :int then assert_instance_of(::Numeric, value, message, &block)
|
195
|
-
when :text then assert_instance_of(::String, value, message, &block)
|
196
|
-
when :varchar then assert_instance_of(::String, value, message, &block)
|
197
|
-
when :timestamp then assert_instance_of(::Time, value, message, &block)
|
198
|
-
when :timeuuid then assert_instance_of(TimeUuid, value, message, &block)
|
199
|
-
when :uuid then assert_instance_of(Uuid, value, message, &block)
|
200
|
-
when :varint then assert_instance_of(::Numeric, value, message, &block)
|
201
|
-
else
|
202
|
-
raise ::RuntimeError, "unsupported type #{type.inspect}"
|
203
|
-
end
|
166
|
+
raise ::ArgumentError, "Unable to guess the type of the argument: #{object.inspect}"
|
204
167
|
end
|
205
168
|
end
|
206
169
|
|
170
|
+
def assert_type(type, value, message = nil, &block)
|
171
|
+
assert_instance_of(Cassandra::Type, type, message, &block)
|
172
|
+
return if value.nil?
|
173
|
+
type.assert(value, message, &block)
|
174
|
+
end
|
175
|
+
|
207
176
|
def assert_instance_of(kind, value, message = nil, &block)
|
208
177
|
unless value.is_a?(kind)
|
209
178
|
message = yield if block_given?
|
@@ -267,6 +236,15 @@ module Cassandra
|
|
267
236
|
end
|
268
237
|
end
|
269
238
|
|
239
|
+
def assert_size(size, value, message = nil, &block)
|
240
|
+
unless value.size == size
|
241
|
+
message = yield if block_given?
|
242
|
+
message ||= "value #{value.inspect} must have size equal to #{size.inspect}, but doesn't"
|
243
|
+
|
244
|
+
raise ::ArgumentError, message
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
270
248
|
def assert(condition, message = nil, &block)
|
271
249
|
unless condition
|
272
250
|
message = yield if block_given?
|