ydbi 0.5.6 → 0.5.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +35 -0
  3. data/.gitignore +8 -0
  4. data/.travis.yml +15 -0
  5. data/ChangeLog +321 -314
  6. data/Gemfile +5 -0
  7. data/Rakefile +10 -0
  8. data/TODO +44 -0
  9. data/bench/bench.rb +79 -0
  10. data/build/rake_task_lib.rb +186 -0
  11. data/doc/DBD_SPEC.rdoc +88 -0
  12. data/doc/DBI_SPEC.rdoc +157 -0
  13. data/doc/homepage/contact.html +62 -0
  14. data/doc/homepage/development.html +124 -0
  15. data/doc/homepage/index.html +83 -0
  16. data/doc/homepage/ruby-dbi.css +91 -0
  17. data/lib/dbd/Mysql.rb +137 -0
  18. data/lib/dbd/ODBC.rb +89 -0
  19. data/lib/dbd/Pg.rb +188 -0
  20. data/lib/dbd/SQLite.rb +97 -0
  21. data/lib/dbd/SQLite3.rb +124 -0
  22. data/lib/dbd/mysql/database.rb +405 -0
  23. data/lib/dbd/mysql/driver.rb +125 -0
  24. data/lib/dbd/mysql/statement.rb +188 -0
  25. data/lib/dbd/odbc/database.rb +128 -0
  26. data/lib/dbd/odbc/driver.rb +38 -0
  27. data/lib/dbd/odbc/statement.rb +137 -0
  28. data/lib/dbd/pg/database.rb +504 -0
  29. data/lib/dbd/pg/exec.rb +47 -0
  30. data/lib/dbd/pg/statement.rb +160 -0
  31. data/lib/dbd/pg/tuples.rb +121 -0
  32. data/lib/dbd/pg/type.rb +209 -0
  33. data/lib/dbd/sqlite/database.rb +151 -0
  34. data/lib/dbd/sqlite/statement.rb +125 -0
  35. data/lib/dbd/sqlite3/database.rb +201 -0
  36. data/lib/dbd/sqlite3/statement.rb +78 -0
  37. data/lib/dbi.rb +13 -17
  38. data/lib/dbi/utils/date.rb +7 -3
  39. data/lib/dbi/version.rb +1 -1
  40. data/prototypes/types2.rb +237 -0
  41. data/setup.rb +1585 -0
  42. data/test/DBD_TESTS +50 -0
  43. data/test/TESTING +16 -0
  44. data/test/dbd/general/test_database.rb +206 -0
  45. data/test/dbd/general/test_statement.rb +326 -0
  46. data/test/dbd/general/test_types.rb +296 -0
  47. data/test/dbd/mysql/base.rb +26 -0
  48. data/test/dbd/mysql/down.sql +19 -0
  49. data/test/dbd/mysql/test_blob.rb +18 -0
  50. data/test/dbd/mysql/test_new_methods.rb +7 -0
  51. data/test/dbd/mysql/test_patches.rb +111 -0
  52. data/test/dbd/mysql/up.sql +28 -0
  53. data/test/dbd/odbc/base.rb +30 -0
  54. data/test/dbd/odbc/down.sql +19 -0
  55. data/test/dbd/odbc/test_new_methods.rb +12 -0
  56. data/test/dbd/odbc/test_ping.rb +10 -0
  57. data/test/dbd/odbc/test_statement.rb +44 -0
  58. data/test/dbd/odbc/test_transactions.rb +58 -0
  59. data/test/dbd/odbc/up.sql +33 -0
  60. data/test/dbd/postgresql/base.rb +31 -0
  61. data/test/dbd/postgresql/down.sql +31 -0
  62. data/test/dbd/postgresql/test_arrays.rb +179 -0
  63. data/test/dbd/postgresql/test_async.rb +121 -0
  64. data/test/dbd/postgresql/test_blob.rb +36 -0
  65. data/test/dbd/postgresql/test_bytea.rb +87 -0
  66. data/test/dbd/postgresql/test_ping.rb +10 -0
  67. data/test/dbd/postgresql/test_timestamp.rb +77 -0
  68. data/test/dbd/postgresql/test_transactions.rb +58 -0
  69. data/test/dbd/postgresql/testdbipg.rb +307 -0
  70. data/test/dbd/postgresql/up.sql +60 -0
  71. data/test/dbd/sqlite/base.rb +32 -0
  72. data/test/dbd/sqlite/test_database.rb +30 -0
  73. data/test/dbd/sqlite/test_driver.rb +68 -0
  74. data/test/dbd/sqlite/test_statement.rb +112 -0
  75. data/test/dbd/sqlite/up.sql +25 -0
  76. data/test/dbd/sqlite3/base.rb +32 -0
  77. data/test/dbd/sqlite3/test_database.rb +77 -0
  78. data/test/dbd/sqlite3/test_driver.rb +67 -0
  79. data/test/dbd/sqlite3/test_statement.rb +88 -0
  80. data/test/dbd/sqlite3/up.sql +33 -0
  81. data/test/dbi/tc_columninfo.rb +4 -9
  82. data/test/dbi/tc_date.rb +2 -9
  83. data/test/dbi/tc_dbi.rb +3 -9
  84. data/test/dbi/tc_row.rb +17 -23
  85. data/test/dbi/tc_sqlbind.rb +6 -7
  86. data/test/dbi/tc_statementhandle.rb +3 -4
  87. data/test/dbi/tc_time.rb +2 -8
  88. data/test/dbi/tc_timestamp.rb +2 -16
  89. data/test/dbi/tc_types.rb +5 -11
  90. data/test/ts_dbd.rb +131 -0
  91. data/ydbi.gemspec +23 -0
  92. metadata +128 -10
