cql-rb 1.0.0.pre6 → 1.0.0.pre7

Sign up to get free protection for your applications and to get access to all the features.
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 VoidResultResponse < ResultResponse
6
+ def self.decode!(buffer)
7
+ new
8
+ end
9
+
10
+ def to_s
11
+ %(RESULT VOID)
12
+ end
13
+
14
+ def void?
15
+ true
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,165 @@
1
+ # encoding: utf-8
2
+
3
+ require 'ipaddr'
4
+ require 'set'
5
+
6
+
7
+ module Cql
8
+ module Protocol
9
+ class TypeConverter
10
+ include Decoding
11
+
12
+ def initialize
13
+ @conversions = conversions
14
+ end
15
+
16
+ def convert_type(buffer, type, size_bytes=4)
17
+ return nil if buffer.empty?
18
+ case type
19
+ when Array
20
+ return nil unless read_size(buffer, size_bytes)
21
+ case type.first
22
+ when :list
23
+ convert_list(buffer, @conversions[type[1]])
24
+ when :map
25
+ convert_map(buffer, @conversions[type[1]], @conversions[type[2]])
26
+ when :set
27
+ convert_set(buffer, @conversions[type[1]])
28
+ end
29
+ else
30
+ @conversions[type].call(buffer, size_bytes)
31
+ end
32
+ end
33
+
34
+ def conversions
35
+ {
36
+ :ascii => method(:convert_ascii),
37
+ :bigint => method(:convert_bigint),
38
+ :blob => method(:convert_blob),
39
+ :boolean => method(:convert_boolean),
40
+ :counter => method(:convert_bigint),
41
+ :decimal => method(:convert_decimal),
42
+ :double => method(:convert_double),
43
+ :float => method(:convert_float),
44
+ :int => method(:convert_int),
45
+ :timestamp => method(:convert_timestamp),
46
+ :varchar => method(:convert_varchar),
47
+ :text => method(:convert_varchar),
48
+ :varint => method(:convert_varint),
49
+ :timeuuid => method(:convert_uuid),
50
+ :uuid => method(:convert_uuid),
51
+ :inet => method(:convert_inet),
52
+ }
53
+ end
54
+
55
+ def convert_ascii(buffer, size_bytes)
56
+ bytes = size_bytes == 4 ? read_bytes!(buffer) : read_short_bytes!(buffer)
57
+ bytes ? bytes.force_encoding(::Encoding::ASCII) : nil
58
+ end
59
+
60
+ def convert_bigint(buffer, size_bytes)
61
+ return nil unless read_size(buffer, size_bytes)
62
+ read_long!(buffer)
63
+ end
64
+
65
+ def convert_blob(buffer, size_bytes)
66
+ bytes = size_bytes == 4 ? read_bytes!(buffer) : read_short_bytes!(buffer)
67
+ bytes ? bytes : nil
68
+ end
69
+
70
+ def convert_boolean(buffer, size_bytes)
71
+ return nil unless read_size(buffer, size_bytes)
72
+ buffer.read(1) == Constants::TRUE_BYTE
73
+ end
74
+
75
+ def convert_decimal(buffer, size_bytes)
76
+ size = read_size(buffer, size_bytes)
77
+ return nil unless size
78
+ read_decimal!(buffer, size)
79
+ end
80
+
81
+ def convert_double(buffer, size_bytes)
82
+ return nil unless read_size(buffer, size_bytes)
83
+ read_double!(buffer)
84
+ end
85
+
86
+ def convert_float(buffer, size_bytes)
87
+ return nil unless read_size(buffer, size_bytes)
88
+ read_float!(buffer)
89
+ end
90
+
91
+ def convert_int(buffer, size_bytes)
92
+ return nil unless read_size(buffer, size_bytes)
93
+ read_int!(buffer)
94
+ end
95
+
96
+ def convert_timestamp(buffer, size_bytes)
97
+ return nil unless read_size(buffer, size_bytes)
98
+ timestamp = read_long!(buffer)
99
+ Time.at(timestamp/1000.0)
100
+ end
101
+
102
+ def convert_varchar(buffer, size_bytes)
103
+ bytes = size_bytes == 4 ? read_bytes!(buffer) : read_short_bytes!(buffer)
104
+ bytes ? bytes.force_encoding(::Encoding::UTF_8) : nil
105
+ end
106
+
107
+ def convert_varint(buffer, size_bytes)
108
+ size = read_size(buffer, size_bytes)
109
+ return nil unless size
110
+ read_varint!(buffer, size)
111
+ end
112
+
113
+ def convert_uuid(buffer, size_bytes)
114
+ return nil unless read_size(buffer, size_bytes)
115
+ read_uuid!(buffer)
116
+ end
117
+
118
+ def convert_inet(buffer, size_bytes)
119
+ size = read_size(buffer, size_bytes)
120
+ return nil unless size
121
+ IPAddr.new_ntoh(buffer.read(size))
122
+ end
123
+
124
+ def convert_list(buffer, value_converter)
125
+ list = []
126
+ size = buffer.read_short
127
+ size.times do
128
+ list << value_converter.call(buffer, 2)
129
+ end
130
+ list
131
+ end
132
+
133
+ def convert_map(buffer, key_converter, value_converter)
134
+ map = {}
135
+ size = buffer.read_short
136
+ size.times do
137
+ key = key_converter.call(buffer, 2)
138
+ value = value_converter.call(buffer, 2)
139
+ map[key] = value
140
+ end
141
+ map
142
+ end
143
+
144
+ def convert_set(buffer, value_converter)
145
+ set = Set.new
146
+ size = buffer.read_short
147
+ size.times do
148
+ set << value_converter.call(buffer, 2)
149
+ end
150
+ set
151
+ end
152
+
153
+ def read_size(buffer, size_bytes)
154
+ if size_bytes == 2
155
+ size = buffer.read_short
156
+ return nil if size & 0x8000 == 0x8000
157
+ else
158
+ size = buffer.read_int
159
+ return nil if size & 0x80000000 == 0x80000000
160
+ end
161
+ size
162
+ end
163
+ end
164
+ end
165
+ end
data/lib/cql/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Cql
4
- VERSION = '1.0.0.pre6'.freeze
4
+ VERSION = '1.0.0.pre7'.freeze
5
5
  end
