bug35572 Blocks appear to succeed w/DB error
authorsaper <saper@saper.info>
Fri, 30 Mar 2012 03:06:43 +0000 (05:06 +0200)
committerBrion Vibber <brion@pobox.com>
Tue, 10 Apr 2012 19:59:24 +0000 (12:59 -0700)
Bug 35572 - Blocks appear to succeed even if query fails due to wrong DB
structure

When emulating INSERT IGNORE ignore only SQL Error Code 23505
- unique key violation

http://www.postgresql.org/docs/9.1/interactive/errcodes-appendix.html

All other error codes (missing column, syntex error, whatever)
should unconditionally abort the transaction and show internal
error to the user.

Patchset 2: Fixed whitespace.
Patchset 3: More whitespace. And ()'s.
Patchset 4: Yet more whitespace.
Patchset 5: rebase & fix conflict in release-notes

Change-Id: Ic32bff9fff46bce124273156d224fa01b8adc008

RELEASE-NOTES-1.20
includes/db/DatabasePostgres.php

index 0e8cdc0..07145ae 100644 (file)
@@ -80,6 +80,7 @@ production.
   characters changed in a revision is now suppressed if no text would follow.
 * (bug 18704) Add a unique CSS class or ID to the tagfilter table row at RecentChanges
 * (bug 33564) transwiki import sometimes result in invalid title.
+* (bug 35572) Blocks appear to succeed even if query fails due to wrong DB structure
 
 === API changes in 1.20 ===
 * (bug 34316) Add ability to retrieve maximum upload size from MediaWiki API.
index 471dffa..d45217e 100644 (file)
@@ -322,16 +322,48 @@ class DatabasePostgres extends DatabaseBase {
                        $sql = mb_convert_encoding( $sql, 'UTF-8' );
                }
                $this->mTransactionState->check();
-               $this->mLastResult = pg_query( $this->mConn, $sql );
+               if( pg_send_query( $this->mConn, $sql ) === false ) {
+                       throw new DBUnexpectedError( $this, "Unable to post new query to PostgreSQL\n" );
+               }
+               $this->mLastResult = pg_get_result( $this->mConn );
                $this->mTransactionState->check();
                $this->mAffectedRows = null;
+               if ( pg_result_error( $this->mLastResult ) ) {
+                       return false;
+               }
                return $this->mLastResult;
        }
 
+       protected function dumpError () {
+               $diags = array( PGSQL_DIAG_SEVERITY,
+                               PGSQL_DIAG_SQLSTATE,
+                               PGSQL_DIAG_MESSAGE_PRIMARY,
+                               PGSQL_DIAG_MESSAGE_DETAIL,
+                               PGSQL_DIAG_MESSAGE_HINT,
+                               PGSQL_DIAG_STATEMENT_POSITION,
+                               PGSQL_DIAG_INTERNAL_POSITION,
+                               PGSQL_DIAG_INTERNAL_QUERY,
+                               PGSQL_DIAG_CONTEXT,
+                               PGSQL_DIAG_SOURCE_FILE,
+                               PGSQL_DIAG_SOURCE_LINE,
+                               PGSQL_DIAG_SOURCE_FUNCTION );
+               foreach ( $diags as $d ) {
+                       wfDebug( sprintf("PgSQL ERROR(%d): %s\n", $d, pg_result_error_field( $this->mLastResult, $d ) ) );
+               }
+       }
+
        function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) {
                /* Transaction stays in the ERROR state until rolledback */
+               if ( $tempIgnore ) {
+                       /* Check for constraint violation */
+                       if ( $errno === '23505' ) {
+                               parent::reportQueryError( $error, $errno, $sql, $fname, $tempIgnore );
+                               return;
+                       }
+               }
+               /* Don't ignore serious errors */
                $this->rollback( __METHOD__ );
-               parent::reportQueryError( $error, $errno, $sql, $fname, $tempIgnore );
+               parent::reportQueryError( $error, $errno, $sql, $fname, false );
        }
 
 
@@ -425,13 +457,21 @@ class DatabasePostgres extends DatabaseBase {
 
        function lastError() {
                if ( $this->mConn ) {
-                       return pg_last_error();
+                       if ( $this->mLastResult ) {
+                               return pg_result_error( $this->mLastResult );
+                       } else {
+                               return pg_last_error();
+                       }
                } else {
                        return 'No database connection';
                }
        }
        function lastErrno() {
-               return pg_last_error() ? 1 : 0;
+               if ( $this->mLastResult ) {
+                       return pg_result_error_field( $this->mLastResult, PGSQL_DIAG_SQLSTATE );
+               } else {
+                       return false;
+               }
        }
 
        function affectedRows() {