@@ -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.
@@ -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,326 @@
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
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 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 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 0, @sth.rows
197
+ assert @sth.fetchable?
198
+ assert @sth.any?
199
+ assert @sth.rows.zero?
200
+ @sth.finish
201
+ end
202
+
203
+ def test_prepare_execute
204
+ assert_nothing_raised do
205
+ @sth = @dbh.prepare("select * from names")
206
+ @sth.execute
207
+ @sth.finish
208
+ end
209
+
210
+ assert_nothing_raised do
211
+ @sth = @dbh.prepare("select * from names where name = ?")
212
+ @sth.execute("Bob")
213
+ @sth.finish
214
+ end
215
+
216
+ assert_nothing_raised do
217
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
218
+ @sth.execute("Bill", 22);
219
+ @sth.finish
220
+ end
221
+ end
222
+
223
+ def test_prepare_execute_with_transactions
224
+ @dbh["AutoCommit"] = false
225
+ config = DBDConfig.get_config['sqlite3']
226
+
227
+ # rollback 1 (the right way)
228
+ @sth = nil
229
+ @sth2 = nil
230
+
231
+ assert_nothing_raised do
232
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
233
+ @sth.execute("Billy", 23)
234
+ @sth2 = @dbh.prepare("select * from names where name = ?")
235
+ @sth2.execute("Billy")
236
+ end
237
+ assert_equal ["Billy", 23 ], @sth2.fetch
238
+ @sth2.finish
239
+ @sth.finish
240
+ assert_nothing_raised { @dbh.rollback }
241
+
242
+ @sth = @dbh.prepare("select * from names where name = ?")
243
+ @sth.execute("Billy")
244
+ assert_nil @sth.fetch
245
+ @sth.finish
246
+
247
+ # rollback 2 (without closing statements first)
248
+
249
+ @sth = nil
250
+ @sth2 = nil
251
+
252
+ assert_nothing_raised do
253
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
254
+ @sth.execute("Billy", 23)
255
+ @sth2 = @dbh.prepare("select * from names where name = ?")
256
+ @sth2.execute("Billy")
257
+ end
258
+
259
+ assert_equal ["Billy", 23], @sth2.fetch
260
+
261
+ # FIXME some throw here, some don't. we should probably normalize this
262
+ @dbh.rollback rescue true
263
+
264
+ @sth2.finish
265
+ @sth.finish
266
+ assert_nothing_raised { @dbh.rollback }
267
+
268
+ @sth = @dbh.prepare("select * from names where name = ?")
269
+ @sth.execute("Billy")
270
+ assert_nil @sth.fetch
271
+ @sth.finish
272
+
273
+ # commit
274
+
275
+ @sth = nil
276
+ @sth2 = nil
277
+
278
+ assert_nothing_raised do
279
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
280
+ @sth.execute("Billy", 23)
281
+ @sth2 = @dbh.prepare("select * from names where name = ?")
282
+ @sth2.execute("Billy")
283
+ end
284
+ assert_equal ["Billy", 23 ], @sth2.fetch
285
+ @sth2.finish
286
+ @sth.finish
287
+ assert_nothing_raised { @dbh.commit }
288
+
289
+ @sth = @dbh.prepare("select * from names where name = ?")
290
+ @sth.execute("Billy")
291
+ assert_equal ["Billy", 23 ], @sth.fetch
292
+ @sth.finish
293
+ end
294
+
295
+ def test_fetch
296
+ @sth = nil
297
+ assert_nothing_raised do
298
+ @sth = @dbh.prepare("select * from names order by age")
299
+ @sth.execute
300
+ end
301
+
302
+ # this tests that we're getting the rows in the right order,
303
+ # and that the types are being converted.
304
+ assert_equal ["Joe", 19], @sth.fetch
305
+ assert_equal ["Bob", 21], @sth.fetch
306
+ assert_equal ["Jim", 30], @sth.fetch
307
+ assert_nil @sth.fetch
308
+
309
+ @sth.finish
310
+ end
311
+
312
+ def test_transaction_block
313
+ @dbh["AutoCommit"] = false
314
+ # this transaction should not fail because it called return early
315
+ @dbh.transaction do |dbh|
316
+ dbh.do('INSERT INTO names (name, age) VALUES (?, ?)', "Cooter", 69)
317
+ return 42
318
+ end
319
+ @sth = @dbh.prepare("select * from names where name = ?")
320
+ @sth.execute("Cooter")
321
+ row = @sth.fetch
322
+ assert row
323
+ assert_equal ["Cooter", 69], row
324
+ @sth.finish
325
+ end
326
+ end