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,165 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'ipaddr'
|
4
|
+
require 'set'
|
5
|
+
|
6
|
+
|
7
|
+
module Cql
|
8
|
+
module Protocol
|
9
|
+
class TypeConverter
|
10
|
+
include Decoding
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@conversions = conversions
|
14
|
+
end
|
15
|
+
|
16
|
+
def convert_type(buffer, type, size_bytes=4)
|
17
|
+
return nil if buffer.empty?
|
18
|
+
case type
|
19
|
+
when Array
|
20
|
+
return nil unless read_size(buffer, size_bytes)
|
21
|
+
case type.first
|
22
|
+
when :list
|
23
|
+
convert_list(buffer, @conversions[type[1]])
|
24
|
+
when :map
|
25
|
+
convert_map(buffer, @conversions[type[1]], @conversions[type[2]])
|
26
|
+
when :set
|
27
|
+
convert_set(buffer, @conversions[type[1]])
|
28
|
+
end
|
29
|
+
else
|
30
|
+
@conversions[type].call(buffer, size_bytes)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def conversions
|
35
|
+
{
|
36
|
+
:ascii => method(:convert_ascii),
|
37
|
+
:bigint => method(:convert_bigint),
|
38
|
+
:blob => method(:convert_blob),
|
39
|
+
:boolean => method(:convert_boolean),
|
40
|
+
:counter => method(:convert_bigint),
|
41
|
+
:decimal => method(:convert_decimal),
|
42
|
+
:double => method(:convert_double),
|
43
|
+
:float => method(:convert_float),
|
44
|
+
:int => method(:convert_int),
|
45
|
+
:timestamp => method(:convert_timestamp),
|
46
|
+
:varchar => method(:convert_varchar),
|
47
|
+
:text => method(:convert_varchar),
|
48
|
+
:varint => method(:convert_varint),
|
49
|
+
:timeuuid => method(:convert_uuid),
|
50
|
+
:uuid => method(:convert_uuid),
|
51
|
+
:inet => method(:convert_inet),
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def convert_ascii(buffer, size_bytes)
|
56
|
+
bytes = size_bytes == 4 ? read_bytes!(buffer) : read_short_bytes!(buffer)
|
57
|
+
bytes ? bytes.force_encoding(::Encoding::ASCII) : nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def convert_bigint(buffer, size_bytes)
|
61
|
+
return nil unless read_size(buffer, size_bytes)
|
62
|
+
read_long!(buffer)
|
63
|
+
end
|
64
|
+
|
65
|
+
def convert_blob(buffer, size_bytes)
|
66
|
+
bytes = size_bytes == 4 ? read_bytes!(buffer) : read_short_bytes!(buffer)
|
67
|
+
bytes ? bytes : nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def convert_boolean(buffer, size_bytes)
|
71
|
+
return nil unless read_size(buffer, size_bytes)
|
72
|
+
buffer.read(1) == Constants::TRUE_BYTE
|
73
|
+
end
|
74
|
+
|
75
|
+
def convert_decimal(buffer, size_bytes)
|
76
|
+
size = read_size(buffer, size_bytes)
|
77
|
+
return nil unless size
|
78
|
+
read_decimal!(buffer, size)
|
79
|
+
end
|
80
|
+
|
81
|
+
def convert_double(buffer, size_bytes)
|
82
|
+
return nil unless read_size(buffer, size_bytes)
|
83
|
+
read_double!(buffer)
|
84
|
+
end
|
85
|
+
|
86
|
+
def convert_float(buffer, size_bytes)
|
87
|
+
return nil unless read_size(buffer, size_bytes)
|
88
|
+
read_float!(buffer)
|
89
|
+
end
|
90
|
+
|
91
|
+
def convert_int(buffer, size_bytes)
|
92
|
+
return nil unless read_size(buffer, size_bytes)
|
93
|
+
read_int!(buffer)
|
94
|
+
end
|
95
|
+
|
96
|
+
def convert_timestamp(buffer, size_bytes)
|
97
|
+
return nil unless read_size(buffer, size_bytes)
|
98
|
+
timestamp = read_long!(buffer)
|
99
|
+
Time.at(timestamp/1000.0)
|
100
|
+
end
|
101
|
+
|
102
|
+
def convert_varchar(buffer, size_bytes)
|
103
|
+
bytes = size_bytes == 4 ? read_bytes!(buffer) : read_short_bytes!(buffer)
|
104
|
+
bytes ? bytes.force_encoding(::Encoding::UTF_8) : nil
|
105
|
+
end
|
106
|
+
|
107
|
+
def convert_varint(buffer, size_bytes)
|
108
|
+
size = read_size(buffer, size_bytes)
|
109
|
+
return nil unless size
|
110
|
+
read_varint!(buffer, size)
|
111
|
+
end
|
112
|
+
|
113
|
+
def convert_uuid(buffer, size_bytes)
|
114
|
+
return nil unless read_size(buffer, size_bytes)
|
115
|
+
read_uuid!(buffer)
|
116
|
+
end
|
117
|
+
|
118
|
+
def convert_inet(buffer, size_bytes)
|
119
|
+
size = read_size(buffer, size_bytes)
|
120
|
+
return nil unless size
|
121
|
+
IPAddr.new_ntoh(buffer.read(size))
|
122
|
+
end
|
123
|
+
|
124
|
+
def convert_list(buffer, value_converter)
|
125
|
+
list = []
|
126
|
+
size = buffer.read_short
|
127
|
+
size.times do
|
128
|
+
list << value_converter.call(buffer, 2)
|
129
|
+
end
|
130
|
+
list
|
131
|
+
end
|
132
|
+
|
133
|
+
def convert_map(buffer, key_converter, value_converter)
|
134
|
+
map = {}
|
135
|
+
size = buffer.read_short
|
136
|
+
size.times do
|
137
|
+
key = key_converter.call(buffer, 2)
|
138
|
+
value = value_converter.call(buffer, 2)
|
139
|
+
map[key] = value
|
140
|
+
end
|
141
|
+
map
|
142
|
+
end
|
143
|
+
|
144
|
+
def convert_set(buffer, value_converter)
|
145
|
+
set = Set.new
|
146
|
+
size = buffer.read_short
|
147
|
+
size.times do
|
148
|
+
set << value_converter.call(buffer, 2)
|
149
|
+
end
|
150
|
+
set
|
151
|
+
end
|
152
|
+
|
153
|
+
def read_size(buffer, size_bytes)
|
154
|
+
if size_bytes == 2
|
155
|
+
size = buffer.read_short
|
156
|
+
return nil if size & 0x8000 == 0x8000
|
157
|
+
else
|
158
|
+
size = buffer.read_int
|
159
|
+
return nil if size & 0x80000000 == 0x80000000
|
160
|
+
end
|
161
|
+
size
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/lib/cql/version.rb
CHANGED
@@ -540,11 +540,42 @@ module Cql
|
|
540
540
|
frame.body.rows.first['set_column'].should == Set.new(["\xab\x43\x21", "\xaf\xd8\x7e\xcd"].map { |s| s.force_encoding(::Encoding::BINARY) })
|
541
541
|
end
|
542
542
|
|
543
|
+
it 'decodes nulls' do
|
544
|
+
frame = described_class.new(ByteBuffer.new("\x81\x00\x00\b\x00\x00\x01\xB6\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x13\x00\x12cql_rb_client_spec\x00\rlots_of_types\x00\x02id\x00\t\x00\fascii_column\x00\x01\x00\rbigint_column\x00\x02\x00\vblob_column\x00\x03\x00\x0Eboolean_column\x00\x04\x00\x0Edecimal_column\x00\x06\x00\rdouble_column\x00\a\x00\ffloat_column\x00\b\x00\vinet_column\x00\x10\x00\nint_column\x00\t\x00\vlist_column\x00 \x00\x01\x00\nmap_column\x00!\x00\r\x00\x04\x00\nset_column\x00\"\x00\x03\x00\vtext_column\x00\r\x00\x10timestamp_column\x00\v\x00\x0Ftimeuuid_column\x00\x0F\x00\vuuid_column\x00\f\x00\x0Evarchar_column\x00\r\x00\rvarint_column\x00\x0E\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x03\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"))
|
545
|
+
row = frame.body.rows.first
|
546
|
+
row.should eql(
|
547
|
+
'id' => 3,
|
548
|
+
'ascii_column' => nil,
|
549
|
+
'bigint_column' => nil,
|
550
|
+
'blob_column' => nil,
|
551
|
+
'boolean_column' => nil,
|
552
|
+
'decimal_column' => nil,
|
553
|
+
'double_column' => nil,
|
554
|
+
'float_column' => nil,
|
555
|
+
'int_column' => nil,
|
556
|
+
'text_column' => nil,
|
557
|
+
'timestamp_column' => nil,
|
558
|
+
'uuid_column' => nil,
|
559
|
+
'varchar_column' => nil,
|
560
|
+
'varint_column' => nil,
|
561
|
+
'timeuuid_column' => nil,
|
562
|
+
'inet_column' => nil,
|
563
|
+
'list_column' => nil,
|
564
|
+
'map_column' => nil,
|
565
|
+
'set_column' => nil,
|
566
|
+
)
|
567
|
+
end
|
568
|
+
|
543
569
|
it 'decodes COUNTER as a number' do
|
544
570
|
frame = described_class.new(ByteBuffer.new("\x81\x00\x00\b\x00\x00\x00N\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\x00\x04test\x00\x04cnts\x00\x02id\x00\r\x00\x02c1\x00\x05\x00\x02c2\x00\x05\x00\x00\x00\x01\x00\x00\x00\x04theo\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x01"))
|
545
571
|
frame.body.rows.first['c1'].should == 3
|
546
572
|
end
|
547
573
|
|
574
|
+
it 'decodes a null COUNTER as nil' do
|
575
|
+
frame = described_class.new(ByteBuffer.new("\x81\x00\x00\b\x00\x00\x00V\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\x00\x12cql_rb_client_spec\x00\bcounters\x00\bcounter1\x00\x05\x00\bcounter2\x00\x05\x00\x00\x00\x01\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x01\xFF\xFF\xFF\xFF"))
|
576
|
+
frame.body.rows.first['counter2'].should be_nil
|
577
|
+
end
|
578
|
+
|
548
579
|
it 'raises an error when encountering an unknown column type' do
|
549
580
|
frame = described_class.new
|
550
581
|
frame << "\x81\x00\x00\b\x00\x00\x00E"
|
@@ -20,7 +20,7 @@ describe 'Regressions' do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
after do
|
23
|
-
client.execute('DROP KEYSPACE cql_rb_client_spec')
|
23
|
+
client.execute('DROP KEYSPACE cql_rb_client_spec') rescue nil
|
24
24
|
client.close
|
25
25
|
end
|
26
26
|
|
@@ -63,18 +63,65 @@ describe 'Regressions' do
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
-
context '
|
67
|
-
it '
|
68
|
-
client.execute(
|
69
|
-
client.execute(
|
70
|
-
result = client.execute(
|
71
|
-
|
66
|
+
context 'frame decoding' do
|
67
|
+
it 'decodes null counters' do
|
68
|
+
client.execute(%<CREATE TABLE counters (id ASCII, counter1 COUNTER, counter2 COUNTER, PRIMARY KEY (id))>)
|
69
|
+
client.execute(%<UPDATE counters SET counter1 = counter1 + 1 WHERE id = 'foo'>)
|
70
|
+
result = client.execute(%<SELECT counter1, counter2 FROM counters WHERE id = 'foo'>)
|
71
|
+
result.first['counter1'].should == 1
|
72
|
+
result.first['counter2'].should be_nil
|
72
73
|
end
|
73
74
|
|
74
|
-
it '
|
75
|
-
client.execute(
|
75
|
+
it 'decodes null values' do
|
76
|
+
client.execute(<<-CQL)
|
77
|
+
CREATE TABLE lots_of_types (
|
78
|
+
id INT,
|
79
|
+
ascii_column ASCII,
|
80
|
+
bigint_column BIGINT,
|
81
|
+
blob_column BLOB,
|
82
|
+
boolean_column BOOLEAN,
|
83
|
+
decimal_column DECIMAL,
|
84
|
+
double_column DOUBLE,
|
85
|
+
float_column FLOAT,
|
86
|
+
int_column INT,
|
87
|
+
text_column TEXT,
|
88
|
+
timestamp_column TIMESTAMP,
|
89
|
+
uuid_column UUID,
|
90
|
+
varchar_column VARCHAR,
|
91
|
+
varint_column VARINT,
|
92
|
+
timeuuid_column TIMEUUID,
|
93
|
+
inet_column INET,
|
94
|
+
list_column LIST<ASCII>,
|
95
|
+
map_column MAP<TEXT, BOOLEAN>,
|
96
|
+
set_column SET<BLOB>,
|
97
|
+
PRIMARY KEY (id)
|
98
|
+
)
|
99
|
+
CQL
|
100
|
+
client.execute(%<INSERT INTO lots_of_types (id) VALUES (3)>)
|
101
|
+
result = client.execute(%<SELECT * FROM lots_of_types WHERE id = 3>)
|
102
|
+
row = result.first
|
103
|
+
row['ascii_column'].should be_nil
|
104
|
+
row['bigint_column'].should be_nil
|
105
|
+
row['blob_column'].should be_nil
|
106
|
+
row['boolean_column'].should be_nil
|
107
|
+
row['decimal_column'].should be_nil
|
108
|
+
row['double_column'].should be_nil
|
109
|
+
row['float_column'].should be_nil
|
110
|
+
row['int_column'].should be_nil
|
111
|
+
row['text_column'].should be_nil
|
112
|
+
row['timestamp_column'].should be_nil
|
113
|
+
row['uuid_column'].should be_nil
|
114
|
+
row['varchar_column'].should be_nil
|
115
|
+
row['varint_column'].should be_nil
|
116
|
+
row['timeuuid_column'].should be_nil
|
117
|
+
row['inet_column'].should be_nil
|
118
|
+
row['list_column'].should be_nil
|
119
|
+
row['map_column'].should be_nil
|
120
|
+
row['set_column'].should be_nil
|
76
121
|
end
|
122
|
+
end
|
77
123
|
|
124
|
+
context 'wat' do
|
78
125
|
it 'null values' do
|
79
126
|
client.execute('CREATE TABLE null_value (a BIGINT, b BOOLEAN, c INT, PRIMARY KEY ((a, b), c))')
|
80
127
|
client.execute('INSERT INTO null_value (a, b, c) VALUES (123123123123, true, 3234)')
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cql-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.pre7
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-05-
|
12
|
+
date: 2013-05-15 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: A pure Ruby CQL3 driver for Cassandra
|
15
15
|
email:
|
@@ -26,8 +26,33 @@ files:
|
|
26
26
|
- lib/cql/io.rb
|
27
27
|
- lib/cql/protocol/decoding.rb
|
28
28
|
- lib/cql/protocol/encoding.rb
|
29
|
+
- lib/cql/protocol/request_body.rb
|
29
30
|
- lib/cql/protocol/request_frame.rb
|
31
|
+
- lib/cql/protocol/requests/credentials_request.rb
|
32
|
+
- lib/cql/protocol/requests/execute_request.rb
|
33
|
+
- lib/cql/protocol/requests/options_request.rb
|
34
|
+
- lib/cql/protocol/requests/prepare_request.rb
|
35
|
+
- lib/cql/protocol/requests/query_request.rb
|
36
|
+
- lib/cql/protocol/requests/register_request.rb
|
37
|
+
- lib/cql/protocol/requests/startup_request.rb
|
38
|
+
- lib/cql/protocol/response_body.rb
|
30
39
|
- lib/cql/protocol/response_frame.rb
|
40
|
+
- lib/cql/protocol/responses/authenticate_response.rb
|
41
|
+
- lib/cql/protocol/responses/detailed_error_response.rb
|
42
|
+
- lib/cql/protocol/responses/error_response.rb
|
43
|
+
- lib/cql/protocol/responses/event_response.rb
|
44
|
+
- lib/cql/protocol/responses/prepared_result_response.rb
|
45
|
+
- lib/cql/protocol/responses/ready_response.rb
|
46
|
+
- lib/cql/protocol/responses/result_response.rb
|
47
|
+
- lib/cql/protocol/responses/rows_result_response.rb
|
48
|
+
- lib/cql/protocol/responses/schema_change_event_result_response.rb
|
49
|
+
- lib/cql/protocol/responses/schema_change_result_response.rb
|
50
|
+
- lib/cql/protocol/responses/set_keyspace_result_response.rb
|
51
|
+
- lib/cql/protocol/responses/status_change_event_result_response.rb
|
52
|
+
- lib/cql/protocol/responses/supported_response.rb
|
53
|
+
- lib/cql/protocol/responses/topology_change_event_result_response.rb
|
54
|
+
- lib/cql/protocol/responses/void_result_response.rb
|
55
|
+
- lib/cql/protocol/type_converter.rb
|
31
56
|
- lib/cql/protocol.rb
|
32
57
|
- lib/cql/uuid.rb
|
33
58
|
- lib/cql/version.rb
|