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.
Files changed (118) hide show
  1. checksums.yaml +13 -5
  2. data/README.md +18 -9
  3. data/ext/cassandra_murmur3/cassandra_murmur3.c +1 -1
  4. data/lib/cassandra.rb +5 -1
  5. data/lib/cassandra/address_resolution.rb +1 -1
  6. data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +1 -1
  7. data/lib/cassandra/address_resolution/policies/none.rb +1 -1
  8. data/lib/cassandra/auth.rb +1 -1
  9. data/lib/cassandra/auth/providers.rb +1 -1
  10. data/lib/cassandra/auth/providers/password.rb +1 -1
  11. data/lib/cassandra/cluster.rb +1 -1
  12. data/lib/cassandra/cluster/client.rb +33 -13
  13. data/lib/cassandra/cluster/connection_pool.rb +1 -1
  14. data/lib/cassandra/cluster/connector.rb +1 -36
  15. data/lib/cassandra/cluster/control_connection.rb +85 -9
  16. data/lib/cassandra/cluster/failed_connection.rb +1 -1
  17. data/lib/cassandra/cluster/metadata.rb +1 -1
  18. data/lib/cassandra/cluster/options.rb +15 -4
  19. data/lib/cassandra/cluster/registry.rb +1 -1
  20. data/lib/cassandra/cluster/schema.rb +76 -16
  21. data/lib/cassandra/cluster/schema/partitioners.rb +1 -1
  22. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +1 -1
  23. data/lib/cassandra/cluster/schema/partitioners/ordered.rb +1 -1
  24. data/lib/cassandra/cluster/schema/partitioners/random.rb +1 -1
  25. data/lib/cassandra/cluster/schema/replication_strategies.rb +1 -1
  26. data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +1 -1
  27. data/lib/cassandra/cluster/schema/replication_strategies/none.rb +1 -1
  28. data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +1 -1
  29. data/lib/cassandra/cluster/schema/type_parser.rb +35 -8
  30. data/lib/cassandra/column.rb +10 -14
  31. data/lib/cassandra/compression.rb +1 -1
  32. data/lib/cassandra/compression/compressors/lz4.rb +1 -1
  33. data/lib/cassandra/compression/compressors/snappy.rb +1 -1
  34. data/lib/cassandra/driver.rb +2 -2
  35. data/lib/cassandra/errors.rb +1 -1
  36. data/lib/cassandra/execution/info.rb +1 -1
  37. data/lib/cassandra/execution/options.rb +3 -2
  38. data/lib/cassandra/execution/trace.rb +1 -1
  39. data/lib/cassandra/executors.rb +1 -1
  40. data/lib/cassandra/future.rb +1 -1
  41. data/lib/cassandra/host.rb +1 -1
  42. data/lib/cassandra/keyspace.rb +55 -5
  43. data/lib/cassandra/listener.rb +1 -1
  44. data/lib/cassandra/load_balancing.rb +1 -1
  45. data/lib/cassandra/load_balancing/policies.rb +1 -1
  46. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +1 -1
  47. data/lib/cassandra/load_balancing/policies/round_robin.rb +1 -1
  48. data/lib/cassandra/load_balancing/policies/token_aware.rb +1 -1
  49. data/lib/cassandra/load_balancing/policies/white_list.rb +1 -1
  50. data/lib/cassandra/null_logger.rb +1 -1
  51. data/lib/cassandra/protocol.rb +6 -1
  52. data/lib/cassandra/protocol/coder.rb +319 -84
  53. data/lib/cassandra/protocol/cql_byte_buffer.rb +1 -1
  54. data/lib/cassandra/protocol/cql_protocol_handler.rb +24 -10
  55. data/lib/cassandra/protocol/request.rb +1 -1
  56. data/lib/cassandra/protocol/requests/auth_response_request.rb +1 -1
  57. data/lib/cassandra/protocol/requests/batch_request.rb +1 -1
  58. data/lib/cassandra/protocol/requests/credentials_request.rb +1 -1
  59. data/lib/cassandra/protocol/requests/execute_request.rb +1 -1
  60. data/lib/cassandra/protocol/requests/options_request.rb +1 -1
  61. data/lib/cassandra/protocol/requests/prepare_request.rb +1 -1
  62. data/lib/cassandra/protocol/requests/query_request.rb +5 -3
  63. data/lib/cassandra/protocol/requests/register_request.rb +1 -1
  64. data/lib/cassandra/protocol/requests/startup_request.rb +1 -1
  65. data/lib/cassandra/protocol/requests/void_query_request.rb +1 -1
  66. data/lib/cassandra/protocol/response.rb +1 -1
  67. data/lib/cassandra/protocol/responses/already_exists_error_response.rb +1 -1
  68. data/lib/cassandra/protocol/responses/auth_challenge_response.rb +1 -1
  69. data/lib/cassandra/protocol/responses/auth_success_response.rb +1 -1
  70. data/lib/cassandra/protocol/responses/authenticate_response.rb +1 -1
  71. data/lib/cassandra/protocol/responses/error_response.rb +1 -1
  72. data/lib/cassandra/protocol/responses/event_response.rb +1 -1
  73. data/lib/cassandra/protocol/responses/prepared_result_response.rb +1 -1
  74. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +9 -2
  75. data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +1 -1
  76. data/lib/cassandra/protocol/responses/ready_response.rb +1 -1
  77. data/lib/cassandra/protocol/responses/result_response.rb +1 -1
  78. data/lib/cassandra/protocol/responses/rows_result_response.rb +1 -1
  79. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +21 -6
  80. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +18 -8
  81. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +1 -1
  82. data/lib/cassandra/protocol/responses/status_change_event_response.rb +1 -1
  83. data/lib/cassandra/protocol/responses/supported_response.rb +1 -1
  84. data/lib/cassandra/protocol/responses/topology_change_event_response.rb +1 -1
  85. data/lib/cassandra/protocol/responses/unavailable_error_response.rb +1 -1
  86. data/lib/cassandra/protocol/responses/unprepared_error_response.rb +1 -1
  87. data/lib/cassandra/protocol/responses/void_result_response.rb +1 -1
  88. data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +1 -1
  89. data/lib/cassandra/protocol/v1.rb +4 -2
  90. data/lib/cassandra/protocol/v3.rb +280 -0
  91. data/lib/cassandra/reconnection.rb +1 -1
  92. data/lib/cassandra/reconnection/policies.rb +1 -1
  93. data/lib/cassandra/reconnection/policies/constant.rb +1 -1
  94. data/lib/cassandra/reconnection/policies/exponential.rb +1 -1
  95. data/lib/cassandra/result.rb +1 -1
  96. data/lib/cassandra/retry.rb +1 -1
  97. data/lib/cassandra/retry/policies.rb +1 -1
  98. data/lib/cassandra/retry/policies/default.rb +1 -1
  99. data/lib/cassandra/retry/policies/downgrading_consistency.rb +1 -1
  100. data/lib/cassandra/retry/policies/fallthrough.rb +1 -1
  101. data/lib/cassandra/session.rb +14 -80
  102. data/lib/cassandra/statement.rb +1 -1
  103. data/lib/cassandra/statements.rb +1 -1
  104. data/lib/cassandra/statements/batch.rb +10 -25
  105. data/lib/cassandra/statements/bound.rb +1 -1
  106. data/lib/cassandra/statements/prepared.rb +24 -31
  107. data/lib/cassandra/statements/simple.rb +22 -66
  108. data/lib/cassandra/statements/void.rb +1 -1
  109. data/lib/cassandra/table.rb +36 -5
  110. data/lib/cassandra/time_uuid.rb +1 -1
  111. data/lib/cassandra/tuple.rb +124 -0
  112. data/lib/cassandra/types.rb +1406 -0
  113. data/lib/cassandra/udt.rb +420 -0
  114. data/lib/cassandra/util.rb +42 -64
  115. data/lib/cassandra/uuid.rb +1 -1
  116. data/lib/cassandra/uuid/generator.rb +1 -1
  117. data/lib/cassandra/version.rb +2 -2
  118. 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
@@ -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?