Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

firebird exception with php 7.0.3 #231

Closed
mawouzo opened this issue Apr 23, 2016 · 18 comments
Closed

firebird exception with php 7.0.3 #231

mawouzo opened this issue Apr 23, 2016 · 18 comments
Labels
interbase Interbase Driver (Tier 2) no change required PHP7 PHP 7.x compatibility issues

Comments

@mawouzo
Copy link

mawouzo commented Apr 23, 2016

this exception is thrown with php 7.0.3 but works well with 7.0.0

PHP Warning: ibase_query(): supplied resource is not a valid Firebird/InterBase link resource in lib\adodb\drivers\adodb-ibase.inc.php on line 378
PHP Fatal error: Uncaught ADODB_Exception: firebird error: [0: ] in EXECUTE("Select * from xxx where x = ? ") in lib\adodb\adodb-exceptions.inc.php:80

@dregad dregad added bug interbase Interbase Driver (Tier 2) PHP7 PHP 7.x compatibility issues labels Apr 23, 2016
@dregad
Copy link
Member

dregad commented Apr 23, 2016

Which version of ADOdb are you using ?
Can you provide some sample code to reproduce the problem ?

@mawouzo
Copy link
Author

mawouzo commented Apr 24, 2016

I use ADOdb 5.20.4 on Windows 2012 / IIS also the same an windows 2008/ IIS

I use a class-system for db access so I did extract the important code to reproduce the error.

class mawDB {
/*****************************************************/
function __construct() {
      $this->db = ADONewConnection('firebird');
      $this->db->debug = true;
      $this->db->dialect = 3;
      $this->db->charSet = 'UTF8';
      $this->db->Connect($servername . ':' . $databasefile ,$username,$password);
      $this->db->SetFetchMode(ADODB_FETCH_ASSOC);
   }
}

class mawDBChild1 extends mawDB {
public function select() {
   $rs = $this->db->GetRow('Select * from Table1');
}
}

class mawDBChild2 extends mawDB {
public function select() {
   $rs = $this->db->GetRow('Select * from table2');

}
}


$mawDb1  = new mawDBChild1();
$mawDb2  = new mawDBChild2();
$mawDb1->select();

This Code works on php 7.0.0 and throws an exception in php 7.0.3 and later versions.

PHP Warning: ibase_query(): supplied resource is not a valid Firebird/InterBase link resource in C:\webs...\adodb\drivers\adodb-ibase.inc.php on line 392

So I did chnage the code:

$mawDb1 = new mawDBChild1();
echo var_dump_pre($mawDb1->db);
$mawDb2 = new mawDBChild2();
echo var_dump_pre($mawDb1->db);

In the first dump
["_connectionID"]=>
resource(8) of type (Firebird/InterBase link)

In the second dump
["_connectionID"]=>
resource(8) of type (Unknown)

I think this is the reason for the exception.

@mawouzo mawouzo closed this as completed Apr 24, 2016
@mawouzo mawouzo reopened this Apr 24, 2016
@mawouzo
Copy link
Author

mawouzo commented Apr 24, 2016

sorry, wrong button clicked.

@mnewnham
Copy link
Contributor

mnewnham commented Apr 24, 2016

Is it possible that this problem with PHP is the cause of your problem. Perhaps you could try with PHP 7.0.5?
EDIT
Looking at this again the problem was said to have been fixed in 7.0.3, so maybe this fix has introduced a regression bug into PHP. I would suggest:

  1. Trying this test with PHP 7.0.2 to determine when the behavior changes.
  2. Writing some test code, bypassing ADOdb entirely to see if the behavior can be duplicated with pure PHP

@mawouzo
Copy link
Author

mawouzo commented Apr 25, 2016

  1. Its still the same with 7.0.5
  2. I cannot find anywhere 7.0.2 windows binaries
  3. I did test this:
    $db = ibase_connect($servername . ':' . $databasefile ,$username,$password);
    $db2 = ibase_connect($servername . ':' . $databasefile ,$username,$password);
    $q = ibase_query($db,"Select * from Table1");
    $q2 = ibase_query($db2,"Select * from Table1");

