Skip to content

Add quantile(), params() for parametric aggregates#33

Merged
theory merged 1 commit into
mainfrom
quantile
Nov 8, 2025
Merged

Add quantile(), params() for parametric aggregates#33
theory merged 1 commit into
mainfrom
quantile

Conversation

@theory
Copy link
Copy Markdown
Collaborator

@theory theory commented Nov 7, 2025

ClickHouse provides a number of "parametric aggregates" which take one or more parameters in a first set of parentheses and then normal arguments in a second. An example is quantile, which can be called like so:

SELECT quantile(0.25)(val) FROM t;

To mimic this feature, implement a params data type and function that takes a list of values of any type. Detect when it's the first argument to any aggregates and pass it as ClickHouse parameters before any other arguments. The equivalent of the above query in PostgreSQL is:

SELECT quantile(params(0.25), val) FROM t;

The pattern is general and can be used for any aggregate functions, but used here only for the new quantile and quantileExact aggregate functions. Others can be added in the future; all they have to do is use the clickhouse_func_push_fail function for their SFUNC, with one variant that takes params as the first argument and the remaining arguments specified as usual (likely as "any" to allow data type enforcement to be pushed down to ClickHouse).

Done by using the new ch_get_params_function() function to detect params()as the first argument to an aggregate function indeparseAggref()` and emitting it before appending the arguments opening parenthesis.

Document the new functions and explain how to use them.

While at it, simplify the handling of F_REGEXP_LIKE_TEXT_TEXT in Postgres 14 and earlier by simply setting it on those versions, rather than using #define to omit any code that uses it. This aligns with how the type mapper handles other such data type constants.

Also:

  • Fix an Assert for a variadic array to apply to the array, rather than the parent node. * Also, remove the unused func_arg field from the deparse_expr_cxt struct and add a comment explaining the array_as_tuple field.

@theory theory requested a review from serprex November 7, 2025 22:21
@theory theory self-assigned this Nov 7, 2025
@theory theory marked this pull request as ready for review November 7, 2025 22:22
Comment thread src/deparse.c Outdated
@theory theory requested a review from serprex November 8, 2025 19:43
@theory theory changed the title Add quantile(), mimic parametric aggregates Add quantile(), params() for parametric aggregates Nov 8, 2025
@theory
Copy link
Copy Markdown
Collaborator Author

theory commented Nov 8, 2025

Requesting another review because I came up with a better, more general approach to supporting parameterized aggregates.

ClickHouse provides a number of "parametric aggregates" which take one
or more parameters in a first set of parentheses and then normal
arguments in a second. An example is `quantile`, which can be called
like so:

    SELECT quantile(0.25)(val) FROM t;

To mimic this feature, implement a `params` data type and function that
takes a list of values of any type. Detect when it's the first argument
to any aggregates and pass it as ClickHouse parameters before any other
arguments. The equivalent of the above query in PostgreSQL is:

    SELECT quantile(params(0.25), val) FROM t;

The pattern is general and can be used for any aggregate functions, but
used here only for the new `quantile` and `quantileExact` aggregate
functions. Others can be added in the future; all they have to do is use
the `clickhouse_func_push_fail` function for their `SFUNC`, with one
variant that takes `params` as the first argument and the remaining
arguments specified as usual (likely as `"any"` to allow data type
enforcement to be pushed down to ClickHouse).

Done by using the new `ch_get_params_function() function to detect
`params()` as the first argument to an aggregate function in
`deparseAggref()` and emitting it before appending the arguments opening
parenthesis.

Document the new functions and explain how to use them.

While at it, simplify the handling of `F_REGEXP_LIKE_TEXT_TEXT` in
Postgres 14 and earlier by simply setting it on those versions, rather
than using `#define` to omit any code that uses it. This aligns with how
the type mapper handles other such data type constants.

Also:

*   Fix an `Assert` for a variadic array to apply to the array, rather
    than the parent node.
*   Also, remove the unused `func_arg` field from the `deparse_expr_cxt`
    struct and add a comment explaining the `array_as_tuple` field.
Copy link
Copy Markdown
Member

@serprex serprex left a comment

Choose a reason for hiding this comment

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

it's hard since it's always going to be awkward how to map (args1)(args2) to postgres. this way at least makes it clearer there's something magical happening

@theory
Copy link
Copy Markdown
Collaborator Author

theory commented Nov 8, 2025

Yes, exactly.

@theory theory merged commit 4a44c63 into main Nov 8, 2025
32 checks passed
@theory theory deleted the quantile branch November 8, 2025 22:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants