data_objects 0.10.0 → 0.10.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.
- data/ChangeLog.markdown +20 -0
- data/LICENSE +1 -29
- data/README.markdown +16 -2
- data/Rakefile +41 -7
- data/lib/data_objects.rb +3 -2
- data/lib/data_objects/byte_array.rb +6 -0
- data/lib/data_objects/connection.rb +21 -9
- data/lib/data_objects/logger.rb +15 -15
- data/lib/data_objects/pooling.rb +250 -0
- data/lib/data_objects/reader.rb +16 -0
- data/lib/data_objects/spec/bacon.rb +9 -0
- data/lib/data_objects/spec/command_spec.rb +54 -47
- data/lib/data_objects/spec/connection_spec.rb +119 -30
- data/lib/data_objects/spec/encoding_spec.rb +64 -6
- data/lib/data_objects/spec/helpers/immediate_red_green_output.rb +59 -0
- data/lib/data_objects/spec/helpers/pending.rb +22 -0
- data/lib/data_objects/spec/helpers/ssl.rb +21 -0
- data/lib/data_objects/spec/reader_spec.rb +47 -24
- data/lib/data_objects/spec/result_spec.rb +10 -19
- data/lib/data_objects/spec/typecast/array_spec.rb +16 -20
- data/lib/data_objects/spec/typecast/bigdecimal_spec.rb +16 -24
- data/lib/data_objects/spec/typecast/boolean_spec.rb +16 -24
- data/lib/data_objects/spec/typecast/byte_array_spec.rb +11 -15
- data/lib/data_objects/spec/typecast/class_spec.rb +7 -11
- data/lib/data_objects/spec/typecast/date_spec.rb +17 -25
- data/lib/data_objects/spec/typecast/datetime_spec.rb +18 -26
- data/lib/data_objects/spec/typecast/float_spec.rb +19 -27
- data/lib/data_objects/spec/typecast/integer_spec.rb +10 -14
- data/lib/data_objects/spec/typecast/nil_spec.rb +18 -30
- data/lib/data_objects/spec/typecast/other_spec.rb +45 -0
- data/lib/data_objects/spec/typecast/range_spec.rb +16 -20
- data/lib/data_objects/spec/typecast/string_spec.rb +72 -13
- data/lib/data_objects/spec/typecast/time_spec.rb +11 -15
- data/lib/data_objects/utilities.rb +18 -0
- data/lib/data_objects/version.rb +1 -2
- data/spec/command_spec.rb +2 -2
- data/spec/connection_spec.rb +7 -5
- data/spec/do_mock2.rb +31 -0
- data/spec/pooling_spec.rb +162 -0
- data/spec/reader_spec.rb +7 -4
- data/spec/result_spec.rb +2 -2
- data/spec/spec_helper.rb +26 -5
- data/spec/transaction_spec.rb +11 -9
- data/tasks/metrics.rake +36 -0
- data/tasks/release.rake +10 -70
- data/tasks/spec.rake +16 -14
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +53 -27
- data/HISTORY.markdown +0 -7
- data/Manifest.txt +0 -44
- data/spec/lib/pending_helpers.rb +0 -11
- data/spec/lib/rspec_immediate_feedback_formatter.rb +0 -53
- data/spec/lib/ssl_helpers.rb +0 -20
- data/tasks/gem.rake +0 -8
- data/tasks/install.rake +0 -13
@@ -1,15 +1,15 @@
|
|
1
|
-
|
1
|
+
shared 'a driver supporting different encodings' do
|
2
2
|
|
3
|
-
before
|
3
|
+
before do
|
4
4
|
@connection = DataObjects::Connection.new(CONFIG.uri)
|
5
5
|
end
|
6
6
|
|
7
|
-
after
|
7
|
+
after do
|
8
8
|
@connection.close
|
9
9
|
end
|
10
10
|
|
11
11
|
|
12
|
-
it
|
12
|
+
it 'should respond to #character_set' do @connection.should.respond_to(:character_set) end
|
13
13
|
|
14
14
|
describe 'character_set' do
|
15
15
|
|
@@ -25,7 +25,9 @@ share_examples_for 'a driver supporting encodings' do
|
|
25
25
|
|
26
26
|
after { @latin1_connection.close }
|
27
27
|
|
28
|
-
it
|
28
|
+
it 'the character set should be ISO-8859-1' do
|
29
|
+
@latin1_connection.character_set.should == 'ISO-8859-1'
|
30
|
+
end
|
29
31
|
end
|
30
32
|
|
31
33
|
describe 'uses UTF-8 when an invalid encoding is given' do
|
@@ -35,9 +37,65 @@ share_examples_for 'a driver supporting encodings' do
|
|
35
37
|
|
36
38
|
after { @latin1_connection.close }
|
37
39
|
|
38
|
-
it
|
40
|
+
it 'the character set should be UTF-8' do
|
41
|
+
@latin1_connection.character_set.should == 'UTF-8'
|
42
|
+
end
|
39
43
|
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
shared 'returning correctly encoded strings for the default encoding' do
|
48
|
+
|
49
|
+
|
50
|
+
setup_test_environment
|
51
|
+
|
52
|
+
before do
|
53
|
+
@connection = DataObjects::Connection.new(CONFIG.uri)
|
54
|
+
end
|
55
|
+
|
56
|
+
after do
|
57
|
+
@connection.close
|
58
|
+
end
|
59
|
+
|
60
|
+
if defined?(::Encoding)
|
61
|
+
describe 'with encoded string support' do
|
40
62
|
|
63
|
+
describe 'reading a String' do
|
64
|
+
before do
|
65
|
+
@reader = @connection.create_command("SELECT name FROM widgets WHERE ad_description = ?").execute_reader('Buy this product now!')
|
66
|
+
@reader.next!
|
67
|
+
@values = @reader.values
|
68
|
+
end
|
69
|
+
|
70
|
+
after do
|
71
|
+
@reader.close
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should return UTF-8 encoded String' do
|
75
|
+
@values.first.should.be.kind_of(String)
|
76
|
+
@values.first.encoding.name.should == 'UTF-8'
|
77
|
+
end
|
78
|
+
end
|
41
79
|
|
80
|
+
describe 'reading a ByteArray' do
|
81
|
+
before do
|
82
|
+
@command = @connection.create_command("SELECT ad_image FROM widgets WHERE ad_description = ?")
|
83
|
+
@command.set_types(Extlib::ByteArray)
|
84
|
+
@reader = @command.execute_reader('Buy this product now!')
|
85
|
+
@reader.next!
|
86
|
+
@values = @reader.values
|
87
|
+
end
|
88
|
+
|
89
|
+
after do
|
90
|
+
@reader.close
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should return ASCII-8BIT encoded ByteArray' do
|
94
|
+
@values.first.should.be.kind_of(::Extlib::ByteArray)
|
95
|
+
@values.first.encoding.name.should == 'ASCII-8BIT'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
42
99
|
end
|
100
|
+
|
43
101
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Bacon
|
2
|
+
module ImmediateRedGreenOutput
|
3
|
+
|
4
|
+
def handle_specification(name)
|
5
|
+
yield
|
6
|
+
@current_group = name
|
7
|
+
end
|
8
|
+
|
9
|
+
def handle_requirement(description)
|
10
|
+
error = yield
|
11
|
+
if error.empty?
|
12
|
+
example_passed
|
13
|
+
elsif error == 'PENDING'
|
14
|
+
example_pending
|
15
|
+
else
|
16
|
+
example_failed(error, description, Counter[:specifications])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def handle_summary
|
21
|
+
puts
|
22
|
+
puts ErrorLog
|
23
|
+
counter = Counter.values_at(:specifications, :requirements, :failed, :errors, :pending)
|
24
|
+
message = ("%d tests, %d assertions, %d failures, %d errors, %d pending" % counter)
|
25
|
+
color = (counter[2].to_i != 0 || counter[3].to_i != 0 ? :red : (counter[4].to_i != 0 ? :yellow : :green))
|
26
|
+
puts self.send(color, message)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def example_failed(error, description, counter)
|
32
|
+
if @current_group
|
33
|
+
puts
|
34
|
+
puts @current_group
|
35
|
+
@current_group = nil # only print the group name once
|
36
|
+
end
|
37
|
+
|
38
|
+
if error == 'FAILED'
|
39
|
+
puts red("- #{description} (FAILED - #{counter})")
|
40
|
+
puts ErrorLog if Backtraces # dump stacktrace immediately
|
41
|
+
else
|
42
|
+
puts red("- #{description} (ERROR - #{counter})")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def example_passed
|
47
|
+
print green('.')
|
48
|
+
end
|
49
|
+
|
50
|
+
def example_pending
|
51
|
+
print yellow('*')
|
52
|
+
end
|
53
|
+
|
54
|
+
def red(s) "\e[31m#{s}\e[0m"; end
|
55
|
+
def green(s) "\e[32m#{s}\e[0m"; end
|
56
|
+
def yellow(s) "\e[33m#{s}\e[0m"; end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module DataObjects::Spec
|
2
|
+
module Pending
|
3
|
+
|
4
|
+
def pending(message = '')
|
5
|
+
raise Bacon::Error.new(:pending, message)
|
6
|
+
end
|
7
|
+
|
8
|
+
def pending_if(message, boolean)
|
9
|
+
if boolean
|
10
|
+
pending(message) { yield }
|
11
|
+
else
|
12
|
+
yield
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Bacon
|
19
|
+
class Context
|
20
|
+
include DataObjects::Spec::Pending
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
module SSLHelpers
|
5
|
+
|
6
|
+
CERTS_DIR = Pathname(__FILE__).dirname.join('ssl_certs').to_s
|
7
|
+
|
8
|
+
CONFIG = OpenStruct.new
|
9
|
+
CONFIG.ca_cert = File.join(CERTS_DIR, 'ca-cert.pem')
|
10
|
+
CONFIG.ca_key = File.join(CERTS_DIR, 'ca-key.pem')
|
11
|
+
CONFIG.server_cert = File.join(CERTS_DIR, 'server-cert.pem')
|
12
|
+
CONFIG.server_key = File.join(CERTS_DIR, 'server-key.pem')
|
13
|
+
CONFIG.client_cert = File.join(CERTS_DIR, 'client-cert.pem')
|
14
|
+
CONFIG.client_key = File.join(CERTS_DIR, 'client-key.pem')
|
15
|
+
CONFIG.cipher = 'AES128-SHA'
|
16
|
+
|
17
|
+
def self.query(*keys)
|
18
|
+
keys.map { |key| "ssl[#{key}]=#{CGI::escape(CONFIG.send(key))}" }.join('&')
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -1,22 +1,18 @@
|
|
1
|
-
|
1
|
+
shared 'a Reader' do
|
2
2
|
|
3
|
-
|
3
|
+
setup_test_environment
|
4
4
|
|
5
|
-
before
|
6
|
-
setup_test_environment
|
7
|
-
end
|
8
|
-
|
9
|
-
before :each do
|
5
|
+
before do
|
10
6
|
@connection = DataObjects::Connection.new(CONFIG.uri)
|
11
7
|
@reader = @connection.create_command("SELECT code, name FROM widgets WHERE ad_description = ? order by id").execute_reader('Buy this product now!')
|
12
8
|
end
|
13
9
|
|
14
|
-
after
|
10
|
+
after do
|
15
11
|
@reader.close
|
16
12
|
@connection.close
|
17
13
|
end
|
18
14
|
|
19
|
-
it
|
15
|
+
it 'should respond to #fields' do @reader.should.respond_to(:fields) end
|
20
16
|
|
21
17
|
describe 'fields' do
|
22
18
|
|
@@ -28,21 +24,21 @@ share_examples_for 'a Reader' do
|
|
28
24
|
|
29
25
|
end
|
30
26
|
|
31
|
-
it
|
27
|
+
it 'should respond to #values' do @reader.should.respond_to(:values) end
|
32
28
|
|
33
29
|
describe 'values' do
|
34
30
|
|
35
31
|
describe 'when the reader is uninitialized' do
|
36
32
|
|
37
33
|
it 'should raise an error' do
|
38
|
-
|
34
|
+
should.raise(DataObjects::DataError) { @reader.values }
|
39
35
|
end
|
40
36
|
|
41
37
|
end
|
42
38
|
|
43
39
|
describe 'when the reader is moved to the first result' do
|
44
40
|
|
45
|
-
before
|
41
|
+
before do
|
46
42
|
@reader.next!
|
47
43
|
end
|
48
44
|
|
@@ -54,7 +50,7 @@ share_examples_for 'a Reader' do
|
|
54
50
|
|
55
51
|
describe 'when the reader is moved to the second result' do
|
56
52
|
|
57
|
-
before
|
53
|
+
before do
|
58
54
|
@reader.next!; @reader.next!
|
59
55
|
end
|
60
56
|
|
@@ -71,20 +67,20 @@ share_examples_for 'a Reader' do
|
|
71
67
|
end
|
72
68
|
|
73
69
|
it 'should raise an error again' do
|
74
|
-
|
70
|
+
should.raise(DataObjects::DataError) { @reader.values }
|
75
71
|
end
|
76
72
|
end
|
77
73
|
|
78
74
|
end
|
79
75
|
|
80
|
-
it
|
76
|
+
it 'should respond to #close' do @reader.should.respond_to(:close) end
|
81
77
|
|
82
78
|
describe 'close' do
|
83
79
|
|
84
80
|
describe 'on an open reader' do
|
85
81
|
|
86
82
|
it 'should return true' do
|
87
|
-
@reader.close.should
|
83
|
+
@reader.close.should.be.true
|
88
84
|
end
|
89
85
|
|
90
86
|
end
|
@@ -96,21 +92,21 @@ share_examples_for 'a Reader' do
|
|
96
92
|
end
|
97
93
|
|
98
94
|
it 'should return false' do
|
99
|
-
@reader.close.should
|
95
|
+
@reader.close.should.be.false
|
100
96
|
end
|
101
97
|
|
102
98
|
end
|
103
99
|
|
104
100
|
end
|
105
101
|
|
106
|
-
it
|
102
|
+
it 'should respond to #next!' do @reader.should.respond_to(:next!) end
|
107
103
|
|
108
104
|
describe 'next!' do
|
109
105
|
|
110
106
|
describe 'successfully moving the cursor initially' do
|
111
107
|
|
112
108
|
it 'should return true' do
|
113
|
-
@reader.next!.should
|
109
|
+
@reader.next!.should.be.true
|
114
110
|
end
|
115
111
|
|
116
112
|
end
|
@@ -122,9 +118,9 @@ share_examples_for 'a Reader' do
|
|
122
118
|
end
|
123
119
|
|
124
120
|
it 'should move the cursor to the next value' do
|
125
|
-
|
126
|
-
|
127
|
-
|
121
|
+
@reader.values.should == ["W0000001", "Widget 1"]
|
122
|
+
lambda { @reader.next! }.should.change { @reader.values }
|
123
|
+
@reader.values.should == ["W0000002", "Widget 2"]
|
128
124
|
end
|
129
125
|
|
130
126
|
end
|
@@ -136,14 +132,14 @@ share_examples_for 'a Reader' do
|
|
136
132
|
end
|
137
133
|
|
138
134
|
it 'should return false when the end is reached' do
|
139
|
-
@reader.next!.should
|
135
|
+
@reader.next!.should.be.false
|
140
136
|
end
|
141
137
|
|
142
138
|
end
|
143
139
|
|
144
140
|
end
|
145
141
|
|
146
|
-
it
|
142
|
+
it 'should respond to #field_count' do @reader.should.respond_to(:field_count) end
|
147
143
|
|
148
144
|
describe 'field_count' do
|
149
145
|
|
@@ -153,4 +149,31 @@ share_examples_for 'a Reader' do
|
|
153
149
|
|
154
150
|
end
|
155
151
|
|
152
|
+
it 'should respond to #values' do @reader.should.respond_to(:values) end
|
153
|
+
|
154
|
+
describe 'each' do
|
155
|
+
|
156
|
+
it 'should yield each row to the block' do
|
157
|
+
rows_yielded = 0
|
158
|
+
@reader.each do |row|
|
159
|
+
row.should.respond_to(:[])
|
160
|
+
|
161
|
+
row.size.should == 2
|
162
|
+
|
163
|
+
# the field names need to be case insensitive as some drivers such as
|
164
|
+
# do_derby, do_h2, do_hsqldb return the field names as uppercase
|
165
|
+
(row['name'] || row['NAME']).should.be.kind_of(String)
|
166
|
+
(row['code'] || row['CODE']).should.be.kind_of(String)
|
167
|
+
|
168
|
+
rows_yielded += 1
|
169
|
+
end
|
170
|
+
rows_yielded.should == 15
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should return the reader' do
|
174
|
+
@reader.each { |row| }.should.equal(@reader)
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
156
179
|
end
|
@@ -1,21 +1,17 @@
|
|
1
|
-
|
1
|
+
shared 'a Result' do
|
2
2
|
|
3
|
-
|
3
|
+
setup_test_environment
|
4
4
|
|
5
|
-
before
|
6
|
-
setup_test_environment
|
7
|
-
end
|
8
|
-
|
9
|
-
before :each do
|
5
|
+
before do
|
10
6
|
@connection = DataObjects::Connection.new(CONFIG.uri)
|
11
7
|
@result = @connection.create_command("INSERT INTO users (name) VALUES (?)").execute_non_query("monkey")
|
12
8
|
end
|
13
9
|
|
14
|
-
after
|
10
|
+
after do
|
15
11
|
@connection.close
|
16
12
|
end
|
17
13
|
|
18
|
-
it
|
14
|
+
it 'should respond to #affected_rows' do @result.should.respond_to(:affected_rows) end
|
19
15
|
|
20
16
|
describe 'affected_rows' do
|
21
17
|
|
@@ -27,15 +23,10 @@ share_examples_for 'a Result' do
|
|
27
23
|
|
28
24
|
end
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
include DataObjectsSpecHelpers
|
26
|
+
shared 'a Result which returns inserted keys' do
|
33
27
|
|
34
|
-
before
|
28
|
+
before do
|
35
29
|
setup_test_environment
|
36
|
-
end
|
37
|
-
|
38
|
-
before :each do
|
39
30
|
@connection = DataObjects::Connection.new(CONFIG.uri)
|
40
31
|
command = @connection.create_command("INSERT INTO users (name) VALUES (?)")
|
41
32
|
# execute the command twice and expose the second result
|
@@ -43,15 +34,15 @@ share_examples_for 'a Result which returns inserted keys' do
|
|
43
34
|
@result = command.execute_non_query("monkey")
|
44
35
|
end
|
45
36
|
|
46
|
-
after
|
37
|
+
after do
|
47
38
|
@connection.close
|
48
39
|
end
|
49
40
|
|
50
|
-
it
|
41
|
+
it 'should respond to #affected_rows' do @result.should.respond_to(:affected_rows) end
|
51
42
|
|
52
43
|
describe 'insert_id' do
|
53
44
|
|
54
|
-
it 'should return the
|
45
|
+
it 'should return the insert_id' do
|
55
46
|
# This is actually the 2nd record inserted
|
56
47
|
@result.insert_id.should == 2
|
57
48
|
end
|
@@ -1,36 +1,32 @@
|
|
1
|
-
|
1
|
+
shared 'supporting Array' do
|
2
2
|
|
3
|
-
|
3
|
+
setup_test_environment
|
4
4
|
|
5
|
-
before
|
6
|
-
setup_test_environment
|
7
|
-
end
|
8
|
-
|
9
|
-
before :each do
|
5
|
+
before do
|
10
6
|
@connection = DataObjects::Connection.new(CONFIG.uri)
|
11
7
|
end
|
12
8
|
|
13
|
-
after
|
9
|
+
after do
|
14
10
|
@connection.close
|
15
11
|
end
|
16
12
|
|
17
13
|
describe 'passing an Array as a parameter in execute_reader' do
|
18
14
|
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
before do
|
16
|
+
@reader = @connection.create_command("SELECT * FROM widgets WHERE id in ?").execute_reader([2,3,4,5])
|
17
|
+
end
|
22
18
|
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
after do
|
20
|
+
@reader.close
|
21
|
+
end
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
32
|
-
counter.should == 4
|
23
|
+
it 'should return correct number of rows' do
|
24
|
+
counter = 0
|
25
|
+
while(@reader.next!) do
|
26
|
+
counter += 1
|
33
27
|
end
|
28
|
+
counter.should == 4
|
29
|
+
end
|
34
30
|
|
35
31
|
end
|
36
32
|
end
|