cql-rb 1.0.0.pre6 → 1.0.0.pre7
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class AuthenticateResponse < ResponseBody
|
6
|
+
attr_reader :authentication_class
|
7
|
+
|
8
|
+
def self.decode!(buffer)
|
9
|
+
new(read_string!(buffer))
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(authentication_class)
|
13
|
+
@authentication_class = authentication_class
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
%(AUTHENTICATE #{authentication_class})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class DetailedErrorResponse < ErrorResponse
|
6
|
+
attr_reader :details
|
7
|
+
|
8
|
+
def initialize(code, message, details)
|
9
|
+
super(code, message)
|
10
|
+
@details = details
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.decode!(code, message, buffer)
|
14
|
+
details = {}
|
15
|
+
case code
|
16
|
+
when 0x1000 # unavailable
|
17
|
+
details[:cl] = read_consistency!(buffer)
|
18
|
+
details[:required] = read_int!(buffer)
|
19
|
+
details[:alive] = read_int!(buffer)
|
20
|
+
when 0x1100 # write_timeout
|
21
|
+
details[:cl] = read_consistency!(buffer)
|
22
|
+
details[:received] = read_int!(buffer)
|
23
|
+
details[:blockfor] = read_int!(buffer)
|
24
|
+
details[:write_type] = read_string!(buffer)
|
25
|
+
when 0x1200 # read_timeout
|
26
|
+
details[:cl] = read_consistency!(buffer)
|
27
|
+
details[:received] = read_int!(buffer)
|
28
|
+
details[:blockfor] = read_int!(buffer)
|
29
|
+
details[:data_present] = read_byte!(buffer) != 0
|
30
|
+
when 0x2400 # already_exists
|
31
|
+
details[:ks] = read_string!(buffer)
|
32
|
+
details[:table] = read_string!(buffer)
|
33
|
+
when 0x2500
|
34
|
+
details[:id] = read_short_bytes!(buffer)
|
35
|
+
end
|
36
|
+
new(code, message, details)
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
%(ERROR #@code "#@message" #@details)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class ErrorResponse < ResponseBody
|
6
|
+
attr_reader :code, :message
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
@code, @message = args
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.decode!(buffer)
|
13
|
+
code = read_int!(buffer)
|
14
|
+
message = read_string!(buffer)
|
15
|
+
case code
|
16
|
+
when 0x1000, 0x1100, 0x1200, 0x2400, 0x2500
|
17
|
+
DetailedErrorResponse.decode!(code, message, buffer)
|
18
|
+
else
|
19
|
+
new(code, message)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
%(ERROR #@code "#@message")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class EventResponse < ResultResponse
|
6
|
+
def self.decode!(buffer)
|
7
|
+
type = read_string!(buffer)
|
8
|
+
case type
|
9
|
+
when SchemaChangeEventResponse::TYPE
|
10
|
+
SchemaChangeEventResponse.decode!(buffer)
|
11
|
+
when StatusChangeEventResponse::TYPE
|
12
|
+
StatusChangeEventResponse.decode!(buffer)
|
13
|
+
when TopologyChangeEventResponse::TYPE
|
14
|
+
TopologyChangeEventResponse.decode!(buffer)
|
15
|
+
else
|
16
|
+
raise UnsupportedEventTypeError, %(Unsupported event type: "#{type}")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class PreparedResultResponse < ResultResponse
|
6
|
+
attr_reader :id, :metadata
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
@id, @metadata = args
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.decode!(buffer)
|
13
|
+
id = read_short_bytes!(buffer)
|
14
|
+
metadata = RowsResultResponse.read_metadata!(buffer)
|
15
|
+
new(id, metadata)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
%(RESULT PREPARED #{id.each_byte.map { |x| x.to_s(16) }.join('')} #@metadata)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class ReadyResponse < ResponseBody
|
6
|
+
def self.decode!(buffer)
|
7
|
+
new
|
8
|
+
end
|
9
|
+
|
10
|
+
def eql?(rs)
|
11
|
+
self.class === rs
|
12
|
+
end
|
13
|
+
alias_method :==, :eql?
|
14
|
+
|
15
|
+
def hash
|
16
|
+
@h ||= to_s.hash ^ 0xbadc0de
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
'READY'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class ResultResponse < ResponseBody
|
6
|
+
def self.decode!(buffer)
|
7
|
+
kind = read_int!(buffer)
|
8
|
+
case kind
|
9
|
+
when 0x01
|
10
|
+
VoidResultResponse.decode!(buffer)
|
11
|
+
when 0x02
|
12
|
+
RowsResultResponse.decode!(buffer)
|
13
|
+
when 0x03
|
14
|
+
SetKeyspaceResultResponse.decode!(buffer)
|
15
|
+
when 0x04
|
16
|
+
PreparedResultResponse.decode!(buffer)
|
17
|
+
when 0x05
|
18
|
+
SchemaChangeResultResponse.decode!(buffer)
|
19
|
+
else
|
20
|
+
raise UnsupportedResultKindError, %(Unsupported result kind: #{kind})
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def void?
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class RowsResultResponse < ResultResponse
|
6
|
+
attr_reader :rows, :metadata
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
@rows, @metadata = args
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.decode!(buffer)
|
13
|
+
column_specs = read_metadata!(buffer)
|
14
|
+
new(read_rows!(buffer, column_specs), column_specs)
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
%(RESULT ROWS #@metadata #@rows)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
COLUMN_TYPES = [
|
24
|
+
nil,
|
25
|
+
:ascii,
|
26
|
+
:bigint,
|
27
|
+
:blob,
|
28
|
+
:boolean,
|
29
|
+
:counter,
|
30
|
+
:decimal,
|
31
|
+
:double,
|
32
|
+
:float,
|
33
|
+
:int,
|
34
|
+
:text,
|
35
|
+
:timestamp,
|
36
|
+
:uuid,
|
37
|
+
:varchar,
|
38
|
+
:varint,
|
39
|
+
:timeuuid,
|
40
|
+
:inet,
|
41
|
+
].freeze
|
42
|
+
|
43
|
+
def self.read_column_type!(buffer)
|
44
|
+
id, type = read_option!(buffer) do |id, b|
|
45
|
+
if id > 0 && id <= 0x10
|
46
|
+
COLUMN_TYPES[id]
|
47
|
+
elsif id == 0x20
|
48
|
+
sub_type = read_column_type!(buffer)
|
49
|
+
[:list, sub_type]
|
50
|
+
elsif id == 0x21
|
51
|
+
key_type = read_column_type!(buffer)
|
52
|
+
value_type = read_column_type!(buffer)
|
53
|
+
[:map, key_type, value_type]
|
54
|
+
elsif id == 0x22
|
55
|
+
sub_type = read_column_type!(buffer)
|
56
|
+
[:set, sub_type]
|
57
|
+
else
|
58
|
+
raise UnsupportedColumnTypeError, %(Unsupported column type: #{id})
|
59
|
+
end
|
60
|
+
end
|
61
|
+
type
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.read_metadata!(buffer)
|
65
|
+
flags = read_int!(buffer)
|
66
|
+
columns_count = read_int!(buffer)
|
67
|
+
if flags & 0x01 == 0x01
|
68
|
+
global_keyspace_name = read_string!(buffer)
|
69
|
+
global_table_name = read_string!(buffer)
|
70
|
+
end
|
71
|
+
column_specs = columns_count.times.map do
|
72
|
+
if global_keyspace_name
|
73
|
+
keyspace_name = global_keyspace_name
|
74
|
+
table_name = global_table_name
|
75
|
+
else
|
76
|
+
keyspace_name = read_string!(buffer)
|
77
|
+
table_name = read_string!(buffer)
|
78
|
+
end
|
79
|
+
column_name = read_string!(buffer)
|
80
|
+
type = read_column_type!(buffer)
|
81
|
+
[keyspace_name, table_name, column_name, type]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.read_rows!(buffer, column_specs)
|
86
|
+
type_converter = TypeConverter.new
|
87
|
+
rows_count = read_int!(buffer)
|
88
|
+
rows = []
|
89
|
+
rows_count.times do |row_index|
|
90
|
+
row = {}
|
91
|
+
column_specs.each do |column_spec|
|
92
|
+
row[column_spec[2]] = type_converter.convert_type(buffer, column_spec[3])
|
93
|
+
end
|
94
|
+
rows << row
|
95
|
+
end
|
96
|
+
rows
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class SchemaChangeEventResponse < EventResponse
|
6
|
+
TYPE = 'SCHEMA_CHANGE'.freeze
|
7
|
+
|
8
|
+
attr_reader :type, :change, :keyspace, :table
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
@change, @keyspace, @table = args
|
12
|
+
@type = TYPE
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.decode!(buffer)
|
16
|
+
new(read_string!(buffer), read_string!(buffer), read_string!(buffer))
|
17
|
+
end
|
18
|
+
|
19
|
+
def eql?(rs)
|
20
|
+
rs.type == self.type && rs.change == self.change && rs.keyspace == self.keyspace && rs.table == self.table
|
21
|
+
end
|
22
|
+
alias_method :==, :eql?
|
23
|
+
|
24
|
+
def hash
|
25
|
+
@h ||= begin
|
26
|
+
h = 0
|
27
|
+
h = ((h & 33554431) * 31) ^ @type.hash
|
28
|
+
h = ((h & 33554431) * 31) ^ @change.hash
|
29
|
+
h = ((h & 33554431) * 31) ^ @keyspace.hash
|
30
|
+
h = ((h & 33554431) * 31) ^ @table.hash
|
31
|
+
h
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
%(EVENT #@type #@change "#@keyspace" "#@table")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class SchemaChangeResultResponse < ResultResponse
|
6
|
+
attr_reader :change, :keyspace, :table
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
@change, @keyspace, @table = args
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.decode!(buffer)
|
13
|
+
new(read_string!(buffer), read_string!(buffer), read_string!(buffer))
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
%(RESULT SCHEMA_CHANGE #@change "#@keyspace" "#@table")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class SetKeyspaceResultResponse < ResultResponse
|
6
|
+
attr_reader :keyspace
|
7
|
+
|
8
|
+
def initialize(keyspace)
|
9
|
+
@keyspace = keyspace
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.decode!(buffer)
|
13
|
+
new(read_string!(buffer))
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
%(RESULT SET_KEYSPACE "#@keyspace")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class StatusChangeEventResponse < EventResponse
|
6
|
+
TYPE = 'STATUS_CHANGE'.freeze
|
7
|
+
|
8
|
+
attr_reader :type, :change, :address, :port
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
@change, @address, @port = args
|
12
|
+
@type = TYPE
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.decode!(buffer)
|
16
|
+
new(read_string!(buffer), *read_inet!(buffer))
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
%(EVENT #@type #@change #@address:#@port)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cql
|
4
|
+
module Protocol
|
5
|
+
class SupportedResponse < ResponseBody
|
6
|
+
attr_reader :options
|
7
|
+
|
8
|
+
def initialize(options)
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.decode!(buffer)
|
13
|
+
new(read_string_multimap!(buffer))
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
%(SUPPORTED #{options})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|