Skip to content

MDEV-40672: Pluggable Aggregate Function - #5522

Draft
drrtuy wants to merge 1 commit into
MariaDB:13.0from
drrtuy:pluggable_aggregate_funcs
Draft

MDEV-40672: Pluggable Aggregate Function#5522
drrtuy wants to merge 1 commit into
MariaDB:13.0from
drrtuy:pluggable_aggregate_funcs

Conversation

@drrtuy

@drrtuy drrtuy commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Add pluggable aggregate function support

What

Implement MDEV-40672 by extending function plugins to provide aggregate functions through the standard Item_sum lifecycle. Support grouped aggregation, DISTINCT, window functions, native and pluggable data types, and safe plugin lifetime management.

Key changes

  • Extend Plugin_function descriptors to distinguish scalar and aggregate functions.
  • Add Item_sum_plugin as the base class for plugin-provided aggregates.
  • Support DISTINCT argument replay and pluggable result types such as UUID.
  • Enable plugin aggregates as window functions, including moving-frame removal.
  • Add test aggregates and MTR coverage for grouping, windows, prepared statements, plugin unloading, invalid descriptors, and type preservation.

How to test

Run:

/git/BuildOf_mdb-13/mysql-test/mtr function_plugin function_plugin_extra

Both tests pass.

@drrtuy
drrtuy requested review from abarkov and vuvova August 10, 2026 18:09
@drrtuy
drrtuy force-pushed the pluggable_aggregate_funcs branch from 5acea19 to df0b051 Compare August 10, 2026 20:32
@drrtuy
drrtuy force-pushed the pluggable_aggregate_funcs branch from df0b051 to 66d0210 Compare August 14, 2026 20:43
@vuvova
vuvova requested a balanced review from Copilot August 15, 2026 20:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds pluggable aggregate functions to MariaDB’s standard aggregation and window-function infrastructure.

Changes:

  • Introduces Item_sum_plugin with plugin lifetime and data-type handling.
  • Adds parser, DISTINCT, and window-function support.
  • Adds test aggregates and MTR coverage.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
sql/sql_yacc.yy Parses and constructs plugin aggregates.
sql/sql_window.cc Handles plugin window aggregates.
sql/sql_schema.h Exposes plugin references during lookup.
sql/sql_schema.cc Implements plugin-aware schema lookup.
sql/item_sum.h Defines plugin aggregate interfaces.
sql/item_sum.cc Implements lifecycle and DISTINCT replay.
sql/item_create.h Adds aggregate builder marker.
sql/item_create.cc Retains plugins during item creation.
plugin/func_test/plugin.cc Adds test aggregate plugins.
plugin/func_test/mysql-test/func_test/function_plugin.test Adds primary functional tests.
plugin/func_test/mysql-test/func_test/function_plugin.result Records primary test results.
plugin/func_test/mysql-test/func_test/function_plugin_negative.test Adds failure-path tests.
plugin/func_test/mysql-test/func_test/function_plugin_negative.result Records negative test results.
plugin/func_test/mysql-test/func_test/function_plugin_extra.test Adds extended lifecycle/type tests.
plugin/func_test/mysql-test/func_test/function_plugin_extra.result Records extended test results.
include/mysql/plugin_function.h Documents the aggregate plugin contract.
include/mysql/plugin_function.h.pp Updates the preprocessed API header.
Suppressed comments (3)

sql/sql_yacc.yy:11375

  • The descriptor contract is only checked when the returned object already casts to Item_sum. An aggregate-marked builder that accidentally returns a scalar skips this block and is accepted even though its arguments were parsed as an aggregate; conversely, a scalar-marked builder returning Item_sum_plugin is accepted as an aggregate. Validate the builder's declared aggregate kind against the returned item (when non-null), and require every aggregate descriptor to return Item_sum_plugin.
            Item_sum *sum_item= item ? dynamic_cast<Item_sum *>(item) : NULL;
            if (function_plugin && sum_item)

sql/item_sum.cc:582

  • This null check does not make the allocation recoverable: ordinary throwing new never returns null (and typically terminates in no-exception builds), so allocation failure cannot reach the caller's ER_OUT_OF_RESOURCES path. Use a non-throwing allocation here.
  m_plugin_lifetime=
    new Item_sum_plugin_lifetime(static_cast<plugin_ref>(plugin));
  return !m_plugin_lifetime;

sql/item_sum.cc:905

  • Routing plugin aggregates through this DISTINCT branch leaves their add() failures unhandled for the common in-memory tree replay path. unique_walk_function() discards the boolean returned by item_sum->add(), and endup() also ignores tree->walk()'s status, so a plugin that reports an allocation or evaluation failure can continue replaying and return a partial result. Propagate the callback failure and stop/fail the walk, as the new on-disk replay loop already does.
  if (item_sum->sum_func() == Item_sum::COUNT_FUNC ||
      item_sum->sum_func() == Item_sum::COUNT_DISTINCT_FUNC ||
      item_sum->sum_func() == Item_sum::PLUGIN_SUM_FUNC)

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread sql/sql_yacc.yy
Comment on lines +11261 to +11263
Create_func *native_builder= Schema::find_implied(thd)->
find_native_function_builder(thd, sysname);
aggregate= dynamic_cast<Create_aggregate_func *>(native_builder) != NULL;
Comment thread sql/item_sum.cc
Comment on lines +562 to +565
Item_sum_plugin_lifetime *lifetime=
static_cast<Item_sum_plugin_lifetime *>(m_plugin_lifetime);
if (lifetime && !--lifetime->ref_count)
delete lifetime;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants