|
From: Paul D. <pa...@sn...> - 2003-01-24 23:37:50
|
There is some code in dbi.rb that attempts to make driver-loading
work in case-insensitive fashion. That is, it allows the driver
name to be given in any lettercase, so that DSNs such as these
are synonymous:
dbi:Mysql:test:localhost
dbi:mysql:test:localhost
Ironically, this code works *except* on filesystems that are not
case sensitive. :-) For example, the code does not work on HFS+
filesystems on Mac OS X.
Cause: Suppose you give a DSN of dbi:mysql:test:localhost.
load_driver attempts to require 'DBD/mysql/mysql', which *works*
on a non-case-sensitive file system. load_driver then assumes
that DBI::DBD.const_get(mysql) can be used to get the appropriate
module constant for generating the driver handle. That fails because
the constant has to be Mysql.
Solution: If const_get fails, look through all the available constants
to see which one matches the given driver name in a caseless match.
That gives you the constant with the proper capitalization.
The patch below fixes the problem. It can be improved, I'm sure,
but it does work for non-case-sensitive filesystems while preserving
existing behavior for case-sensitive filesystems.
--- dbi.rb.orig Tue Oct 22 10:06:04 2002
+++ dbi.rb Fri Jan 24 17:30:51 2003
@@ -460,8 +460,24 @@
end
found ||= driver_name
+
+ # on a filesystem that is not case-sensitive, the initial require
+ # attempt that loads the driver may succeed even though the lettercase
+ # of driver_name doesn't match the actual filename. If that happens,
+ # const_get will fail and it become necessary to look though the list
+ # of constants and look for a caseless match. The result of this
+ # this match provides the constant with the proper lettercase -- which
+ # can be used to generate the driver handle.
- dr = DBI::DBD.const_get(found.intern)
+ dr = nil
+ begin
+ dr = DBI::DBD.const_get(found.intern)
+ rescue NameError
+ # caseless look for constants to find actual constant
+ found = found.downcase
+ found = DBI::DBD.constants.find { |e| e.downcase == found }
+ dr = DBI::DBD.const_get(found.intern) unless found.nil?
+ end
dbd_dr = dr::Driver.new
drh = DBI::DriverHandle.new(dbd_dr)
drh.trace(@@trace_mode, @@trace_output)
|