@@ -540,11 +540,42 @@ module Cql
540
540
  frame.body.rows.first['set_column'].should == Set.new(["\xab\x43\x21", "\xaf\xd8\x7e\xcd"].map { |s| s.force_encoding(::Encoding::BINARY) })
541
541
  end
542
542
 
543
+ it 'decodes nulls' do
544
+ frame = described_class.new(ByteBuffer.new("\x81\x00\x00\b\x00\x00\x01\xB6\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x13\x00\x12cql_rb_client_spec\x00\rlots_of_types\x00\x02id\x00\t\x00\fascii_column\x00\x01\x00\rbigint_column\x00\x02\x00\vblob_column\x00\x03\x00\x0Eboolean_column\x00\x04\x00\x0Edecimal_column\x00\x06\x00\rdouble_column\x00\a\x00\ffloat_column\x00\b\x00\vinet_column\x00\x10\x00\nint_column\x00\t\x00\vlist_column\x00 \x00\x01\x00\nmap_column\x00!\x00\r\x00\x04\x00\nset_column\x00\"\x00\x03\x00\vtext_column\x00\r\x00\x10timestamp_column\x00\v\x00\x0Ftimeuuid_column\x00\x0F\x00\vuuid_column\x00\f\x00\x0Evarchar_column\x00\r\x00\rvarint_column\x00\x0E\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x03\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"))
545
+ row = frame.body.rows.first
546
+ row.should eql(
547
+ 'id' => 3,
548
+ 'ascii_column' => nil,
549
+ 'bigint_column' => nil,
550
+ 'blob_column' => nil,
551
+ 'boolean_column' => nil,
552
+ 'decimal_column' => nil,
553
+ 'double_column' => nil,
554
+ 'float_column' => nil,
555
+ 'int_column' => nil,
556
+ 'text_column' => nil,
557
+ 'timestamp_column' => nil,
558
+ 'uuid_column' => nil,
559
+ 'varchar_column' => nil,
560
+ 'varint_column' => nil,
561
+ 'timeuuid_column' => nil,
562
+ 'inet_column' => nil,
563
+ 'list_column' => nil,
564
+ 'map_column' => nil,
565
+ 'set_column' => nil,
566
+ )
567
+ end
568
+
543
569
  it 'decodes COUNTER as a number' do
544
570
  frame = described_class.new(ByteBuffer.new("\x81\x00\x00\b\x00\x00\x00N\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\x00\x04test\x00\x04cnts\x00\x02id\x00\r\x00\x02c1\x00\x05\x00\x02c2\x00\x05\x00\x00\x00\x01\x00\x00\x00\x04theo\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x01"))
545
571
  frame.body.rows.first['c1'].should == 3
546
572
  end
547
573
 
574
+ it 'decodes a null COUNTER as nil' do
575
+ frame = described_class.new(ByteBuffer.new("\x81\x00\x00\b\x00\x00\x00V\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\x00\x12cql_rb_client_spec\x00\bcounters\x00\bcounter1\x00\x05\x00\bcounter2\x00\x05\x00\x00\x00\x01\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x01\xFF\xFF\xFF\xFF"))
576
+ frame.body.rows.first['counter2'].should be_nil
577
+ end
578
+
548
579
  it 'raises an error when encountering an unknown column type' do
