cassandra-driver 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/README.md +18 -9
- data/ext/cassandra_murmur3/cassandra_murmur3.c +1 -1
- 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 +19 -15
@@ -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?
|