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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b124803dcab2b1006f95c5bfd252d1982350ae6c
4
- data.tar.gz: 7472c8d1410fa5cd5e39bb79dea8059c43d5ba7a
3
+ metadata.gz: a5ec545e31663df97597447cdbd33b25e2d88c86
4
+ data.tar.gz: f3bc08654b1fac1b7cc99988e269aa8d3707c412
5
5
  SHA512:
6
- metadata.gz: b894e704798f71cd4791a4c019fde839a69cb75c89d30073210c8032e0e8e042da347cf786bdb8615dd86a26fe946994f6513e0d9b4ed238811da96f8ef44f71
7
- data.tar.gz: 7bc0cd53a34cf88e7c85c5ede1343fe35e3a63ab9659b9c427a7a582f6a2df33f93f167703bd3d434cff036914faea273ce6d450ca282846428fb9ccfe29d69e
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.0
1
+ 0.2.1
@@ -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
@@ -1,7 +1,7 @@
1
1
  module MonetDB
2
2
  MAJOR = 0
3
3
  MINOR = 2
4
- TINY = 0
4
+ TINY = 1
5
5
 
6
6
  VERSION = [MAJOR, MINOR, TINY].join(".")
7
7
  end
@@ -10,4 +10,14 @@ class SimpleConnection
10
10
  }
11
11
  end
12
12
 
13
+ def connected?
14
+ !@socket.nil?
15
+ end
16
+
17
+ private
18
+
19
+ def socket
20
+ @socket
21
+ end
22
+
13
23
  end
@@ -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
@@ -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.0
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