const SLOW_WRITE_SEC = 0.500;
const SMALL_WRITE_ROWS = 100;
+ /** @var string Whether lock granularity is on the level of the entire database */
+ const ATTR_DB_LEVEL_LOCKING = 'db-level-locking';
+
/** @var string SQL query */
protected $lastQuery = '';
/** @var float|bool UNIX timestamp of last write query */
/** @var TransactionProfiler */
protected $trxProfiler;
+ /** @var int */
+ protected $nonNativeInsertSelectBatchSize = 10000;
+
/**
* Constructor and database handle and attempt to connect to the DB server
*
$this->queryLogger = $params['queryLogger'];
$this->errorLogger = $params['errorLogger'];
+ if ( isset( $params['nonNativeInsertSelectBatchSize'] ) ) {
+ $this->nonNativeInsertSelectBatchSize = $params['nonNativeInsertSelectBatchSize'];
+ }
+
// Set initial dummy domain until open() sets the final DB/prefix
$this->currentDomain = DatabaseDomain::newUnspecified();
* - cliMode: Whether to consider the execution context that of a CLI script.
* - agent: Optional name used to identify the end-user in query profiling/logging.
* - srvCache: Optional BagOStuff instance to an APC-style cache.
+ * - nonNativeInsertSelectBatchSize: Optional batch size for non-native INSERT SELECT emulation.
* @return Database|null If the database driver or extension cannot be found
* @throws InvalidArgumentException If the database driver or extension cannot be found
* @since 1.18
return $conn;
}
+ /**
+ * @param string $dbType A possible DB type (sqlite, mysql, postgres,...)
+ * @param string|null $driver Optional name of a specific DB client driver
+ * @return array Map of (Database::ATTRIBUTE_* constant => value) for all such constants
+ * @throws InvalidArgumentException
+ * @since 1.31
+ */
+ final public static function attributesFromType( $dbType, $driver = null ) {
+ static $defaults = [ self::ATTR_DB_LEVEL_LOCKING => false ];
+
+ $class = self::getClass( $dbType, $driver );
+
+ return call_user_func( [ $class, 'getAttributes' ] ) + $defaults;
+ }
+
/**
* @param string $dbType A possible DB type (sqlite, mysql, postgres,...)
* @param string|null $driver Optional name of a specific DB client driver
return $class;
}
+ /**
+ * @return array Map of (Database::ATTRIBUTE_* constant => value
+ * @since 1.31
+ */
+ protected static function getAttributes() {
+ return [];
+ }
+
/**
* Set the PSR-3 logger interface to use for query logging. (The logger
* interfaces for connection logging and error logging can be set with the
$fname = __METHOD__,
$insertOptions = [], $selectOptions = [], $selectJoinConds = []
) {
+ $insertOptions = array_diff( (array)$insertOptions, [ 'NO_AUTO_COLUMNS' ] );
+
// For web requests, do a locking SELECT and then INSERT. This puts the SELECT burden
// on only the master (without needing row-based-replication). It also makes it easy to
// know how big the INSERT is going to be.
return false;
}
- $rows = [];
- foreach ( $res as $row ) {
- $rows[] = (array)$row;
+ try {
+ $affectedRowCount = 0;
+ $this->startAtomic( $fname );
+ $rows = [];
+ $ok = true;
+ foreach ( $res as $row ) {
+ $rows[] = (array)$row;
+
+ // Avoid inserts that are too huge
+ if ( count( $rows ) >= $this->nonNativeInsertSelectBatchSize ) {
+ $ok = $this->insert( $destTable, $rows, $fname, $insertOptions );
+ if ( !$ok ) {
+ break;
+ }
+ $affectedRowCount += $this->affectedRows();
+ $rows = [];
+ }
+ }
+ if ( $rows && $ok ) {
+ $ok = $this->insert( $destTable, $rows, $fname, $insertOptions );
+ if ( $ok ) {
+ $affectedRowCount += $this->affectedRows();
+ }
+ }
+ if ( $ok ) {
+ $this->endAtomic( $fname );
+ $this->affectedRowCount = $affectedRowCount;
+ } else {
+ $this->rollback( $fname, self::FLUSHING_INTERNAL );
+ $this->affectedRowCount = 0;
+ }
+ return $ok;
+ } catch ( Exception $e ) {
+ $this->rollback( $fname, self::FLUSHING_INTERNAL );
+ $this->affectedRowCount = 0;
+ throw $e;
}
-
- return $this->insert( $destTable, $rows, $fname, $insertOptions );
}
/**
if ( !is_array( $insertOptions ) ) {
$insertOptions = [ $insertOptions ];
}
+ $insertOptions = array_diff( (array)$insertOptions, [ 'NO_AUTO_COLUMNS' ] );
$insertOptions = $this->makeInsertOptions( $insertOptions );