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
 [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

Add a Patch

Pull Requests

Add a Pull Request

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-2019 The PHP Group
All rights reserved.
Last updated: Tue Aug 20 14:01:47 2019 UTC