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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad8c87f3d7ccc81d5b43765b4702882db21aab6f
4
- data.tar.gz: c997140f2444a259a62c79a90118f7a1d634b3d1
3
+ metadata.gz: 076ceeab9f5eff0e9ab577f1e433b087342a8457
4
+ data.tar.gz: 049f3ecd2f935016bdd4bb08a87648163609600b
5
5
  SHA512:
6
- metadata.gz: d409efa148092c538432f7d7ad0aa19dfd72370e1596415c5a69a8bb7a9918d0a5ca674f29a24115aa7cc62945c41ac8278f87540bd5e20becaabcf5039cfc44
7
- data.tar.gz: ee05afbf07ba5453e50bdaffe3a3c761a4419285fb8132d2241b334e32c9f25ee4da2f527b100d6f58a0c3fcbd4f6b56de9de873d2a9bac54dc0486d5c1c4c6e
6
+ metadata.gz: e08c27d6a73bd4fc11573958ae2216affc238180d90d92c32aee98b20103a8614e6c1b693845b000c465b4ba9fd04b25c45a9ba012535a91e635974d832c66e5
7
+ data.tar.gz: 0e897851f1dab23f7eaa7ac1380071f4fa2bf0511a16911a5976156d197a533ba83b0fc05a2ee925050b9bc8b96f3ebf31a937158eddd222503b6e68c5343a7d
data/lib/cql.rb CHANGED
@@ -17,6 +17,7 @@ module Cql
17
17
  Io = Ione::Io
18
18
  end
19
19
 
20
+ require 'cql/error_codes'
20
21
  require 'cql/uuid'
21
22
  require 'cql/time_uuid'
22
23
  require 'cql/compression'
@@ -6,6 +6,8 @@ module Cql
6
6
  # if any. `message` contains the human readable error message sent by the
7
7
  # server.
8
8
  class QueryError < CqlError
9
+ include ErrorCodes
10
+
9
11
  attr_reader :code, :cql, :details
10
12
 
11
13
  def initialize(code, message, cql=nil, details=nil)
@@ -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 == 0x0a && @protocol_version > 1
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
@@ -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?(Cql::QueryError) && e.code == 0x100
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.shift(@raw_metadata.size)
220
- unless bound_args.size == @raw_metadata.size && args.size <= 1
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(args.last)
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 0x1000 # unavailable
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 0x1100 # write_timeout
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 0x1200 # read_timeout
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 0x2400 # already_exists
30
+ when ALREADY_EXISTS
31
31
  details[:ks] = buffer.read_string
32
32
  details[:table] = buffer.read_string
33
- when 0x2500
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 0x1000, 0x1100, 0x1200, 0x2400, 0x2500
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
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Cql
4
- VERSION = '2.0.4'.freeze
4
+ VERSION = '2.0.5'.freeze
5
5
  end
@@ -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
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: 2014-10-26 00:00:00.000000000 Z
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