Php – Linux odbc fatal error : Allowed memory size

Linux odbc fatal error : Allowed memory size… here is a solution to the problem.

Linux odbc fatal error : Allowed memory size

I’m currently having some problems setting up an intranet using an odbc link between AS400 (iseries V6R1) and Debian, I’m using iseriesAccess7.1 odbc driver 64-bit, unixODBC2.3.1 and php5.4 with unixODBC support.

My link seems good because I can connect to my database using the isql command (which is part of unixODBC) and do some SQL queries, but it’s not possible to read the records in the database using a php script.
When I try to start a small script on my intranet, I get the following error:

fatal error: The memory size of 134217728 bytes allowed in /home/www/imypdo/imypdo.php on line 122 has been exhausted (an attempt was made to allocate 493921239296 bytes).

Over 450 GB !! There is nothing in /var/log/messages and /etc/httpd/logs/error_log

A simple SQL query (only 1 row in the selection) will return some weird characters (see below), and once I select 1 or 2 more rows, a memory size error occurs.

[0] =>

array ( [ADHMAR] => AAAAAAA a@Yÿ Œ4–X 0!ÿŒ4làÿŒ4làÿŒ4!)

I’m almost certain this is a 64-bit driver-related issue because I already have another Debian linked to this series, but with a 32-bit driver and it works just fine.
Strangely the isql command is running, but there is nothing in the log file….

If it’s really a 64-bit driver issue, how do I prove it to IBM?

Any help would be appreciated

Thanks

———————— Connection class —————- ———-

private $_bdd = "DSN=db2;" ,
        $_user = "USERNAME",
        $_pwd = "Password";

private $_con,
        $_isConnected;

public function open_connection(){
    $this->_con = odbc_connect ($this->_bdd, $this->_user, $this->_pwd ) or die("Error Connection") ;
    $this->_isConnected = true;
}

public function close_connection(){
     odbc_close($this->_con);
     $this->_isConnected = false;
}

public function execute($sql){

if(!( $this->_isConnected))
        $this->open_connection();

#execute sql
    $res = odbc_exec($this->_con, $sql);

return $res;
}

public function fetchRow($res){

$row = odbc_fetch_array($res);
    return $row;
}

——————————– Query script ———— ——————

public function getPhoneLogsByDate($startDate, $endDate) {

$startDate  = date('Ymd', strtotime($startDate));
    $endDate    = date('Ymd', strtotime($endDate));

$rr = new As400_Model_as400query();

$rr->open_connection();

$sql = "select trim(tluser) as USER, trim(tlacct) as CLIENT, trim(concat(concat(concat(concat(concat(concat(substr(trim(tldate),1,4),'-'),substr(trim(tldate),5,2)),'-'),substr (trim(tldate),7,2)),' '), concat(concat(concat(concat(substr( substr(trim(tltime+1000000),2,6),1,2),':'),substr(substr(trim(tltime+1000000),2,6),3,2)),':'), substr(substr (trim(tltime+1000000),2,6),5,2)))) as DATETIME 
            ,trim(concat(concat(concat(concat(concat(concat(concat(concat(concat(concat(trreas,'|'),trsr01),'|'),trsr02),'|'),trsr03),'|'),trsr04),'|'),trsr05)) as REASONS
            ,trim(concat(concat(concat(tnnot1,tnnot2),tnnot3),tnnot4)) as NOTES

from cabledta.tlogmstr left join cabledta.tlogreas on trnum#=tlnum#  left join cabledta.tlognote on tnnum#=tlnum#
            where tldate>='".$startDate."' and tldate <='".$endDate."'";

$res = $rr->execute($sql);

$response = array();

while ($row = $rr->fetchRow($res)){

$response[] = array(

'userName'      => $row['USER'],
                                'clientNumber'  => $row['CLIENT'],
                                'logDateTime'   => $row['DATETIME'],
                                'logReasons'    => $row['REASONS'],
                                'logNotes'      => utf8_encode($row['NOTES'])

);

}
    $rr->close_connection();

return $response;
}

Solution

iSeriesAccess for Linux 7.1 ODBC drivers is compiled for older versions of unixODBC that specify 32-bit SQLLEN. When your application or middleware (in this case, php) is compiled against a newer version of unixODBC (as of 2.2.14), 64-bit SQLLEN is used by default. Because the driver only overwrites the first 32 bits of data, the result of any API call that takes a SQLLEN pointer as a parameter in this case is undefined.

You have two options: recompile PHP and set up BUILD_LEGACY_64_BIT_MODE (-DBUILD_LEGACY_64_BIT_MODE) or use the new IBM i ODBC driver that uses 64-bit SQLLEN. You can find more information about the new ODBC driver included in the IBM i Access Client Solutions Linux application package in this article I wrote: http://www.ibm.com/developerworks/ibmi/library/i-ibmi-access-client-solutions-linux Nick mentioned in the above comment. You can find out how to download the driver here: http://iprodeveloper.com/blog/how-do-you-actually-get-access-client-solutions

Related Problems and Solutions