diff options
-rw-r--r-- | includes/bootstrap.inc | 1 | ||||
-rw-r--r-- | includes/database/database.inc | 132 | ||||
-rw-r--r-- | includes/database/pgsql/query.inc | 92 | ||||
-rw-r--r-- | includes/database/schema.inc | 2 | ||||
-rw-r--r-- | includes/database/select.inc | 6 | ||||
-rw-r--r-- | includes/database/sqlite/query.inc | 10 | ||||
-rw-r--r-- | includes/install.core.inc | 1 | ||||
-rw-r--r-- | includes/install.inc | 20 | ||||
-rw-r--r-- | includes/theme.maintenance.inc | 1 | ||||
-rw-r--r-- | modules/simpletest/drupal_web_test_case.php | 2 |
10 files changed, 66 insertions, 201 deletions
diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc index 9060a0e2065..1e446f01b35 100644 --- a/includes/bootstrap.inc +++ b/includes/bootstrap.inc @@ -2244,7 +2244,6 @@ function _drupal_bootstrap_database() { // The database autoload routine comes first so that we can load the database // system without hitting the database. That is especially important during // the install or upgrade process. - spl_autoload_register('db_autoload'); spl_autoload_register('drupal_autoload_class'); spl_autoload_register('drupal_autoload_interface'); } diff --git a/includes/database/database.inc b/includes/database/database.inc index 98dafae8a47..c85e35a10cc 100644 --- a/includes/database/database.inc +++ b/includes/database/database.inc @@ -648,13 +648,20 @@ abstract class DatabaseConnection extends PDO { * * @param string $class * The class for which we want the potentially driver-specific class. + * @param array $files + * The name of the files in which the driver-specific class can be. + * @param $use_autoload + * If TRUE, attempt to load classes using PHP's autoload capability + * as well as the manual approach here. * @return string * The name of the class that should be used for this driver. */ - public function getDriverClass($class) { + public function getDriverClass($class, array $files = array(), $use_autoload = FALSE) { if (empty($this->driverClasses[$class])) { - $this->driverClasses[$class] = $class . '_' . $this->driver(); - if (!class_exists($this->driverClasses[$class])) { + $driver = $this->driver(); + $this->driverClasses[$class] = $class . '_' . $driver; + Database::loadDriverFile($driver, $files); + if (!class_exists($this->driverClasses[$class], $use_autoload)) { $this->driverClasses[$class] = $class; } } @@ -681,7 +688,7 @@ abstract class DatabaseConnection extends PDO { * @see SelectQuery */ public function select($table, $alias = NULL, array $options = array()) { - $class = $this->getDriverClass('SelectQuery'); + $class = $this->getDriverClass('SelectQuery', array('query.inc', 'select.inc')); return new $class($table, $alias, $this, $options); } @@ -697,7 +704,7 @@ abstract class DatabaseConnection extends PDO { * @see InsertQuery */ public function insert($table, array $options = array()) { - $class = $this->getDriverClass('InsertQuery'); + $class = $this->getDriverClass('InsertQuery', array('query.inc')); return new $class($this, $table, $options); } @@ -713,7 +720,7 @@ abstract class DatabaseConnection extends PDO { * @see MergeQuery */ public function merge($table, array $options = array()) { - $class = $this->getDriverClass('MergeQuery'); + $class = $this->getDriverClass('MergeQuery', array('query.inc')); return new $class($this, $table, $options); } @@ -730,7 +737,7 @@ abstract class DatabaseConnection extends PDO { * @see UpdateQuery */ public function update($table, array $options = array()) { - $class = $this->getDriverClass('UpdateQuery'); + $class = $this->getDriverClass('UpdateQuery', array('query.inc')); return new $class($this, $table, $options); } @@ -746,7 +753,7 @@ abstract class DatabaseConnection extends PDO { * @see DeleteQuery */ public function delete($table, array $options = array()) { - $class = $this->getDriverClass('DeleteQuery'); + $class = $this->getDriverClass('DeleteQuery', array('query.inc')); return new $class($this, $table, $options); } @@ -762,7 +769,7 @@ abstract class DatabaseConnection extends PDO { * @see TruncateQuery */ public function truncate($table, array $options = array()) { - $class = $this->getDriverClass('TruncateQuery'); + $class = $this->getDriverClass('TruncateQuery', array('query.inc')); return new $class($this, $table, $options); } @@ -776,7 +783,7 @@ abstract class DatabaseConnection extends PDO { */ public function schema() { if (empty($this->schema)) { - $class = $this->getDriverClass('DatabaseSchema'); + $class = $this->getDriverClass('DatabaseSchema', array('schema.inc')); if (class_exists($class)) { $this->schema = new $class($this); } @@ -1581,6 +1588,34 @@ abstract class Database { self::$ignoreTargets[$key][$target] = TRUE; } + /** + * Load a file for the database that might hold a class. + * + * @param $driver + * The name of the driver. + * @param array $files + * The name of the files the driver specific class can be. + */ + public static function loadDriverFile($driver, array $files = array()) { + static $base_path; + + if (empty($base_path)) { + $base_path = dirname(realpath(__FILE__)); + } + + $driver_base_path = "$base_path/$driver"; + foreach ($files as $file) { + // Load the base file first so that classes extending base classes will + // have the base class loaded. + foreach (array("$base_path/$file", "$driver_base_path/$file") as $filename) { + // The OS caches file_exists() and PHP caches require_once(), so + // we'll let both of those take care of performance here. + if (file_exists($filename)) { + require_once $filename; + } + } + } + } } /** @@ -2109,82 +2144,6 @@ class DatabaseStatementEmpty implements Iterator, DatabaseStatementInterface { } /** - * Autoload callback for the database system. - */ -function db_autoload($class) { - static $base_path = ''; - static $checked = array(); - - static $files = array( - 'query.inc' => array( - 'QueryPlaceholderInterface', - 'QueryConditionInterface', 'DatabaseCondition', - 'Query', 'DeleteQuery', 'InsertQuery', 'UpdateQuery', 'MergeQuery', 'TruncateQuery', - 'QueryAlterableInterface', - ), - 'select.inc' => array('QueryAlterableInterface', 'SelectQueryInterface', 'SelectQuery', 'SelectQueryExtender'), - 'database.inc' => array('DatabaseConnection'), - 'log.inc' => array('DatabaseLog'), - 'prefetch.inc' => array('DatabaseStatementPrefetch'), - 'schema.inc' => array('DatabaseSchema'), - ); - - // If a class doesn't exist, it may get checked a second time - // by class_exists(). If so, just bail out now. - if (isset($checked[$class])) { - return; - } - $checked[$class] = TRUE; - - if (empty($base_path)) { - $base_path = dirname(realpath(__FILE__)); - } - - // If there is an underscore in the class name, we know it's a - // driver-specific file so check for those. If not, it's a generic. - // Note that we use require_once here instead of require because of a - // quirk in class_exists(). By default, class_exists() will try to - // autoload a class if it's not found. However, we cannot tell - // at this point whether or not the class is going to exist, only - // the file that it would be in if it does exist. That means we may - // try to include a file that was already included by another - // autoload call, which would break. Using require_once() neatly - // avoids that issue. - if (strpos($class, '_') !== FALSE) { - list($base, $driver) = explode('_', $class); - - // Drivers have an extra file, and may put their SelectQuery implementation - // in the main query file since it's so small. - $driver_files = $files; - $driver_files['query.inc'][] = 'SelectQuery'; - $driver_files['install.inc'] = array('DatabaseTasks'); - - foreach ($driver_files as $file => $classes) { - if (in_array($base, $classes)) { - $filename = "{$base_path}/{$driver}/{$file}"; - // We might end up looking in a file that doesn't exist, so check that. - if (file_exists($filename)) { - require_once $filename; - // If the class now exists, we're done. Otherwise keep searching in - // additional files. - if (class_exists($class, FALSE) || interface_exists($class, FALSE)) { - return; - } - } - } - } - } - else { - foreach ($files as $file => $classes) { - if (in_array($class, $classes)) { - require_once $base_path . '/' . $file; - return; - } - } - } -} - -/** * The following utility functions are simply convenience wrappers. * * They should never, ever have any database-specific code in them. @@ -2915,4 +2874,3 @@ function db_ignore_slave() { $_SESSION['ignore_slave_server'] = REQUEST_TIME + $duration; } } - diff --git a/includes/database/pgsql/query.inc b/includes/database/pgsql/query.inc index 2214d668a7c..c475a00111a 100644 --- a/includes/database/pgsql/query.inc +++ b/includes/database/pgsql/query.inc @@ -208,95 +208,3 @@ class UpdateQuery_pgsql extends UpdateQuery { return $stmt->rowCount(); } } - -class SelectQuery_pgsql extends SelectQuery { - - public function orderRandom() { - $alias = $this->addExpression('RANDOM()', 'random_field'); - $this->orderBy($alias); - return $this; - } - - /** - * Overrides SelectQuery::orderBy(). - * - * PostgreSQL adheres strictly to the SQL-92 standard and requires that when - * using DISTINCT or GROUP BY conditions, fields and expressions that are - * ordered on also need to be selected. This is a best effort implementation - * to handle the cases that can be automated by adding the field if it is not - * yet selected. - * - * @code - * $query = db_select('node', 'n'); - * $query->join('node_revision', 'nr', 'n.vid = nr.vid'); - * $query - * ->distinct() - * ->fields('n') - * ->orderBy('timestamp'); - * @endcode - * - * In this query, it is not possible (without relying on the schema) to know - * whether timestamp belongs to node_revisions and needs to be added or - * belongs to node and is already selected. Queries like this will need to be - * corrected in the original query by adding an explicit call to - * SelectQuery::addField() or SelectQuery::fields(). - * - * Since this has a small performance impact, both by the additional - * processing in this function and in the database that needs to return the - * additional fields, this is done as an override instead of implementing it - * directly in SelectQuery::orderBy(). - */ - public function orderBy($field, $direction = 'ASC') { - // Call parent function to order on this. - $return = parent::orderBy($field, $direction); - - // If there is a table alias specified, split it up. - if (strpos($field, '.') !== FALSE) { - list($table, $table_field) = explode('.', $field); - } - // Figure out if the field has already been added. - foreach ($this->fields as $existing_field) { - if (!empty($table)) { - // If table alias is given, check if field and table exists. - if ($existing_field['table'] == $table && $existing_field['field'] == $table_field) { - return $return; - } - } - else { - // If there is no table, simply check if the field exists as a field or - // an aliased field. - if ($existing_field['alias'] == $field) { - return $return; - } - } - } - - // Also check expression aliases. - foreach ($this->expressions as $expression) { - if ($expression['alias'] == $field) { - return $return; - } - } - - // If a table loads all fields, it can not be added again. It would - // result in an ambigious alias error because that field would be loaded - // twice: Once through table_alias.* and once directly. If the field - // actually belongs to a different table, it must be added manually. - foreach ($this->tables as $table) { - if (!empty($table['all_fields'])) { - return $return; - } - } - - // If $field contains an characters which are not allowed in a field name - // it is considered an expression, these can't be handeld automatically - // either. - if ($this->connection->escapeField($field) != $field) { - return $return; - } - - // This is a case that can be handled automatically, add the field. - $this->addField(NULL, $field); - return $return; - } -} diff --git a/includes/database/schema.inc b/includes/database/schema.inc index 187f9e6b864..36c7964c62f 100644 --- a/includes/database/schema.inc +++ b/includes/database/schema.inc @@ -6,6 +6,8 @@ * Generic Database schema code. */ +require_once dirname(__FILE__) . '/query.inc'; + /** * @defgroup schemaapi Schema API * @{ diff --git a/includes/database/select.inc b/includes/database/select.inc index 7780fc5cdd1..b0d0eb275ec 100644 --- a/includes/database/select.inc +++ b/includes/database/select.inc @@ -6,6 +6,8 @@ * @{ */ +require_once dirname(__FILE__) . '/query.inc'; + /** * Interface for extendable query objects. * @@ -642,7 +644,9 @@ class SelectQueryExtender implements SelectQueryInterface { /* Implementations of QueryExtendableInterface. */ public function extend($extender_name) { - $class = $this->connection->getDriverClass($extender_name); + // The extender can be anywhere so this needs to go to the registry, which + // is surely loaded by now. + $class = $this->connection->getDriverClass($extender_name, array(), TRUE); return new $class($this, $this->connection); } diff --git a/includes/database/sqlite/query.inc b/includes/database/sqlite/query.inc index ec2b57a2c05..158da3d0a64 100644 --- a/includes/database/sqlite/query.inc +++ b/includes/database/sqlite/query.inc @@ -12,16 +12,6 @@ */ /** - * SQLite specific query builder for SELECT statements. - */ -class SelectQuery_sqlite extends SelectQuery { - public function forUpdate($set = TRUE) { - // SQLite does not support FOR UPDATE so nothing to do. - return $this; - } -} - -/** * SQLite specific implementation of InsertQuery. * * We ignore all the default fields and use the clever SQLite syntax: diff --git a/includes/install.core.inc b/includes/install.core.inc index 5b01eb634cd..6a8c6f4407f 100644 --- a/includes/install.core.inc +++ b/includes/install.core.inc @@ -289,7 +289,6 @@ function install_begin_request(&$install_state) { // Initialize the database system. Note that the connection // won't be initialized until it is actually requested. require_once DRUPAL_ROOT . '/includes/database/database.inc'; - spl_autoload_register('db_autoload'); // Verify the last completed task in the database, if there is one. $task = install_verify_completed_task(); diff --git a/includes/install.inc b/includes/install.inc index 2c9810a08ed..1b7d7a79646 100644 --- a/includes/install.inc +++ b/includes/install.inc @@ -254,7 +254,6 @@ function drupal_get_database_types() { // Because we have no registry yet, we need to also include the install.inc // file for the driver explicitly. require_once DRUPAL_ROOT . '/includes/database/database.inc'; - spl_autoload_register('db_autoload'); foreach (file_scan_directory(DRUPAL_ROOT . '/includes/database', '/^[a-z]*$/i', array('recurse' => FALSE)) as $file) { if (file_exists($file->uri . '/database.inc') && file_exists($file->uri . '/install.inc')) { $drivers[$file->filename] = $file->uri; @@ -262,8 +261,7 @@ function drupal_get_database_types() { } foreach ($drivers as $driver => $file) { - $class = 'DatabaseTasks_' . $driver; - $installer = new $class(); + $installer = db_installer_object($driver); if ($installer->installable()) { $databases[$driver] = $installer; } @@ -1248,8 +1246,18 @@ function install_profile_info($profile, $locale = 'en') { * encoding. */ function db_run_tasks($driver) { - $task_class = 'DatabaseTasks_' . $driver; - $DatabaseTasks = new $task_class(); - $DatabaseTasks->runTasks(); + db_installer_object($driver)->runTasks(); return TRUE; } + +/** + * Returns a database installer object. + * + * @param $driver + * The name of the driver. + */ +function db_installer_object($driver) { + Database::loadDriverFile($driver, array('install.inc')); + $task_class = 'DatabaseTasks_' . $driver; + return new $task_class(); +} diff --git a/includes/theme.maintenance.inc b/includes/theme.maintenance.inc index 7cc03126f15..4950d8278b3 100644 --- a/includes/theme.maintenance.inc +++ b/includes/theme.maintenance.inc @@ -41,7 +41,6 @@ function _drupal_maintenance_theme() { // to work. See _drupal_log_error(). if (!class_exists('Database', FALSE)) { require_once DRUPAL_ROOT . '/includes/database/database.inc'; - spl_autoload_register('db_autoload'); } // We use the default theme as the maintenance theme. If a default theme diff --git a/modules/simpletest/drupal_web_test_case.php b/modules/simpletest/drupal_web_test_case.php index c5c63d8c51e..e50adda6288 100644 --- a/modules/simpletest/drupal_web_test_case.php +++ b/modules/simpletest/drupal_web_test_case.php @@ -611,8 +611,6 @@ class DrupalUnitTestCase extends DrupalTestCase { // Store necessary current values before switching to the test environment. $this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files'); - spl_autoload_register('db_autoload'); - // Reset all statics so that test is performed with a clean environment. drupal_static_reset(); |