Commit 984f27ef authored by Dries's avatar Dries

- Patch #106559 by kbahey, catch, DamZ, chx et al: more drupal_lookup_path() optimizations.

parent 706ce875
......@@ -39,6 +39,7 @@ public function __construct(array $connection_options = array()) {
$this->sqliteCreateFunction('length', 'strlen', 1);
$this->sqliteCreateFunction('concat', array($this, 'sqlFunctionConcat'));
$this->sqliteCreateFunction('substring', array($this, 'sqlFunctionSubstring'), 3);
$this->sqliteCreateFunction('substring_index', array($this, 'sqlFunctionSubstringIndex'), 3);
$this->sqliteCreateFunction('rand', array($this, 'sqlFunctionRand'));
}
......@@ -82,6 +83,20 @@ public function sqlFunctionSubstring($string, $from, $length) {
return substr($string, $from - 1, $length);
}
/**
* SQLite compatibility implementation for the SUBSTRING_INDEX() SQL function.
*/
public function sqlFunctionSubstringIndex($string, $delimiter, $count) {
$end = 0;
for ($i = 0; $i < $count; $i++) {
$end = strpos($string, $delimiter, $end + 1);
if ($end === FALSE) {
$end = strlen($string);
}
}
return substr($string, 0, $end);
}
/**
* SQLite compatibility implementation for the RAND() SQL function.
*/
......
......@@ -430,7 +430,10 @@ public function changeField(&$ret, $table, $field, $field_new, $spec, $keys_new
*/
public function addIndex(&$ret, $table, $name, $fields) {
$schema['indexes'][$name] = $fields;
$ret[] = update_sql($this->createIndexSql($table, $schema));
$statements = $this->createIndexSql($table, $schema);
foreach ($statements as $statement) {
$ret[] = update_sql($statement);
}
}
/**
......@@ -461,8 +464,10 @@ public function dropIndex(&$ret, $table, $name) {
*/
public function addUniqueKey(&$ret, $table, $name, $fields) {
$schema['unique keys'][$name] = $fields;
$ret[] = update_sql($this->createIndexSql($table, $schema));
$statements = $this->createIndexSql($table, $schema);
foreach ($statements as $statement) {
$ret[] = update_sql($statement);
}
}
/**
......
......@@ -48,31 +48,37 @@ function drupal_lookup_path($action, $path = '', $path_language = '') {
// $map is an array with language keys, holding arrays of Drupal paths to alias relations
$map = &drupal_static(__FUNCTION__, array());
$no_src = &drupal_static(__FUNCTION__ . ':no_src', array());
$count = &drupal_static(__FUNCTION__ . ':count');
$whitelist = &drupal_static(__FUNCTION__ . ':whitelist');
$system_paths = &drupal_static(__FUNCTION__ . ':system_paths');
$no_aliases = &drupal_static(__FUNCTION__ . ':no_alias', array());
$first_call = &drupal_static(__FUNCTION__ . ':first_call', TRUE);
$path_language = $path_language ? $path_language : $language->language;
// Use $count to avoid looking up paths in subsequent calls if there simply are no aliases
if (!isset($count)) {
$count = db_query('SELECT COUNT(pid) FROM {url_alias}')->fetchField();
// Retrieve the path alias whitelist.
if (!isset($whitelist)) {
$whitelist = variable_get('path_alias_whitelist', NULL);
if (!isset($whitelist)) {
$whitelist = drupal_path_alias_whitelist_rebuild();
}
}
$path_language = $path_language ? $path_language : $language->language;
if ($action == 'wipe') {
$map = array();
$no_src = array();
$count = NULL;
$system_paths = array();
$no_aliases = array();
$whitelist = drupal_path_alias_whitelist_rebuild();
}
elseif ($count > 0 && $path != '') {
elseif ($whitelist && $path != '') {
if ($action == 'alias') {
// During the first call to drupal_lookup_path() per language, load the
// expected system paths for the page from cache.
if ($first_call) {
$first_call = FALSE;
$map[$path_language] = array();
// Load system paths from cache.
$cid = current_path();
......@@ -93,6 +99,12 @@ function drupal_lookup_path($action, $path = '', $path_language = '') {
if (isset($map[$path_language][$path])) {
return $map[$path_language][$path];
}
// Check the path whitelist, if the top_level part before the first /
// is not in the list, then there is no need to do anything further,
// it is not in the database.
elseif (!isset($whitelist[strtok($path, '/')])) {
return FALSE;
}
// For system paths which were not cached, query aliases individually.
else if (!isset($no_aliases[$path_language][$path])) {
// Get the most fitting result falling back with alias without language
......@@ -347,3 +359,22 @@ function drupal_match_path($path, $patterns) {
function current_path() {
return $_GET['q'];
}
/**
* Rebuild the path alias white list.
*
* @return
* An array containing a white list of path aliases.
*/
function drupal_path_alias_whitelist_rebuild() {
// For each alias in the database, get the top level component of the system
// path it corresponds to. This is the portion of the path before the first /
// if present, otherwise the whole path itself.
$whitelist = array();
$result = db_query("SELECT SUBSTRING_INDEX(src, '/', 1) AS path FROM {url_alias} GROUP BY path");
foreach ($result as $row) {
$whitelist[$row->path] = TRUE;
}
variable_set('path_alias_whitelist', $whitelist);
return $whitelist;
}
......@@ -339,6 +339,11 @@ function system_install() {
\'SELECT CASE WHEN $1 THEN $2 ELSE $3 END;\'
LANGUAGE \'sql\''
);
db_query('CREATE OR REPLACE FUNCTION "substr_index"(text, text, integer) RETURNS text AS
\'SELECT array_to_string((string_to_array($1, $2)) [1:$3], $2);\'
LANGUAGE \'sql\''
);
}
// Create tables.
......@@ -3495,6 +3500,25 @@ function system_update_7023() {
return $ret;
}
/**
* Add the substr_index() function to PostgreSQL.
*
* Note: this should go into the driver itself, but we have no support
* for driver-specific updates yet.
*/
function system_update_7024() {
$ret = array();
if (db_driver() == 'pgsql') {
$ret[] = update_sql('CREATE OR REPLACE FUNCTION "substr_index"(text, text, integer) RETURNS text AS
\'SELECT array_to_string((string_to_array($1, $2)) [1:$3], $2);\'
LANGUAGE \'sql\''
);
}
return $ret;
}
/**
* @} End of "defgroup updates-6.x-to-7.x"
* The next series of updates should start at 8000.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment