dbd-pg 0.3.3

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.
@@ -0,0 +1,48 @@
1
+ ================================================================================
2
+ Using DBD tests
3
+ ================================================================================
4
+
5
+ Create a YAML file named .ruby-dbi.test-config.yaml in your home directory.
6
+
7
+ This file is a hash of keys that determine what you want to test and how you
8
+ access the databases related to those tests.
9
+
10
+ The key 'dbtypes' is an array which determines what tests you want to run. They
11
+ *do not* correspond to the driver names, they correspond to the test
12
+ directories that were made for them.
13
+
14
+ Each 'dbtype' has a key that contains a hash of values:
15
+ - username: the username of your account
16
+ - password: the password for your account
17
+ - dbname: the name of the database to connect to
18
+
19
+ NOTE that tests expect to connect to a database on localhost currently. This
20
+ may be fixed in the future, especially when we start writing Oracle and
21
+ SQLServer tests.
22
+
23
+ Each DBD test relies on database semantics which may not match up entirely with
24
+ this configuration. For instance, the postgresql tests expect you to be able to
25
+ work with the database directly via the `psql' client. This is something which
26
+ will eventually be remedied as time and ability allows.
27
+
28
+ Here is a sample configuration to get you started with the postgresql tests:
29
+
30
+ ################################################################################
31
+
32
+ ---
33
+ dbtypes:
34
+ - postgresql
35
+ postgresql:
36
+ username: erikh
37
+ password: monkeys
38
+ dbname: rubytest
39
+
40
+ ################################################################################
41
+
42
+ NOTE the --- is part of the file and is not a separator.
43
+
44
+ ================================================================================
45
+ Writing DBD tests
46
+ ================================================================================
47
+
48
+ Coming soon.
@@ -0,0 +1,157 @@
1
+ @class = Class.new(DBDConfig.testbase(DBDConfig.current_dbtype)) do
2
+ def test_ping
3
+ assert @dbh.ping
4
+ # XXX if it isn't obvious, this should be tested better. Not sure what
5
+ # good behavior is yet.
6
+ end
7
+
8
+ def test_columns
9
+ assert_nothing_raised do
10
+ cols = @dbh.columns("precision_test")
11
+
12
+ assert(cols)
13
+ assert_kind_of(Array, cols)
14
+ assert_equal(2, cols.length)
15
+
16
+ # the first column should always be "text_field" and have the following
17
+ # properties:
18
+ assert_equal("text_field", cols[0]["name"])
19
+ assert(!cols[0]["nullable"])
20
+
21
+ assert_equal(20, cols[0]["precision"])
22
+ # scale can be either nil or 0 for character types.
23
+ case cols[0]["scale"]
24
+ when nil
25
+ assert_equal(nil, cols[0]["scale"])
26
+ when 0
27
+ assert_equal(0, cols[0]["scale"])
28
+ else
29
+ flunk "scale can be either 0 or nil for character types"
30
+ end
31
+
32
+ assert_equal(
33
+ DBI::Type::Varchar,
34
+ DBI::TypeUtil.type_name_to_module(cols[0]["type_name"])
35
+ )
36
+
37
+ # the second column should always be "integer_field" and have the following
38
+ # properties:
39
+ assert_equal("integer_field", cols[1]["name"])
40
+ assert(cols[1]["nullable"])
41
+ assert_equal(1, cols[1]["scale"])
42
+ assert_equal(2, cols[1]["precision"])
43
+ assert_equal(
44
+ DBI::Type::Decimal,
45
+ DBI::TypeUtil.type_name_to_module(cols[1]["type_name"])
46
+ )
47
+
48
+ # finally, we ensure that every column in the array is a ColumnInfo
49
+ # object
50
+ cols.each { |col| assert_kind_of(DBI::ColumnInfo, col) }
51
+ end
52
+ end
53
+
54
+ def test_prepare
55
+ @sth = @dbh.prepare('select * from names')
56
+
57
+ assert @sth
58
+ assert_kind_of DBI::StatementHandle, @sth
59
+
60
+ @sth.finish
61
+ end
62
+
63
+ def test_do
64
+ assert_equal 1, @dbh.do("insert into names (name, age) values (?, ?)", "Billy", 21)
65
+ @sth = @dbh.prepare("select * from names where name = ?")
66
+ @sth.execute("Billy")
67
+ assert_equal ["Billy", 21], @sth.fetch
68
+ @sth.finish
69
+ end
70
+
71
+ def test_tables
72
+ tables = @dbh.tables.sort
73
+
74
+ # since this is a general test, let's prune the system tables
75
+ # FIXME not so sure if this should be a general test anymore.
76
+ if dbtype == "odbc"
77
+ tables -= [
78
+ "administrable_role_authorizations",
79
+ "applicable_roles",
80
+ "attributes",
81
+ "check_constraint_routine_usage",
82
+ "check_constraints",
83
+ "column_domain_usage",
84
+ "column_privileges",
85
+ "column_udt_usage",
86
+ "columns",
87
+ "constraint_column_usage",
88
+ "constraint_table_usage",
89
+ "data_type_privileges",
90
+ "domain_constraints",
91
+ "domain_udt_usage",
92
+ "domains",
93
+ "element_types",
94
+ "enabled_roles",
95
+ "information_schema_catalog_name",
96
+ "key_column_usage",
97
+ "parameters",
98
+ "referential_constraints",
99
+ "role_column_grants",
100
+ "role_routine_grants",
101
+ "role_table_grants",
102
+ "role_usage_grants",
103
+ "routine_privileges",
104
+ "routines",
105
+ "schemata",
106
+ "sequences",
107
+ "sql_features",
108
+ "sql_implementation_info",
109
+ "sql_languages",
110
+ "sql_packages",
111
+ "sql_parts",
112
+ "sql_sizing",
113
+ "sql_sizing_profiles",
114
+ "table_constraints",
115
+ "table_privileges",
116
+ "tables",
117
+ "triggered_update_columns",
118
+ "triggers",
119
+ "usage_privileges",
120
+ "view_column_usage",
121
+ "view_routine_usage",
122
+ "view_table_usage",
123
+ "views"
124
+ ]
125
+ end
126
+
127
+ case dbtype
128
+ when "postgresql"
129
+ tables.reject! { |x| x =~ /^pg_/ }
130
+ assert_equal %w(array_test bit_test blob_test boolean_test bytea_test field_types_test names precision_test time_test timestamp_test view_names), tables
131
+ else
132
+ assert_equal %w(bit_test blob_test boolean_test field_types_test names precision_test time_test timestamp_test view_names), tables
133
+ end
134
+ end
135
+
136
+ def test_attrs
137
+ # test defaults
138
+ assert @dbh["AutoCommit"] # should be true
139
+
140
+ # test setting
141
+ assert !(@dbh["AutoCommit"] = false)
142
+ assert !@dbh["AutoCommit"]
143
+
144
+ # test committing an outstanding transaction
145
+
146
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
147
+ @sth.execute("Billy", 22)
148
+ @sth.finish
149
+
150
+ assert @dbh["AutoCommit"] = true # should commit at this point
151
+
152
+ @sth = @dbh.prepare("select * from names where name = ?")
153
+ @sth.execute("Billy")
154
+ assert_equal [ "Billy", 22 ], @sth.fetch
155
+ @sth.finish
156
+ end
157
+ end
@@ -0,0 +1,240 @@
1
+ @class = Class.new(DBDConfig.testbase(DBDConfig.current_dbtype)) do
2
+ def test_quoting # FIXME breaks sqlite-ruby to a segfault - research
3
+ @sth = nil
4
+
5
+ assert_nothing_raised do
6
+ if dbtype == "postgresql"
7
+ @sth = @dbh.prepare('select E\'\\\\\'')
8
+ else
9
+ @sth = @dbh.prepare('select \'\\\\\'')
10
+ end
11
+ @sth.execute
12
+ row = @sth.fetch
13
+ assert_equal ['\\'], row
14
+ @sth.finish
15
+ end
16
+ end
17
+
18
+ def test_duplicate_columns
19
+ assert_nothing_raised do
20
+ @sth = @dbh.prepare("select name, name from names where name = ?")
21
+ @sth.execute("Bob")
22
+ assert_equal [["Bob", "Bob"]], @sth.fetch_all
23
+ @sth.finish
24
+ end
25
+ end
26
+
27
+ def test_columninfo
28
+ @sth = nil
29
+
30
+ assert_nothing_raised do
31
+ @sth = @dbh.prepare("select * from precision_test")
32
+ @sth.execute
33
+
34
+ cols = @sth.column_info
35
+
36
+ assert(cols)
37
+ assert_kind_of(Array, cols)
38
+ assert_equal(2, 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_equal(20, cols[0]["precision"])
44
+ # scale can be either nil or 0 for character types.
45
+ case cols[0]["scale"]
46
+ when nil
47
+ assert_equal(nil, cols[0]["scale"])
48
+ when 0
49
+ assert_equal(0, cols[0]["scale"])
50
+ else
51
+ flunk "scale can be either 0 or nil for character types"
52
+ end
53
+
54
+ assert_equal(
55
+ DBI::Type::Varchar,
56
+ DBI::TypeUtil.type_name_to_module(cols[0]["type_name"])
57
+ )
58
+
59
+ # the second column should always be "integer_field" and have the following
60
+ # properties:
61
+ assert_equal("integer_field", cols[1]["name"])
62
+ assert_equal(1, cols[1]["scale"])
63
+ assert_equal(2, cols[1]["precision"])
64
+ assert_equal(
65
+ DBI::Type::Decimal,
66
+ DBI::TypeUtil.type_name_to_module(cols[1]["type_name"])
67
+ )
68
+
69
+ cols.each { |col| assert_kind_of(DBI::ColumnInfo, col) }
70
+ @sth.finish
71
+ end
72
+ end
73
+
74
+ def test_duplicate_columns
75
+ assert_nothing_raised do
76
+ @sth = @dbh.prepare("select name, name from names where name = ?")
77
+ @sth.execute("Bob")
78
+ assert_equal [["Bob", "Bob"]], @sth.fetch_all
79
+ @sth.finish
80
+ end
81
+ end
82
+
83
+ def test_rows
84
+ @sth = nil
85
+
86
+ assert_nothing_raised do
87
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
88
+ @sth.execute("Bill", 22);
89
+ end
90
+
91
+ assert 1, @sth.rows
92
+
93
+ @sth.finish
94
+ @sth = nil
95
+
96
+ assert_nothing_raised do
97
+ @sth = @dbh.prepare("delete from names where name = ?")
98
+ @sth.execute("Bill");
99
+ end
100
+
101
+ assert 1, @sth.rows
102
+
103
+ @sth.finish
104
+
105
+ assert_nothing_raised do
106
+ @sth = @dbh.prepare("select * from names")
107
+ @sth.execute
108
+ end
109
+
110
+ assert_equal 0, @sth.rows
111
+ assert @sth.fetchable?
112
+ assert @sth.any?
113
+ assert @sth.rows.zero?
114
+ @sth.finish
115
+ end
116
+
117
+ def test_execute
118
+ assert_nothing_raised do
119
+ @sth = @dbh.prepare("select * from names")
120
+ @sth.execute
121
+ @sth.finish
122
+ end
123
+
124
+ assert_nothing_raised do
125
+ @sth = @dbh.prepare("select * from names where name = ?")
126
+ @sth.execute("Bob")
127
+ @sth.finish
128
+ end
129
+
130
+ assert_nothing_raised do
131
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
132
+ @sth.execute("Bill", 22);
133
+ @sth.finish
134
+ end
135
+ end
136
+
137
+ def test_execute_with_transactions
138
+ @dbh["AutoCommit"] = false
139
+ config = DBDConfig.get_config['sqlite3']
140
+
141
+ # rollback 1 (the right way)
142
+ @sth = nil
143
+ @sth2 = nil
144
+
145
+ assert_nothing_raised do
146
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
147
+ @sth.execute("Billy", 23)
148
+ @sth2 = @dbh.prepare("select * from names where name = ?")
149
+ @sth2.execute("Billy")
150
+ end
151
+ assert_equal ["Billy", 23 ], @sth2.fetch
152
+ @sth2.finish
153
+ @sth.finish
154
+ assert_nothing_raised { @dbh.rollback }
155
+
156
+ @sth = @dbh.prepare("select * from names where name = ?")
157
+ @sth.execute("Billy")
158
+ assert_nil @sth.fetch
159
+ @sth.finish
160
+
161
+ # rollback 2 (without closing statements first)
162
+
163
+ @sth = nil
164
+ @sth2 = nil
165
+
166
+ assert_nothing_raised do
167
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
168
+ @sth.execute("Billy", 23)
169
+ @sth2 = @dbh.prepare("select * from names where name = ?")
170
+ @sth2.execute("Billy")
171
+ end
172
+
173
+ assert_equal ["Billy", 23], @sth2.fetch
174
+
175
+ # FIXME some throw here, some don't. we should probably normalize this
176
+ @dbh.rollback rescue true
177
+
178
+ @sth2.finish
179
+ @sth.finish
180
+ assert_nothing_raised { @dbh.rollback }
181
+
182
+ @sth = @dbh.prepare("select * from names where name = ?")
183
+ @sth.execute("Billy")
184
+ assert_nil @sth.fetch
185
+ @sth.finish
186
+
187
+ # commit
188
+
189
+ @sth = nil
190
+ @sth2 = nil
191
+
192
+ assert_nothing_raised do
193
+ @sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
194
+ @sth.execute("Billy", 23)
195
+ @sth2 = @dbh.prepare("select * from names where name = ?")
196
+ @sth2.execute("Billy")
197
+ end
198
+ assert_equal ["Billy", 23 ], @sth2.fetch
199
+ @sth2.finish
200
+ @sth.finish
201
+ assert_nothing_raised { @dbh.commit }
202
+
203
+ @sth = @dbh.prepare("select * from names where name = ?")
204
+ @sth.execute("Billy")
205
+ assert_equal ["Billy", 23 ], @sth.fetch
206
+ @sth.finish
207
+ end
208
+
209
+ def test_fetch
210
+ @sth = nil
211
+ assert_nothing_raised do
212
+ @sth = @dbh.prepare("select * from names order by age")
213
+ @sth.execute
214
+ end
215
+
216
+ # this tests that we're getting the rows in the right order,
217
+ # and that the types are being converted.
218
+ assert_equal ["Joe", 19], @sth.fetch
219
+ assert_equal ["Bob", 21], @sth.fetch
220
+ assert_equal ["Jim", 30], @sth.fetch
221
+ assert_nil @sth.fetch
222
+
223
+ @sth.finish
224
+ end
225
+
226
+ def test_transaction_block
227
+ @dbh["AutoCommit"] = false
228
+ # this transaction should not fail because it called return early
229
+ @dbh.transaction do |dbh|
230
+ dbh.do('INSERT INTO names (name, age) VALUES (?, ?)', "Cooter", 69)
231
+ return 42
232
+ end
233
+ @sth = @dbh.prepare("select * from names where name = ?")
234
+ @sth.execute("Cooter")
235
+ row = @sth.fetch
236
+ assert row
237
+ assert_equal ["Cooter", 69], row
238
+ @sth.finish
239
+ end
240
+ end
@@ -0,0 +1,253 @@
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 (?)")
8
+ @sth.bind_param(1, 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
+ # FIXME
29
+ # Ideally, this test should be split across the DBI tests and DBD, but for
30
+ # now testing against the DBDs really doesn't cost us anything other than
31
+ # debugging time if something breaks.
32
+ def test_bind_coltype
33
+ # ensure type conv didn't get turned off somewhere.
34
+ assert(DBI.convert_types)
35
+ assert(@dbh.convert_types)
36
+
37
+ assert_nothing_raised do
38
+ @sth = @dbh.prepare("select name, age from names order by age")
39
+ assert(@sth.convert_types) # again
40
+ @sth.execute
41
+ @sth.bind_coltype(2, DBI::Type::Varchar)
42
+ assert_equal(
43
+ [
44
+ ["Joe", "19"],
45
+ ["Bob", "21"],
46
+ ["Jim", "30"],
47
+ ], @sth.fetch_all
48
+ )
49
+ @sth.finish
50
+ end
51
+
52
+ # just to be sure..
53
+ assert_nothing_raised do
54
+ @sth = @dbh.prepare("select name, age from names order by age")
55
+ @sth.execute
56
+ @sth.bind_coltype(2, DBI::Type::Float)
57
+ @sth.fetch_all.collect { |x| assert_kind_of(Float, x[1]) }
58
+ @sth.finish
59
+ end
60
+
61
+ # now, let's check some failure cases
62
+ @sth = @dbh.prepare("select name, age from names order by age")
63
+
64
+ # can't bind_coltype before execute
65
+ assert_raise(DBI::InterfaceError) { @sth.bind_coltype(1, DBI::Type::Float) }
66
+ # can't index < 1
67
+ assert_raise(DBI::InterfaceError) { @sth.bind_coltype(0, DBI::Type::Float) }
68
+ end
69
+
70
+ def test_noconv
71
+ # XXX this test will fail the whole test suite miserably if it fails at any point.
72
+ assert(DBI.convert_types)
73
+
74
+ DBI.convert_types = false
75
+ @sth.finish rescue nil
76
+ @dbh.disconnect
77
+ set_base_dbh
78
+
79
+ assert(!@dbh.convert_types)
80
+
81
+ assert_nothing_raised do
82
+ @sth = @dbh.prepare("select * from names order by age")
83
+ assert(!@sth.convert_types)
84
+ @sth.execute
85
+ assert_equal(
86
+ [
87
+ ["Joe", "19"],
88
+ ["Bob", "21"],
89
+ ["Jim", "30"],
90
+ ], @sth.fetch_all
91
+ )
92
+ @sth.finish
93
+ end
94
+
95
+ DBI.convert_types = true
96
+ @sth.finish rescue nil
97
+ @dbh.disconnect
98
+ set_base_dbh
99
+
100
+ assert(DBI.convert_types)
101
+ assert(@dbh.convert_types)
102
+
103
+ assert_nothing_raised do
104
+ @sth = @dbh.prepare("select * from names order by age")
105
+ assert(@sth.convert_types)
106
+ @sth.execute
107
+ assert_equal(
108
+ [
109
+ ["Joe", 19],
110
+ ["Bob", 21],
111
+ ["Jim", 30],
112
+ ], @sth.fetch_all
113
+ )
114
+ @sth.finish
115
+ end
116
+
117
+ @dbh.convert_types = false
118
+
119
+ assert_nothing_raised do
120
+ @sth = @dbh.prepare("select * from names order by age")
121
+ assert(!@sth.convert_types)
122
+ @sth.execute
123
+ assert_equal(
124
+ [
125
+ ["Joe", "19"],
126
+ ["Bob", "21"],
127
+ ["Jim", "30"],
128
+ ], @sth.fetch_all
129
+ )
130
+ @sth.finish
131
+ end
132
+
133
+ @dbh.convert_types = true
134
+
135
+ assert_nothing_raised do
136
+ @sth = @dbh.prepare("select * from names order by age")
137
+ assert(@sth.convert_types)
138
+ @sth.convert_types = false
139
+ @sth.execute
140
+ assert_equal(
141
+ [
142
+ ["Joe", "19"],
143
+ ["Bob", "21"],
144
+ ["Jim", "30"],
145
+ ], @sth.fetch_all
146
+ )
147
+ @sth.finish
148
+ end
149
+ rescue Exception => e
150
+ DBI.convert_types = true
151
+ @sth.finish
152
+ @dbh.disconnect
153
+ set_base_dbh
154
+ raise e
155
+ end
156
+
157
+ def test_null
158
+ assert_nothing_raised do
159
+ @sth = @dbh.prepare('insert into names (name, age) values (?, ?)')
160
+ @sth.execute("'NULL'", 201)
161
+ @sth.execute(nil, 202)
162
+ @sth.execute("NULL", 203)
163
+ @sth.finish
164
+ end
165
+
166
+ assert_nothing_raised do
167
+ @sth = @dbh.prepare('select * from names where age > 200 order by age')
168
+ @sth.execute
169
+ assert_equal(["'NULL'", 201], @sth.fetch)
170
+ assert_equal([nil, 202], @sth.fetch)
171
+ assert_equal(["NULL", 203], @sth.fetch)
172
+ @sth.finish
173
+ end
174
+ end
175
+
176
+ def test_time
177
+ @sth = nil
178
+ t = nil
179
+ assert_nothing_raised do
180
+ @sth = @dbh.prepare("insert into time_test (mytime) values (?)")
181
+ t = Time.now
182
+ @sth.execute(t)
183
+ @sth.finish
184
+ end
185
+
186
+ assert_nothing_raised do
187
+ @sth = @dbh.prepare("select * from time_test")
188
+ @sth.execute
189
+ row = @sth.fetch
190
+ assert_kind_of DateTime, row[0]
191
+ assert_equal t.hour, row[0].hour
192
+ assert_equal t.min, row[0].min
193
+ assert_equal t.sec, row[0].sec
194
+ @sth.finish
195
+ end
196
+ end
197
+
198
+ def test_timestamp
199
+ @sth = nil
200
+ # We omit fractional second testing here -- timestamp precision
201
+ # is a very slippery, dependent on driver and driver version.
202
+ t = DBI::Timestamp.new(2008, 3, 8, 10, 39, 1)
203
+ assert_nothing_raised do
204
+ @sth = @dbh.prepare("insert into timestamp_test (mytimestamp) values (?)")
205
+ @sth.execute(t)
206
+ @sth.finish
207
+ end
208
+
209
+ assert_nothing_raised do
210
+ @sth = @dbh.prepare("select * from timestamp_test")
211
+ @sth.execute
212
+ row = @sth.fetch
213
+ assert_kind_of DateTime, row[0]
214
+ assert_equal t.year, row[0].year
215
+ assert_equal t.month, row[0].month
216
+ assert_equal t.day, row[0].day
217
+ assert_equal t.hour, row[0].hour
218
+ assert_equal t.min, row[0].min
219
+ assert_equal t.sec, row[0].sec
220
+ # omit fractional tests
221
+ @sth.finish
222
+ end
223
+ end
224
+
225
+ def test_boolean_return
226
+ @sth = nil
227
+
228
+ unless dbtype == "odbc" # ODBC has no boolean type
229
+ assert_nothing_raised do
230
+ @sth = @dbh.prepare("insert into boolean_test (num, mybool) values (?, ?)")
231
+ @sth.execute(1, true)
232
+ @sth.execute(2, false)
233
+ @sth.finish
234
+ end
235
+
236
+ assert_nothing_raised do
237
+ @sth = @dbh.prepare("select * from boolean_test order by num")
238
+ @sth.execute
239
+
240
+ pairs = @sth.fetch_all
241
+
242
+ assert_equal(
243
+ [
244
+ [1, true],
245
+ [2, false],
246
+ ], pairs
247
+ )
248
+
249
+ @sth.finish
250
+ end
251
+ end
252
+ end
253
+ end