This throws an exception in 7.0.3 and works with 7.0.5 , so I think this is not the problem.

  1. As I writing before, I think the problem is that the ADOdb Connection Object lose his connection ID after a second Connection is oppened. See in my first example the var_dump_pre($mawDb1->db);
    is called twice ,but have different entrys for the _connectionID

@mnewnham
Copy link
Contributor

I think you are going to need to write a simple, pure php routine bypassing the ADOdb driver. If you are getting issues like the one above where the version of PHP affects the results of the code, then it is more than likely a problem with PHP itself.

If in fact it is ADOdb that has the issue, then the php code you provide could help us determine the cause of the issue.

@mawouzo
Copy link
Author

mawouzo commented Apr 26, 2016

I think you are going to need to write a simple, pure php routine bypassing the ADOdb driver.

Without ADOdb I cannot reproduce the error

If in fact it is ADOdb that has the issue, then the php code you provide could help us determine the cause of the issue.

Look at my second post, there you will find an example.

@dregad
Copy link
Member

dregad commented May 26, 2016

Hi @mawouzo

I finally got around to setting up Firebird on a PHP 7.0.4 test environment (on Ubuntu 16.10) to investigate this issue. I can indeed replicate the behavior you describe:

include('adodb.inc.php');
$servername = 'localhost';
$databasefile = 'employee';
$username = 'SYSDBA';
$password = 'masterkey';
$sql = 'select * from country';

function init() {
    global $servername, $databasefile, $username, $password;
    $db = ADONewConnection('firebird');
    $db->dialect = 3;
    $db->charSet = 'UTF8';
    $db->Connect($servername . ':' . $databasefile, $username, $password);
    $db->SetFetchMode(ADODB_FETCH_ASSOC);
    $db->debug = true;
    return $db;
}

$d1 = init();
$d2 = init();
print_r($d1->getRow($sql));

Fails with

PHP Warning:  fbird_query(): supplied resource is not a valid Firebird/InterBase link resource in /home/dregad/dev/adodb/drivers/adodb-firebird.inc.php on line 387
0: 
        ADOConnection._Execute(select * from country, false)% line  183, file: /home/dregad/dev/adodb/drivers/adodb-firebird.inc.php
    ADODB_firebird._Execute(select * from country, false)% line 1246, file: /home/dregad/dev/adodb/adodb.inc.php
ADOConnection.Execute(select * from country, false)% line 1891, file: /home/dregad/dev/adodb/adodb.inc.php
ADOConnection.GetRow(select * from country)% line    1, file: php shell code

Looking at what happens to the connection:

echo "**** Open connection 1\n";
$d1 = init(); var_dump($d1->_connectionID);
echo "**** Open connection 2\n";
$d2 = init(); var_dump($d1->_connectionID, $d2->_connectionID);

After opening the 2nd connection, the 1st one is no longer valid (as you pointed out before)

**** Open connection 1
resource(10) of type (Firebird/InterBase link)
**** Open connection 2
resource(10) of type (Unknown)                             <<<<< THIS IS THE ISSUE
resource(11) of type (Firebird/InterBase link)

So far, we're on the same page. Now let's try to get ADOdb out of the equation, as per @mnewnham's suggestion:

I think you are going to need to write a simple, pure php routine bypassing the ADOdb driver.

Without ADOdb I cannot reproduce the error

Well...

echo "**** Open connection 1\n"; $d1 = ibase_connect("$servername:$databasefile", $username, $password); var_dump($d1);
echo "**** Open connection 2\n"; $d2 = ibase_connect("$servername:$databasefile", $username, $password); var_dump($d1, $d2);
**** Open connection 1
resource(5) of type (Firebird/InterBase link)
**** Open connection 2
resource(5) of type (Unknown)                             <<<<< BINGO !
resource(6) of type (Firebird/InterBase link)

This proves that ADOdb has absolutely nothing to do with this error, it is a problem with PHP's interbase driver. Since the same code works just fine on PHP 5.6 (and according to you on PHP 7.0.0 as well, although I did not test that), I would assume that something was changed in the driver.

