ydbi 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/ChangeLog +3699 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +25 -0
  6. data/Rakefile +8 -0
  7. data/TODO +44 -0
  8. data/bench/bench.rb +79 -0
  9. data/bin/dbi +518 -0
  10. data/bin/test_broken_dbi +37 -0
  11. data/build/Rakefile.dbi.rb +60 -0
  12. data/build/rake_task_lib.rb +187 -0
  13. data/doc/DBD_SPEC.rdoc +88 -0
  14. data/doc/DBI_SPEC.rdoc +157 -0
  15. data/doc/homepage/contact.html +62 -0
  16. data/doc/homepage/development.html +124 -0
  17. data/doc/homepage/index.html +83 -0
  18. data/doc/homepage/ruby-dbi.css +91 -0
  19. data/examples/test1.pl +39 -0
  20. data/examples/test1.rb +20 -0
  21. data/examples/xmltest.rb +8 -0
  22. data/lib/dbd/Mysql.rb +137 -0
  23. data/lib/dbd/ODBC.rb +89 -0
  24. data/lib/dbd/Pg.rb +188 -0
  25. data/lib/dbd/SQLite.rb +97 -0
  26. data/lib/dbd/SQLite3.rb +124 -0
  27. data/lib/dbd/mysql/database.rb +405 -0
  28. data/lib/dbd/mysql/driver.rb +125 -0
  29. data/lib/dbd/mysql/statement.rb +188 -0
  30. data/lib/dbd/odbc/database.rb +128 -0
  31. data/lib/dbd/odbc/driver.rb +38 -0
  32. data/lib/dbd/odbc/statement.rb +137 -0
  33. data/lib/dbd/pg/database.rb +516 -0
  34. data/lib/dbd/pg/exec.rb +47 -0
  35. data/lib/dbd/pg/statement.rb +160 -0
  36. data/lib/dbd/pg/tuples.rb +121 -0
  37. data/lib/dbd/pg/type.rb +209 -0
  38. data/lib/dbd/sqlite/database.rb +151 -0
  39. data/lib/dbd/sqlite/statement.rb +125 -0
  40. data/lib/dbd/sqlite3/database.rb +201 -0
  41. data/lib/dbd/sqlite3/statement.rb +78 -0
  42. data/lib/dbi.rb +336 -0
  43. data/lib/dbi/base_classes.rb +12 -0
  44. data/lib/dbi/base_classes/database.rb +135 -0
  45. data/lib/dbi/base_classes/driver.rb +47 -0
  46. data/lib/dbi/base_classes/statement.rb +171 -0
  47. data/lib/dbi/binary.rb +25 -0
  48. data/lib/dbi/columninfo.rb +107 -0
  49. data/lib/dbi/exceptions.rb +65 -0
  50. data/lib/dbi/handles.rb +49 -0
  51. data/lib/dbi/handles/database.rb +241 -0
  52. data/lib/dbi/handles/driver.rb +60 -0
  53. data/lib/dbi/handles/statement.rb +408 -0
  54. data/lib/dbi/row.rb +269 -0
  55. data/lib/dbi/sql.rb +22 -0
  56. data/lib/dbi/sql/preparedstatement.rb +115 -0
  57. data/lib/dbi/sql_type_constants.rb +75 -0
  58. data/lib/dbi/trace.rb +91 -0
  59. data/lib/dbi/types.rb +218 -0
  60. data/lib/dbi/typeutil.rb +109 -0
  61. data/lib/dbi/utils.rb +60 -0
  62. data/lib/dbi/utils/date.rb +59 -0
  63. data/lib/dbi/utils/tableformatter.rb +112 -0
  64. data/lib/dbi/utils/time.rb +52 -0
  65. data/lib/dbi/utils/timestamp.rb +96 -0
  66. data/lib/dbi/utils/xmlformatter.rb +73 -0
  67. data/lib/dbi/version.rb +3 -0
  68. data/prototypes/types2.rb +237 -0
  69. data/readme.md +274 -0
  70. data/setup.rb +1585 -0
  71. data/test/DBD_TESTS +50 -0
  72. data/test/TESTING +16 -0
  73. data/test/dbd/general/test_database.rb +206 -0
  74. data/test/dbd/general/test_statement.rb +326 -0
  75. data/test/dbd/general/test_types.rb +296 -0
  76. data/test/dbd/mysql/base.rb +26 -0
  77. data/test/dbd/mysql/down.sql +19 -0
  78. data/test/dbd/mysql/test_blob.rb +18 -0
  79. data/test/dbd/mysql/test_new_methods.rb +7 -0
  80. data/test/dbd/mysql/test_patches.rb +111 -0
  81. data/test/dbd/mysql/up.sql +28 -0
  82. data/test/dbd/odbc/base.rb +30 -0
  83. data/test/dbd/odbc/down.sql +19 -0
  84. data/test/dbd/odbc/test_new_methods.rb +12 -0
  85. data/test/dbd/odbc/test_ping.rb +10 -0
  86. data/test/dbd/odbc/test_statement.rb +44 -0
  87. data/test/dbd/odbc/test_transactions.rb +58 -0
  88. data/test/dbd/odbc/up.sql +33 -0
  89. data/test/dbd/postgresql/base.rb +31 -0
  90. data/test/dbd/postgresql/down.sql +31 -0
  91. data/test/dbd/postgresql/test_arrays.rb +179 -0
  92. data/test/dbd/postgresql/test_async.rb +121 -0
  93. data/test/dbd/postgresql/test_blob.rb +36 -0
  94. data/test/dbd/postgresql/test_bytea.rb +87 -0
  95. data/test/dbd/postgresql/test_ping.rb +10 -0
  96. data/test/dbd/postgresql/test_timestamp.rb +77 -0
  97. data/test/dbd/postgresql/test_transactions.rb +58 -0
  98. data/test/dbd/postgresql/testdbipg.rb +307 -0
  99. data/test/dbd/postgresql/up.sql +60 -0
  100. data/test/dbd/sqlite/base.rb +32 -0
  101. data/test/dbd/sqlite/test_database.rb +30 -0
  102. data/test/dbd/sqlite/test_driver.rb +68 -0
  103. data/test/dbd/sqlite/test_statement.rb +112 -0
  104. data/test/dbd/sqlite/up.sql +25 -0
  105. data/test/dbd/sqlite3/base.rb +32 -0
  106. data/test/dbd/sqlite3/test_database.rb +77 -0
  107. data/test/dbd/sqlite3/test_driver.rb +67 -0
  108. data/test/dbd/sqlite3/test_statement.rb +88 -0
  109. data/test/dbd/sqlite3/up.sql +33 -0
  110. data/test/dbi/tc_columninfo.rb +94 -0
  111. data/test/dbi/tc_date.rb +88 -0
  112. data/test/dbi/tc_dbi.rb +184 -0
  113. data/test/dbi/tc_row.rb +256 -0
  114. data/test/dbi/tc_sqlbind.rb +168 -0
  115. data/test/dbi/tc_statementhandle.rb +29 -0
  116. data/test/dbi/tc_time.rb +77 -0
  117. data/test/dbi/tc_timestamp.rb +142 -0
  118. data/test/dbi/tc_types.rb +268 -0
  119. data/test/ts_dbd.rb +131 -0
  120. data/test/ts_dbi.rb +16 -0
  121. data/ydbi.gemspec +24 -0
  122. metadata +224 -0
