cql-rb 1.0.0.pre5 → 1.0.0.pre6
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.
- 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
|