Problem/Motivation

Followup of #2999612: Properly deprecate db_query_range.

There's some overlap between how Drupal\Core\Utility\Error is determining the caller, and a similar functionality in Drupal\Core\Database\Log::findCaller.

Proposed resolution

Remove duplication.

Remaining tasks

None

User interface changes

None

API changes

Add new static method Drupal\Core\Database\Log::removeDatabaseEntries().

Data model changes

None

Release notes snippet

TBD

Issue fork drupal-2999962

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

voleger created an issue. See original summary.

voleger’s picture

I guess we need just remove the related function. Because of script will check the namespace of the caller class:
((isset($caller['class']) && (strpos($caller['class'], 'Query') !== FALSE || strpos($caller['class'], 'Database') !== FALSE || strpos($caller['class'], 'PDO') !== FALSE)) || in_array($caller['function'], $db_functions)))

So, the instance of the caller of both methods after functions replacements will be in the Drupal\Core\Database\ namespace.

mondrake’s picture

Uhm... it looks like there's some overlap between how Drupal\Core\Utility\Error is determining the caller, and a similar functionality in Drupal\Core\Database\Log::findCaller. Wondering is there's a chance to unify that.

mondrake’s picture

Assigned: Unassigned » mondrake

Working on #3.

andypost’s picture

Result array for debug_backtrace() & $e->getTrace() are the same so makes sense to unify

mondrake’s picture

Status: Active » Needs review
StatusFileSize
new7.49 KB

This would be the idea, taking big portions from #2867788: Log::findCaller fails to report the correct caller function with non-core drivers.. If we agree this is the right direction, I can also take more testing from there.

Status: Needs review » Needs work

The last submitted patch, 6: 2999962-6.patch, failed testing. View results

mondrake’s picture

Assigned: mondrake » Unassigned
mondrake’s picture

Title: Deprecation of the db_query and db_query_range in core/lib/Drupal/Core/Utility/Error.php » Unify Database/Log::findCaller and Utility/Error::getLastCaller
Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new1.17 KB
new8.2 KB

This should fix one of the fails.

mondrake’s picture

Actually both :). Ready for review.

voleger’s picture

+++ b/core/lib/Drupal/Core/Utility/Error.php
@@ -75,6 +70,33 @@ public static function decodeException($exception) {
+        strpos($function, 'db_', 0) === 0

I guess there should be a mention to remove this check of deprecated functions in Drupal 9.

mondrake’s picture

+++ b/core/lib/Drupal/Core/Utility/Error.php
@@ -75,6 +70,33 @@ public static function decodeException($exception) {
+    // @todo in Drupal 9.0, remove the check for deprecated 'db_' functions.

like this? ;)

just a few lines above...

voleger’s picture

Yeah) Like this. Sorry)
+1 for RTBC