549
580
  frame = described_class.new
550
581
  frame << "\x81\x00\x00\b\x00\x00\x00E"
@@ -20,7 +20,7 @@ describe 'Regressions' do
20
20
  end
21
21
 
22
22
  after do
23
- client.execute('DROP KEYSPACE cql_rb_client_spec')
23
+ client.execute('DROP KEYSPACE cql_rb_client_spec') rescue nil
24
24
  client.close
25
25
  end
26
26
 
@@ -63,18 +63,65 @@ describe 'Regressions' do
63
63
  end
64
64
  end
65
65
 
66
- context 'wat' do
67
- it 'finds all things' do
68
- client.execute('CREATE TABLE t_b (a BIGINT, b BOOLEAN, c SET<BIGINT>, PRIMARY KEY (a, b))')
69
- client.execute('INSERT INTO t_b (a, b, c) VALUES (271, false, {429512359, 22140083129, 154124373, 7133790052, 3263802876, 7306375341, 1086106894, 18819871958, 2754233688, 11353254728, 9045041985, 17997058330, 12443485304, 8549364896, 731630293, 21159857519, 1111535777, 3180792037, 9563930655, 7144898604, 12770338502, 22740775138, 18618244615, 22214143018, 6934152431, 18762976055, 17285647286, 20125813811, 9133629150, 15424700007, 118980476, 14741258930, 18779991792, 8324600546, 11637140295, 9991399356, 19199483004, 21445636099, 16558957905, 15918629196, 18233976642, 11046492659, 6935319727, 10159850783, 4663807554, 7355805674, 7635043414, 21675092442, 13600103335, 22306919328, 9217523096, 12529064948, 8776455938, 2245602097, 15670128881, 18058001691, 21092222111, 17277710588, 14115070523, 9070732951, 2812255943, 9349962400, 3159466851, 16008470639, 19953811077, 21577742012, 22095236133, 14644601174, 8617764033, 16140330747, 6430474270, 8193684764, 18867977174, 19652105799, 17553107189, 18499057047, 15047410679, 14622689532, 116299629, 7516765793, 8115675759, 16051975041, 16430971219, 10443592529, 7029456978, 4636255483, 10311426631, 18607907259, 13049692716, 20594963153, 11747270720, 8552608868, 13807260864, 18374272405, 19847587719, 12573496801, 2860931462, 16578852692, 22804253685, 2720329280})')
70
- result = client.execute('SELECT * FROM t_b')
71
- raise unless result.first['c'] == Set.new([429512359, 22140083129, 154124373, 7133790052, 3263802876, 7306375341, 1086106894, 18819871958, 2754233688, 11353254728, 9045041985, 17997058330, 12443485304, 8549364896, 731630293, 21159857519, 1111535777, 3180792037, 9563930655, 7144898604, 12770338502, 22740775138, 18618244615, 22214143018, 6934152431, 18762976055, 17285647286, 20125813811, 9133629150, 15424700007, 118980476, 14741258930, 18779991792, 8324600546, 11637140295, 9991399356, 19199483004, 21445636099, 16558957905, 15918629196, 18233976642, 11046492659, 6935319727, 10159850783, 4663807554, 7355805674, 7635043414, 21675092442, 13600103335, 22306919328, 9217523096, 12529064948, 8776455938, 2245602097, 15670128881, 18058001691, 21092222111, 17277710588, 14115070523, 9070732951, 2812255943, 9349962400, 3159466851, 16008470639, 19953811077, 21577742012, 22095236133, 14644601174, 8617764033, 16140330747, 6430474270, 8193684764, 18867977174, 19652105799, 17553107189, 18499057047, 15047410679, 14622689532, 116299629, 7516765793, 8115675759, 16051975041, 16430971219, 10443592529, 7029456978, 4636255483, 10311426631, 18607907259, 13049692716, 20594963153, 11747270720, 8552608868, 13807260864, 18374272405, 19847587719, 12573496801, 2860931462, 16578852692, 22804253685, 2720329280])
66
+ context 'frame decoding' do
67
+ it 'decodes null counters' do
68
+ client.execute(%<CREATE TABLE counters (id ASCII, counter1 COUNTER, counter2 COUNTER, PRIMARY KEY (id))>)
69
+ client.execute(%<UPDATE counters SET counter1 = counter1 + 1 WHERE id = 'foo'>)
70
+ result = client.execute(%<SELECT counter1, counter2 FROM counters WHERE id = 'foo'>)
71
+ result.first['counter1'].should == 1
72
+ result.first['counter2'].should be_nil
72
73
  end
73
74
 
