Problem/Motivation

Views supports a minimal set of aggregate functions that are hard coded into the default query plugin. It would be useful to have a way to add support for the full range of SQL aggregates available in MySQL & PostgreSQL (GROUP_CONCT/STRING_AGG, VARIANCE, ...), as well as providing a means of supporting the extended set of OGC spatial aggregates supported by PostgreSQL (ST_Union, ST_ClusterWithin, ...), and allowing any other user-defined aggregates that may be available.

Proposed resolution

Code 1: Patch excerpt, 1 line to add aggregate definitions via plugin.

--- a/plugins/views_plugin_query_default.inc
+++ b/plugins/views_plugin_query_default.inc
@@ -1592,7 +1592,7 @@ class views_plugin_query_default extends views_plugin_query {
           'sort' => 'views_handler_sort_group_by_numeric',
         ),
       )
-    );
+    ) + views_fetch_plugin_data('query_aggregate');
   }
 
   /**

For further details, see "Implementation Example", and for further details a related issue with patch for implementation in D7 "Support Plugins for Views Aggregate in D7").

Remaining tasks

  1. Add ctools plugin search in aggregate definition function
  2. Create Plugins for all default aggregate functions in order to provide implementation example.
  3. Remove hard-coded default aggregates from views_plugin_query_default.inc
  4. Test

User interface changes

None.

API changes

Add Annotation-based plugin support for ViewsAggregate

Data model changes

None.

Implementation Example

Code 2: Sample implementation of VAR_SAMP in Drupal 7 using Ctools plugin.

function views_views_plugins() {
  return array(
    'query_aggregate' => array(
      'var_samp' => array(
        'title' => t('Sample Variance'),
        'method' => 'views_query_default_aggregation_method_simple',
        'handler' => array(
          'argument' => 'views_handler_argument_group_by_numeric',
          'filter' => 'views_handler_filter_group_by_numeric',
          'sort' => 'views_handler_sort_group_by_numeric',
        ),
      ),
...

Original report by joachim

  function get_aggregation_info() {
    // @todo -- need a way to get database specific and customized aggregation
    // functions into here.

What's the best way to do this?

Should aggregation functions be another type of plugin?

(Background for this is that for Commerce product node displays it would be useful to have a GROUP_CONCAT available.)

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dawehner’s picture

Well i'm wondering why an alter hook in that function wouldn't help?
Another kind of plugin type would definitive quite complicated

joachim’s picture

Sure, we could drupal_alter that list.

But the aggregation items defined in that function refer to methods of the views_plugin_query_default class. Presumably, a module altering an item into the list would need to be able define a function to call instead of a method.

joachim’s picture

Also, the GROUP_CONCAT option could feasibly use further UI options.

What do you think about adding GROUP_CONCAT to Views? It could be useful for things like taxonomy terms, if field handlers can be made aware of the need to explode() their incoming values before formatting them.

joachim’s picture

robertwb’s picture

I think that the simplest appraoch here is to use the existing hook_views_plugin system, and define a new "type" of plugin called "query_aggregate". The new "type" is automatically created whenever a module returns something via hook_views_plugins whose key is not already in the plugins array. This approach results in only a single line of Views code being modified, does not require any new hooks, and allows any module to provide aggregates very simply (provided that they can use the existing views aggregate methods). The code block below is an example for adding a geospatial UNION (st_union) aggregate for a geofield, likely I will submit this as a patch to geofield. The attached patch is all that is required to support the aggregate definition.


function [module name]_views_plugins() {
  return array(
    'query_aggregate' => array(
      'st_union' => array(
        'title' => t('Spatial Union'),
        'method' => 'views_query_default_aggregation_method_simple',
        'handler' => array(
          'argument' => 'geofield_handler_argument',
          'filter' => 'geofield_handler_filter',
          'sort' => 'geofield_handler_sort',
        ),
      ),
    ),
  );
}

robertwb’s picture

Status: Active » Needs review
robertwb’s picture

Title: allow get_aggregation_info() to have customized aggregation functions » Support Plugins for Views Aggregate in D7
joachim’s picture

This probably should be added to D8 core first, then backported.

robertwb’s picture

Thanks for taking a look @joachim, I created a D8 implementation which mirrors this quite closely, though the plugin stuff is obviously a bit different- still I think it it reasonable to consider it a back port. Updating this to have the D8 issue as a parent.

robertwb’s picture

Issue summary: View changes
robertwb’s picture

Issue summary: View changes
robertwb’s picture

Issue summary: View changes
robertwb’s picture

Issue summary: View changes
robertwb’s picture

FileSize
566 bytes

Attaching an example module implementing the var_pop and var_samp aggregate functions.

robertwb’s picture

Title: Support Plugins for Views Aggregate in D7 » Support Plugins for Views Aggregate in D7 (D8 Backport)

  • dawehner committed bf1e53a on 7.x-3.x authored by robertwb
    Issue #1359298 by robertwb: Support Plugins for Views Aggregate in D7 (...
dawehner’s picture

Status: Needs review » Reviewed & tested by the community

There we go

dawehner’s picture

Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

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

robertwb’s picture

The issue with D8 still seems to be lingering, but this has been committed in D7 - https://www.drupal.org/node/1359298 and if your interest is spatial aggregates I have posted up an example.