cql-rb 2.0.4 → 2.0.5
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/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
|