sbf-data_objects 0.10.17
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 +7 -0
- data/ChangeLog.markdown +115 -0
- data/LICENSE +20 -0
- data/README.markdown +18 -0
- data/Rakefile +20 -0
- data/lib/data_objects/byte_array.rb +6 -0
- data/lib/data_objects/command.rb +79 -0
- data/lib/data_objects/connection.rb +95 -0
- data/lib/data_objects/error/connection_error.rb +4 -0
- data/lib/data_objects/error/data_error.rb +4 -0
- data/lib/data_objects/error/integrity_error.rb +4 -0
- data/lib/data_objects/error/sql_error.rb +17 -0
- data/lib/data_objects/error/syntax_error.rb +4 -0
- data/lib/data_objects/error/transaction_error.rb +4 -0
- data/lib/data_objects/error.rb +4 -0
- data/lib/data_objects/extension.rb +9 -0
- data/lib/data_objects/logger.rb +247 -0
- data/lib/data_objects/pooling.rb +243 -0
- data/lib/data_objects/quoting.rb +99 -0
- data/lib/data_objects/reader.rb +45 -0
- data/lib/data_objects/result.rb +21 -0
- data/lib/data_objects/spec/lib/pending_helpers.rb +13 -0
- data/lib/data_objects/spec/lib/ssl.rb +19 -0
- data/lib/data_objects/spec/setup.rb +5 -0
- data/lib/data_objects/spec/shared/command_spec.rb +201 -0
- data/lib/data_objects/spec/shared/connection_spec.rb +148 -0
- data/lib/data_objects/spec/shared/encoding_spec.rb +161 -0
- data/lib/data_objects/spec/shared/error/sql_error_spec.rb +23 -0
- data/lib/data_objects/spec/shared/quoting_spec.rb +0 -0
- data/lib/data_objects/spec/shared/reader_spec.rb +180 -0
- data/lib/data_objects/spec/shared/result_spec.rb +67 -0
- data/lib/data_objects/spec/shared/typecast/array_spec.rb +29 -0
- data/lib/data_objects/spec/shared/typecast/bigdecimal_spec.rb +112 -0
- data/lib/data_objects/spec/shared/typecast/boolean_spec.rb +133 -0
- data/lib/data_objects/spec/shared/typecast/byte_array_spec.rb +76 -0
- data/lib/data_objects/spec/shared/typecast/class_spec.rb +53 -0
- data/lib/data_objects/spec/shared/typecast/date_spec.rb +114 -0
- data/lib/data_objects/spec/shared/typecast/datetime_spec.rb +140 -0
- data/lib/data_objects/spec/shared/typecast/float_spec.rb +115 -0
- data/lib/data_objects/spec/shared/typecast/integer_spec.rb +92 -0
- data/lib/data_objects/spec/shared/typecast/ipaddr_spec.rb +0 -0
- data/lib/data_objects/spec/shared/typecast/nil_spec.rb +107 -0
- data/lib/data_objects/spec/shared/typecast/other_spec.rb +41 -0
- data/lib/data_objects/spec/shared/typecast/range_spec.rb +29 -0
- data/lib/data_objects/spec/shared/typecast/string_spec.rb +130 -0
- data/lib/data_objects/spec/shared/typecast/time_spec.rb +111 -0
- data/lib/data_objects/transaction.rb +111 -0
- data/lib/data_objects/uri.rb +109 -0
- data/lib/data_objects/utilities.rb +18 -0
- data/lib/data_objects/version.rb +3 -0
- data/lib/data_objects.rb +20 -0
- data/spec/command_spec.rb +24 -0
- data/spec/connection_spec.rb +31 -0
- data/spec/do_mock.rb +29 -0
- data/spec/do_mock2.rb +29 -0
- data/spec/pooling_spec.rb +153 -0
- data/spec/reader_spec.rb +19 -0
- data/spec/result_spec.rb +21 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/transaction_spec.rb +37 -0
- data/spec/uri_spec.rb +23 -0
- data/tasks/release.rake +14 -0
- data/tasks/spec.rake +10 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +122 -0
@@ -0,0 +1,148 @@
|
|
1
|
+
def test_connection(conn)
|
2
|
+
reader = conn.create_command(CONFIG.testsql || 'SELECT 1').execute_reader
|
3
|
+
reader.next!
|
4
|
+
result = reader.values[0]
|
5
|
+
result
|
6
|
+
ensure
|
7
|
+
reader.close
|
8
|
+
conn.close
|
9
|
+
end
|
10
|
+
|
11
|
+
shared_examples 'a Connection' do
|
12
|
+
before :all do
|
13
|
+
setup_test_environment
|
14
|
+
end
|
15
|
+
|
16
|
+
before do
|
17
|
+
@connection = DataObjects::Connection.new(CONFIG.uri)
|
18
|
+
end
|
19
|
+
|
20
|
+
after do
|
21
|
+
@connection.close
|
22
|
+
end
|
23
|
+
|
24
|
+
it { expect(@connection).to be_kind_of(DataObjects::Connection) }
|
25
|
+
it { expect(@connection).to be_kind_of(DataObjects::Pooling) }
|
26
|
+
|
27
|
+
it { expect(@connection).to respond_to(:dispose) }
|
28
|
+
it 'responds to #create_command' do
|
29
|
+
expect(@connection).to respond_to(:create_command)
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'create_command' do
|
33
|
+
it 'is a kind of Command' do
|
34
|
+
expect(@connection.create_command('This is a dummy command')).to be_kind_of(DataObjects::Command)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'various connection URIs' do
|
39
|
+
it 'opens with an uri object' do
|
40
|
+
uri = DataObjects::URI.new(
|
41
|
+
scheme: @driver,
|
42
|
+
user: @user,
|
43
|
+
password: @password,
|
44
|
+
host: @host,
|
45
|
+
port: @port&.to_i,
|
46
|
+
path: @database
|
47
|
+
)
|
48
|
+
conn = DataObjects::Connection.new(uri)
|
49
|
+
expect(test_connection(conn)).to eq 1
|
50
|
+
conn.close
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'works with non-JDBC URLs' do
|
54
|
+
conn = DataObjects::Connection.new(CONFIG.uri.sub('jdbc:', '').to_s)
|
55
|
+
expect(test_connection(conn)).to eq 1
|
56
|
+
conn.close
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'dispose' do
|
61
|
+
describe 'on open connection' do
|
62
|
+
it 'dispose is true' do
|
63
|
+
conn = DataObjects::Connection.new(CONFIG.uri)
|
64
|
+
conn.detach
|
65
|
+
expect(conn.dispose).to be true
|
66
|
+
conn.close
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'on closed connection' do
|
71
|
+
before do
|
72
|
+
@closed_connection = DataObjects::Connection.new(CONFIG.uri)
|
73
|
+
@closed_connection&.detach
|
74
|
+
@closed_connection&.dispose
|
75
|
+
end
|
76
|
+
|
77
|
+
after do
|
78
|
+
@closed_connection&.close
|
79
|
+
@closed_connection = nil
|
80
|
+
end
|
81
|
+
|
82
|
+
it { expect(@closed_connection&.dispose).to be false }
|
83
|
+
|
84
|
+
it 'raises an error on creating a command' do
|
85
|
+
expect do
|
86
|
+
@closed_connection&.create_command('INSERT INTO non_existent_table (tester) VALUES (1)')&.execute_non_query
|
87
|
+
end.to raise_error(DataObjects::ConnectionError)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
shared_examples 'a Connection with authentication support' do
|
94
|
+
before :all do
|
95
|
+
%w(@driver @user @password @host @port @database).each do |ivar|
|
96
|
+
raise "+#{ivar}+ should be defined in before block" unless instance_variable_get(ivar)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe 'with an invalid URI' do
|
101
|
+
it 'raises an error if bad username is given' do
|
102
|
+
expect { DataObjects::Connection.new("#{@driver}://thisreallyshouldntexist:#{@password}@#{@host}:#{@port}#{@database}") }
|
103
|
+
.to raise_error(DataObjects::ConnectionError)
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'raises an error if bad password is given' do
|
107
|
+
expect { DataObjects::Connection.new("#{@driver}://#{@user}:completelyincorrectpassword:#{@host}:#{@port}#{@database}") }
|
108
|
+
.to raise_error(DataObjects::SQLError)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'raises an error if an invalid port is given' do
|
112
|
+
expect { DataObjects::Connection.new("#{@driver}://#{@user}:#{@password}:#{@host}:648646543#{@database}") }.to raise_error(DataObjects::SQLError)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'raises an error if an invalid database is given' do
|
116
|
+
expect { DataObjects::Connection.new("#{@driver}://#{@user}:#{@password}:#{@host}:#{@port}/someweirddatabase") }.to raise_error(DataObjects::SQLError)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
shared_examples 'a Connection allowing default database' do
|
122
|
+
describe 'with a URI without a database' do
|
123
|
+
it 'connects properly' do
|
124
|
+
conn = DataObjects::Connection.new("#{@driver}://#{@user}:#{@password}@#{@host}:#{@port}")
|
125
|
+
expect(test_connection(conn)).to eq 1
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
shared_examples 'a Connection with SSL support' do
|
131
|
+
if DataObjectsSpecHelpers.test_environment_supports_ssl?
|
132
|
+
describe 'connecting with SSL' do
|
133
|
+
it 'connects securely' do
|
134
|
+
conn = DataObjects::Connection.new("#{CONFIG.uri}?#{CONFIG.ssl}")
|
135
|
+
expect(conn.secure?).to be true
|
136
|
+
conn.close
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe 'connecting without SSL' do
|
142
|
+
it 'does not connect securely' do
|
143
|
+
conn = DataObjects::Connection.new(CONFIG.uri)
|
144
|
+
expect(conn.secure?).to be false
|
145
|
+
conn.close
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
shared_examples 'a driver supporting different encodings' do
|
2
|
+
describe 'character_set' do
|
3
|
+
before do
|
4
|
+
@connection = DataObjects::Connection.new(CONFIG.uri)
|
5
|
+
end
|
6
|
+
|
7
|
+
after do
|
8
|
+
@connection.close
|
9
|
+
end
|
10
|
+
|
11
|
+
it { expect(@connection).to respond_to(:character_set) }
|
12
|
+
|
13
|
+
it 'uses utf8 by default' do
|
14
|
+
expect(@connection.character_set).to eq 'UTF-8'
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'sets the character set through the URI' do
|
18
|
+
before do
|
19
|
+
# @latin1_connection = DataObjects::Connection.new("#{CONFIG.uri}?encoding=latin1")
|
20
|
+
@latin1_connection = DataObjects::Connection.new(
|
21
|
+
"#{CONFIG.scheme}://#{CONFIG.user}:#{CONFIG.pass}@#{CONFIG.host}:#{CONFIG.port}#{CONFIG.database}?encoding=ISO-8859-1"
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
after { @latin1_connection.close }
|
26
|
+
|
27
|
+
it { expect(@latin1_connection.character_set).to eq 'ISO-8859-1' }
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'uses UTF-8 when an invalid encoding is given' do
|
31
|
+
before do
|
32
|
+
@latin1_connection = DataObjects::Connection.new(
|
33
|
+
"#{CONFIG.scheme}://#{CONFIG.user}:#{CONFIG.pass}@#{CONFIG.host}:#{CONFIG.port}#{CONFIG.database}?encoding=ISO-INVALID"
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
after { @latin1_connection.close }
|
38
|
+
|
39
|
+
it { expect(@latin1_connection.character_set).to eq 'UTF-8' }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
shared_examples 'returning correctly encoded strings for the default database encoding' do
|
45
|
+
if defined?(Encoding)
|
46
|
+
|
47
|
+
before :all do
|
48
|
+
setup_test_environment
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'with encoded string support' do
|
52
|
+
before do
|
53
|
+
@connection = DataObjects::Connection.new(CONFIG.uri)
|
54
|
+
end
|
55
|
+
|
56
|
+
after do
|
57
|
+
@connection.close
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'reading a String' do
|
61
|
+
before do
|
62
|
+
@reader = @connection.create_command('SELECT name, whitepaper_text FROM widgets WHERE ad_description = ?')
|
63
|
+
.execute_reader('Buy this product now!')
|
64
|
+
@reader.next!
|
65
|
+
@values = @reader.values
|
66
|
+
end
|
67
|
+
|
68
|
+
after do
|
69
|
+
@reader.close
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'returns UTF-8 encoded String' do
|
73
|
+
expect(@values.first).to be_kind_of(String)
|
74
|
+
expect(@values.first.encoding.name).to eq 'UTF-8'
|
75
|
+
expect(@values.last).to be_kind_of(String)
|
76
|
+
expect(@values.last.encoding.name).to eq 'UTF-8'
|
77
|
+
end
|
78
|
+
end
|
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 'returns ASCII-8BIT encoded ByteArray' do
|
94
|
+
expect(@values.first).to be_kind_of(Extlib::ByteArray)
|
95
|
+
expect(@values.first.encoding.name).to eq 'ASCII-8BIT'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
shared_examples 'returning correctly encoded strings for the default internal encoding' do
|
103
|
+
if defined?(Encoding)
|
104
|
+
|
105
|
+
before :all do
|
106
|
+
setup_test_environment
|
107
|
+
end
|
108
|
+
|
109
|
+
describe 'with encoded string support' do
|
110
|
+
before do
|
111
|
+
@encoding_before = Encoding.default_internal
|
112
|
+
Encoding.default_internal = 'ISO-8859-1'
|
113
|
+
@connection = DataObjects::Connection.new(CONFIG.uri)
|
114
|
+
end
|
115
|
+
|
116
|
+
after do
|
117
|
+
@connection.close
|
118
|
+
Encoding.default_internal = @encoding_before
|
119
|
+
end
|
120
|
+
|
121
|
+
describe 'reading a String' do
|
122
|
+
before do
|
123
|
+
@reader = @connection.create_command('SELECT name, whitepaper_text FROM widgets WHERE ad_description = ?')
|
124
|
+
.execute_reader('Buy this product now!')
|
125
|
+
@reader.next!
|
126
|
+
@values = @reader.values
|
127
|
+
end
|
128
|
+
|
129
|
+
after do
|
130
|
+
@reader.close
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'returns ISO-8859-1 encoded String' do
|
134
|
+
expect(@values.first).to be_kind_of(String)
|
135
|
+
expect(@values.first.encoding.name).to eq 'ISO-8859-1'
|
136
|
+
expect(@values.last).to be_kind_of(String)
|
137
|
+
expect(@values.last.encoding.name).to eq 'ISO-8859-1'
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe 'reading a ByteArray' do
|
142
|
+
before do
|
143
|
+
@command = @connection.create_command('SELECT ad_image FROM widgets WHERE ad_description = ?')
|
144
|
+
@command.set_types(Extlib::ByteArray)
|
145
|
+
@reader = @command.execute_reader('Buy this product now!')
|
146
|
+
@reader.next!
|
147
|
+
@values = @reader.values
|
148
|
+
end
|
149
|
+
|
150
|
+
after do
|
151
|
+
@reader.close
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'returns ASCII-8BIT encoded ByteArray' do
|
155
|
+
expect(@values.first).to be_kind_of(Extlib::ByteArray)
|
156
|
+
expect(@values.first.encoding.name).to eq 'ASCII-8BIT'
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
shared_examples 'raising a SQLError' do
|
2
|
+
before :all do
|
3
|
+
setup_test_environment
|
4
|
+
end
|
5
|
+
|
6
|
+
describe 'an invalid query' do
|
7
|
+
it 'raises an error' do
|
8
|
+
@connection = DataObjects::Connection.new(CONFIG.uri)
|
9
|
+
invalid_query = @connection.create_command('SLCT * FROM widgets WHERE ad_description = ? order by id')
|
10
|
+
expect { invalid_query.execute_reader('Buy this product now!') }.to raise_error(DataObjects::SQLError)
|
11
|
+
@connection.close
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'an invalid result set' do
|
16
|
+
it 'raises an error' do
|
17
|
+
@connection = DataObjects::Connection.new(CONFIG.uri)
|
18
|
+
invalid_result = @connection.create_command('SELECT MAX((SELECT 1 UNION SELECT 2))')
|
19
|
+
expect { invalid_result.execute_reader }.to raise_error(DataObjects::SQLError)
|
20
|
+
@connection.close
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
File without changes
|
@@ -0,0 +1,180 @@
|
|
1
|
+
shared_examples 'a Reader' do
|
2
|
+
before :all do
|
3
|
+
setup_test_environment
|
4
|
+
end
|
5
|
+
|
6
|
+
before do
|
7
|
+
@connection = DataObjects::Connection.new(CONFIG.uri)
|
8
|
+
@reader = @connection.create_command('SELECT code, name FROM widgets WHERE ad_description = ? order by id')
|
9
|
+
.execute_reader('Buy this product now!')
|
10
|
+
@reader2 = @connection.create_command('SELECT code FROM widgets WHERE ad_description = ? order by id').execute_reader('Buy this product now!')
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
@reader.close
|
15
|
+
@reader2.close
|
16
|
+
@connection.close
|
17
|
+
end
|
18
|
+
|
19
|
+
it { expect(@reader).to respond_to(:fields) }
|
20
|
+
|
21
|
+
describe 'fields' do
|
22
|
+
it 'returns the correct fields in the reader' do
|
23
|
+
# we downcase the field names as some drivers such as do_derby, do_h2,
|
24
|
+
# do_hsqldb, do_oracle return the field names as uppercase
|
25
|
+
expect(@reader.fields).to be_array_case_insensitively_equal_to(%w(code name))
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns the field alias as the name, when the SQL AS keyword is specified' do
|
29
|
+
reader = @connection.create_command('SELECT code AS codigo, name AS nombre FROM widgets WHERE ad_description = ? order by id')
|
30
|
+
.execute_reader('Buy this product now!')
|
31
|
+
expect(reader.fields).not_to be_array_case_insensitively_equal_to(%w(code name))
|
32
|
+
expect(reader.fields).to be_array_case_insensitively_equal_to(%w(codigo nombre))
|
33
|
+
reader.close
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it { expect(@reader).to respond_to(:values) }
|
38
|
+
|
39
|
+
describe 'values' do
|
40
|
+
describe 'when the reader is uninitialized' do
|
41
|
+
it 'raises an error' do
|
42
|
+
expect { @reader.values }.to raise_error(DataObjects::DataError)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'when the reader is moved to the first result' do
|
47
|
+
before do
|
48
|
+
@reader.next!
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'returns the correct first set of in the reader' do
|
52
|
+
expect(@reader.values).to eq ['W0000001', 'Widget 1']
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'when the reader is moved to the second result' do
|
57
|
+
before do
|
58
|
+
@reader.next!
|
59
|
+
@reader.next!
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'returns the correct first set of in the reader' do
|
63
|
+
expect(@reader.values).to eq ['W0000002', 'Widget 2']
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'when the reader is moved to the end' do
|
68
|
+
before do
|
69
|
+
while @reader.next!; end
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'raises an error again' do
|
73
|
+
expect { @reader.values }.to raise_error(DataObjects::DataError)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it { expect(@reader).to respond_to(:close) }
|
79
|
+
|
80
|
+
describe 'close' do
|
81
|
+
describe 'on an open reader' do
|
82
|
+
it 'returns true' do
|
83
|
+
expect(@reader.close).to be true
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe 'on an already closed reader' do
|
88
|
+
before do
|
89
|
+
@reader.close
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'returns false' do
|
93
|
+
expect(@reader.close).to be false
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it { expect(@reader).to respond_to(:next!) }
|
99
|
+
|
100
|
+
describe 'next!' do
|
101
|
+
describe 'successfully moving the cursor initially' do
|
102
|
+
it 'returns true' do
|
103
|
+
expect(@reader.next!).to be true
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'moving the cursor' do
|
108
|
+
before do
|
109
|
+
@reader.next!
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'moves the cursor to the next value' do
|
113
|
+
expect(@reader.values).to eq ['W0000001', 'Widget 1']
|
114
|
+
expect { @reader.next! }.to(change { @reader.values })
|
115
|
+
expect(@reader.values).to eq ['W0000002', 'Widget 2']
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe 'arriving at the end of the reader' do
|
120
|
+
before do
|
121
|
+
while @reader.next!; end
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'returns false when the end is reached' do
|
125
|
+
expect(@reader.next!).to be false
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
it { expect(@reader).to respond_to(:field_count) }
|
131
|
+
|
132
|
+
describe 'field_count' do
|
133
|
+
it 'counts the number of fields' do
|
134
|
+
expect(@reader.field_count).to eq 2
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
it { expect(@reader).to respond_to(:values) }
|
139
|
+
|
140
|
+
describe 'each' do
|
141
|
+
it 'yields each row to the block for multiple columns' do
|
142
|
+
rows_yielded = 0
|
143
|
+
@reader.each do |row|
|
144
|
+
expect(row).to respond_to(:[])
|
145
|
+
|
146
|
+
expect(row.size).to eq 2
|
147
|
+
|
148
|
+
# the field names need to be case insensitive as some drivers such as
|
149
|
+
# do_derby, do_h2, do_hsqldb return the field names as uppercase
|
150
|
+
expect(row['name'] || row['NAME']).to be_kind_of(String)
|
151
|
+
expect(row['code'] || row['CODE']).to be_kind_of(String)
|
152
|
+
|
153
|
+
rows_yielded += 1
|
154
|
+
end
|
155
|
+
expect(rows_yielded).to eq 15
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'yields each row to the block for a single column' do
|
159
|
+
rows_yielded = 0
|
160
|
+
@reader2.each do |row|
|
161
|
+
expect(row).to respond_to(:[])
|
162
|
+
|
163
|
+
expect(row.size).to eq 1
|
164
|
+
|
165
|
+
# the field names need to be case insensitive as some drivers such as
|
166
|
+
# do_derby, do_h2, do_hsqldb return the field names as uppercase
|
167
|
+
expect(row['code'] || row['CODE']).to be_kind_of(String)
|
168
|
+
|
169
|
+
rows_yielded += 1
|
170
|
+
end
|
171
|
+
expect(rows_yielded).to eq 15
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'returns the reader' do
|
175
|
+
expect(@reader.each do |_row|
|
176
|
+
# empty block
|
177
|
+
end).to equal(@reader)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
shared_examples 'a Result' do
|
2
|
+
before :all do
|
3
|
+
setup_test_environment
|
4
|
+
end
|
5
|
+
|
6
|
+
before do
|
7
|
+
@connection = DataObjects::Connection.new(CONFIG.uri)
|
8
|
+
@result = @connection.create_command('INSERT INTO users (name) VALUES (?)').execute_non_query('monkey')
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
@connection.close
|
13
|
+
end
|
14
|
+
|
15
|
+
it { expect(@result).to respond_to(:affected_rows) }
|
16
|
+
|
17
|
+
describe 'affected_rows' do
|
18
|
+
it 'returns the number of affected rows' do
|
19
|
+
expect(@result.affected_rows).to eq 1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
shared_examples 'a Result which returns inserted key with sequences' do
|
25
|
+
describe 'insert_id' do
|
26
|
+
before do
|
27
|
+
setup_test_environment
|
28
|
+
@connection = DataObjects::Connection.new(CONFIG.uri)
|
29
|
+
command = @connection.create_command('INSERT INTO users (name) VALUES (?)')
|
30
|
+
# execute the command twice and expose the second result
|
31
|
+
command.execute_non_query('monkey')
|
32
|
+
@result = command.execute_non_query('monkey')
|
33
|
+
end
|
34
|
+
|
35
|
+
after do
|
36
|
+
@connection.close
|
37
|
+
end
|
38
|
+
|
39
|
+
it { expect(@result).to respond_to(:affected_rows) }
|
40
|
+
|
41
|
+
it 'returns the insert_id' do
|
42
|
+
# This is actually the 2nd record inserted
|
43
|
+
expect(@result.insert_id).to eq 2
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
shared_examples 'a Result which returns nil without sequences' do
|
49
|
+
describe 'insert_id' do
|
50
|
+
before do
|
51
|
+
setup_test_environment
|
52
|
+
@connection = DataObjects::Connection.new(CONFIG.uri)
|
53
|
+
command = @connection.create_command('INSERT INTO invoices (invoice_number) VALUES (?)')
|
54
|
+
# execute the command twice and expose the second result
|
55
|
+
@result = command.execute_non_query('monkey')
|
56
|
+
end
|
57
|
+
|
58
|
+
after do
|
59
|
+
@connection.close
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'returns the insert_id' do
|
63
|
+
# This is actually the 2nd record inserted
|
64
|
+
expect(@result.insert_id).to be_nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
shared_examples 'supporting Array' do
|
2
|
+
before :all do
|
3
|
+
setup_test_environment
|
4
|
+
end
|
5
|
+
|
6
|
+
before do
|
7
|
+
@connection = DataObjects::Connection.new(CONFIG.uri)
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
@connection.close
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'passing an Array as a parameter in execute_reader' do
|
15
|
+
before do
|
16
|
+
@reader = @connection.create_command('SELECT * FROM widgets WHERE id in ?').execute_reader([2, 3, 4, 5])
|
17
|
+
end
|
18
|
+
|
19
|
+
after do
|
20
|
+
@reader.close
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'returns correct number of rows' do
|
24
|
+
counter = 0
|
25
|
+
counter += 1 while @reader.next!
|
26
|
+
expect(counter).to eq 4
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|