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.
- checksums.yaml +4 -4
- data/.envrc +3 -0
- data/.github/workflows/ruby.yml +65 -0
- data/.gitignore +19 -0
- data/ChangeLog +8 -0
- data/Gemfile +5 -0
- data/Rakefile +14 -0
- data/TODO +44 -0
- data/bench/bench.rb +79 -0
- data/build/rake_task_lib.rb +186 -0
- data/devenv.lock +228 -0
- data/devenv.nix +55 -0
- data/devenv.yaml +8 -0
- data/doc/DBD_SPEC.rdoc +88 -0
- data/doc/DBI_SPEC.rdoc +157 -0
- data/doc/homepage/contact.html +62 -0
- data/doc/homepage/development.html +124 -0
- data/doc/homepage/index.html +83 -0
- data/doc/homepage/ruby-dbi.css +91 -0
- data/lib/dbd/Mysql.rb +137 -0
- data/lib/dbd/ODBC.rb +89 -0
- data/lib/dbd/Pg.rb +189 -0
- data/lib/dbd/SQLite.rb +97 -0
- data/lib/dbd/SQLite3.rb +124 -0
- data/lib/dbd/mysql/database.rb +405 -0
- data/lib/dbd/mysql/driver.rb +125 -0
- data/lib/dbd/mysql/statement.rb +188 -0
- data/lib/dbd/odbc/database.rb +128 -0
- data/lib/dbd/odbc/driver.rb +38 -0
- data/lib/dbd/odbc/statement.rb +137 -0
- data/lib/dbd/pg/database.rb +508 -0
- data/lib/dbd/pg/exec.rb +47 -0
- data/lib/dbd/pg/statement.rb +160 -0
- data/lib/dbd/pg/tuples.rb +121 -0
- data/lib/dbd/pg/type.rb +209 -0
- data/lib/dbd/sqlite/database.rb +151 -0
- data/lib/dbd/sqlite/statement.rb +125 -0
- data/lib/dbd/sqlite3/database.rb +201 -0
- data/lib/dbd/sqlite3/statement.rb +78 -0
- data/lib/dbi/version.rb +1 -1
- data/prototypes/types2.rb +237 -0
- data/readme.md +3 -4
- data/setup.rb +1585 -0
- data/test/DBD_TESTS +50 -0
- data/test/TESTING +16 -0
- data/test/dbd/general/test_database.rb +206 -0
- data/test/dbd/general/test_statement.rb +325 -0
- data/test/dbd/general/test_types.rb +295 -0
- data/test/dbd/mysql/base.rb +26 -0
- data/test/dbd/mysql/down.sql +19 -0
- data/test/dbd/mysql/test_blob.rb +18 -0
- data/test/dbd/mysql/test_new_methods.rb +7 -0
- data/test/dbd/mysql/test_patches.rb +111 -0
- data/test/dbd/mysql/up.sql +28 -0
- data/test/dbd/odbc/base.rb +30 -0
- data/test/dbd/odbc/down.sql +19 -0
- data/test/dbd/odbc/test_new_methods.rb +12 -0
- data/test/dbd/odbc/test_ping.rb +10 -0
- data/test/dbd/odbc/test_statement.rb +44 -0
- data/test/dbd/odbc/test_transactions.rb +58 -0
- data/test/dbd/odbc/up.sql +33 -0
- data/test/dbd/postgresql/base.rb +31 -0
- data/test/dbd/postgresql/down.sql +31 -0
- data/test/dbd/postgresql/test_arrays.rb +179 -0
- data/test/dbd/postgresql/test_async.rb +121 -0
- data/test/dbd/postgresql/test_blob.rb +37 -0
- data/test/dbd/postgresql/test_bytea.rb +88 -0
- data/test/dbd/postgresql/test_ping.rb +10 -0
- data/test/dbd/postgresql/test_timestamp.rb +77 -0
- data/test/dbd/postgresql/test_transactions.rb +58 -0
- data/test/dbd/postgresql/testdbipg.rb +307 -0
- data/test/dbd/postgresql/up.sql +60 -0
- data/test/dbd/sqlite/base.rb +32 -0
- data/test/dbd/sqlite/test_database.rb +30 -0
- data/test/dbd/sqlite/test_driver.rb +68 -0
- data/test/dbd/sqlite/test_statement.rb +112 -0
- data/test/dbd/sqlite/up.sql +25 -0
- data/test/dbd/sqlite3/base.rb +32 -0
- data/test/dbd/sqlite3/test_database.rb +77 -0
- data/test/dbd/sqlite3/test_driver.rb +67 -0
- data/test/dbd/sqlite3/test_statement.rb +88 -0
- data/test/dbd/sqlite3/up.sql +33 -0
- data/test/dbi/tc_dbi.rb +1 -1
- data/test/ts_dbd.rb +136 -0
- data/ydbi.gemspec +25 -0
- metadata +148 -12
@@ -0,0 +1,201 @@
|
|
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
|
@@ -0,0 +1,78 @@
|
|
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/lib/dbi/version.rb
CHANGED
@@ -0,0 +1,237 @@
|
|
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
|
data/readme.md
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
# Release a new ydbi gem
|
2
2
|
|
3
|
-
*
|
4
|
-
*
|
5
|
-
*
|
6
|
-
* bundle exec gem push pkg/ydbi-*.gem
|
3
|
+
* rake ydbd-pg:clobber_package rake ydbd-pg:clobber_package; rake ydbi:gem ydbd-pg:gem
|
4
|
+
* gem push ydbd-pg-0.5.4.gem
|
5
|
+
* gem push ydbi-0.5.4.gem
|
7
6
|
|
8
7
|
# Description
|
9
8
|
The DBI package is a vendor independent interface for accessing databases.
|