cql-rb 1.0.6 → 1.1.0.pre0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +4 -9
- data/lib/cql.rb +1 -0
- data/lib/cql/byte_buffer.rb +23 -7
- data/lib/cql/client.rb +11 -6
- data/lib/cql/client/asynchronous_client.rb +37 -83
- data/lib/cql/client/asynchronous_prepared_statement.rb +10 -4
- data/lib/cql/client/column_metadata.rb +16 -0
- data/lib/cql/client/request_runner.rb +46 -0
- data/lib/cql/future.rb +4 -5
- data/lib/cql/io.rb +2 -5
- data/lib/cql/io/connection.rb +220 -0
- data/lib/cql/io/io_reactor.rb +213 -185
- data/lib/cql/protocol.rb +1 -0
- data/lib/cql/protocol/cql_protocol_handler.rb +201 -0
- data/lib/cql/protocol/decoding.rb +6 -31
- data/lib/cql/protocol/encoding.rb +1 -5
- data/lib/cql/protocol/request.rb +4 -0
- data/lib/cql/protocol/responses/schema_change_result_response.rb +15 -0
- data/lib/cql/protocol/type_converter.rb +56 -76
- data/lib/cql/time_uuid.rb +104 -0
- data/lib/cql/uuid.rb +4 -2
- data/lib/cql/version.rb +1 -1
- data/spec/cql/client/asynchronous_client_spec.rb +47 -71
- data/spec/cql/client/asynchronous_prepared_statement_spec.rb +68 -0
- data/spec/cql/client/client_shared.rb +3 -3
- data/spec/cql/client/column_metadata_spec.rb +80 -0
- data/spec/cql/client/request_runner_spec.rb +120 -0
- data/spec/cql/future_spec.rb +26 -11
- data/spec/cql/io/connection_spec.rb +460 -0
- data/spec/cql/io/io_reactor_spec.rb +212 -265
- data/spec/cql/protocol/cql_protocol_handler_spec.rb +216 -0
- data/spec/cql/protocol/decoding_spec.rb +9 -28
- data/spec/cql/protocol/encoding_spec.rb +0 -5
- data/spec/cql/protocol/request_spec.rb +16 -0
- data/spec/cql/protocol/response_frame_spec.rb +2 -2
- data/spec/cql/protocol/responses/schema_change_result_response_spec.rb +70 -0
- data/spec/cql/time_uuid_spec.rb +136 -0
- data/spec/cql/uuid_spec.rb +1 -5
- data/spec/integration/client_spec.rb +34 -38
- data/spec/integration/io_spec.rb +283 -0
- data/spec/integration/protocol_spec.rb +53 -113
- data/spec/integration/regression_spec.rb +124 -0
- data/spec/integration/uuid_spec.rb +76 -0
- data/spec/spec_helper.rb +12 -9
- data/spec/support/fake_io_reactor.rb +52 -21
- data/spec/support/fake_server.rb +2 -2
- metadata +33 -10
- checksums.yaml +0 -15
- data/lib/cql/io/node_connection.rb +0 -209
- data/spec/cql/protocol/type_converter_spec.rb +0 -52
data/lib/cql/protocol.rb
CHANGED
@@ -0,0 +1,201 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
# This class wraps a single connection and translates between request/
|
6
|
+
# response frames and raw bytes.
|
7
|
+
#
|
8
|
+
# You send requests with #send_request, and receive responses through the
|
9
|
+
# returned future.
|
10
|
+
#
|
11
|
+
# Instances of this class are thread safe.
|
12
|
+
#
|
13
|
+
# @examle Sending an OPTIONS request
|
14
|
+
# future = protocol_handler.send_request(Cql::Protocol::OptionsRequest.new)
|
15
|
+
# response = future.get
|
16
|
+
# puts "These options are supported: #{response.options}"
|
17
|
+
#
|
18
|
+
class CqlProtocolHandler
|
19
|
+
# @return [String] the current keyspace for the underlying connection
|
20
|
+
attr_reader :keyspace
|
21
|
+
|
22
|
+
def initialize(connection)
|
23
|
+
@connection = connection
|
24
|
+
@connection.on_data(&method(:receive_data))
|
25
|
+
@connection.on_closed(&method(:socket_closed))
|
26
|
+
@responses = Array.new(128) { nil }
|
27
|
+
@read_buffer = ByteBuffer.new
|
28
|
+
@current_frame = Protocol::ResponseFrame.new(@read_buffer)
|
29
|
+
@request_queue_in = []
|
30
|
+
@request_queue_out = []
|
31
|
+
@event_listeners = []
|
32
|
+
@lock = Mutex.new
|
33
|
+
@closed_future = Future.new
|
34
|
+
@keyspace = nil
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [true, false] true if the underlying connection is connected
|
38
|
+
def connected?
|
39
|
+
@connection.connected?
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [true, false] true if the underlying connection is closed
|
43
|
+
def closed?
|
44
|
+
@connection.closed?
|
45
|
+
end
|
46
|
+
|
47
|
+
# Register to receive notification when the underlying connection has
|
48
|
+
# closed. If the connection closed abruptly the error will be passed
|
49
|
+
# to the listener, otherwise it will not receive any parameters.
|
50
|
+
#
|
51
|
+
# @yieldparam error [nil, Error] the error that caused the connection to
|
52
|
+
# close, if any
|
53
|
+
def on_closed(&listener)
|
54
|
+
@closed_future.on_complete(&listener)
|
55
|
+
@closed_future.on_failure(&listener)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Register to receive server sent events, like schema changes, nodes going
|
59
|
+
# up or down, etc. To actually receive events you also need to send a
|
60
|
+
# REGISTER request for the events you wish to receive.
|
61
|
+
#
|
62
|
+
# @yieldparam event [Cql::Protocol::EventResponse] an event sent by the server
|
63
|
+
def on_event(&listener)
|
64
|
+
@lock.synchronize do
|
65
|
+
@event_listeners << listener
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Serializes and send a request over the underlying connection.
|
70
|
+
#
|
71
|
+
# Returns a future that will resolve to the response. When the connection
|
72
|
+
# closes the futures of all active requests will be failed with the error
|
73
|
+
# that caused the connection to close, or nil
|
74
|
+
#
|
75
|
+
# @return [Cql::Future<Cql::Protocol::Response>] a future that resolves to
|
76
|
+
# the response
|
77
|
+
def send_request(request)
|
78
|
+
return Future.failed(NotConnectedError.new) if closed?
|
79
|
+
future = Future.new
|
80
|
+
id = nil
|
81
|
+
@lock.synchronize do
|
82
|
+
if (id = next_stream_id)
|
83
|
+
@responses[id] = future
|
84
|
+
end
|
85
|
+
end
|
86
|
+
if id
|
87
|
+
@connection.write do |buffer|
|
88
|
+
request.encode_frame(id, buffer)
|
89
|
+
end
|
90
|
+
else
|
91
|
+
@lock.synchronize do
|
92
|
+
@request_queue_in << [request.encode_frame(0), future]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
future
|
96
|
+
end
|
97
|
+
|
98
|
+
# Closes the underlying connection.
|
99
|
+
#
|
100
|
+
# @return [Cql::Future] a future that completes when the connection has closed
|
101
|
+
def close
|
102
|
+
@connection.close
|
103
|
+
@closed_future
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def receive_data(data)
|
109
|
+
@current_frame << data
|
110
|
+
while @current_frame.complete?
|
111
|
+
id = @current_frame.stream_id
|
112
|
+
if id == -1
|
113
|
+
notify_event_listeners(@current_frame.body)
|
114
|
+
else
|
115
|
+
complete_request(id, @current_frame.body)
|
116
|
+
end
|
117
|
+
@current_frame = Protocol::ResponseFrame.new(@read_buffer)
|
118
|
+
flush_request_queue
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def notify_event_listeners(event_response)
|
123
|
+
return if @event_listeners.empty?
|
124
|
+
@lock.synchronize do
|
125
|
+
@event_listeners.each do |listener|
|
126
|
+
listener.call(@current_frame.body) rescue nil
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def complete_request(id, response)
|
132
|
+
future = @lock.synchronize do
|
133
|
+
future = @responses[id]
|
134
|
+
@responses[id] = nil
|
135
|
+
future
|
136
|
+
end
|
137
|
+
if response.is_a?(Protocol::SetKeyspaceResultResponse)
|
138
|
+
@keyspace = response.keyspace
|
139
|
+
end
|
140
|
+
future.complete!(response)
|
141
|
+
end
|
142
|
+
|
143
|
+
def flush_request_queue
|
144
|
+
@lock.synchronize do
|
145
|
+
if @request_queue_out.empty? && !@request_queue_in.empty?
|
146
|
+
@request_queue_out = @request_queue_in
|
147
|
+
@request_queue_in = []
|
148
|
+
end
|
149
|
+
end
|
150
|
+
while true
|
151
|
+
id = nil
|
152
|
+
request_buffer = nil
|
153
|
+
@lock.synchronize do
|
154
|
+
if @request_queue_out.any? && (id = next_stream_id)
|
155
|
+
request_buffer, future = @request_queue_out.shift
|
156
|
+
@responses[id] = future
|
157
|
+
end
|
158
|
+
end
|
159
|
+
if id
|
160
|
+
Protocol::Request.change_stream_id(id, request_buffer)
|
161
|
+
@connection.write(request_buffer)
|
162
|
+
else
|
163
|
+
break
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def socket_closed(cause)
|
169
|
+
request_failure_cause = cause || Io::ConnectionClosedError.new
|
170
|
+
@lock.synchronize do
|
171
|
+
@responses.each_with_index do |future, i|
|
172
|
+
if future
|
173
|
+
@responses[i].fail!(request_failure_cause)
|
174
|
+
@responses[i] = nil
|
175
|
+
end
|
176
|
+
end
|
177
|
+
@request_queue_in.each do |_, future|
|
178
|
+
future.fail!(request_failure_cause)
|
179
|
+
end
|
180
|
+
@request_queue_in.clear
|
181
|
+
@request_queue_out.each do |_, future|
|
182
|
+
future.fail!(request_failure_cause)
|
183
|
+
end
|
184
|
+
@request_queue_out.clear
|
185
|
+
if cause
|
186
|
+
@closed_future.fail!(cause)
|
187
|
+
else
|
188
|
+
@closed_future.complete!
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def next_stream_id
|
194
|
+
@responses.each_with_index do |task, index|
|
195
|
+
return index if task.nil?
|
196
|
+
end
|
197
|
+
nil
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -31,34 +31,15 @@ module Cql
|
|
31
31
|
def read_decimal!(buffer, length=buffer.length)
|
32
32
|
size = read_int!(buffer)
|
33
33
|
number_string = read_varint!(buffer, length - 4).to_s
|
34
|
-
|
35
|
-
if number_string.start_with?(MINUS)
|
36
|
-
number_string = number_string[1, number_string.length - 1]
|
37
|
-
fraction_string = MINUS + ZERO << DECIMAL_POINT
|
38
|
-
else
|
39
|
-
fraction_string = ZERO + DECIMAL_POINT
|
40
|
-
end
|
41
|
-
(size - number_string.length).times { fraction_string << ZERO }
|
42
|
-
fraction_string << number_string
|
43
|
-
else
|
44
|
-
fraction_string = number_string[0, number_string.length - size]
|
45
|
-
fraction_string << DECIMAL_POINT
|
46
|
-
fraction_string << number_string[number_string.length - size, number_string.length]
|
47
|
-
end
|
34
|
+
fraction_string = number_string[0, number_string.length - size] << DECIMAL_POINT << number_string[number_string.length - size, number_string.length]
|
48
35
|
BigDecimal.new(fraction_string)
|
49
36
|
rescue RangeError => e
|
50
37
|
raise DecodingError, e.message, e.backtrace
|
51
38
|
end
|
52
39
|
|
53
40
|
def read_long!(buffer)
|
54
|
-
|
55
|
-
|
56
|
-
hi ^= 0xffffffff
|
57
|
-
lo ^= 0xffffffff
|
58
|
-
0 - (hi << 32) - lo - 1
|
59
|
-
else
|
60
|
-
(hi << 32) + lo
|
61
|
-
end
|
41
|
+
top, bottom = buffer.read(8).unpack(Formats::TWO_INTS_FORMAT)
|
42
|
+
(top << 32) | bottom
|
62
43
|
rescue RangeError => e
|
63
44
|
raise DecodingError, e.message, e.backtrace
|
64
45
|
end
|
@@ -76,11 +57,7 @@ module Cql
|
|
76
57
|
end
|
77
58
|
|
78
59
|
def read_int!(buffer)
|
79
|
-
|
80
|
-
if (val > 0x7fffffff)
|
81
|
-
val = 0 - ((val - 1) ^ 0xffffffff)
|
82
|
-
end
|
83
|
-
val
|
60
|
+
buffer.read_int
|
84
61
|
rescue RangeError => e
|
85
62
|
raise DecodingError, "Not enough bytes available to decode an int: #{e.message}", e.backtrace
|
86
63
|
end
|
@@ -109,8 +86,8 @@ module Cql
|
|
109
86
|
raise DecodingError, "Not enough bytes available to decode a long string: #{e.message}", e.backtrace
|
110
87
|
end
|
111
88
|
|
112
|
-
def read_uuid!(buffer)
|
113
|
-
|
89
|
+
def read_uuid!(buffer, impl=Uuid)
|
90
|
+
impl.new(read_varint!(buffer, 16, false))
|
114
91
|
rescue RangeError => e
|
115
92
|
raise DecodingError, "Not enough bytes available to decode a UUID: #{e.message}", e.backtrace
|
116
93
|
end
|
@@ -184,8 +161,6 @@ module Cql
|
|
184
161
|
|
185
162
|
private
|
186
163
|
|
187
|
-
MINUS = '-'.freeze
|
188
|
-
ZERO = '0'.freeze
|
189
164
|
DECIMAL_POINT = '.'.freeze
|
190
165
|
end
|
191
166
|
end
|
@@ -27,11 +27,7 @@ module Cql
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def write_uuid(buffer, uuid)
|
30
|
-
|
31
|
-
write_int(buffer, (v >> 96) & 0xffffffff)
|
32
|
-
write_int(buffer, (v >> 64) & 0xffffffff)
|
33
|
-
write_int(buffer, (v >> 32) & 0xffffffff)
|
34
|
-
write_int(buffer, v & 0xffffffff)
|
30
|
+
write_varint(buffer, uuid.value)
|
35
31
|
end
|
36
32
|
|
37
33
|
def write_string_list(buffer, strs)
|
data/lib/cql/protocol/request.rb
CHANGED
@@ -19,6 +19,10 @@ module Cql
|
|
19
19
|
buffer.update(offset + 4, [(buffer.bytesize - offset - 8)].pack(Formats::INT_FORMAT))
|
20
20
|
buffer
|
21
21
|
end
|
22
|
+
|
23
|
+
def self.change_stream_id(new_stream_id, buffer, offset=0)
|
24
|
+
buffer.update(offset + 2, new_stream_id.chr)
|
25
|
+
end
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
@@ -13,6 +13,21 @@ module Cql
|
|
13
13
|
new(read_string!(buffer), read_string!(buffer), read_string!(buffer))
|
14
14
|
end
|
15
15
|
|
16
|
+
def eql?(other)
|
17
|
+
self.change == other.change && self.keyspace == other.keyspace && self.table == other.table
|
18
|
+
end
|
19
|
+
alias_method :==, :eql?
|
20
|
+
|
21
|
+
def hash
|
22
|
+
@h ||= begin
|
23
|
+
h = 0
|
24
|
+
h = ((h & 0xffffffff) * 31) ^ @change.hash
|
25
|
+
h = ((h & 0xffffffff) * 31) ^ @keyspace.hash
|
26
|
+
h = ((h & 0xffffffff) * 31) ^ @table.hash
|
27
|
+
h
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
16
31
|
def to_s
|
17
32
|
%(RESULT SCHEMA_CHANGE #@change "#@keyspace" "#@table")
|
18
33
|
end
|
@@ -36,35 +36,27 @@ module Cql
|
|
36
36
|
def to_bytes(io, type, value, size_bytes=4)
|
37
37
|
case type
|
38
38
|
when Array
|
39
|
-
unless value.
|
39
|
+
unless value.is_a?(Enumerable)
|
40
40
|
raise InvalidValueError, 'Value for collection must be enumerable'
|
41
41
|
end
|
42
42
|
case type.first
|
43
43
|
when :list, :set
|
44
44
|
_, sub_type = type
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
to_bytes(raw, sub_type, element, 2)
|
50
|
-
end
|
51
|
-
write_bytes(io, raw)
|
52
|
-
else
|
53
|
-
nil_to_bytes(io, size_bytes)
|
45
|
+
raw = ''
|
46
|
+
write_short(raw, value.size)
|
47
|
+
value.each do |element|
|
48
|
+
to_bytes(raw, sub_type, element, 2)
|
54
49
|
end
|
50
|
+
write_bytes(io, raw)
|
55
51
|
when :map
|
56
52
|
_, key_type, value_type = type
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
to_bytes(raw, value_type, value, 2)
|
63
|
-
end
|
64
|
-
write_bytes(io, raw)
|
65
|
-
else
|
66
|
-
nil_to_bytes(io, size_bytes)
|
53
|
+
raw = ''
|
54
|
+
write_short(raw, value.size)
|
55
|
+
value.each do |key, value|
|
56
|
+
to_bytes(raw, key_type, key, 2)
|
57
|
+
to_bytes(raw, value_type, value, 2)
|
67
58
|
end
|
59
|
+
write_bytes(io, raw)
|
68
60
|
else
|
69
61
|
raise UnsupportedColumnTypeError, %(Unsupported column collection type: #{type.first})
|
70
62
|
end
|
@@ -96,7 +88,7 @@ module Cql
|
|
96
88
|
:varchar => method(:bytes_to_varchar),
|
97
89
|
:text => method(:bytes_to_varchar),
|
98
90
|
:varint => method(:bytes_to_varint),
|
99
|
-
:timeuuid => method(:
|
91
|
+
:timeuuid => method(:bytes_to_timeuuid),
|
100
92
|
:uuid => method(:bytes_to_uuid),
|
101
93
|
:inet => method(:bytes_to_inet),
|
102
94
|
}
|
@@ -108,7 +100,6 @@ module Cql
|
|
108
100
|
:bigint => method(:bigint_to_bytes),
|
109
101
|
:blob => method(:blob_to_bytes),
|
110
102
|
:boolean => method(:boolean_to_bytes),
|
111
|
-
:counter => method(:bigint_to_bytes),
|
112
103
|
:decimal => method(:decimal_to_bytes),
|
113
104
|
:double => method(:double_to_bytes),
|
114
105
|
:float => method(:float_to_bytes),
|
@@ -197,6 +188,11 @@ module Cql
|
|
197
188
|
read_uuid!(buffer)
|
198
189
|
end
|
199
190
|
|
191
|
+
def bytes_to_timeuuid(buffer, size_bytes)
|
192
|
+
return nil unless read_size(buffer, size_bytes)
|
193
|
+
read_uuid!(buffer, TimeUuid)
|
194
|
+
end
|
195
|
+
|
200
196
|
def bytes_to_inet(buffer, size_bytes)
|
201
197
|
size = read_size(buffer, size_bytes)
|
202
198
|
return nil unless size
|
@@ -233,7 +229,7 @@ module Cql
|
|
233
229
|
end
|
234
230
|
|
235
231
|
def ascii_to_bytes(io, value, size_bytes)
|
236
|
-
v = value
|
232
|
+
v = value.encode(::Encoding::ASCII)
|
237
233
|
if size_bytes == 4
|
238
234
|
write_bytes(io, v)
|
239
235
|
else
|
@@ -242,16 +238,16 @@ module Cql
|
|
242
238
|
end
|
243
239
|
|
244
240
|
def bigint_to_bytes(io, value, size_bytes)
|
245
|
-
if
|
246
|
-
|
247
|
-
write_long(io, value)
|
241
|
+
if size_bytes == 4
|
242
|
+
write_int(io, 8)
|
248
243
|
else
|
249
|
-
|
244
|
+
write_short(io, 8)
|
250
245
|
end
|
246
|
+
write_long(io, value)
|
251
247
|
end
|
252
248
|
|
253
249
|
def blob_to_bytes(io, value, size_bytes)
|
254
|
-
v = value
|
250
|
+
v = value.encode(::Encoding::BINARY)
|
255
251
|
if size_bytes == 4
|
256
252
|
write_bytes(io, v)
|
257
253
|
else
|
@@ -260,16 +256,16 @@ module Cql
|
|
260
256
|
end
|
261
257
|
|
262
258
|
def boolean_to_bytes(io, value, size_bytes)
|
263
|
-
if
|
264
|
-
|
265
|
-
io << (value ? Constants::TRUE_BYTE : Constants::FALSE_BYTE)
|
259
|
+
if size_bytes == 4
|
260
|
+
write_int(io, 1)
|
266
261
|
else
|
267
|
-
|
262
|
+
write_short(io, 1)
|
268
263
|
end
|
264
|
+
io << (value ? Constants::TRUE_BYTE : Constants::FALSE_BYTE)
|
269
265
|
end
|
270
266
|
|
271
267
|
def decimal_to_bytes(io, value, size_bytes)
|
272
|
-
raw =
|
268
|
+
raw = write_decimal('', value)
|
273
269
|
if size_bytes == 4
|
274
270
|
write_bytes(io, raw)
|
275
271
|
else
|
@@ -278,43 +274,43 @@ module Cql
|
|
278
274
|
end
|
279
275
|
|
280
276
|
def double_to_bytes(io, value, size_bytes)
|
281
|
-
if
|
282
|
-
|
283
|
-
write_double(io, value)
|
277
|
+
if size_bytes == 4
|
278
|
+
write_int(io, 8)
|
284
279
|
else
|
285
|
-
|
280
|
+
write_short(io, 8)
|
286
281
|
end
|
282
|
+
write_double(io, value)
|
287
283
|
end
|
288
284
|
|
289
285
|
def float_to_bytes(io, value, size_bytes)
|
290
|
-
if
|
291
|
-
|
292
|
-
write_float(io, value)
|
286
|
+
if size_bytes == 4
|
287
|
+
write_int(io, 4)
|
293
288
|
else
|
294
|
-
|
289
|
+
write_short(io, 4)
|
295
290
|
end
|
291
|
+
write_float(io, value)
|
296
292
|
end
|
297
293
|
|
298
294
|
def inet_to_bytes(io, value, size_bytes)
|
299
|
-
if
|
300
|
-
|
301
|
-
io << value.hton
|
295
|
+
if size_bytes == 4
|
296
|
+
write_int(io, value.ipv6? ? 16 : 4)
|
302
297
|
else
|
303
|
-
|
298
|
+
write_short(io, value.ipv6? ? 16 : 4)
|
304
299
|
end
|
300
|
+
io << value.hton
|
305
301
|
end
|
306
302
|
|
307
303
|
def int_to_bytes(io, value, size_bytes)
|
308
|
-
if
|
309
|
-
|
310
|
-
write_int(io, value)
|
304
|
+
if size_bytes == 4
|
305
|
+
write_int(io, 4)
|
311
306
|
else
|
312
|
-
|
307
|
+
write_short(io, 4)
|
313
308
|
end
|
309
|
+
write_int(io, value)
|
314
310
|
end
|
315
311
|
|
316
312
|
def varchar_to_bytes(io, value, size_bytes)
|
317
|
-
v = value
|
313
|
+
v = value.encode(::Encoding::UTF_8)
|
318
314
|
if size_bytes == 4
|
319
315
|
write_bytes(io, v)
|
320
316
|
else
|
@@ -323,48 +319,32 @@ module Cql
|
|
323
319
|
end
|
324
320
|
|
325
321
|
def timestamp_to_bytes(io, value, size_bytes)
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
write_long(io, ms)
|
322
|
+
ms = (value.to_f * 1000).to_i
|
323
|
+
if size_bytes == 4
|
324
|
+
write_int(io, 8)
|
330
325
|
else
|
331
|
-
|
326
|
+
write_short(io, 8)
|
332
327
|
end
|
328
|
+
write_long(io, ms)
|
333
329
|
end
|
334
330
|
|
335
331
|
def uuid_to_bytes(io, value, size_bytes)
|
336
|
-
if
|
337
|
-
|
338
|
-
write_uuid(io, value)
|
332
|
+
if size_bytes == 4
|
333
|
+
write_int(io, 16)
|
339
334
|
else
|
340
|
-
|
335
|
+
write_short(io, 16)
|
341
336
|
end
|
337
|
+
write_uuid(io, value)
|
342
338
|
end
|
343
339
|
|
344
340
|
def varint_to_bytes(io, value, size_bytes)
|
345
|
-
raw =
|
341
|
+
raw = write_varint('', value)
|
346
342
|
if size_bytes == 4
|
347
343
|
write_bytes(io, raw)
|
348
344
|
else
|
349
345
|
write_short_bytes(io, raw)
|
350
346
|
end
|
351
347
|
end
|
352
|
-
|
353
|
-
def size_to_bytes(io, size, size_bytes)
|
354
|
-
if size_bytes == 4
|
355
|
-
write_int(io, size)
|
356
|
-
else
|
357
|
-
write_short(io, size)
|
358
|
-
end
|
359
|
-
end
|
360
|
-
|
361
|
-
def nil_to_bytes(io, size_bytes)
|
362
|
-
if size_bytes == 4
|
363
|
-
write_int(io, -1)
|
364
|
-
else
|
365
|
-
write_short(io, -1)
|
366
|
-
end
|
367
|
-
end
|
368
348
|
end
|
369
349
|
end
|
370
350
|
end
|