* @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
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,
$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
}
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 ) {
$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;
}
/**
* @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 ) ) . ')';
$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__ );
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]] = [
$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" );
$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 ) {
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 ) {
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;
}
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 ) . "'";
}
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 );
}
}
// 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 ],
* @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 ";
$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__ );
return 'BITOR(' . $fieldLeft . ', ' . $fieldRight . ')';
}
- function getDBname() {
- return $this->dbName;
- }
-
function getServer() {
return $this->server;
}