cql-rb 1.2.2 → 2.0.0.pre0
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.
- 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
|