dbd-mysql 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
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