Search code examples
phpdb2-400db2-connectibm-db2

db2_connect() returns resource ID despite failing


I'm running on an AS/400 V7R2 using the ibm_db2 driver from a PHP script.

I noticed if I pass an invalid library list to db2_connect() with the i5_libl option with the rest of the connection string being valid, it will still return a resource ID despite an error being reported by ini_set("display_errors", 1);. In addition, db2_conn_error() and db2_conn_errormsg() do not contain anything. On the flip side, when I do provide a valid library list, my IF statements evaluate the same exact way, the only difference is an error isn't output to the screen by ini_set("display_errors", 1);

I realized that instead of failing due to the invalid library list it instead is making a connection using the default library list for the DB username provided. This can be scary for me because if for some reason my library list is invalid it will default to the wrong list (main concern being a mixture of development and production environments).

Can anyone else reproduce this behavior? I don't know if this is just my system and I need a PTF, or if this is typical. How do you verify a DB2 connection was established with the intended options?

Code to reproduce (replace system name, username and password accordingly):

<?php
ini_set("display_errors", 1);
$systemName = 'yourSystemName';
$userID = 'yourUserID';
$password = 'yourPassword';
$options['i5_libl'] = implode('Z', array(
    'INVALID',        
    'LIB',       
    'LIST',   
    'IMPLODED',  
    'WITH',   
    'THE',      
    'LETTER',       
    'Z'
));
$options['i5_naming'] = DB2_I5_NAMING_ON;

$conn = db2_connect($systemName,$userID,$password,$options);
//The error output to the screen at this point from `ini_set("display_errors", 1);` is:
//Warning: db2_connect(): Statement Execute Failed in /PATH/TO/FILE/test.php on line 58 

echo "<br />|".db2_conn_error()." ||| ".db2_conn_errormsg()."|<br />"; //This displays as "| ||| |"
print_r($conn); //This prints out a resource ID
echo "<br />";

if(isset($conn) && $conn === true){ 
    //Expected to not pass since either false or a resource ID is supposed to be returned.
    //Evaluated to false.
    echo "Boolean true<br />";
}
if(isset($conn) && $conn == true){ 
    //Despite the connection failing according to `ini_set("display_errors", 1)` and a resource ID being reportedly returned
    //this evaluates to true and "Non-Boolean true 2" echos out to the screen.
    echo "Non-Boolean true 2<br />";  
}
if(isset($conn) && $conn == "true"){ 
    //Evaluates to false. db2_connect() returns a resource ID on success, so I did not expect this to evaluate to true.
    echo "String true";
}
if(isset($conn) && $conn === false){ 
    //Expected for this to evaluate to true since an error was logged by ini_set("display_errors", 1)
    //This did not evaluate to true.
    echo "Boolean false<br />";
}
if(isset($conn) && $conn == false){ 
    //Just checking to see if a non-Boolean false was returned.  Evaluates to false.
    echo "Non-Boolean false 2<br />";
}
if(isset($conn) && $conn == "false"){ 
    //Just checking to see if the string "false" was returned.  Evaluates to false.
    echo "String false";
}
?>

Solution

  • I ended up opening a ticket with Zend and it turns out this is intended behavior.

    As we know the i5_libl options calls qsys2/qcmdexc('cmd',cmdlen) according to http://php.net/manual/en/function.db2-connect.php. But logically the connection has to be established in order for it to know which QSQSRVR job to change the library list for. Instead of closing the connection upon a failure it just issues a warning and db_conn_error() and db2_connerrormsg() report everything as normal.

    Fortunately this registers as a statement error and this can be detected with the following:

    if (db2_stmt_error()) {
        echo "error ID: " . (db2_stmt_error());
        echo "<br>error message: " . (db2_stmt_errormsg());
    }
    

    I suggested to Zend to close the connection or force a connection error or something. I can not think of any instance in which I would want to connect to the DB with a library list other than what I specified without any warning or blatant notification. This could lead to a disaster if development and production data get intertwined with each other.