ironruby-dbi 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,336 @@
1
+ @class = Class.new(DBDConfig.testbase(DBDConfig.current_dbtype)) do
2
+
3
+ def prep_status_statement
4
+ @sth.finish if (@sth and !@sth.finished?)
5
+ @sth = @dbh.prepare("select * from names order by age")
6
+ @sth.raise_error = true
7
+ end
8
+
9
+ def test_status
10
+ names_rc = 3
11
+
12
+ [:fetch, :fetch_hash, :each, :fetch_all].each do |call|
13
+ assert_raise(DBI::InterfaceError, DBI::NotSupportedError) do
14
+ prep_status_statement
15
+ @sth.send(call)
16
+ end
17
+ end
18
+
19
+ # for these next three, it doesn't really matter what the args are, it should fail
20
+ assert_raises(DBI::InterfaceError, DBI::NotSupportedError) do
21
+ prep_status_statement
22
+ @sth.fetch_many(1)
23
+ end
24
+
25
+ assert_raises(DBI::InterfaceError, DBI::NotSupportedError) do
26
+ prep_status_statement
27
+ @sth.fetch_scroll(0, 0)
28
+ end
29
+
30
+ assert_raises(DBI::InterfaceError, DBI::NotSupportedError) do
31
+ prep_status_statement
32
+ @sth.each { |x| }
33
+ end
34
+
35
+ assert_raises(DBI::InterfaceError) do
36
+ prep_status_statement
37
+ @sth.execute
38
+ 2.times { @sth.fetch_all }
39
+ end
40
+
41
+ assert_raises(DBI::InterfaceError) do
42
+ prep_status_statement
43
+ @sth.execute
44
+ # XXX fetch_many won't know it can't fetch anything until the third time around.
45
+ 3.times { @sth.fetch_many(names_rc) }
46
+ end
47
+ @sth.finish
48
+ end
49
+
50
+ def test_execute
51
+ assert_nothing_raised do
52
+ sth = @dbh.execute("select * from names order by age") do |sth|
53
+ assert_equal([["Joe", 19], ["Bob", 21], ["Jim", 30]], sth.fetch_all)
54
+ end
55
+ end
56
+ end
57
+
58
+ def test_quoting # FIXME breaks sqlite-ruby to a segfault - research
59
+ @sth = nil
60
+
61
+ assert_nothing_raised do
62
+ if dbtype == "postgresql"
63
+ @sth = @dbh.prepare('select E\'\\\\\'')
64
+ elsif dbtype == "mssql"
65
+ @sth = @dbh.prepare 'select \'\\\''
66
+ else
67
+ @sth = @dbh.prepare('select \'\\\\\'')
68
+ end
69
+ @sth.execute
70
+ row = @sth.fetch
71
+ @sth.finish
72
+ assert_equal ['\\'], row
73
+ end
74
+ end
75
+
76
+ def test_duplicate_columns
77
+ @sth = nil
78
+ assert_nothing_raised do
79
+ @sth = @dbh.prepare("select name, name from names where name = @name")
80
+ @sth.execute(:name => "Bob")
81
+ assert_equal [["Bob", "Bob"]], @sth.fetch_all
82
+ @sth.finish
83
+ end
84
+ end
85
+
86
+ def test_columninfo
87
+ @sth = nil
88
+
89
+ assert_nothing_raised do
90
+ @sth = @dbh.prepare("select * from precision_test")
91
+ @sth.execute
92
+
93
+ cols = @sth.column_info
94
+
95
+ assert(cols)
96
+ assert_kind_of(Array, cols)
97
+ assert_equal(4, cols.length)
98
+
99
+ # the first column should always be "text_field" and have the following
100
+ # properties:
101
+ assert_equal("text_field", cols[0]["name"])
102
+ assert_equal(20, cols[0]["precision"])
103
+ ## scale can be either nil or 0 for character types.
104
+ case cols[0]["scale"]
105
+ when nil
106
+ assert_equal(nil, cols[0]["scale"])
107
+ when 0
108
+ assert_equal(0, cols[0]["scale"])
109
+ else
110
+ flunk "scale can be either 0 or nil for character types"
111
+ end
112
+
113
+ assert_equal(
114
+ DBI::Type::Varchar.object_id,
115
+ DBI::TypeUtil.type_name_to_module(cols[0]["type_name"]).object_id
116
+ )
117
+
118
+ # the second column should always be "integer_field" and have the following
119
+ # properties:
120
+ assert_equal("integer_field", cols[1]["name"])
121
+ # if these aren't set on the field, they should not exist
122
+ # FIXME mysql does not follow this rule, neither does ODBC
123
+ if dbtype == "mysql"
124
+ assert_equal(0, cols[1]["scale"])
125
+ assert_equal(11, cols[1]["precision"])
126
+ elsif dbtype == "odbc"
127
+ assert_equal(0, cols[1]["scale"])
128
+ assert_equal(10, cols[1]["precision"])
129
+ elsif dbtype == "mssql"
130
+ assert_equal(255, cols[1]["scale"])
131
+ assert_equal(10, cols[1]["precision"])
132
+ else
133
+ assert(!cols[1]["scale"])
134
+ assert(!cols[1]["precision"])
135
+ end
136
+
137
+ assert_equal(
138
+ DBI::Type::Integer.object_id,
139
+ DBI::TypeUtil.type_name_to_module(cols[1]["type_name"]).object_id
140
+ )
141
+
142
+ # the second column should always be "integer_field" and have the following
143
+ # properties:
144
+ assert_equal("decimal_field", cols[2]["name"])
145
+ assert_equal(1, cols[2]["scale"])
146
+ assert_equal(2, cols[2]["precision"])
147
+ assert_equal(
148
+ DBI::Type::Decimal.object_id,
149
+ DBI::TypeUtil.type_name_to_module(cols[2]["type_name"]).object_id
150
+ )
151
+
152
+ # the second column should always be "numeric_field" and have the following
153
+ # properties:
154
+ assert_equal("numeric_field", cols[3]["name"])
155
+ assert_equal(6, cols[3]["scale"])
156
+ assert_equal(30, cols[3]["precision"])
157
+ assert_equal(
158
+ DBI::Type::Decimal.object_id,
159
+ DBI::TypeUtil.type_name_to_module(cols[3]["type_name"]).object_id
160
+ )
161
+
162
+ cols.each { |col| assert_kind_of(DBI::ColumnInfo, col) }
163
+ @sth.finish
164
+ end
165
+ end
166
+
167
+ def test_duplicate_columns
168
+ assert_nothing_raised do
169
+ @sth = @dbh.prepare("select name, name from names where name = @name")
170
+ @sth.execute(:name => "Bob")
171
+ assert_equal [["Bob", "Bob"]], @sth.fetch_all
172
+ @sth.finish
173
+ end
174
+ end
175
+
176
+ def test_rows
177
+ @sth = nil
178
+
179
+ assert_nothing_raised do
180
+ @sth = @dbh.prepare("insert into names (name, age) values (@name, @age)")
181
+ @sth.execute(:name => "Bill", :age => 22)
182
+ end
183
+
184
+ assert 1, @sth.rows
185
+
186
+ @sth.finish
187
+ @sth = nil
188
+
189
+ assert_nothing_raised do
190
+ @sth = @dbh.prepare("delete from names where name = @name")
191
+ @sth.execute(:name => "Bill");
192
+ end
193
+
194
+ assert 1, @sth.rows
195
+
196
+ @sth.finish
197
+
198
+ assert_nothing_raised do
199
+ @sth = @dbh.prepare("select * from names")
200
+ @sth.execute
201
+ end
202
+
203
+ assert_equal 0, @sth.rows
204
+ assert @sth.fetchable?
205
+ assert @sth.any?
206
+ assert @sth.rows.zero?
207
+ @sth.finish
208
+ end
209
+
210
+ def test_prepare_execute
211
+ assert_nothing_raised do
212
+ @sth = @dbh.prepare("select * from names")
213
+ @sth.execute
214
+ @sth.finish
215
+ end
216
+
217
+ assert_nothing_raised do
218
+ @sth = @dbh.prepare("select * from names where name = @name")
219
+ @sth.execute(:name => "Bob")
220
+ @sth.finish
221
+ end
222
+
223
+ assert_nothing_raised do
224
+ @sth = @dbh.prepare("insert into names (name, age) values (@name, @age)")
225
+ @sth.execute(:name => "Bill", :age => 22);
226
+ @sth.finish
227
+ end
228
+ end
229
+
230
+
231
+ def test_prepare_execute_with_transactions
232
+ @dbh["AutoCommit"] = false
233
+ #config = DBDConfig.get_config['sqlite3']
234
+
235
+ # rollback 1 (the right way)
236
+ @sth = nil
237
+ @sth2 = nil
238
+
239
+ assert_nothing_raised do
240
+ @sth = @dbh.prepare("insert into names (name, age) values (@name, @age)")
241
+ @sth.execute(:name => "Billy", :age => 23)
242
+ @sth2 = @dbh.prepare("select * from names where name = @name")
243
+ @sth2.execute(:name => "Billy")
244
+ end
245
+ assert_equal ["Billy", 23 ], @sth2.fetch
246
+ @sth2.finish
247
+ @sth.finish
248
+ assert_nothing_raised { @dbh.rollback }
249
+
250
+ @sth = @dbh.prepare("select * from names where name = @name")
251
+ @sth.execute(:name => "Billy")
252
+ res = @sth.fetch
253
+ @sth.finish
254
+ assert_nil res
255
+
256
+ # rollback 2 (without closing statements first)
257
+
258
+ @sth = nil
259
+ @sth2 = nil
260
+
261
+ assert_nothing_raised do
262
+ @sth = @dbh.prepare("insert into names (name, age) values (@name, @age)")
263
+ @sth.execute(:name => "Billy", :age => 23)
264
+ @sth2 = @dbh.prepare("select * from names where name = @name")
265
+ @sth2.execute(:name => "Billy")
266
+ end
267
+
268
+ assert_equal ["Billy", 23], @sth2.fetch
269
+
270
+ # FIXME some throw here, some don't. we should probably normalize this
271
+ @dbh.rollback rescue true
272
+
273
+ @sth2.finish
274
+ @sth.finish
275
+ assert_nothing_raised { @dbh.rollback }
276
+
277
+ @sth = @dbh.prepare("select * from names where name = @name")
278
+ @sth.execute(:name => "Billy")
279
+ assert_nil @sth.fetch
280
+ @sth.finish
281
+
282
+ # commit
283
+
284
+ @sth = nil
285
+ @sth2 = nil
286
+
287
+ assert_nothing_raised do
288
+ @sth = @dbh.prepare("insert into names (name, age) values (@name, @age)")
289
+ @sth.execute(:name => "Billy", :age => 23)
290
+ @sth2 = @dbh.prepare("select * from names where name = @name")
291
+ @sth2.execute(:name => "Billy")
292
+ end
293
+ assert_equal ["Billy", 23 ], @sth2.fetch
294
+ @sth2.finish
295
+ @sth.finish
296
+ assert_nothing_raised { @dbh.commit }
297
+
298
+ @sth = @dbh.prepare("select * from names where name = @name")
299
+ @sth.execute(:name => "Billy")
300
+ assert_equal ["Billy", 23 ], @sth.fetch
301
+ @sth.finish
302
+ end
303
+
304
+ def test_fetch
305
+ @sth = nil
306
+ assert_nothing_raised do
307
+ @sth = @dbh.prepare("select * from names order by age")
308
+ @sth.execute
309
+ end
310
+
311
+ # this tests that we're getting the rows in the right order,
312
+ # and that the types are being converted.
313
+ assert_equal ["Joe", 19], @sth.fetch
314
+ assert_equal ["Bob", 21], @sth.fetch
315
+ assert_equal ["Jim", 30], @sth.fetch
316
+ assert_nil @sth.fetch
317
+
318
+ @sth.finish
319
+ end
320
+
321
+ def test_transaction_block
322
+ @dbh["AutoCommit"] = false
323
+ # this transaction should not fail because it called return early
324
+ @dbh.transaction do |dbh|
325
+ dbh.do('INSERT INTO names (name, age) VALUES (@name, @age)', :name => "Cooter", :age => 69)
326
+ return 42
327
+ end
328
+ @sth = @dbh.prepare("select * from names where name = @name")
329
+ @sth.execute(:name => "Cooter")
330
+ row = @sth.fetch
331
+ assert row
332
+ assert_equal ["Cooter", 69], row
333
+ @sth.finish
334
+ @dbh["AutoCommit"] = true
335
+ end
336
+ end
@@ -0,0 +1,288 @@
1
+ @class = Class.new(DBDConfig.testbase(DBDConfig.current_dbtype)) do
2
+ def skip_bit
3
+ # FIXME this test fails because DBI's type system blows goats.
4
+ @sth = nil
5
+
6
+ assert_nothing_raised do
7
+ @sth = @dbh.prepare("insert into bit_test (mybit) values (@mybit)")
8
+ @sth.bind_param(:mybit, 0, DBI::SQL_TINYINT)
9
+ @sth.execute
10
+ # if dbtype == "postgresql"
11
+ # @sth.execute("0")
12
+ # else
13
+ # @sth.execute(0)
14
+ # end
15
+ @sth.finish
16
+ end
17
+
18
+ assert_nothing_raised do
19
+ @sth = @dbh.prepare("select * from bit_test")
20
+ @sth.execute
21
+ row = @sth.fetch
22
+ @sth.finish
23
+
24
+ assert_equal [0], row
25
+ end
26
+ end
27
+
28
+ def test_numeric_types
29
+ assert(@dbh.convert_types)
30
+
31
+ @sth = @dbh.prepare("insert into precision_test (text_field, integer_field, decimal_field, numeric_field) values (@text_field, @integer_field, @decimal_field, @numeric_field)")
32
+ assert(@sth.convert_types)
33
+ 1.step(5) do |x|
34
+ @sth.execute(:text_field => "poop#{x}", :integer_field => x, :decimal_field => x + 0.123, :numeric_field => x + 0.234)
35
+ end
36
+
37
+ @sth.finish
38
+
39
+ @sth = @dbh.prepare("select integer_field, decimal_field, numeric_field from precision_test")
40
+ @sth.execute
41
+ col_info = @sth.column_info
42
+ begin
43
+ 1.step(5) do |x|
44
+ row = @sth.fetch
45
+
46
+ assert_kind_of(Integer, row[0])
47
+ assert_kind_of(BigDecimal, row[1])
48
+ assert_kind_of(BigDecimal, row[2])
49
+
50
+ # FIXME BigDecimal requires a string and some databases will pad
51
+ # decimal/numeric with constrained precision. We should account for
52
+ # this, but I'm not quite sure how yet.
53
+ end
54
+ ensure
55
+ @sth.finish
56
+ end
57
+ end
58
+
59
+ # FIXME
60
+ # Ideally, this test should be split across the DBI tests and DBD, but for
61
+ # now testing against the DBDs really doesn't cost us anything other than
62
+ # debugging time if something breaks.
63
+ def test_bind_coltype
64
+ # ensure type conv didn't get turned off somewhere.
65
+ assert(DBI.convert_types)
66
+ assert(@dbh.convert_types)
67
+
68
+ assert_nothing_raised do
69
+ @sth = @dbh.prepare("select name, age from names order by age")
70
+ assert(@sth.convert_types) # again
71
+ @sth.execute
72
+ @sth.bind_coltype(2, DBI::Type::Varchar)
73
+ assert_equal(
74
+ [
75
+ ["Joe", "19"],
76
+ ["Bob", "21"],
77
+ ["Jim", "30"],
78
+ ], @sth.fetch_all
79
+ )
80
+ @sth.finish
81
+ end
82
+
83
+ # just to be sure..
84
+ assert_nothing_raised do
85
+ @sth = @dbh.prepare("select name, age from names order by age")
86
+ @sth.execute
87
+ @sth.bind_coltype(2, DBI::Type::Float)
88
+ @sth.fetch_all.collect { |x| assert_kind_of(Float, x[1]) }
89
+ @sth.finish
90
+ end
91
+
92
+ # now, let's check some failure cases
93
+ @sth = @dbh.prepare("select name, age from names order by age")
94
+
95
+ # can't bind_coltype before execute
96
+ assert_raises(DBI::InterfaceError) { @sth.bind_coltype(1, DBI::Type::Float) }
97
+ # can't index < 1
98
+ assert_raises(DBI::InterfaceError) { @sth.bind_coltype(0, DBI::Type::Float) }
99
+ end
100
+
101
+ def test_noconv
102
+ # XXX this test will fail the whole test suite miserably if it fails at any point.
103
+ assert(DBI.convert_types)
104
+
105
+ DBI.convert_types = false
106
+ @sth.finish rescue nil
107
+ @dbh.disconnect
108
+ set_base_dbh
109
+
110
+ assert(!@dbh.convert_types)
111
+
112
+ assert_nothing_raised do
113
+ @sth = @dbh.prepare("select * from names order by age")
114
+ assert(!@sth.convert_types)
115
+ @sth.execute
116
+ assert_equal(
117
+ [
118
+ ["Joe", "19"],
119
+ ["Bob", "21"],
120
+ ["Jim", "30"],
121
+ ], @sth.fetch_all
122
+ )
123
+ @sth.finish
124
+ end
125
+
126
+ DBI.convert_types = true
127
+ @sth.finish rescue nil
128
+ @dbh.disconnect
129
+ set_base_dbh
130
+
131
+ assert(DBI.convert_types)
132
+ assert(@dbh.convert_types)
133
+
134
+ assert_nothing_raised do
135
+ @sth = @dbh.prepare("select * from names order by age")
136
+ assert(@sth.convert_types)
137
+ @sth.execute
138
+ assert_equal(
139
+ [
140
+ ["Joe", 19],
141
+ ["Bob", 21],
142
+ ["Jim", 30],
143
+ ], @sth.fetch_all
144
+ )
145
+ @sth.finish
146
+ end
147
+ @dbh.convert_types = false
148
+ assert_nothing_raised do
149
+ @sth = @dbh.prepare("select * from names order by age")
150
+ assert(!@sth.convert_types)
151
+ @sth.execute
152
+ assert_equal(
153
+ [
154
+ ["Joe", "19"],
155
+ ["Bob", "21"],
156
+ ["Jim", "30"],
157
+ ], @sth.fetch_all
158
+ )
159
+ @sth.finish
160
+ end
161
+
162
+ @dbh.convert_types = true
163
+
164
+ assert_nothing_raised do
165
+ @sth = @dbh.prepare("select * from names order by age")
166
+ assert(@sth.convert_types)
167
+ @sth.convert_types = false
168
+ @sth.execute
169
+ assert_equal(
170
+ [
171
+ ["Joe", "19"],
172
+ ["Bob", "21"],
173
+ ["Jim", "30"],
174
+ ], @sth.fetch_all
175
+ )
176
+ @sth.finish
177
+ end
178
+ rescue Exception => e
179
+ DBI.convert_types = true
180
+ @sth.finish
181
+ @dbh.disconnect
182
+ set_base_dbh
183
+ raise e
184
+ end
185
+
186
+ def test_null
187
+ assert_nothing_raised do
188
+ @sth = @dbh.prepare('insert into names (name, age) values (@name, @age)')
189
+ begin
190
+ @sth.execute(:name => "'NULL'", :age => 201)
191
+ @sth.execute(:name => nil, :age => 202)
192
+ @sth.execute(:name => "NULL", :age => 203)
193
+ ensure
194
+ @sth.finish
195
+ end
196
+ end
197
+
198
+ assert_nothing_raised do
199
+ begin
200
+ @sth = @dbh.prepare('select * from names where age > 200 order by age')
201
+ @sth.execute
202
+ assert_equal(["'NULL'", 201], @sth.fetch)
203
+ assert_equal([nil, 202], @sth.fetch)
204
+ assert_equal(["NULL", 203], @sth.fetch)
205
+ ensure
206
+ @sth.finish
207
+ end
208
+ end
209
+ end
210
+
211
+ def test_time
212
+ @sth = nil
213
+ t = nil
214
+ assert_nothing_raised do
215
+ @sth = @dbh.prepare("insert into time_test (mytime) values (@mytime)")
216
+ t = Time.now
217
+ @sth.execute(:mytime => t)
218
+ @sth.finish
219
+ end
220
+
221
+ assert_nothing_raised do
222
+ @sth = @dbh.prepare("select * from time_test")
223
+ @sth.execute
224
+ row = @sth.fetch
225
+ assert_kind_of DateTime, row[0]
226
+ assert_equal t.hour, row[0].hour
227
+ assert_equal t.min, row[0].min
228
+ assert_equal t.sec, row[0].sec
229
+ @sth.finish
230
+ end
231
+ end
232
+
233
+ def test_timestamp
234
+ @sth = nil
235
+ # We omit fractional second testing here -- timestamp precision
236
+ # is a very slippery, dependent on driver and driver version.
237
+ t = DBI::Timestamp.new(2008, 3, 8, 10, 39, 1)
238
+ #assert_nothing_raised do
239
+ @sth = @dbh.prepare("insert into timestamp_test (mytimestamp) values (@mytimestamp)")
240
+ @sth.execute(:mytimestamp => t)
241
+ @sth.finish
242
+ #end
243
+
244
+ assert_nothing_raised do
245
+ @sth = @dbh.prepare("select * from timestamp_test")
246
+ @sth.execute
247
+ row = @sth.fetch
248
+ assert_kind_of DateTime, row[0]
249
+ assert_equal t.year, row[0].year
250
+ assert_equal t.month, row[0].month
251
+ assert_equal t.day, row[0].day
252
+ assert_equal t.hour, row[0].hour
253
+ assert_equal t.min, row[0].min
254
+ assert_equal t.sec, row[0].sec
255
+ # omit fractional tests
256
+ @sth.finish
257
+ end
258
+ end
259
+
260
+ def test_boolean_return
261
+ @sth = nil
262
+
263
+ unless dbtype == "odbc" # ODBC has no boolean type
264
+ assert_nothing_raised do
265
+ @sth = @dbh.prepare("insert into boolean_test (num, mybool) values (@num, @mybool)")
266
+ @sth.execute(:num => 1, :mybool => true)
267
+ @sth.execute(:num => 2, :mybool => false)
268
+ @sth.finish
269
+ end
270
+
271
+ assert_nothing_raised do
272
+ @sth = @dbh.prepare("select * from boolean_test order by num")
273
+ @sth.execute
274
+
275
+ pairs = @sth.fetch_all
276
+
277
+ assert_equal(
278
+ [
279
+ [1, true],
280
+ [2, false],
281
+ ], pairs
282
+ )
283
+
284
+ @sth.finish
285
+ end
286
+ end
287
+ end
288
+ end