cql-rb 1.0.0.pre6 → 1.0.0.pre7

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 (34) hide show
  1. data/bin/cqlexec +2 -2
  2. data/lib/cql/protocol.rb +26 -1
  3. data/lib/cql/protocol/decoding.rb +3 -0
  4. data/lib/cql/protocol/request_body.rb +15 -0
  5. data/lib/cql/protocol/request_frame.rb +1 -266
  6. data/lib/cql/protocol/requests/credentials_request.rb +31 -0
  7. data/lib/cql/protocol/requests/execute_request.rb +129 -0
  8. data/lib/cql/protocol/requests/options_request.rb +19 -0
  9. data/lib/cql/protocol/requests/prepare_request.rb +31 -0
  10. data/lib/cql/protocol/requests/query_request.rb +33 -0
  11. data/lib/cql/protocol/requests/register_request.rb +20 -0
  12. data/lib/cql/protocol/requests/startup_request.rb +27 -0
  13. data/lib/cql/protocol/response_body.rb +13 -0
  14. data/lib/cql/protocol/response_frame.rb +1 -533
  15. data/lib/cql/protocol/responses/authenticate_response.rb +21 -0
  16. data/lib/cql/protocol/responses/detailed_error_response.rb +44 -0
  17. data/lib/cql/protocol/responses/error_response.rb +28 -0
  18. data/lib/cql/protocol/responses/event_response.rb +21 -0
  19. data/lib/cql/protocol/responses/prepared_result_response.rb +23 -0
  20. data/lib/cql/protocol/responses/ready_response.rb +24 -0
  21. data/lib/cql/protocol/responses/result_response.rb +29 -0
  22. data/lib/cql/protocol/responses/rows_result_response.rb +100 -0
  23. data/lib/cql/protocol/responses/schema_change_event_result_response.rb +40 -0
  24. data/lib/cql/protocol/responses/schema_change_result_response.rb +21 -0
  25. data/lib/cql/protocol/responses/set_keyspace_result_response.rb +21 -0
  26. data/lib/cql/protocol/responses/status_change_event_result_response.rb +24 -0
  27. data/lib/cql/protocol/responses/supported_response.rb +21 -0
  28. data/lib/cql/protocol/responses/topology_change_event_result_response.rb +14 -0
  29. data/lib/cql/protocol/responses/void_result_response.rb +19 -0
  30. data/lib/cql/protocol/type_converter.rb +165 -0
  31. data/lib/cql/version.rb +1 -1
  32. data/spec/cql/protocol/response_frame_spec.rb +31 -0
  33. data/spec/integration/regression_spec.rb +56 -9
  34. metadata +27 -2
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ module Cql
4
+ module Protocol
5
+ class OptionsRequest < RequestBody
6
+ def initialize
7
+ super(5)
8
+ end
9
+
10
+ def write(io)
11
+ io
12
+ end
13
+
14
+ def to_s
15
+ %(OPTIONS)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ module Cql
4
+ module Protocol
5
+ class PrepareRequest < RequestBody
6
+ attr_reader :cql
7
+
8
+ def initialize(cql)
9
+ super(9)
10
+ @cql = cql
11
+ end
12
+
13
+ def write(io)
14
+ write_long_string(io, @cql)
15
+ end
16
+
17
+ def to_s
18
+ %(PREPARE "#@cql")
19
+ end
20
+
21
+ def eql?(rq)
22
+ self.class === rq && rq.cql == self.cql
23
+ end
24
+ alias_method :==, :eql?
25
+
26
+ def hash
27
+ @h ||= @cql.hash
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ module Cql
4
+ module Protocol
5
+ class QueryRequest < RequestBody
6
+ attr_reader :cql, :consistency
7
+
8
+ def initialize(cql, consistency)
9
+ super(7)
10
+ @cql = cql
11
+ @consistency = consistency
12
+ end
13
+
14
+ def write(io)
15
+ write_long_string(io, @cql)
16
+ write_consistency(io, @consistency)
17
+ end
18
+
19
+ def to_s
20
+ %(QUERY "#@cql" #{@consistency.to_s.upcase})
21
+ end
22
+
23
+ def eql?(rq)
24
+ self.class === rq && rq.cql.eql?(self.cql) && rq.consistency.eql?(self.consistency)
25
+ end
26
+ alias_method :==, :eql?
27
+
28
+ def hash
29
+ @h ||= (@cql.hash * 31) ^ consistency.hash
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ module Cql
4
+ module Protocol
5
+ class RegisterRequest < RequestBody
6
+ def initialize(*events)
7
+ super(11)
8
+ @events = events
9
+ end
10
+
11
+ def write(io)
12
+ write_string_list(io, @events)
13
+ end
14
+
15
+ def to_s
16
+ %(REGISTER #@events)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+
3
+ module Cql
4
+ module Protocol
5
+ class StartupRequest < RequestBody
6
+ def initialize(cql_version='3.0.0', compression=nil)
7
+ super(1)
8
+ @arguments = {CQL_VERSION => cql_version}
9
+ @arguments[COMPRESSION] = compression if compression
10
+ end
11
+
12
+ def write(io)
13
+ write_string_map(io, @arguments)
14
+ io
15
+ end
16
+
17
+ def to_s
18
+ %(STARTUP #@arguments)
19
+ end
20
+
21
+ private
22
+
23
+ CQL_VERSION = 'CQL_VERSION'.freeze
24
+ COMPRESSION = 'COMPRESSION'.freeze
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ module Cql
5
+ module Protocol
6
+ class ResponseBody
7
+ extend Decoding
8
+
9
+ def self.decode!(buffer)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,10 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'ipaddr'
4
- require 'bigdecimal'
5
- require 'set'
6
-
7
-
8
3
  module Cql
9
4
  module Protocol
10
5
  class ResponseFrame
@@ -130,532 +125,5 @@ module Cql
130
125
  end
131
126
  end
132
127
  end
133
-
134
- class ResponseBody
135
- extend Decoding
136
-
137
- def self.decode!(buffer)
138
- end
139
- end
140
-
141
- class ErrorResponse < ResponseBody
142
- attr_reader :code, :message
143
-
144
- def initialize(*args)
145
- @code, @message = args
146
- end
147
-
148
- def self.decode!(buffer)
149
- code = read_int!(buffer)
150
- message = read_string!(buffer)
151
- case code
152
- when 0x1000, 0x1100, 0x1200, 0x2400, 0x2500
153
- DetailedErrorResponse.decode!(code, message, buffer)
154
- else
155
- new(code, message)
156
- end
157
- end
158
-
159
- def to_s
160
- %(ERROR #@code "#@message")
161
- end
162
- end
163
-
164
- class DetailedErrorResponse < ErrorResponse
165
- attr_reader :details
166
-
167
- def initialize(code, message, details)
168
- super(code, message)
169
- @details = details
170
- end
171
-
172
- def self.decode!(code, message, buffer)
173
- details = {}
174
- case code
175
- when 0x1000 # unavailable
176
- details[:cl] = read_consistency!(buffer)
177
- details[:required] = read_int!(buffer)
178
- details[:alive] = read_int!(buffer)
179
- when 0x1100 # write_timeout
180
- details[:cl] = read_consistency!(buffer)
181
- details[:received] = read_int!(buffer)
182
- details[:blockfor] = read_int!(buffer)
183
- details[:write_type] = read_string!(buffer)
184
- when 0x1200 # read_timeout
185
- details[:cl] = read_consistency!(buffer)
186
- details[:received] = read_int!(buffer)
187
- details[:blockfor] = read_int!(buffer)
188
- details[:data_present] = read_byte!(buffer) != 0
189
- when 0x2400 # already_exists
190
- details[:ks] = read_string!(buffer)
191
- details[:table] = read_string!(buffer)
192
- when 0x2500
193
- details[:id] = read_short_bytes!(buffer)
194
- end
195
- new(code, message, details)
196
- end
197
-
198
- def to_s
199
- %(ERROR #@code "#@message" #@details)
200
- end
201
- end
202
-
203
- class ReadyResponse < ResponseBody
204
- def self.decode!(buffer)
205
- new
206
- end
207
-
208
- def eql?(rs)
209
- self.class === rs
210
- end
211
- alias_method :==, :eql?
212
-
213
- def hash
214
- @h ||= to_s.hash ^ 0xbadc0de
215
- end
216
-
217
- def to_s
218
- 'READY'
219
- end
220
- end
221
-
222
- class AuthenticateResponse < ResponseBody
223
- attr_reader :authentication_class
224
-
225
- def self.decode!(buffer)
226
- new(read_string!(buffer))
227
- end
228
-
229
- def initialize(authentication_class)
230
- @authentication_class = authentication_class
231
- end
232
-
233
- def to_s
234
- %(AUTHENTICATE #{authentication_class})
235
- end
236
- end
237
-
238
- class SupportedResponse < ResponseBody
239
- attr_reader :options
240
-
241
- def initialize(options)
242
- @options = options
243
- end
244
-
245
- def self.decode!(buffer)
246
- new(read_string_multimap!(buffer))
247
- end
248
-
249
- def to_s
250
- %(SUPPORTED #{options})
251
- end
252
- end
253
-
254
- class ResultResponse < ResponseBody
255
- def self.decode!(buffer)
256
- kind = read_int!(buffer)
257
- case kind
258
- when 0x01
259
- VoidResultResponse.decode!(buffer)
260
- when 0x02
261
- RowsResultResponse.decode!(buffer)
262
- when 0x03
263
- SetKeyspaceResultResponse.decode!(buffer)
264
- when 0x04
265
- PreparedResultResponse.decode!(buffer)
266
- when 0x05
267
- SchemaChangeResultResponse.decode!(buffer)
268
- else
269
- raise UnsupportedResultKindError, %(Unsupported result kind: #{kind})
270
- end
271
- end
272
-
273
- def void?
274
- false
275
- end
276
- end
277
-
278
- class VoidResultResponse < ResultResponse
279
- def self.decode!(buffer)
280
- new
281
- end
282
-
283
- def to_s
284
- %(RESULT VOID)
285
- end
286
-
287
- def void?
288
- true
289
- end
290
- end
291
-
292
- class RowsResultResponse < ResultResponse
293
- attr_reader :rows, :metadata
294
-
295
- def initialize(*args)
296
- @rows, @metadata = args
297
- end
298
-
299
- def self.decode!(buffer)
300
- column_specs = read_metadata!(buffer)
301
- new(read_rows!(buffer, column_specs), column_specs)
302
- end
303
-
304
- def to_s
305
- %(RESULT ROWS #@metadata #@rows)
306
- end
307
-
308
- private
309
-
310
- COLUMN_TYPES = [
311
- nil,
312
- :ascii,
313
- :bigint,
314
- :blob,
315
- :boolean,
316
- :counter,
317
- :decimal,
318
- :double,
319
- :float,
320
- :int,
321
- :text,
322
- :timestamp,
323
- :uuid,
324
- :varchar,
325
- :varint,
326
- :timeuuid,
327
- :inet,
328
- ].freeze
329
-
330
- def self.read_column_type!(buffer)
331
- id, type = read_option!(buffer) do |id, b|
332
- if id > 0 && id <= 0x10
333
- COLUMN_TYPES[id]
334
- elsif id == 0x20
335
- sub_type = read_column_type!(buffer)
336
- [:list, sub_type]
337
- elsif id == 0x21
338
- key_type = read_column_type!(buffer)
339
- value_type = read_column_type!(buffer)
340
- [:map, key_type, value_type]
341
- elsif id == 0x22
342
- sub_type = read_column_type!(buffer)
343
- [:set, sub_type]
344
- else
345
- raise UnsupportedColumnTypeError, %(Unsupported column type: #{id})
346
- end
347
- end
348
- type
349
- end
350
-
351
- def self.read_metadata!(buffer)
352
- flags = read_int!(buffer)
353
- columns_count = read_int!(buffer)
354
- if flags & 0x01 == 0x01
355
- global_keyspace_name = read_string!(buffer)
356
- global_table_name = read_string!(buffer)
357
- end
358
- column_specs = columns_count.times.map do
359
- if global_keyspace_name
360
- keyspace_name = global_keyspace_name
361
- table_name = global_table_name
362
- else
363
- keyspace_name = read_string!(buffer)
364
- table_name = read_string!(buffer)
365
- end
366
- column_name = read_string!(buffer)
367
- type = read_column_type!(buffer)
368
- [keyspace_name, table_name, column_name, type]
369
- end
370
- end
371
-
372
- class TypeConverter
373
- include Decoding
374
-
375
- def initialize
376
- @conversions = conversions
377
- end
378
-
379
- def convert_type(buffer, type, size_bytes=4)
380
- return nil if buffer.empty?
381
- case type
382
- when Array
383
- buffer.discard(size_bytes)
384
- case type.first
385
- when :list
386
- convert_list(buffer, @conversions[type[1]])
387
- when :map
388
- convert_map(buffer, @conversions[type[1]], @conversions[type[2]])
389
- when :set
390
- convert_set(buffer, @conversions[type[1]])
391
- end
392
- else
393
- @conversions[type].call(buffer, size_bytes)
394
- end
395
- end
396
-
397
- def conversions
398
- {
399
- :ascii => method(:convert_ascii),
400
- :bigint => method(:convert_bigint),
401
- :blob => method(:convert_blob),
402
- :boolean => method(:convert_boolean),
403
- :counter => method(:convert_bigint),
404
- :decimal => method(:convert_decimal),
405
- :double => method(:convert_double),
406
- :float => method(:convert_float),
407
- :int => method(:convert_int),
408
- :timestamp => method(:convert_timestamp),
409
- :varchar => method(:convert_varchar),
410
- :text => method(:convert_varchar),
411
- :varint => method(:convert_varint),
412
- :timeuuid => method(:convert_uuid),
413
- :uuid => method(:convert_uuid),
414
- :inet => method(:convert_inet),
415
- }
416
- end
417
-
418
- def convert_ascii(buffer, size_bytes)
419
- bytes = size_bytes == 4 ? read_bytes!(buffer) : read_short_bytes!(buffer)
420
- bytes ? bytes.force_encoding(::Encoding::ASCII) : nil
421
- end
422
-
423
- def convert_bigint(buffer, size_bytes)
424
- buffer.discard(size_bytes)
425
- read_long!(buffer)
426
- end
427
-
428
- def convert_blob(buffer, size_bytes)
429
- bytes = size_bytes == 4 ? read_bytes!(buffer) : read_short_bytes!(buffer)
430
- bytes ? bytes : nil
431
- end
432
-
433
- def convert_boolean(buffer, size_bytes)
434
- buffer.discard(size_bytes)
435
- buffer.read(1) == Constants::TRUE_BYTE
436
- end
437
-
438
- def convert_counter(buffer, size_bytes)
439
- buffer.discard(size_bytes)
440
- read_long!(buffer)
441
- end
442
-
443
- def convert_decimal(buffer, size_bytes)
444
- read_decimal!(buffer, buffer.read_int)
445
- end
446
-
447
- def convert_double(buffer, size_bytes)
448
- buffer.discard(size_bytes)
449
- read_double!(buffer)
450
- end
451
-
452
- def convert_float(buffer, size_bytes)
453
- buffer.discard(size_bytes)
454
- read_float!(buffer)
455
- end
456
-
457
- def convert_int(buffer, size_bytes)
458
- buffer.discard(size_bytes)
459
- read_int!(buffer)
460
- end
461
-
462
- def convert_timestamp(buffer, size_bytes)
463
- buffer.discard(size_bytes)
464
- timestamp = read_long!(buffer)
465
- Time.at(timestamp/1000.0)
466
- end
467
-
468
- def convert_varchar(buffer, size_bytes)
469
- bytes = size_bytes == 4 ? read_bytes!(buffer) : read_short_bytes!(buffer)
470
- bytes ? bytes.force_encoding(::Encoding::UTF_8) : nil
471
- end
472
-
473
- def convert_varint(buffer, size_bytes)
474
- read_varint!(buffer, buffer.read_int)
475
- end
476
-
477
- def convert_uuid(buffer, size_bytes)
478
- buffer.discard(size_bytes)
479
- read_uuid!(buffer)
480
- end
481
-
482
- def convert_inet(buffer, size_bytes)
483
- size = size_bytes == 4 ? buffer.read_int : buffer.read_short
484
- IPAddr.new_ntoh(buffer.read(size))
485
- end
486
-
487
- def convert_list(buffer, value_converter)
488
- list = []
489
- size = buffer.read_short
490
- size.times do
491
- list << value_converter.call(buffer, 2)
492
- end
493
- list
494
- end
495
-
496
- def convert_map(buffer, key_converter, value_converter)
497
- map = {}
498
- size = buffer.read_short
499
- size.times do
500
- key = key_converter.call(buffer, 2)
501
- value = value_converter.call(buffer, 2)
502
- map[key] = value
503
- end
504
- map
505
- end
506
-
507
- def convert_set(buffer, value_converter)
508
- set = Set.new
509
- size = buffer.read_short
510
- size.times do
511
- set << value_converter.call(buffer, 2)
512
- end
513
- set
514
- end
515
- end
516
-
517
- def self.read_rows!(buffer, column_specs)
518
- type_converter = TypeConverter.new
519
- rows_count = read_int!(buffer)
520
- rows = []
521
- rows_count.times do |row_index|
522
- row = {}
523
- column_specs.each do |column_spec|
524
- row[column_spec[2]] = type_converter.convert_type(buffer, column_spec[3])
525
- end
526
- rows << row
527
- end
528
- rows
529
- end
530
- end
531
-
532
- class SetKeyspaceResultResponse < ResultResponse
533
- attr_reader :keyspace
534
-
535
- def initialize(keyspace)
536
- @keyspace = keyspace
537
- end
538
-
539
- def self.decode!(buffer)
540
- new(read_string!(buffer))
541
- end
542
-
543
- def to_s
544
- %(RESULT SET_KEYSPACE "#@keyspace")
545
- end
546
- end
547
-
548
- class PreparedResultResponse < ResultResponse
549
- attr_reader :id, :metadata
550
-
551
- def initialize(*args)
552
- @id, @metadata = args
553
- end
554
-
555
- def self.decode!(buffer)
556
- id = read_short_bytes!(buffer)
557
- metadata = RowsResultResponse.read_metadata!(buffer)
558
- new(id, metadata)
559
- end
560
-
561
- def to_s
562
- %(RESULT PREPARED #{id.each_byte.map { |x| x.to_s(16) }.join('')} #@metadata)
563
- end
564
- end
565
-
566
- class SchemaChangeResultResponse < ResultResponse
567
- attr_reader :change, :keyspace, :table
568
-
569
- def initialize(*args)
570
- @change, @keyspace, @table = args
571
- end
572
-
573
- def self.decode!(buffer)
574
- new(read_string!(buffer), read_string!(buffer), read_string!(buffer))
575
- end
576
-
577
- def to_s
578
- %(RESULT SCHEMA_CHANGE #@change "#@keyspace" "#@table")
579
- end
580
- end
581
-
582
- class EventResponse < ResultResponse
583
- def self.decode!(buffer)
584
- type = read_string!(buffer)
585
- case type
586
- when SchemaChangeEventResponse::TYPE
587
- SchemaChangeEventResponse.decode!(buffer)
588
- when StatusChangeEventResponse::TYPE
589
- StatusChangeEventResponse.decode!(buffer)
590
- when TopologyChangeEventResponse::TYPE
591
- TopologyChangeEventResponse.decode!(buffer)
592
- else
593
- raise UnsupportedEventTypeError, %(Unsupported event type: "#{type}")
594
- end
595
- end
596
- end
597
-
598
- class SchemaChangeEventResponse < EventResponse
599
- TYPE = 'SCHEMA_CHANGE'.freeze
600
-
601
- attr_reader :type, :change, :keyspace, :table
602
-
603
- def initialize(*args)
604
- @change, @keyspace, @table = args
605
- @type = TYPE
606
- end
607
-
608
- def self.decode!(buffer)
609
- new(read_string!(buffer), read_string!(buffer), read_string!(buffer))
610
- end
611
-
612
- def eql?(rs)
613
- rs.type == self.type && rs.change == self.change && rs.keyspace == self.keyspace && rs.table == self.table
614
- end
615
- alias_method :==, :eql?
616
-
617
- def hash
618
- @h ||= begin
619
- h = 0
620
- h = ((h & 33554431) * 31) ^ @type.hash
621
- h = ((h & 33554431) * 31) ^ @change.hash
622
- h = ((h & 33554431) * 31) ^ @keyspace.hash
623
- h = ((h & 33554431) * 31) ^ @table.hash
624
- h
625
- end
626
- end
627
-
628
- def to_s
629
- %(EVENT #@type #@change "#@keyspace" "#@table")
630
- end
631
- end
632
-
633
- class StatusChangeEventResponse < EventResponse
634
- TYPE = 'STATUS_CHANGE'.freeze
635
-
636
- attr_reader :type, :change, :address, :port
637
-
638
- def initialize(*args)
639
- @change, @address, @port = args
640
- @type = TYPE
641
- end
642
-
643
- def self.decode!(buffer)
644
- new(read_string!(buffer), *read_inet!(buffer))
645
- end
646
-
647
- def to_s
648
- %(EVENT #@type #@change #@address:#@port)
649
- end
650
- end
651
-
652
- class TopologyChangeEventResponse < StatusChangeEventResponse
653
- TYPE = 'TOPOLOGY_CHANGE'.freeze
654
-
655
- def initialize(*args)
656
- super
657
- @type = TYPE
658
- end
659
- end
660
128
  end
661
- end
129
+ end