cql-rb 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: de475cb52182f982ae799799efa2666839c515eb
4
- data.tar.gz: 6d736d939d31b342a732c7e47708b39329cce374
3
+ metadata.gz: e88f9a36365441fa61492560764b32e62d390c77
4
+ data.tar.gz: 19a2ea3a083d33044364d7bed38fe7ba6edb8d28
5
5
  SHA512:
6
- metadata.gz: 087c4fb13f332dd30744a2b7e11a180a23043383b637221895723a9e5cbc9ccf12e56d7fbe30ec95f09d54ce5092338670b46bf1130b815c864b672c13f6b37b
7
- data.tar.gz: 066cb8bb0af5e671443acc12b68b0c6975fcd22da11ec4236299f19ea34d41558bae878f64ebddcb7b1801075df3cfa0b1815de15a728614ed11d3b3313ec49a
6
+ metadata.gz: bae2fb550cae96e4c2451f33a9637094365e351649555b95a09a683454ead2a49cb4d7f3f48b1082848b2647083de3743e3aa6874dc56e34ddddcdd78d7b7c9e
7
+ data.tar.gz: c81ce3639c98d94b6f294ff6e10316251f45b720f533af245f34b745d29f5b4905a34725fd8b378e2aea3ecfc763c011d3cdb38a9c727f52bc5a727f4104e131
@@ -35,7 +35,7 @@ module Cql
35
35
  #
36
36
  # Execute the batch and return the result.
37
37
  #
38
- # @param options [Hash] an options hash or a symbol (as a shortcut for
38
+ # @param [Hash] options an options hash or a symbol (as a shortcut for
39
39
  # specifying the consistency), see {Cql::Client::Client#execute} for
40
40
  # full details about how this value is interpreted.
41
41
  # @raise [Cql::QueryError] raised when there is an error on the server side
@@ -86,33 +86,35 @@ module Cql
86
86
 
87
87
  def execute(options=nil)
88
88
  options = @execute_options_decoder.decode_options(@options, options)
89
- connection = nil
90
- attempts = 0
91
- begin
92
- connection = @connection_manager.random_connection
93
- request = Protocol::BatchRequest.new(BATCH_TYPES[@type], options[:consistency], options[:trace])
94
- @parts.each do |cql_or_statement, *bound_args|
95
- if cql_or_statement.is_a?(String)
96
- type_hints = nil
97
- if bound_args.last.is_a?(Hash) && bound_args.last.include?(:type_hints)
98
- bound_args = bound_args.dup
99
- type_hints = bound_args.pop[:type_hints]
100
- end
101
- request.add_query(cql_or_statement, bound_args, type_hints)
89
+ connection = @connection_manager.random_connection
90
+ request = Protocol::BatchRequest.new(BATCH_TYPES[@type], options[:consistency], options[:trace])
91
+ unprepared_statements = nil
92
+ @parts.each do |part, *bound_args|
93
+ if part.is_a?(String) || part.prepared?(connection)
94
+ add_part(connection, request, part, bound_args)
95
+ else
96
+ unprepared_statements ||= []
97
+ unprepared_statements << [part, bound_args]
98
+ end
99
+ end
100
+ @parts = []
101
+ if unprepared_statements.nil?
102
+ @request_runner.execute(connection, request, options[:timeout])
103
+ else
104
+ fs = unprepared_statements.map do |statement, _|
105
+ if statement.respond_to?(:async)
106
+ statement.async.prepare(connection)
102
107
  else
103
- cql_or_statement.add_to_batch(request, connection, bound_args)
108
+ statement.prepare(connection)
104
109
  end
105
110
  end
106
- rescue NotPreparedError
107
- attempts += 1
108
- if attempts < 3
109
- retry
110
- else
111
- raise
111
+ Future.all(*fs).flat_map do
112
+ unprepared_statements.each do |statement, bound_args|
113
+ add_part(connection, request, statement, bound_args)
114
+ end
115
+ @request_runner.execute(connection, request, options[:timeout])
112
116
  end
113
117
  end
114
- @parts = []
115
- @request_runner.execute(connection, request, options[:timeout])
116
118
  end
117
119
 
118
120
  private
@@ -122,6 +124,19 @@ module Cql
122
124
  :unlogged => Protocol::BatchRequest::UNLOGGED_TYPE,
123
125
  :counter => Protocol::BatchRequest::COUNTER_TYPE,
