Quantcast
Channel: Issues for Drupal core
Viewing all articles
Browse latest Browse all 300665

Programmatically calling addHavingExpression() on the query of a view with sorting options breaks the query.

$
0
0

Problem/Motivation

Adding a having condition is necessary for placing conditions on fields created via subqueries. For example creating a custom view field plugin with the following section of code:

$this->query->addField(
  '',
  "(
    SELECT COUNT(t.field)
    FROM table t
      WHERE t.field = $this->tableAlias.field
  )",
  'custom_field_name',
  []
);

Now because the field is not part of a table, it cannot be filtered in the 'WHERE' clause of the query, thus a condition is needed in the 'HAVE' clause.
But calling $this->query->addHavingExpression() also adds a 'GROUP BY' clause to the query because of this code:

$this->hasAggregate = FALSE;
$non_aggregates = $this->getNonAggregates();
if (count($this->having)) {
  $this->hasAggregate = TRUE;
}
elseif (!$this->hasAggregate) {
  // Allow 'GROUP BY' even no aggregation function has been set.
  $this->hasAggregate = $this->view->display_handler->getOption('group_by');
}
$groupby = [];
if ($this->hasAggregate && (!empty($this->groupby) || !empty($non_aggregates))) {
  $groupby = array_unique(array_merge($this->groupby, $non_aggregates));
}

And if the view does not explicitly use aggregation, an error is thrown because the sorting fields are not taken into consideration as non-aggreagets by the getNonAggregates() method.

Thrown error:

Drupal\Core\Database\DatabaseExceptionWrapper: Exception in Workbench: Recent content[workbench_recent_content]: SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'node_field_data.changed' which is not functionally dependent on columns in GROUP BY clause;

Also, as a curiosity, why is aggregation forced when adding 'HAVE' clauses?

Proposed resolution

Change the method Drupal\views\Plugin\views\query\Sql::getNonAggregates() to also take into consideration the 'ORDER BY' fields:

foreach ($this->fields + $this->orderby as $field) {

Viewing all articles
Browse latest Browse all 300665

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>