dbd-mysql 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.
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ (C) 2008 Erik Hollensbe <erik@hollensbe.org>. All rights reserved.
2
+
3
+ Please see "README" for earlier copyrights.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+ 1. Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in the
12
+ documentation and/or other materials provided with the distribution.
13
+ 3. The name of the author may not be used to endorse or promote products
14
+ derived from this software without specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19
+ THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README ADDED
@@ -0,0 +1,271 @@
1
+ = Description
2
+ The DBI package is a vendor independent interface for accessing databases.
3
+ It is similar, but not identical to, Perl's DBI module.
4
+
5
+ = Synopsis
6
+
7
+ require 'dbi'
8
+
9
+ # Connect to a database, old style
10
+ dbh = DBI.connect('DBI:Mysql:test', 'testuser', 'testpwd')
11
+
12
+ # Insert some rows, use placeholders
13
+ 1.upto(13) do |i|
14
+ sql = "insert into simple01 (SongName, SongLength_s) VALUES (?, ?)"
15
+ dbh.do(sql, "Song #{i}", "#{i*10}")
16
+ end
17
+
18
+ # Select all rows from simple01
19
+ sth = dbh.prepare('select * from simple01')
20
+ sth.execute
21
+
22
+ # Print out each row
23
+ while row=sth.fetch do
24
+ p row
25
+ end
26
+
27
+ # Close the statement handle when done
28
+ sth.finish
29
+
30
+ # Don't prepare, just do it!
31
+ dbh.do('delete from simple01 where internal_id > 10')
32
+
33
+ # And finally, disconnect
34
+ dbh.disconnect
35
+
36
+ # Same example, but a little more Ruby-ish
37
+ DBI.connect('DBI:Mysql:test', 'testuser', 'testpwd') do | dbh |
38
+
39
+ sql = "insert into simple01 (SongName, SongLength_s) VALUES (?, ?)"
40
+
41
+ dbh.prepare(sql) do | sth |
42
+ 1.upto(13) { |i| sth.execute("Song #{i}", "#{i*10}") }
43
+ end
44
+
45
+ dbh.select_all('select * from simple01') do | row |
46
+ p row
47
+ end
48
+
49
+ dbh.do('delete from simple01 where internal_id > 10')
50
+
51
+ end
52
+
53
+ = Prerequisites
54
+ Ruby 1.8.6 or later is the test target, however you may have success with
55
+ earlier 1.8.x versions of Ruby.
56
+
57
+ = RubyForge Project
58
+ General information: http://ruby-dbi.rubyforge.org
59
+ Project information: http://rubyforge.org/projects/ruby-dbi/
60
+ Downloads: http://rubyforge.org/frs/?group_id=234
61
+
62
+ = Installation
63
+ There are many database drivers (DBDs) available. You only need to install
64
+ the DBDs for the database software that you will be using.
65
+
66
+ == Gem setup:
67
+
68
+ gem install dbi
69
+ # One or more of:
70
+ gem install dbd-mysql
71
+ gem install dbd-pg
72
+ gem install dbd-sqlite3
73
+ gem install dbd-sqlite
74
+
75
+ == Without rubygems:
76
+
77
+ ruby setup.rb config
78
+ ruby setup.rb setup
79
+ ruby setup.rb install
80
+
81
+ == The bleeding edge:
82
+
83
+ git clone git://hollensbe.org/git/ruby-dbi.git
84
+ git checkout -b development origin/development
85
+
86
+ Also available at
87
+
88
+ git clone git://github.com/erikh/ruby-dbi.git
89
+
90
+ = Available Database Drivers (DBDs)
91
+
92
+ == DBD::MySQL
93
+ MySQL
94
+ Depends on the mysql-ruby package from http://www.tmtm.org/mysql or
95
+ available from the RAA.
96
+
97
+ == DBD::ODBC
98
+ ODBC
99
+ Depends on the ruby-odbc package (0.5 or later, 0.9.3 or later recommended) at
100
+ http://www.ch-werner.de/rubyodbc or available from the RAA. Works together
101
+ with unix-odbc.
102
+
103
+ == DBD::OCI8
104
+ OCI8 (Oracle)
105
+ Depends on the the ruby-oci8 package, available on the RAA and RubyForge.
106
+
107
+ == DBD::Pg
108
+ PostgreSQL
109
+ Depends on the pg package, available on RubyForge.
110
+
111
+ == DBD::SQLite
112
+ SQLite (versions 2.x and earlier)
113
+ Depends on the sqlite-ruby package, available on rubyforge.
114
+
115
+ == DBD::SQLite3
116
+ SQLite 3.x
117
+ Depends on the sqlite3-ruby package, available on rubyforge.
118
+
119
+ = Additional Documentation
120
+ See the directories doc/* for DBI and DBD specific information.
121
+ The DBI specification is at doc/DBI_SPEC.rdoc.
122
+ The DBD specification is at doc/DBD_SPEC.rdoc.
123
+
124
+ = Articles
125
+ == Tutorial: Using the Ruby DBI Module
126
+ http://www.kitebird.com/articles/ruby-dbi.html
127
+
128
+ = Applications
129
+ == dbi
130
+ The SQL command line interpreter dbi is available in directory
131
+ bin/. It gets installed by default.
132
+
133
+ = License
134
+
135
+ Copyright (c) 2008 Erik Hollensbe
136
+
137
+ Copyright (c) 2005-2006 Kirk Haines, Francis Hwang, Patrick May and Daniel
138
+ Berger.
139
+
140
+ Copyright (c) 2001, 2002, 2003, 2004 Michael Neumann <mneumann@ntecs.de>
141
+ and others (see the beginning of each file for copyright holder information).
142
+
143
+ All rights reserved.
144
+
145
+ Redistribution and use in source and binary forms, with or without
146
+ modification, are permitted provided that the following conditions are met:
147
+
148
+ 1. Redistributions of source code must retain the above copyright notice,
149
+ this list of conditions and the following disclaimer.
150
+ 2. Redistributions in binary form must reproduce the above copyright notice,
151
+ this list of conditions and the following disclaimer in the documentation
152
+ and/or other materials provided with the distribution.
153
+ 3. The name of the author may not be used to endorse or promote products
154
+ derived from this software without specific prior written permission.
155
+
156
+ THIS SOFTWARE IS PROVIDED 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
157
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
158
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
159
+ THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
160
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
161
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
162
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
163
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
164
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
165
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
166
+
167
+ This is the BSD license which is less restrictive than GNU's GPL
168
+ (General Public License).
169
+
170
+ = Contributors
171
+
172
+ Pistos
173
+ Too much to specify. Infinite patience and help.
174
+
175
+ Christopher Maujean
176
+ Lots of initial help when reviving the project.
177
+
178
+ Jun Mukai <mukai@jmuk.org>
179
+ Contributed initial SQLite3 DBD.
180
+
181
+ John J. Fox IV
182
+ Lots of help testing on multiple platforms.
183
+
184
+ Kirk Haines
185
+ One of the authors of the rewrite effort (January 2006).
186
+
187
+ Francis Hwang
188
+ One of the authors of the rewrite effort (January 2006).
189
+
190
+ Patrick May
191
+ One of the authors of the rewrite effort (January 2006).
192
+
193
+ Daniel Berger
194
+ One of the authors of the rewrite effort (January 2006).
195
+
196
+ Michael Neumann
197
+ Original author of Ruby/DBI; wrote the DBI and most of the DBDs.
198
+
199
+ Rainer Perl
200
+ Author of Ruby/DBI 0.0.4 from which many good ideas were taken.
201
+
202
+ Jim Weirich
203
+ Original author of DBD::Pg. Wrote additional code (e.g. sql.rb,
204
+ testcases). Gave many helpful hints and comments.
205
+
206
+ Eli Green
207
+ Implemented DatabaseHandle#columns for Mysql and Pg.
208
+
209
+ Masatoshi SEKI
210
+ For his version of module BasicQuote in sql.rb.
211
+
212
+ John Gorman
213
+ For his case insensitive load_driver patch and parameter parser.
214
+
215
+ David Muse
216
+ For testing the DBD::SQLRelay and for his initial DBD.
217
+
218
+ Jim Menard
219
+ Extended DBD::Oracle for method columns.
220
+
221
+ Joseph McDonald
222
+ Fixed bug in DBD::Pg (default values in method columns).
223
+
224
+ Norbert Gawor
225
+ Fixed bug in DBD::ODBC (method columns) and proxyserver.
226
+
227
+ James F. Hranicky
228
+ Patch for DBD::Pg (cache PGResult#result in Tuples) which increased
229
+ performance by a factor around 100.
230
+
231
+ Stephen Davies
232
+ Added method Statement#fetch_scroll for DBD::Pg.
233
+
234
+ Dave Thomas
235
+ Several enhancements.
236
+
237
+ Brad Hilton
238
+ Column coercing patch for DBD::Mysql.
239
+
240
+ Sean Chittenden
241
+ Originally a co-owner of the project. Submitted several patches
242
+ and helped with lots of comments.
243
+
244
+ MoonWolf
245
+ Provided the quote/escape_byte patch for DBD::Pg, DBD::SQLite patch and
246
+ Database#columns implementation. Further patches.
247
+
248
+ Paul DuBois
249
+ Fixed typos and formatting. Maintains DBD::Mysql.
250
+
251
+ Tim Bates
252
+ Bug fixes for Mysql and DBI.
253
+
254
+ Brian Candler
255
+ Zero-padding date/time/timestamps fix.
256
+
257
+ Florian G. Pflug
258
+ Discussion and helpful comments/benchmarks about DBD::Pg async_exec vs.
259
+ exec.
260
+
261
+ Oliver M. Bolzer
262
+ Patches to support Postgres arrays for DBD::Pg.
263
+
264
+ Stephen R. Veit
265
+ ruby-db2 and DBD::DB2 enhancements.
266
+
267
+ Dennis Vshivkov
268
+ DBD::Pg patches
269
+
270
+ Cail Borrell from frontbase.com
271
+ For the Frontbase DBD and C interface.
data/lib/dbd/Mysql.rb ADDED
@@ -0,0 +1,111 @@
1
+ #--
2
+ # Copyright (c) 2001, 2002 Michael Neumann <neumann@s-direktnet.de>
3
+ #
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions
8
+ # are met:
9
+ # 1. Redistributions of source code must retain the above copyright
10
+ # notice, this list of conditions and the following disclaimer.
11
+ # 2. Redistributions in binary form must reproduce the above copyright
12
+ # notice, this list of conditions and the following disclaimer in the
13
+ # documentation and/or other materials provided with the distribution.
14
+ # 3. The name of the author may not be used to endorse or promote products
15
+ # derived from this software without specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18
+ # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19
+ # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20
+ # THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23
+ # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25
+ # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26
+ # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ #
28
+ # $Id$
29
+ #++
30
+
31
+ begin
32
+ require 'rubygems'
33
+ gem 'mysql'
34
+ gem 'dbi'
35
+ rescue LoadError => e
36
+ end
37
+
38
+ require 'dbi'
39
+ require "mysql"
40
+ require "thread" # for Mutex
41
+
42
+ module DBI
43
+ module DBD
44
+ #
45
+ # DBD::Mysql - Database Driver for the MySQL database system.
46
+ #
47
+ # Requires DBI and the 'mysql' gem or package to work.
48
+ #
49
+ # Only things that extend DBI's results are documented.
50
+ #
51
+ module Mysql
52
+ VERSION = "0.3.3"
53
+ DESCRIPTION = "MySQL DBI DBD, Leverages 'mysql' low-level driver"
54
+
55
+ MyError = ::MysqlError
56
+
57
+ #
58
+ # returns 'Mysql'
59
+ #
60
+ # See DBI::TypeUtil#convert for more information.
61
+ #
62
+ def self.driver_name
63
+ "Mysql"
64
+ end
65
+
66
+ DBI::TypeUtil.register_conversion(driver_name) do |obj|
67
+ newobj = case obj
68
+ when ::DBI::Binary
69
+ obj = obj.to_s.gsub(/\\/) { "\\\\" }
70
+ obj = obj.to_s.gsub(/'/) { "''" }
71
+ "'#{obj}'"
72
+ when ::Time
73
+ "'#{obj.strftime("%H:%M:%S")}'"
74
+ when ::Date
75
+ "'#{obj.strftime("%m/%d/%Y")}'"
76
+ when ::NilClass
77
+ "NULL"
78
+ else
79
+ obj
80
+ end
81
+
82
+ if newobj.object_id == obj.object_id
83
+ [newobj, true]
84
+ else
85
+ [newobj, false]
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ #
93
+ # Utility Methods for the MySQL DBD.
94
+ #
95
+
96
+ module DBI::DBD::Mysql::Util
97
+ private
98
+
99
+ # Raise exception using information from MysqlError object e.
100
+ # For state value, use SQLSTATE value if mysql-ruby defines
101
+ # sqlstate method, otherwise nil.
102
+ def error(e)
103
+ sqlstate = e.respond_to?("sqlstate") ? e.sqlstate : nil
104
+ raise DBI::DatabaseError.new(e.message, e.errno, sqlstate)
105
+ end
106
+
107
+ end # module Util
108
+
109
+ require 'dbd/mysql/driver'
110
+ require 'dbd/mysql/database'
111
+ require 'dbd/mysql/statement'
@@ -0,0 +1,391 @@
1
+ module DBI::DBD::Mysql
2
+ #
3
+ # Models the DBI::BaseDatabase API to create DBI::DatabaseHandle objects.
4
+ #
5
+ class Database < DBI::BaseDatabase
6
+ include Util
7
+
8
+ #
9
+ # Hash to translate MySQL type names to DBI SQL type constants
10
+ #
11
+ # Only used in #mysql_type_info.
12
+ #
13
+ #--
14
+ # Eli Green:
15
+ # The hope is that we don't ever need to just assume the default values.
16
+ # However, in some cases (notably floats and doubles), I have seen
17
+ # "show fields from table" return absolutely zero information about size
18
+ # and precision. Sigh. I probably should have made a struct to store
19
+ # this info in ... but I didn't.
20
+ #++
21
+ MYSQL_to_XOPEN = {
22
+ "TINYINT" => [DBI::SQL_TINYINT, 1, nil],
23
+ "SMALLINT" => [DBI::SQL_SMALLINT, 6, nil],
24
+ "MEDIUMINT" => [DBI::SQL_SMALLINT, 6, nil],
25
+ "INT" => [DBI::SQL_INTEGER, 11, nil],
26
+ "INTEGER" => [DBI::SQL_INTEGER, 11, nil],
27
+ "BIGINT" => [DBI::SQL_BIGINT, 25, nil],
28
+ "INT24" => [DBI::SQL_BIGINT, 25, nil],
29
+ "REAL" => [DBI::SQL_REAL, 12, nil],
30
+ "FLOAT" => [DBI::SQL_FLOAT, 12, nil],
31
+ "DECIMAL" => [DBI::SQL_DECIMAL, 12, nil],
32
+ "NUMERIC" => [DBI::SQL_NUMERIC, 12, nil],
33
+ "DOUBLE" => [DBI::SQL_DOUBLE, 22, nil],
34
+ "CHAR" => [DBI::SQL_CHAR, 1, nil],
35
+ "VARCHAR" => [DBI::SQL_VARCHAR, 255, nil],
36
+ "DATE" => [DBI::SQL_DATE, 10, nil],
37
+ "TIME" => [DBI::SQL_TIME, 8, nil],
38
+ "TIMESTAMP" => [DBI::SQL_TIMESTAMP, 19, nil],
39
+ "DATETIME" => [DBI::SQL_TIMESTAMP, 19, nil],
40
+ "TINYBLOB" => [DBI::SQL_BINARY, 255, nil],
41
+ "BLOB" => [DBI::SQL_VARBINARY, 65535, nil],
42
+ "MEDIUMBLOB" => [DBI::SQL_VARBINARY, 16277215, nil],
43
+ "LONGBLOB" => [DBI::SQL_LONGVARBINARY, 2147483657, nil],
44
+ "TINYTEXT" => [DBI::SQL_VARCHAR, 255, nil],
45
+ "TEXT" => [DBI::SQL_LONGVARCHAR, 65535, nil],
46
+ "MEDIUMTEXT" => [DBI::SQL_LONGVARCHAR, 16277215, nil],
47
+ "LONGTEXT" => [DBI::SQL_LONGVARCHAR, 2147483657, nil],
48
+ "ENUM" => [DBI::SQL_CHAR, 255, nil],
49
+ "SET" => [DBI::SQL_CHAR, 255, nil],
50
+ "BIT" => [DBI::SQL_BIT, 8, nil],
51
+ nil => [DBI::SQL_OTHER, nil, nil]
52
+ }
53
+
54
+
55
+ #
56
+ # This maps type names to DBI Types.
57
+ #
58
+ TYPE_MAP = {}
59
+
60
+ ::Mysql::Field.constants.grep(/^TYPE_/).each do |const|
61
+ mysql_type = MysqlField.const_get(const) # numeric type code
62
+ coercion_method = DBI::Type::Varchar # default coercion method
63
+ case const
64
+ when 'TYPE_TINY'
65
+ mysql_type_name = 'TINYINT'
66
+ coercion_method = DBI::Type::Integer
67
+ when 'TYPE_SHORT'
68
+ mysql_type_name = 'SMALLINT'
69
+ coercion_method = DBI::Type::Integer
70
+ when 'TYPE_INT24'
71
+ mysql_type_name = 'MEDIUMINT'
72
+ coercion_method = DBI::Type::Integer
73
+ when 'TYPE_LONG'
74
+ mysql_type_name = 'INT'
75
+ coercion_method = DBI::Type::Integer
76
+ when 'TYPE_LONGLONG'
77
+ mysql_type_name = 'BIGINT'
78
+ coercion_method = DBI::Type::Integer
79
+ when 'TYPE_FLOAT'
80
+ mysql_type_name = 'FLOAT'
81
+ coercion_method = DBI::Type::Float
82
+ when 'TYPE_DOUBLE'
83
+ mysql_type_name = 'DOUBLE'
84
+ coercion_method = DBI::Type::Float
85
+ when 'TYPE_VAR_STRING', 'TYPE_STRING'
86
+ mysql_type_name = 'VARCHAR' # questionable?
87
+ coercion_method = DBI::Type::Varchar
88
+ when 'TYPE_DATE'
89
+ mysql_type_name = 'DATE'
90
+ coercion_method = DBI::Type::Timestamp
91
+ when 'TYPE_TIME'
92
+ mysql_type_name = 'TIME'
93
+ coercion_method = DBI::Type::Timestamp
94
+ when 'TYPE_DATETIME', 'TYPE_TIMESTAMP'
95
+ mysql_type_name = 'DATETIME'
96
+ coercion_method = DBI::Type::Timestamp
97
+ when 'TYPE_CHAR'
98
+ mysql_type_name = 'TINYINT' # questionable?
99
+ when 'TYPE_TINY_BLOB'
100
+ mysql_type_name = 'TINYBLOB' # questionable?
101
+ when 'TYPE_MEDIUM_BLOB'
102
+ mysql_type_name = 'MEDIUMBLOB' # questionable?
103
+ when 'TYPE_LONG_BLOB'
104
+ mysql_type_name = 'LONGBLOB' # questionable?
105
+ when 'TYPE_GEOMETRY'
106
+ mysql_type_name = 'BLOB' # questionable?
107
+ when 'TYPE_YEAR',
108
+ 'TYPE_DECIMAL', # questionable?
109
+ 'TYPE_BLOB', # questionable?
110
+ 'TYPE_ENUM',
111
+ 'TYPE_SET',
112
+ 'TYPE_BIT',
113
+ 'TYPE_NULL'
114
+ mysql_type_name = const.sub(/^TYPE_/, '')
115
+ else
116
+ mysql_type_name = 'UNKNOWN'
117
+ end
118
+ TYPE_MAP[mysql_type] = [mysql_type_name, coercion_method]
119
+ end
120
+ TYPE_MAP[nil] = ['UNKNOWN', DBI::Type::Varchar]
121
+ TYPE_MAP[246] = ['NUMERIC', DBI::Type::Decimal]
122
+
123
+ #
124
+ # Constructor. Attributes supported:
125
+ #
126
+ # * AutoCommit: Commit after each executed statement. This will raise
127
+ # a DBI::NotSupportedError if the backend does not support
128
+ # transactions.
129
+ #
130
+ def initialize(handle, attr)
131
+ super
132
+ # check server version to determine transaction capability
133
+ ver_str = @handle.get_server_info
134
+ major, minor, teeny = ver_str.split(".")
135
+ teeny.sub!(/\D*$/, "") # strip any non-numeric suffix if present
136
+ server_version = major.to_i*10000 + minor.to_i*100 + teeny.to_i
137
+ # It's not until 3.23.17 that SET AUTOCOMMIT,
138
+ # BEGIN, COMMIT, and ROLLBACK all are available
139
+ @have_transactions = (server_version >= 32317)
140
+ # assume that the connection begins in AutoCommit mode
141
+ @attr['AutoCommit'] = true
142
+ @mutex = Mutex.new
143
+ end
144
+
145
+ def disconnect
146
+ self.rollback unless @attr['AutoCommit']
147
+ @handle.close
148
+ rescue MyError => err
149
+ error(err)
150
+ end
151
+
152
+ def ping
153
+ begin
154
+ @handle.ping
155
+ return true
156
+ rescue MyError
157
+ return false
158
+ end
159
+ end
160
+
161
+ def tables
162
+ @handle.list_tables
163
+ rescue MyError => err
164
+ error(err)
165
+ end
166
+
167
+ #
168
+ # See DBI::BaseDatabase#columns.
169
+ #
170
+ # Extra attributes:
171
+ #
172
+ # * sql_type: XOPEN integer constant relating to type.
173
+ # * nullable: true if the column allows NULL as a value.
174
+ # * indexed: true if the column belongs to an index.
175
+ # * primary: true if the column is a part of a primary key.
176
+ # * unique: true if the values in this column are unique.
177
+ # * default: the default value if this column is not explicitly set.
178
+ #
179
+ def columns(table)
180
+ dbh = DBI::DatabaseHandle.new(self)
181
+ uniques = []
182
+ dbh.execute("SHOW INDEX FROM #{table}") do |sth|
183
+ sth.each do |row|
184
+ uniques << row[4] if row[1] == "0"
185
+ end
186
+ end
187
+
188
+ ret = nil
189
+ dbh.execute("SHOW FIELDS FROM #{table}") do |sth|
190
+ ret = sth.collect do |row|
191
+ name, type, nullable, key, default, extra = row
192
+ #type = row[1]
193
+ #size = type[type.index('(')+1..type.index(')')-1]
194
+ #size = 0
195
+ #type = type[0..type.index('(')-1]
196
+
197
+ sqltype, type, size, decimal = mysql_type_info(row[1])
198
+ col = Hash.new
199
+ col['name'] = name
200
+ col['sql_type'] = sqltype
201
+ col['type_name'] = type
202
+ col['nullable'] = nullable == "YES"
203
+ col['indexed'] = key != ""
204
+ col['primary'] = key == "PRI"
205
+ col['unique'] = uniques.index(name) != nil
206
+ col['precision'] = size
207
+ col['scale'] = decimal
208
+ col['default'] = row[4]
209
+ col
210
+ end # collect
211
+ end # execute
212
+
213
+ ret
214
+ end
215
+
216
+ def do(stmt, *bindvars)
217
+ st = Statement.new(self, @handle, stmt, @mutex)
218
+ st.bind_params(*bindvars)
219
+ res = st.execute
220
+ st.finish
221
+ return res
222
+ rescue MyError => err
223
+ error(err)
224
+ end
225
+
226
+
227
+ def prepare(statement)
228
+ Statement.new(self, @handle, statement, @mutex)
229
+ end
230
+
231
+ #
232
+ # MySQL has several backends, some of which may not support commits.
233
+ # If the backend this database uses doesn't, calling this method will
234
+ # raise a DBI::NotSupportedError.
235
+ #
236
+ def commit
237
+ if @have_transactions
238
+ self.do("COMMIT")
239
+ else
240
+ raise NotSupportedError
241
+ end
242
+ rescue MyError => err
243
+ error(err)
244
+ end
245
+
246
+ #
247
+ # See #commit for information regarding transactionless database
248
+ # backends.
249
+ #
250
+ def rollback
251
+ if @have_transactions
252
+ self.do("ROLLBACK")
253
+ else
254
+ raise NotSupportedError
255
+ end
256
+ rescue MyError => err
257
+ error(err)
258
+ end
259
+
260
+
261
+ # def quote(value)
262
+ # case value
263
+ # when String
264
+ # "'#{@handle.quote(value)}'"
265
+ # when DBI::Binary
266
+ # "'#{@handle.quote(value.to_s)}'"
267
+ # when TrueClass
268
+ # "'1'"
269
+ # when FalseClass
270
+ # "'0'"
271
+ # else
272
+ # super
273
+ # end
274
+ # end
275
+
276
+ #
277
+ # See DBI::DBD::MySQL::Database.new for supported attributes and usage.
278
+ #
279
+ def []=(attr, value)
280
+ case attr
281
+ when 'AutoCommit'
282
+ if @have_transactions
283
+ self.do("SET AUTOCOMMIT=" + (value ? "1" : "0"))
284
+ else
285
+ raise NotSupportedError
286
+ end
287
+ else
288
+ raise NotSupportedError
289
+ end
290
+
291
+ @attr[attr] = value
292
+ end
293
+
294
+ private # -------------------------------------------------
295
+
296
+ #
297
+ # Given a type name, weans some basic information from that and returns
298
+ # it in a format similar to columns.
299
+ #
300
+ # Return is an array of +sqltype+, +type+, +size+, and +decimal+.
301
+ # +sqltype+ is the XOPEN type, and +type+ is the string with the
302
+ # parameters removed.
303
+ #
304
+ # +size+ and +decimal+ refer to +precision+ and +scale+ in most cases,
305
+ # but not always for all types. Please consult the documentation for
306
+ # your MySQL version.
307
+ #
308
+ #
309
+ def mysql_type_info(typedef)
310
+ sqltype, type, size, decimal = nil, nil, nil, nil
311
+
312
+ pos = typedef.index('(')
313
+ if not pos.nil?
314
+ type = typedef[0..pos-1]
315
+ size = typedef[pos+1..-2]
316
+ pos = size.index(',')
317
+ if not pos.nil?
318
+ size, decimal = size.split(',', 2)
319
+ decimal = decimal.to_i
320
+ end
321
+ size = size.to_i
322
+ else
323
+ type = typedef
324
+ end
325
+
326
+ type_info = MYSQL_to_XOPEN[type.upcase] || MYSQL_to_XOPEN[nil]
327
+ sqltype = type_info[0]
328
+ if size.nil? then size = type_info[1] end
329
+ if decimal.nil? then decimal = type_info[2] end
330
+ return sqltype, type, size, decimal
331
+ end
332
+
333
+ #--
334
+ # Driver-specific functions ------------------------------------------------
335
+ #++
336
+
337
+ public
338
+
339
+ def __createdb(db)
340
+ @handle.create_db(db)
341
+ end
342
+
343
+ def __dropdb(db)
344
+ @handle.drop_db(db)
345
+ end
346
+
347
+ def __shutdown
348
+ @handle.shutdown
349
+ end
350
+
351
+ def __reload
352
+ @handle.reload
353
+ end
354
+
355
+ def __insert_id
356
+ @handle.insert_id
357
+ end
358
+
359
+ def __thread_id
360
+ @handle.thread_id
361
+ end
362
+
363
+ def __info
364
+ @handle.info
365
+ end
366
+
367
+ def __host_info
368
+ @handle.host_info
369
+ end
370
+
371
+ def __proto_info
372
+ @handle.proto_info
373
+ end
374
+
375
+ def __server_info
376
+ @handle.server_info
377
+ end
378
+
379
+ def __client_info
380
+ @handle.client_info
381
+ end
382
+
383
+ def __client_version
384
+ @handle.client_version
385
+ end
386
+
387
+ def __stat
388
+ @handle.stat
389
+ end
390
+ end # class Database
391
+ end