Patch #106559 by kbahey, Damien Tournoud, catch: skip looking up certain paths in drupal_lookup_path() From: damz --- database/sqlite/database.inc | 15 ++++++++++++++ database/sqlite/schema.inc | 11 +++++++--- path.inc | 45 +++++++++++++++++++++++++++++++++++------- system/system.install | 24 ++++++++++++++++++++++ 4 files changed, 85 insertions(+), 10 deletions(-) diff --git includes/database/sqlite/database.inc includes/database/sqlite/database.inc index 6d8166d..ebbe01e 100644 --- includes/database/sqlite/database.inc +++ includes/database/sqlite/database.inc @@ -39,6 +39,7 @@ class DatabaseConnection_sqlite extends DatabaseConnection { $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 DatabaseConnection { } /** + * 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) { diff --git includes/database/sqlite/schema.inc includes/database/sqlite/schema.inc index 3a4bac0..565a9cc 100644 --- includes/database/sqlite/schema.inc +++ includes/database/sqlite/schema.inc @@ -430,7 +430,10 @@ class DatabaseSchema_sqlite extends DatabaseSchema { */ 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 DatabaseSchema { */ 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); + } } /** diff --git includes/path.inc includes/path.inc index 017100e..da9d0b6 100644 --- includes/path.inc +++ includes/path.inc @@ -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; +} diff --git modules/system/system.install modules/system/system.install index f0505aa..b290cab 100644 --- modules/system/system.install +++ modules/system/system.install @@ -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() { } /** + * 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. */