Merge "rdbms: Use correct value for 'sslmode' in DatabasePostgres"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 26 Mar 2019 18:51:26 +0000 (18:51 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 26 Mar 2019 18:51:26 +0000 (18:51 +0000)
1  2 
includes/libs/rdbms/database/DatabasePostgres.php

@@@ -86,7 -86,7 +86,7 @@@ class DatabasePostgres extends Databas
                return false;
        }
  
 -      public function open( $server, $user, $password, $dbName ) {
 +      protected function open( $server, $user, $password, $dbName, $schema, $tablePrefix ) {
                # Test for Postgres support, to avoid suppressed fatal error
                if ( !function_exists( 'pg_connect' ) ) {
                        throw new DBConnectionError(
                $this->server = $server;
                $this->user = $user;
                $this->password = $password;
 -              $this->dbName = $dbName;
  
                $connectVars = [
                        // pg_connect() user $user as the default database. Since a database is *required*,
                        $connectVars['port'] = (int)$this->port;
                }
                if ( $this->flags & self::DBO_SSL ) {
-                       $connectVars['sslmode'] = 1;
+                       $connectVars['sslmode'] = 'require';
                }
  
                $this->connectString = $this->makeConnectionString( $connectVars );
                $this->query( "SET standard_conforming_strings = on", __METHOD__ );
                $this->query( "SET bytea_output = 'escape'", __METHOD__ ); // PHP bug 53127
  
 -              $this->determineCoreSchema( $this->schema );
 -              // The schema to be used is now in the search path; no need for explicit qualification
 -              $this->schema = '';
 +              $this->determineCoreSchema( $schema );
 +              $this->currentDomain = new DatabaseDomain( $dbName, $schema, $tablePrefix );
  
 -              return $this->conn;
 +              return (bool)$this->conn;
 +      }
 +
 +      protected function relationSchemaQualifier() {
 +              if ( $this->coreSchema === $this->currentDomain->getSchema() ) {
 +                      // The schema to be used is now in the search path; no need for explicit qualification
 +                      return '';
 +              }
 +
 +              return parent::relationSchemaQualifier();
        }
  
        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->dbName !== $db ) {
 -                      return (bool)$this->open( $this->server, $this->user, $this->password, $db );
 +      public function doSelectDomain( DatabaseDomain $domain ) {
 +              if ( $this->getDBname() !== $domain->getDatabase() ) {
 +                      // 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
 +                      $this->open(
 +                              $this->server,
 +                              $this->user,
 +                              $this->password,
 +                              $domain->getDatabase(),
 +                              $domain->getSchema(),
 +                              $domain->getTablePrefix()
 +                      );
                } else {
 -                      return true;
 +                      $this->currentDomain = $domain;
                }
 +
 +              return true;
        }
  
        /**
                        !preg_match( '/^SELECT\s+pg_(try_|)advisory_\w+\(/', $sql );
        }
  
 +      /**
 +       * @param string $sql
 +       * @return bool|mixed|resource
 +       */
        public function doQuery( $sql ) {
                $conn = $this->getBindingHandle();
  
        }
  
        public function numRows( $res ) {
 +              if ( $res === false ) {
 +                      return 0;
 +              }
 +
                if ( $res instanceof ResultWrapper ) {
                        $res = $res->result;
                }
@@@ -657,18 -638,6 +657,18 @@@ __INDEXATTR__
                return true;
        }
  
 +      protected function makeUpdateOptionsArray( $options ) {
 +              if ( !is_array( $options ) ) {
 +                      $options = [ $options ];
 +              }
 +
 +              // PostgreSQL doesn't support anything like "ignore" for
 +              // UPDATE.
 +              $options = array_diff( $options, [ 'IGNORE' ] );
 +
 +              return parent::makeUpdateOptionsArray( $options );
 +      }
 +
        /**
         * INSERT SELECT wrapper
         * $varMap must be an associative array of the form [ 'dest1' => 'source1', ... ]
         * 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)?
 +       * @todo FIXME: Implement this a little better (separate select/insert)?
         *
         * @param string $destTable
         * @param array|string $srcTable
         * @param array $insertOptions
         * @param array $selectOptions
         * @param array $selectJoinConds
 -       * @return bool
         */
 -      public function nativeInsertSelect(
 +      protected function nativeInsertSelect(
                $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__,
                $insertOptions = [], $selectOptions = [], $selectJoinConds = []
        ) {
                                $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ') ' .
                                        $selectSql . ' ON CONFLICT DO NOTHING';
  
 -                              return $this->query( $sql, $fname );
 +                              $this->query( $sql, $fname );
                        } else {
                                // IGNORE and we don't have ON CONFLICT DO NOTHING, so just use the non-native version
 -                              return $this->nonNativeInsertSelect(
 +                              $this->nonNativeInsertSelect(
                                        $destTable, $srcTable, $varMap, $conds, $fname,
                                        $insertOptions, $selectOptions, $selectJoinConds
                                );
                        }
 +              } else {
 +                      parent::nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname,
 +                              $insertOptions, $selectOptions, $selectJoinConds );
                }
 -
 -              return parent::nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname,
 -                      $insertOptions, $selectOptions, $selectJoinConds );
        }
  
        public function tableName( $name, $format = 'quoted' ) {
                        . ' WHERE relkind = \'r\''
                        . ' AND nspname = ' . $this->addQuotes( $this->getCoreSchema() )
                        . ' AND relname = ' . $this->addQuotes( $oldName )
 -                      . ' AND adsrc LIKE \'nextval(%\'',
 +                      . ' AND pg_get_expr(adbin, adrelid) LIKE \'nextval(%\'',
                        $fname
                );
                $row = $this->fetchObject( $res );
                        }
  
                        $oid = $this->fetchObject( $res )->oid;
 -                      $res = $this->query( 'SELECT adsrc FROM pg_attribute a'
 +                      $res = $this->query( 'SELECT pg_get_expr(adbin, adrelid) AS adsrc FROM pg_attribute a'
                                . ' JOIN pg_attrdef d ON (a.attrelid=d.adrelid and a.attnum=d.adnum)'
                                . " WHERE a.attrelid = $oid"
 -                              . ' AND adsrc LIKE \'nextval(%\'',
 +                              . ' AND pg_get_expr(adbin, adrelid) LIKE \'nextval(%\'',
                                $fname
                        );
                        $row = $this->fetchObject( $res );
                return false;
        }
  
 +      /**
 +       * @suppress SecurityCheck-SQLInjection array_map not recognized T204911
 +       */
        public function listTables( $prefix = null, $fname = __METHOD__ ) {
                $eschemas = implode( ',', array_map( [ $this, 'addQuotes' ], $this->getCoreSchemas() ) );
                $result = $this->query(
         * @return string[]
         */
        private function pg_array_parse( $text, &$output, $limit = false, $offset = 1 ) {
 -              if ( false === $limit ) {
 +              if ( $limit === false ) {
                        $limit = strlen( $text ) - 1;
                        $output = [];
                }
 -              if ( '{}' == $text ) {
 +              if ( $text == '{}' ) {
                        return $output;
                }
                do {
 -                      if ( '{' != $text[$offset] ) {
 +                      if ( $text[$offset] != '{' ) {
                                preg_match( "/(\\{?\"([^\"\\\\]|\\\\.)*\"|[^,{}]+)+([,}]+)/",
                                        $text, $match, 0, $offset );
                                $offset += strlen( $match[0] );
 -                              $output[] = ( '"' != $match[1][0]
 +                              $output[] = ( $match[1][0] != '"'
                                        ? $match[1]
                                        : stripcslashes( substr( $match[1], 1, -1 ) ) );
 -                              if ( '},' == $match[3] ) {
 +                              if ( $match[3] == '},' ) {
                                        return $output;
                                }
                        } else {
@@@ -1346,6 -1313,14 +1346,6 @@@ SQL
                return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail, $ignoreIndex ];
        }
  
 -      public function getDBname() {
 -              return $this->dbName;
 -      }
 -
 -      public function getServer() {
 -              return $this->server;
 -      }
 -
        public function buildConcat( $stringList ) {
                return implode( ' || ', $stringList );
        }