124
126
  }.freeze
127
+
128
+ def add_part(connection, request, part, bound_args)
129
+ if part.is_a?(String)
130
+ type_hints = nil
131
+ if bound_args.last.is_a?(Hash) && bound_args.last.include?(:type_hints)
132
+ bound_args = bound_args.dup
133
+ type_hints = bound_args.pop[:type_hints]
134
+ end
135
+ request.add_query(part, bound_args, type_hints)
136
+ else
137
+ part.add_to_batch(request, connection, bound_args)
138
+ end
139
+ end
125
140
  end
126
141
 
127
142
  # @private
@@ -196,6 +196,11 @@ module Cql
196
196
  f.map(self)
197
197
  end
198
198
 
199
+ # @private
200
+ def prepared?(connection)
201
+ !!connection[self]
202
+ end
203
+
199
204
  # @private
200
205
  def add_to_batch(batch, connection, bound_args)
201
206
  statement_id = connection[self]
@@ -263,6 +268,11 @@ module Cql
263
268
  @async_statement
264
269
  end
265
270
 
271
+ # @private
272
+ def prepared?(connection)
273
+ @async_statement.prepared?(connection)
274
+ end
275
+
266
276
  # @private
267
277
  def add_to_batch(batch, connection, bound_arguments)
268
278
  @async_statement.add_to_batch(batch, connection, bound_arguments)
@@ -29,7 +29,7 @@ module Cql
29
29
  def read_decimal(len=bytesize)
30
30
  size = read_signed_int
31
31
  number_string = read_varint(len - 4).to_s
32
- if number_string.length < size
32
+ if number_string.length <= size
33
33
  if number_string.start_with?(MINUS)
34
34
  number_string = number_string[1, number_string.length - 1]
35
35
  fraction_string = MINUS + ZERO << DECIMAL_POINT
@@ -251,15 +251,10 @@ module Cql
251
251
  def append_varint(n)
252
252
  num = n
253
253
  bytes = []
254
- if num == 0
255
- bytes << 0
256
- else
257
- until num == 0
258
- bytes << (num & 0xff)
259
- num = num >> 8
260
- break if num == -1
261
- end
262
- end
254
+ begin
255
+ bytes << (num & 0xff)
256
+ num >>= 8
257
+ end until (num == 0 || num == -1) && (bytes.last[7] == num[7])
263
258
  append(bytes.reverse.pack(Formats::BYTES_FORMAT))
264
259
  end
265
260
 
data/lib/cql/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Cql
4
- VERSION = '2.0.2'.freeze
4
+ VERSION = '2.0.3'.freeze
5
5
  end
@@ -64,6 +64,10 @@ module Cql
64
64
  end
65
65
  end
66
66
 
67
+ before do
68
+ prepared_statement.stub(:prepared?).and_return(true)
69
+ end
70
+
67
71
  it 'creates a BATCH request and executes it on a random connection' do
68
72
  batch.execute.value
69
73
  connection.should have_received(:send_request).with(an_instance_of(Protocol::BatchRequest), nil)
@@ -104,22 +108,36 @@ module Cql
104
108
  encoded_frame.to_s.should include(Protocol::QueryRequest.encode_values(Protocol::CqlByteBuffer.new, [3], [:int]))
105
109
  end
106
110
 
107
- it 'tries again when a prepared statement raises NotPreparedError' do
108
- connection1 = double(:connection1)
109
- connection2 = double(:connection2)
110
- connection2.stub(:send_request).and_return(Cql::Future.resolved(Protocol::VoidResultResponse.new(nil)))
111
- connection_manager.stub(:random_connection).and_return(connection1, connection2)
112
- prepared_statement.stub(:add_to_batch).with(anything, connection1, anything).and_raise(NotPreparedError)
113
- prepared_statement.stub(:add_to_batch).with(anything, connection2, anything)
114
- batch.add(prepared_statement, 3, 'foo')
115
- expect { batch.execute.value }.to_not raise_error
116
- end
111
+ context 'when the statement has not been prepared on the selected connection' do
112
+ let :connection do
113
+ double(:connection)
114
+ end
117
115
 
