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