Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • rklusman2/UNL-CMS
  • yzha1/UNL-CMS
  • pear/UNL-CMS
  • bbieber2/UNL-CMS
  • tsteiner2/UNL-CMS
  • erasmussen2/UNL-CMS
  • UNL-Information-Services/UNL-CMS
7 results
Show changes
Showing
with 1553 additions and 928 deletions
<?php
/**
* @file
* Batch processing API for processes to run in multiple HTTP requests.
......@@ -21,6 +20,7 @@
* @param $id
* The ID of the batch to load. When a progressive batch is being processed,
* the relevant ID is found in $_REQUEST['id'].
*
* @return
* An array representing the batch, or FALSE if no batch was found.
*/
......@@ -36,7 +36,7 @@ function batch_load($id) {
}
/**
* State-based dispatcher for the batch processing page.
* Renders the batch processing page based on the current state of the batch.
*
* @see _batch_shutdown()
*/
......@@ -94,7 +94,7 @@ function _batch_page() {
}
/**
* Initialize the batch processing.
* Initializes the batch processing.
*
* JavaScript-enabled clients are identified by the 'has_js' cookie set in
* drupal.js. If no JavaScript-enabled page has been visited during the current
......@@ -110,7 +110,7 @@ function _batch_start() {
}
/**
* Output a batch processing page with JavaScript support.
* Outputs a batch processing page with JavaScript support.
*
* This initializes the batch and error messages. Note that in JavaScript-based
* processing, the batch processing page is displayed only once and updated via
......@@ -144,7 +144,7 @@ function _batch_progress_page_js() {
}
/**
* Do one execution pass in JavaScript-mode and return progress to the browser.
* Does one execution pass with JavaScript and returns progress to the browser.
*
* @see _batch_progress_page_js()
* @see _batch_process()
......@@ -164,7 +164,7 @@ function _batch_do() {
}
/**
* Output a batch processing page without JavaScript support.
* Outputs a batch processing page without JavaScript support.
*
* @see _batch_process()
*/
......@@ -228,7 +228,7 @@ function _batch_progress_page_nojs() {
}
/**
* Process sets in a batch.
* Processes sets in a batch.
*
* If the batch was marked for progressive execution (default), this executes as
* many operations in batch sets until an execution time of 1 second has been
......@@ -370,7 +370,7 @@ function _batch_process() {
}
/**
* Helper function for _batch_process(): returns the formatted percentage.
* Formats the percent completion for a batch set.
*
* @param $total
* The total number of operations.
......@@ -379,11 +379,14 @@ function _batch_process() {
* rather than an integer in the case of a multi-step operation that is not
* yet complete; in that case, the fractional part of $current represents the
* fraction of the operation that has been completed.
*
* @return
* The properly formatted percentage, as a string. We output percentages
* using the correct number of decimal places so that we never print "100%"
* until we are finished, but we also never print more decimal places than
* are meaningful.
*
* @see _batch_process()
*/
function _batch_api_percentage($total, $current) {
if (!$total || $total == $current) {
......@@ -410,7 +413,7 @@ function _batch_api_percentage($total, $current) {
}
/**
* Return the batch set being currently processed.
* Returns the batch set being currently processed.
*/
function &_batch_current_set() {
$batch = &batch_get();
......@@ -418,7 +421,7 @@ function &_batch_current_set() {
}
/**
* Retrieve the next set in a batch.
* Retrieves the next set in a batch.
*
* If there is a subsequent set in this batch, assign it as the new set to
* process and execute its form submit handler (if defined), which may add
......@@ -442,7 +445,7 @@ function _batch_next_set() {
}
/**
* End the batch processing.
* Ends the batch processing.
*
* Call the 'finished' callback of each batch set to allow custom handling of
* the results and resolve page redirection.
......@@ -521,7 +524,10 @@ function _batch_finished() {
}
/**
* Shutdown function; store the current batch data for the next request.
* Shutdown function: Stores the current batch data for the next request.
*
* @see _batch_page()
* @see drupal_register_shutdown_function()
*/
function _batch_shutdown() {
if ($batch = batch_get()) {
......@@ -531,4 +537,3 @@ function _batch_shutdown() {
->execute();
}
}
<?php
/**
* @file
* Queue handlers used by the Batch API.
*
* Those implementations:
* - ensure FIFO ordering,
* - let an item be repeatedly claimed until it is actually deleted (no notion
* of lease time or 'expire' date), to allow multipass operations.
* These implementations:
* - Ensure FIFO ordering.
* - Allow an item to be repeatedly claimed until it is actually deleted (no
* notion of lease time or 'expire' date), to allow multipass operations.
*/
/**
* Batch queue implementation.
* Defines a batch queue.
*
* Stale items from failed batches are cleaned from the {queue} table on cron
* using the 'created' date.
*/
class BatchQueue extends SystemQueue {
/**
* Overrides SystemQueue::claimItem().
*
* Unlike SystemQueue::claimItem(), this method provides a default lease
* time of 0 (no expiration) instead of 30. This allows the item to be
* claimed repeatedly until it is deleted.
*/
public function claimItem($lease_time = 0) {
$item = db_query_range('SELECT data, item_id FROM {queue} q WHERE name = :name ORDER BY item_id ASC', 0, 1, array(':name' => $this->name))->fetchObject();
if ($item) {
......@@ -29,9 +35,9 @@ class BatchQueue extends SystemQueue {
}
/**
* Retrieve all remaining items in the queue.
* Retrieves all remaining items in the queue.
*
* This is specific to Batch API and is not part of the DrupalQueueInterface,
* This is specific to Batch API and is not part of the DrupalQueueInterface.
*/
public function getAllItems() {
$result = array();
......@@ -44,10 +50,17 @@ class BatchQueue extends SystemQueue {
}
/**
* Batch queue implementation used for non-progressive batches.
* Defines a batch queue for non-progressive batches.
*/
class BatchMemoryQueue extends MemoryQueue {
/**
* Overrides MemoryQueue::claimItem().
*
* Unlike MemoryQueue::claimItem(), this method provides a default lease
* time of 0 (no expiration) instead of 30. This allows the item to be
* claimed repeatedly until it is deleted.
*/
public function claimItem($lease_time = 0) {
if (!empty($this->queue)) {
reset($this->queue);
......@@ -57,9 +70,9 @@ class BatchMemoryQueue extends MemoryQueue {
}
/**
* Retrieve all remaining items in the queue.
* Retrieves all remaining items in the queue.
*
* This is specific to Batch API and is not part of the DrupalQueueInterface,
* This is specific to Batch API and is not part of the DrupalQueueInterface.
*/
public function getAllItems() {
$result = array();
......
This diff is collapsed.
......@@ -6,7 +6,7 @@
*/
/**
* A stub cache implementation to be used during the installation process.
* Defines a stub cache implementation to be used during installation.
*
* The stub implementation is needed when database access is not yet available.
* Because Drupal's caching system never requires that cached data be present,
......@@ -15,17 +15,30 @@
* normal operations would have a negative impact on performance.
*/
class DrupalFakeCache extends DrupalDatabaseCache implements DrupalCacheInterface {
/**
* Overrides DrupalDatabaseCache::get().
*/
function get($cid) {
return FALSE;
}
/**
* Overrides DrupalDatabaseCache::getMultiple().
*/
function getMultiple(&$cids) {
return array();
}
/**
* Overrides DrupalDatabaseCache::set().
*/
function set($cid, $data, $expire = CACHE_PERMANENT) {
}
/**
* Overrides DrupalDatabaseCache::clear().
*/
function clear($cid = NULL, $wildcard = FALSE) {
// If there is a database cache, attempt to clear it whenever possible. The
// reason for doing this is that the database cache can accumulate data
......@@ -52,6 +65,9 @@ class DrupalFakeCache extends DrupalDatabaseCache implements DrupalCacheInterfac
}
}
/**
* Overrides DrupalDatabaseCache::isEmpty().
*/
function isEmpty() {
return TRUE;
}
......
<?php
/**
* Get the cache object for a cache bin.
* @file
* Functions and interfaces for cache handling.
*/
/**
* Gets the cache object for a cache bin.
*
* By default, this returns an instance of the DrupalDatabaseCache class.
* Classes implementing DrupalCacheInterface can register themselves both as a
* default implementation and for specific bins.
*
* @see DrupalCacheInterface
*
* @param $bin
* The cache bin for which the cache object should be returned.
* @return DrupalCacheInterface
* The cache object associated with the specified bin.
*
* @see DrupalCacheInterface
*/
function _cache_get_object($bin) {
// We do not use drupal_static() here because we do not want to change the
......@@ -29,7 +34,7 @@ function _cache_get_object($bin) {
}
/**
* Return data from the persistent cache
* Returns data from the persistent cache.
*
* Data may be stored as either plain text or as serialized data. cache_get
* will automatically return unserialized objects and arrays.
......@@ -44,19 +49,22 @@ function _cache_get_object($bin) {
*
* @return
* The cache or FALSE on failure.
*
* @see cache_set()
*/
function cache_get($cid, $bin = 'cache') {
return _cache_get_object($bin)->get($cid);
}
/**
* Return data from the persistent cache when given an array of cache IDs.
* Returns data from the persistent cache when given an array of cache IDs.
*
* @param $cids
* An array of cache IDs for the data to retrieve. This is passed by
* reference, and will have the IDs successfully returned from cache removed.
* @param $bin
* The cache bin where the data is stored.
*
* @return
* An array of the items successfully returned from cache indexed by cid.
*/
......@@ -65,50 +73,22 @@ function cache_get_multiple(array &$cids, $bin = 'cache') {
}
/**
* Store data in the persistent cache.
* Stores data in the persistent cache.
*
* The persistent cache is split up into several cache bins. In the default
* cache implementation, each cache bin corresponds to a database table by the
* same name. Other implementations might want to store several bins in data
* structures that get flushed together. While it is not a problem for most
* cache bins if the entries in them are flushed before their expire time, some
* might break functionality or are extremely expensive to recalculate. These
* will be marked with a (*). The other bins expired automatically by core.
* Contributed modules can add additional bins and get them expired
* automatically by implementing hook_flush_caches().
*
* - cache: Generic cache storage bin (used for variables, theme registry,
* locale date, list of simpletest tests etc).
*
* - cache_block: Stores the content of various blocks.
*
* - cache field: Stores the field data belonging to a given object.
*
* - cache_filter: Stores filtered pieces of content.
*
* - cache_form(*): Stores multistep forms. Flushing this bin means that some
* forms displayed to users lose their state and the data already submitted
* to them.
*
* - cache_menu: Stores the structure of visible navigation menus per page.
*
* - cache_page: Stores generated pages for anonymous users. It is flushed
* very often, whenever a page changes, at least for every ode and comment
* submission. This is the only bin affected by the page cache setting on
* the administrator panel.
*
* - cache path: Stores the system paths that have an alias.
*
* - cache update(*): Stores available releases. The update server (for
* example, drupal.org) needs to produce the relevant XML for every project
* installed on the current site. As this is different for (almost) every
* site, it's very expensive to recalculate for the update server.
* might break functionality or are extremely expensive to recalculate. The
* other bins are expired automatically by core. Contributed modules can add
* additional bins and get them expired automatically by implementing
* hook_flush_caches().
*
* The reasons for having several bins are as follows:
*
* - smaller bins mean smaller database tables and allow for faster selects and
* inserts
* - we try to put fast changing cache items and rather static ones into
* - Smaller bins mean smaller database tables and allow for faster selects and
* inserts.
* - We try to put fast changing cache items and rather static ones into
* different bins. The effect is that only the fast changing bins will need a
* lot of writes to disk. The more static bins will also be better cacheable
* with MySQL's query cache.
......@@ -117,13 +97,27 @@ function cache_get_multiple(array &$cids, $bin = 'cache') {
* The cache ID of the data to store.
* @param $data
* The data to store in the cache. Complex data types will be automatically
* serialized before insertion.
* Strings will be stored as plain text and not serialized.
* serialized before insertion. Strings will be stored as plain text and are
* not serialized.
* @param $bin
* The cache bin to store the data in. Valid core values are 'cache_block',
* 'cache_bootstrap', 'cache_field', 'cache_filter', 'cache_form',
* 'cache_menu', 'cache_page', 'cache_update' or 'cache' for the default
* cache.
* The cache bin to store the data in. Valid core values are:
* - cache: (default) Generic cache storage bin (used for theme registry,
* locale date, list of simpletest tests, etc.).
* - cache_block: Stores the content of various blocks.
* - cache_bootstrap: Stores the class registry, the system list of modules,
* the list of which modules implement which hooks, and the Drupal variable
* list.
* - cache_field: Stores the field data belonging to a given object.
* - cache_filter: Stores filtered pieces of content.
* - cache_form: Stores multistep forms. Flushing this bin means that some
* forms displayed to users lose their state and the data already submitted
* to them. This bin should not be flushed before its expired time.
* - cache_menu: Stores the structure of visible navigation menus per page.
* - cache_page: Stores generated pages for anonymous users. It is flushed
* very often, whenever a page changes, at least for every node and comment
* submission. This is the only bin affected by the page cache setting on
* the administrator panel.
* - cache_path: Stores the system paths that have an alias.
* @param $expire
* One of the following values:
* - CACHE_PERMANENT: Indicates that the item should never be removed unless
......@@ -132,13 +126,16 @@ function cache_get_multiple(array &$cids, $bin = 'cache') {
* general cache wipe.
* - A Unix timestamp: Indicates that the item should be kept at least until
* the given time, after which it behaves like CACHE_TEMPORARY.
*
* @see _update_cache_set()
* @see cache_get()
*/
function cache_set($cid, $data, $bin = 'cache', $expire = CACHE_PERMANENT) {
return _cache_get_object($bin)->set($cid, $data, $expire);
}
/**
* Expire data from the cache.
* Expires data from the cache.
*
* If called without arguments, expirable entries will be cleared from the
* cache_page and cache_block bins.
......@@ -146,15 +143,12 @@ function cache_set($cid, $data, $bin = 'cache', $expire = CACHE_PERMANENT) {
* @param $cid
* If set, the cache ID to delete. Otherwise, all cache entries that can
* expire are deleted.
*
* @param $bin
* If set, the bin $bin to delete from. Mandatory
* argument if $cid is set.
*
* If set, the cache bin to delete from. Mandatory argument if $cid is set.
* @param $wildcard
* If $wildcard is TRUE, cache IDs starting with $cid are deleted in
* addition to the exact cache ID specified by $cid. If $wildcard is
* TRUE and $cid is '*' then the entire bin $bin is emptied.
* If TRUE, cache IDs starting with $cid are deleted in addition to the
* exact cache ID specified by $cid. If $wildcard is TRUE and $cid is '*',
* the entire cache bin is emptied.
*/
function cache_clear_all($cid = NULL, $bin = NULL, $wildcard = FALSE) {
if (!isset($cid) && !isset($bin)) {
......@@ -170,13 +164,14 @@ function cache_clear_all($cid = NULL, $bin = NULL, $wildcard = FALSE) {
}
/**
* Check if a cache bin is empty.
* Checks if a cache bin is empty.
*
* A cache bin is considered empty if it does not contain any valid data for any
* cache ID.
*
* @param $bin
* The cache bin to check.
*
* @return
* TRUE if the cache bin specified is empty.
*/
......@@ -185,7 +180,7 @@ function cache_is_empty($bin) {
}
/**
* Interface for cache implementations.
* Defines an interface for cache implementations.
*
* All cache implementations have to implement this interface.
* DrupalDatabaseCache provides the default implementation, which can be
......@@ -223,7 +218,7 @@ function cache_is_empty($bin) {
*/
interface DrupalCacheInterface {
/**
* Constructor.
* Constructs a new cache interface.
*
* @param $bin
* The cache bin for which the object is created.
......@@ -231,31 +226,34 @@ interface DrupalCacheInterface {
function __construct($bin);
/**
* Return data from the persistent cache. Data may be stored as either plain
* text or as serialized data. cache_get will automatically return
* unserialized objects and arrays.
* Returns data from the persistent cache.
*
* Data may be stored as either plain text or as serialized data. cache_get()
* will automatically return unserialized objects and arrays.
*
* @param $cid
* The cache ID of the data to retrieve.
*
* @return
* The cache or FALSE on failure.
*/
function get($cid);
/**
* Return data from the persistent cache when given an array of cache IDs.
* Returns data from the persistent cache when given an array of cache IDs.
*
* @param $cids
* An array of cache IDs for the data to retrieve. This is passed by
* reference, and will have the IDs successfully returned from cache
* removed.
*
* @return
* An array of the items successfully returned from cache indexed by cid.
*/
function getMultiple(&$cids);
/**
* Store data in the persistent cache.
* Stores data in the persistent cache.
*
* @param $cid
* The cache ID of the data to store.
......@@ -276,8 +274,10 @@ interface DrupalCacheInterface {
/**
* Expire data from the cache. If called without arguments, expirable
* entries will be cleared from the cache_page and cache_block bins.
* Expires data from the cache.
*
* If called without arguments, expirable entries will be cleared from the
* cache_page and cache_block bins.
*
* @param $cid
* If set, the cache ID to delete. Otherwise, all cache entries that can
......@@ -290,7 +290,7 @@ interface DrupalCacheInterface {
function clear($cid = NULL, $wildcard = FALSE);
/**
* Check if a cache bin is empty.
* Checks if a cache bin is empty.
*
* A cache bin is considered empty if it does not contain any valid data for
* any cache ID.
......@@ -302,7 +302,7 @@ interface DrupalCacheInterface {
}
/**
* Default cache implementation.
* Defines a default cache implementation.
*
* This is Drupal's default cache implementation. It uses the database to store
* cached data. Each cache bin corresponds to a database table by the same name.
......@@ -310,16 +310,25 @@ interface DrupalCacheInterface {
class DrupalDatabaseCache implements DrupalCacheInterface {
protected $bin;
/**
* Constructs a new DrupalDatabaseCache object.
*/
function __construct($bin) {
$this->bin = $bin;
}
/**
* Implements DrupalCacheInterface::get().
*/
function get($cid) {
$cids = array($cid);
$cache = $this->getMultiple($cids);
return reset($cache);
}
/**
* Implements DrupalCacheInterface::getMultiple().
*/
function getMultiple(&$cids) {
try {
// Garbage collection necessary when enforcing a minimum cache lifetime.
......@@ -357,11 +366,31 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
* The bin being requested.
*/
protected function garbageCollection() {
global $user;
$cache_lifetime = variable_get('cache_lifetime', 0);
// Clean-up the per-user cache expiration session data, so that the session
// handler can properly clean-up the session data for anonymous users.
if (isset($_SESSION['cache_expiration'])) {
$expire = REQUEST_TIME - $cache_lifetime;
foreach ($_SESSION['cache_expiration'] as $bin => $timestamp) {
if ($timestamp < $expire) {
unset($_SESSION['cache_expiration'][$bin]);
}
}
if (!$_SESSION['cache_expiration']) {
unset($_SESSION['cache_expiration']);
}
}
// Garbage collection necessary when enforcing a minimum cache lifetime.
// Garbage collection of temporary items is only necessary when enforcing
// a minimum cache lifetime.
if (!$cache_lifetime) {
return;
}
// When cache lifetime is in force, avoid running garbage collection too
// often since this will remove temporary cache items indiscriminately.
$cache_flush = variable_get('cache_flush_' . $this->bin, 0);
if ($cache_flush && ($cache_flush + variable_get('cache_lifetime', 0) <= REQUEST_TIME)) {
if ($cache_flush && ($cache_flush + $cache_lifetime <= REQUEST_TIME)) {
// Reset the variable immediately to prevent a meltdown in heavy load situations.
variable_set('cache_flush_' . $this->bin, 0);
// Time to flush old cache data
......@@ -373,13 +402,14 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
}
/**
* Prepare a cached item.
* Prepares a cached item.
*
* Checks that items are either permanent or did not expire, and unserializes
* data as appropriate.
*
* @param $cache
* An item loaded from cache_get() or cache_get_multiple().
*
* @return
* The item with data unserialized as appropriate or FALSE if there is no
* valid item to load.
......@@ -390,17 +420,16 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
if (!isset($cache->data)) {
return FALSE;
}
// If enforcing a minimum cache lifetime, validate that the data is
// currently valid for this user before we return it by making sure the cache
// entry was created before the timestamp in the current session's cache
// timer. The cache variable is loaded into the $user object by _drupal_session_read()
// in session.inc. If the data is permanent or we're not enforcing a minimum
// cache lifetime always return the cached data.
if ($cache->expire != CACHE_PERMANENT && variable_get('cache_lifetime', 0) && $user->cache > $cache->created) {
// This cache data is too old and thus not valid for us, ignore it.
// If the cached data is temporary and subject to a per-user minimum
// lifetime, compare the cache entry timestamp with the user session
// cache_expiration timestamp. If the cache entry is too old, ignore it.
if ($cache->expire != CACHE_PERMANENT && variable_get('cache_lifetime', 0) && isset($_SESSION['cache_expiration'][$this->bin]) && $_SESSION['cache_expiration'][$this->bin] > $cache->created) {
// Ignore cache data that is too old and thus not valid for this user.
return FALSE;
}
// If the data is permanent or not subject to a minimum cache lifetime,
// unserialize and return the cached data.
if ($cache->serialized) {
$cache->data = unserialize($cache->data);
}
......@@ -408,6 +437,9 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
return $cache;
}
/**
* Implements DrupalCacheInterface::set().
*/
function set($cid, $data, $expire = CACHE_PERMANENT) {
$fields = array(
'serialized' => 0,
......@@ -434,16 +466,18 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
}
}
/**
* Implements DrupalCacheInterface::clear().
*/
function clear($cid = NULL, $wildcard = FALSE) {
global $user;
if (empty($cid)) {
if (variable_get('cache_lifetime', 0)) {
// We store the time in the current user's $user->cache variable which
// will be saved into the sessions bin by _drupal_session_write(). We then
// simulate that the cache was flushed for this user by not returning
// cached data that was cached before the timestamp.
$user->cache = REQUEST_TIME;
// We store the time in the current user's session. We then simulate
// that the cache was flushed for this user by not returning cached
// data that was cached before the timestamp.
$_SESSION['cache_expiration'][$this->bin] = REQUEST_TIME;
$cache_flush = variable_get('cache_flush_' . $this->bin, 0);
if ($cache_flush == 0) {
......@@ -496,6 +530,9 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
}
}
/**
* Implements DrupalCacheInterface::isEmpty().
*/
function isEmpty() {
$this->garbageCollection();
$query = db_select($this->bin);
......
This diff is collapsed.
......@@ -41,7 +41,7 @@
* $result = db_query_range('SELECT n.nid, n.title, n.created
* FROM {node} n WHERE n.uid = :uid', 0, 10, array(':uid' => $uid));
* foreach ($result as $record) {
* // Perform operations on $node->title, etc. here.
* // Perform operations on $record->title, etc. here.
* }
* @endcode
* Curly braces are used around "node" to provide table prefixing via
......@@ -152,7 +152,7 @@
* }
*
* // $txn goes out of scope here. Unless the transaction was rolled back, it
* // gets automatically commited here.
* // gets automatically committed here.
* }
*
* function my_other_function($id) {
......@@ -167,7 +167,7 @@
* }
* @endcode
*
* @link http://drupal.org/developing/api/database
* @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.
*
......@@ -988,6 +1004,9 @@ abstract class DatabaseConnection extends PDO {
* @param $name
* Optional name of the savepoint.
*
* @return DatabaseTransaction
* A DatabaseTransaction object.
*
* @see DatabaseTransaction
*/
public function startTransaction($name = '') {
......@@ -1016,9 +1035,9 @@ abstract class DatabaseConnection extends PDO {
throw new DatabaseTransactionNoActiveException();
}
// A previous rollback to an earlier savepoint may mean that the savepoint
// in question has already been rolled back.
if (!in_array($savepoint_name, $this->transactionLayers)) {
return;
// in question has already been accidentally committed.
if (!isset($this->transactionLayers[$savepoint_name])) {
throw new DatabaseTransactionNoActiveException();
}
// We need to find the point we're rolling back to, all other savepoints
......@@ -1096,8 +1115,12 @@ abstract class DatabaseConnection extends PDO {
if (!$this->supportsTransactions()) {
return;
}
// The transaction has already been committed earlier. There is nothing we
// need to do. If this transaction was part of an earlier out-of-order
// rollback, an exception would already have been thrown by
// Database::rollback().
if (!isset($this->transactionLayers[$name])) {
throw new DatabaseTransactionNoActiveException();
return;
}
// Mark this layer as committable.
......@@ -1426,9 +1449,6 @@ abstract class Database {
/**
* Gets the connection object for the specified database key and target.
*
* Note: do not use the setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE) on the
* returned object because of http://bugs.php.net/bug.php?id=43139.
*
* @param $target
* The database target name.
* @param $key
......@@ -1623,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 {
......@@ -1690,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]);
}
}
......@@ -1848,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()) {
......@@ -1899,21 +1932,19 @@ class DatabaseTransaction {
}
/**
* A prepared statement.
* Represents a prepared statement.
*
* Some methods in that class are purposely commented out. Due to a change in
* Some methods in that class are purposefully commented out. Due to a change in
* how PHP defines PDOStatement, we can't define a signature for those methods
* that will work the same way between versions older than 5.2.6 and later
* versions.
*
* Please refer to http://bugs.php.net/bug.php?id=42452 for more details.
* versions. See http://bugs.php.net/bug.php?id=42452 for more details.
*
* Child implementations should either extend PDOStatement:
* @code
* class DatabaseStatement_oracle extends PDOStatement implements DatabaseStatementInterface {}
* @endcode
* or implement their own class, but in that case they will also have to
* implement the Iterator or IteratorArray interfaces before
* or define their own class. If defining their own class, they will also have
* to implement either the Iterator or IteratorAggregate interface before
* DatabaseStatementInterface:
* @code
* class DatabaseStatement_oracle implements Iterator, DatabaseStatementInterface {}
......@@ -1997,7 +2028,7 @@ interface DatabaseStatementInterface extends Traversable {
* The numeric index of the field to return. Defaults to the first field.
*
* @return
* A single field from the next record.
* A single field from the next record, or FALSE if there is no next record.
*/
public function fetchField($index = 0);
......@@ -2017,7 +2048,7 @@ interface DatabaseStatementInterface extends Traversable {
* helper method, so one is added.
*
* @return
* An associative array.
* An associative array, or FALSE if there is no next row.
*/
public function fetchAssoc();
......@@ -2045,7 +2076,7 @@ interface DatabaseStatementInterface extends Traversable {
* The index of the column number to fetch.
*
* @return
* An indexed array.
* An indexed array, or an empty array if there is no result set.
*/
public function fetchCol($index = 0);
......@@ -2065,7 +2096,7 @@ interface DatabaseStatementInterface extends Traversable {
* The numeric index of the field to use as the array value.
*
* @return
* An associative array.
* An associative array, or an empty array if there is no result set.
*/
public function fetchAllKeyed($key_index = 0, $value_index = 1);
......@@ -2084,7 +2115,7 @@ interface DatabaseStatementInterface extends Traversable {
* set for the query will be used.
*
* @return
* An associative array.
* An associative array, or an empty array if there is no result set.
*/
public function fetchAllAssoc($key, $fetch = NULL);
}
......@@ -2670,7 +2701,7 @@ function db_condition($conjunction) {
/**
* @ingroup schemaapi
* @addtogroup schemaapi
* @{
*/
......@@ -2767,7 +2798,7 @@ function _db_create_keys_sql($spec) {
* Renames a table.
*
* @param $table
* The table to be renamed.
* The current name of the table to be renamed.
* @param $new_name
* The new name for the table.
*/
......@@ -2987,7 +3018,7 @@ function db_change_field($table, $field, $field_new, $spec, $keys_new = array())
}
/**
* @} End of "ingroup schemaapi".
* @} End of "addtogroup schemaapi".
*/
/**
......
......@@ -128,9 +128,10 @@ class DatabaseLog {
* Determine the routine that called this query.
*
* We define "the routine that called this query" as the first entry in
* the call stack that is not inside includes/database. That makes the
* climbing logic very simple, and handles the variable stack depth caused
* by the query builders.
* the call stack that is not inside includes/database and does have a file
* (which excludes call_user_func_array(), anonymous functions and similar).
* That makes the climbing logic very simple, and handles the variable stack
* depth caused by the query builders.
*
* @link http://www.php.net/debug_backtrace
* @return
......@@ -144,7 +145,8 @@ class DatabaseLog {
$stack = debug_backtrace();
$stack_count = count($stack);
for ($i = 0; $i < $stack_count; ++$i) {
if (strpos($stack[$i]['file'], 'includes' . DIRECTORY_SEPARATOR . 'database') === FALSE) {
if (!empty($stack[$i]['file']) && strpos($stack[$i]['file'], 'includes' . DIRECTORY_SEPARATOR . 'database') === FALSE) {
$stack[$i] += array('args' => array());
return array(
'file' => $stack[$i]['file'],
'line' => $stack[$i]['line'],
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -328,9 +328,9 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
// rename them when renaming the table.
$indexes = $this->connection->query('SELECT indexname FROM pg_indexes WHERE schemaname = :schema AND tablename = :table', array(':schema' => $old_schema, ':table' => $old_table_name));
foreach ($indexes as $index) {
if (preg_match('/^' . preg_quote($old_full_name) . '_(.*)_idx$/', $index->indexname, $matches)) {
if (preg_match('/^' . preg_quote($old_full_name) . '_(.*)$/', $index->indexname, $matches)) {
$index_name = $matches[1];
$this->connection->query('ALTER INDEX ' . $index->indexname . ' RENAME TO {' . $new_name . '}_' . $index_name . '_idx');
$this->connection->query('ALTER INDEX ' . $index->indexname . ' RENAME TO {' . $new_name . '}_' . $index_name);
}
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.