cql-rb 1.0.0.pre6 → 1.0.0.pre7
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.
- data/bin/cqlexec +2 -2
- data/lib/cql/protocol.rb +26 -1
- data/lib/cql/protocol/decoding.rb +3 -0
- data/lib/cql/protocol/request_body.rb +15 -0
- data/lib/cql/protocol/request_frame.rb +1 -266
- data/lib/cql/protocol/requests/credentials_request.rb +31 -0
- data/lib/cql/protocol/requests/execute_request.rb +129 -0
- data/lib/cql/protocol/requests/options_request.rb +19 -0
- data/lib/cql/protocol/requests/prepare_request.rb +31 -0
- data/lib/cql/protocol/requests/query_request.rb +33 -0
- data/lib/cql/protocol/requests/register_request.rb +20 -0
- data/lib/cql/protocol/requests/startup_request.rb +27 -0
- data/lib/cql/protocol/response_body.rb +13 -0
- data/lib/cql/protocol/response_frame.rb +1 -533
- data/lib/cql/protocol/responses/authenticate_response.rb +21 -0
- data/lib/cql/protocol/responses/detailed_error_response.rb +44 -0
- data/lib/cql/protocol/responses/error_response.rb +28 -0
- data/lib/cql/protocol/responses/event_response.rb +21 -0
- data/lib/cql/protocol/responses/prepared_result_response.rb +23 -0
- data/lib/cql/protocol/responses/ready_response.rb +24 -0
- data/lib/cql/protocol/responses/result_response.rb +29 -0
- data/lib/cql/protocol/responses/rows_result_response.rb +100 -0
- data/lib/cql/protocol/responses/schema_change_event_result_response.rb +40 -0
- data/lib/cql/protocol/responses/schema_change_result_response.rb +21 -0
- data/lib/cql/protocol/responses/set_keyspace_result_response.rb +21 -0
- data/lib/cql/protocol/responses/status_change_event_result_response.rb +24 -0
- data/lib/cql/protocol/responses/supported_response.rb +21 -0
- data/lib/cql/protocol/responses/topology_change_event_result_response.rb +14 -0
- data/lib/cql/protocol/responses/void_result_response.rb +19 -0
- data/lib/cql/protocol/type_converter.rb +165 -0
- data/lib/cql/version.rb +1 -1
- data/spec/cql/protocol/response_frame_spec.rb +31 -0
- data/spec/integration/regression_spec.rb +56 -9
- metadata +27 -2
data/bin/cqlexec
CHANGED
@@ -14,7 +14,7 @@ class CqlExecutor
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def run(io)
|
17
|
-
@client = Cql::Client.
|
17
|
+
@client = Cql::Client.connect(host: @options[:host], port: @options[:port])
|
18
18
|
|
19
19
|
# TODO register for events
|
20
20
|
|
@@ -33,7 +33,7 @@ class CqlExecutor
|
|
33
33
|
rescue Interrupt
|
34
34
|
exit
|
35
35
|
ensure
|
36
|
-
@client.
|
36
|
+
@client.close
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
data/lib/cql/protocol.rb
CHANGED
@@ -38,5 +38,30 @@ end
|
|
38
38
|
|
39
39
|
require 'cql/protocol/encoding'
|
40
40
|
require 'cql/protocol/decoding'
|
41
|
+
require 'cql/protocol/type_converter'
|
42
|
+
require 'cql/protocol/response_body'
|
43
|
+
require 'cql/protocol/responses/error_response'
|
44
|
+
require 'cql/protocol/responses/detailed_error_response'
|
45
|
+
require 'cql/protocol/responses/ready_response'
|
46
|
+
require 'cql/protocol/responses/authenticate_response'
|
47
|
+
require 'cql/protocol/responses/supported_response'
|
48
|
+
require 'cql/protocol/responses/result_response'
|
49
|
+
require 'cql/protocol/responses/void_result_response'
|
50
|
+
require 'cql/protocol/responses/rows_result_response'
|
51
|
+
require 'cql/protocol/responses/set_keyspace_result_response'
|
52
|
+
require 'cql/protocol/responses/prepared_result_response'
|
53
|
+
require 'cql/protocol/responses/schema_change_result_response'
|
54
|
+
require 'cql/protocol/responses/event_response'
|
55
|
+
require 'cql/protocol/responses/schema_change_event_result_response'
|
56
|
+
require 'cql/protocol/responses/status_change_event_result_response'
|
57
|
+
require 'cql/protocol/responses/topology_change_event_result_response'
|
58
|
+
require 'cql/protocol/request_body'
|
59
|
+
require 'cql/protocol/requests/startup_request'
|
60
|
+
require 'cql/protocol/requests/credentials_request'
|
61
|
+
require 'cql/protocol/requests/options_request'
|
62
|
+
require 'cql/protocol/requests/register_request'
|
63
|
+
require 'cql/protocol/requests/query_request'
|
64
|
+
require 'cql/protocol/requests/prepare_request'
|
65
|
+
require 'cql/protocol/requests/execute_request'
|
41
66
|
require 'cql/protocol/response_frame'
|
42
|
-
require 'cql/protocol/request_frame'
|
67
|
+
require 'cql/protocol/request_frame'
|
@@ -16,270 +16,5 @@ module Cql
|
|
16
16
|
io << buffer
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
20
|
-
class RequestBody
|
21
|
-
include Encoding
|
22
|
-
|
23
|
-
attr_reader :opcode
|
24
|
-
|
25
|
-
def initialize(opcode)
|
26
|
-
@opcode = opcode
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class StartupRequest < RequestBody
|
31
|
-
def initialize(cql_version='3.0.0', compression=nil)
|
32
|
-
super(1)
|
33
|
-
@arguments = {CQL_VERSION => cql_version}
|
34
|
-
@arguments[COMPRESSION] = compression if compression
|
35
|
-
end
|
36
|
-
|
37
|
-
def write(io)
|
38
|
-
write_string_map(io, @arguments)
|
39
|
-
io
|
40
|
-
end
|
41
|
-
|
42
|
-
def to_s
|
43
|
-
%(STARTUP #@arguments)
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
CQL_VERSION = 'CQL_VERSION'.freeze
|
49
|
-
COMPRESSION = 'COMPRESSION'.freeze
|
50
|
-
end
|
51
|
-
|
52
|
-
class CredentialsRequest < RequestBody
|
53
|
-
attr_reader :credentials
|
54
|
-
|
55
|
-
def initialize(credentials)
|
56
|
-
super(4)
|
57
|
-
@credentials = credentials.dup.freeze
|
58
|
-
end
|
59
|
-
|
60
|
-
def write(io)
|
61
|
-
write_string_map(io, @credentials)
|
62
|
-
end
|
63
|
-
|
64
|
-
def to_s
|
65
|
-
%(CREDENTIALS #{@credentials})
|
66
|
-
end
|
67
|
-
|
68
|
-
def eql?(rq)
|
69
|
-
self.class === rq && rq.credentials.eql?(@credentials)
|
70
|
-
end
|
71
|
-
alias_method :==, :eql?
|
72
|
-
|
73
|
-
def hash
|
74
|
-
@h ||= @credentials.hash
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
class OptionsRequest < RequestBody
|
79
|
-
def initialize
|
80
|
-
super(5)
|
81
|
-
end
|
82
|
-
|
83
|
-
def write(io)
|
84
|
-
io
|
85
|
-
end
|
86
|
-
|
87
|
-
def to_s
|
88
|
-
%(OPTIONS)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
class RegisterRequest < RequestBody
|
93
|
-
def initialize(*events)
|
94
|
-
super(11)
|
95
|
-
@events = events
|
96
|
-
end
|
97
|
-
|
98
|
-
def write(io)
|
99
|
-
write_string_list(io, @events)
|
100
|
-
end
|
101
|
-
|
102
|
-
def to_s
|
103
|
-
%(REGISTER #@events)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
class QueryRequest < RequestBody
|
108
|
-
attr_reader :cql, :consistency
|
109
|
-
|
110
|
-
def initialize(cql, consistency)
|
111
|
-
super(7)
|
112
|
-
@cql = cql
|
113
|
-
@consistency = consistency
|
114
|
-
end
|
115
|
-
|
116
|
-
def write(io)
|
117
|
-
write_long_string(io, @cql)
|
118
|
-
write_consistency(io, @consistency)
|
119
|
-
end
|
120
|
-
|
121
|
-
def to_s
|
122
|
-
%(QUERY "#@cql" #{@consistency.to_s.upcase})
|
123
|
-
end
|
124
|
-
|
125
|
-
def eql?(rq)
|
126
|
-
self.class === rq && rq.cql.eql?(self.cql) && rq.consistency.eql?(self.consistency)
|
127
|
-
end
|
128
|
-
alias_method :==, :eql?
|
129
|
-
|
130
|
-
def hash
|
131
|
-
@h ||= (@cql.hash * 31) ^ consistency.hash
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
class PrepareRequest < RequestBody
|
136
|
-
attr_reader :cql
|
137
|
-
|
138
|
-
def initialize(cql)
|
139
|
-
super(9)
|
140
|
-
@cql = cql
|
141
|
-
end
|
142
|
-
|
143
|
-
def write(io)
|
144
|
-
write_long_string(io, @cql)
|
145
|
-
end
|
146
|
-
|
147
|
-
def to_s
|
148
|
-
%(PREPARE "#@cql")
|
149
|
-
end
|
150
|
-
|
151
|
-
def eql?(rq)
|
152
|
-
self.class === rq && rq.cql == self.cql
|
153
|
-
end
|
154
|
-
alias_method :==, :eql?
|
155
|
-
|
156
|
-
def hash
|
157
|
-
@h ||= @cql.hash
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
class ExecuteRequest < RequestBody
|
162
|
-
attr_reader :id, :metadata, :values, :consistency
|
163
|
-
|
164
|
-
def initialize(id, metadata, values, consistency)
|
165
|
-
super(10)
|
166
|
-
raise ArgumentError, "Metadata for #{metadata.size} columns, but #{values.size} values given" if metadata.size != values.size
|
167
|
-
@id = id
|
168
|
-
@metadata = metadata
|
169
|
-
@values = values
|
170
|
-
@consistency = consistency
|
171
|
-
end
|
172
|
-
|
173
|
-
def write(io)
|
174
|
-
write_short_bytes(io, @id)
|
175
|
-
write_short(io, @metadata.size)
|
176
|
-
@metadata.each_with_index do |(_, _, _, type), index|
|
177
|
-
write_value(io, @values[index], type)
|
178
|
-
end
|
179
|
-
write_consistency(io, @consistency)
|
180
|
-
end
|
181
|
-
|
182
|
-
def to_s
|
183
|
-
id = @id.each_byte.map { |x| x.to_s(16) }.join('')
|
184
|
-
%(EXECUTE #{id} #@values #{@consistency.to_s.upcase})
|
185
|
-
end
|
186
|
-
|
187
|
-
def eql?(rq)
|
188
|
-
self.class === rq && rq.id == self.id && rq.metadata == self.metadata && rq.values == self.values && rq.consistency == self.consistency
|
189
|
-
end
|
190
|
-
alias_method :==, :eql?
|
191
|
-
|
192
|
-
def hash
|
193
|
-
@h ||= begin
|
194
|
-
h = 0
|
195
|
-
h = ((h & 33554431) * 31) ^ @id.hash
|
196
|
-
h = ((h & 33554431) * 31) ^ @metadata.hash
|
197
|
-
h = ((h & 33554431) * 31) ^ @values.hash
|
198
|
-
h = ((h & 33554431) * 31) ^ @consistency.hash
|
199
|
-
h
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
private
|
204
|
-
|
205
|
-
def write_value(io, value, type)
|
206
|
-
if Array === type
|
207
|
-
raise InvalidValueError, 'Value for collection must be enumerable' unless value.is_a?(Enumerable)
|
208
|
-
case type.first
|
209
|
-
when :list, :set
|
210
|
-
_, sub_type = type
|
211
|
-
raw = ''
|
212
|
-
write_short(raw, value.size)
|
213
|
-
value.each do |element|
|
214
|
-
rr = ''
|
215
|
-
write_value(rr, element, sub_type)
|
216
|
-
raw << rr[2, rr.length - 2]
|
217
|
-
end
|
218
|
-
write_bytes(io, raw)
|
219
|
-
when :map
|
220
|
-
_, key_type, value_type = type
|
221
|
-
raw = ''
|
222
|
-
write_short(raw, value.size)
|
223
|
-
value.each do |key, value|
|
224
|
-
rr = ''
|
225
|
-
write_value(rr, key, key_type)
|
226
|
-
raw << rr[2, rr.length - 2]
|
227
|
-
rr = ''
|
228
|
-
write_value(rr, value, value_type)
|
229
|
-
raw << rr[2, rr.length - 2]
|
230
|
-
end
|
231
|
-
write_bytes(io, raw)
|
232
|
-
else
|
233
|
-
raise UnsupportedColumnTypeError, %(Unsupported column collection type: #{type.first})
|
234
|
-
end
|
235
|
-
else
|
236
|
-
case type
|
237
|
-
when :ascii
|
238
|
-
write_bytes(io, value.encode(::Encoding::ASCII))
|
239
|
-
when :bigint
|
240
|
-
write_int(io, 8)
|
241
|
-
write_long(io, value)
|
242
|
-
when :blob
|
243
|
-
write_bytes(io, value.encode(::Encoding::BINARY))
|
244
|
-
when :boolean
|
245
|
-
write_int(io, 1)
|
246
|
-
io << (value ? Constants::TRUE_BYTE : Constants::FALSE_BYTE)
|
247
|
-
when :decimal
|
248
|
-
raw = write_decimal('', value)
|
249
|
-
write_int(io, raw.size)
|
250
|
-
io << raw
|
251
|
-
when :double
|
252
|
-
write_int(io, 8)
|
253
|
-
write_double(io, value)
|
254
|
-
when :float
|
255
|
-
write_int(io, 4)
|
256
|
-
write_float(io, value)
|
257
|
-
when :inet
|
258
|
-
write_int(io, value.ipv6? ? 16 : 4)
|
259
|
-
io << value.hton
|
260
|
-
when :int
|
261
|
-
write_int(io, 4)
|
262
|
-
write_int(io, value)
|
263
|
-
when :text, :varchar
|
264
|
-
write_bytes(io, value.encode(::Encoding::UTF_8))
|
265
|
-
when :timestamp
|
266
|
-
ms = (value.to_f * 1000).to_i
|
267
|
-
write_int(io, 8)
|
268
|
-
write_long(io, ms)
|
269
|
-
when :timeuuid, :uuid
|
270
|
-
write_int(io, 16)
|
271
|
-
write_uuid(io, value)
|
272
|
-
when :varint
|
273
|
-
raw = write_varint('', value)
|
274
|
-
write_int(io, raw.length)
|
275
|
-
io << raw
|
276
|
-
else
|
277
|
-
raise UnsupportedColumnTypeError, %(Unsupported column type: #{type})
|
278
|
-
end
|
279
|
-
end
|
280
|
-
rescue TypeError => e
|
281
|
-
raise TypeError, %("#{value}" cannot be encoded as #{type.to_s.upcase}: #{e.message}), e.backtrace
|
282
|
-
end
|
283
|
-
end
|
284
19
|
end
|
285
|
-
end
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class CredentialsRequest < RequestBody
|
6
|
+
attr_reader :credentials
|
7
|
+
|
8
|
+
def initialize(credentials)
|
9
|
+
super(4)
|
10
|
+
@credentials = credentials.dup.freeze
|
11
|
+
end
|
12
|
+
|
13
|
+
def write(io)
|
14
|
+
write_string_map(io, @credentials)
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
%(CREDENTIALS #{@credentials})
|
19
|
+
end
|
20
|
+
|
21
|
+
def eql?(rq)
|
22
|
+
self.class === rq && rq.credentials.eql?(@credentials)
|
23
|
+
end
|
24
|
+
alias_method :==, :eql?
|
25
|
+
|
26
|
+
def hash
|
27
|
+
@h ||= @credentials.hash
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class ExecuteRequest < RequestBody
|
6
|
+
attr_reader :id, :metadata, :values, :consistency
|
7
|
+
|
8
|
+
def initialize(id, metadata, values, consistency)
|
9
|
+
super(10)
|
10
|
+
raise ArgumentError, "Metadata for #{metadata.size} columns, but #{values.size} values given" if metadata.size != values.size
|
11
|
+
@id = id
|
12
|
+
@metadata = metadata
|
13
|
+
@values = values
|
14
|
+
@consistency = consistency
|
15
|
+
end
|
16
|
+
|
17
|
+
def write(io)
|
18
|
+
write_short_bytes(io, @id)
|
19
|
+
write_short(io, @metadata.size)
|
20
|
+
@metadata.each_with_index do |(_, _, _, type), index|
|
21
|
+
write_value(io, @values[index], type)
|
22
|
+
end
|
23
|
+
write_consistency(io, @consistency)
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
id = @id.each_byte.map { |x| x.to_s(16) }.join('')
|
28
|
+
%(EXECUTE #{id} #@values #{@consistency.to_s.upcase})
|
29
|
+
end
|
30
|
+
|
31
|
+
def eql?(rq)
|
32
|
+
self.class === rq && rq.id == self.id && rq.metadata == self.metadata && rq.values == self.values && rq.consistency == self.consistency
|
33
|
+
end
|
34
|
+
alias_method :==, :eql?
|
35
|
+
|
36
|
+
def hash
|
37
|
+
@h ||= begin
|
38
|
+
h = 0
|
39
|
+
h = ((h & 33554431) * 31) ^ @id.hash
|
40
|
+
h = ((h & 33554431) * 31) ^ @metadata.hash
|
41
|
+
h = ((h & 33554431) * 31) ^ @values.hash
|
42
|
+
h = ((h & 33554431) * 31) ^ @consistency.hash
|
43
|
+
h
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def write_value(io, value, type)
|
50
|
+
if Array === type
|
51
|
+
raise InvalidValueError, 'Value for collection must be enumerable' unless value.is_a?(Enumerable)
|
52
|
+
case type.first
|
53
|
+
when :list, :set
|
54
|
+
_, sub_type = type
|
55
|
+
raw = ''
|
56
|
+
write_short(raw, value.size)
|
57
|
+
value.each do |element|
|
58
|
+
rr = ''
|
59
|
+
write_value(rr, element, sub_type)
|
60
|
+
raw << rr[2, rr.length - 2]
|
61
|
+
end
|
62
|
+
write_bytes(io, raw)
|
63
|
+
when :map
|
64
|
+
_, key_type, value_type = type
|
65
|
+
raw = ''
|
66
|
+
write_short(raw, value.size)
|
67
|
+
value.each do |key, value|
|
68
|
+
rr = ''
|
69
|
+
write_value(rr, key, key_type)
|
70
|
+
raw << rr[2, rr.length - 2]
|
71
|
+
rr = ''
|
72
|
+
write_value(rr, value, value_type)
|
73
|
+
raw << rr[2, rr.length - 2]
|
74
|
+
end
|
75
|
+
write_bytes(io, raw)
|
76
|
+
else
|
77
|
+
raise UnsupportedColumnTypeError, %(Unsupported column collection type: #{type.first})
|
78
|
+
end
|
79
|
+
else
|
80
|
+
case type
|
81
|
+
when :ascii
|
82
|
+
write_bytes(io, value.encode(::Encoding::ASCII))
|
83
|
+
when :bigint
|
84
|
+
write_int(io, 8)
|
85
|
+
write_long(io, value)
|
86
|
+
when :blob
|
87
|
+
write_bytes(io, value.encode(::Encoding::BINARY))
|
88
|
+
when :boolean
|
89
|
+
write_int(io, 1)
|
90
|
+
io << (value ? Constants::TRUE_BYTE : Constants::FALSE_BYTE)
|
91
|
+
when :decimal
|
92
|
+
raw = write_decimal('', value)
|
93
|
+
write_int(io, raw.size)
|
94
|
+
io << raw
|
95
|
+
when :double
|
96
|
+
write_int(io, 8)
|
97
|
+
write_double(io, value)
|
98
|
+
when :float
|
99
|
+
write_int(io, 4)
|
100
|
+
write_float(io, value)
|
101
|
+
when :inet
|
102
|
+
write_int(io, value.ipv6? ? 16 : 4)
|
103
|
+
io << value.hton
|
104
|
+
when :int
|
105
|
+
write_int(io, 4)
|
106
|
+
write_int(io, value)
|
107
|
+
when :text, :varchar
|
108
|
+
write_bytes(io, value.encode(::Encoding::UTF_8))
|
109
|
+
when :timestamp
|
110
|
+
ms = (value.to_f * 1000).to_i
|
111
|
+
write_int(io, 8)
|
112
|
+
write_long(io, ms)
|
113
|
+
when :timeuuid, :uuid
|
114
|
+
write_int(io, 16)
|
115
|
+
write_uuid(io, value)
|
116
|
+
when :varint
|
117
|
+
raw = write_varint('', value)
|
118
|
+
write_int(io, raw.length)
|
119
|
+
io << raw
|
120
|
+
else
|
121
|
+
raise UnsupportedColumnTypeError, %(Unsupported column type: #{type})
|
122
|
+
end
|
123
|
+
end
|
124
|
+
rescue TypeError => e
|
125
|
+
raise TypeError, %("#{value}" cannot be encoded as #{type.to_s.upcase}: #{e.message}), e.backtrace
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|