cql-rb 1.0.0.pre5 → 1.0.0.pre6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +61 -46
- data/lib/cql.rb +1 -0
- data/lib/cql/byte_buffer.rb +138 -0
- data/lib/cql/future.rb +3 -0
- data/lib/cql/io/node_connection.rb +29 -26
- data/lib/cql/protocol.rb +1 -1
- data/lib/cql/protocol/decoding.rb +41 -33
- data/lib/cql/protocol/encoding.rb +4 -15
- data/lib/cql/protocol/request_frame.rb +3 -3
- data/lib/cql/protocol/response_frame.rb +174 -81
- data/lib/cql/version.rb +1 -1
- data/spec/cql/byte_buffer_spec.rb +299 -0
- data/spec/cql/io/io_reactor_spec.rb +13 -16
- data/spec/cql/protocol/decoding_spec.rb +128 -91
- data/spec/cql/protocol/encoding_spec.rb +8 -57
- data/spec/cql/protocol/request_frame_spec.rb +10 -5
- data/spec/cql/protocol/response_frame_spec.rb +31 -15
- data/spec/integration/client_spec.rb +4 -0
- data/spec/integration/protocol_spec.rb +1 -1
- data/spec/integration/regression_spec.rb +41 -14
- data/spec/spec_helper.rb +13 -6
- data/spec/support/bytes_helper.rb +1 -1
- data/spec/support/fake_server.rb +10 -2
- metadata +5 -2
@@ -7,7 +7,7 @@ module Cql
|
|
7
7
|
module Protocol
|
8
8
|
describe Encoding do
|
9
9
|
let :buffer do
|
10
|
-
|
10
|
+
ByteBuffer.new
|
11
11
|
end
|
12
12
|
|
13
13
|
describe '#write_int' do
|
@@ -18,7 +18,6 @@ module Cql
|
|
18
18
|
|
19
19
|
it 'appends to the buffer' do
|
20
20
|
buffer << "\xab"
|
21
|
-
buffer.force_encoding(::Encoding::BINARY)
|
22
21
|
Encoding.write_int(buffer, 10)
|
23
22
|
buffer.should eql_bytes("\xab\x00\x00\x00\x0a")
|
24
23
|
end
|
@@ -37,7 +36,6 @@ module Cql
|
|
37
36
|
|
38
37
|
it 'appends to the buffer' do
|
39
38
|
buffer << "\xab"
|
40
|
-
buffer.force_encoding(::Encoding::BINARY)
|
41
39
|
Encoding.write_short(buffer, 10)
|
42
40
|
buffer.should eql_bytes("\xab\x00\x0a")
|
43
41
|
end
|
@@ -54,15 +52,8 @@ module Cql
|
|
54
52
|
buffer.should eql_bytes("\x00\x05hello")
|
55
53
|
end
|
56
54
|
|
57
|
-
it 'returns a binary string' do
|
58
|
-
str = 'I love π'
|
59
|
-
Encoding.write_string(buffer, str)
|
60
|
-
buffer.encoding.should == ::Encoding::BINARY
|
61
|
-
end
|
62
|
-
|
63
55
|
it 'encodes a string with multibyte characters' do
|
64
56
|
buffer << "\xff"
|
65
|
-
buffer.force_encoding(::Encoding::BINARY)
|
66
57
|
str = 'I love π'
|
67
58
|
Encoding.write_string(buffer, str)
|
68
59
|
buffer.should eql_bytes("\xff\x00\x09I love π")
|
@@ -80,7 +71,6 @@ module Cql
|
|
80
71
|
|
81
72
|
it 'appends to the buffer' do
|
82
73
|
buffer << "\xab"
|
83
|
-
buffer.force_encoding(::Encoding::BINARY)
|
84
74
|
Encoding.write_string(buffer, 'foo')
|
85
75
|
buffer.should eql_bytes("\xab\x00\x03foo")
|
86
76
|
end
|
@@ -94,18 +84,11 @@ module Cql
|
|
94
84
|
describe '#write_long_string' do
|
95
85
|
it 'encodes a string' do
|
96
86
|
Encoding.write_long_string(buffer, 'hello world ' * 100_000)
|
97
|
-
buffer
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'returns a binary string' do
|
101
|
-
str = 'I love π'
|
102
|
-
Encoding.write_long_string(buffer, str)
|
103
|
-
buffer.encoding.should == ::Encoding::BINARY
|
87
|
+
buffer.read(45).should eql_bytes("\x00\x12\x4f\x80hello world hello world hello world hello")
|
104
88
|
end
|
105
89
|
|
106
90
|
it 'encodes a string with multibyte characters' do
|
107
91
|
buffer << "\xff"
|
108
|
-
buffer.force_encoding(::Encoding::BINARY)
|
109
92
|
str = 'I love π'
|
110
93
|
Encoding.write_long_string(buffer, str)
|
111
94
|
buffer.should eql_bytes("\xff\x00\x00\x00\x09I love π")
|
@@ -118,7 +101,6 @@ module Cql
|
|
118
101
|
|
119
102
|
it 'appends to the buffer' do
|
120
103
|
buffer << "\xab"
|
121
|
-
buffer.force_encoding(::Encoding::BINARY)
|
122
104
|
Encoding.write_long_string(buffer, 'foo')
|
123
105
|
buffer.should eql_bytes("\xab\x00\x00\x00\x03foo")
|
124
106
|
end
|
@@ -141,9 +123,8 @@ module Cql
|
|
141
123
|
|
142
124
|
it 'appends to the buffer' do
|
143
125
|
buffer << 'FOO'
|
144
|
-
buffer.force_encoding(::Encoding::BINARY)
|
145
126
|
Encoding.write_uuid(buffer, uuid)
|
146
|
-
buffer.should
|
127
|
+
buffer.read(3).should eql_bytes('FOO')
|
147
128
|
end
|
148
129
|
|
149
130
|
it 'returns the buffer' do
|
@@ -158,15 +139,8 @@ module Cql
|
|
158
139
|
buffer.should eql_bytes("\x00\x04\x00\x03foo\x00\x03bar\x00\x05hello\x00\x05world")
|
159
140
|
end
|
160
141
|
|
161
|
-
it 'returns a binary string' do
|
162
|
-
str = %w[I love π]
|
163
|
-
Encoding.write_string_list(buffer, str)
|
164
|
-
buffer.encoding.should == ::Encoding::BINARY
|
165
|
-
end
|
166
|
-
|
167
142
|
it 'encodes a string with multibyte characters' do
|
168
143
|
buffer << "\xff"
|
169
|
-
buffer.force_encoding(::Encoding::BINARY)
|
170
144
|
str = %w[I love π]
|
171
145
|
Encoding.write_string_list(buffer, str)
|
172
146
|
buffer.should eql_bytes("\xff\x00\x03\x00\x01I\x00\x04love\x00\x02π")
|
@@ -174,12 +148,11 @@ module Cql
|
|
174
148
|
|
175
149
|
it 'encodes an empty string list' do
|
176
150
|
Encoding.write_string_list(buffer, [])
|
177
|
-
buffer.should
|
151
|
+
buffer.should eql_bytes("\x00\x00")
|
178
152
|
end
|
179
153
|
|
180
154
|
it 'appends to the buffer' do
|
181
155
|
buffer << "\xab"
|
182
|
-
buffer.force_encoding(::Encoding::BINARY)
|
183
156
|
Encoding.write_string_list(buffer, %w[foo bar])
|
184
157
|
buffer.should eql_bytes("\xab\x00\x02\x00\x03foo\x00\x03bar")
|
185
158
|
end
|
@@ -196,15 +169,8 @@ module Cql
|
|
196
169
|
buffer.should eql_bytes("\x00\x00\x07\xd0" << ("\xaa" * 2000))
|
197
170
|
end
|
198
171
|
|
199
|
-
it 'returns a binary string' do
|
200
|
-
str = 'I love π'
|
201
|
-
Encoding.write_bytes(buffer, str)
|
202
|
-
buffer.encoding.should == ::Encoding::BINARY
|
203
|
-
end
|
204
|
-
|
205
172
|
it 'encodes a string with multibyte characters' do
|
206
173
|
buffer << "\xff"
|
207
|
-
buffer.force_encoding(::Encoding::BINARY)
|
208
174
|
str = 'I love π'
|
209
175
|
Encoding.write_bytes(buffer, str)
|
210
176
|
buffer.should eql_bytes("\xff\x00\x00\x00\x09I love π")
|
@@ -217,7 +183,6 @@ module Cql
|
|
217
183
|
|
218
184
|
it 'appends to the buffer' do
|
219
185
|
buffer << "\xab"
|
220
|
-
buffer.force_encoding(::Encoding::BINARY)
|
221
186
|
Encoding.write_bytes(buffer, "\xf0\x0b\xbar")
|
222
187
|
buffer.should eql_bytes("\xab\x00\x00\x00\x04\xf0\x0b\xbar")
|
223
188
|
end
|
@@ -234,15 +199,8 @@ module Cql
|
|
234
199
|
buffer.should eql_bytes("\x00\x03\xaa\xbb\xcc")
|
235
200
|
end
|
236
201
|
|
237
|
-
it 'returns a binary string' do
|
238
|
-
str = 'I love π'
|
239
|
-
Encoding.write_short_bytes(buffer, str)
|
240
|
-
buffer.encoding.should == ::Encoding::BINARY
|
241
|
-
end
|
242
|
-
|
243
202
|
it 'encodes a string with multibyte characters' do
|
244
203
|
buffer << "\xff"
|
245
|
-
buffer.force_encoding(::Encoding::BINARY)
|
246
204
|
str = 'I love π'
|
247
205
|
Encoding.write_short_bytes(buffer, str)
|
248
206
|
buffer.should eql_bytes("\xff\x00\x09I love π")
|
@@ -255,7 +213,6 @@ module Cql
|
|
255
213
|
|
256
214
|
it 'appends to the buffer' do
|
257
215
|
buffer << "\xab"
|
258
|
-
buffer.force_encoding(::Encoding::BINARY)
|
259
216
|
Encoding.write_short_bytes(buffer, "\xf0\x0b\xbar")
|
260
217
|
buffer.should eql_bytes("\xab\x00\x04\xf0\x0b\xbar")
|
261
218
|
end
|
@@ -279,7 +236,7 @@ module Cql
|
|
279
236
|
}.each do |consistency, expected_encoding|
|
280
237
|
it "encodes #{consistency}" do
|
281
238
|
Encoding.write_consistency(buffer, consistency)
|
282
|
-
buffer.should
|
239
|
+
buffer.should eql_bytes(expected_encoding)
|
283
240
|
end
|
284
241
|
end
|
285
242
|
|
@@ -289,7 +246,6 @@ module Cql
|
|
289
246
|
|
290
247
|
it 'appends to the buffer' do
|
291
248
|
buffer << "\xab"
|
292
|
-
buffer.force_encoding(::Encoding::BINARY)
|
293
249
|
Encoding.write_consistency(buffer, :one)
|
294
250
|
buffer.should eql_bytes("\xab\x00\x01")
|
295
251
|
end
|
@@ -313,7 +269,6 @@ module Cql
|
|
313
269
|
|
314
270
|
it 'appends to the buffer' do
|
315
271
|
buffer << "\xab"
|
316
|
-
buffer.force_encoding(::Encoding::BINARY)
|
317
272
|
Encoding.write_string_map(buffer, 'foo' => 'bar')
|
318
273
|
buffer.should eql_bytes("\xab\x00\x01\x00\x03foo\x00\x03bar")
|
319
274
|
end
|
@@ -332,7 +287,6 @@ module Cql
|
|
332
287
|
|
333
288
|
it 'appends to the buffer' do
|
334
289
|
buffer << "\x99"
|
335
|
-
buffer.force_encoding(::Encoding::BINARY)
|
336
290
|
Encoding.write_long(buffer, 0x0123456789)
|
337
291
|
buffer.should eql_bytes("\x99\x00\x00\x00\x01\x23\x45\x67\x89")
|
338
292
|
end
|
@@ -356,7 +310,6 @@ module Cql
|
|
356
310
|
|
357
311
|
it 'appends to the buffer' do
|
358
312
|
buffer << "\x99"
|
359
|
-
buffer.force_encoding(::Encoding::BINARY)
|
360
313
|
Encoding.write_varint(buffer, -234234234234)
|
361
314
|
buffer.should eql_bytes("\x99\xC9v\x8D:\x86")
|
362
315
|
end
|
@@ -375,9 +328,8 @@ module Cql
|
|
375
328
|
|
376
329
|
it 'appends to the buffer' do
|
377
330
|
buffer << "\x99"
|
378
|
-
buffer.force_encoding(::Encoding::BINARY)
|
379
331
|
Encoding.write_decimal(buffer, BigDecimal.new('1042342234234.123423435647768234'))
|
380
|
-
buffer
|
332
|
+
buffer.read(1).should eql_bytes("\x99")
|
381
333
|
end
|
382
334
|
|
383
335
|
it 'returns the buffer' do
|
@@ -394,9 +346,8 @@ module Cql
|
|
394
346
|
|
395
347
|
it 'appends to the buffer' do
|
396
348
|
buffer << 'BEFORE'
|
397
|
-
buffer.force_encoding(::Encoding::BINARY)
|
398
349
|
Encoding.write_double(buffer, 10000.123123123)
|
399
|
-
buffer.should
|
350
|
+
buffer.read(6).should eql_bytes('BEFORE')
|
400
351
|
end
|
401
352
|
|
402
353
|
it 'returns the buffer' do
|
@@ -414,7 +365,7 @@ module Cql
|
|
414
365
|
it 'appends to the buffer' do
|
415
366
|
buffer << 'BEFORE'
|
416
367
|
Encoding.write_float(buffer, 12.13)
|
417
|
-
buffer.should
|
368
|
+
buffer.read(6).should eql_bytes('BEFORE')
|
418
369
|
end
|
419
370
|
|
420
371
|
it 'returns the buffer' do
|
@@ -52,6 +52,11 @@ module Cql
|
|
52
52
|
bytes = RequestFrame.new(QueryRequest.new('USE system', :all)).write('')
|
53
53
|
bytes.should == "\x01\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x0aUSE system\x00\x05"
|
54
54
|
end
|
55
|
+
|
56
|
+
it 'correctly encodes queries with multibyte characters' do
|
57
|
+
bytes = RequestFrame.new(QueryRequest.new("INSERT INTO users (user_id, first, last, age) VALUES ('test', 'ümlaut', 'test', 1)", :all)).write(ByteBuffer.new)
|
58
|
+
bytes.should eql_bytes("\x01\x00\x00\a\x00\x00\x00Y\x00\x00\x00SINSERT INTO users (user_id, first, last, age) VALUES ('test', '\xC3\xBCmlaut', 'test', 1)\x00\x05")
|
59
|
+
end
|
55
60
|
end
|
56
61
|
|
57
62
|
context 'with PREPARE requests' do
|
@@ -106,11 +111,11 @@ module Cql
|
|
106
111
|
specs.each do |type, value, expected_bytes|
|
107
112
|
it "encodes #{type} values" do
|
108
113
|
metadata = [['ks', 'tbl', 'id_column', type]]
|
109
|
-
|
110
|
-
|
111
|
-
length =
|
112
|
-
result_bytes =
|
113
|
-
result_bytes.should
|
114
|
+
buffer = RequestFrame.new(ExecuteRequest.new(id, metadata, [value], :one)).write(ByteBuffer.new)
|
115
|
+
buffer.discard(8 + 2 + 16 + 2)
|
116
|
+
length = buffer.read_int
|
117
|
+
result_bytes = buffer.read(length)
|
118
|
+
result_bytes.should eql_bytes(expected_bytes)
|
114
119
|
end
|
115
120
|
end
|
116
121
|
|
@@ -123,7 +123,7 @@ module Cql
|
|
123
123
|
|
124
124
|
context 'when fed an ERROR frame with details' do
|
125
125
|
it 'has more details for a unavailable error' do
|
126
|
-
frame = described_class.new("\x81\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x10\x00\x00\x0cUnavailable!\x00\x05\x00\x00\x00\x03\x00\x00\x00\x02")
|
126
|
+
frame = described_class.new(ByteBuffer.new("\x81\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x10\x00\x00\x0cUnavailable!\x00\x05\x00\x00\x00\x03\x00\x00\x00\x02"))
|
127
127
|
frame.body.details.should == {
|
128
128
|
:cl => :all,
|
129
129
|
:required => 3,
|
@@ -132,7 +132,7 @@ module Cql
|
|
132
132
|
end
|
133
133
|
|
134
134
|
it 'has more details for a write_timeout error' do
|
135
|
-
frame = described_class.new("\x81\x00\x00\x00\x00\x00\x00K\x00\x00\x11\x00\x000Operation timed out - received only 0 responses.\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\tBATCH_LOG")
|
135
|
+
frame = described_class.new(ByteBuffer.new("\x81\x00\x00\x00\x00\x00\x00K\x00\x00\x11\x00\x000Operation timed out - received only 0 responses.\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\tBATCH_LOG"))
|
136
136
|
frame.body.details.should == {
|
137
137
|
:cl => :one,
|
138
138
|
:received => 0,
|
@@ -142,14 +142,14 @@ module Cql
|
|
142
142
|
end
|
143
143
|
|
144
144
|
it 'has more details for a read_timeout error' do
|
145
|
-
frame = described_class.new("\x81\x00\x00\x00\x00\x00\x00\x25\x00\x00\x12\x00\x00\x14Operation timed out.\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x01")
|
145
|
+
frame = described_class.new(ByteBuffer.new("\x81\x00\x00\x00\x00\x00\x00\x25\x00\x00\x12\x00\x00\x14Operation timed out.\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x01"))
|
146
146
|
frame.body.details.should == {
|
147
147
|
:cl => :one,
|
148
148
|
:received => 0,
|
149
149
|
:blockfor => 1,
|
150
150
|
:data_present => true
|
151
151
|
}
|
152
|
-
frame = described_class.new("\x81\x00\x00\x00\x00\x00\x00\x25\x00\x00\x12\x00\x00\x14Operation timed out.\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00")
|
152
|
+
frame = described_class.new(ByteBuffer.new("\x81\x00\x00\x00\x00\x00\x00\x25\x00\x00\x12\x00\x00\x14Operation timed out.\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00"))
|
153
153
|
frame.body.details.should == {
|
154
154
|
:cl => :one,
|
155
155
|
:received => 0,
|
@@ -159,7 +159,7 @@ module Cql
|
|
159
159
|
end
|
160
160
|
|
161
161
|
it 'has more details for an already_exists error with a keyspace' do
|
162
|
-
frame = described_class.new("\x81\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x24\x00\x00\x10Keyspace exists!\x00\x05stuff\x00\x00")
|
162
|
+
frame = described_class.new(ByteBuffer.new("\x81\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x24\x00\x00\x10Keyspace exists!\x00\x05stuff\x00\x00"))
|
163
163
|
frame.body.details.should == {
|
164
164
|
:ks => 'stuff',
|
165
165
|
:table => '',
|
@@ -167,7 +167,7 @@ module Cql
|
|
167
167
|
end
|
168
168
|
|
169
169
|
it 'has more details for an already_exists error with a keyspace and table' do
|
170
|
-
frame = described_class.new("\x81\x00\x00\x00\x00\x00\x00\x24\x00\x00\x24\x00\x00\x10Keyspace exists!\x00\x05stuff\x00\x06things")
|
170
|
+
frame = described_class.new(ByteBuffer.new("\x81\x00\x00\x00\x00\x00\x00\x24\x00\x00\x24\x00\x00\x10Keyspace exists!\x00\x05stuff\x00\x06things"))
|
171
171
|
frame.body.details.should == {
|
172
172
|
:ks => 'stuff',
|
173
173
|
:table => 'things',
|
@@ -175,14 +175,14 @@ module Cql
|
|
175
175
|
end
|
176
176
|
|
177
177
|
it 'has more details for an unprepared error' do
|
178
|
-
frame = described_class.new("\x81\x00\x00\x00\x00\x00\x00\x33\x00\x00\x25\x00\x00\x1bUnknown prepared statement!\x00\x10\xCAH\x7F\x1Ez\x82\xD2<N\x8A\xF35Qq\xA5/")
|
178
|
+
frame = described_class.new(ByteBuffer.new("\x81\x00\x00\x00\x00\x00\x00\x33\x00\x00\x25\x00\x00\x1bUnknown prepared statement!\x00\x10\xCAH\x7F\x1Ez\x82\xD2<N\x8A\xF35Qq\xA5/"))
|
179
179
|
frame.body.details.should == {
|
180
180
|
:id => "\xCAH\x7F\x1Ez\x82\xD2<N\x8A\xF35Qq\xA5/"
|
181
181
|
}
|
182
182
|
end
|
183
183
|
|
184
184
|
it 'has a pretty #to_s representation' do
|
185
|
-
frame = described_class.new("\x81\x00\x00\x00\x00\x00\x00\x33\x00\x00\x25\x00\x00\x1bUnknown prepared statement!\x00\x10\xCAH\x7F\x1Ez\x82\xD2<N\x8A\xF35Qq\xA5/")
|
185
|
+
frame = described_class.new(ByteBuffer.new("\x81\x00\x00\x00\x00\x00\x00\x33\x00\x00\x25\x00\x00\x1bUnknown prepared statement!\x00\x10\xCAH\x7F\x1Ez\x82\xD2<N\x8A\xF35Qq\xA5/"))
|
186
186
|
frame.body.to_s.should match(/^ERROR 9472 "Unknown prepared statement!" \{:id=>".+?"\}$/)
|
187
187
|
end
|
188
188
|
end
|
@@ -541,7 +541,7 @@ module Cql
|
|
541
541
|
end
|
542
542
|
|
543
543
|
it 'decodes COUNTER as a number' do
|
544
|
-
frame = described_class.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")
|
544
|
+
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
545
|
frame.body.rows.first['c1'].should == 3
|
546
546
|
end
|
547
547
|
|
@@ -553,6 +553,22 @@ module Cql
|
|
553
553
|
end
|
554
554
|
end
|
555
555
|
|
556
|
+
context 'when decoding an INET column' do
|
557
|
+
let :rows do
|
558
|
+
frame = described_class.new
|
559
|
+
frame << "\x81\x00\x00\b\x00\x00\x00V\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\x00\ntest_types\x00\rlots_of_types\x00\vinet_column\x00\x10\x00\x00\x00\x02\x00\x00\x00\x04\x7F\x00\x00\x01\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
|
560
|
+
frame.body.rows.to_a
|
561
|
+
end
|
562
|
+
|
563
|
+
it 'decodes IPv4 values' do
|
564
|
+
rows[0]['inet_column'].should == IPAddr.new('127.0.0.1')
|
565
|
+
end
|
566
|
+
|
567
|
+
it 'decodes IPv6 values' do
|
568
|
+
rows[1]['inet_column'].should == IPAddr.new('::1')
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
556
572
|
context 'when it\'s an unknown type' do
|
557
573
|
it 'raises an error' do
|
558
574
|
expect { frame << "\x81\x00\x00\b\x00\x00\x00\x05\x00\x00\x00\xffhello" }.to raise_error(UnsupportedResultKindError)
|
@@ -652,8 +668,8 @@ module Cql
|
|
652
668
|
|
653
669
|
context 'when fed an unsupported event type' do
|
654
670
|
it 'raises an exception' do
|
655
|
-
|
656
|
-
expect { described_class.new(
|
671
|
+
bytes = ByteBuffer.new("\x81\x00\xFF\f\x00\x00\x00\x06\x00\x04PING")
|
672
|
+
expect { described_class.new(bytes) }.to raise_error(UnsupportedEventTypeError, /PING/)
|
657
673
|
end
|
658
674
|
end
|
659
675
|
|
@@ -665,20 +681,20 @@ module Cql
|
|
665
681
|
|
666
682
|
context 'when fed more bytes than needed' do
|
667
683
|
it 'it consumes its bytes, leaving the rest' do
|
668
|
-
buffer = "\x81\x00\x00\x06\x00\x00\x00\x27\x00\x02\x00\x0bCQL_VERSION\x00\x01\x00\x053.0.0\x00\x0bCOMPRESSION\x00\x00"
|
684
|
+
buffer = ByteBuffer.new("\x81\x00\x00\x06\x00\x00\x00\x27\x00\x02\x00\x0bCQL_VERSION\x00\x01\x00\x053.0.0\x00\x0bCOMPRESSION\x00\x00")
|
669
685
|
buffer << "\x81\x00\x00\x00"
|
670
686
|
described_class.new(buffer)
|
671
|
-
buffer.should
|
687
|
+
buffer.should eql_bytes("\x81\x00\x00\x00")
|
672
688
|
end
|
673
689
|
end
|
674
690
|
|
675
691
|
context 'when fed a frame that is longer than the specification specifies' do
|
676
692
|
it 'it consumes the body length, leaving the rest' do
|
677
|
-
buffer = "\x81\x00\x00\x06\x00\x00\x00\x2a"
|
693
|
+
buffer = ByteBuffer.new("\x81\x00\x00\x06\x00\x00\x00\x2a")
|
678
694
|
buffer << "\x00\x02\x00\x0bCQL_VERSION\x00\x01\x00\x053.0.0\x00\x0bCOMPRESSION\x00\x00"
|
679
695
|
buffer << "\xab\xcd\xef\x99"
|
680
696
|
described_class.new(buffer)
|
681
|
-
buffer.should
|
697
|
+
buffer.should eql_bytes("\x99")
|
682
698
|
end
|
683
699
|
end
|
684
700
|
|
@@ -151,5 +151,9 @@ describe 'A CQL client' do
|
|
151
151
|
client = Cql::Client.new(connection_options.merge(port: 9160))
|
152
152
|
expect { client.connect }.to raise_error(Cql::IoError)
|
153
153
|
end
|
154
|
+
|
155
|
+
it 'fails gracefully when connecting to something that does not run C*' do
|
156
|
+
expect { Cql::Client.connect(host: 'google.com') }.to raise_error(Cql::Io::ConnectionTimeoutError)
|
157
|
+
end
|
154
158
|
end
|
155
159
|
end
|
@@ -385,7 +385,7 @@ describe 'Protocol parsing and communication' do
|
|
385
385
|
it 'does nothing the second time #start is called' do
|
386
386
|
io_reactor = Cql::Io::IoReactor.new
|
387
387
|
io_reactor.start.get
|
388
|
-
io_reactor.add_connection('
|
388
|
+
io_reactor.add_connection(ENV['CASSANDRA_HOST'], 9042)
|
389
389
|
io_reactor.queue_request(Cql::Protocol::StartupRequest.new).get
|
390
390
|
io_reactor.start.get
|
391
391
|
response = io_reactor.queue_request(Cql::Protocol::QueryRequest.new('USE system', :any)).get
|
@@ -8,25 +8,31 @@ describe 'Regressions' do
|
|
8
8
|
{:host => ENV['CASSANDRA_HOST']}
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
11
|
+
let :client do
|
12
|
+
Cql::Client.new(connection_options)
|
13
|
+
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
before do
|
16
|
+
client.connect
|
17
|
+
client.execute('DROP KEYSPACE cql_rb_client_spec') rescue nil
|
18
|
+
client.execute(%(CREATE KEYSPACE cql_rb_client_spec WITH REPLICATION = {'CLASS': 'SimpleStrategy', 'replication_factor': 1}))
|
19
|
+
client.use('cql_rb_client_spec')
|
20
|
+
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
after do
|
23
|
+
client.execute('DROP KEYSPACE cql_rb_client_spec')
|
24
|
+
client.close
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'executes queries with multibyte characters' do
|
28
|
+
client.execute(%(CREATE TABLE users (user_id VARCHAR PRIMARY KEY, first VARCHAR, last VARCHAR, age INT)))
|
29
|
+
client.execute(%(INSERT INTO users (user_id, first, last, age) VALUES ('test', 'ümlaut', 'test', 1)))
|
30
|
+
end
|
26
31
|
|
32
|
+
context 'with prepared statements' do
|
27
33
|
it 'handles multibyte characters in prepared statements' do
|
28
34
|
client.execute(%(CREATE TABLE users (user_id VARCHAR PRIMARY KEY, first VARCHAR, last VARCHAR, age INT)))
|
29
|
-
client.execute("INSERT INTO users (user_id, first, last, age) VALUES ('test', 'ümlaut', 'test', 1)")
|
35
|
+
client.execute("INSERT INTO users (user_id, first, last, age) VALUES ('test', 'ümlaut', 'test', 1)")
|
30
36
|
statement = client.prepare('INSERT INTO users (user_id, first, last, age) VALUES (?, ?, ?, ?)')
|
31
37
|
statement.execute('test2', 'test2', 'test2', 2)
|
32
38
|
statement.execute('test3', 'ümlaut', 'test3', 3)
|
@@ -56,4 +62,25 @@ describe 'Regressions' do
|
|
56
62
|
statement.execute('eve@gmail.com')
|
57
63
|
end
|
58
64
|
end
|
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])
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'inet' do
|
75
|
+
client.execute('select inet_column from test_types.lots_of_types')
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'null values' do
|
79
|
+
client.execute('CREATE TABLE null_value (a BIGINT, b BOOLEAN, c INT, PRIMARY KEY ((a, b), c))')
|
80
|
+
client.execute('INSERT INTO null_value (a, b, c) VALUES (123123123123, true, 3234)')
|
81
|
+
client.execute('INSERT INTO null_value (a, b, c) VALUES (123123123123, true, 234243)')
|
82
|
+
client.execute('INSERT INTO null_value (a, b, c) VALUES (456456, false, 465645)')
|
83
|
+
p client.execute('SELECT * FROM null_value').to_a
|
84
|
+
end
|
85
|
+
end
|
59
86
|
end
|