Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 1.5.0b4

Bug #6226 Loading mysql driver fails
Submitted: 2005-12-12 11:39 UTC
From: petra dot arentzen at pegu dot de Assigned: lsmith
Status: Closed Package: MDB2_Driver_mysqli
PHP Version: 4.3.10 OS: Linux debian 2.6.14
Roadmaps: (Not assigned)    

 [2005-12-12 11:39 UTC] petra dot arentzen at pegu dot de
Description: ------------ MDB2 2.0.0beta6 beta MDB2_Driver_mysql 0.1.1 beta Loading of mysql.php fails if "MDB2.php" is included by include-path, because there is a test if include-file "MDB2/Driver/mysql.php" exists. Because the script's current directory isn't PEAR's main directory (which is in include-path) this must fail and MDB2::factory() will return an error. Maybe this problem applies to other drivers too. Test script: --------------- <? // from liveuser example5 require_once 'MDB2.php'; $dsn = 'mysql://testuser:testpassword@localhost/testdatabase'; $options = array( 'portability' => (MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL), want to use DB as the backend ); $dsn = MDB2::parseDSN($dsn); $database = $dsn['database']; unset($dsn['database']); $manager =& MDB2_Schema::factory($dsn, $options); ?> Commenting out line 317 - 321 in "MDB2.php" solves the problem. Expected result: ---------------- $manager should be a valid MDB2 Object Actual result: -------------- $manager is an Error Object


 [2005-12-12 11:41 UTC] lsmith
The drivers are no longer part of the core package. You need to install them separately: pear install MDB2_Driver_mysql-beta
 [2005-12-12 12:16 UTC] petra dot arentzen at pegu dot de
Of course I had installed the mysql driver. The problem ist not that the include does not work - it's the test if the file exists before including it. The include would work but the code will not be executed because the previous test failes. /usr/share/php/MDB2.php: function &factory($dsn, $options = false) { $dsninfo = MDB2::parseDSN($dsn); if (!array_key_exists('phptype', $dsninfo)) { $err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, 'no RDBMS driver specified'); return $err; } $class_name = 'MDB2_Driver_'.$dsninfo['phptype']; if (!class_exists($class_name)) { $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php'; # if (!MDB2::fileExists($file_name)) { # $err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, # 'unable to find: '.$file_name); # return $err; # } if (!include_once($file_name)) { $err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, 'unable to load driver class: '. $file_name); return $err; } } $db =& new $class_name(); $db->setDSN($dsninfo); $err = MDB2::setOptions($db, $options); if (PEAR::isError($err)) { return $err; } return $db; } The lines with the leading '#' which I have filled in on my local file are causing the trouble.
 [2005-12-12 12:57 UTC] lsmith
I really dont understand what you are doing, but for PEAR to work the PEAR path needs to be in the include path and it is your job to ensure that no files collide with PEAR if the PEAR dir is not the first in the include path. There is nothing I can do about this.
 [2005-12-12 13:43 UTC] petra dot arentzen at pegu dot de
And I don't understand why you don't understand. It's not the first time I am using PEAR. I worked e.g with DB, DB_DataObject for more than three years. I'm sure that my Include-Path ist set correctly. No other pear application had ever had trouble with it. It seems that the (imho) useless test for the existence of the file before including it causes the trouble. So if I comment out this test the code works. In this case the code with the <code> if (!include_once($file_name)) { </code> works fine because my include-path is set correcly. Now I've told all I can tell about this bug/ trouble/ problem and if you are telling me further that it is my fail then I can't change it. I've tried my very best ;-)
 [2005-12-12 13:47 UTC] lsmith
This is the implementation if fileExists(). I do not see anything that would cause your issues. function fileExists($file) { $dirs = explode(PATH_SEPARATOR, ini_get('include_path')); foreach ($dirs as $dir) { if (is_readable($dir . DIRECTORY_SEPARATOR . $file)) { return true; } } return false; } The test is not useless, because it makes it possible to differentiate between the non existance of the file and a parse error in the file. I have also never ever had a single bug report on this piece of code. It also used in LiveUser. So it seems there is something in your environment thats "non standard". Maybe some wierd safe mode setup?
 [2005-12-12 16:20 UTC] petra dot arentzen at pegu dot de
Your hint about safe_mode leads me some steps further. I've debugged my script again and again. The problem seems to be the PHP-function is_readable(). Here's what I figured out: safe_mode off/ user: petra - works fine safe_mode on/ user: petra - fails safe_mode on/ user: root - workes fine This seems to be very similar to the following bug This bug was reported for php 5 cvs version. Perhaps it's an old bug which had survived since 4.3.10 or even earlier. So it seems not to be a problem of MDB2. But perhaps it makes sense to remove calling fileExists().
 [2005-12-12 17:04 UTC] lsmith
I fear I will probably not be able to help you. I do not see another way of implementing the functionality I want (differentiate between file missing and file has parse errors). I will investigate but since you are the first user that experienced this and since it seems that safe_mode is on its way out (its likely to be dropped with php6 at the latest) I am relunctant to drop this feature. I may consider making it optional during debug mode only, but I will need to ponder it.
 [2005-12-12 17:36 UTC] petra dot arentzen at pegu dot de
Ok, thank you. I think I can live with that.
 [2005-12-13 10:28 UTC] lsmith
This bug has been fixed in CVS. If this was a documentation problem, the fix will appear on by the end of next Sunday (CET). If this was a problem with the website, the change should be live shortly. Otherwise, the fix will appear in the package's next release. Thank you for the report and for helping us make PEAR better. Well looking at it, it seems to make more sense to do the fileExists() check if the include failed, since the entire purpose is to determine the proper error message (file missing or file has parse errors). This should even speed things up a bit when loading drivers. However there is another use case where I cannot do without fileExists() and that is in the loadModule() method. The problem is that some modules are backend specific and some are not: MDB2_Extended vs. MDB2_Driver_Datatype_mysql Since I do not want to make the user think about this, I check if the given file exists for once case and if it does not try the other case in order to determine what file to include and how to load the instance. I will add a parameter for the user to hint this in loadModule() if they are in the unfortunate situation of safe_mode ..