ydbi 0.5.0 → 0.5.1

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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +4 -0
  3. data/build/Rakefile.dbi.rb +4 -4
  4. data/lib/dbi/version.rb +1 -1
  5. data/test/dbi/tc_dbi.rb +1 -1
  6. metadata +9 -124
  7. data/.gitignore +0 -6
  8. data/Gemfile +0 -4
  9. data/Rakefile +0 -8
  10. data/TODO +0 -44
  11. data/bench/bench.rb +0 -79
  12. data/build/rake_task_lib.rb +0 -187
  13. data/doc/DBD_SPEC.rdoc +0 -88
  14. data/doc/DBI_SPEC.rdoc +0 -157
  15. data/doc/homepage/contact.html +0 -62
  16. data/doc/homepage/development.html +0 -124
  17. data/doc/homepage/index.html +0 -83
  18. data/doc/homepage/ruby-dbi.css +0 -91
  19. data/lib/dbd/Mysql.rb +0 -137
  20. data/lib/dbd/ODBC.rb +0 -89
  21. data/lib/dbd/Pg.rb +0 -188
  22. data/lib/dbd/SQLite.rb +0 -97
  23. data/lib/dbd/SQLite3.rb +0 -124
  24. data/lib/dbd/mysql/database.rb +0 -405
  25. data/lib/dbd/mysql/driver.rb +0 -125
  26. data/lib/dbd/mysql/statement.rb +0 -188
  27. data/lib/dbd/odbc/database.rb +0 -128
  28. data/lib/dbd/odbc/driver.rb +0 -38
  29. data/lib/dbd/odbc/statement.rb +0 -137
  30. data/lib/dbd/pg/database.rb +0 -516
  31. data/lib/dbd/pg/exec.rb +0 -47
  32. data/lib/dbd/pg/statement.rb +0 -160
  33. data/lib/dbd/pg/tuples.rb +0 -121
  34. data/lib/dbd/pg/type.rb +0 -209
  35. data/lib/dbd/sqlite/database.rb +0 -151
  36. data/lib/dbd/sqlite/statement.rb +0 -125
  37. data/lib/dbd/sqlite3/database.rb +0 -201
  38. data/lib/dbd/sqlite3/statement.rb +0 -78
  39. data/prototypes/types2.rb +0 -237
  40. data/setup.rb +0 -1585
  41. data/test/DBD_TESTS +0 -50
  42. data/test/TESTING +0 -16
  43. data/test/dbd/general/test_database.rb +0 -206
  44. data/test/dbd/general/test_statement.rb +0 -326
  45. data/test/dbd/general/test_types.rb +0 -296
  46. data/test/dbd/mysql/base.rb +0 -26
  47. data/test/dbd/mysql/down.sql +0 -19
  48. data/test/dbd/mysql/test_blob.rb +0 -18
  49. data/test/dbd/mysql/test_new_methods.rb +0 -7
  50. data/test/dbd/mysql/test_patches.rb +0 -111
  51. data/test/dbd/mysql/up.sql +0 -28
  52. data/test/dbd/odbc/base.rb +0 -30
  53. data/test/dbd/odbc/down.sql +0 -19
  54. data/test/dbd/odbc/test_new_methods.rb +0 -12
  55. data/test/dbd/odbc/test_ping.rb +0 -10
  56. data/test/dbd/odbc/test_statement.rb +0 -44
  57. data/test/dbd/odbc/test_transactions.rb +0 -58
  58. data/test/dbd/odbc/up.sql +0 -33
  59. data/test/dbd/postgresql/base.rb +0 -31
  60. data/test/dbd/postgresql/down.sql +0 -31
  61. data/test/dbd/postgresql/test_arrays.rb +0 -179
  62. data/test/dbd/postgresql/test_async.rb +0 -121
  63. data/test/dbd/postgresql/test_blob.rb +0 -36
  64. data/test/dbd/postgresql/test_bytea.rb +0 -87
  65. data/test/dbd/postgresql/test_ping.rb +0 -10
  66. data/test/dbd/postgresql/test_timestamp.rb +0 -77
  67. data/test/dbd/postgresql/test_transactions.rb +0 -58
  68. data/test/dbd/postgresql/testdbipg.rb +0 -307
  69. data/test/dbd/postgresql/up.sql +0 -60
  70. data/test/dbd/sqlite/base.rb +0 -32
  71. data/test/dbd/sqlite/test_database.rb +0 -30
  72. data/test/dbd/sqlite/test_driver.rb +0 -68
  73. data/test/dbd/sqlite/test_statement.rb +0 -112
  74. data/test/dbd/sqlite/up.sql +0 -25
  75. data/test/dbd/sqlite3/base.rb +0 -32
  76. data/test/dbd/sqlite3/test_database.rb +0 -77
  77. data/test/dbd/sqlite3/test_driver.rb +0 -67
  78. data/test/dbd/sqlite3/test_statement.rb +0 -88
  79. data/test/dbd/sqlite3/up.sql +0 -33
  80. data/test/ts_dbd.rb +0 -131
  81. data/ydbi.gemspec +0 -24
