Merge "Linker: Document parseComment() as returning HTML"
[lhc/web/wiklou.git] / includes / db / DatabaseOracle.php
index f4f04f1..6d921b9 100644 (file)
  * @ingroup Database
  */
 
+use MediaWiki\MediaWikiServices;
 use Wikimedia\Rdbms\Database;
+use Wikimedia\Rdbms\DatabaseDomain;
 use Wikimedia\Rdbms\Blob;
 use Wikimedia\Rdbms\ResultWrapper;
 use Wikimedia\Rdbms\DBConnectionError;
 use Wikimedia\Rdbms\DBUnexpectedError;
+use Wikimedia\Rdbms\DBExpectedError;
 
 /**
  * @ingroup Database
@@ -80,17 +83,9 @@ class DatabaseOracle extends Database {
                return false;
        }
 
-       /**
-        * Usually aborts on failure
-        * @param string $server
-        * @param string $user
-        * @param string $password
-        * @param string $dbName
-        * @throws DBConnectionError
-        * @return resource|null
-        */
-       function open( $server, $user, $password, $dbName ) {
+       protected function open( $server, $user, $password, $dbName, $schema, $tablePrefix ) {
                global $wgDBOracleDRCP;
+
                if ( !function_exists( 'oci_connect' ) ) {
                        throw new DBConnectionError(
                                $this,
@@ -102,20 +97,15 @@ class DatabaseOracle extends Database {
                $this->close();
                $this->user = $user;
                $this->password = $password;
-               // changed internal variables functions
-               // mServer now holds the TNS endpoint
-               // mDBname is schema name if different from username
                if ( !$server ) {
-                       // backward compatibillity (server used to be null and TNS was supplied in dbname)
+                       // Backward compatibility (server used to be null and TNS was supplied in dbname)
                        $this->server = $dbName;
-                       $this->dbName = $user;
+                       $realDatabase = $user;
                } else {
+                       // $server now holds the TNS endpoint
                        $this->server = $server;
-                       if ( !$dbName ) {
-                               $this->dbName = $user;
-                       } else {
-                               $this->dbName = $dbName;
-                       }
+                       // $dbName is schema name if different from username
+                       $realDatabase = $dbName ?: $user;
                }
 
                if ( !strlen( $user ) ) { # e.g. the class is being loaded
@@ -156,9 +146,15 @@ class DatabaseOracle extends Database {
                }
                Wikimedia\restoreWarnings();
 
-               if ( $this->user != $this->dbName ) {
+               if ( $this->user != $realDatabase ) {
                        // change current schema in session
-                       $this->selectDB( $this->dbName );
+                       $this->selectDB( $realDatabase );
+               } else {
+                       $this->currentDomain = new DatabaseDomain(
+                               $realDatabase,
+                               null,
+                               $tablePrefix
+                       );
                }
 
                if ( !$this->conn ) {
@@ -172,7 +168,7 @@ class DatabaseOracle extends Database {
                $this->doQuery( 'ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' );
                $this->doQuery( 'ALTER SESSION SET NLS_NUMERIC_CHARACTERS=\'.,\'' );
 
-               return $this->conn;
+               return (bool)$this->conn;
        }
 
        /**
@@ -446,8 +442,6 @@ class DatabaseOracle extends Database {
         * @throws DBUnexpectedError
         */
        private function insertOneRow( $table, $row, $fname ) {
-               global $wgContLang;
-
                $table = $this->tableName( $table );
                // "INSERT INTO tables (a, b, c)"
                $sql = "INSERT INTO " . $table . " (" . implode( ',', array_keys( $row ) ) . ')';
@@ -493,7 +487,8 @@ class DatabaseOracle extends Database {
                                        $val = $this->getInfinity();
                                }
 
-                               $val = ( $wgContLang != null ) ? $wgContLang->checkTitleEncoding( $val ) : $val;
+                               $val = MediaWikiServices::getInstance()->getContentLanguage()->
+                                       checkTitleEncoding( $val );
                                if ( oci_bind_by_name( $stmt, ":$col", $val, -1, SQLT_CHR ) === false ) {
                                        $e = oci_error( $stmt );
                                        $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
@@ -663,8 +658,8 @@ class DatabaseOracle extends Database {
                                        atc.table_name
                                ) || '_' ||
                                atc.column_name || '_SEQ' = '{$this->tablePrefix}' || asq.sequence_name
-                               AND asq.sequence_owner = upper('{$this->dbName}')
-                               AND atc.owner = upper('{$this->dbName}')" );
+                               AND asq.sequence_owner = upper('{$this->getDBname()}')
+                               AND atc.owner = upper('{$this->getDBname()}')" );
 
                        while ( ( $row = $result->fetchRow() ) !== false ) {
                                $this->sequenceData[$row[1]] = [
@@ -744,7 +739,7 @@ class DatabaseOracle extends Database {
                        $listWhere = ' AND table_name LIKE \'' . strtoupper( $prefix ) . '%\'';
                }
 
-               $owner = strtoupper( $this->dbName );
+               $owner = strtoupper( $this->getDBname() );
                $result = $this->doQuery( "SELECT table_name FROM all_tables " .
                        "WHERE owner='$owner' AND table_name NOT LIKE '%!_IDX\$_' ESCAPE '!' $listWhere" );
 
@@ -822,7 +817,7 @@ class DatabaseOracle extends Database {
                $table = $this->tableName( $table );
                $table = strtoupper( $this->removeIdentifierQuotes( $table ) );
                $index = strtoupper( $index );
-               $owner = strtoupper( $this->dbName );
+               $owner = strtoupper( $this->getDBname() );
                $sql = "SELECT 1 FROM all_indexes WHERE owner='$owner' AND index_name='{$table}_{$index}'";
                $res = $this->doQuery( $sql );
                if ( $res ) {
@@ -844,7 +839,7 @@ class DatabaseOracle extends Database {
        function tableExists( $table, $fname = __METHOD__ ) {
                $table = $this->tableName( $table );
                $table = $this->addQuotes( strtoupper( $this->removeIdentifierQuotes( $table ) ) );
-               $owner = $this->addQuotes( strtoupper( $this->dbName ) );
+               $owner = $this->addQuotes( strtoupper( $this->getDBname() ) );
                $sql = "SELECT 1 FROM all_tables WHERE owner=$owner AND table_name=$table";
                $res = $this->doQuery( $sql );
                if ( $res && $res->numRows() > 0 ) {
@@ -1040,23 +1035,33 @@ class DatabaseOracle extends Database {
                return true;
        }
 
-       function selectDB( $db ) {
-               $this->dbName = $db;
-               if ( $db == null || $db == $this->user ) {
+       protected function doSelectDomain( DatabaseDomain $domain ) {
+               if ( $domain->getSchema() !== null ) {
+                       // We use the *database* aspect of $domain for schema, not the domain schema
+                       throw new DBExpectedError( $this, __CLASS__ . ": domain schemas are not supported." );
+               }
+
+               $database = $domain->getDatabase();
+               if ( $database === null || $database === $this->user ) {
+                       // Backward compatibility
+                       $this->currentDomain = $domain;
+
                        return true;
                }
-               $sql = 'ALTER SESSION SET CURRENT_SCHEMA=' . strtoupper( $db );
+
+               // https://docs.oracle.com/javadb/10.8.3.0/ref/rrefsqlj32268.html
+               $encDatabase = $this->addIdentifierQuotes( strtoupper( $database ) );
+               $sql = "ALTER SESSION SET CURRENT_SCHEMA=$encDatabase";
                $stmt = oci_parse( $this->conn, $sql );
                Wikimedia\suppressWarnings();
                $success = oci_execute( $stmt );
                Wikimedia\restoreWarnings();
-               if ( !$success ) {
+               if ( $success ) {
+                       // Update that domain fields on success (no exception thrown)
+                       $this->currentDomain = $domain;
+               } else {
                        $e = oci_error( $stmt );
-                       if ( $e['code'] != '1435' ) {
-                               $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
-                       }
-
-                       return false;
+                       $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
                }
 
                return true;
@@ -1067,9 +1072,9 @@ class DatabaseOracle extends Database {
        }
 
        function addQuotes( $s ) {
-               global $wgContLang;
-               if ( isset( $wgContLang->mLoaded ) && $wgContLang->mLoaded ) {
-                       $s = $wgContLang->checkTitleEncoding( $s );
+               $contLang = MediaWikiServices::getInstance()->getContentLanguage();
+               if ( isset( $contLang->mLoaded ) && $contLang->mLoaded ) {
+                       $s = $contLang->checkTitleEncoding( $s );
                }
 
                return "'" . $this->strencode( $s ) . "'";
@@ -1092,15 +1097,15 @@ class DatabaseOracle extends Database {
        }
 
        private function wrapFieldForWhere( $table, &$col, &$val ) {
-               global $wgContLang;
-
                $col_info = $this->fieldInfoMulti( $table, $col );
                $col_type = $col_info != false ? $col_info->type() : 'CONSTANT';
                if ( $col_type == 'CLOB' ) {
                        $col = 'TO_CHAR(' . $col . ')';
-                       $val = $wgContLang->checkTitleEncoding( $val );
+                       $val =
+                               MediaWikiServices::getInstance()->getContentLanguage()->checkTitleEncoding( $val );
                } elseif ( $col_type == 'VARCHAR2' ) {
-                       $val = $wgContLang->checkTitleEncoding( $val );
+                       $val =
+                               MediaWikiServices::getInstance()->getContentLanguage()->checkTitleEncoding( $val );
                }
        }
 
@@ -1188,7 +1193,9 @@ class DatabaseOracle extends Database {
                // all deletions on these tables have transactions so final failure rollbacks these updates
                // @todo: Normalize the schema to match MySQL, no special FKs and such
                $table = $this->tableName( $table );
-               if ( $table == $this->tableName( 'user' ) && $wgActorTableSchemaMigrationStage < MIGRATION_NEW ) {
+               if ( $table == $this->tableName( 'user' ) &&
+                       ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD )
+               ) {
                        $this->update( 'archive', [ 'ar_user' => 0 ],
                                [ 'ar_user' => $conds['user_id'] ], $fname );
                        $this->update( 'ipblocks', [ 'ipb_user' => 0 ],
@@ -1225,8 +1232,6 @@ class DatabaseOracle extends Database {
         * @throws DBUnexpectedError
         */
        function update( $table, $values, $conds, $fname = __METHOD__, $options = [] ) {
-               global $wgContLang;
-
                $table = $this->tableName( $table );
                $opts = $this->makeUpdateOptions( $options );
                $sql = "UPDATE $opts $table SET ";
@@ -1270,7 +1275,8 @@ class DatabaseOracle extends Database {
                                        $val = '31-12-2030 12:00:00.000000';
                                }
 
-                               $val = ( $wgContLang != null ) ? $wgContLang->checkTitleEncoding( $val ) : $val;
+                               $val = MediaWikiServices::getInstance()->getContentLanguage()->
+                                       checkTitleEncoding( $val );
                                if ( oci_bind_by_name( $stmt, ":$col", $val ) === false ) {
                                        $e = oci_error( $stmt );
                                        $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
@@ -1342,10 +1348,6 @@ class DatabaseOracle extends Database {
                return 'BITOR(' . $fieldLeft . ', ' . $fieldRight . ')';
        }
 
-       function getDBname() {
-               return $this->dbName;
-       }
-
        function getServer() {
                return $this->server;
        }