118
- it 'gives up when the prepared statement has raised NotPreparedError three times' do
119
- prepared_statement.stub(:add_to_batch).with(anything, connection, anything).and_raise(NotPreparedError)
120
- batch.add(prepared_statement, 3, 'foo')
121
- expect { batch.execute.value }.to raise_error(NotPreparedError)
122
- prepared_statement.should have_received(:add_to_batch).exactly(3).times
116
+ before do
117
+ connection.stub(:send_request).and_return(Cql::Future.resolved(Protocol::VoidResultResponse.new(nil)))
118
+ connection_manager.stub(:random_connection).and_return(connection)
119
+ prepared_statement.stub(:prepared?).with(connection).and_return(false)
120
+ prepared_statement.stub(:add_to_batch)
121
+ prepared_statement.stub(:prepare) do |c|
122
+ c.should equal(connection), 'expected #prepare to be called with the connection returned by the connection manager'
123
+ prepared_statement.stub(:prepared?).with(connection).and_return(true)
124
+ Future.resolved(prepared_statement)
125
+ end
126
+ end
127
+
128
+ it 'prepares the statement before sending the request' do
129
+ batch.add(prepared_statement, 3, 'foo')
130
+ batch.execute.value.should be_a(VoidResult)
131
+ end
132
+
133
+ it 'supports synchronous prepared statements' do
134
+ synchronous_prepared_statement = double(:synchronous_prepared_statement)
135
+ synchronous_prepared_statement.stub(:async).and_return(prepared_statement)
136
+ synchronous_prepared_statement.stub(:prepared?) { |c| prepared_statement.prepared?(c) }
137
+ synchronous_prepared_statement.stub(:add_to_batch) { |*args| prepared_statement.add_to_batch(*args) }
138
+ batch.add(synchronous_prepared_statement, 3, 'foo')
139
+ batch.execute.value.should be_a(VoidResult)
140
+ end
123
141
  end
124
142
 
125
143
  it 'returns a future that resolves to the response' do
@@ -81,6 +81,11 @@ module Cql
81
81
  buffer.read_decimal.should == BigDecimal.new('-0.0012095473475870063')
82
82
  end
83
83
 
84
+ it 'decodes a small negative decimal' do
85
+ buffer = described_class.new("\x00\x00\x00\x12\x91z\xE1\xAF\x06c\x5A")
86
+ buffer.read_decimal.should == BigDecimal.new('-0.031108612692221094')
87
+ end
88
+
84
89
  it 'consumes the bytes' do
85
90
  buffer << 'HELLO'
86
91
  buffer.read_decimal(buffer.length - 5)
@@ -815,6 +820,16 @@ module Cql
815
820
  buffer.should eql_bytes("\x00")
816
821
  end
817
822
 
823
+ it 'encodes with zero padding when number is positive and sign bit is on' do
824
+ buffer.append_varint(128)
825
+ buffer.should eql_bytes("\x00\x80")
826
+ end
827
+
828
+ it 'encodes without zero padding when number is negative and sign bit is on' do
829
+ buffer.append_varint(-128)
830
+ buffer.should eql_bytes("\x80")
831
+ end
832
+
818
833
  it 'encodes a variable length integer' do
819
834
  buffer.append_varint(1231312312331283012830129382342342412123)
820
835
  buffer.should eql_bytes("\x03\x9EV \x15\f\x03\x9DK\x18\xCDI\\$?\a[")
@@ -825,6 +840,11 @@ module Cql
825
840
  buffer.should eql_bytes("\xC9v\x8D:\x86")
826
841
  end
827
842
 
843
+ it 'encodes a small negative variable length integer' do
844
+ buffer.append_varint(-39911)
845
+ buffer.should eql_bytes("\xFFd\x19")
846
+ end
847
+
828
848
  it 'encodes a negative variable length integer' do
829
849
  buffer.append_varint(-1)
830
850
  buffer.should eql_bytes("\xff")
@@ -863,6 +883,11 @@ module Cql
863
883
  buffer.should eql_bytes("\x00\x00\x00\x01\x01\xD4\xC0")
864
884
  end
865
885
 
886
+ it 'encodes a BigDecimal with zero padding when sign bit is on' do
887
+ buffer.append_decimal(BigDecimal.new('25.0'))
888
+ buffer.should eql_bytes("\x00\x00\x00\x01\x00\xFA")
889
+ end
890
+
866
891
  it 'appends to the buffer' do
867
892
  buffer << "\x99"
868
893
  buffer.append_decimal(BigDecimal.new('1042342234234.123423435647768234'))
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.2
4
+ version: 2.0.3
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-07-04 00:00:00.000000000 Z
11
+ date: 2014-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ione