74
- it 'inet' do
75
- client.execute('select inet_column from test_types.lots_of_types')
75
+ it 'decodes null values' do
76
+ client.execute(<<-CQL)
77
+ CREATE TABLE lots_of_types (
78
+ id INT,
79
+ ascii_column ASCII,
80
+ bigint_column BIGINT,
81
+ blob_column BLOB,
82
+ boolean_column BOOLEAN,
83
+ decimal_column DECIMAL,
84
+ double_column DOUBLE,
85
+ float_column FLOAT,
86
+ int_column INT,
87
+ text_column TEXT,
88
+ timestamp_column TIMESTAMP,
89
+ uuid_column UUID,
90
+ varchar_column VARCHAR,
91
+ varint_column VARINT,
92
+ timeuuid_column TIMEUUID,
93
+ inet_column INET,
94
+ list_column LIST<ASCII>,
95
+ map_column MAP<TEXT, BOOLEAN>,
96
+ set_column SET<BLOB>,
97
+ PRIMARY KEY (id)
98
+ )
99
+ CQL
100
+ client.execute(%<INSERT INTO lots_of_types (id) VALUES (3)>)
101
+ result = client.execute(%<SELECT * FROM lots_of_types WHERE id = 3>)
102
+ row = result.first
103
+ row['ascii_column'].should be_nil
104
+ row['bigint_column'].should be_nil
105
+ row['blob_column'].should be_nil
106
+ row['boolean_column'].should be_nil
107
+ row['decimal_column'].should be_nil
108
+ row['double_column'].should be_nil
109
+ row['float_column'].should be_nil
110
+ row['int_column'].should be_nil
111
+ row['text_column'].should be_nil
112
+ row['timestamp_column'].should be_nil
113
+ row['uuid_column'].should be_nil
114
+ row['varchar_column'].should be_nil
115
+ row['varint_column'].should be_nil
116
+ row['timeuuid_column'].should be_nil
117
+ row['inet_column'].should be_nil
118
+ row['list_column'].should be_nil
119
+ row['map_column'].should be_nil
120
+ row['set_column'].should be_nil
76
121
  end
122
+ end
77
123
 
124
+ context 'wat' do
78
125
  it 'null values' do
79
126
  client.execute('CREATE TABLE null_value (a BIGINT, b BOOLEAN, c INT, PRIMARY KEY ((a, b), c))')
80
127
  client.execute('INSERT INTO null_value (a, b, c) VALUES (123123123123, true, 3234)')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cql-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre6
4
+ version: 1.0.0.pre7
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-13 00:00:00.000000000 Z
12
+ date: 2013-05-15 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A pure Ruby CQL3 driver for Cassandra
15
15
  email:
@@ -26,8 +26,33 @@ files:
26
26
  - lib/cql/io.rb
27
27
  - lib/cql/protocol/decoding.rb
28
28
  - lib/cql/protocol/encoding.rb
29
+ - lib/cql/protocol/request_body.rb
29
30
  - lib/cql/protocol/request_frame.rb
31
+ - lib/cql/protocol/requests/credentials_request.rb
32
+ - lib/cql/protocol/requests/execute_request.rb
33
+ - lib/cql/protocol/requests/options_request.rb
34
+ - lib/cql/protocol/requests/prepare_request.rb
35
+ - lib/cql/protocol/requests/query_request.rb
36
+ - lib/cql/protocol/requests/register_request.rb
37
+ - lib/cql/protocol/requests/startup_request.rb
38
+ - lib/cql/protocol/response_body.rb
30
39
  - lib/cql/protocol/response_frame.rb
40
+ - lib/cql/protocol/responses/authenticate_response.rb
41
+ - lib/cql/protocol/responses/detailed_error_response.rb
42
+ - lib/cql/protocol/responses/error_response.rb
43
+ - lib/cql/protocol/responses/event_response.rb
44
+ - lib/cql/protocol/responses/prepared_result_response.rb
45
+ - lib/cql/protocol/responses/ready_response.rb
46
+ - lib/cql/protocol/responses/result_response.rb
47
+ - lib/cql/protocol/responses/rows_result_response.rb
48
+ - lib/cql/protocol/responses/schema_change_event_result_response.rb
49
+ - lib/cql/protocol/responses/schema_change_result_response.rb
50
+ - lib/cql/protocol/responses/set_keyspace_result_response.rb
51
+ - lib/cql/protocol/responses/status_change_event_result_response.rb
52
+ - lib/cql/protocol/responses/supported_response.rb
53
+ - lib/cql/protocol/responses/topology_change_event_result_response.rb
54
+ - lib/cql/protocol/responses/void_result_response.rb
55
+ - lib/cql/protocol/type_converter.rb
31
56
  - lib/cql/protocol.rb
32
57
  - lib/cql/uuid.rb
33
58
  - lib/cql/version.rb