|   | php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
| 
  [2005-11-25 11:38 UTC] slapaf at hotmail dot com
 Description:
------------
When using PDO for simple query in Firebird it returns first row as null.
I've tried using ADODB for control and it returns the correct results. 
Reproduce code:
---------------
$dbh = new PDO("firebird:dbname=localhost:test.fdb","****","******");
	$sql='SELECT EVENT_NAME FROM EVENTS';
	foreach($dbh->query($sql) as $row){
		print '<pre>'.gettype($row['EVENT_NAME']).' : '.$row['EVENT_NAME'];
	}
Expected result:
----------------
string : name 1
string : name 2
string : name 3
string : name 4
Actual result:
--------------
NULL : 
string : name 2
string : name 3
string : name 4
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits             | |||||||||||||||||||||||||||||||||||||
|  Copyright © 2001-2025 The PHP Group All rights reserved. | Last updated: Fri Oct 31 08:00:01 2025 UTC | 
same problem on linux, php 5.1.2 I tried to debug the problem, but imho the problem is strange. The reason why the first row is null is as following: file: ext/pdo/pdo_stmt.c line: 532 <code> case PDO_PARAM_STR: if (value && !(value_len == 0 && stmt->dbh->oracle_nulls == PDO_NULL_EMPTY_STRING)) { ZVAL_STRINGL(dest, value, value_len, !caller_frees); if (caller_frees) { caller_frees = 0; } break; } default: ZVAL_NULL(dest); </code> With the first returned row from DB the first if clause above evaluates to false. so ZVAL_NULL is called. thats the reason for the null values in the first result set. Normally should "value" point to the argument "ptr" of the firebird_stmt_get_col function (in firebird_statement.c). gdp says that ptr is filled with the data out of DB properly. So why is "value" not the same as "ptr" and why is this only in the first result set?? greetz ThomasCrazy solution, but it works: $stmt = $db->prepare('SELECT * FROM table WHERE 2>?'); $stmt->execute(array(1)); while($radek = $stmt->fetch()) print_r($radek); All rows will be printed on the screen including the first. When you use "prepare statement" with one or more parameters, you get all rows. P.S: Srry for my bad english.I have met the same problem. OS : Windows XP SP2 PHP: 5.2.3 Firebird : WI-V6.3.1.12855 Firebird 2.0 I have a simple table named school in my database, the CREATE TABLE statement is as below : CREATE TABLE school ( school_code SMALLINT PRIMARY KEY, school_name VARCHAR(40) NOT NULL, short_name VARCHAR(20) ); And there were total 14 rows in the table, the school_code was from 1 to 14. When I submitted such a simple query "SELECT * FROM school order by school_code ASC " to the Firebird Server using PDO, the first row it returned is NULL,NULL,NULL, while the rest rows can be returned correctly. In other words only the first row in which the field 'school_code' should be 1 was not right. Then I tested another query "SELECT * FROM school order by school_code DESC ", this time the field 'school_code' in the first row should be 14, however, the result of the first row was still NULL,NULL,NULL, while other rows was returned correctly, even the row in which the field 'school_code' was 1. I have tested the following PDO functions : 1.foreach ( $conn->query($query) as $row ) print_r( $row ); 2.$rs=$conn->query($query); while( $row=$rs->fetch( ) ) print_r( $row ); 3.$rs=$conn->query($query); $data=$rs->fetchall( ); foreach( $data as $row ) print_r( $row ); I met the same problem in every test. So, I tried to access Firebird directly. I used the ibase_* functions to query the same SQL statement, every row was returned correctly. And, I have to use PDO to maintain my code in the future, so I tried to access firebird database via ODBC. This time, I also submitted the same query using PDO, fortunately, there was no error. Therefore, I can continue my work with PDO/ODBC/Firebird. I think I can change the PDO DSN if this bug was corrected in the future. So, I think there must be something wrong in the Firebird PDO driver. I hope this problem will be solved as soon as possible. Brook Dong Peng from China 2007-8-20System : Windows NT 5.1 build 2600 (MS Windows XP SP2) Apache 2.0 PHP 5.1.2 & 5.2.3 I tried several methods : PDOStatement->fetchAll(), PDOStatement->fetch(), PDO->query() with arguments : PDO::FETCH_NUM, PDO::FETCH_ASSOC, PDO::FETCH_LAZY, PDO::FETCH_COLUMN, PDO::FETCH_GROUP same result : First row is missing Array ( [LAN_ID] => [LAN_NAME_EN] => [LAN_CODE] => ) Array ( [LAN_ID] => 2 [LAN_NAME_EN] => FRENCH [LAN_CODE] => FR ) Array ( [LAN_ID] => 3 [LAN_NAME_EN] => ENGLISH [LAN_CODE] => EN ) I tried with different tables and select statements and I always got the same result. As it seems to be a pretty obvious bug/error, could it be corrected in the next release (of PHP), please ?Well, tried to dig into this ... After some trial and error, I found this little quick and dirty trick, which solves (or rather works around) another quick and dirty trick ... Try this in etc/pdo_firebird/firebird_statement.c: /* called by PDO to retrieve information about the fields being returned */ static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) /* {{{ */ { pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; struct pdo_column_data *col = &stmt->columns[colno]; XSQLVAR *var = &S->out_sqlda.sqlvar[colno]; /* allocate storage for the column */ var->sqlind = (void*)emalloc(var->sqllen + 2*sizeof(short)); var->sqldata = &((char*)var->sqlind)[sizeof(short)]; col->precision = -var->sqlscale; col->maxlen = var->sqllen; col->namelen = var->aliasname_length; col->name = estrndup(var->aliasname,var->aliasname_length); /* ==================================================== * Compensates for hack in another function: * Force data-type in column to string */ col->param_type = PDO_PARAM_STR; /* ================================================= */ return 1; } /* }}} */ The same hack is found in same module, in another function, but AFTER the columntype is set for the first row - hence it works for the subsequent rows ... static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ */ unsigned long *len, int *caller_frees TSRMLS_DC) { pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; XSQLVAR const *var = &S->out_sqlda.sqlvar[colno]; if (*var->sqlind == -1) { /* A NULL value */ *ptr = NULL; *len = 0; } else { /* override the column param type */ /* set_param_type(&stmt->columns[colno].param_type,var); */ =====> stmt->columns[colno].param_type = PDO_PARAM_STR; if (var->sqlscale < 0) { static ISC_INT64 const scales[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 100000000, 1000000000, 1000000000, LL_LIT(10000000000),LL_LIT(100000000000), The row pointed to above (=====>) could/should be removed, as columntype definition _should_ be handled in firebird_stmt_describe() function (where my hack resides). I have tested this with PHP 5.2.4 on Fedora Core 7 - and this hack works. I miss the total overview of PDO, so I can't reactivate the code-parts originally handling conversion from native Firebird/Interbase sql-type to PDO datatype constants. But this work should be done. If I have/get the time, and come to understand the code better, I would be happy to contribute. For now I hope the above can help anyone, who compile the source, and that this quick and dirty hack can make it into the next release (5.2.5?) of PHP. It works, but is not the long term solution, I think. Greetings, Lars