diff --git a/core/lib/Drupal/Core/Database/Log.php b/core/lib/Drupal/Core/Database/Log.php index 5d5d560c1521..14f5a382d314 100644 --- a/core/lib/Drupal/Core/Database/Log.php +++ b/core/lib/Drupal/Core/Database/Log.php @@ -130,12 +130,11 @@ class Log { * Determine the routine that called this query. * * We define "the routine that called this query" as the first entry in - * the call stack that is not inside the includes/Drupal/Database directory - * and does not begin with db_. That makes the climbing logic very simple, and - * handles the variable stack depth caused by the query builders. - * - * @todo Revisit this logic to not be dependent on file path, so that we can - * split most of the DB layer out of Drupal. + * the call stack that is not inside the includes/Drupal/Database directory, + * does not begin with db_ and does have a file (which excludes + * call_user_func_array(), anonymous functions and similar). That makes the + * climbing logic very simple, and handles the variable stack depth caused by + * the query builders. * * @link http://www.php.net/debug_backtrace * @return @@ -154,7 +153,8 @@ class Log { if (empty($stack[$i]['class'])) { $stack[$i]['class'] = ''; } - if (strpos($stack[$i]['class'], __NAMESPACE__) === FALSE && strpos($stack[$i + 1]['function'], 'db_') === FALSE) { + if (strpos($stack[$i]['class'], __NAMESPACE__) === FALSE && strpos($stack[$i + 1]['function'], 'db_') === FALSE && !empty($stack[$i]['file'])) { + $stack[$i] += array('file' => '?', 'line' => '?', 'args' => array()); return array( 'file' => $stack[$i]['file'], 'line' => $stack[$i]['line'], diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/LoggingTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/LoggingTest.php index 60d2a3c0941a..769acf071b02 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Database/LoggingTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Database/LoggingTest.php @@ -26,14 +26,17 @@ class LoggingTest extends DatabaseTestBase { * Test that we can log the existence of a query. */ function testEnableLogging() { - Database::startLog('testing'); + $log = Database::startLog('testing'); db_query('SELECT name FROM {test} WHERE age > :age', array(':age' => 25))->fetchCol(); db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'))->fetchCol(); + // Trigger a call that does not have file in the backtrace. + call_user_func_array('db_query', array('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo')))->fetchCol(); + $queries = Database::getLog('testing', 'default'); - $this->assertEqual(count($queries), 2, t('Correct number of queries recorded.')); + $this->assertEqual(count($queries), 3, t('Correct number of queries recorded.')); foreach ($queries as $query) { $this->assertEqual($query['caller']['function'], __FUNCTION__, t('Correct function in query log.'));