@@ -1,125 +0,0 @@
1
- #
2
- # See DBI::BaseStatement.
3
- #
4
- class DBI::DBD::SQLite::Statement < DBI::BaseStatement
5
- DBI_TYPE_MAP = [
6
- [ /^INT(EGER)?$/i, DBI::SQL_INTEGER ],
7
- [ /^(OID|ROWID|_ROWID_)$/i, DBI::SQL_OTHER ],
8
- [ /^FLOAT$/i, DBI::SQL_FLOAT ],
9
- [ /^REAL$/i, DBI::SQL_REAL ],
10
- [ /^DOUBLE$/i, DBI::SQL_DOUBLE ],
11
- [ /^DECIMAL/i, DBI::SQL_DECIMAL ],
12
- [ /^(BOOL|BOOLEAN)$/i, DBI::SQL_BOOLEAN ],
13
- [ /^TIME$/i, DBI::SQL_TIME ],
14
- [ /^DATE$/i, DBI::SQL_DATE ],
15
- [ /^TIMESTAMP$/i, DBI::SQL_TIMESTAMP ],
16
- [ /^(VARCHAR|TEXT)/i, DBI::SQL_VARCHAR ],
17
- [ /^CHAR$/i, DBI::SQL_CHAR ],
18
- ]
19
-
20
- def initialize(stmt, dbh)
21
- @dbh = dbh
22
- @statement = DBI::SQL::PreparedStatement.new(@dbh, stmt)
23
- @attr = { }
24
- @params = [ ]
25
- @rows = [ ]
26
- @result_set = nil
27
- @dbh.open_handles += 1
28
- end
29
-
30
- #
31
- # See DBI::BaseStatement#bind_param. This method will also raise
32
- # DBI::InterfaceError if +param+ is not a Fixnum, to prevent incorrect
33
- # binding.
34
- #
35
- def bind_param(param, value, attributes=nil)
36
- unless param.kind_of? Fixnum
37
- raise DBI::InterfaceError, "Only numeric parameters are supported"
38
- end
39
-
40
- @params[param-1] = value
41
-
42
- # FIXME what to do with attributes? are they important in SQLite?
43
- end
44
-
45
- #
46
- # See DBI::BaseStatement#execute.
47
- #
48
- # In the event AutoCommit is off and no transaction is currently executing,
49
- # one will be opened at this point. It is your responsibility to #finish,
50
- # #cancel, #rollback, or #commit.
51
- #
52
- def execute
53
- sql = @statement.bind(@params)
54
- # XXX sqlite re-escapes this for us automatically, it's causing trouble with everything else.
55
- # this will probably break in a horrible manner and I will be forced to "fix" it again.
56
- sql.gsub!(/\\\\/) { '\\' }
57
- DBI::DBD::SQLite.check_sql(sql)
58
-
59
- begin
60
- unless @dbh.db.transaction_active?
61
- @dbh.db.transaction
62
- end
63
- @result_set = @dbh.db.query(sql)
64
- @dbh.commit if @dbh["AutoCommit"]
65
- rescue Exception => e
66
- raise DBI::DatabaseError, e.message
67
- end
68
- end
69
-
70
- alias :finish :cancel
71
-
72
- def finish
73
- # nil out the result set
74
- @result_set.close if @result_set
75
- @result_set = nil
76
- @rows = nil
77
- @dbh.open_handles -= 1
78
- end
79
-
80
- def fetch
81
- return nil if @result_set.eof?
82
-
83
- row = @result_set.next
84
- return nil unless row
85
-
86
- return row
87
- end
88
-
89
- def column_info
90
- columns = [ ]
91
-
92
- # FIXME this shit should *really* be abstracted into DBI
93
- # FIXME this still doesn't handle nullable/unique/default stuff.
94
- @result_set.columns.each_with_index do |name, i|
95
- columns[i] = { } unless columns[i]
96
- columns[i]["name"] = name
97
- type_name = @result_set.types[i]
98
-
99
- if type_name
100
- m = DBI::DBD::SQLite.parse_type(type_name)
101
-
102
- columns[i]["type_name"] = m[1]
103
- columns[i]["precision"] = m[3].to_i if m[3]
104
- columns[i]["scale"] = m[5].to_i if m[5]
105
- DBI_TYPE_MAP.each do |map|
106
- if columns[i]["type_name"] =~ map[0]
107
- columns[i]["sql_type"] = map[1]
108
- break
109
- end
110
- end
111
-
112
- case columns[i]["type_name"]
113
- when 'double'
114
- columns[i]["dbi_type"] = DBI::Type::Float
115
- end
116
- end
117
- end
118
-
119
- return columns
120
- end
121
-
122
- def rows
123
- return @dbh.db.changes
124
- end
125
- end
@@ -1,201 +0,0 @@
1
- #
2
- # See DBI::BaseDatabase.
3
- #
4
- class DBI::DBD::SQLite3::Database < DBI::BaseDatabase
5
- #
6
- # Constructor. Valid attributes:
7
- #
8
- # * AutoCommit: Commit after every statement execution.
9
- #
10
- # The following attributes go directly to the low-level SQLite3 driver.
11
- # Please consult it's documentation for more information.
12
- #
13
- # * auto_vacuum
14
- # * cache_size
15
- # * default_cache_size
16
- # * default_synchronous
17
- # * default_temp_store
18
- # * full_column_names
19
- # * synchronous
20
- # * temp_store
21
- # * type_translation
22
- #
23
- def initialize(dbname, attr)
24
- @db = ::SQLite3::Database.new(dbname)
25
-
26
- @db.type_translation = false
27
-
28
- @attr = {'AutoCommit' => true}
29
- if attr then
30
- attr.each_pair do |key, value|
31
- begin
32
- self[key] = value
33
- rescue DBI::NotSupportedError
34
- end
35
- end
36
- end
37
- __generate_attr__
38
- end
39
-
40
- def disconnect()
41
- @db.rollback if @db.transaction_active?
42
- @db.close
43
- end
44
-
45
- def prepare(statement)
46
- DBI::DBD::SQLite3::Statement.new(statement, @db)
47
- end
48
-
49
- def database_name
50
- st = DBI::DBD::SQLite3::Statement.new('PRAGMA database_list', @db)
51
- st.execute
52
- row = st.fetch
53
- st.finish
54
-
55
- return row[2]
56
- end
57
-
58
- def ping()
59
- not @db.closed?
60
- end
61
-
62
- def commit()
63
- if @db.transaction_active?
64
- @db.commit
65
- @db.transaction
66
- else
67
- raise DBI::ProgrammingError.new("No active transaction.")
68
- end
69
- end
70
-
71
- #
72
- # See DBI::BaseDatabase#rollback.
73
- #
74
- # If all statements were not closed before the rollback occurs, a
75
- # DBI::Warning may be raised if the database encounters an error because of
76
- # it.
77
- #
78
- # This method will also raise DBI::ProgrammingError if not in a
79
- # transaction.
80
- #
81
- def rollback()
82
- if @db.transaction_active?
83
- begin
84
- @db.rollback
85
- @db.transaction
86
- rescue Exception => e
87
- raise DBI::Warning, "Statements were not closed prior to rollback"
88
- end
89
- else
90
- raise DBI::ProgrammingError.new("No active transaction.")
91
- end
92
- end
93
-
94
- def tables()
95
- ret = []
96
- result = @db.execute(%q(
97
- SELECT name FROM sqlite_master WHERE type IN ('table', 'view')
98
- UNION ALL
99
- SELECT name FROM sqlite_temp_master WHERE type in ('table', 'view') ORDER BY 1
100
- ))
101
- result.each{|row| ret.push(row[0])}
102
- ret
103
- end
104
-
105
- #
106
- # See DBI::BaseDatabase#columns.
107
- #
108
- # Additional Attributes:
109
- #
110
- # * sql_type: XOPEN integer SQL Type.
111
- # * nullable: true if NULL is allowed in this column.
112
- # * default: the value that will be used in new rows if this column
113
- # receives no data.
114
- #
115
- def columns(table)
116
- @db.type_translation = false
117
- ret =
118
- @db.table_info(table).map do |hash|
119
- m = DBI::DBD::SQLite3.parse_type(hash['type'])
120
- h = {
121
- 'name' => hash['name'],
122
- 'type_name' => m[1],
123
- 'sql_type' =>
124
- begin
125
- DBI.const_get('SQL_'+hash['type'].upcase)
126
- rescue NameError
127
- DBI::SQL_OTHER
128
- end,
129
- 'nullable' => (hash['notnull'] == '0'),
130
- 'default' => (@attr['type_translation'] && (not hash['dflt_value'])) ?
131
- @db.translator.translate(hash['type'], hash['dflt_value']) :
132
- hash['dflt_value']
133
- }
134
-
135
- h['precision'] = m[3].to_i if m[3]
136
- h['scale'] = m[5].to_i if m[5]
137
-
138
- h
139
- end
140
- @db.type_translation = @attr['type_translation']
141
- ret
142
- end
143
-
144
- def quote(value)
145
- ::SQLite3::Database.quote(value.to_s)
146
- end
147
-
148
- #
149
- # This method is used to aid the constructor and probably should not be
150
- # used independently.
151
- #
152
- def __generate_attr__()
153
- tt = @db.type_translation
154
- @db.type_translation = false
155
- [ 'auto_vacuum', 'cache_size', 'default_cache_size',
156
- 'default_synchronous', 'default_temp_store', 'full_column_names',
157
- 'synchronous', 'temp_store', 'type_translation' ].each do |key|
158
- unless @attr.has_key?(key) then
159
- @attr[key] = @db.__send__(key)
160
- end
161
- end
162
- @db.type_translation = tt
163
- end
164
-
165
- #
166
- # See #new for valid attributes.
167
- #
168
- # If Autocommit is set to true, commit happens immediately if a transaction
169
- # is open.
170
- #
171
- def []=(attr, value)
172
- case attr
173
- when 'AutoCommit'
174
- if value
175
- @db.commit if @db.transaction_active?
176
- else
177
- @db.transaction unless @db.transaction_active?
178
- end
179
- @attr[attr] = value
180
- when 'auto_vacuum', 'cache_size', 'count_changes',
181
- 'default_cache_size', 'encoding', 'full_column_names',
182
- 'page_size', 'short_column_names', 'synchronous',
183
- 'temp_store', 'temp_store_directory'
184
- @db.__send__((attr+'='), value)
185
- @attr[attr] = @db.__send__(attr)
186
- when 'busy_timeout'
187
- @db.busy_timeout(value)
188
- @attr[attr] = value
189
- when 'busy_handler'
190
- @db.busy_timeout(&value)
191
- @attr[attr] = value
192
- when 'type_translation'
193
- @db.type_translation = value
194
- @attr[attr] = value
195
- else
196
- raise DBI::NotSupportedError
197
- end
198
-
199
- return value
200
- end
201
- end
@@ -1,78 +0,0 @@
1
- #
2
- # See DBI::BaseStatement.
3
- #
4
- class DBI::DBD::SQLite3::Statement < DBI::BaseStatement
5
- def initialize(sql, db)
6
- sql.gsub!(/\\\\/) { '\\' } # sqlite underneath does this for us automatically, and it's causing trouble with the rest of the system.
7
- @sql = sql
8
- @db = db
9
- @stmt = db.prepare(sql)
10
- @result = nil
11
- rescue ::SQLite3::Exception, RuntimeError => err
12
- raise DBI::ProgrammingError.new(err.message)
13
- end
14
-
15
- #
16
- # See DBI::BaseStatement#bind_param. This method will also raise
17
- # DBI::InterfaceError if +param+ is not a Fixnum, to prevent incorrect
18
- # binding.
19
- #
20
- def bind_param(param, value, attribs=nil)
21
- raise DBI::InterfaceError, "Bound parameter must be an integer" unless param.kind_of? Fixnum
22
- @stmt.bind_param(param, value)
23
- end
24
-
25
- def execute()
26
- @result = @stmt.execute
27
- @rows = DBI::SQL.query?(@sql) ? 0 : @db.changes
28
- end
29
-
30
- def finish()
31
- @stmt.close rescue nil
32
- @result = nil
33
- end
34
-
35
- def fetch()
36
- ret = @result.next
37
- return ret unless ret
38
- [ret].flatten
39
- end
40
-
41
- def column_info()
42
- @stmt.columns.zip(@stmt.types).map{|name, type_name|
43
- m = DBI::DBD::SQLite3.parse_type(type_name)
44
- h = {
45
- 'name' => name,
46
- 'type_name' => m[1],
47
- 'sql_type' =>
48
- begin
49
- DBI.const_get('SQL_'+m[1].upcase)
50
- rescue NameError
51
- DBI::SQL_OTHER
52
- end,
53
- }
54
- h['precision'] = m[3].to_i if m[3]
55
- h['scale'] = m[5].to_i if m[5]
56
-
57
- case h['type_name']
58
- when 'double'
59
- h['dbi_type'] = DBI::Type::Float
60
- end
61
-
62
- h
63
- }
64
- end
65
-
66
- def rows()
67
- @rows
68
- end
69
-
70
- def bind_params(*bindvars)
71
- @stmt.bind_params(bindvars)
72
- end
73
-
74
- def cancel()
75
- @result = nil
76
- @index = 0
77
- end
78
- end
data/prototypes/types2.rb DELETED
@@ -1,237 +0,0 @@
1
- require 'date'
2
- require 'time'
3
-
4
- #
5
- # General example, these would be types that would exist in DBI proper
6
- #
7
-
8
- module DBI
9
- class DBI::Type
10
- def self.parse(obj, type=nil, dbh=nil)
11
- if type
12
- sym = ( "to_" + type.to_s ).to_sym
13
- begin
14
- return self.__send__(sym, obj)
15
- rescue ::NoMethodError
16
- self.to_type(obj)
17
- end
18
- else
19
- return self.to_type(obj)
20
- end
21
- end
22
-
23
- def self.coerce(obj, type=nil, dbh=nil)
24
- if type
25
- sym = ( "from_" + type.to_s ).to_sym
26
- begin
27
- return self.__send__(sym, obj)
28
- rescue ::NoMethodError
29
- self.from_type(obj)
30
- end
31
- else
32
- return self.from_type(obj)
33
- end
34
- end
35
-
36
- def self.from_type(obj)
37
- obj.to_s rescue obj.to_str rescue obj
38
- end
39
-
40
- def self.to_type(obj)
41
- obj
42
- end
43
- end
44
-
45
- class DBI::Type::Null < DBI::Type
46
- def self.to_type(obj)
47
- return obj unless obj
48
- return nil if obj.to_s.match(/^null$/i)
49
- return obj
50
- end
51
-
52
- def self.from_type(obj)
53
- obj
54
- end
55
- end
56
-
57
- class DBI::Type::Integer < DBI::Type::Null
58
- def self.parse(obj)
59
- obj = super
60
- return obj unless obj
61
- return obj.to_i if obj.respond_to? :to_i
62
- return obj
63
- end
64
- end
65
-
66
- class DBI::Type::Timestamp < DBI::Type::Null
67
- def self.to_type(obj)
68
- obj = super
69
- return obj unless obj
70
-
71
- case obj
72
- when ::DateTime
73
- return obj
74
- when ::Date
75
- return ::DateTime.strptime(obj.to_s, "%Y-%m-%d")
76
- when ::Time
77
- return ::DateTime.parse(obj.to_s)
78
- when ::Integer
79
- return ::DateTime.parse(::Time.at(obj).to_s)
80
- else
81
- return ::DateTime.parse(obj.to_s) if obj.respond_to? :to_s
82
- return ::DateTime.parse(obj.to_str) if obj.respond_to? :to_str
83
- return obj
84
- end
85
- end
86
-
87
- def self.from_type(obj)
88
- obj = super
89
- return obj unless obj
90
-
91
- case obj
92
- when ::DateTime
93
- return obj.to_s # produces ISO8601
94
- when ::Time
95
- return obj.iso8601
96
- when ::Integer
97
- return ::Time.at(obj).iso8601
98
- else
99
- return obj
100
- end
101
- end
102
- end
103
- end
104
-
105
- module DBI::DBD
106
- class Pg
107
-
108
- #
109
- # during connect time, after DatabaseHandle initialization, the hash
110
- # that DatabaseHandle#type_map provides would be tweaked to take
111
- # advantage of the available date formats.
112
- #
113
- # See 'PgDatabaseHandle' below for a mock.
114
- #
115
-
116
- class Type
117
- class Timestamp < DBI::Type::Timestamp
118
- def self.from_dmy(obj)
119
- return obj if DBI::Type::Null.parse(obj).nil?
120
-
121
- case obj
122
- when ::DateTime, ::Time
123
- obj.strftime("%d/%m/%Y %H:%M:%S")
124
- when ::Integer
125
- ::Time.at(obj).strftime("%d/%m/%Y %H:%M:%S")
126
- else
127
- # punt... this will actually try the baseline
128
- # conversion at this point
129
- raise "Crap!"
130
- end
131
- end
132
-
133
- def self.to_dmy(obj)
134
- return obj if DBI::Type::Null.parse(obj).nil?
135
-
136
- # realistically all there needs to be is a check for the
137
- # type ruby-pg typically returns and string, but to be
138
- # complete I'm showing how it could be done if the type was
139
- # less clear.
140
-
141
- case obj
142
- when ::DateTime
143
- return obj
144
- when ::Time
145
- return ::DateTime.parse(obj.to_s)
146
- else
147
- return ::DateTime.strptime(obj, "%d/%m/%Y %H:%M:%S")
148
- end
149
- end
150
- end
151
- end
152
- end
153
- end
154
-
155
- #
156
- # this is just used to emulate the methods a DatabaseHandle would have to
157
- # faciliate this.. certainly not a full (or correct) mirroring of the DBI API.
158
- #
159
- class DatabaseHandle
160
-
161
- attr_accessor :columns
162
-
163
- def outbound_type_map
164
- {
165
- 'timestamp' => [DBI::Type::Timestamp]
166
- }
167
- end
168
-
169
- def inbound_type_map
170
- {
171
- ::DateTime => [DBI::Type::Timestamp],
172
- ::Time => [DBI::Type::Timestamp]
173
- }
174
- end
175
-
176
- # humor me while I completely break DBI for the sake of brevity..
177
- def execute(*bindvars)
178
- bindvars.collect do |var|
179
- type_info = inbound_type_map[var.class]
180
- type_info[0].coerce(var, type_info[1], self)
181
- end
182
- end
183
-
184
- def fetch(*bindvars)
185
- ret = []
186
-
187
- bindvars.each_with_index do |var, i|
188
- type_info = outbound_type_map[columns[i]]
189
- ret.push type_info[0].parse(var, type_info[1], self)
190
- end
191
-
192
- return ret
193
- end
194
- end
195
-
196
- class PgDatabaseHandle < DatabaseHandle
197
- def outbound_type_map
198
- {
199
- 'timestamp' => [DBI::DBD::Pg::Type::Timestamp, :dmy]
200
- }
201
- end
202
-
203
- def inbound_type_map
204
- {
205
- ::DateTime => [DBI::DBD::Pg::Type::Timestamp, :dmy],
206
- ::Time => [DBI::DBD::Pg::Type::Timestamp, :dmy]
207
- }
208
- end
209
- end
210
-
211
- # ok! now for the functional example:
212
-
213
- if __FILE__ == $0
214
-
215
- dbh = DatabaseHandle.new
216
- dbh.columns = %w(timestamp timestamp)
217
- # this would go TO the database..
218
- p dbh.execute(DateTime.now, Time.now)
219
- # this would come FROM the database...
220
- p dbh.fetch(Time.now.iso8601, DateTime.now.to_s)
221
-
222
- # now the Pg example:
223
- dbh = PgDatabaseHandle.new
224
- dbh.columns = %w(timestamp timestamp)
225
-
226
- # this would go TO the database..
227
- p dbh.execute(DateTime.now, Time.now)
228
- # this would come FROM the database...
229
- p dbh.fetch(Time.now.strftime("%d/%m/%Y %H:%M:%S"), DateTime.now.strftime("%d/%m/%Y %H:%M:%S"))
230
-
231
- # this should fail appropriately
232
- begin
233
- dbh.fetch(Time.now.iso8601, DateTime.now.to_s)
234
- rescue Exception
235
- puts "this failed like it should"
236
- end
237
- end