Fix some postgres test failures
authorAaron Schulz <aschulz@wikimedia.org>
Wed, 10 May 2017 01:27:28 +0000 (18:27 -0700)
committerKrinkle <krinklemail@gmail.com>
Wed, 10 May 2017 01:59:47 +0000 (01:59 +0000)
Bug: T75174
Change-Id: If9812ae301f0af84fa012e2e980b92036c1b29b2

includes/libs/rdbms/database/DBConnRef.php
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/database/DatabasePostgres.php
includes/libs/rdbms/database/IDatabase.php
tests/phpunit/includes/api/ApiQueryWatchlistIntegrationTest.php
tests/phpunit/includes/db/LBFactoryTest.php

index c15572c..b6167aa 100644 (file)
@@ -349,6 +349,10 @@ class DBConnRef implements IDatabase {
                return $this->__call( __FUNCTION__, func_get_args() );
        }
 
+       public function databasesAreIndependent() {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+
        public function selectDB( $db ) {
                return $this->__call( __FUNCTION__, func_get_args() );
        }
index 3bb7e6a..3de86ac 100644 (file)
@@ -1691,6 +1691,10 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                return $field;
        }
 
+       public function databasesAreIndependent() {
+               return false;
+       }
+
        public function selectDB( $db ) {
                # Stub. Shouldn't cause serious problems if it's not overridden, but
                # if your database engine supports a concept similar to MySQL's
index b92d072..6cf890d 100644 (file)
@@ -105,7 +105,10 @@ class DatabasePostgres extends Database {
                $this->mDBname = $dbName;
 
                $connectVars = [
-                       'dbname' => $dbName,
+                       // pg_connect() user $user as the default database. Since a database is *required*,
+                       // at least pick a "don't care" database that is more likely to exist. This case
+                       // arrises when LoadBalancer::getConnection( $i, [], '' ) is used.
+                       'dbname' => strlen( $dbName ) ? $dbName : 'postgres',
                        'user' => $user,
                        'password' => $password
                ];
@@ -165,11 +168,16 @@ class DatabasePostgres extends Database {
                return $this->mConn;
        }
 
+       public function databasesAreIndependent() {
+               return true;
+       }
+
        /**
         * Postgres doesn't support selectDB in the same way MySQL does. So if the
         * DB name doesn't match the open connection, open a new one
         * @param string $db
         * @return bool
+        * @throws DBUnexpectedError
         */
        public function selectDB( $db ) {
                if ( $this->mDBname !== $db ) {
index ac9914b..bec26a6 100644 (file)
@@ -1029,11 +1029,25 @@ interface IDatabase {
         */
        public function buildStringCast( $field );
 
+       /**
+        * Returns true if DBs are assumed to be on potentially different servers
+        *
+        * In systems like mysql/mariadb, different databases can easily be referenced on a single
+        * connection merely by name, even in a single query via JOIN. On the other hand, Postgres
+        * treats databases as fully separate, only allowing mechanisms like postgres_fdw to
+        * effectively "mount" foreign DBs. This is true even among DBs on the same server.
+        *
+        * @return bool
+        * @since 1.29
+        */
+       public function databasesAreIndependent();
+
        /**
         * Change the current database
         *
         * @param string $db
         * @return bool Success or failure
+        * @throws DBConnectionError If databasesAreIndependent() is true and an error occurs
         */
        public function selectDB( $db );
 
index 0a2cd83..b508928 100644 (file)
@@ -1475,6 +1475,9 @@ class ApiQueryWatchlistIntegrationTest extends ApiTestCase {
 
                $this->watchPages( $otherUser, [ $target ] );
 
+               $reloadedUser = User::newFromName( $otherUser->getName() );
+               $this->assertEquals( '1234567890', $reloadedUser->getOption( 'watchlisttoken' ) );
+
                $result = $this->doListWatchlistRequest( [
                        'wlowner' => $otherUser->getName(),
                        'wltoken' => '1234567890',
index 8b285cb..049f81f 100644 (file)
@@ -409,16 +409,27 @@ class LBFactoryTest extends MediaWikiTestCase {
                        "Correct full table name"
                );
 
-               \MediaWiki\suppressWarnings();
-               $this->assertFalse( $db->selectDB( 'garbage-db' ) );
-               \MediaWiki\restoreWarnings();
-
                $this->assertEquals(
                        $this->quoteTable( $db, 'garbage-db' ) . '.' . $this->quoteTable( $db, 'page' ),
                        $db->tableName( 'garbage-db.page' ),
                        "Correct full table name"
                );
 
+               if ( $db->databasesAreIndependent() ) {
+                       try {
+                               $e = null;
+                               $db->selectDB( 'garbage-db' );
+                       } catch ( \Wikimedia\Rdbms\DBConnectionError $e ) {
+                               // expected
+                       }
+                       $this->assertInstanceOf( '\Wikimedia\Rdbms\DBConnectionError', $e );
+                       $this->assertFalse( $db->isOpen() );
+               } else {
+                       \MediaWiki\suppressWarnings();
+                       $this->assertFalse( $db->selectDB( 'garbage-db' ) );
+                       \MediaWiki\restoreWarnings();
+               }
+
                $factory->closeAll();
                $factory->destroy();
        }