cql-rb 2.0.4 → 2.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/cql.rb +1 -0
- data/lib/cql/client.rb +2 -0
- data/lib/cql/client/client.rb +1 -1
- data/lib/cql/client/connector.rb +1 -1
- data/lib/cql/client/prepared_statement.rb +11 -4
- data/lib/cql/error_codes.rb +96 -0
- data/lib/cql/protocol/responses/detailed_error_response.rb +5 -5
- data/lib/cql/protocol/responses/error_response.rb +3 -1
- data/lib/cql/version.rb +1 -1
- data/spec/cql/client/prepared_statement_spec.rb +19 -0
- data/spec/integration/client_spec.rb +7 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 076ceeab9f5eff0e9ab577f1e433b087342a8457
|
4
|
+
data.tar.gz: 049f3ecd2f935016bdd4bb08a87648163609600b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e08c27d6a73bd4fc11573958ae2216affc238180d90d92c32aee98b20103a8614e6c1b693845b000c465b4ba9fd04b25c45a9ba012535a91e635974d832c66e5
|
7
|
+
data.tar.gz: 0e897851f1dab23f7eaa7ac1380071f4fa2bf0511a16911a5976156d197a533ba83b0fc05a2ee925050b9bc8b96f3ebf31a937158eddd222503b6e68c5343a7d
|
data/lib/cql.rb
CHANGED
data/lib/cql/client.rb
CHANGED
data/lib/cql/client/client.rb
CHANGED
@@ -365,7 +365,7 @@ module Cql
|
|
365
365
|
def connect_with_protocol_version_fallback
|
366
366
|
f = create_cluster_connector.connect_all(@hosts, @connections_per_node)
|
367
367
|
f.fallback do |error|
|
368
|
-
if error.is_a?(QueryError) && error.code ==
|
368
|
+
if error.is_a?(QueryError) && error.code == QueryError::PROTOCOL_ERROR && @protocol_version > 1
|
369
369
|
@logger.warn('Could not connect using protocol version %d (will try again with %d): %s' % [@protocol_version, @protocol_version - 1, error.message])
|
370
370
|
@protocol_version -= 1
|
371
371
|
connect_with_protocol_version_fallback
|
data/lib/cql/client/connector.rb
CHANGED
@@ -24,7 +24,7 @@ module Cql
|
|
24
24
|
connected_connections = connections.select(&:connected?)
|
25
25
|
if connected_connections.empty?
|
26
26
|
e = connections.first.error
|
27
|
-
if e.is_a?(
|
27
|
+
if e.is_a?(QueryError) && e.code == QueryError::BAD_CREDENTIALS
|
28
28
|
e = AuthenticationError.new(e.message)
|
29
29
|
end
|
30
30
|
raise e
|
@@ -150,7 +150,13 @@ module Cql
|
|
150
150
|
def execute(*args)
|
151
151
|
connection = @connection_manager.random_connection
|
152
152
|
if connection[self]
|
153
|
-
run(args, connection)
|
153
|
+
f = run(args, connection)
|
154
|
+
f.fallback do |e|
|
155
|
+
raise e unless e.is_a?(QueryError) && e.code == QueryError::UNPREPARED
|
156
|
+
prepare(connection).flat_map do
|
157
|
+
run(args, connection)
|
158
|
+
end
|
159
|
+
end
|
154
160
|
else
|
155
161
|
prepare(connection).flat_map do
|
156
162
|
run(args, connection)
|
@@ -216,11 +222,12 @@ module Cql
|
|
216
222
|
private
|
217
223
|
|
218
224
|
def run(args, connection)
|
219
|
-
bound_args = args.
|
220
|
-
|
225
|
+
bound_args = args.take(@raw_metadata.size)
|
226
|
+
remaining_args = args.drop(@raw_metadata.size)
|
227
|
+
unless bound_args.size == @raw_metadata.size && remaining_args.size <= 1
|
221
228
|
raise ArgumentError, "Expected #{@raw_metadata.size} arguments, got #{bound_args.size}"
|
222
229
|
end
|
223
|
-
options = @execute_options_decoder.decode_options(
|
230
|
+
options = @execute_options_decoder.decode_options(remaining_args.last)
|
224
231
|
statement_id = connection[self]
|
225
232
|
request_metadata = @raw_result_metadata.nil?
|
226
233
|
request = Protocol::ExecuteRequest.new(statement_id, @raw_metadata, bound_args, request_metadata, options[:consistency], options[:serial_consistency], options[:page_size], options[:paging_state], options[:trace])
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module ErrorCodes
|
5
|
+
# Something unexpected happened. This indicates a server-side bug.
|
6
|
+
SERVER_ERROR = 0x0000
|
7
|
+
|
8
|
+
# Some client message triggered a protocol violation (for instance a QUERY
|
9
|
+
# message is sent before a STARTUP one has been sent).
|
10
|
+
PROTOCOL_ERROR = 0x000A
|
11
|
+
|
12
|
+
# CREDENTIALS request failed because Cassandra did not accept the provided credentials.
|
13
|
+
BAD_CREDENTIALS = 0x0100
|
14
|
+
|
15
|
+
# Unavailable exception.
|
16
|
+
#
|
17
|
+
# Details:
|
18
|
+
#
|
19
|
+
# * `:cl` - The consistency level of the query having triggered the exception.
|
20
|
+
# * `:required` - An int representing the number of nodes that should be alive to respect `:cl`.
|
21
|
+
# * `:alive` - An int representing the number of replica that were known to be
|
22
|
+
# alive when the request has been processed (since an unavailable
|
23
|
+
# exception has been triggered, there will be `:alive` < `:required`.
|
24
|
+
UNAVAILABLE = 0x1000
|
25
|
+
|
26
|
+
# The request cannot be processed because the coordinator node is overloaded.
|
27
|
+
OVERLOADED = 0x1001
|
28
|
+
|
29
|
+
# The request was a read request but the coordinator node is bootstrapping.
|
30
|
+
IS_BOOTSTRAPPING = 0x1002
|
31
|
+
|
32
|
+
# Error during a truncation error.
|
33
|
+
TRUNCATE_ERROR = 0x1003
|
34
|
+
|
35
|
+
# Timeout exception during a write request.
|
36
|
+
#
|
37
|
+
# Details:
|
38
|
+
#
|
39
|
+
# * `:cl` - The consistency level of the query having triggered the exception.
|
40
|
+
# * `:received` - An int representing the number of nodes having acknowledged the request.
|
41
|
+
# * `:blockfor` - The number of replica whose acknowledgement is required to achieve `:cl`.
|
42
|
+
# * `:write_type` - A string that describe the type of the write that timeouted. The value of that string can be one of:
|
43
|
+
# - `"SIMPLE"`: the write was a non-batched non-counter write.
|
44
|
+
# - `"BATCH"`: the write was a (logged) batch write. If this type is received, it means the batch log
|
45
|
+
# has been successfully written (otherwise a `"BATCH_LOG"` type would have been send instead).
|
46
|
+
# - `"UNLOGGED_BATCH"`: the write was an unlogged batch. Not batch log write has been attempted.
|
47
|
+
# - `"COUNTER"`: the write was a counter write (batched or not).
|
48
|
+
# - `"BATCH_LOG"`: the timeout occured during the write to the batch log when a (logged) batch write was requested.
|
49
|
+
WRITE_TIMEOUT = 0x1100
|
50
|
+
|
51
|
+
# Timeout exception during a read request.
|
52
|
+
#
|
53
|
+
# Details:
|
54
|
+
#
|
55
|
+
# * `:cl` - The consistency level of the query having triggered the exception
|
56
|
+
# * `:received` - An int representing the number of nodes having answered the request.
|
57
|
+
# * `:blockfor` - The number of replica whose response is required to achieve `:cl`.
|
58
|
+
# Please note that it is possible to have `:received` >= `:blockfor` if
|
59
|
+
# `:data_present` is false. And also in the (unlikely) case were `:cl` is
|
60
|
+
# achieved but the coordinator node timeout while waiting for read-repair
|
61
|
+
# acknowledgement.
|
62
|
+
# * `:data_present` - If `true`, it means the replica that was asked for data has not responded.
|
63
|
+
READ_TIMEOUT = 0x1200
|
64
|
+
|
65
|
+
# The submitted query has a syntax error.
|
66
|
+
SYNTAX_ERROR = 0x2000
|
67
|
+
|
68
|
+
# The logged user doesn't have the right to perform the query.
|
69
|
+
UNAUTHORIZED = 0x2100
|
70
|
+
|
71
|
+
# The query is syntactically correct but invalid.
|
72
|
+
INVALID = 0x2200
|
73
|
+
|
74
|
+
# The query is invalid because of some configuration issue.
|
75
|
+
CONFIG_ERROR = 0x2300
|
76
|
+
|
77
|
+
# The query attempted to create a keyspace or a table that was already existing.
|
78
|
+
#
|
79
|
+
# Details:
|
80
|
+
#
|
81
|
+
# * `:ks` - A string representing either the keyspace that already exists, or the
|
82
|
+
# keyspace in which the table that already exists is.
|
83
|
+
# * `:table` - A string representing the name of the table that already exists. If the
|
84
|
+
# query was attempting to create a keyspace, `:table` will be present but
|
85
|
+
# will be the empty string.
|
86
|
+
ALREADY_EXISTS = 0x2400
|
87
|
+
|
88
|
+
# Can be thrown while a prepared statement tries to be executed if the
|
89
|
+
# provide prepared statement ID is not known by this host.
|
90
|
+
#
|
91
|
+
# Details:
|
92
|
+
#
|
93
|
+
# * `:id` - The unknown ID.
|
94
|
+
UNPREPARED = 0x2500
|
95
|
+
end
|
96
|
+
end
|
@@ -13,24 +13,24 @@ module Cql
|
|
13
13
|
def self.decode(code, message, protocol_version, buffer, length, trace_id=nil)
|
14
14
|
details = {}
|
15
15
|
case code
|
16
|
-
when
|
16
|
+
when UNAVAILABLE
|
17
17
|
details[:cl] = buffer.read_consistency
|
18
18
|
details[:required] = buffer.read_int
|
19
19
|
details[:alive] = buffer.read_int
|
20
|
-
when
|
20
|
+
when WRITE_TIMEOUT
|
21
21
|
details[:cl] = buffer.read_consistency
|
22
22
|
details[:received] = buffer.read_int
|
23
23
|
details[:blockfor] = buffer.read_int
|
24
24
|
details[:write_type] = buffer.read_string
|
25
|
-
when
|
25
|
+
when READ_TIMEOUT
|
26
26
|
details[:cl] = buffer.read_consistency
|
27
27
|
details[:received] = buffer.read_int
|
28
28
|
details[:blockfor] = buffer.read_int
|
29
29
|
details[:data_present] = buffer.read_byte != 0
|
30
|
-
when
|
30
|
+
when ALREADY_EXISTS
|
31
31
|
details[:ks] = buffer.read_string
|
32
32
|
details[:table] = buffer.read_string
|
33
|
-
when
|
33
|
+
when UNPREPARED
|
34
34
|
details[:id] = buffer.read_short_bytes
|
35
35
|
end
|
36
36
|
new(code, message, details)
|
@@ -3,6 +3,8 @@
|
|
3
3
|
module Cql
|
4
4
|
module Protocol
|
5
5
|
class ErrorResponse < Response
|
6
|
+
include ErrorCodes
|
7
|
+
|
6
8
|
attr_reader :code, :message
|
7
9
|
|
8
10
|
def initialize(*args)
|
@@ -13,7 +15,7 @@ module Cql
|
|
13
15
|
code = buffer.read_int
|
14
16
|
message = buffer.read_string
|
15
17
|
case code
|
16
|
-
when
|
18
|
+
when UNAVAILABLE, WRITE_TIMEOUT, READ_TIMEOUT, ALREADY_EXISTS, UNPREPARED
|
17
19
|
new_length = length - 4 - 4 - message.bytesize
|
18
20
|
DetailedErrorResponse.decode(code, message, protocol_version, buffer, new_length)
|
19
21
|
else
|
data/lib/cql/version.rb
CHANGED
@@ -295,6 +295,25 @@ module Cql
|
|
295
295
|
statement.execute(11, 'hello', trace: true).value
|
296
296
|
tracing.should be_true
|
297
297
|
end
|
298
|
+
|
299
|
+
it 'prepares the statement again when it is lost' do
|
300
|
+
prepare_requests = 0
|
301
|
+
connections.each do |c|
|
302
|
+
c[:num_prepare] = 0
|
303
|
+
c.handle_request do |r, t|
|
304
|
+
if r.is_a?(Protocol::ExecuteRequest) && c[:num_prepare] == 1
|
305
|
+
Protocol::ErrorResponse.new(0x2500, 'Unprepared')
|
306
|
+
else
|
307
|
+
if r == Protocol::PrepareRequest.new(cql)
|
308
|
+
c[:num_prepare] += 1
|
309
|
+
end
|
310
|
+
handle_request(c, r, t)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
statement.execute(11, 'hello').value
|
315
|
+
connections.map { |c| c[:num_prepare] }.should include(2)
|
316
|
+
end
|
298
317
|
end
|
299
318
|
|
300
319
|
describe '#batch' do
|
@@ -108,6 +108,13 @@ describe 'A CQL client' do
|
|
108
108
|
counters = result.each_with_object({}) { |row, acc| acc[row['id']] = row['count'] }
|
109
109
|
counters.should eql('foo' => 11, 'bar' => 3)
|
110
110
|
end
|
111
|
+
|
112
|
+
it 'handles altered tables' do
|
113
|
+
result1 = statement.execute('sue')
|
114
|
+
client.execute('ALTER TABLE users ADD password VARCHAR')
|
115
|
+
result2 = statement.execute('sue')
|
116
|
+
result2.to_a.should eql(result1.to_a)
|
117
|
+
end
|
111
118
|
end
|
112
119
|
|
113
120
|
context 'with multiple connections' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cql-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Theo Hultberg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ione
|
@@ -54,6 +54,7 @@ files:
|
|
54
54
|
- lib/cql/compression.rb
|
55
55
|
- lib/cql/compression/lz4_compressor.rb
|
56
56
|
- lib/cql/compression/snappy_compressor.rb
|
57
|
+
- lib/cql/error_codes.rb
|
57
58
|
- lib/cql/protocol.rb
|
58
59
|
- lib/cql/protocol/cql_byte_buffer.rb
|
59
60
|
- lib/cql/protocol/cql_protocol_handler.rb
|