ydbi 0.5.8 → 0.6.0

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.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/ruby.yml +65 -0
  4. data/.gitignore +19 -0
  5. data/ChangeLog +8 -0
  6. data/Gemfile +5 -0
  7. data/Rakefile +14 -0
  8. data/TODO +44 -0
  9. data/bench/bench.rb +79 -0
  10. data/build/rake_task_lib.rb +186 -0
  11. data/devenv.lock +228 -0
  12. data/devenv.nix +55 -0
  13. data/devenv.yaml +8 -0
  14. data/doc/DBD_SPEC.rdoc +88 -0
  15. data/doc/DBI_SPEC.rdoc +157 -0
  16. data/doc/homepage/contact.html +62 -0
  17. data/doc/homepage/development.html +124 -0
  18. data/doc/homepage/index.html +83 -0
  19. data/doc/homepage/ruby-dbi.css +91 -0
  20. data/lib/dbd/Mysql.rb +137 -0
  21. data/lib/dbd/ODBC.rb +89 -0
  22. data/lib/dbd/Pg.rb +189 -0
  23. data/lib/dbd/SQLite.rb +97 -0
  24. data/lib/dbd/SQLite3.rb +124 -0
  25. data/lib/dbd/mysql/database.rb +405 -0
  26. data/lib/dbd/mysql/driver.rb +125 -0
  27. data/lib/dbd/mysql/statement.rb +188 -0
  28. data/lib/dbd/odbc/database.rb +128 -0
  29. data/lib/dbd/odbc/driver.rb +38 -0
  30. data/lib/dbd/odbc/statement.rb +137 -0
  31. data/lib/dbd/pg/database.rb +508 -0
  32. data/lib/dbd/pg/exec.rb +47 -0
  33. data/lib/dbd/pg/statement.rb +160 -0
  34. data/lib/dbd/pg/tuples.rb +121 -0
  35. data/lib/dbd/pg/type.rb +209 -0
  36. data/lib/dbd/sqlite/database.rb +151 -0
  37. data/lib/dbd/sqlite/statement.rb +125 -0
  38. data/lib/dbd/sqlite3/database.rb +201 -0
  39. data/lib/dbd/sqlite3/statement.rb +78 -0
  40. data/lib/dbi/version.rb +1 -1
  41. data/prototypes/types2.rb +237 -0
  42. data/readme.md +3 -4
  43. data/setup.rb +1585 -0
  44. data/test/DBD_TESTS +50 -0
  45. data/test/TESTING +16 -0
  46. data/test/dbd/general/test_database.rb +206 -0
  47. data/test/dbd/general/test_statement.rb +325 -0
  48. data/test/dbd/general/test_types.rb +295 -0
  49. data/test/dbd/mysql/base.rb +26 -0
  50. data/test/dbd/mysql/down.sql +19 -0
  51. data/test/dbd/mysql/test_blob.rb +18 -0
  52. data/test/dbd/mysql/test_new_methods.rb +7 -0
  53. data/test/dbd/mysql/test_patches.rb +111 -0
  54. data/test/dbd/mysql/up.sql +28 -0
  55. data/test/dbd/odbc/base.rb +30 -0
  56. data/test/dbd/odbc/down.sql +19 -0
  57. data/test/dbd/odbc/test_new_methods.rb +12 -0
  58. data/test/dbd/odbc/test_ping.rb +10 -0
  59. data/test/dbd/odbc/test_statement.rb +44 -0
  60. data/test/dbd/odbc/test_transactions.rb +58 -0
  61. data/test/dbd/odbc/up.sql +33 -0
  62. data/test/dbd/postgresql/base.rb +31 -0
  63. data/test/dbd/postgresql/down.sql +31 -0
  64. data/test/dbd/postgresql/test_arrays.rb +179 -0
  65. data/test/dbd/postgresql/test_async.rb +121 -0
  66. data/test/dbd/postgresql/test_blob.rb +37 -0
  67. data/test/dbd/postgresql/test_bytea.rb +88 -0
  68. data/test/dbd/postgresql/test_ping.rb +10 -0
  69. data/test/dbd/postgresql/test_timestamp.rb +77 -0
  70. data/test/dbd/postgresql/test_transactions.rb +58 -0
  71. data/test/dbd/postgresql/testdbipg.rb +307 -0
  72. data/test/dbd/postgresql/up.sql +60 -0
  73. data/test/dbd/sqlite/base.rb +32 -0
  74. data/test/dbd/sqlite/test_database.rb +30 -0
  75. data/test/dbd/sqlite/test_driver.rb +68 -0
  76. data/test/dbd/sqlite/test_statement.rb +112 -0
  77. data/test/dbd/sqlite/up.sql +25 -0
  78. data/test/dbd/sqlite3/base.rb +32 -0
  79. data/test/dbd/sqlite3/test_database.rb +77 -0
  80. data/test/dbd/sqlite3/test_driver.rb +67 -0
  81. data/test/dbd/sqlite3/test_statement.rb +88 -0
  82. data/test/dbd/sqlite3/up.sql +33 -0
  83. data/test/dbi/tc_dbi.rb +1 -1
  84. data/test/ts_dbd.rb +136 -0
  85. data/ydbi.gemspec +25 -0
  86. metadata +148 -12
