Although an external 'database' is specified in hook_views_data definition, the external database is not used by the query.

In views_plugin_query_default.inc:

    // Go ahead and build the query.
    $query = db_select($this->base_table, $this->base_table)->addTag('views');

I think the db_select should specify the external database in the options parameter:

    // Set query options if base_database is specified
    $queryOptions = isset($view->base_database) ? array('target' => $view->base_database) : array();
    // Go ahead and build the query.    
    $query = db_select($this->base_table, $this->base_table)->addTag('views', array('target' => $base_database);

($view should be passed as an argument to function query)

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dawehner’s picture

Mh Views uses db_set_active, which should work without using the base database, right?

asimov6’s picture

I guess you are right. I must have set up my database configuration in settings the wrong way.

asimov6’s picture

This is how I added my external database to the $databases array in settings.php. If this is how it should be done than I quess the bug exists. Tell me if I'm wrong.

$databases = array (
  'default' => 
  array (
    'default' => 
    array (
      'driver' => 'mysql',
      'database' => 'drupal7',
      'username' => 'user',
      'password' => 'pass',
      'host' => 'localhost',
      'port' => '',
      'prefix' => '',
    ),
    'dbexternal' => 
    array (
      'driver' => 'mysql',
      'database' => 'external',
      'username' => 'user',
      'password' => 'pass',
      'host' => 'localhost',
      'port' => '',
      'prefix' => '',
    ),
  ),
);

In hook_views_data I specified 'dbexternal' as the database to use.

dawehner’s picture

I don't see any problems here. Can you debug in the views code whether "dbexternal" is there defined as variable?

lsolesen’s picture

having same problem. let me know where in the views code I need to debug, and I will get right back to you.

dawehner’s picture

Well views uses the drupal core api.

Did you tryed out whether drupal core supports db_set_active currently?

lsolesen’s picture

It does. I was able to do the following:

$courses = db_query("SELECT id, name 
                              FROM {kortkursus} 
                              WHERE dato_slut > :date", array(':date' => date('Y-m-d')), array('target' => 'vih'));
lsolesen’s picture

The new database is present in the view. However, it is not being set because of the below.

Seem to have narrowed it down to the active connection not being set in the following code in includes/database/database.inc:

  final public static function setActiveConnection($key = 'default') {
    if (empty(self::$databaseInfo)) {
      self::parseConnectionInfo();
    }
    if (!empty(self::$databaseInfo[$key])) {
      $old_key = self::$activeKey;
      self::$activeKey = $key;
      return $old_key;
    }
  }

I have this in setting.php

$databases['default']['default'] = array(
    'driver' => 'mysql',
    'database' => 'drupal',
    'username' => 'root',
    'password' => 'xxxx',
    'host' => 'localhost',
    'port' => '',
    'prefix' => '',
);

$databases['default']['vih'][] = array(
    'driver' => 'mysql',
    'database' => 'vih',
    'username' => 'root',
    'password' => 'xxxx',
    'host' => 'localhost',
);

As mention in http://drupal.org/node/949526#comment-3726838 it works with a regular db_query.

So I am not quite sure whether views or core has to be changed?

dawehner’s picture

Can you check in plugins/views_plugin_query_defaut.inc::execute whether $view->base_database is set?
and this code is executed?



      // Detect an external database.
      if (isset($view->base_database)) {
        db_set_active($view->base_database);
        $external = TRUE;
      }

Thanks for tracking down this issue!

lsolesen’s picture

It is set to 'vih' as expected.

dawehner’s picture

Then the only thing which might can happen is that db_select doesn't support the set database and you have to do it manually.

dawehner’s picture

Status: Active » Needs review
FileSize
2.98 KB

The problem is that db_set_active does only support db_query calls.

 */
function db_select($table, $alias = NULL, array $options = array()) {
  if (empty($options['target'])) {
    $options['target'] = 'default';
  }
  return Database::getConnection($options['target'])->select($table, $alias, $options);
}

What about adding a d7wtf tag ;)

Crell says there is no usecase for this.

lsolesen’s picture

+    $options = array();
+    // Detect an external database.
+    if (isset($view->base_database)) {
+      $options['target'] = $view->base_database;
+    }

$view is never set in the query() function.

dawehner’s picture

FileSize
3.07 KB

Oh thanks!

New version of the patch

lsolesen’s picture

I am still pretty certain that $view can never be set in the query function?

dawehner’s picture

but $this->view should be there

lsolesen’s picture

Checking the patch again.

bojanz’s picture

Status: Needs review » Reviewed & tested by the community

Nice.

dawehner’s picture

Issue tags: +d7wtf

@bojanz

Do you understand why this kind of api change is wanted?

bojanz’s picture

Yes. Looks like a simple oversight, not sure why Crell was against it.
And now, 5 minutes before RC1, it's too late.

merlinofchaos’s picture

One of the problems with this patch is that by selecting only the specific View query to utilize the external database, any secondary queries run by the view will not use the external database.

That means we may have to evaluate all secondary queries.

dawehner’s picture

As on irc: secondary queries are executed on pre_render,

but the db_set_active is only in the execute method of the query plugin.

So they get executed against the main database, at the moment already(in d6)

merlinofchaos’s picture

Seems like that shouldn't hold this up, then.

dawehner’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -d7wtf

Commited it.

Status: Fixed » Closed (fixed)

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