=== modified file 'includes/bootstrap.inc' --- includes/bootstrap.inc 2008-11-24 10:41:39 +0000 +++ includes/bootstrap.inc 2008-11-29 23:15:44 +0000 @@ -428,8 +428,7 @@ function conf_init() { global $base_url, $base_path, $base_root; // Export the following settings.php variables to the global namespace - global $databases, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access; - $conf = array(); + global $db_prefix, $cookie_domain, $installed_profile, $update_free_access; if (!drupal_valid_http_host()) { // HTTP_HOST is invalid, e.g. if containing slashes it may be an attack. @@ -581,7 +580,8 @@ function drupal_get_filename($type, $nam * with variable_set() as well as those explicitly specified in the configuration * file. */ -function variable_init($conf = array()) { +function variable_init() { + $db_active = db_set_active('_bootstrap'); // NOTE: caching the variables improves performance by 20% when serving cached pages. if ($cached = cache_get('variables', 'cache')) { $variables = $cached->data; @@ -590,10 +590,7 @@ function variable_init($conf = array()) $variables = array_map('unserialize', db_query('SELECT name, value FROM {variable}')->fetchAllKeyed()); cache_set('variables', $variables); } - - foreach ($conf as $name => $value) { - $variables[$name] = $value; - } + db_set_active($db_active); return $variables; } @@ -626,9 +623,11 @@ function variable_get($name, $default) { function variable_set($name, $value) { global $conf; + $active_db = db_set_active('_bootstrap'); db_merge('variable')->key(array('name' => $name))->fields(array('value' => serialize($value)))->execute(); cache_clear_all('variables', 'cache'); + db_set_active($active_db); $conf[$name] = $value; } @@ -642,10 +641,12 @@ function variable_set($name, $value) { function variable_del($name) { global $conf; + $active_db = db_set_active('_bootstrap'); db_delete('variable') ->condition('name', $name) ->execute(); cache_clear_all('variables', 'cache'); + db_set_active($active_db); unset($conf[$name]); } @@ -1052,7 +1053,7 @@ function drupal_anonymous_user($session * DRUPAL_BOOTSTRAP_FULL: Drupal is fully loaded, validate and fix input data. */ function drupal_bootstrap($phase = NULL) { - static $phases = array(DRUPAL_BOOTSTRAP_CONFIGURATION, DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE, DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_VARIABLES, DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), $completed_phase = -1; + static $phases = array(DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), $completed_phase = -1; if (isset($phase)) { while ($phases && $phase > $completed_phase) { @@ -1076,22 +1077,39 @@ function drupal_get_bootstrap_phase() { } function _drupal_bootstrap($phase) { - global $conf; + global $conf, $databases; switch ($phase) { - case DRUPAL_BOOTSTRAP_CONFIGURATION: + case DRUPAL_BOOTSTRAP_DATABASE: + // Allow specifying special cache handlers using memcached or files for + // storing cache information. + require_once DRUPAL_ROOT . '/' . variable_get('cache_inc', 'includes/cache.inc'); + // 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'; + // Register autoload functions so that we can access classes and interfaces. + spl_autoload_register('drupal_autoload_class'); + spl_autoload_register('drupal_autoload_interface'); + // Initialize configuration variables. + $conf = variable_init(); drupal_initialize_variables(); - // Start a page timer: - timer_start('page'); // Initialize the configuration conf_init(); + $databases = variable_get('databases', NULL); + // If there are no databases then we need to install. + if (!$databases && basename($_SERVER['SCRIPT_NAME']) != 'install.php') { + require_once DRUPAL_ROOT . '/includes/install.inc'; + install_goto('install.php'); + } + else { + db_set_active(); + } + // Start a page timer: + timer_start('page'); break; case DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE: - // Allow specifying special cache handlers in settings.php, like - // using memcached or files for storing cache information. - require_once DRUPAL_ROOT . '/' . variable_get('cache_inc', 'includes/cache.inc'); // If the page_cache_fastpath is set to TRUE in settings.php and // page_cache_fastpath (implemented in the special implementation of // cache.inc) printed the page and indicated this with a returned TRUE @@ -1101,15 +1119,6 @@ function _drupal_bootstrap($phase) { } break; - case DRUPAL_BOOTSTRAP_DATABASE: - // 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'; - // Register autoload functions so that we can access classes and interfaces. - spl_autoload_register('drupal_autoload_class'); - spl_autoload_register('drupal_autoload_interface'); - break; - case DRUPAL_BOOTSTRAP_ACCESS: // Deny access to blocked IP addresses - t() is not yet available. if (drupal_is_denied(ip_address())) { @@ -1125,11 +1134,6 @@ function _drupal_bootstrap($phase) { session_start(); break; - case DRUPAL_BOOTSTRAP_VARIABLES: - // Initialize configuration variables, using values from settings.php if available. - $conf = variable_init(isset($conf) ? $conf : array()); - break; - case DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE: $cache_mode = variable_get('cache', CACHE_DISABLED); // Get the page from the cache. @@ -1477,8 +1481,11 @@ function drupal_autoload_class($class) { * NULL if either of the REGISTRY_* constants is passed in as $type. */ function _registry_check_code($type, $name = NULL) { - static $lookup_cache, $cache_update_needed; + static $lookup_cache, $cache_update_needed, $connection; + if (!isset($connection)) { + $connection = Database::getConnection('_bootstrap'); + } if (!isset($lookup_cache)) { $lookup_cache = _registry_get_lookup_cache(); } @@ -1513,7 +1520,7 @@ function _registry_check_code($type, $na // This function may get called when the default database is not active, but // there is no reason we'd ever want to not use the default database for // this query. - $file = Database::getConnection('default')->query("SELECT filename FROM {registry} WHERE name = :name AND type = :type", array( + $file = $connection->query("SELECT filename FROM {registry} WHERE name = :name AND type = :type", array( ':name' => $name, ':type' => $type, )) === modified file 'includes/cache.inc' --- includes/cache.inc 2008-10-12 04:30:05 +0000 +++ includes/cache.inc 2008-11-29 23:15:44 +0000 @@ -17,6 +17,9 @@ function cache_get($cid, $table = 'cache') { global $user; + if ($table == 'cache_registry') { + $db_active = db_set_active('_bootstrap'); + } // Garbage collection necessary when enforcing a minimum cache lifetime $cache_flush = variable_get('cache_flush', 0); if ($cache_flush && ($cache_flush + variable_get('cache_lifetime', 0) <= REQUEST_TIME)) { @@ -30,6 +33,9 @@ function cache_get($cid, $table = 'cache } $cache = db_query("SELECT data, created, headers, expire, serialized FROM {" . $table . "} WHERE cid = :cid", array(':cid' => $cid))->fetchObject(); + if ($table == 'cache_registry') { + db_set_active($db_active); + } if (isset($cache->data)) { // If the data is permanent or we're not enforcing a minimum cache lifetime // always return the cached data. @@ -119,11 +125,16 @@ function cache_set($cid, $data, $table = $fields['data'] = $data; $fields['serialized'] = 0; } - + if ($table == 'cache_registry') { + $db_active = db_set_active('_bootstrap'); + } db_merge($table) ->key(array('cid' => $cid)) ->fields($fields) ->execute(); + if ($table == 'cache_registry') { + db_set_active($db_active); + } } /** @@ -155,6 +166,9 @@ function cache_clear_all($cid = NULL, $t return; } + if ($table == 'cache_registry') { + $db_active = db_set_active('_bootstrap'); + } if (empty($cid)) { if (variable_get('cache_lifetime', 0)) { // We store the time in the current user's $user->cache variable which @@ -203,4 +217,7 @@ function cache_clear_all($cid = NULL, $t ->execute(); } } + if ($table == 'cache_registry') { + db_set_active($db_active); + } } === modified file 'includes/database/database.inc' --- includes/database/database.inc 2008-11-22 13:51:38 +0000 +++ includes/database/database.inc 2008-11-29 23:15:44 +0000 @@ -797,7 +797,15 @@ abstract class Database { * * @var array */ - static protected $databaseInfo = NULL; + static protected $databaseInfo = array( + '_bootstrap' => array( + 'default' => array( + 'driver' => 'sqlite', + 'database' => 'sites/default/files/.ht.boot.sqlite', + ), + ), + ); + /** * A list of key/target credentials to simply ignore. @@ -811,7 +819,7 @@ abstract class Database { * * @var string */ - static protected $activeKey = 'default'; + static protected $activeKey = '_bootstrap'; /** * An array of active query log objects. @@ -949,7 +957,7 @@ abstract class Database { * The previous database connection key. */ final public static function setActiveConnection($key = 'default') { - if (empty(self::$databaseInfo)) { + if (empty(self::$databaseInfo[$key])) { self::parseConnectionInfo(); } @@ -968,7 +976,7 @@ abstract class Database { _db_check_install_needed(); - $databaseInfo = $databases; + $databaseInfo = $databases ? $databases : array(); foreach ($databaseInfo as $index => $info) { foreach ($databaseInfo[$index] as $target => $value) { // If there is no "driver" property, then we assume it's an array of @@ -980,7 +988,7 @@ abstract class Database { } } - self::$databaseInfo = $databaseInfo; + self::$databaseInfo = $databaseInfo + self::$databaseInfo; } /** @@ -1016,7 +1024,7 @@ abstract class Database { * The connection key for which we want information. */ final public static function getConnectionInfo($key = 'default') { - if (empty(self::$databaseInfo)) { + if (empty(self::$databaseInfo[$key])) { self::parseConnectionInfo(); } === modified file 'includes/database/sqlite/database.inc' --- includes/database/sqlite/database.inc 2008-11-23 06:06:15 +0000 +++ includes/database/sqlite/database.inc 2008-11-29 23:15:44 +0000 @@ -31,6 +31,7 @@ class DatabaseConnection_sqlite extends $this->transactionSupport = isset($connection_options['transactions']) ? $connection_options['transactions'] : TRUE; + $this->readOnly = !is_writable($connection_options['database']); parent::__construct('sqlite:'. $connection_options['database'], '', '', $connection_options); $this->exec('PRAGMA encoding="UTF-8"'); === modified file 'includes/database/sqlite/query.inc' --- includes/database/sqlite/query.inc 2008-11-23 06:06:15 +0000 +++ includes/database/sqlite/query.inc 2008-11-29 23:15:44 +0000 @@ -16,7 +16,7 @@ class InsertQuery_sqlite extends InsertQuery { public function execute() { - if (count($this->insertFields) + count($this->defaultFields) == 0) { + if ($this->connection->readOnly || count($this->insertFields) + count($this->defaultFields) == 0) { return NULL; } if (count($this->insertFields)) { @@ -69,6 +69,9 @@ class UpdateQuery_sqlite extends UpdateQ } public function execute() { + if ($this->connection->readOnly) { + return FALSE; + } // Get the fields used in the update query, and remove those that are already // in the condition. $fields = $this->expressionFields + $this->fields; @@ -115,6 +118,9 @@ class UpdateQuery_sqlite extends UpdateQ */ class DeleteQuery_sqlite extends DeleteQuery { public function execute() { + if ($this->connection->readOnly) { + return FALSE; + } if (!count($this->condition)) { $total_rows = $this->connection->query('SELECT COUNT(*) FROM {' . $this->connection->escapeTable($this->table) . '}')->fetchField(); parent::execute(); === modified file 'includes/install.inc' --- includes/install.inc 2008-11-24 10:41:39 +0000 +++ includes/install.inc 2008-11-29 23:15:44 +0000 @@ -537,27 +537,6 @@ function _drupal_install_module($module) } /** - * Manually include all files for the active database. - * - * Because we have no registry yet, we need to manually include the - * necessary database include files. - */ -function drupal_install_init_database() { - static $included = FALSE; - - if (!$included) { - $connection_info = Database::getConnectionInfo(); - $driver = $connection_info['default']['driver']; - require_once DRUPAL_ROOT . '/includes/database/query.inc'; - require_once DRUPAL_ROOT . '/includes/database/select.inc'; - require_once DRUPAL_ROOT . '/includes/database/schema.inc'; - foreach (glob(DRUPAL_ROOT . '/includes/database/' . $driver . '/*.inc') as $include_file) { - require_once $include_file; - } - } -} - -/** * Callback to install the system module. * * Separated from the installation of other modules so core system @@ -566,14 +545,12 @@ function drupal_install_init_database() function drupal_install_system() { $system_path = dirname(drupal_get_filename('module', 'system', NULL)); require_once DRUPAL_ROOT . '/' . $system_path . '/system.install'; - drupal_install_init_database(); module_invoke('system', 'install'); $system_versions = drupal_get_schema_versions('system'); $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED; db_query("INSERT INTO {system} (filename, name, type, owner, status, schema_version) VALUES('%s', '%s', '%s', '%s', %d, %d)", $system_path . '/system.module', 'system', 'module', '', 1, $system_version); // Now that we've installed things properly, bootstrap the full Drupal environment - drupal_install_init_database(); drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); module_rebuild_cache(); } === modified file 'includes/module.inc' --- includes/module.inc 2008-11-24 10:41:39 +0000 +++ includes/module.inc 2008-11-29 23:15:44 +0000 @@ -427,7 +427,7 @@ function module_implements($hook, $sort $cached_hooks = count($implementations); } if (!isset($implementations[$hook])) { - $implementations[$hook] = db_query("SELECT module FROM {registry} WHERE type = 'function' AND suffix = :hook ORDER BY weight, module", array(':hook' => $hook))->fetchCol(); + $implementations[$hook] = Database::getConnection('_bootstrap')->query("SELECT module FROM {registry} WHERE type = 'function' AND suffix = :hook ORDER BY weight, module", array(':hook' => $hook))->fetchCol(); } foreach ($implementations[$hook] as $module) { $function = $module . '_' . $hook; === modified file 'includes/registry.inc' --- includes/registry.inc 2008-11-16 19:41:14 +0000 +++ includes/registry.inc 2008-11-29 23:15:44 +0000 @@ -53,6 +53,7 @@ function _registry_rebuild() { $files["$filename"] = array('module' => '', 'weight' => 0); } + $active_db = db_set_active('_bootstrap'); foreach (registry_get_parsed_files() as $filename => $file) { // Add the md5 to those files we've already parsed. if (isset($files[$filename])) { @@ -89,6 +90,7 @@ function _registry_rebuild() { if (count($unchanged_resources) > 0) { _registry_set_lookup_cache($unchanged_resources); } + db_set_active($active_db); } /** === modified file 'install.php' --- install.php 2008-11-24 10:41:39 +0000 +++ install.php 2008-11-29 23:15:44 +0000 @@ -34,12 +34,12 @@ function install_main() { } require_once DRUPAL_ROOT . '/includes/bootstrap.inc'; - drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION); + drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE); // This must go after drupal_bootstrap(), which unsets globals! global $profile, $install_locale, $conf; - require_once DRUPAL_ROOT . '/modules/system/system.install'; + require_once DRUPAL_ROOT . '/includes/module.inc'; require_once DRUPAL_ROOT . '/includes/file.inc'; // Ensure correct page headers are sent (e.g. caching) @@ -48,13 +48,10 @@ function install_main() { // Set up $language, so t() caller functions will still work. drupal_init_language(); - // Load module basics (needed for hook invokes). - include_once DRUPAL_ROOT . '/includes/module.inc'; - $module_list['system']['filename'] = 'modules/system/system.module'; - $module_list['filter']['filename'] = 'modules/filter/filter.module'; - module_list(TRUE, FALSE, $module_list); - drupal_load('module', 'system'); - drupal_load('module', 'filter'); + // Load filter and system modules here. + db_set_active('_bootstrap'); + module_load_all(); + db_set_active(); // Set up theme system for the maintenance page. drupal_maintenance_theme(); @@ -62,33 +59,11 @@ function install_main() { // Check existing settings.php. $verify = install_verify_settings(); - if ($verify) { - // Since we have a database connection, we use the normal cache system. - // This is important, as the installer calls into the Drupal system for - // the clean URL checks, so we should maintain the cache properly. - require_once DRUPAL_ROOT . '/includes/cache.inc'; - $conf['cache_inc'] = 'includes/cache.inc'; - - // 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'; - // Check if Drupal is installed. $task = install_verify_drupal(); if ($task == 'done') { install_already_done_error(); } - } - else { - // Since no persistent storage is available yet, and functions that check - // for cached data will fail, we temporarily replace the normal cache - // system with a stubbed-out version that short-circuits the actual - // caching process and avoids any errors. - require_once DRUPAL_ROOT . '/includes/cache-install.inc'; - $conf['cache_inc'] = 'includes/cache-install.inc'; - - $task = NULL; - } // Decide which profile to use. if (!empty($_GET['profile'])) { @@ -162,9 +137,8 @@ function install_main() { * Verify if Drupal is installed. */ function install_verify_drupal() { - // Read the variable manually using the @ so we don't trigger an error if it fails. try { - if ($result = db_query("SELECT value FROM {variable} WHERE name = '%s'", 'install_task')) { + if ($result = Database::getConnection('_bootstrap')->query("SELECT value FROM {variable} WHERE name = 'install_task'")) { return unserialize(db_result($result)); } } @@ -390,15 +364,11 @@ function install_settings_form_submit($f global $profile, $install_locale; $database = array_intersect_key($form_state['values']['_database'], array_flip(array('driver', 'database', 'username', 'password', 'host', 'port'))); - // Update global settings array and save - $settings['databases'] = array( - 'value' => array('default' => array('default' => $database)), - 'required' => TRUE, - ); $settings['db_prefix'] = array( 'value' => $form_state['values']['db_prefix'], 'required' => TRUE, ); + variable_set('databases', array('default' => array('default' => $database))); drupal_rewrite_settings($settings); // Continue to install profile step @@ -625,7 +595,6 @@ function install_tasks($profile, $task) // Bootstrap newly installed Drupal, while preserving existing messages. $messages = isset($_SESSION['messages']) ? $_SESSION['messages'] : ''; - drupal_install_init_database(); drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); $_SESSION['messages'] = $messages;