@@ -0,0 +1,296 @@
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
+ 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 (?, ?, ?, ?)")
32
+ assert(@sth.convert_types)
33
+ 1.step(5) do |x|
34
+ @sth.execute("poop#{x}", x, x + 0.123, 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
+ 1.step(5) do |x|
43
+ row = @sth.fetch
44
+
45
+ assert_kind_of(Integer, row[0])
46
+ assert_kind_of(BigDecimal, row[1])
47
+ assert_kind_of(BigDecimal, row[2])
48
+
49
+ # FIXME BigDecimal requires a string and some databases will pad
50
+ # decimal/numeric with constrained precision. We should account for
51
+ # this, but I'm not quite sure how yet.
52
+ end
53
+ @sth.finish
54
+ end
55
+
56
+ # FIXME
57
+ # Ideally, this test should be split across the DBI tests and DBD, but for
58
+ # now testing against the DBDs really doesn't cost us anything other than
59
+ # debugging time if something breaks.
60
+ def test_bind_coltype
61
+ # ensure type conv didn't get turned off somewhere.
62
+ assert(DBI.convert_types)
63
+ assert(@dbh.convert_types)
64
+
65
+ assert_nothing_raised do
66
+ @sth = @dbh.prepare("select name, age from names order by age")
67
+ assert(@sth.convert_types) # again
68
+ @sth.execute
69
+ @sth.bind_coltype(2, DBI::Type::Varchar)
70
+ assert_equal(
71
+ [
72
+ ["Joe", "19"],
73
+ ["Bob", "21"],
74
+ ["Jim", "30"],
75
+ ], @sth.fetch_all
76
+ )
77
+ @sth.finish
78
+ end
79
+
80
+ assert_nothing_raised do
81
+ @sth = @dbh.prepare("select age, name from names order by age")
82
+ assert(@sth.convert_types) # again
83
+ @sth.execute
84
+ @sth.bind_coltype(1, DBI::Type::Varchar)
85
+ assert_equal(
86
+ [
87
+ ["19", "Joe"],
88
+ ["21", "Bob"],
89
+ ["30", "Jim"],
90
+ ], @sth.fetch_all
91
+ )
92
+ @sth.finish
93
+ end
94
+
95
+ # just to be sure..
96
+ assert_nothing_raised do
97
+ @sth = @dbh.prepare("select name, age from names order by age")
98
+ @sth.execute
99
+ @sth.bind_coltype(2, DBI::Type::Float)
100
+ @sth.fetch_all.collect { |x| assert_kind_of(Float, x[1]) }
101
+ @sth.finish
102
+ end
103
+
104
+ # now, let's check some failure cases
105
+ @sth = @dbh.prepare("select name, age from names order by age")
106
+
107
+ # can't bind_coltype before execute
108
+ assert_raises(DBI::InterfaceError) { @sth.bind_coltype(1, DBI::Type::Float) }
109
+ # can't index < 1
110
+ assert_raises(DBI::InterfaceError) { @sth.bind_coltype(0, DBI::Type::Float) }
111
+ end
112
+
113
+ def test_noconv
114
+ # XXX this test will fail the whole test suite miserably if it fails at any point.
115
+ assert(DBI.convert_types)
116
+
117
+ DBI.convert_types = false
118
+ @sth.finish rescue nil
119
+ @dbh.disconnect
120
+ set_base_dbh
121
+
122
+ assert(!@dbh.convert_types)
123
+
124
+ assert_nothing_raised do
125
+ @sth = @dbh.prepare("select * from names order by age")
126
+ assert(!@sth.convert_types)
127
+ @sth.execute
128
+ assert_equal(
129
+ [
130
+ ["Joe", "19"],
131
+ ["Bob", "21"],
132
+ ["Jim", "30"],
133
+ ], @sth.fetch_all
134
+ )
135
+ @sth.finish
136
+ end
137
+
138
+ DBI.convert_types = true
139
+ @sth.finish rescue nil
140
+ @dbh.disconnect
141
+ set_base_dbh
142
+
143
+ assert(DBI.convert_types)
144
+ assert(@dbh.convert_types)
145
+
146
+ assert_nothing_raised do
147
+ @sth = @dbh.prepare("select * from names order by age")
148
+ assert(@sth.convert_types)
149
+ @sth.execute
150
+ assert_equal(
151
+ [
152
+ ["Joe", 19],
153
+ ["Bob", 21],
154
+ ["Jim", 30],
155
+ ], @sth.fetch_all
156
+ )
157
+ @sth.finish
158
+ end
159
+
160
+ @dbh.convert_types = false
161
+
162
+ assert_nothing_raised do
163
+ @sth = @dbh.prepare("select * from names order by age")
164
+ assert(!@sth.convert_types)
165
+ @sth.execute
166
+ assert_equal(
167
+ [
168
+ ["Joe", "19"],
169
+ ["Bob", "21"],
170
+ ["Jim", "30"],
171
+ ], @sth.fetch_all
172
+ )
173
+ @sth.finish
174
+ end
175
+
176
+ @dbh.convert_types = true
177
+
178
+ assert_nothing_raised do
179
+ @sth = @dbh.prepare("select * from names order by age")
180
+ assert(@sth.convert_types)
181
+ @sth.convert_types = false
182
+ @sth.execute
183
+ assert_equal(
184
+ [
185
+ ["Joe", "19"],
186
+ ["Bob", "21"],
187
+ ["Jim", "30"],
188
+ ], @sth.fetch_all
189
+ )
190
+ @sth.finish
191
+ end
192
+ rescue Exception => e
193
+ DBI.convert_types = true
194
+ @sth.finish
195
+ @dbh.disconnect
196
+ set_base_dbh
197
+ raise e
198
+ end
199
+
200
+ def test_null
201
+ assert_nothing_raised do
202
+ @sth = @dbh.prepare('insert into names (name, age) values (?, ?)')
203
+ @sth.execute("'NULL'", 201)
204
+ @sth.execute(nil, 202)
205
+ @sth.execute("NULL", 203)
206
+ @sth.finish
207
+ end
208
+
209
+ assert_nothing_raised do
210
+ @sth = @dbh.prepare('select * from names where age > 200 order by age')
211
+ @sth.execute
212
+ assert_equal(["'NULL'", 201], @sth.fetch)
213
+ assert_equal([nil, 202], @sth.fetch)
214
+ assert_equal(["NULL", 203], @sth.fetch)
215
+ @sth.finish
216
+ end
217
+ end
218
+
219
+ def test_time
220
+ @sth = nil
221
+ t = nil
222
+ assert_nothing_raised do
223
+ @sth = @dbh.prepare("insert into time_test (mytime) values (?)")
224
+ t = Time.now
225
+ @sth.execute(t)
226
+ @sth.finish
227
+ end
228
+
229
+ assert_nothing_raised do
230
+ @sth = @dbh.prepare("select * from time_test")
231
+ @sth.execute
232
+ row = @sth.fetch
233
+ assert_kind_of DateTime, row[0]
234
+ assert_equal t.hour, row[0].hour
235
+ assert_equal t.min, row[0].min
236
+ assert_equal t.sec, row[0].sec
237
+ @sth.finish
238
+ end
239
+ end
240
+
241
+ def test_timestamp
242
+ @sth = nil
243
+ # We omit fractional second testing here -- timestamp precision
244
+ # is a very slippery, dependent on driver and driver version.
245
+ t = DBI::Timestamp.new(2008, 3, 8, 10, 39, 1)
246
+ assert_nothing_raised do
247
+ @sth = @dbh.prepare("insert into timestamp_test (mytimestamp) values (?)")
248
+ @sth.execute(t)
249
+ @sth.finish
250
+ end
251
+
252
+ assert_nothing_raised do
253
+ @sth = @dbh.prepare("select * from timestamp_test")
254
+ @sth.execute
255
+ row = @sth.fetch
256
+ assert_kind_of DateTime, row[0]
257
+ assert_equal t.year, row[0].year
258
+ assert_equal t.month, row[0].month
259
+ assert_equal t.day, row[0].day
260
+ assert_equal t.hour, row[0].hour
261
+ assert_equal t.min, row[0].min
262
+ assert_equal t.sec, row[0].sec
263
+ # omit fractional tests
264
+ @sth.finish
265
+ end
266
+ end
267
+
268
+ def test_boolean_return
269
+ @sth = nil
270
+
271
+ unless dbtype == "odbc" # ODBC has no boolean type
272
+ assert_nothing_raised do
273
+ @sth = @dbh.prepare("insert into boolean_test (num, mybool) values (?, ?)")
274
+ @sth.execute(1, true)
275
+ @sth.execute(2, false)
276
+ @sth.finish
277
+ end
278
+
279
+ assert_nothing_raised do
280
+ @sth = @dbh.prepare("select * from boolean_test order by num")
281
+ @sth.execute
282
+
283
+ pairs = @sth.fetch_all
284
+
285
+ assert_equal(
286
+ [
287
+ [1, true],
288
+ [2, false],
289
+ ], pairs
290
+ )
291
+
292
+ @sth.finish
293
+ end
294
+ end
295
+ end
296
+ end
@@ -0,0 +1,26 @@
1
+ DBDConfig.set_testbase(:mysql, Class.new(Test::Unit::TestCase) do
2
+ def dbtype
3
+ "mysql"
4
+ end
5
+
6
+ def test_base
7
+ assert_equal(@dbh.driver_name, "Mysql")
8
+ assert_kind_of(DBI::DBD::Mysql::Database, @dbh.instance_variable_get(:@handle))
9
+ end
10
+
11
+ def set_base_dbh
12
+ config = DBDConfig.get_config["mysql"]
13
+ @dbh = DBI.connect("dbi:Mysql:"+config["dbname"], config["username"], config["password"], { })
14
+ end
15
+
16
+ def setup
17
+ set_base_dbh
18
+ DBDConfig.inject_sql(@dbh, dbtype, "dbd/mysql/up.sql")
19
+ end
20
+
21
+ def teardown
22
+ DBDConfig.inject_sql(@dbh, dbtype, "dbd/mysql/down.sql")
23
+ @dbh.disconnect
24
+ end
25
+ end
26
+ )
@@ -0,0 +1,19 @@
1
+ drop view view_names;
2
+ ---
3
+ drop table names;
4
+ ---
5
+ drop table blob_test;
6
+ ---
7
+ drop table boolean_test;
8
+ ---
9
+ drop table time_test;
10
+ ---
11
+ drop table timestamp_test;
12
+ ---
13
+ drop table bit_test;
14
+ ---
15
+ drop table field_types_test;
16
+ ---
17
+ drop table db_specific_types_test;
18
+ ---
19
+ drop table precision_test;
@@ -0,0 +1,18 @@
1
+ class TestMySQLBlob < DBDConfig.testbase(:mysql)
2
+ def test_blob_round_trip
3
+ data =(0..255).collect{|n| n.chr}.join("")
4
+ sql = "INSERT INTO blob_test (name, data) VALUES (?, ?)"
5
+
6
+ @dbh.do(sql, 'test1', DBI::Binary.new(data))
7
+ @dbh.do(sql, 'test2', data)
8
+
9
+ @dbh.prepare(sql) do |sth|
10
+ sth.execute('test3', DBI::Binary.new(data))
11
+ sth.execute('test4', data)
12
+ end
13
+
14
+ @dbh.select_all("SELECT name, data FROM blob_test") do |name, fetch_data|
15
+ assert_equal fetch_data, data
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ class TestNewMethods < DBDConfig.testbase(:mysql)
2
+ def test_database_name
3
+ assert_nothing_raised do
4
+ assert_equal DBDConfig.get_config[dbtype]['dbname'], @dbh.database_name
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,111 @@
1
+ class TestMysqlPatches < DBDConfig.testbase(:mysql)
2
+ def test_exception_on_aggregate
3
+ assert_nothing_raised do
4
+ sth = @dbh.prepare("select sum(age) from names")
5
+ sth.execute
6
+ row = sth.fetch
7
+ assert_equal(70.0, row[0])
8
+ sth.finish
9
+
10
+ sth = @dbh.prepare("select count(*) from names")
11
+ sth.execute
12
+ assert_equal([3], sth.fetch)
13
+ sth.finish
14
+ end
15
+ end
16
+
17
+ def test_timestamps
18
+ timestamp = "04-06-1978 06:00:00"
19
+ datestamp = "04-06-1978"
20
+ date = Date.strptime(datestamp, "%m-%d-%Y")
21
+ stamp = DateTime.strptime(timestamp, "%m-%d-%Y %H:%M:%S")
22
+ assert_nothing_raised do
23
+ @sth = @dbh.prepare("insert into db_specific_types_test (ts) values (?)")
24
+ @sth.execute(stamp)
25
+ @sth.finish
26
+ end
27
+
28
+ assert_nothing_raised do
29
+ @sth = @dbh.prepare("select ts from db_specific_types_test where ts is not null")
30
+ @sth.execute
31
+
32
+ newstamp = @sth.fetch[0]
33
+
34
+ assert_equal(newstamp, stamp)
35
+ assert_equal(newstamp.strftime("%m-%d-%Y %H:%M:%S"), timestamp)
36
+ @sth.finish
37
+ end
38
+
39
+ assert_nothing_raised do
40
+ @sth = @dbh.prepare("insert into db_specific_types_test (dt) values (?)")
41
+ @sth.execute(date)
42
+ @sth.finish
43
+ end
44
+
45
+ assert_nothing_raised do
46
+ @sth = @dbh.prepare("select dt from db_specific_types_test where dt is not null")
47
+ @sth.execute
48
+
49
+ newdate = @sth.fetch[0]
50
+
51
+ assert_equal(newdate, date)
52
+ assert_equal(newdate.strftime("%m-%d-%Y"), datestamp)
53
+ @sth.finish
54
+ end
55
+ end
56
+
57
+ # FIXME when the spec is more solid, this should be in the general tests
58
+ def test_columns
59
+ assert_nothing_raised do
60
+ assert_equal [
61
+ {
62
+ :name =>"foo",
63
+ :default =>"1",
64
+ :primary =>true,
65
+ :scale =>nil,
66
+ :sql_type =>4,
67
+ :nullable =>false,
68
+ :indexed =>true,
69
+ :precision =>11,
70
+ :type_name =>"int",
71
+ :unique =>true
72
+ }
73
+ ], @dbh.columns("field_types_test")
74
+ end
75
+
76
+ assert_nothing_raised do
77
+ sth = @dbh.prepare("insert into field_types_test (foo) values (?)")
78
+ sth.execute(2)
79
+ sth.finish
80
+ end
81
+
82
+ assert_nothing_raised do
83
+ sth = @dbh.prepare("select * from field_types_test")
84
+ sth.execute
85
+ row = sth.fetch
86
+ columns = sth.column_info
87
+ sth.finish
88
+
89
+ assert_equal [2], row
90
+ assert_equal [
91
+ {
92
+ :dbi_type => DBI::Type::Integer,
93
+ :name =>"foo",
94
+ :mysql_type_name =>"INT",
95
+ :mysql_max_length =>1,
96
+ :primary =>true,
97
+ :scale =>0,
98
+ :mysql_flags =>49155,
99
+ :sql_type =>4,
100
+ :nullable =>false,
101
+ :mysql_type =>3,
102
+ :indexed =>true,
103
+ :mysql_length =>11,
104
+ :precision =>11,
105
+ :type_name =>"INTEGER",
106
+ :unique =>true
107
+ }
108
+ ], columns
109
+ end
110
+ end
111
+ end