From:             stein at visibone dot com
Operating system: Windows 2000
PHP version:      5.2.5
PHP Bug Type:     MySQLi related
Bug description:  mysqli_connect_error() false negative for host errors

Description:
------------
If you don't like this cramming of 4 bugs in 1, please consider this
solely a report of bug #1 which is the most serious.  Fix the first two
assert()'s in the reproduce code and call it a solved.

I think the mysqli connect-time error handling has a lot of bugs.  I hope
you'll bear with this report of 4 separate bugs.  They all contribute to a
very difficult time for PHP code to detect connection failure (as opposed
humans detecting it from warning messages in the output).  I hope someone
will find this a useful analysis of what goes wrong when connections go
wrong. 

Bug #1: a bad host (misspelled domain, server down) can't be detected by
mysqli_connect_error() or mysqli_connect_errno() -- they return empty
string and zero.  I have a hunch that in bug #30051 he actually detected
this problem at first, but then he brought up his server on localhost and
it went away so he closed his submission.  I think bug #31163 reported this
problem and then died of neglect.  Bug #31745 may have suffered from it,
but it seems to be more about exceptions versus error messages. 

Again, bug 1 is the most serious.  It breaks Example#1 on
http://www.php.net/manual/en/function.mysqli-connect.php when there's no
MySQL server running on localhost.  Bugs 2,3,4 make workarounds hard.

Bug #2: the object oriented constructor "new mysqli" never returns FALSE. 
This was reported in bug #32818 but waived off as a non-bug without
explanation.  The documentation for this constructor is smooshed in with
that of mysqli_connect(), where it states "Returns ... FALSE if the
connection failed".  So I believe bug #32818 was not bogus, or the
documentation is.

Bug #3 $mysqli->error member never passes the isset() nor
property_exists() tests.  Not when the connection fails, nor when it works,
nor after a good query, nor a bad.  Maybe all mysqli properties suffer from
this.  The reproduce code demonstrates the same lapse for mysqli::error,
mysqli::errno, and mysqli_result::num_rows.  So this may be a defect of
mysqli or some faux pas of the PHP5 object model itself.  I could find no
existing bug that described it.

Bug #4 mysqli object limbo.  Connection failure is undetectable without
generating a warning.  "new mysql" returns what is by every diagnostic a
mysqli object. (get_class(), instanceof, and is_a() all say it is.)  But if
the connection failed, doing anything with the instance will give you the
ubiquitous and inscrutible "Couldn't fetch mysqli" warning.

Drastic workaround for object oriented (works around all four bugs):

     $mysqli = @new mysqli(...);
     if (NULL === @$mysqli->error) {
          die('connect fail: ' . mysqli_connect_error());
     }

This may break someday.  It's undocumented what the error member should do
if the connection succeeds, but it acually does become the empty string.

Gentle workaround for procedural, same as Example #2 in mysqli_connect()
manual page:

     $link = @mysqli_connect(...);
     if (FALSE === $link) {
          die('connect fail: ' . mysqli_connect_error());
     }

Although in either case the message will be blank for host errors.

I believe bug 1 is the serious one.  Classic mysql_connect() doesn't make
this mistake.  Bugs 2,3,4 are relatively minor quirks of the object model. 
All four bugs together make connection errors difficult to detect in the
code.

Reproduce code:
---------------
http://www.visibone.com/php/mysqli_connect_bugs.php.txt

If you find this too verbose, please concentrate on the first two
assert()'s.  Fix them and I'd call this issue closed.

Expected result:
----------------
Many of the assert()'s should fail, especially the ones commented "// BUG"

Actual result:
--------------
Testing... 2 tables ...Done.

(or a different number of tables)

I.e. no warnings, all assert()'s pass.

-- 
Edit bug report at http://bugs.php.net/?id=44352&edit=1
-- 
Try a CVS snapshot (PHP 5.2): 
http://bugs.php.net/fix.php?id=44352&r=trysnapshot52
Try a CVS snapshot (PHP 5.3): 
http://bugs.php.net/fix.php?id=44352&r=trysnapshot53
Try a CVS snapshot (PHP 6.0): 
http://bugs.php.net/fix.php?id=44352&r=trysnapshot60
Fixed in CVS:                 http://bugs.php.net/fix.php?id=44352&r=fixedcvs
Fixed in release:             
http://bugs.php.net/fix.php?id=44352&r=alreadyfixed
Need backtrace:               http://bugs.php.net/fix.php?id=44352&r=needtrace
Need Reproduce Script:        http://bugs.php.net/fix.php?id=44352&r=needscript
Try newer version:            http://bugs.php.net/fix.php?id=44352&r=oldversion
Not developer issue:          http://bugs.php.net/fix.php?id=44352&r=support
Expected behavior:            http://bugs.php.net/fix.php?id=44352&r=notwrong
Not enough info:              
http://bugs.php.net/fix.php?id=44352&r=notenoughinfo
Submitted twice:              
http://bugs.php.net/fix.php?id=44352&r=submittedtwice
register_globals:             http://bugs.php.net/fix.php?id=44352&r=globals
PHP 4 support discontinued:   http://bugs.php.net/fix.php?id=44352&r=php4
Daylight Savings:             http://bugs.php.net/fix.php?id=44352&r=dst
IIS Stability:                http://bugs.php.net/fix.php?id=44352&r=isapi
Install GNU Sed:              http://bugs.php.net/fix.php?id=44352&r=gnused
Floating point limitations:   http://bugs.php.net/fix.php?id=44352&r=float
No Zend Extensions:           http://bugs.php.net/fix.php?id=44352&r=nozend
MySQL Configuration Error:    http://bugs.php.net/fix.php?id=44352&r=mysqlcfg

Reply via email to