monetdb 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZWIxMjU2MTVlNWE5OGI2NmM5OTM5MjljZWVkNTQ2NzViOTUxMDAyOA==
4
+ Mjg1NWNmZjNmOWY2M2M5OWIwZDcxY2Y0ODA3ODBmNDc0MzgyYWFiMA==
5
5
  data.tar.gz: !binary |-
6
- ZmU2YTQ4ZDhkOTk0NGVlMDY0ZTg4ODU4NjA5MThhM2U1YTc1ZjNmZQ==
6
+ OWIxYTQzZTYyYTQzZmYzZWZkNjE5NWFmNDllNDcyZjgwNDk1MzZlMw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NjJmYzAxZGQ1MmY0ZDk4OWU3MzViNzYyYTNhMTVmYjhiZWEyZWM2YjZlMmYw
10
- YWVhOTA5NWM1YWNlZmM3NTc5ZDJhNjQ1MDU4NWJlZTQyYTIwZWEyNzcxNjM4
11
- N2VlZTc2ZGY4OGM4N2Y2MjBiYjZiYmFhYzU3Y2JiMzIxNTU2ZmU=
9
+ YTk1ODNlMDViZDVlZWE5MDRlNmEzOTc3Y2MyNjE0MWFjYWUyNjJhM2ZlYzJm
10
+ ODZiNjNlMTViZjg5MzFkMTgxMDJjMWU5YmJhNGVhM2Y3OWE3MjJhMzMyZWI3
11
+ YmYzNThkMzgxOTUxZTE4OTAzZWNhM2RlNDA2MmYzZDIzMjAwODU=
12
12
  data.tar.gz: !binary |-
13
- NDM2MWJlNjg0NTkzNTY5ZjhmNTdhM2E0M2I4MjIzZDYyZjMwMjdjN2VhMmY3
14
- OGU1MzQ0YWE2NzczNjhjODAyOTI3MTgyZTExYTc5Yzg1OGEwOGNlN2JkY2Y1
15
- NGI2YTg3MjUxYjkxYWFmMWVmNmIyYjY3ZmVmNzE0YzhlMDI1MGU=
13
+ YWZlZjUyYjhiODEyZjdiMjBmMzkxNzk4NmMxZmRkMDVmNDU0Mzg0N2Q1ODRj
14
+ NDdiZDVmYzA1ZGI0MjkxMjhhOTc4YzFiMDU4MTM3ZjQzNzkwZDMwNjQxMDlk
15
+ MTU1NmVlMmViMDQwOGFkZmRkNDBkZWU1NzcxODViOWUyNmJjZDc=
data/CHANGELOG.rdoc CHANGED
@@ -1,5 +1,9 @@
1
1
  = MonetDB CHANGELOG
2
2
 
3
+ == Version 0.2.4 (October 29, 2014)
4
+
5
+ * Being able to reconnect after getting invalid query header error
6
+
3
7
  == Version 0.2.3 (October 22, 2014)
4
8
 
5
9
  * Dropped activesupport dependency
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.3
1
+ 0.2.4
@@ -63,13 +63,21 @@ module MonetDB
63
63
  true
64
64
  end
65
65
 
66
+ def disconnect
67
+ socket.disconnect if connected?
68
+ @socket = nil
69
+ end
70
+
66
71
  def connected?
67
72
  !socket.nil?
68
73
  end
69
74
 
70
- def disconnect
71
- socket.disconnect if connected?
72
- @socket = nil
75
+ def reconnect?
76
+ !!config[:reconnect]
77
+ end
78
+
79
+ def check_connectivity!
80
+ connect if reconnect? && !connected?
73
81
  end
74
82
 
75
83
  private
@@ -1,8 +1,15 @@
1
+ require "monetdb/connection/query/table"
2
+
1
3
  module MonetDB
2
4
  class Connection
3
5
  module Query
4
6
 
7
+ def self.included(base)
8
+ base.send :include, Table
9
+ end
10
+
5
11
  def query(statement)
12
+ check_connectivity!
6
13
  raise ConnectionError, "Not connected to server" unless connected?
7
14
 
8
15
  start = Time.now
@@ -11,19 +18,7 @@ module MonetDB
11
18
  response = read.split("\n")
12
19
 
13
20
  log :info, "\n SQL (#{((Time.now - start) * 1000).round(1)}ms) #{statement}"
14
-
15
- query_header, table_header = extract_headers!(response)
16
-
17
- if query_header[:type] == Q_TABLE
18
- unless query_header[:rows] == response.size
19
- raise QueryError, "Amount of fetched rows does not match header value (#{response.size} instead of #{query_header[:rows]})"
20
- end
21
- response = parse_rows(query_header, table_header, response.join("\n"))
22
- else
23
- response = true
24
- end
25
-
26
- response
21
+ parse_response response
27
22
  end
28
23
 
29
24
  alias :select_rows :query
@@ -39,6 +34,15 @@ module MonetDB
39
34
 
40
35
  private
41
36
 
37
+ def parse_response(response)
38
+ query_header, table_header = extract_headers!(response)
39
+ if query_header[:type] == Q_TABLE
40
+ parse_table_response query_header, table_header, response
41
+ else
42
+ true
43
+ end
44
+ end
45
+
42
46
  def extract_headers!(response)
43
47
  [parse_query_header!(response), parse_scheme_header!(response)]
44
48
  end
@@ -49,6 +53,7 @@ module MonetDB
49
53
  raise QueryError, header if header[0].chr == MSG_ERROR
50
54
 
51
55
  unless header[0].chr == MSG_QUERY
56
+ ENV["MONETDB_QUERY_RESPONSE"] = ([header] + response).join("\n").inspect
52
57
  raise QueryError, "Expected an query header (#{MSG_QUERY}) but got (#{header[0].chr})"
53
58
  end
54
59
 
@@ -87,67 +92,6 @@ module MonetDB
87
92
  {:table_name => table_name, :column_names => column_names, :column_types => column_types, :column_lengths => column_lengths}.freeze
88
93
  end
89
94
 
90
- def parse_rows(query_header, table_header, response)
91
- start = Time.now
92
- column_types = table_header[:column_types]
93
-
94
- response.slice(0..-3).split("\t]\n").collect do |row|
95
- parsed, values = [], row.slice(1..-1).split(",\t")
96
- values.each_with_index do |value, index|
97
- parsed << parse_value(column_types[index], value.strip)
98
- end
99
- parsed
100
- end.tap do
101
- log :info, " RUBY (#{((Time.now - start) * 1000).round(1)}ms) [ Rows: #{query_header[:rows]}, Bytesize: #{response.bytesize} bytes ]"
102
- end
103
- end
104
-
105
- def parse_value(type, value)
106
- unless value == "NULL"
107
- case type
108
- when :varchar, :text
109
- parse_string_value value
110
- when :int, :smallint, :bigint
111
- parse_integer_value value
112
- when :double, :float, :real
113
- parse_float_value value
114
- when :date
115
- parse_date_value value
116
- when :timestamp
117
- parse_date_time_value value
118
- when :tinyint
119
- parse_boolean_value value
120
- else
121
- raise NotImplementedError, "Cannot parse value of type #{type.inspect}"
122
- end
123
- end
124
- end
125
-
126
- def parse_string_value(value)
127
- value.slice(1..-2).force_encoding("UTF-8")
128
- end
129
-
130
- def parse_integer_value(value)
131
- value.to_i
132
- end
133
-
134
- def parse_float_value(value)
135
- value.to_f
136
- end
137
-
138
- def parse_date_value(value)
139
- Date.new *value.split("-").collect(&:to_i)
140
- end
141
-
142
- def parse_date_time_value(value)
143
- date, time = value.split(" ")
144
- Time.new *(date.split("-") + time.split(":")).collect(&:to_i)
145
- end
146
-
147
- def parse_boolean_value(value)
148
- value == "1"
149
- end
150
-
151
95
  end
152
96
  end
153
97
  end
@@ -0,0 +1,86 @@
1
+ module MonetDB
2
+ class Connection
3
+ module Query
4
+ module Table
5
+
6
+ def parse_table_response(query_header, table_header, response)
7
+ unless query_header[:rows] == response.size
8
+ disconnect if reconnect?
9
+ raise QueryError, "Amount of fetched rows does not match header value (#{response.size} instead of #{query_header[:rows]})"
10
+ end
11
+ parse_table_rows query_header, table_header, response.join("\n")
12
+ end
13
+
14
+ def parse_table_rows(query_header, table_header, response)
15
+ start = Time.now
16
+ rows = response.slice(0..-3).split("\t]\n")
17
+ parse_rows(table_header, rows).tap do
18
+ log :info, " RUBY (#{((Time.now - start) * 1000).round(1)}ms) [ Rows: #{query_header[:rows]}, Bytesize: #{response.bytesize} bytes ]"
19
+ end
20
+ end
21
+
22
+ def parse_rows(table_header, rows)
23
+ column_types = table_header[:column_types]
24
+ rows.collect do |row|
25
+ parse_row column_types, row
26
+ end
27
+ end
28
+
29
+ def parse_row(column_types, row)
30
+ [].tap do |parsed|
31
+ row.slice(1..-1).split(",\t").each_with_index do |value, index|
32
+ parsed << parse_value(column_types[index], value.strip)
33
+ end
34
+ end
35
+ end
36
+
37
+ def parse_value(type, value)
38
+ unless value == "NULL"
39
+ case type
40
+ when :varchar, :text
41
+ parse_string_value value
42
+ when :int, :smallint, :bigint
43
+ parse_integer_value value
44
+ when :double, :float, :real
45
+ parse_float_value value
46
+ when :date
47
+ parse_date_value value
48
+ when :timestamp
49
+ parse_date_time_value value
50
+ when :tinyint
51
+ parse_boolean_value value
52
+ else
53
+ raise NotImplementedError, "Cannot parse value of type #{type.inspect}"
54
+ end
55
+ end
56
+ end
57
+
58
+ def parse_string_value(value)
59
+ value.slice(1..-2).force_encoding("UTF-8")
60
+ end
61
+
62
+ def parse_integer_value(value)
63
+ value.to_i
64
+ end
65
+
66
+ def parse_float_value(value)
67
+ value.to_f
68
+ end
69
+
70
+ def parse_date_value(value)
71
+ Date.new *value.split("-").collect(&:to_i)
72
+ end
73
+
74
+ def parse_date_time_value(value)
75
+ date, time = value.split(" ")
76
+ Time.new *(date.split("-") + time.split(":")).collect(&:to_i)
77
+ end
78
+
79
+ def parse_boolean_value(value)
80
+ value == "1"
81
+ end
82
+
83
+ end
84
+ end
85
+ end
86
+ end
@@ -1,7 +1,7 @@
1
1
  module MonetDB
2
2
  MAJOR = 0
3
3
  MINOR = 2
4
- TINY = 3
4
+ TINY = 4
5
5
 
6
6
  VERSION = [MAJOR, MINOR, TINY].join(".")
7
7
  end
@@ -14,6 +14,13 @@ class SimpleConnection
14
14
  !@socket.nil?
15
15
  end
16
16
 
17
+ def reconnect?
18
+ false
19
+ end
20
+
21
+ def check_connectivity!
22
+ end
23
+
17
24
  private
18
25
 
19
26
  def socket
@@ -280,7 +280,7 @@ module Unit
280
280
  assert_equal [
281
281
  ["Paul Engel", Date.parse("1982-08-01"), 1709.34],
282
282
  ["Ken Adams", Date.parse("1980-10-31"), 2003.47]
283
- ], @connection.send(:parse_rows, query_header, table_header, response)
283
+ ], @connection.send(:parse_table_rows, query_header, table_header, response)
284
284
  end
285
285
  end
286
286
 
@@ -45,16 +45,6 @@ module Unit
45
45
  end
46
46
  end
47
47
 
48
- describe "#connected?" do
49
- it "returns whether it has an active socket" do
50
- assert_equal false, @connection.connected?
51
- @connection.instance_variable_set :@socket, mock
52
- assert_equal true, @connection.connected?
53
- @connection.instance_variable_set :@socket, nil
54
- assert_equal false, @connection.connected?
55
- end
56
- end
57
-
58
48
  describe "#disconnect" do
59
49
  describe "when disconnected" do
60
50
  it "does nothing" do
@@ -79,6 +69,71 @@ module Unit
79
69
  end
80
70
  end
81
71
 
72
+ describe "#connected?" do
73
+ it "returns whether it has an active socket" do
74
+ assert_equal false, @connection.connected?
75
+ @connection.instance_variable_set :@socket, mock
76
+ assert_equal true, @connection.connected?
77
+ @connection.instance_variable_set :@socket, nil
78
+ assert_equal false, @connection.connected?
79
+ end
80
+ end
81
+
82
+ describe "#reconnect?" do
83
+ describe "at default" do
84
+ it "returns false" do
85
+ assert_equal false, @connection.reconnect?
86
+ end
87
+ end
88
+
89
+ describe "when configured to true" do
90
+ it "returns true" do
91
+ @connection.instance_variable_get(:@config)[:reconnect] = true
92
+ assert_equal true, @connection.reconnect?
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "#check_connectivity!" do
98
+ describe "when configured reconnect: true" do
99
+ before do
100
+ @connection.expects(:reconnect?).returns(true)
101
+ end
102
+
103
+ describe "when disconnected" do
104
+ it "connects" do
105
+ @connection.expects(:connected?).returns(false)
106
+ @connection.expects(:connect)
107
+ @connection.check_connectivity!
108
+ end
109
+ end
110
+
111
+ describe "when connected" do
112
+ it "does nothing" do
113
+ @connection.expects(:connected?).returns(true)
114
+ @connection.expects(:connect).never
115
+ @connection.check_connectivity!
116
+ end
117
+ end
118
+ end
119
+
120
+ describe "when not configured reconnect: true" do
121
+ describe "when disconnected" do
122
+ it "does nothing" do
123
+ @connection.expects(:connect).never
124
+ @connection.check_connectivity!
125
+ end
126
+ end
127
+
128
+ describe "when connected" do
129
+ it "does nothing" do
130
+ @connection.expects(:connect).never
131
+ @connection.check_connectivity!
132
+ end
133
+ end
134
+ end
135
+ end
136
+
82
137
  describe "#socket" do
83
138
  it "returns its instance variable :@socket" do
84
139
  @connection.instance_variable_set :@socket, (socket = mock)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monetdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Engel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-22 00:00:00.000000000 Z
11
+ date: 2014-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -115,6 +115,7 @@ files:
115
115
  - lib/monetdb/connection/logger.rb
116
116
  - lib/monetdb/connection/messages.rb
117
117
  - lib/monetdb/connection/query.rb
118
+ - lib/monetdb/connection/query/table.rb
118
119
  - lib/monetdb/connection/setup.rb
119
120
  - lib/monetdb/error.rb
120
121
  - lib/monetdb/version.rb