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