dawehner’s picture

  1. +++ b/core/lib/Drupal/Core/Database/Database.php
    @@ -503,7 +503,7 @@ public static function getConnectionInfoAsUrl($key = 'default') {
    -  protected static function getDatabaseDriverNamespace(array $connection_info) {
    +  public static function getDatabaseDriverNamespace(array $connection_info) {
         if (isset($connection_info['namespace'])) {
           return $connection_info['namespace'];
         }
    

    May I ask whether its we need a method for this and not just get the namespace out of $connection_info itself.

  2. +++ b/core/lib/Drupal/Core/Database/Log.php
    @@ -2,6 +2,8 @@
     
     namespace Drupal\Core\Database;
     
    +use Drupal\Core\Utility\Error;
    +
     /**
    

    Looking through all Drupal\Core\Database code there is no reference to anything outside of its own namespace. I am wondering whether that's a sign that we should move this error helper methods into a component instead.

  3. +++ b/core/lib/Drupal/Core/Utility/Error.php
    @@ -75,6 +70,33 @@ public static function decodeException($exception) {
    +  public static function removeDatabaseEntries(array &$backtrace, $driver_namespace) {
    +    // Starting from the very last entry in the backtrace (which is the first
    +    // call in the request), find the offset of the first function call that
    +    // can be identified as a call to a method/function in the database layer.
    +    // @todo in Drupal 9.0, remove the check for deprecated 'db_' functions.
    +    for ($offset = count($backtrace) - 1; $offset >= 0; $offset--) {
    +      $class = isset($backtrace[$offset]['class']) ? $backtrace[$offset]['class'] : '';
    +      $function = isset($backtrace[$offset]['function']) ? $backtrace[$offset]['function'] : '';
    +      if (
    +        strpos($class, 'Drupal\Core\Database', 0) === 0 ||
    +        strpos($class, $driver_namespace, 0) === 0 ||
    +        strpos($function, 'db_', 0) === 0
    +      ) {
    +        break;
    +      }
    +    }
    +    $backtrace = array_slice($backtrace, $offset);
    +  }
    

    Could this be some sort of generic function instead which allows you to pass along a callable for the filtering? Like backtrace_filter or so?

berdir’s picture

> Looking through all Drupal\Core\Database code there is no reference to anything outside of its own namespace. I am wondering whether that's a sign that we should move this error helper methods into a component instead.

Yes, the goal with DBTNG was always to keep dependencies to an absolute minimum as the idea back then was to separate this into a standalone library at some that Drupal would just use.

That never fully happened but I think we should really think before adding more dependencies to that component.

mondrake’s picture

#14:

1. 'namespace' may not be set if you have a settings.php still on D7, hence we fall back

  protected static function getDatabaseDriverNamespace(array $connection_info) {
    if (isset($connection_info['namespace'])) {
      return $connection_info['namespace'];
    }
    // Fallback for Drupal 7 settings.php.
    return 'Drupal\\Core\\Database\\Driver\\' . $connection_info['driver'];
  }

if that wasn't the case, then yes that method would be redundant. An idea could be to fill in 'namespace' it if missing in settings.php, at each request. But that will be unnecessary most of the time and then just more overhead.

2. I have no particular argument here. Whatever.

3. Yes, but sitting where then?

voleger’s picture

voleger’s picture

+++ b/core/lib/Drupal/Core/Database/Log.php
@@ -137,31 +148,31 @@ public function log(StatementInterface $statement, $args, $time) {
-    for ($i = 0, $stack_count = count($stack); $i < $stack_count; ++$i) {
-      // If the call was made from a function, 'class' will be empty. It's
-      // just easier to give it a default value than to try and integrate
-      // that into the if statement below.
-      if (empty($stack[$i]['class'])) {
-        $stack[$i]['class'] = '';
-      }
-      if (strpos($stack[$i]['class'], __NAMESPACE__) === FALSE && strpos($stack[$i + 1]['function'], 'db_') === FALSE && !empty($stack[$i]['file'])) {
-        $stack[$i] += ['file' => '?', 'line' => '?', 'args' => []];
-        return [
-          'file' => $stack[$i]['file'],
-          'line' => $stack[$i]['line'],
-          'function' => $stack[$i + 1]['function'],
-          'class' => isset($stack[$i + 1]['class']) ? $stack[$i + 1]['class'] : NULL,
-          'type' => isset($stack[$i + 1]['type']) ? $stack[$i + 1]['type'] : NULL,
-          'args' => $stack[$i + 1]['args'],
-        ];
+    Error::removeDatabaseEntries($stack, $this->getDriverNamespace());
+    return Error::getLastCaller($stack);

How about to dispatch an event here and move find caller implementation to the event subscriber?

voleger’s picture

Any thoughts about that?

voleger’s picture

StatusFileSize
new15.86 KB
new11.54 KB

Let's try to implement a few event subscribers.

Status: Needs review » Needs work

The last submitted patch, 20: 2999962-20.patch, failed testing. View results

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

voleger’s picture

voleger’s picture

Status: Needs work » Needs review
StatusFileSize
new10.81 KB
new3.41 KB

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

voleger’s picture

Version: 8.9.x-dev » 9.0.x-dev
Status: Needs review » Needs work
Related issues: +#3109097: Drupal 9 does not handle db_* functions any more

Address @todo from the latest patch #3109097: Drupal 9 does not handle db_* functions any more
Set to needs work

mondrake’s picture

Assigned: Unassigned » mondrake

So, #2867788: Log::findCaller fails to report the correct caller function with non-core drivers. has now landed; the major concern here seems to be to have Log depend on Error. Let's see if we can do the other way around. Working on it.

mondrake’s picture

Assigned: mondrake » Unassigned
Status: Needs work » Needs review
StatusFileSize
new4.2 KB

Simpler now.

mondrake’s picture

Version: 9.0.x-dev » 9.1.x-dev
Status: Needs review » Postponed

This needs #3112476: Always set $info['namespace'] on database connection info, to ensure that the namespace is available from the connection info, though.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

mondrake’s picture

Status: Postponed » Needs work

mondrake’s picture

Status: Needs work » Needs review
daffie’s picture

Issue summary: View changes

Created the CR and updated the IS.

mondrake’s picture

Fixed and commented in MR

daffie’s picture

Status: Needs review » Needs work
mondrake’s picture

Status: Needs work » Needs review
daffie’s picture

Status: Needs review » Reviewed & tested by the community

This is a nice little fix.
All code changes look good to me.
There is a CR for the API-addition.
For me it is RTBC.

  • catch committed 9140cae on 9.2.x
    Issue #2999962 by mondrake, voleger, daffie, dawehner, Berdir: Unify...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Nice clean-up!

Committed 981d78c and pushed to 9.2.x. Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.