monetdb 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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