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