Skip to content

Commit

Permalink
- Patch #225450 by Crell, chx, bjaspan, catch, swentel, recidive et a…
Browse files Browse the repository at this point in the history
…l: next generation database layer for Drupal 7.
  • Loading branch information
dbuytaert committed Aug 21, 2008
1 parent 0e79597 commit 69e6f41
Show file tree
Hide file tree
Showing 61 changed files with 6,451 additions and 3,744 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

Drupal 7.0, xxxx-xx-xx (development version)
----------------------
- Database:
* Fully rewritten database layer utilizing PHP 5's PDO abstraction layer.
* Added query builders for INSERT, UPDATE, DELETE, MERGE, and SELECT queries.
* Support for Master/slave replication, transactions, multi-insert queries,
delayed inserts, and other features.
- Security:
* Protected cron.php -- cron will only run if the proper key is provided.
* Changed to much stronger password hashes that are also compatible with the
Expand Down
172 changes: 128 additions & 44 deletions includes/bootstrap.inc
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ function conf_init() {
global $base_url, $base_path, $base_root;

// Export the following settings.php variables to the global namespace
global $db_url, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access;
global $databases, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access;
$conf = array();

if (file_exists('./' . conf_path() . '/settings.php')) {
Expand Down Expand Up @@ -520,11 +520,7 @@ function variable_get($name, $default) {
function variable_set($name, $value) {
global $conf;

$serialized_value = serialize($value);
db_query("UPDATE {variable} SET value = '%s' WHERE name = '%s'", $serialized_value, $name);
if (!db_affected_rows()) {
@db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')", $name, $serialized_value);
}
db_merge('variable')->key(array('name' => $name))->fields(array('value' => serialize($value)))->execute();

cache_clear_all('variables', 'cache');

Expand Down Expand Up @@ -813,24 +809,33 @@ function request_uri() {
function watchdog($type, $message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL) {
global $user, $base_root;

// Prepare the fields to be logged
$log_message = array(
'type' => $type,
'message' => $message,
'variables' => $variables,
'severity' => $severity,
'link' => $link,
'user' => $user,
'request_uri' => $base_root . request_uri(),
'referer' => referer_uri(),
'ip' => ip_address(),
'timestamp' => time(),
static $in_error_state = FALSE;

// It is possible that the error handling will itself trigger an error. In that case, we could
// end up in an infinite loop. To avoid that, we implement a simple static semaphore.
if (!$in_error_state) {
$in_error_state = TRUE;

// Prepare the fields to be logged
$log_message = array(
'type' => $type,
'message' => $message,
'variables' => $variables,
'severity' => $severity,
'link' => $link,
'user' => $user,
'request_uri' => $base_root . request_uri(),
'referer' => referer_uri(),
'ip' => ip_address(),
'timestamp' => time(),
);

// Call the logging hooks to log/process the message
foreach (module_implements('watchdog', TRUE) as $module) {
module_invoke($module, 'watchdog', $log_message);
// Call the logging hooks to log/process the message
foreach (module_implements('watchdog', TRUE) as $module) {
module_invoke($module, 'watchdog', $log_message);
}
}
$in_error_state = FALSE;
}

/**
Expand Down Expand Up @@ -973,9 +978,24 @@ function drupal_bootstrap($phase) {
$current_phase = $phases[$phase_index];
unset($phases[$phase_index++]);
_drupal_bootstrap($current_phase);

global $_drupal_current_bootstrap_phase;
$_drupal_current_bootstrap_phase = $current_phase;
}
}

/**
* Return the current bootstrap phase for this Drupal process. The
* current phase is the one most recently completed by
* drupal_bootstrap().
*
* @see drupal_bootstrap
*/
function drupal_get_bootstrap_phase() {
global $_drupal_current_bootstrap_phase;
return $_drupal_current_bootstrap_phase;
}

function _drupal_bootstrap($phase) {
global $conf;

Expand Down Expand Up @@ -1003,9 +1023,9 @@ function _drupal_bootstrap($phase) {
break;

case DRUPAL_BOOTSTRAP_DATABASE:
// Initialize the default database.
require_once './includes/database.inc';
db_set_active();
// Initialize the database system. Note that the connection
// won't be initialized until it is actually requested.
require_once './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');
Expand Down Expand Up @@ -1209,6 +1229,87 @@ function ip_address($reset = false) {
return $ip_address;
}

/**
* @ingroup schemaapi
* @{
*/

/**
* Get the schema definition of a table, or the whole database schema.
*
* The returned schema will include any modifications made by any
* module that implements hook_schema_alter().
*
* @param $table
* The name of the table. If not given, the schema of all tables is returned.
* @param $rebuild
* If true, the schema will be rebuilt instead of retrieved from the cache.
*/
function drupal_get_schema($table = NULL, $rebuild = FALSE) {
static $schema = array();

if (empty($schema) || $rebuild) {
// Try to load the schema from cache.
if (!$rebuild && $cached = cache_get('schema')) {
$schema = $cached->data;
}
// Otherwise, rebuild the schema cache.
else {
$schema = array();
// Load the .install files to get hook_schema.
// On some databases this function may be called before bootstrap has
// been completed, so we force the functions we need to load just in case.
if (drupal_function_exists('module_load_all_includes')) {

// There is currently a bug in module_list() where it caches what it
// was last called with, which is not always what you want.
// module_load_all_includes() calls module_list(), but if this function
// is called very early in the bootstrap process then it will be
// uninitialized and therefore return no modules. Instead, we have to
// "prime" module_list() here to to values we want, specifically
// "yes rebuild the list and don't limit to bootstrap".
// TODO: Remove this call after http://drupal.org/node/222109 is fixed.
module_list(TRUE, FALSE);
module_load_all_includes('install');
}

// Invoke hook_schema for all modules.
foreach (module_implements('schema') as $module) {
$current = module_invoke($module, 'schema');
require_once('./includes/common.inc');
if (drupal_function_exists('_drupal_initialize_schema')) {
_drupal_initialize_schema($module, $current);
}

$schema = array_merge($schema, $current);
}

if (drupal_function_exists('drupal_alter')) {
drupal_alter('schema', $schema);
}

if (drupal_get_bootstrap_phase() == DRUPAL_BOOTSTRAP_FULL) {
cache_set('schema', $schema);
}
}
}

if (!isset($table)) {
return $schema;
}
elseif (isset($schema[$table])) {
return $schema[$table];
}
else {
return FALSE;
}
}

/**
* @} End of "ingroup schemaapi".
*/


/**
* @ingroup registry
* @{
Expand Down Expand Up @@ -1245,7 +1346,7 @@ function drupal_function_exists($function) {
return TRUE;
}

$file = db_result(db_query("SELECT filename FROM {registry} WHERE name = '%s' AND type = '%s'", $function, 'function'));
$file = db_result(db_query("SELECT filename FROM {registry} WHERE name = :name AND type = :type", array(':name' => $function, ':type' => 'function')));
if ($file) {
require_once($file);
$checked[$function] = function_exists($function);
Expand Down Expand Up @@ -1293,7 +1394,7 @@ function drupal_autoload_class($class) {
* Helper for registry_check_{interface, class}.
*/
function _registry_check_code($type, $name) {
$file = db_result(db_query("SELECT filename FROM {registry} WHERE name = '%s' AND type = '%s'", $name, $type));
$file = db_result(db_query("SELECT filename FROM {registry} WHERE name = :name AND type = :type", array(':name' => $name, ':type' => $type)));
if ($file) {
require_once($file);
registry_mark_code($type, $name);
Expand Down Expand Up @@ -1358,7 +1459,7 @@ function registry_cache_hook_implementations($hook, $write_to_persistent_cache =
if ($write_to_persistent_cache === TRUE) {
// Only write this to cache if the implementations data we are going to cache
// is different to what we loaded earlier in the request.
if ($implementations != registry_get_hook_implementations_cache()) {
if ($implementations != module_implements()) {
cache_set('hooks', $implementations, 'cache_registry');
}
}
Expand Down Expand Up @@ -1412,23 +1513,6 @@ function registry_load_path_files($return = FALSE) {
}
}

/**
* registry_get_hook_implementations_cache
*/
function registry_get_hook_implementations_cache() {
static $implementations;
if ($implementations === NULL) {
if ($cache = cache_get('hooks', 'cache_registry')) {
$implementations = $cache->data;
}
else {
$implementations = array();
}
}
return $implementations;
}

/**
* @} End of "ingroup registry".
*/

28 changes: 16 additions & 12 deletions includes/cache.inc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ function cache_get($cid, $table = 'cache') {
// 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)) {
$cache->data = db_decode_blob($cache->data);
if ($cache->serialized) {
$cache->data = unserialize($cache->data);
}
Expand All @@ -45,7 +44,6 @@ function cache_get($cid, $table = 'cache') {
return FALSE;
}
else {
$cache->data = db_decode_blob($cache->data);
if ($cache->serialized) {
$cache->data = unserialize($cache->data);
}
Expand Down Expand Up @@ -101,16 +99,22 @@ function cache_get($cid, $table = 'cache') {
* A string containing HTTP header information for cached pages.
*/
function cache_set($cid, $data, $table = 'cache', $expire = CACHE_PERMANENT, $headers = NULL) {
$serialized = 0;
$fields = array(
'serialized' => 0,
'created' => time(),
'expire' => $expire,
'headers' => $headers,
);
if (!is_string($data)) {
$data = serialize($data);
$serialized = 1;
$fields['data'] = serialize($data);
$fields['serialized'] = 1;
}
$created = time();
db_query("UPDATE {" . $table . "} SET data = %b, created = %d, expire = %d, headers = '%s', serialized = %d WHERE cid = '%s'", $data, $created, $expire, $headers, $serialized, $cid);
if (!db_affected_rows()) {
@db_query("INSERT INTO {" . $table . "} (cid, data, created, expire, headers, serialized) VALUES ('%s', %b, %d, %d, '%s', %d)", $cid, $data, $created, $expire, $headers, $serialized);
else {
$fields['data'] = $data;
$fields['serialized'] = 0;
}

db_merge($table)->key(array('cid' => $cid))->fields($fields)->execute();
}

/**
Expand Down Expand Up @@ -170,14 +174,14 @@ function cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
else {
if ($wildcard) {
if ($cid == '*') {
db_query("DELETE FROM {" . $table . "}");
db_delete($table)->execute();
}
else {
db_query("DELETE FROM {" . $table . "} WHERE cid LIKE '%s%%'", $cid);
db_delete($table)->condition('cid', $cid .'%', 'LIKE')->execute();
}
}
else {
db_query("DELETE FROM {" . $table . "} WHERE cid = '%s'", $cid);
db_delete($table)->condition('cid', $cid)->execute();
}
}
}
Expand Down
Loading

0 comments on commit 69e6f41

Please sign in to comment.