@@ -167,7 +167,7 @@
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @link http://drupal.org/developing/api/database @endlink
|
||||
* @see http://drupal.org/developing/api/database
|
||||
*/
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ abstract class DatabaseConnection extends PDO {
|
||||
|
||||
/**
|
||||
* The key representing this connection.
|
||||
*
|
||||
*
|
||||
* The key is a unique string which identifies a database connection. A
|
||||
* connection can be a single server or a cluster of master and slaves (use
|
||||
* target to pick between master and slave).
|
||||
@@ -303,12 +303,28 @@ abstract class DatabaseConnection extends PDO {
|
||||
// Call PDO::__construct and PDO::setAttribute.
|
||||
parent::__construct($dsn, $username, $password, $driver_options);
|
||||
|
||||
// Set a specific PDOStatement class if the driver requires that.
|
||||
// Set a Statement class, unless the driver opted out.
|
||||
if (!empty($this->statementClass)) {
|
||||
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array($this->statementClass, array($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys this Connection object.
|
||||
*
|
||||
* PHP does not destruct an object if it is still referenced in other
|
||||
* variables. In case of PDO database connection objects, PHP only closes the
|
||||
* connection when the PDO object is destructed, so any references to this
|
||||
* object may cause the number of maximum allowed connections to be exceeded.
|
||||
*/
|
||||
public function destroy() {
|
||||
// Destroy all references to this connection by setting them to NULL.
|
||||
// The Statement class attribute only accepts a new value that presents a
|
||||
// proper callable, so we reset it to PDOStatement.
|
||||
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDOStatement', array()));
|
||||
$this->schema = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default query options for any given query.
|
||||
*
|
||||
@@ -1627,8 +1643,8 @@ abstract class Database {
|
||||
*/
|
||||
final public static function removeConnection($key) {
|
||||
if (isset(self::$databaseInfo[$key])) {
|
||||
self::closeConnection(NULL, $key);
|
||||
unset(self::$databaseInfo[$key]);
|
||||
unset(self::$connections[$key]);
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
@@ -1694,11 +1710,24 @@ abstract class Database {
|
||||
if (!isset($key)) {
|
||||
$key = self::$activeKey;
|
||||
}
|
||||
// To close the connection, we need to unset the static variable.
|
||||
// To close a connection, it needs to be set to NULL and removed from the
|
||||
// static variable. In all cases, closeConnection() might be called for a
|
||||
// connection that was not opened yet, in which case the key is not defined
|
||||
// yet and we just ensure that the connection key is undefined.
|
||||
if (isset($target)) {
|
||||
if (isset(self::$connections[$key][$target])) {
|
||||
self::$connections[$key][$target]->destroy();
|
||||
self::$connections[$key][$target] = NULL;
|
||||
}
|
||||
unset(self::$connections[$key][$target]);
|
||||
}
|
||||
else {
|
||||
if (isset(self::$connections[$key])) {
|
||||
foreach (self::$connections[$key] as $target => $connection) {
|
||||
self::$connections[$key][$target]->destroy();
|
||||
self::$connections[$key][$target] = NULL;
|
||||
}
|
||||
}
|
||||
unset(self::$connections[$key]);
|
||||
}
|
||||
}
|
||||
@@ -1852,8 +1881,8 @@ class DatabaseTransaction {
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
public function __construct(DatabaseConnection &$connection, $name = NULL) {
|
||||
$this->connection = &$connection;
|
||||
public function __construct(DatabaseConnection $connection, $name = NULL) {
|
||||
$this->connection = $connection;
|
||||
// If there is no transaction depth, then no transaction has started. Name
|
||||
// the transaction 'drupal_transaction'.
|
||||
if (!$depth = $connection->transactionDepth()) {
|
||||
|
@@ -13,11 +13,11 @@
|
||||
class DatabaseConnection_mysql extends DatabaseConnection {
|
||||
|
||||
/**
|
||||
* Flag to indicate if we have registered the nextID cleanup function.
|
||||
* Flag to indicate if the cleanup function in __destruct() should run.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $shutdownRegistered = FALSE;
|
||||
protected $needsCleanup = FALSE;
|
||||
|
||||
public function __construct(array $connection_options = array()) {
|
||||
// This driver defaults to transaction support, except if explicitly passed FALSE.
|
||||
@@ -78,6 +78,12 @@ class DatabaseConnection_mysql extends DatabaseConnection {
|
||||
$this->exec(implode('; ', $connection_options['init_commands']));
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
if ($this->needsCleanup) {
|
||||
$this->nextIdDelete();
|
||||
}
|
||||
}
|
||||
|
||||
public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
|
||||
return $this->query($query . ' LIMIT ' . (int) $from . ', ' . (int) $count, $args, $options);
|
||||
}
|
||||
@@ -115,12 +121,7 @@ class DatabaseConnection_mysql extends DatabaseConnection {
|
||||
$this->query('INSERT INTO {sequences} (value) VALUES (:value) ON DUPLICATE KEY UPDATE value = value', array(':value' => $existing_id));
|
||||
$new_id = $this->query('INSERT INTO {sequences} () VALUES ()', array(), array('return' => Database::RETURN_INSERT_ID));
|
||||
}
|
||||
if (!$this->shutdownRegistered) {
|
||||
// Use register_shutdown_function() here to keep the database system
|
||||
// independent of Drupal.
|
||||
register_shutdown_function(array($this, 'nextIdDelete'));
|
||||
$shutdownRegistered = TRUE;
|
||||
}
|
||||
$this->needsCleanup = TRUE;
|
||||
return $new_id;
|
||||
}
|
||||
|
||||
|
@@ -1898,8 +1898,13 @@ class DatabaseCondition implements QueryConditionInterface, Countable {
|
||||
function __clone() {
|
||||
$this->changed = TRUE;
|
||||
foreach ($this->conditions as $key => $condition) {
|
||||
if ($key !== '#conjunction' && $condition['field'] instanceOf QueryConditionInterface) {
|
||||
$this->conditions[$key]['field'] = clone($condition['field']);
|
||||
if ($key !== '#conjunction') {
|
||||
if ($condition['field'] instanceOf QueryConditionInterface) {
|
||||
$this->conditions[$key]['field'] = clone($condition['field']);
|
||||
}
|
||||
if ($condition['value'] instanceOf SelectQueryInterface) {
|
||||
$this->conditions[$key]['value'] = clone($condition['value']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -57,39 +57,18 @@ class InsertQuery_sqlite extends InsertQuery {
|
||||
* we don't select those rows.
|
||||
*
|
||||
* A query like this one:
|
||||
* UPDATE test SET name = 'newname' WHERE tid = 1
|
||||
* UPDATE test SET col1 = 'newcol1', col2 = 'newcol2' WHERE tid = 1
|
||||
* will become:
|
||||
* UPDATE test SET name = 'newname' WHERE tid = 1 AND name <> 'newname'
|
||||
* UPDATE test SET col1 = 'newcol1', col2 = 'newcol2' WHERE tid = 1 AND (col1 <> 'newcol1' OR col2 <> 'newcol2')
|
||||
*/
|
||||
class UpdateQuery_sqlite extends UpdateQuery {
|
||||
/**
|
||||
* Helper function that removes the fields that are already in a condition.
|
||||
*
|
||||
* @param $fields
|
||||
* The fields.
|
||||
* @param QueryConditionInterface $condition
|
||||
* A database condition.
|
||||
*/
|
||||
protected function removeFieldsInCondition(&$fields, QueryConditionInterface $condition) {
|
||||
foreach ($condition->conditions() as $child_condition) {
|
||||
if ($child_condition['field'] instanceof QueryConditionInterface) {
|
||||
$this->removeFieldsInCondition($fields, $child_condition['field']);
|
||||
}
|
||||
else {
|
||||
unset($fields[$child_condition['field']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
if (!empty($this->queryOptions['sqlite_return_matched_rows'])) {
|
||||
return parent::execute();
|
||||
}
|
||||
|
||||
// Get the fields used in the update query, and remove those that are already
|
||||
// in the condition.
|
||||
// Get the fields used in the update query.
|
||||
$fields = $this->expressionFields + $this->fields;
|
||||
$this->removeFieldsInCondition($fields, $this->condition);
|
||||
|
||||
// Add the inverse of the fields to the condition.
|
||||
$condition = new DatabaseCondition('OR');
|
||||
|
Reference in New Issue
Block a user