* @file
* @ingroup Database
*/
+namespace Wikimedia\Rdbms;
+
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
use Wikimedia\ScopedCallback;
-use Wikimedia\Rdbms\TransactionProfiler;
-use Wikimedia\Rdbms\LikeMatch;
-use Wikimedia\Rdbms\DatabaseDomain;
-use Wikimedia\Rdbms\ResultWrapper;
-use Wikimedia\Rdbms\DBMasterPos;
-use Wikimedia\Rdbms\Blob;
use Wikimedia\Timestamp\ConvertibleTimestamp;
+use MediaWiki;
+use BagOStuff;
+use HashBagOStuff;
+use InvalidArgumentException;
+use DBQueryError;
+use DBUnexpectedError;
+use DBConnectionError;
+use DBReadOnlyError;
+use Exception;
+use RuntimeException;
/**
* Relational database abstraction object
'oracle' => [],
'mssql' => [],
];
+ static $classAliases = [
+ 'DatabaseMssql' => DatabaseMssql::class,
+ 'DatabaseMysql' => DatabaseMysql::class,
+ 'DatabaseMysqli' => DatabaseMysqli::class,
+ 'DatabaseSqlite' => DatabaseSqlite::class,
+ 'DatabasePostgres' => DatabasePostgres::class
+ ];
$driver = false;
$dbType = strtolower( $dbType );
} else {
$driver = $dbType;
}
+
if ( $driver === false || $driver === '' ) {
throw new InvalidArgumentException( __METHOD__ .
" no viable database extension found for type '$dbType'" );
}
$class = 'Database' . ucfirst( $driver );
- if ( class_exists( $class ) && is_subclass_of( $class, 'IDatabase' ) ) {
+ if ( isset( $classAliases[$class] ) ) {
+ $class = $classAliases[$class];
+ }
+
+ if ( class_exists( $class ) && is_subclass_of( $class, IDatabase::class ) ) {
// Resolve some defaults for b/c
$p['host'] = isset( $p['host'] ) ? $p['host'] : false;
$p['user'] = isset( $p['user'] ) ? $p['user'] : false;
$sql .= " WHERE " . $this->makeList( $conds, self::LIST_AND );
}
- return $this->query( $sql, $fname );
+ return (bool)$this->query( $sql, $fname );
}
public function makeList( $a, $mode = self::LIST_COMMA ) {
}
/**
- * Get the name of an index in a given table.
+ * Allows for index remapping in queries where this is not consistent across DBMS
*
* @param string $index
* @return string
return false;
}
- /**
- * Lock specific tables
- *
- * @param array $read Array of tables to lock for read access
- * @param array $write Array of tables to lock for write access
- * @param string $method Name of caller
- * @param bool $lowPriority Whether to indicate writes to be LOW PRIORITY
- * @return bool
- */
- public function lockTables( $read, $write, $method, $lowPriority = true ) {
+ public function tableLocksHaveTransactionScope() {
return true;
}
- /**
- * Unlock specific tables
- *
- * @param string $method The caller
- * @return bool
- */
- public function unlockTables( $method ) {
+ final public function lockTables( array $read, array $write, $method ) {
+ if ( $this->writesOrCallbacksPending() ) {
+ throw new DBUnexpectedError( $this, "Transaction writes or callbacks still pending." );
+ }
+
+ if ( $this->tableLocksHaveTransactionScope() ) {
+ $this->startAtomic( $method );
+ }
+
+ return $this->doLockTables( $read, $write, $method );
+ }
+
+ protected function doLockTables( array $read, array $write, $method ) {
+ return true;
+ }
+
+ final public function unlockTables( $method ) {
+ if ( $this->tableLocksHaveTransactionScope() ) {
+ $this->endAtomic( $method );
+
+ return true; // locks released on COMMIT/ROLLBACK
+ }
+
+ return $this->doUnlockTables( $method );
+ }
+
+ protected function doUnlockTables( $method ) {
return true;
}
}
}
-class_alias( Database::class, 'DatabaseBase' );
+class_alias( Database::class, 'DatabaseBase' ); // b/c for old name
+class_alias( Database::class, 'Database' ); // b/c global alias