php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #43246 firebird: INSERT ... RETURNING ... throws exception
Submitted: 2007-11-11 14:24 UTC Modified: 2007-11-19 22:19 UTC
From: hp-php dot net at oeri dot ch Assigned:
Status: Closed Package: PDO related
PHP Version: 5.3CVS-2007-11-11 (CVS) OS: Linux 2.6
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: hp-php dot net at oeri dot ch
New email:
PHP Version: OS:

 

 [2007-11-11 14:24 UTC] hp-php dot net at oeri dot ch
Description:
------------
Executing (prepared or directly) an "INSERT ... RETURNING" throws an exception

Reproduce code:
---------------
<?php

$pdo = new PDO( 'firebird:dbname=localhost:devel', 'devel', 'devel' );
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
	
// VARIANT A: ORDINARY INSERT
$stmt = $pdo->query( 'INSERT INTO "a" ("data") VALUES (2500)' );
echo "Variant 'A': done";

// VARIANT B: RETURNING INSERT
$stmt = $pdo->query( 'INSERT INTO "a" ("data") VALUES (2500) RETURNING "data"' );
$res = $stmt->fetchAll( PDO::FETCH_ASSOC );
print_r( $res );
echo "Variant 'B': done";

?>

Expected result:
----------------
Variant 'A': done
Variant 'B': done

(Both statements executed)


Actual result:
--------------
Variant 'A': done<br />
<b>Fatal error</b>:  Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: -804 Dynamic SQL Error SQL error code = -804 Incorrect values within SQLDA structure ' in PHPDocument4:11
Stack trace:
#0 PHPDocument4(11): PDO-&gt;query('INSERT INTO &quot;a&quot;...')
#1 /var/www/devel/htdocs/dummy.php(1): include('PHPDocument4')
#2 {main}
  thrown in <b>PHPDocument4</b> on line <b>11</b><br />


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-11-12 12:49 UTC] hp-php dot net at oeri dot ch
INSERT ... RETURNING works fine with pdo_pgsql. An "indice" for a problem within pdo_firebird (and not pdo itself).
 [2007-11-12 16:05 UTC] hp-php dot net at oeri dot ch
Although I'm not a C master, I've looked through the code and found:

pdo_statement.c:
/* an EXECUTE PROCEDURE statement can be fetched from once, without calling the API, because
 * the result was returned in the execute call */

That's totally contrary to the docs and source of this bug. As it is, RETURNING querys get classified as "procedures". Cleaning pdo_statement.c of this "special" behaviour, solves the bug! Below, you find a minimally intrusive patch (as I don't know how to attach in here):

diff -u php5-orig/ext/pdo_firebird/firebird_statement.c php5/ext/pdo_firebird/firebird_statement.c
--- php5-orig/ext/pdo_firebird/firebird_statement.c     2007-11-12 16:59:34.000000000 +0100
+++ php5/ext/pdo_firebird/firebird_statement.c  2007-11-12 16:58:46.000000000 +0100
@@ -99,11 +99,15 @@

                /* assume all params have been bound */

+#if 0
                if ((S->statement_type == isc_info_sql_stmt_exec_procedure &&
                                isc_dsql_execute2(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION,
                                        S->in_sqlda, &S->out_sqlda))
                                || isc_dsql_execute(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION,
                                        S->in_sqlda)) {
+#else
+               if (isc_dsql_execute(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION, S->in_sqlda)) {
+#endif
                        break;
                }

@@ -138,9 +142,11 @@

                /* an EXECUTE PROCEDURE statement can be fetched from once, without calling the API, because
                 * the result was returned in the execute call */
+#if 0
                if (S->statement_type == isc_info_sql_stmt_exec_procedure) {
                        S->exhausted = 1;
                } else {
+#endif
                        if (isc_dsql_fetch(H->isc_status, &S->stmt, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) {
                                if (H->isc_status[0] && H->isc_status[1]) {
                                        RECORD_ERROR(stmt);
@@ -148,7 +154,9 @@
                                S->exhausted = 1;
                                return 0;
                        }
+#if 0
                }
+#endif
                return 1;
        }
        return 0;
 [2007-11-15 18:48 UTC] hp at oeri dot ch
Path against the latest CVS version:

http://php.pastebin.com/f4184b130
 [2007-11-15 21:08 UTC] hp at oeri dot ch
There seems to be no possibility to differentiate singleton queries from recordset (execute procedure can return recordsets, no?).

The best solution - conforming to docs - is:


http://php.pastebin.com/f748ad795


Specification:
a) everything returns only by "fetch"
b) "procedure" can only fetch one row
c) "fetch" on something else than "select"/"procedure" does not segfault
 [2007-11-19 22:19 UTC] lwe@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

Fixed in PHP_5_3
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Mon Jun 02 18:01:26 2025 UTC