From d46dd02c8104baaaaf7da6614777283c5f917492 Mon Sep 17 00:00:00 2001 From: OverlordQ Date: Tue, 27 Oct 2009 05:33:31 +0000 Subject: [PATCH] (bug 18909) Add missing INSERT SELECT wrapper for Postgres --- RELEASE-NOTES | 1 + includes/db/DatabasePostgres.php | 75 ++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 0b5de5a535..1650305034 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -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 == diff --git a/includes/db/DatabasePostgres.php b/includes/db/DatabasePostgres.php index fa96efe156..fcdb94fb5f 100644 --- a/includes/db/DatabasePostgres.php +++ b/includes/db/DatabasePostgres.php @@ -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 ) { -- 2.20.1