I did a quick Google search to see if anyone else had experienced the same issue, and found this, which was opened a few days after your reported your issue here. The problem has also been logged on Launchpad (#1578600) and also upstream (PHP #72175).

Since I've demonstrated that this is not an ADOdb issue, I will close this, and encourage you to monitor the upstream bugs.

@dregad dregad closed this as completed May 26, 2016
@dregad
Copy link
Member

dregad commented May 26, 2016

As pointed out on the StackOverflow question, this commit php/php-src@8bfa519 may be the one that introduced the bug (in release php-7.0.3RC1)

@NetVicious
Copy link

On launchpad (#1578600) the bug has been found and fixed.

Waiting for the upstream fix.

@dregad
Copy link
Member

dregad commented Jun 29, 2016

Thanks for the update

@mawouzo
Copy link
Author

mawouzo commented Feb 6, 2017

I will come back to this issue because this error is still alive in the windows php 7.1.0.

in this discussion https://bugs.php.net/bug.php?id=72175 you can read that nobody really wants or can fix this. All my projects use AdoDB for Firebird and the way to update to php 7 is so not possible.
Does anybody see a way to get this bug fixed ?
Is it maybe possible to make a PDO_firebird driver ?

@dregad
Copy link
Member

dregad commented Feb 6, 2017

Does anybody see a way to get this bug fixed ?

Not possible within ADOdb, sorry.

Is it maybe possible to make a PDO_firebird driver ?

Contributions are welcome. Don't hesitate to submit a pull request !

@NetVicious
Copy link

NetVicious commented Feb 6, 2017

I'm using a class to do all the database operations, and I fixed this problem in my code using static variables to store the connection to the database.

In my code I'm doing several connections to database due to chains of php calls, all of the connections use the same library.


class ps_DB {
  
	private static $lid = 0;
....

@mnewnham
Copy link
Contributor

mnewnham commented Feb 6, 2017

@NetVicious , if you could provide us with a bigger code snippet, perhaps we could add it to the firebird ADOdb page with a pointer to this thread

@NetVicious
Copy link

Hi mnewnham!

My class it's a simple class for do BD actions. It was ripped from an old mysql class and changed to work with firebird.

The original one for mysql it's this http://www.servielectronico.com/PhpShop/db/db_mysql.inc

@mawouzo
Copy link
Author

mawouzo commented Feb 23, 2017

@NetVicious
Sorry, but this link doesn't work.

@NetVicious
Copy link

NetVicious commented Feb 24, 2017

I got it from the Google cache ;-)

Remember this script it's the original for mysql I modified to work with Firebird/Interbase.
It needs constants for the DB_HOST,DB_USER,DB_PWD.

Fee free to modify it to work with adoDB, and remember to modify the $lid variable definition to private static $lid = 0 to avoid the problem we have on the php.

<?php
/*
 *
 * Copyright (c) Edikon Corporation.  All rights reserved.
 * Distributed under the phpShop Public License (pSPL) Version 1.0.
 *
 * $Id: db_mysql.inc,v 1.2 2000/09/03 19:19:42 pfmartin Exp $
 *
 */


/***********************************************************************

mySQL Database Access Class

Heavily based on the PHPLIB database access class available at 
http://phplib.netuse.de.

We use only a subset of the functions available in PHPLIB and their syntax is 
exactly the same.  This makes working with previous version of phpShop seamless
and keeps a consistent API for database access.  

Methods in the class are:

query($q) - Established connection to database and runs the query returning 
            a query ID if successfull.

next_record() - Returns the next row in the RecordSet for the last query run.  
                Returns False if RecordSet is empty or at the end.

num_rows()  -Returns the number of rows in the RecordSet from a query.

f($field_name) - Returns the value of the given field name for the current
                 record in the RecordSet.  

sf($field_name) - Returns the value of the field name from the $vars variable
                  if it is set, otherwise returns the value of the current
		  record in the RecordSet.  Useful for handling forms that have
		  been submitted with errors.  This way, fields retain the values 
		  sent in the $vars variable (user input) instead of the database
		  values.

p($field_name) - Prints the value of the given field name for the current
                 record in the RecordSet.

sp($field_name) - Prints the value of the field name from the $vars variable
                  if it is set, otherwise prints the value of the current
		  record in the RecordSet.  Useful for handling forms that have
		  been submitted with errors.  This way, fields retain the values 
		  sent in the $vars variable (user input) instead of the database
		  values.


************************************************************************/


class ps_DB {
  
  var $lid = 0;             	// Link ID for database connection
  var $qid = 0;			// Query ID for current query
  var $row;			// Current row in query result set
  var $record = array();	// Current row record data
  var $error = "";		// Error Message
  var $errno = "";		// Error Number



  // Connects to DB and returns DB lid 
  // PRIVATE
  function connect() { 

    if ($this->lid == 0) {
      $this->lid = mysql_pconnect(DB_HOST,DB_USER,DB_PWD); 
      if (!$this->lid) {
	$this->halt("connect(" . DB_HOST . "," . DB_USER . ",DB_PWD)  failed.");
      } 
      
      if (!@mysql_select_db(DB_NAME,$this->lid)) {
	$this->halt("Cannot connect to database ".DB_NAME);
	return 0;
      }
    }
    return $this->lid;
  }


  // Runs query and sets up the query id for the class.
  // PUBLIC
  function query($q) {
    
    if (empty($q))
      return 0;
    
    if (!$this->connect()) {
      return 0; 
    }
    
    if ($this->qid) {
      @mysql_free_result($this->qid);
      $this->qid = 0;
    }
    
    $this->qid = @mysql_query($q, $this->lid);
    $this->row   = 0;
    $this->errno = mysql_errno();
    $this->error = mysql_error();
    if (!$this->qid) {
      $this->halt("Invalid SQL: ".$q);
    }

    return $this->qid;
  }
  

  // Return next record in result set
  // PUBLIC
  function next_record() {

    if (!$this->qid) {
      $this->halt("next_record called with no query pending.");
      return 0;
    }
    
    $this->record = @mysql_fetch_array($this->qid);
    $this->row   += 1;
    $this->errno  = mysql_errno();
    $this->error  = mysql_error();
    
    $stat = is_array($this->record);
    return $stat;
  }
  

  // Field Value
  // PUBLIC
  function f($field_name) {
    return stripslashes($this->record[$field_name]);
  }

  // Selective field value
  // PUBLIC
  function sf($field_name) {
    global $vars, $default;

    if ($vars["error"] and $vars["$field_name"]) {
      return stripslashes($vars["$field_name"]);
    } elseif ($default["$field_name"]) {
      return stripslashes($default["$field_name"]);
    } else {
      return stripslashes($this->record[$field_name]);
    }
  }                             

  // Print field
  // PUBLIC
  function p($field_name) {
      print stripslashes($this->record[$field_name]);
  }                             

  // Selective print field
  // PUBLIC
  function sp($field_name) {
    global $vars, $default;

    if ($vars["error"] and $vars["$field_name"]) {
      print stripslashes($vars["$field_name"]);
    } elseif ($default["$field_name"]) {
      print stripslashes($default["$field_name"]);
    } else {
      print stripslashes($this->record[$field_name]);
    }
  }                          

  // Returns the number of rows in query
  function num_rows() { 
    
    if ($this->lid) { 
      return @mysql_numrows($this->qid); 
    } 
    else { 
      return 0; 
    } 
  }



  

  // Halt and display error message
  // PRIVATE
  function halt($msg) {
    $this->error = @mysql_error($this->lid);
    $this->errno = @mysql_errno($this->lid);

    printf("</td></tr></table><b>Database error:</b> %s<br>\n", $msg);
    printf("<b>MySQL Error</b>: %s (%s)<br>\n",
	   $this->errno,
	   $this->error);
    
    exit;

  }

}
?>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interbase Interbase Driver (Tier 2) no change required PHP7 PHP 7.x compatibility issues
Projects
None yet
Development

No branches or pull requests

4 participants