Index: includes/path.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/path.inc,v retrieving revision 1.37 diff -u -p -r1.37 path.inc --- includes/path.inc 26 May 2009 09:12:28 -0000 1.37 +++ includes/path.inc 31 May 2009 20:20:50 -0000 @@ -48,31 +48,41 @@ function drupal_lookup_path($action, $pa // $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)) { + if ($whitelist_cache = cache_get('path_alias_whitelist', 'cache_path')) { + $whitelist = $whitelist_cache->data; + } + else { + $whitelist = drupal_path_alias_whitelist(); + cache_set('path_alias_whitelist', $whitelist, 'cache_path'); + } } + $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(); + cache_set('path_alias_whitelist', $whitelist, 'cache_path'); } - 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 +103,12 @@ function drupal_lookup_path($action, $pa 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 +363,21 @@ function drupal_match_path($path, $patte 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() { + // 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; + } + return $whitelist; +} Index: includes/database/sqlite/database.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database/sqlite/database.inc,v retrieving revision 1.16 diff -u -p -r1.16 database.inc --- includes/database/sqlite/database.inc 17 May 2009 03:31:36 -0000 1.16 +++ includes/database/sqlite/database.inc 31 May 2009 20:20:50 -0000 @@ -39,6 +39,7 @@ class DatabaseConnection_sqlite extends $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')); } @@ -83,6 +84,20 @@ class DatabaseConnection_sqlite extends } /** + * 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. */ public function sqlFunctionRand($seed = NULL) { Index: includes/database/sqlite/schema.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database/sqlite/schema.inc,v retrieving revision 1.5 diff -u -p -r1.5 schema.inc --- includes/database/sqlite/schema.inc 25 May 2009 13:42:53 -0000 1.5 +++ includes/database/sqlite/schema.inc 31 May 2009 20:20:51 -0000 @@ -430,7 +430,10 @@ class DatabaseSchema_sqlite extends Data */ 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 @@ class DatabaseSchema_sqlite extends Data */ 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); + } } /** Index: modules/system/system.install =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.install,v retrieving revision 1.332 diff -u -p -r1.332 system.install --- modules/system/system.install 27 May 2009 18:34:01 -0000 1.332 +++ modules/system/system.install 31 May 2009 20:21:06 -0000 @@ -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. @@ -3496,6 +3501,25 @@ function system_update_7023() { } /** + * Generate the URL alias prefix list. + */ +function system_update_7024() { + $ret = array(); + + // Add the alternative implementation of substring_index() for PostgreSQL. + // Note: this should go into the driver itself, but we have no support + // for driver-specific update yet. + if (db_driver() == 'pgsql') { + 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\'' + ); + } + + return $ret; +} + +/** * @} End of "defgroup updates-6.x-to-7.x" * The next series of updates should start at 8000. */