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.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +18 -9
  3. data/lib/cassandra.rb +5 -1
  4. data/lib/cassandra/address_resolution.rb +1 -1
  5. data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +1 -1
  6. data/lib/cassandra/address_resolution/policies/none.rb +1 -1
  7. data/lib/cassandra/auth.rb +1 -1
  8. data/lib/cassandra/auth/providers.rb +1 -1
  9. data/lib/cassandra/auth/providers/password.rb +1 -1
  10. data/lib/cassandra/cluster.rb +1 -1
  11. data/lib/cassandra/cluster/client.rb +33 -13
  12. data/lib/cassandra/cluster/connection_pool.rb +1 -1
  13. data/lib/cassandra/cluster/connector.rb +1 -36
  14. data/lib/cassandra/cluster/control_connection.rb +85 -9
  15. data/lib/cassandra/cluster/failed_connection.rb +1 -1
  16. data/lib/cassandra/cluster/metadata.rb +1 -1
  17. data/lib/cassandra/cluster/options.rb +15 -4
  18. data/lib/cassandra/cluster/registry.rb +1 -1
  19. data/lib/cassandra/cluster/schema.rb +76 -16
  20. data/lib/cassandra/cluster/schema/partitioners.rb +1 -1
  21. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +1 -1
  22. data/lib/cassandra/cluster/schema/partitioners/ordered.rb +1 -1
  23. data/lib/cassandra/cluster/schema/partitioners/random.rb +1 -1
  24. data/lib/cassandra/cluster/schema/replication_strategies.rb +1 -1
  25. data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +1 -1
  26. data/lib/cassandra/cluster/schema/replication_strategies/none.rb +1 -1
  27. data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +1 -1
  28. data/lib/cassandra/cluster/schema/type_parser.rb +35 -8
  29. data/lib/cassandra/column.rb +10 -14
  30. data/lib/cassandra/compression.rb +1 -1
  31. data/lib/cassandra/compression/compressors/lz4.rb +1 -1
  32. data/lib/cassandra/compression/compressors/snappy.rb +1 -1
  33. data/lib/cassandra/driver.rb +2 -2
  34. data/lib/cassandra/errors.rb +1 -1
  35. data/lib/cassandra/execution/info.rb +1 -1
  36. data/lib/cassandra/execution/options.rb +3 -2
  37. data/lib/cassandra/execution/trace.rb +1 -1
  38. data/lib/cassandra/executors.rb +1 -1
  39. data/lib/cassandra/future.rb +1 -1
  40. data/lib/cassandra/host.rb +1 -1
  41. data/lib/cassandra/keyspace.rb +55 -5
  42. data/lib/cassandra/listener.rb +1 -1
  43. data/lib/cassandra/load_balancing.rb +1 -1
  44. data/lib/cassandra/load_balancing/policies.rb +1 -1
  45. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +1 -1
  46. data/lib/cassandra/load_balancing/policies/round_robin.rb +1 -1
  47. data/lib/cassandra/load_balancing/policies/token_aware.rb +1 -1
  48. data/lib/cassandra/load_balancing/policies/white_list.rb +1 -1
  49. data/lib/cassandra/null_logger.rb +1 -1
  50. data/lib/cassandra/protocol.rb +6 -1
  51. data/lib/cassandra/protocol/coder.rb +319 -84
  52. data/lib/cassandra/protocol/cql_byte_buffer.rb +1 -1
  53. data/lib/cassandra/protocol/cql_protocol_handler.rb +24 -10
  54. data/lib/cassandra/protocol/request.rb +1 -1
  55. data/lib/cassandra/protocol/requests/auth_response_request.rb +1 -1
  56. data/lib/cassandra/protocol/requests/batch_request.rb +1 -1
  57. data/lib/cassandra/protocol/requests/credentials_request.rb +1 -1
  58. data/lib/cassandra/protocol/requests/execute_request.rb +1 -1
  59. data/lib/cassandra/protocol/requests/options_request.rb +1 -1
  60. data/lib/cassandra/protocol/requests/prepare_request.rb +1 -1
  61. data/lib/cassandra/protocol/requests/query_request.rb +5 -3
  62. data/lib/cassandra/protocol/requests/register_request.rb +1 -1
  63. data/lib/cassandra/protocol/requests/startup_request.rb +1 -1
  64. data/lib/cassandra/protocol/requests/void_query_request.rb +1 -1
  65. data/lib/cassandra/protocol/response.rb +1 -1
  66. data/lib/cassandra/protocol/responses/already_exists_error_response.rb +1 -1
  67. data/lib/cassandra/protocol/responses/auth_challenge_response.rb +1 -1
  68. data/lib/cassandra/protocol/responses/auth_success_response.rb +1 -1
  69. data/lib/cassandra/protocol/responses/authenticate_response.rb +1 -1
  70. data/lib/cassandra/protocol/responses/error_response.rb +1 -1
  71. data/lib/cassandra/protocol/responses/event_response.rb +1 -1
  72. data/lib/cassandra/protocol/responses/prepared_result_response.rb +1 -1
  73. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +9 -2
  74. data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +1 -1
  75. data/lib/cassandra/protocol/responses/ready_response.rb +1 -1
  76. data/lib/cassandra/protocol/responses/result_response.rb +1 -1
  77. data/lib/cassandra/protocol/responses/rows_result_response.rb +1 -1
  78. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +21 -6
  79. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +18 -8
  80. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +1 -1
  81. data/lib/cassandra/protocol/responses/status_change_event_response.rb +1 -1
  82. data/lib/cassandra/protocol/responses/supported_response.rb +1 -1
  83. data/lib/cassandra/protocol/responses/topology_change_event_response.rb +1 -1
  84. data/lib/cassandra/protocol/responses/unavailable_error_response.rb +1 -1
  85. data/lib/cassandra/protocol/responses/unprepared_error_response.rb +1 -1
  86. data/lib/cassandra/protocol/responses/void_result_response.rb +1 -1
  87. data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +1 -1
  88. data/lib/cassandra/protocol/v1.rb +4 -2
  89. data/lib/cassandra/protocol/v3.rb +280 -0
  90. data/lib/cassandra/reconnection.rb +1 -1
  91. data/lib/cassandra/reconnection/policies.rb +1 -1
  92. data/lib/cassandra/reconnection/policies/constant.rb +1 -1
  93. data/lib/cassandra/reconnection/policies/exponential.rb +1 -1
  94. data/lib/cassandra/result.rb +1 -1
  95. data/lib/cassandra/retry.rb +1 -1
  96. data/lib/cassandra/retry/policies.rb +1 -1
  97. data/lib/cassandra/retry/policies/default.rb +1 -1
  98. data/lib/cassandra/retry/policies/downgrading_consistency.rb +1 -1
  99. data/lib/cassandra/retry/policies/fallthrough.rb +1 -1
  100. data/lib/cassandra/session.rb +14 -80
  101. data/lib/cassandra/statement.rb +1 -1
  102. data/lib/cassandra/statements.rb +1 -1
  103. data/lib/cassandra/statements/batch.rb +10 -25
  104. data/lib/cassandra/statements/bound.rb +1 -1
  105. data/lib/cassandra/statements/prepared.rb +24 -31
  106. data/lib/cassandra/statements/simple.rb +22 -66
  107. data/lib/cassandra/statements/void.rb +1 -1
  108. data/lib/cassandra/table.rb +36 -5
  109. data/lib/cassandra/time_uuid.rb +1 -1
  110. data/lib/cassandra/tuple.rb +124 -0
  111. data/lib/cassandra/types.rb +1406 -0
  112. data/lib/cassandra/udt.rb +420 -0
  113. data/lib/cassandra/util.rb +42 -64
  114. data/lib/cassandra/uuid.rb +1 -1
  115. data/lib/cassandra/uuid/generator.rb +1 -1
  116. data/lib/cassandra/version.rb +2 -2
  117. 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
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2014 DataStax, Inc.
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 assert_type(type, value, message = nil, &block)
157
- return if value.nil?
158
-
159
- case type
160
- when ::Array
161
- case type.first
162
- when :list
163
- assert_instance_of(::Array, value, message, &block)
164
- value.each do |v|
165
- assert_type(type[1], v)
166
- end
167
- when :set
168
- assert_instance_of(::Set, value, message, &block)
169
- value.each do |v|
170
- assert_type(type[1], v)
171
- end
172
- when :map
173
- assert_instance_of(::Hash, value, message, &block)
174
- value.each do |k, v|
175
- assert_type(type[1], k)
176
- assert_type(type[2], v)
177
- end
178
- when :custom
179
- assert_responds_to_all([:bytesize, :to_s], value, message, &block)
180
- else
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
- case type
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?