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) |