cql-rb 2.0.2 → 2.0.3

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: 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