cql-rb 1.2.2 → 2.0.0.pre0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +4 -0
- data/README.md +139 -17
- data/lib/cql/client.rb +237 -8
- data/lib/cql/client/asynchronous_client.rb +138 -54
- data/lib/cql/client/asynchronous_prepared_statement.rb +41 -6
- data/lib/cql/client/authenticators.rb +46 -0
- data/lib/cql/client/batch.rb +115 -0
- data/lib/cql/client/connector.rb +255 -0
- data/lib/cql/client/execute_options_decoder.rb +25 -9
- data/lib/cql/client/keyspace_changer.rb +5 -5
- data/lib/cql/client/peer_discovery.rb +33 -0
- data/lib/cql/client/query_result.rb +124 -1
- data/lib/cql/client/request_runner.rb +4 -2
- data/lib/cql/client/synchronous_client.rb +14 -2
- data/lib/cql/client/synchronous_prepared_statement.rb +19 -1
- data/lib/cql/future.rb +97 -50
- data/lib/cql/io/connection.rb +0 -1
- data/lib/cql/io/io_reactor.rb +1 -1
- data/lib/cql/protocol.rb +8 -1
- data/lib/cql/protocol/cql_protocol_handler.rb +2 -2
- data/lib/cql/protocol/decoding.rb +10 -15
- data/lib/cql/protocol/frame_decoder.rb +2 -1
- data/lib/cql/protocol/frame_encoder.rb +5 -4
- data/lib/cql/protocol/requests/auth_response_request.rb +31 -0
- data/lib/cql/protocol/requests/batch_request.rb +59 -0
- data/lib/cql/protocol/requests/credentials_request.rb +1 -1
- data/lib/cql/protocol/requests/execute_request.rb +45 -17
- data/lib/cql/protocol/requests/options_request.rb +1 -1
- data/lib/cql/protocol/requests/prepare_request.rb +1 -1
- data/lib/cql/protocol/requests/query_request.rb +97 -5
- data/lib/cql/protocol/requests/register_request.rb +1 -1
- data/lib/cql/protocol/requests/startup_request.rb +4 -4
- data/lib/cql/protocol/response.rb +2 -2
- data/lib/cql/protocol/responses/auth_challenge_response.rb +25 -0
- data/lib/cql/protocol/responses/auth_success_response.rb +25 -0
- data/lib/cql/protocol/responses/authenticate_response.rb +1 -1
- data/lib/cql/protocol/responses/detailed_error_response.rb +1 -1
- data/lib/cql/protocol/responses/error_response.rb +3 -2
- data/lib/cql/protocol/responses/event_response.rb +3 -2
- data/lib/cql/protocol/responses/prepared_result_response.rb +10 -6
- data/lib/cql/protocol/responses/raw_rows_result_response.rb +27 -0
- data/lib/cql/protocol/responses/ready_response.rb +1 -1
- data/lib/cql/protocol/responses/result_response.rb +2 -2
- data/lib/cql/protocol/responses/rows_result_response.rb +43 -23
- data/lib/cql/protocol/responses/schema_change_event_response.rb +1 -1
- data/lib/cql/protocol/responses/schema_change_result_response.rb +1 -1
- data/lib/cql/protocol/responses/set_keyspace_result_response.rb +1 -1
- data/lib/cql/protocol/responses/status_change_event_response.rb +1 -1
- data/lib/cql/protocol/responses/supported_response.rb +1 -1
- data/lib/cql/protocol/responses/void_result_response.rb +1 -1
- data/lib/cql/protocol/type_converter.rb +2 -2
- data/lib/cql/uuid.rb +2 -2
- data/lib/cql/version.rb +1 -1
- data/spec/cql/client/asynchronous_client_spec.rb +493 -50
- data/spec/cql/client/asynchronous_prepared_statement_spec.rb +193 -11
- data/spec/cql/client/authenticators_spec.rb +56 -0
- data/spec/cql/client/batch_spec.rb +277 -0
- data/spec/cql/client/connector_spec.rb +606 -0
- data/spec/cql/client/execute_options_decoder_spec.rb +95 -0
- data/spec/cql/client/keyspace_changer_spec.rb +8 -8
- data/spec/cql/client/peer_discovery_spec.rb +92 -0
- data/spec/cql/client/query_result_spec.rb +352 -0
- data/spec/cql/client/request_runner_spec.rb +31 -5
- data/spec/cql/client/synchronous_client_spec.rb +44 -1
- data/spec/cql/client/synchronous_prepared_statement_spec.rb +63 -1
- data/spec/cql/future_spec.rb +50 -2
- data/spec/cql/protocol/cql_protocol_handler_spec.rb +16 -5
- data/spec/cql/protocol/decoding_spec.rb +16 -6
- data/spec/cql/protocol/encoding_spec.rb +3 -1
- data/spec/cql/protocol/frame_encoder_spec.rb +99 -50
- data/spec/cql/protocol/requests/auth_response_request_spec.rb +62 -0
- data/spec/cql/protocol/requests/batch_request_spec.rb +155 -0
- data/spec/cql/protocol/requests/credentials_request_spec.rb +1 -1
- data/spec/cql/protocol/requests/execute_request_spec.rb +184 -71
- data/spec/cql/protocol/requests/options_request_spec.rb +1 -1
- data/spec/cql/protocol/requests/prepare_request_spec.rb +1 -1
- data/spec/cql/protocol/requests/query_request_spec.rb +255 -32
- data/spec/cql/protocol/requests/register_request_spec.rb +1 -1
- data/spec/cql/protocol/requests/startup_request_spec.rb +12 -6
- data/spec/cql/protocol/responses/auth_challenge_response_spec.rb +31 -0
- data/spec/cql/protocol/responses/auth_success_response_spec.rb +31 -0
- data/spec/cql/protocol/responses/authenticate_response_spec.rb +2 -1
- data/spec/cql/protocol/responses/detailed_error_response_spec.rb +14 -7
- data/spec/cql/protocol/responses/error_response_spec.rb +4 -2
- data/spec/cql/protocol/responses/event_response_spec.rb +7 -4
- data/spec/cql/protocol/responses/prepared_result_response_spec.rb +89 -34
- data/spec/cql/protocol/responses/raw_rows_result_response_spec.rb +66 -0
- data/spec/cql/protocol/responses/ready_response_spec.rb +1 -1
- data/spec/cql/protocol/responses/result_response_spec.rb +19 -7
- data/spec/cql/protocol/responses/rows_result_response_spec.rb +56 -11
- data/spec/cql/protocol/responses/schema_change_event_response_spec.rb +2 -1
- data/spec/cql/protocol/responses/schema_change_result_response_spec.rb +2 -1
- data/spec/cql/protocol/responses/set_keyspace_result_response_spec.rb +1 -1
- data/spec/cql/protocol/responses/status_change_event_response_spec.rb +2 -1
- data/spec/cql/protocol/responses/supported_response_spec.rb +2 -1
- data/spec/cql/protocol/responses/topology_change_event_response_spec.rb +2 -1
- data/spec/cql/protocol/responses/void_result_response_spec.rb +1 -1
- data/spec/cql/protocol/type_converter_spec.rb +21 -4
- data/spec/cql/uuid_spec.rb +10 -3
- data/spec/integration/client_spec.rb +251 -28
- data/spec/integration/protocol_spec.rb +213 -62
- data/spec/integration/regression_spec.rb +4 -1
- data/spec/integration/uuid_spec.rb +4 -1
- data/spec/support/fake_io_reactor.rb +5 -5
- metadata +36 -7
- data/lib/cql/client/connection_helper.rb +0 -181
- data/spec/cql/client/connection_helper_spec.rb +0 -429
@@ -4,8 +4,12 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
|
6
6
|
describe 'Protocol parsing and communication' do
|
7
|
+
let :protocol_version do
|
8
|
+
2
|
9
|
+
end
|
10
|
+
|
7
11
|
let! :io_reactor do
|
8
|
-
ir = Cql::Io::IoReactor.new(Cql::Protocol::CqlProtocolHandler)
|
12
|
+
ir = Cql::Io::IoReactor.new(lambda { |*args| Cql::Protocol::CqlProtocolHandler.new(*args, protocol_version) })
|
9
13
|
ir.start
|
10
14
|
connections << ir.connect(ENV['CASSANDRA_HOST'], 9042, 5).value
|
11
15
|
ir
|
@@ -26,24 +30,42 @@ describe 'Protocol parsing and communication' do
|
|
26
30
|
end
|
27
31
|
end
|
28
32
|
|
33
|
+
def authentication_enabled?
|
34
|
+
ir = Cql::Io::IoReactor.new(lambda { |*args| Cql::Protocol::CqlProtocolHandler.new(*args, protocol_version) })
|
35
|
+
ir.start
|
36
|
+
connected = ir.connect(ENV['CASSANDRA_HOST'], 9042, 5)
|
37
|
+
started = connected.flat_map do |connection|
|
38
|
+
connection.send_request(Cql::Protocol::StartupRequest.new('3.1.0'))
|
39
|
+
end
|
40
|
+
response = started.value
|
41
|
+
required = response.is_a?(Cql::Protocol::AuthenticateResponse)
|
42
|
+
ir.stop.value
|
43
|
+
required
|
44
|
+
end
|
45
|
+
|
46
|
+
|
29
47
|
def raw_execute_request(request)
|
30
48
|
connection = connections.first
|
31
49
|
connection.send_request(request).value
|
32
50
|
end
|
33
51
|
|
34
|
-
def execute_request(request)
|
52
|
+
def execute_request(request, auto_authenticate=true)
|
35
53
|
response = raw_execute_request(request)
|
36
|
-
if response.is_a?(Cql::Protocol::AuthenticateResponse)
|
54
|
+
if response.is_a?(Cql::Protocol::AuthenticateResponse) && auto_authenticate
|
37
55
|
unless response.authentication_class == 'org.apache.cassandra.auth.PasswordAuthenticator'
|
38
56
|
raise "Cassandra required an unsupported authenticator: #{response.authentication_class}"
|
39
57
|
end
|
40
|
-
|
58
|
+
if protocol_version == 1
|
59
|
+
response = execute_request(Cql::Protocol::CredentialsRequest.new('username' => 'cassandra', 'password' => 'cassandra'))
|
60
|
+
else
|
61
|
+
response = execute_request(Cql::Protocol::AuthResponseRequest.new("\x00cassandra\x00cassandra"))
|
62
|
+
end
|
41
63
|
end
|
42
64
|
response
|
43
65
|
end
|
44
66
|
|
45
67
|
def query(cql, consistency=:one)
|
46
|
-
response = execute_request(Cql::Protocol::QueryRequest.new(cql, consistency))
|
68
|
+
response = execute_request(Cql::Protocol::QueryRequest.new(cql, nil, nil, consistency))
|
47
69
|
raise response.to_s if response.is_a?(Cql::Protocol::ErrorResponse)
|
48
70
|
response
|
49
71
|
end
|
@@ -103,60 +125,87 @@ describe 'Protocol parsing and communication' do
|
|
103
125
|
response.options.should have_key('CQL_VERSION')
|
104
126
|
end
|
105
127
|
|
128
|
+
it 'sends a bad STARTUP and receives ERROR' do
|
129
|
+
response = execute_request(Cql::Protocol::StartupRequest.new('9.9.9'))
|
130
|
+
response.code.should == 10
|
131
|
+
response.message.should include('not supported')
|
132
|
+
end
|
133
|
+
|
106
134
|
context 'when authentication is not required' do
|
107
135
|
it 'sends STARTUP and receives READY' do
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
it 'sends a bad STARTUP and receives ERROR' do
|
113
|
-
response = execute_request(Cql::Protocol::StartupRequest.new('9.9.9'))
|
114
|
-
response.code.should == 10
|
115
|
-
response.message.should include('not supported')
|
136
|
+
pending('authentication required', if: authentication_enabled?) do
|
137
|
+
response = execute_request(Cql::Protocol::StartupRequest.new('3.1.0'), false)
|
138
|
+
response.should be_a(Cql::Protocol::ReadyResponse)
|
139
|
+
end
|
116
140
|
end
|
117
141
|
end
|
118
142
|
|
119
143
|
context 'when authentication is required' do
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
started = connected.flat_map do |connection|
|
125
|
-
connection.send_request(Cql::Protocol::StartupRequest.new)
|
126
|
-
end
|
127
|
-
response = started.value
|
128
|
-
required = response.is_a?(Cql::Protocol::AuthenticateResponse)
|
129
|
-
ir.stop.value
|
130
|
-
required
|
131
|
-
end
|
144
|
+
context 'and the protocol version is 1' do
|
145
|
+
let :protocol_version do
|
146
|
+
1
|
147
|
+
end
|
132
148
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
149
|
+
it 'sends STARTUP and receives AUTHENTICATE' do
|
150
|
+
pending('authentication not configured', unless: authentication_enabled?) do
|
151
|
+
response = raw_execute_request(Cql::Protocol::StartupRequest.new('3.1.0'))
|
152
|
+
response.should be_a(Cql::Protocol::AuthenticateResponse)
|
153
|
+
end
|
137
154
|
end
|
138
|
-
end
|
139
155
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
156
|
+
it 'ignores the AUTHENTICATE response and receives ERROR' do
|
157
|
+
pending('authentication not configured', unless: authentication_enabled?) do
|
158
|
+
raw_execute_request(Cql::Protocol::StartupRequest.new('3.1.0'))
|
159
|
+
response = raw_execute_request(Cql::Protocol::RegisterRequest.new('TOPOLOGY_CHANGE'))
|
160
|
+
response.code.should == 10
|
161
|
+
end
|
145
162
|
end
|
146
|
-
end
|
147
163
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
164
|
+
it 'sends STARTUP followed by CREDENTIALS and receives READY' do
|
165
|
+
raw_execute_request(Cql::Protocol::StartupRequest.new('3.1.0'))
|
166
|
+
response = raw_execute_request(Cql::Protocol::CredentialsRequest.new('username' => 'cassandra', 'password' => 'cassandra'))
|
167
|
+
response.should be_a(Cql::Protocol::ReadyResponse)
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'sends bad username and password in CREDENTIALS and receives ERROR' do
|
171
|
+
pending('authentication not configured', unless: authentication_enabled?) do
|
172
|
+
raw_execute_request(Cql::Protocol::StartupRequest.new('3.1.0'))
|
173
|
+
response = raw_execute_request(Cql::Protocol::CredentialsRequest.new('username' => 'foo', 'password' => 'bar'))
|
174
|
+
response.code.should == 0x100
|
175
|
+
end
|
176
|
+
end
|
152
177
|
end
|
153
178
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
179
|
+
context 'and the protocol version is 2' do
|
180
|
+
it 'sends STARTUP and receives AUTHENTICATE' do
|
181
|
+
pending('authentication not configured', unless: authentication_enabled?) do
|
182
|
+
response = raw_execute_request(Cql::Protocol::StartupRequest.new('3.1.0'))
|
183
|
+
response.should be_a(Cql::Protocol::AuthenticateResponse)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'ignores the AUTHENTICATE response and receives ERROR' do
|
188
|
+
pending('authentication not configured', unless: authentication_enabled?) do
|
189
|
+
raw_execute_request(Cql::Protocol::StartupRequest.new('3.1.0'))
|
190
|
+
response = raw_execute_request(Cql::Protocol::RegisterRequest.new('TOPOLOGY_CHANGE'))
|
191
|
+
response.code.should == 10
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'sends STARTUP followed by AUTH_RESPONSE and receives AUTH_SUCCESS' do
|
196
|
+
pending('authentication not configured', unless: authentication_enabled?) do
|
197
|
+
raw_execute_request(Cql::Protocol::StartupRequest.new('3.1.0'))
|
198
|
+
response = raw_execute_request(Cql::Protocol::AuthResponseRequest.new("\x00cassandra\x00cassandra"))
|
199
|
+
response.should be_a(Cql::Protocol::AuthSuccessResponse)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'sends bad username and password in AUTH_RESPONSE and receives ERROR' do
|
204
|
+
pending('authentication not configured', unless: authentication_enabled?) do
|
205
|
+
raw_execute_request(Cql::Protocol::StartupRequest.new('3.1.0'))
|
206
|
+
response = raw_execute_request(Cql::Protocol::AuthResponseRequest.new("\x00cassandra\x00ardnassac"))
|
207
|
+
response.code.should == 0x100
|
208
|
+
end
|
160
209
|
end
|
161
210
|
end
|
162
211
|
end
|
@@ -164,7 +213,7 @@ describe 'Protocol parsing and communication' do
|
|
164
213
|
|
165
214
|
context 'when set up' do
|
166
215
|
before do
|
167
|
-
response = execute_request(Cql::Protocol::StartupRequest.new)
|
216
|
+
response = execute_request(Cql::Protocol::StartupRequest.new('3.1.0'))
|
168
217
|
response
|
169
218
|
end
|
170
219
|
|
@@ -201,7 +250,7 @@ describe 'Protocol parsing and communication' do
|
|
201
250
|
end
|
202
251
|
|
203
252
|
it 'sends a bad CQL string and receives ERROR' do
|
204
|
-
response = execute_request(Cql::Protocol::QueryRequest.new('HELLO WORLD', :any))
|
253
|
+
response = execute_request(Cql::Protocol::QueryRequest.new('HELLO WORLD', nil, nil, :any))
|
205
254
|
response.should be_a(Cql::Protocol::ErrorResponse)
|
206
255
|
end
|
207
256
|
|
@@ -320,6 +369,69 @@ describe 'Protocol parsing and communication' do
|
|
320
369
|
]
|
321
370
|
end
|
322
371
|
end
|
372
|
+
|
373
|
+
it 'sends an INSERT command with bound values' do
|
374
|
+
in_keyspace_with_table do
|
375
|
+
cql = %<INSERT INTO users (user_name, email) VALUES (?, ?)>
|
376
|
+
response = execute_request(Cql::Protocol::QueryRequest.new(cql, ['sue', 'sue@inter.net'], nil, :one))
|
377
|
+
response.should be_void
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
it 'sends an UPDATE command with bound values' do
|
382
|
+
in_keyspace_with_table do
|
383
|
+
cql = %<UPDATE users SET email = ? WHERE user_name = ?>
|
384
|
+
response = execute_request(Cql::Protocol::QueryRequest.new(cql, ['sue@inter.net', 'sue'], nil, :one))
|
385
|
+
response.should be_void
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
it 'sends a SELECT command with bound values' do
|
390
|
+
in_keyspace_with_table do
|
391
|
+
query(%<INSERT INTO users (user_name, email) VALUES ('phil', 'phil@heck.com')>)
|
392
|
+
query(%<INSERT INTO users (user_name, email) VALUES ('sue', 'sue@inter.net')>)
|
393
|
+
cql = %<SELECT * FROM users WHERE user_name = ?>
|
394
|
+
response = execute_request(Cql::Protocol::QueryRequest.new(cql, ['sue'], nil, :one))
|
395
|
+
response.rows.should == [
|
396
|
+
{'user_name' => 'sue', 'email' => 'sue@inter.net', 'password' => nil}
|
397
|
+
]
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
it 'guesses the types of bound values' do
|
402
|
+
in_keyspace do
|
403
|
+
query('CREATE TABLE types (a BIGINT PRIMARY KEY, b DOUBLE, c ASCII, d BOOLEAN, e TIMESTAMP, f UUID, g DECIMAL, h BLOB)')
|
404
|
+
cql = %<UPDATE types SET b = ?, c = ?, d = ?, e = ?, f = ?, g = ?, h = ? WHERE a = ?>
|
405
|
+
values = [123.456, 'foo', true, Time.now, Cql::TimeUuid::Generator.new.next, BigDecimal.new('0.01'), 'hello', 3]
|
406
|
+
response = execute_request(Cql::Protocol::QueryRequest.new(cql, values, nil, :one))
|
407
|
+
response.should be_void
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
it 'uses the provided type hints to encode bound values' do
|
412
|
+
in_keyspace do
|
413
|
+
query('CREATE TABLE types (a INT PRIMARY KEY, b FLOAT)')
|
414
|
+
cql = %<UPDATE types SET b = ? WHERE a = ?>
|
415
|
+
values = [123.456, 3]
|
416
|
+
hints = [:float, :int]
|
417
|
+
response = execute_request(Cql::Protocol::QueryRequest.new(cql, values, hints, :one))
|
418
|
+
response.should be_void
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
it 'sends a SELECT command with a page size and receives a ROWS RESULT with a paging state' do
|
423
|
+
in_keyspace_with_table do
|
424
|
+
10.times do
|
425
|
+
query(%<INSERT INTO users (user_name, email) VALUES ('#{rand(234234).to_s(36)}', 'someone@somewhere.sx')>)
|
426
|
+
end
|
427
|
+
response = execute_request(Cql::Protocol::QueryRequest.new('SELECT * FROM users', nil, nil, :one, nil, 6))
|
428
|
+
response.paging_state.should_not be_nil
|
429
|
+
response.rows.size.should == 6
|
430
|
+
response = execute_request(Cql::Protocol::QueryRequest.new('SELECT * FROM users', nil, nil, :one, nil, 6, response.paging_state))
|
431
|
+
response.paging_state.should be_nil
|
432
|
+
response.rows.size.should == 4
|
433
|
+
end
|
434
|
+
end
|
323
435
|
end
|
324
436
|
|
325
437
|
context 'with PREPARE requests' do
|
@@ -335,20 +447,58 @@ describe 'Protocol parsing and communication' do
|
|
335
447
|
in_keyspace do
|
336
448
|
create_table_cql = %<CREATE TABLE stuff (id1 UUID, id2 VARINT, id3 TIMESTAMP, value1 DOUBLE, value2 TIMEUUID, value3 BLOB, PRIMARY KEY (id1, id2, id3))>
|
337
449
|
insert_cql = %<INSERT INTO stuff (id1, id2, id3, value1, value2, value3) VALUES (?, ?, ?, ?, ?, ?)>
|
338
|
-
create_response = execute_request(Cql::Protocol::QueryRequest.new(create_table_cql, :one))
|
450
|
+
create_response = execute_request(Cql::Protocol::QueryRequest.new(create_table_cql, nil, nil, :one))
|
339
451
|
create_response.should_not be_a(Cql::Protocol::ErrorResponse)
|
340
452
|
prepare_response = execute_request(Cql::Protocol::PrepareRequest.new(insert_cql))
|
341
453
|
prepare_response.should_not be_a(Cql::Protocol::ErrorResponse)
|
342
|
-
|
454
|
+
values = [Cql::Uuid.new('cfd66ccc-d857-4e90-b1e5-df98a3d40cd6'), -12312312312, Time.now, 345345.234234, Cql::Uuid.new('a4a70900-24e1-11df-8924-001ff3591711'), "\xab\xcd\xef".force_encoding(::Encoding::BINARY)]
|
455
|
+
execute_response = execute_request(Cql::Protocol::ExecuteRequest.new(prepare_response.id, prepare_response.metadata, values, nil, :one, nil, nil, nil, true))
|
343
456
|
execute_response.should_not be_a(Cql::Protocol::ErrorResponse)
|
344
457
|
end
|
345
458
|
end
|
459
|
+
|
460
|
+
it 'sends an EXECUTE with a page size and receives a RESULT with a paging state' do
|
461
|
+
in_keyspace_with_table do
|
462
|
+
10.times do
|
463
|
+
query(%<INSERT INTO users (user_name, email) VALUES ('#{rand(234234).to_s(36)}', 'someone@somewhere.sx')>)
|
464
|
+
end
|
465
|
+
response = execute_request(Cql::Protocol::PrepareRequest.new('SELECT * FROM users'))
|
466
|
+
statement_id = response.id
|
467
|
+
metadata = response.metadata
|
468
|
+
response = execute_request(Cql::Protocol::ExecuteRequest.new(statement_id, metadata, [], true, :one, nil, 6, nil))
|
469
|
+
response.paging_state.should_not be_nil
|
470
|
+
response.rows.size.should == 6
|
471
|
+
response = execute_request(Cql::Protocol::ExecuteRequest.new(statement_id, metadata, [], true, :one, nil, 6, response.paging_state))
|
472
|
+
response.paging_state.should be_nil
|
473
|
+
response.rows.size.should == 4
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
context 'with BATCH requests' do
|
479
|
+
it 'sends a BATCH request and receives RESULT' do
|
480
|
+
in_keyspace_with_table do
|
481
|
+
cql1 = %<INSERT INTO users (user_name, email) VALUES (?, ?)>
|
482
|
+
cql2 = %<UPDATE users SET email = ? WHERE user_name = 'sue'>
|
483
|
+
cql3 = %<INSERT INTO users (user_name, email) VALUES ('tim', 'tim@pim.com')>
|
484
|
+
prepared_response1 = execute_request(Cql::Protocol::PrepareRequest.new(cql1))
|
485
|
+
prepared_response2 = execute_request(Cql::Protocol::PrepareRequest.new(cql3))
|
486
|
+
request = Cql::Protocol::BatchRequest.new(0, :quorum)
|
487
|
+
request.add_query(cql1, ['sue', 'sue@inter.net'])
|
488
|
+
request.add_query(cql2, ['eve'])
|
489
|
+
request.add_query(cql3)
|
490
|
+
request.add_prepared(prepared_response1.id, prepared_response1.metadata, ['phil', 'phil@heck.com'])
|
491
|
+
request.add_prepared(prepared_response2.id, prepared_response2.metadata, [])
|
492
|
+
response = execute_request(request)
|
493
|
+
response.should be_void
|
494
|
+
end
|
495
|
+
end
|
346
496
|
end
|
347
497
|
|
348
498
|
context 'with tracing' do
|
349
499
|
it 'sends a QUERY request with the tracing flag and receives a RESULT with a trace ID' do
|
350
500
|
in_keyspace_with_table do
|
351
|
-
response = execute_request(Cql::Protocol::QueryRequest.new('SELECT * FROM users', :quorum, true))
|
501
|
+
response = execute_request(Cql::Protocol::QueryRequest.new('SELECT * FROM users', nil, nil, :quorum, nil, nil, nil, true))
|
352
502
|
response.trace_id.should_not be_nil
|
353
503
|
end
|
354
504
|
end
|
@@ -363,7 +513,7 @@ describe 'Protocol parsing and communication' do
|
|
363
513
|
it 'sends an EXECUTE request with the tracing flag and receives a RESULT with a trace ID' do
|
364
514
|
in_keyspace_with_table do
|
365
515
|
prepare_response = execute_request(Cql::Protocol::PrepareRequest.new('SELECT * FROM users'))
|
366
|
-
execute_response = execute_request(Cql::Protocol::ExecuteRequest.new(prepare_response.id, prepare_response.metadata, [], :one, true))
|
516
|
+
execute_response = execute_request(Cql::Protocol::ExecuteRequest.new(prepare_response.id, prepare_response.metadata, [], true, :one, nil, nil, nil, true))
|
367
517
|
execute_response.trace_id.should_not be_nil
|
368
518
|
end
|
369
519
|
end
|
@@ -377,11 +527,11 @@ describe 'Protocol parsing and communication' do
|
|
377
527
|
it 'sends a compressed request and receives a compressed response' do
|
378
528
|
compressor.stub(:compress).and_call_original
|
379
529
|
compressor.stub(:decompress).and_call_original
|
380
|
-
io_reactor = Cql::Io::IoReactor.new(lambda { |*args| Cql::Protocol::CqlProtocolHandler.new(*args, compressor) })
|
530
|
+
io_reactor = Cql::Io::IoReactor.new(lambda { |*args| Cql::Protocol::CqlProtocolHandler.new(*args, protocol_version, compressor) })
|
381
531
|
io_reactor.start.value
|
382
532
|
begin
|
383
533
|
connection = io_reactor.connect(ENV['CASSANDRA_HOST'], 9042, 0.1).value
|
384
|
-
connection.send_request(Cql::Protocol::StartupRequest.new(
|
534
|
+
connection.send_request(Cql::Protocol::StartupRequest.new('3.1.0', 'snappy')).value
|
385
535
|
connection.send_request(Cql::Protocol::PrepareRequest.new('SELECT * FROM system.peers')).value
|
386
536
|
compressor.should have_received(:compress).at_least(1).times
|
387
537
|
compressor.should have_received(:decompress).at_least(1).times
|
@@ -399,10 +549,10 @@ describe 'Protocol parsing and communication' do
|
|
399
549
|
it 'handles multiple concurrent requests' do
|
400
550
|
in_keyspace_with_table do
|
401
551
|
futures = 10.times.map do
|
402
|
-
connection.send_request(Cql::Protocol::QueryRequest.new('SELECT * FROM users', :quorum))
|
552
|
+
connection.send_request(Cql::Protocol::QueryRequest.new('SELECT * FROM users', nil, nil, :quorum))
|
403
553
|
end
|
404
554
|
|
405
|
-
futures << connection.send_request(Cql::Protocol::QueryRequest.new(%<INSERT INTO users (user_name, email) VALUES ('sam', 'sam@ham.com')>, :one))
|
555
|
+
futures << connection.send_request(Cql::Protocol::QueryRequest.new(%<INSERT INTO users (user_name, email) VALUES ('sam', 'sam@ham.com')>, nil, nil, :one))
|
406
556
|
|
407
557
|
Cql::Future.all(*futures).value
|
408
558
|
end
|
@@ -413,7 +563,7 @@ describe 'Protocol parsing and communication' do
|
|
413
563
|
threads = Array.new(10) do
|
414
564
|
Thread.new do
|
415
565
|
futures = 200.times.map do
|
416
|
-
connection.send_request(Cql::Protocol::QueryRequest.new('SELECT * FROM users', :quorum))
|
566
|
+
connection.send_request(Cql::Protocol::QueryRequest.new('SELECT * FROM users', nil, nil, :quorum))
|
417
567
|
end
|
418
568
|
Cql::Future.all(*futures).value
|
419
569
|
end
|
@@ -427,7 +577,7 @@ describe 'Protocol parsing and communication' do
|
|
427
577
|
|
428
578
|
context 'in special circumstances' do
|
429
579
|
it 'raises an exception when it cannot connect to Cassandra' do
|
430
|
-
io_reactor = Cql::Io::IoReactor.new(Cql::Protocol::CqlProtocolHandler)
|
580
|
+
io_reactor = Cql::Io::IoReactor.new(lambda { |*args| Cql::Protocol::CqlProtocolHandler.new(*args, protocol_version) })
|
431
581
|
io_reactor.start.value
|
432
582
|
expect { io_reactor.connect('example.com', 9042, 0.1).value }.to raise_error(Cql::Io::ConnectionError)
|
433
583
|
expect { io_reactor.connect('blackhole', 9042, 0.1).value }.to raise_error(Cql::Io::ConnectionError)
|
@@ -435,15 +585,16 @@ describe 'Protocol parsing and communication' do
|
|
435
585
|
end
|
436
586
|
|
437
587
|
it 'does nothing the second time #start is called' do
|
438
|
-
io_reactor = Cql::Io::IoReactor.new(Cql::Protocol::CqlProtocolHandler)
|
588
|
+
io_reactor = Cql::Io::IoReactor.new(lambda { |*args| Cql::Protocol::CqlProtocolHandler.new(*args, 2) })
|
439
589
|
io_reactor.start.value
|
440
590
|
connection = io_reactor.connect(ENV['CASSANDRA_HOST'], 9042, 0.1).value
|
441
|
-
response = connection.send_request(Cql::Protocol::StartupRequest.new).value
|
591
|
+
response = connection.send_request(Cql::Protocol::StartupRequest.new('3.1.0')).value
|
442
592
|
if response.is_a?(Cql::Protocol::AuthenticateResponse)
|
443
|
-
connection.send_request(Cql::Protocol::
|
593
|
+
response = connection.send_request(Cql::Protocol::AuthResponseRequest.new("\x00cassandra\x00cassandra")).value
|
594
|
+
response.should be_a(Cql::Protocol::AuthSuccessResponse)
|
444
595
|
end
|
445
596
|
io_reactor.start.value
|
446
|
-
response = connection.send_request(Cql::Protocol::QueryRequest.new('USE system', :any)).value
|
597
|
+
response = connection.send_request(Cql::Protocol::QueryRequest.new('USE system', nil, nil, :any)).value
|
447
598
|
response.should_not be_a(Cql::Protocol::ErrorResponse)
|
448
599
|
end
|
449
600
|
end
|
@@ -5,7 +5,10 @@ require 'spec_helper'
|
|
5
5
|
|
6
6
|
describe 'Regressions' do
|
7
7
|
let :connection_options do
|
8
|
-
{
|
8
|
+
{
|
9
|
+
:host => ENV['CASSANDRA_HOST'],
|
10
|
+
:credentials => {:username => 'cassandra', :password => 'cassandra'},
|
11
|
+
}
|
9
12
|
end
|
10
13
|
|
11
14
|
let :client do
|
@@ -5,7 +5,10 @@ require 'spec_helper'
|
|
5
5
|
|
6
6
|
describe 'Loading and storing UUIDs' do
|
7
7
|
let :connection_options do
|
8
|
-
{
|
8
|
+
{
|
9
|
+
:host => ENV['CASSANDRA_HOST'],
|
10
|
+
:credentials => {:username => 'cassandra', :password => 'cassandra'},
|
11
|
+
}
|
9
12
|
end
|
10
13
|
|
11
14
|
let :client do
|
@@ -73,7 +73,7 @@ end
|
|
73
73
|
class FakeConnection
|
74
74
|
attr_reader :host, :port, :timeout, :requests, :keyspace
|
75
75
|
|
76
|
-
def initialize(host, port, timeout)
|
76
|
+
def initialize(host, port, timeout, data={})
|
77
77
|
@host = host
|
78
78
|
@port = port
|
79
79
|
@timeout = timeout
|
@@ -81,7 +81,7 @@ class FakeConnection
|
|
81
81
|
@responses = []
|
82
82
|
@closed = false
|
83
83
|
@keyspace = nil
|
84
|
-
@data =
|
84
|
+
@data = data
|
85
85
|
@registered_event_types = []
|
86
86
|
@event_listeners = []
|
87
87
|
@closed_listeners = []
|
@@ -100,9 +100,9 @@ class FakeConnection
|
|
100
100
|
!@closed
|
101
101
|
end
|
102
102
|
|
103
|
-
def close
|
103
|
+
def close(cause=nil)
|
104
104
|
@closed = true
|
105
|
-
@closed_listeners.each(
|
105
|
+
@closed_listeners.each { |listener| listener.call(cause) }
|
106
106
|
end
|
107
107
|
|
108
108
|
def handle_request(&handler)
|
@@ -151,7 +151,7 @@ class FakeConnection
|
|
151
151
|
when Cql::Protocol::StartupRequest
|
152
152
|
Cql::Protocol::ReadyResponse.new
|
153
153
|
when Cql::Protocol::QueryRequest
|
154
|
-
Cql::Protocol::RowsResultResponse.new([], [], nil)
|
154
|
+
Cql::Protocol::RowsResultResponse.new([], [], nil, nil)
|
155
155
|
end
|
156
156
|
end
|
157
157
|
end
|