data/test/DBD_TESTS ADDED
@@ -0,0 +1,50 @@
1
+ ================================================================================
2
+ Using DBD tests
3
+ ================================================================================
4
+
5
+ Before you do anything, read the TESTING file.
6
+
7
+ Create a YAML file named .ruby-dbi.test-config.yaml in your home directory.
8
+
9
+ This file is a hash of keys that determine what you want to test and how you
10
+ access the databases related to those tests.
11
+
12
+ The key 'dbtypes' is an array which determines what tests you want to run. They
13
+ *do not* correspond to the driver names, they correspond to the test
14
+ directories that were made for them.
15
+
16
+ Each 'dbtype' has a key that contains a hash of values:
17
+ - username: the username of your account
18
+ - password: the password for your account
19
+ - dbname: the name of the database to connect to
20
+
21
+ NOTE that tests expect to connect to a database on localhost currently. This
22
+ may be fixed in the future, especially when we start writing Oracle and
23
+ SQLServer tests.
24
+
25
+ Each DBD test relies on database semantics which may not match up entirely with
26
+ this configuration. For instance, the postgresql tests expect you to be able to
27
+ work with the database directly via the `psql' client. This is something which
28
+ will eventually be remedied as time and ability allows.
29
+
30
+ Here is a sample configuration to get you started with the postgresql tests:
31
+
32
+ ################################################################################
33
+
34
+ ---
35
+ dbtypes:
36
+ - postgresql
37
+ postgresql:
38
+ username: erikh
39
+ password: monkeys
40
+ dbname: rubytest
41
+
42
+ ################################################################################
43
+
44
+ NOTE the --- is part of the file and is not a separator.
45
+
46
+ ================================================================================
47
+ Writing DBD tests
48
+ ================================================================================
49
+
50
+ Coming soon.
data/test/TESTING ADDED
@@ -0,0 +1,16 @@
1
+ ================================================================================
2
+ Running Tests
3
+ ================================================================================
4
+
5
+ You must have the source distribution (from git) to run the tests properly. This
6
+ is something I plan to remedy in 0.6.0.
7
+
8
+ You need the 'test-unit' gem to get started...
9
+
10
+ gem install test-unit
11
+
12
+ There are three rake targets, run from the root of the source.
13
+
14
+ test_dbi: these are interface tests and do not require database connectivity.
15
+ test_dbd: these are database-specific tests. Read DBD_TESTS.
16
+ test: runs the both test_dbi and test_dbd
@@ -0,0 +1,206 @@
1
+ @class = Class.new(DBDConfig.testbase(DBDConfig.current_dbtype)) do
2
+
3
+ def test_last_statement
4
+ @sth = @dbh.prepare("select * from names")
5
+ @sth.finish
6
+ assert_equal "select * from names", @dbh.last_statement
7
+
8
+ @sth = @dbh.execute("select * from names")
9
+ @sth.finish
10
+ assert_equal "select * from names", @dbh.last_statement
11
+
12
+ @dbh.do("select * from names")
13
+ assert_equal "select * from names", @dbh.last_statement
14
+ end
15
+
16
+ def test_empty_query
17
+ ["", " ", "\t"].each do |str|
18
+ [:do, :prepare, :execute, :select_one, :select_all].each do |call|
19
+ assert_raises(DBI::InterfaceError) do
20
+ @dbh.send(call, str)
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ def test_ping
27
+ assert @dbh.ping
28
+ # XXX if it isn't obvious, this should be tested better. Not sure what
29
+ # good behavior is yet.
30
+ end
31
+
32
+ def test_columns
33
+ assert_nothing_raised do
34
+ cols = @dbh.columns("precision_test")
35
+
36
+ assert(cols)
37
+ assert_kind_of(Array, cols)
38
+ assert_equal(4, cols.length)
39
+
40
+ # the first column should always be "text_field" and have the following
41
+ # properties:
42
+ assert_equal("text_field", cols[0]["name"])
43
+ assert(!cols[0]["nullable"])
44
+
45
+ assert_equal(20, cols[0]["precision"])
46
+ # scale can be either nil or 0 for character types.
47
+ case cols[0]["scale"]
48
+ when nil
49
+ assert_equal(nil, cols[0]["scale"])
50
+ when 0
51
+ assert_equal(0, cols[0]["scale"])
52
+ else
53
+ flunk "scale can be either 0 or nil for character types"
54
+ end
55
+
56
+ assert_equal(
57
+ DBI::Type::Varchar.object_id,
58
+ DBI::TypeUtil.type_name_to_module(cols[0]["type_name"]).object_id
59
+ )
60
+
61
+ # the second column should always be "integer_field" and have the following
62
+ # properties:
63
+ assert_equal("integer_field", cols[1]["name"])
64
+ assert(cols[1]["nullable"])
65
+ assert_equal(1, cols[2]["scale"])
66
+ assert_equal(2, cols[2]["precision"])
67
+
68
+ assert_equal(
69
+ DBI::Type::Integer.object_id,
70
+ DBI::TypeUtil.type_name_to_module(cols[1]["type_name"]).object_id
71
+ )
72
+
73
+ # the second column should always be "integer_field" and have the following
74
+ # properties:
75
+ assert_equal("decimal_field", cols[2]["name"])
76
+ assert(cols[2]["nullable"])
77
+ assert_equal(1, cols[2]["scale"])
78
+ assert_equal(2, cols[2]["precision"])
79
+ assert_equal(
80
+ DBI::Type::Decimal.object_id,
81
+ DBI::TypeUtil.type_name_to_module(cols[2]["type_name"]).object_id
82
+ )
83
+
84
+ # the second column should always be "numeric_field" and have the following
85
+ # properties:
86
+ assert_equal("numeric_field", cols[3]["name"])
87
+ assert(cols[3]["nullable"])
88
+ assert_equal(6, cols[3]["scale"])
89
+ assert_equal(30, cols[3]["precision"])
90
+ assert_equal(
91
+ DBI::Type::Decimal.object_id,
92
+ DBI::TypeUtil.type_name_to_module(cols[3]["type_name"]).object_id
93
+ )
94
+
95
+ # finally, we ensure that every column in the array is a ColumnInfo
96
+ # object
97
+ cols.each { |col| assert_kind_of(DBI::ColumnInfo, col) }
98
+ end
99
+ end
100
+
101
+ def test_prepare
102
+ @sth = @dbh.prepare('select * from names')
103
+
104
+ assert @sth
105
+ assert_kind_of DBI::StatementHandle, @sth
106
+
107
+ @sth.finish
108
+ end
109
+
110
+ def test_do
111
+ assert_equal 1, @dbh.do("insert into names (name, age) values (?, ?)", "Billy", 21)
112
+ @sth = @dbh.prepare("select * from names where name = ?")
113
+ @sth.execute("Billy")
114
+ assert_equal ["Billy", 21], @sth.fetch
115
+ @sth.finish
116
+ end
117
+
118
+ def test_tables
119
+ tables = @dbh.tables.sort
120
+
121
+ # since this is a general test, let's prune the system tables
122
+ # FIXME not so sure if this should be a general test anymore.
123
+ if dbtype == "odbc"
124
+ tables -= [
125
+ "administrable_role_authorizations",
126
+ "applicable_roles",
127
+ "attributes",
128
+ "check_constraint_routine_usage",
129
+ "check_constraints",
130
+ "column_domain_usage",
131
+ "column_privileges",
132
+ "column_udt_usage",
133
+ "columns",
134
+ "constraint_column_usage",
135
+ "constraint_table_usage",
136
+ "data_type_privileges",
137
+ "domain_constraints",
138
+ "domain_udt_usage",
139
+ "domains",
140
+ "element_types",
141
+ "enabled_roles",
142
+ "information_schema_catalog_name",
143
+ "key_column_usage",
144
+ "parameters",
145
+ "referential_constraints",
146
+ "role_column_grants",
147
+ "role_routine_grants",
148
+ "role_table_grants",
149
+ "role_usage_grants",
150
+ "routine_privileges",
151
+ "routines",
152
+ "schemata",
153
+ "sequences",
154
+ "sql_features",
155
+ "sql_implementation_info",
156
+ "sql_languages",
157
+ "sql_packages",
158
+ "sql_parts",
159
+ "sql_sizing",
160
+ "sql_sizing_profiles",
161
+ "table_constraints",
162
+ "table_privileges",
163
+ "tables",
164
+ "triggered_update_columns",
165
+ "triggers",
166
+ "usage_privileges",
167
+ "view_column_usage",
168
+ "view_routine_usage",
169
+ "view_table_usage",
170
+ "views"
171
+ ]
172
+ end
173
+
174
+ case dbtype
175
+ when "postgresql"
176
+ tables.reject! { |x| x =~ /^pg_/ }
177
+ assert_equal %w(array_test bit_test blob_test boolean_test bytea_test db_specific_types_test enum_type_test field_types_test names precision_test time_test timestamp_test view_names), tables
178
+ when 'sqlite3'
179
+ assert_equal %w(bit_test blob_test boolean_test db_specific_types_test field_types_test names names_defined_with_spaces precision_test time_test timestamp_test view_names), tables
180
+ else
181
+ assert_equal %w(bit_test blob_test boolean_test db_specific_types_test field_types_test names precision_test time_test timestamp_test view_names), tables
182
+ end
183
+ end
184
+
185
+ def test_attrs
186
+ # test defaults
187
+ assert @dbh["AutoCommit"] # should be true
188
+
189
+ # test setting
190
+ assert !(@dbh["AutoCommit"] = false)
191
+ assert !@dbh["AutoCommit"]
192
+
193
+ # test committing an outstanding transaction
194
+
195
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
196
+ @sth.execute("Billy", 22)
197
+ @sth.finish
198
+
199
+ assert @dbh["AutoCommit"] = true # should commit at this point
200
+
201
+ @sth = @dbh.prepare("select * from names where name = ?")
202
+ @sth.execute("Billy")
203
+ assert_equal [ "Billy", 22 ], @sth.fetch
204
+ @sth.finish
205
+ end
206
+ end
@@ -0,0 +1,325 @@
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
+ end
48
+
49
+ def test_execute
50
+ assert_nothing_raised do
51
+ @dbh.execute("select * from names order by age") do |sth|
52
+ assert_equal([["Joe", 19], ["Bob", 21], ["Jim", 30]], sth.fetch_all)
53
+ end
54
+ end
55
+ end
56
+
57
+ def test_quoting # FIXME breaks sqlite-ruby to a segfault - research
58
+ @sth = nil
59
+
60
+ assert_nothing_raised do
61
+ if dbtype == "postgresql"
62
+ @sth = @dbh.prepare('select E\'\\\\\'')
63
+ else
64
+ @sth = @dbh.prepare('select \'\\\\\'')
65
+ end
66
+ @sth.execute
67
+ row = @sth.fetch
68
+ assert_equal ['\\'], row
69
+ @sth.finish
70
+ end
71
+ end
72
+
73
+ def test_duplicate_columns_1
74
+ assert_nothing_raised do
75
+ @sth = @dbh.prepare("select name, name from names where name = ?")
76
+ @sth.execute("Bob")
77
+ assert_equal [["Bob", "Bob"]], @sth.fetch_all
78
+ @sth.finish
79
+ end
80
+ end
81
+
82
+ def test_columninfo
83
+ @sth = nil
84
+
85
+ assert_nothing_raised do
86
+ @sth = @dbh.prepare("select * from precision_test")
87
+ @sth.execute
88
+
89
+ cols = @sth.column_info
90
+
91
+ assert(cols)
92
+ assert_kind_of(Array, cols)
93
+ assert_equal(4, cols.length)
94
+
95
+ # the first column should always be "text_field" and have the following
96
+ # properties:
97
+ assert_equal("text_field", cols[0]["name"])
98
+ assert_equal(20, cols[0]["precision"])
99
+ # scale can be either nil or 0 for character types.
100
+ case cols[0]["scale"]
101
+ when nil
102
+ assert_equal(nil, cols[0]["scale"])
103
+ when 0
104
+ assert_equal(0, cols[0]["scale"])
105
+ else
106
+ flunk "scale can be either 0 or nil for character types"
107
+ end
108
+
109
+ assert_equal(
110
+ DBI::Type::Varchar.object_id,
111
+ DBI::TypeUtil.type_name_to_module(cols[0]["type_name"]).object_id
112
+ )
113
+
114
+ # the second column should always be "integer_field" and have the following
115
+ # properties:
116
+ assert_equal("integer_field", cols[1]["name"])
117
+ # if these aren't set on the field, they should not exist
118
+ # FIXME mysql does not follow this rule, neither does ODBC
119
+ if dbtype == "mysql"
120
+ assert_equal(0, cols[1]["scale"])
121
+ assert_equal(11, cols[1]["precision"])
122
+ elsif dbtype == "odbc"
123
+ assert_equal(0, cols[1]["scale"])
124
+ assert_equal(10, cols[1]["precision"])
125
+ else
126
+ assert(!cols[1]["scale"])
127
+ assert(!cols[1]["precision"])
128
+ end
129
+
130
+ assert_equal(
131
+ DBI::Type::Integer.object_id,
132
+ DBI::TypeUtil.type_name_to_module(cols[1]["type_name"]).object_id
133
+ )
134
+
135
+ # the second column should always be "integer_field" and have the following
136
+ # properties:
137
+ assert_equal("decimal_field", cols[2]["name"])
138
+ assert_equal(1, cols[2]["scale"])
139
+ assert_equal(2, cols[2]["precision"])
140
+ assert_equal(
141
+ DBI::Type::Decimal.object_id,
142
+ DBI::TypeUtil.type_name_to_module(cols[2]["type_name"]).object_id
143
+ )
144
+
145
+ # the second column should always be "numeric_field" and have the following
146
+ # properties:
147
+ assert_equal("numeric_field", cols[3]["name"])
148
+ assert_equal(6, cols[3]["scale"])
149
+ assert_equal(30, cols[3]["precision"])
150
+ assert_equal(
151
+ DBI::Type::Decimal.object_id,
152
+ DBI::TypeUtil.type_name_to_module(cols[3]["type_name"]).object_id
153
+ )
154
+
155
+ cols.each { |col| assert_kind_of(DBI::ColumnInfo, col) }
156
+ @sth.finish
157
+ end
158
+ end
159
+
160
+ def test_duplicate_columns
161
+ assert_nothing_raised do
162
+ @sth = @dbh.prepare("select name, name from names where name = ?")
163
+ @sth.execute("Bob")
164
+ assert_equal [["Bob", "Bob"]], @sth.fetch_all
165
+ @sth.finish
166
+ end
167
+ end
168
+
169
+ def test_rows
170
+ @sth = nil
171
+
172
+ assert_nothing_raised do
173
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
174
+ @sth.execute("Bill", 22);
175
+ end
176
+
177
+ assert_equal 1, @sth.rows
178
+
179
+ @sth.finish
180
+ @sth = nil
181
+
182
+ assert_nothing_raised do
183
+ @sth = @dbh.prepare("delete from names where name = ?")
184
+ @sth.execute("Bill");
185
+ end
186
+
187
+ assert_equal 1, @sth.rows
188
+
189
+ @sth.finish
190
+
191
+ assert_nothing_raised do
192
+ @sth = @dbh.prepare("select * from names")
193
+ @sth.execute
194
+ end
195
+
196
+ assert_equal 3, @sth.rows
197
+ assert @sth.fetchable?
198
+ assert @sth.any?
199
+ @sth.finish
200
+ end
201
+
202
+ def test_prepare_execute
203
+ assert_nothing_raised do
204
+ @sth = @dbh.prepare("select * from names")
205
+ @sth.execute
206
+ @sth.finish
207
+ end
208
+
209
+ assert_nothing_raised do
210
+ @sth = @dbh.prepare("select * from names where name = ?")
211
+ @sth.execute("Bob")
212
+ @sth.finish
213
+ end
214
+
215
+ assert_nothing_raised do
216
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
217
+ @sth.execute("Bill", 22);
218
+ @sth.finish
219
+ end
220
+ end
221
+
222
+ def test_prepare_execute_with_transactions
223
+ @dbh["AutoCommit"] = false
224
+ config = DBDConfig.get_config['sqlite3']
225
+
226
+ # rollback 1 (the right way)
227
+ @sth = nil
228
+ @sth2 = nil
229
+
230
+ assert_nothing_raised do
231
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
232
+ @sth.execute("Billy", 23)
233
+ @sth2 = @dbh.prepare("select * from names where name = ?")
234
+ @sth2.execute("Billy")
235
+ end
236
+ assert_equal ["Billy", 23 ], @sth2.fetch
237
+ @sth2.finish
238
+ @sth.finish
239
+ assert_nothing_raised { @dbh.rollback }
240
+
241
+ @sth = @dbh.prepare("select * from names where name = ?")
242
+ @sth.execute("Billy")
243
+ assert_nil @sth.fetch
244
+ @sth.finish
245
+
246
+ # rollback 2 (without closing statements first)
247
+
248
+ @sth = nil
249
+ @sth2 = nil
250
+
251
+ assert_nothing_raised do
252
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
253
+ @sth.execute("Billy", 23)
254
+ @sth2 = @dbh.prepare("select * from names where name = ?")
255
+ @sth2.execute("Billy")
256
+ end
257
+
258
+ assert_equal ["Billy", 23], @sth2.fetch
259
+
260
+ # FIXME some throw here, some don't. we should probably normalize this
261
+ @dbh.rollback rescue true
262
+
263
+ @sth2.finish
264
+ @sth.finish
265
+ assert_nothing_raised { @dbh.rollback }
266
+
267
+ @sth = @dbh.prepare("select * from names where name = ?")
268
+ @sth.execute("Billy")
269
+ assert_nil @sth.fetch
270
+ @sth.finish
271
+
272
+ # commit
273
+
274
+ @sth = nil
275
+ @sth2 = nil
276
+
277
+ assert_nothing_raised do
278
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
279
+ @sth.execute("Billy", 23)
280
+ @sth2 = @dbh.prepare("select * from names where name = ?")
281
+ @sth2.execute("Billy")
282
+ end
283
+ assert_equal ["Billy", 23 ], @sth2.fetch
284
+ @sth2.finish
285
+ @sth.finish
286
+ assert_nothing_raised { @dbh.commit }
287
+
288
+ @sth = @dbh.prepare("select * from names where name = ?")
289
+ @sth.execute("Billy")
290
+ assert_equal ["Billy", 23 ], @sth.fetch
291
+ @sth.finish
292
+ end
293
+
294
+ def test_fetch
295
+ @sth = nil
296
+ assert_nothing_raised do
297
+ @sth = @dbh.prepare("select * from names order by age")
298
+ @sth.execute
299
+ end
300
+
301
+ # this tests that we're getting the rows in the right order,
302
+ # and that the types are being converted.
303
+ assert_equal ["Joe", 19], @sth.fetch
304
+ assert_equal ["Bob", 21], @sth.fetch
305
+ assert_equal ["Jim", 30], @sth.fetch
306
+ assert_nil @sth.fetch
307
+
308
+ @sth.finish
309
+ end
310
+
311
+ def test_transaction_block
312
+ @dbh["AutoCommit"] = false
313
+ # this transaction should not fail because it called return early
314
+ @dbh.transaction do |dbh|
315
+ dbh.do('INSERT INTO names (name, age) VALUES (?, ?)', "Cooter", 69)
316
+ return 42
317
+ end
318
+ @sth = @dbh.prepare("select * from names where name = ?")
319
+ @sth.execute("Cooter")
320
+ row = @sth.fetch
321
+ assert row
322
+ assert_equal ["Cooter", 69], row
323
+ @sth.finish
324
+ end
325
+ end