(bug 18909) Add missing INSERT SELECT wrapper for Postgres
authorOverlordQ <overlordq@users.mediawiki.org>
Tue, 27 Oct 2009 05:33:31 +0000 (05:33 +0000)
committerOverlordQ <overlordq@users.mediawiki.org>
Tue, 27 Oct 2009 05:33:31 +0000 (05:33 +0000)
RELEASE-NOTES
includes/db/DatabasePostgres.php

index 0b5de5a..1650305 100644 (file)
@@ -601,6 +601,7 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 * User::isValidPassword now only returns boolean results, User::getPasswordValidity
   can be used to get an error message string
 * The error message shown in Special:ChangePassword now parses wiki markup
+* (bug 18909) Add missing Postgres INSERT SELECT wrapper
 
 == API changes in 1.16 ==
 
index fa96efe..fcdb94f 100644 (file)
@@ -873,6 +873,81 @@ class DatabasePostgres extends DatabaseBase {
 
        }
 
+       /**
+        * INSERT SELECT wrapper
+        * $varMap must be an associative array of the form array( 'dest1' => 'source1', ...)
+        * Source items may be literals rather then field names, but strings should be quoted with Database::addQuotes()
+        * $conds may be "*" to copy the whole table
+        * srcTable may be an array of tables.
+        * @todo FIXME: implement this a little better (seperate select/insert)?
+       */
+       function insertSelect( $destTable, $srcTable, $varMap, $conds, $fname = 'DatabasePostgres::insertSelect',
+               $insertOptions = array(), $selectOptions = array() )
+       {
+               $destTable = $this->tableName( $destTable );
+
+               // If IGNORE is set, we use savepoints to emulate mysql's behavior
+               $ignore = in_array( 'IGNORE', $insertOptions ) ? 'mw' : '';
+
+               if( is_array( $insertOptions ) ) {
+                       $insertOptions = implode( ' ', $insertOptions );
+               }
+               if( !is_array( $selectOptions ) ) {
+                       $selectOptions = array( $selectOptions );
+               }
+               list( $startOpts, $useIndex, $tailOpts ) = $this->makeSelectOptions( $selectOptions );
+               if( is_array( $srcTable ) ) {
+                       $srcTable = implode( ',', array_map( array( &$this, 'tableName' ), $srcTable ) );
+               } else {
+                       $srcTable = $this->tableName( $srcTable );
+               }
+
+               // If we are not in a transaction, we need to be for savepoint trickery
+               $didbegin = 0;
+               if ( $ignore ) {
+                       if( !$this->mTrxLevel ) {
+                               $this->begin();
+                               $didbegin = 1;
+                       }
+                       $olde = error_reporting( 0 );
+                       $numrowsinserted = 0;
+                       pg_query( $this->mConn, "SAVEPOINT $ignore");
+               }
+
+               $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' .
+                               " SELECT $startOpts " . implode( ',', $varMap ) .
+                               " FROM $srcTable $useIndex";
+
+               if ( $conds != '*') {
+                       $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
+               }
+
+               $sql .= " $tailOpts";
+
+               $res = (bool)$this->query( $sql, $fname, $ignore );
+               if( $ignore ) {
+                       $bar = pg_last_error();
+                       if( $bar != false ) {
+                               pg_query( $this->mConn, "ROLLBACK TO $ignore" );
+                       } else {
+                               pg_query( $this->mConn, "RELEASE $ignore" );
+                               $numrowsinserted++;
+                       }
+                       $olde = error_reporting( $olde );
+                       if( $didbegin ) {
+                               $this->commit();
+                       }
+
+                       // Set the affected row count for the whole operation
+                       $this->mAffectedRows = $numrowsinserted;
+
+                       // IGNORE always returns true
+                       return true;
+               }
+
+               return $res;
+       }
+       
        function tableName( $name ) {
                # Replace reserved words with better ones
                switch( $name ) {