php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #36578 $stmt->fetch() on empty resultset does nothing
Submitted: 2006-03-01 19:59 UTC Modified: 2006-03-02 21:24 UTC
From: terry at bitsoup dot com Assigned:
Status: Not a bug Package: PDO related
PHP Version: 5.1.2 OS: Windows XP
Private report: No CVE-ID: None
 [2006-03-01 19:59 UTC] terry at bitsoup dot com
Description:
------------
A fetch against a statment that returns an empty resultset doesn't set any PDO error information, nor does it raise an exception.

Testing against MySQL 5.0.18

Reproduce code:
---------------
Database connection is successful, and mode is set to throw exceptions:

  try
  {
    $sth = $dbh->prepare("SELECT * from any_table where 1=2");
    $sth->execute();
    $row = $sth->fetch();
    echo "ERROR=" . $sth->errorCode();
  }
  catch (PDOException $e)
  {
    dbg("DB Error!: " . $e->getMessage());
    die();
  }

Expected result:
----------------
Either 

ERROR=20

when not using exceptions, or an exception.



Actual result:
--------------
ERROR=00

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-03-01 20:01 UTC] terry at bitsoup dot com
Sorry, error code should be 02, not 20
 [2006-03-02 08:42 UTC] tony2001@php.net
Empty resultset is not an error, it's a common situation.
No bug here.
 [2006-03-02 17:25 UTC] terry at bitsoup dot com
The empty resultset is not the error. Calling fetch() on an empty resultset sets the error code to a warning and/or generates an exception in every database engine I've seen.

In Oracle, it's error ORA-1403: no data found.
It's SQL_NODATA in ODBC drivers.
I believe it's Error 2053 in MySQL. mysql_stmt_fetch() returns MYSQL_NO_DATA, and not 0 for success.

In it's current state, fetch() returning null without raising the exception means we'll have to add the test and throw the exception manually on every single query.
 [2006-03-02 17:51 UTC] tony2001@php.net
$s = oci_parse($c, "select 1 from dual where 1 = 2"); 
oci_execute($s); 
var_dump(oci_fetch($s));
=>
bool(false) and no error.
 [2006-03-02 19:51 UTC] terry at bitsoup dot com
That's because you are currently discarding the error in oci8. You have it on the TODO list to handle the fetch case properly.

	if ((statement->error == OCI_NO_DATA) || (nrows == 0)) {
		if (statement->last_query == 0) {
			/* reset define-list for refcursors */
			if (statement->columns) {
				zend_hash_destroy(statement->columns);
				efree(statement->columns);
				statement->columns = 0;
				statement->ncolumns = 0;
			}
			statement->executed = 0;
		}

		statement->error = 0; /* OCI_NO_DATA is NO error for us!!! */
		statement->has_data = 0;

		return 0;
	}
 [2006-03-02 19:58 UTC] tony2001@php.net
> statement->error = 0; /* OCI_NO_DATA is NO error for us!!! */
This line talks for itself.

>You have it on the TODO list to handle the fetch case properly.
No, I don't have such item in my TODO list.

Please stop reopening this report.
If you consider such case as an error - you have to handle it yourself, while others will continue using usual semantics - error is error and "no data" is just no data.
 [2006-03-02 20:49 UTC] terry at bitsoup dot com
I'm just going to assume you don't want to fix broken functionality with the way fetch() is handled. Since I can't convince you, you should refer to the ANSI SQL standard to see how NO_DATA_FOUND is properly handled.

In php_oci_error(), the case OCI_NO_DATA exists, but I can't see any place it's being called from. I supplied the example code that shows where it's being circumvented, though.

It makes sense to suppress the error when you don't have exception handling, but it's being handled incorrectly in PHP5.

In oci8.c for 5.1.0-RC1, the TO-DO list has the line 
 * - Change return-value for OCIFetch*() (1-row read, 0-Normal end, false-error) . That's why I mentioned being in the TO-DO list. It's no longer there.

begin
select 1 from dual where 1=2;
exception
when NO_DATA_FOUND then
  do_stuff();
end;
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Mon Mar 01 07:01:23 2021 UTC