monetdb 0.2.0 → 0.2.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.rdoc +5 -0
- data/VERSION +1 -1
- data/lib/monetdb/connection.rb +2 -39
- data/lib/monetdb/connection/io.rb +47 -0
- data/lib/monetdb/connection/query.rb +2 -2
- data/lib/monetdb/version.rb +1 -1
- data/test/test_helper/simple_connection.rb +10 -0
- data/test/unit/connection/test_io.rb +86 -0
- data/test/unit/connection/test_query.rb +74 -0
- data/test/unit/test_connection.rb +0 -66
- data/test/unit/test_monetdb.rb +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5ec545e31663df97597447cdbd33b25e2d88c86
|
4
|
+
data.tar.gz: f3bc08654b1fac1b7cc99988e269aa8d3707c412
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab6e208b3f0c3a93de085f7ee71d15277b1615e7cd3b77f722d7cf35f96abb9fcf463083cffa724ec691497cfaf6dd7f91a3553b74bbe3260ca848e876e62781
|
7
|
+
data.tar.gz: e10a8e18b1a99d5fdaff880af3ab7b358a4962a6ffdbc9a179c454901f5b6df9f77cb4327db2756e1daa9cee3848d2fa9e3918f6e9e41085d373ce8ce360acd4
|
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
= MonetDB CHANGELOG
|
2
2
|
|
3
|
+
== Version 0.2.1 (October 13, 2014)
|
4
|
+
|
5
|
+
* Extracted IO related methods to MonetDB::Connection::IO
|
6
|
+
* Fixed bug when parsing rows (excluding "\t]" at end of string)
|
7
|
+
|
3
8
|
== Version 0.2.0 (October 13, 2014)
|
4
9
|
|
5
10
|
* Complete rewrite of the gem (only focussed on querying data using SQL)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.1
|
data/lib/monetdb/connection.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "socket"
|
2
|
+
require "monetdb/connection/io"
|
2
3
|
require "monetdb/connection/messages"
|
3
4
|
require "monetdb/connection/setup"
|
4
5
|
require "monetdb/connection/query"
|
@@ -6,6 +7,7 @@ require "monetdb/connection/query"
|
|
6
7
|
module MonetDB
|
7
8
|
class Connection
|
8
9
|
|
10
|
+
include IO
|
9
11
|
include Messages
|
10
12
|
include Setup
|
11
13
|
include Query
|
@@ -82,44 +84,5 @@ module MonetDB
|
|
82
84
|
MonetDB.logger.send(type, msg) if MonetDB.logger
|
83
85
|
end
|
84
86
|
|
85
|
-
def read
|
86
|
-
raise ConnectionError, "Not connected to server" unless connected?
|
87
|
-
|
88
|
-
length, last_chunk = read_length
|
89
|
-
data, iterations = "", 0
|
90
|
-
|
91
|
-
while (length > 0) && (iterations < 1000) do
|
92
|
-
received = socket.recv(length)
|
93
|
-
data << received
|
94
|
-
length -= received.bytesize
|
95
|
-
iterations += 1
|
96
|
-
end
|
97
|
-
data << read unless last_chunk
|
98
|
-
|
99
|
-
data
|
100
|
-
end
|
101
|
-
|
102
|
-
def read_length
|
103
|
-
bytes = socket.recv(2).unpack("v")[0]
|
104
|
-
[(bytes >> 1), (bytes & 1) == 1]
|
105
|
-
end
|
106
|
-
|
107
|
-
def write(message)
|
108
|
-
raise ConnectionError, "Not connected to server" unless connected?
|
109
|
-
pack(message).each do |chunk|
|
110
|
-
socket.write(chunk)
|
111
|
-
end
|
112
|
-
true
|
113
|
-
end
|
114
|
-
|
115
|
-
def pack(message)
|
116
|
-
chunks = message.scan(/.{1,#{MAX_MSG_SIZE}}/m)
|
117
|
-
chunks.each_with_index.to_a.collect do |chunk, index|
|
118
|
-
last_bit = (index == chunks.size - 1) ? 1 : 0
|
119
|
-
length = [(chunk.size << 1) | last_bit].pack("v")
|
120
|
-
"#{length}#{chunk}"
|
121
|
-
end.freeze
|
122
|
-
end
|
123
|
-
|
124
87
|
end
|
125
88
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module MonetDB
|
2
|
+
class Connection
|
3
|
+
module IO
|
4
|
+
private
|
5
|
+
|
6
|
+
def read
|
7
|
+
raise ConnectionError, "Not connected to server" unless connected?
|
8
|
+
|
9
|
+
length, last_chunk = read_length
|
10
|
+
data, iterations = "", 0
|
11
|
+
|
12
|
+
while (length > 0) && (iterations < 1000) do
|
13
|
+
received = socket.recv(length)
|
14
|
+
data << received
|
15
|
+
length -= received.bytesize
|
16
|
+
iterations += 1
|
17
|
+
end
|
18
|
+
data << read unless last_chunk
|
19
|
+
|
20
|
+
data
|
21
|
+
end
|
22
|
+
|
23
|
+
def read_length
|
24
|
+
bytes = socket.recv(2).unpack("v")[0]
|
25
|
+
[(bytes >> 1), (bytes & 1) == 1]
|
26
|
+
end
|
27
|
+
|
28
|
+
def write(message)
|
29
|
+
raise ConnectionError, "Not connected to server" unless connected?
|
30
|
+
pack(message).each do |chunk|
|
31
|
+
socket.write(chunk)
|
32
|
+
end
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def pack(message)
|
37
|
+
chunks = message.scan(/.{1,#{MAX_MSG_SIZE}}/m)
|
38
|
+
chunks.each_with_index.to_a.collect do |chunk, index|
|
39
|
+
last_bit = (index == chunks.size - 1) ? 1 : 0
|
40
|
+
length = [(chunk.size << 1) | last_bit].pack("v")
|
41
|
+
"#{length}#{chunk}"
|
42
|
+
end.freeze
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -76,7 +76,7 @@ module MonetDB
|
|
76
76
|
|
77
77
|
def parse_rows(table_header, response)
|
78
78
|
column_types = table_header[:column_types]
|
79
|
-
response.split("\t]\n").collect do |row|
|
79
|
+
response.slice(0..-3).split("\t]\n").collect do |row|
|
80
80
|
parsed, values = [], row.slice(1..-1).split(",\t")
|
81
81
|
values.each_with_index do |value, index|
|
82
82
|
parsed << parse_value(column_types[index], value.strip)
|
@@ -101,7 +101,7 @@ module MonetDB
|
|
101
101
|
when :tinyint
|
102
102
|
parse_boolean_value value
|
103
103
|
else
|
104
|
-
raise NotImplementedError, "Cannot parse value of type #{type}"
|
104
|
+
raise NotImplementedError, "Cannot parse value of type #{type.inspect}"
|
105
105
|
end
|
106
106
|
end
|
107
107
|
end
|
data/lib/monetdb/version.rb
CHANGED
@@ -0,0 +1,86 @@
|
|
1
|
+
require_relative "../../test_helper"
|
2
|
+
|
3
|
+
module Unit
|
4
|
+
module Connection
|
5
|
+
class TestIO < MiniTest::Test
|
6
|
+
|
7
|
+
class Connection < SimpleConnection
|
8
|
+
include MonetDB::Connection::Messages
|
9
|
+
include MonetDB::Connection::IO
|
10
|
+
end
|
11
|
+
|
12
|
+
describe MonetDB::Connection::IO do
|
13
|
+
before do
|
14
|
+
@connection = Connection.new
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#read" do
|
18
|
+
describe "when disconnected" do
|
19
|
+
it "raises a connection error" do
|
20
|
+
assert_raises MonetDB::ConnectionError do
|
21
|
+
@connection.send(:read)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "when connected" do
|
27
|
+
it "obtains the block size and reads the server response" do
|
28
|
+
socket = mock
|
29
|
+
@connection.instance_variable_set(:@socket, socket)
|
30
|
+
|
31
|
+
first_chunk = " " * 44
|
32
|
+
last_chunk = " " * 22
|
33
|
+
|
34
|
+
socket.expects(:recv).with(2).returns("\x85\x00")
|
35
|
+
socket.expects(:recv).with(66).returns(first_chunk)
|
36
|
+
socket.expects(:recv).with(22).returns(last_chunk)
|
37
|
+
|
38
|
+
assert_equal first_chunk + last_chunk, @connection.send(:read)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#write" do
|
44
|
+
describe "when disconnected" do
|
45
|
+
it "raises a connection error" do
|
46
|
+
assert_raises MonetDB::ConnectionError do
|
47
|
+
@connection.send(:write, "")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "when connected" do
|
53
|
+
it "writes chunks to the active socket provided with the length header" do
|
54
|
+
socket = mock
|
55
|
+
socket.expects(:write).with("\f\x00Hello")
|
56
|
+
socket.expects(:write).with("\t\x00World!")
|
57
|
+
|
58
|
+
@connection.instance_variable_set(:@socket, socket)
|
59
|
+
@connection.expects(:pack).with("foo bar").returns(["\f\x00Hello", "\t\x00World!"])
|
60
|
+
|
61
|
+
assert_equal true, @connection.send(:write, "foo bar")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#pack" do
|
67
|
+
it "returns chunks provided with a length header" do
|
68
|
+
message = "BIG:monetdb:{MD5}6432e841c9943d524b9b922ee1e5924a:sql:test_drive:"
|
69
|
+
assert_equal ["#{[131].pack("v")}#{message}"], @connection.send(:pack, message)
|
70
|
+
|
71
|
+
message = "hKszBZEmQ1uOPYrpVFEc:merovingian:9:RIPEMD160,SHA256,SHA1,MD5:LIT:SHA512:"
|
72
|
+
assert_equal ["#{[145].pack("v")}#{message}"], @connection.send(:pack, message)
|
73
|
+
|
74
|
+
message.expects(:scan).with(/.{1,#{MonetDB::Connection::MAX_MSG_SIZE}}/m).returns(%w(foobar bazqux paul))
|
75
|
+
assert_equal [
|
76
|
+
"#{[12].pack("v")}foobar",
|
77
|
+
"#{[12].pack("v")}bazqux",
|
78
|
+
"#{[9].pack("v")}paul"
|
79
|
+
], @connection.send(:pack, message)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -14,6 +14,80 @@ module Unit
|
|
14
14
|
@connection = Connection.new
|
15
15
|
end
|
16
16
|
|
17
|
+
describe "#query" do
|
18
|
+
describe "when disconnected" do
|
19
|
+
it "raises a connection error" do
|
20
|
+
assert_raises MonetDB::ConnectionError do
|
21
|
+
@connection.query("")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "when connected" do
|
27
|
+
before do
|
28
|
+
@connection.instance_variable_set(:@socket, mock)
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "when doing a select query" do
|
32
|
+
describe "when returning the correct amount of records" do
|
33
|
+
it "returns the result set" do
|
34
|
+
query = "SELECT * FROM foo_bars"
|
35
|
+
response = <<-RESPONSE
|
36
|
+
&1 0 2 2 2
|
37
|
+
% sys.foo_bars,\tsys.foo_bars # table_name
|
38
|
+
% id,\tname # name
|
39
|
+
% int,\tvarchar # type
|
40
|
+
% 2,\t17 # length
|
41
|
+
[ 1,\t"Paul Engel"\t]
|
42
|
+
[ 2,\t"Ken Adams"\t]
|
43
|
+
RESPONSE
|
44
|
+
|
45
|
+
@connection.expects(:write).with("s#{query};")
|
46
|
+
@connection.expects(:read).returns(response.strip)
|
47
|
+
|
48
|
+
assert_equal [
|
49
|
+
[1, "Paul Engel"],
|
50
|
+
[2, "Ken Adams"]
|
51
|
+
], @connection.query(query)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "when not returning the correct amount of records" do
|
56
|
+
it "raises a query error" do
|
57
|
+
query = "SELECT * FROM foo_bars"
|
58
|
+
response = <<-RESPONSE
|
59
|
+
&1 0 3 2 2
|
60
|
+
% sys.foo_bars,\tsys.foo_bars # table_name
|
61
|
+
% id,\tname # name
|
62
|
+
% int,\tvarchar # type
|
63
|
+
% 2,\t17 # length
|
64
|
+
[ 1,\t"Paul Engel"\t]
|
65
|
+
[ 2,\t"Ken Adams"\t]
|
66
|
+
RESPONSE
|
67
|
+
|
68
|
+
@connection.expects(:write).with("s#{query};")
|
69
|
+
@connection.expects(:read).returns(response.strip)
|
70
|
+
|
71
|
+
assert_raises MonetDB::QueryError do
|
72
|
+
@connection.query(query)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "when doing another query" do
|
79
|
+
it "returns true" do
|
80
|
+
query = "UPDATE foo_bars SET updated_at = NOW()"
|
81
|
+
|
82
|
+
@connection.expects(:write).with("s#{query};")
|
83
|
+
@connection.expects(:read).returns("&2 23 -1")
|
84
|
+
|
85
|
+
assert_equal true, @connection.query(query)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
17
91
|
describe "#extract_headers!" do
|
18
92
|
it "returns an array with delegated return values" do
|
19
93
|
response, foo, bar = mock, mock, mock
|
@@ -106,72 +106,6 @@ module Unit
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
end
|
109
|
-
|
110
|
-
describe "#read" do
|
111
|
-
describe "when disconnected" do
|
112
|
-
it "raises a connection error" do
|
113
|
-
assert_raises MonetDB::ConnectionError do
|
114
|
-
@connection.send(:read)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
describe "when connected" do
|
120
|
-
it "obtains the block size and reads the server response" do
|
121
|
-
socket = mock
|
122
|
-
@connection.instance_variable_set(:@socket, socket)
|
123
|
-
|
124
|
-
first_chunk = " " * 44
|
125
|
-
last_chunk = " " * 22
|
126
|
-
|
127
|
-
socket.expects(:recv).with(2).returns("\x85\x00")
|
128
|
-
socket.expects(:recv).with(66).returns(first_chunk)
|
129
|
-
socket.expects(:recv).with(22).returns(last_chunk)
|
130
|
-
|
131
|
-
assert_equal first_chunk + last_chunk, @connection.send(:read)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
describe "#write" do
|
137
|
-
describe "when disconnected" do
|
138
|
-
it "raises a connection error" do
|
139
|
-
assert_raises MonetDB::ConnectionError do
|
140
|
-
@connection.send(:write, "")
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
describe "when connected" do
|
146
|
-
it "writes chunks to the active socket provided with the length header" do
|
147
|
-
socket = mock
|
148
|
-
socket.expects(:write).with("\f\x00Hello")
|
149
|
-
socket.expects(:write).with("\t\x00World!")
|
150
|
-
|
151
|
-
@connection.instance_variable_set(:@socket, socket)
|
152
|
-
@connection.expects(:pack).with("foo bar").returns(["\f\x00Hello", "\t\x00World!"])
|
153
|
-
|
154
|
-
assert_equal true, @connection.send(:write, "foo bar")
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
describe "#pack" do
|
160
|
-
it "returns chunks provided with a length header" do
|
161
|
-
message = "BIG:monetdb:{MD5}6432e841c9943d524b9b922ee1e5924a:sql:test_drive:"
|
162
|
-
assert_equal ["#{[131].pack("v")}#{message}"], @connection.send(:pack, message)
|
163
|
-
|
164
|
-
message = "hKszBZEmQ1uOPYrpVFEc:merovingian:9:RIPEMD160,SHA256,SHA1,MD5:LIT:SHA512:"
|
165
|
-
assert_equal ["#{[145].pack("v")}#{message}"], @connection.send(:pack, message)
|
166
|
-
|
167
|
-
message.expects(:scan).with(/.{1,#{MonetDB::Connection::MAX_MSG_SIZE}}/m).returns(%w(foobar bazqux paul))
|
168
|
-
assert_equal [
|
169
|
-
"#{[12].pack("v")}foobar",
|
170
|
-
"#{[12].pack("v")}bazqux",
|
171
|
-
"#{[9].pack("v")}paul"
|
172
|
-
], @connection.send(:pack, message)
|
173
|
-
end
|
174
|
-
end
|
175
109
|
end
|
176
110
|
|
177
111
|
end
|
data/test/unit/test_monetdb.rb
CHANGED
@@ -7,7 +7,7 @@ module Unit
|
|
7
7
|
it "has the current version" do
|
8
8
|
version = File.read(path("VERSION")).strip
|
9
9
|
assert_equal version, MonetDB::VERSION
|
10
|
-
assert File.read(path "CHANGELOG.rdoc").include?("Version #{version}")
|
10
|
+
assert File.read(path "CHANGELOG.rdoc").include?("Version #{version} ")
|
11
11
|
end
|
12
12
|
|
13
13
|
describe ".logger" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: monetdb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Engel
|
@@ -125,6 +125,7 @@ files:
|
|
125
125
|
- VERSION
|
126
126
|
- lib/monetdb.rb
|
127
127
|
- lib/monetdb/connection.rb
|
128
|
+
- lib/monetdb/connection/io.rb
|
128
129
|
- lib/monetdb/connection/messages.rb
|
129
130
|
- lib/monetdb/connection/query.rb
|
130
131
|
- lib/monetdb/connection/setup.rb
|
@@ -136,6 +137,7 @@ files:
|
|
136
137
|
- test/test_helper/coverage.rb
|
137
138
|
- test/test_helper/minitest.rb
|
138
139
|
- test/test_helper/simple_connection.rb
|
140
|
+
- test/unit/connection/test_io.rb
|
139
141
|
- test/unit/connection/test_messages.rb
|
140
142
|
- test/unit/connection/test_query.rb
|
141
143
|
- test/unit/connection/test_setup.rb
|
@@ -169,6 +171,7 @@ test_files:
|
|
169
171
|
- test/test_helper/coverage.rb
|
170
172
|
- test/test_helper/minitest.rb
|
171
173
|
- test/test_helper/simple_connection.rb
|
174
|
+
- test/unit/connection/test_io.rb
|
172
175
|
- test/unit/connection/test_messages.rb
|
173
176
|
- test/unit/connection/test_query.rb
|
174
177
|
- test/unit/connection/test_setup.rb
|