* code should use lastErrno() and lastError() to handle the
* situation as appropriate.
*
+ * Do not use this function outside of the Database classes.
+ *
* @param $ignoreErrors bool|null
*
* @return bool The previous value of the flag.
* @param $flag Integer: DBO_* constants from Defines.php:
* - DBO_DEBUG: output some debug info (same as debug())
* - DBO_NOBUFFER: don't buffer results (inverse of bufferResults())
- * - DBO_IGNORE: ignore errors (same as ignoreErrors())
* - DBO_TRX: automatically start transactions
* - DBO_DEFAULT: automatically sets DBO_TRX if not in command line mode
* and removes it in command line mode
/**
* Given a DB type, construct the name of the appropriate child class of
* DatabaseBase. This is designed to replace all of the manual stuff like:
- * $class = 'Database' . ucfirst( strtolower( $type ) );
+ * $class = 'Database' . ucfirst( strtolower( $dbType ) );
* as well as validate against the canonical list of DB types we have
*
* This factory function is mostly useful for when you need to connect to a
*
* @param string $dbType A possible DB type
* @param array $p An array of options to pass to the constructor.
- * Valid options are: host, user, password, dbname, flags, tablePrefix
+ * Valid options are: host, user, password, dbname, flags, tablePrefix, driver
* @return DatabaseBase subclass or null
*/
final public static function factory( $dbType, $p = array() ) {
$canonicalDBTypes = array(
- 'mysql', 'postgres', 'sqlite', 'oracle', 'mssql'
+ 'mysql' => array( 'mysqli', 'mysql' ),
+ 'postgres' => array(),
+ 'sqlite' => array(),
+ 'oracle' => array(),
+ 'mssql' => array(),
);
+
+ $driver = false;
$dbType = strtolower( $dbType );
- $class = 'Database' . ucfirst( $dbType );
+ if ( isset( $canonicalDBTypes[$dbType] ) && $canonicalDBTypes[$dbType] ) {
+ $possibleDrivers = $canonicalDBTypes[$dbType];
+ if ( !empty( $p['driver'] ) ) {
+ if ( in_array( $p['driver'], $possibleDrivers ) ) {
+ $driver = $p['driver'];
+ } else {
+ throw new MWException( __METHOD__ .
+ " cannot construct Database with type '$dbType' and driver '{$p['driver']}'" );
+ }
+ } else {
+ foreach ( $possibleDrivers as $posDriver ) {
+ if ( extension_loaded( $posDriver ) ) {
+ $driver = $posDriver;
+ break;
+ }
+ }
+ }
+ } else {
+ $driver = $dbType;
+ }
+ if ( $driver === false ) {
+ throw new MWException( __METHOD__ .
+ " no viable database extension found for type '$dbType'" );
+ }
- if ( in_array( $dbType, $canonicalDBTypes ) || ( class_exists( $class ) && is_subclass_of( $class, 'DatabaseBase' ) ) ) {
+ $class = 'Database' . ucfirst( $driver );
+ if ( class_exists( $class ) && is_subclass_of( $class, 'DatabaseBase' ) ) {
return new $class(
isset( $p['host'] ) ? $p['host'] : false,
isset( $p['user'] ) ? $p['user'] : false,
* for a successful read query, or false on failure if $tempIgnore set
*/
public function query( $sql, $fname = __METHOD__, $tempIgnore = false ) {
- $isMaster = !is_null( $this->getLBInfo( 'master' ) );
- if ( !Profiler::instance()->isStub() ) {
- # generalizeSQL will probably cut down the query to reasonable
- # logging size most of the time. The substr is really just a sanity check.
-
- if ( $isMaster ) {
- $queryProf = 'query-m: ' . substr( DatabaseBase::generalizeSQL( $sql ), 0, 255 );
- $totalProf = 'DatabaseBase::query-master';
- } else {
- $queryProf = 'query: ' . substr( DatabaseBase::generalizeSQL( $sql ), 0, 255 );
- $totalProf = 'DatabaseBase::query';
- }
-
- wfProfileIn( $totalProf );
- wfProfileIn( $queryProf );
- }
+ global $wgUser, $wgDebugDBTransactions;
$this->mLastQuery = $sql;
if ( !$this->mDoneWrites && $this->isWriteQuery( $sql ) ) {
}
# Add a comment for easy SHOW PROCESSLIST interpretation
- global $wgUser;
if ( is_object( $wgUser ) && $wgUser->isItemLoaded( 'name' ) ) {
$userName = $wgUser->getName();
if ( mb_strlen( $userName ) > 15 ) {
# is really used by application
$sqlstart = substr( $sql, 0, 10 ); // very much worth it, benchmark certified(tm)
if ( strpos( $sqlstart, "SHOW " ) !== 0 && strpos( $sqlstart, "SET " ) !== 0 ) {
- global $wgDebugDBTransactions;
if ( $wgDebugDBTransactions ) {
wfDebug( "Implicit transaction start.\n" );
}
Profiler::instance()->transactionWritingIn( $this->mServer, $this->mDBname );
}
+ $isMaster = !is_null( $this->getLBInfo( 'master' ) );
+ if ( !Profiler::instance()->isStub() ) {
+ # generalizeSQL will probably cut down the query to reasonable
+ # logging size most of the time. The substr is really just a sanity check.
+ if ( $isMaster ) {
+ $queryProf = 'query-m: ' . substr( DatabaseBase::generalizeSQL( $sql ), 0, 255 );
+ $totalProf = 'DatabaseBase::query-master';
+ } else {
+ $queryProf = 'query: ' . substr( DatabaseBase::generalizeSQL( $sql ), 0, 255 );
+ $totalProf = 'DatabaseBase::query';
+ }
+ wfProfileIn( $totalProf );
+ wfProfileIn( $queryProf );
+ }
+
if ( $this->debug() ) {
static $cnt = 0;
$sql = preg_replace( '/\s+/', ' ', $sql );
# All numbers => N
- $sql = preg_replace( '/-?[0-9]+/s', 'N', $sql );
+ $sql = preg_replace( '/-?\d+(,-?\d+)+/s', 'N,...,N', $sql );
+ $sql = preg_replace( '/-?\d+/s', 'N', $sql );
return $sql;
}
}
/**
- * If it's a string, adds quotes and backslashes
- * Otherwise returns as-is
+ * Adds quotes and backslashes.
*
* @param $s string
*