Skip to main content

AggregateCallSyntax

Struct AggregateCallSyntax 

Source
pub struct AggregateCallSyntax {
    pub group_concat_separator: bool,
    pub within_group: bool,
    pub aggregate_filter: bool,
    pub filter_optional_where: bool,
    pub aggregate_args_require_adjacent_paren: bool,
    pub null_treatment: bool,
    pub aggregate_calls_reject_empty_arguments: bool,
    pub over_requires_windowable_function: bool,
    pub window_function_tail: bool,
    pub standalone_argument_order_by: bool,
}
Expand description

Dialect-owned aggregate/window function-call syntax accepted by the parser.

The call-grammar forms specific to aggregate and window function calls — the in-parenthesis and post-) tails, the argument-shape and arity restrictions, and the OVER-eligibility gate. Split out of CallSyntax at its 16-field line as the aggregate/window axis, distinct from the scalar special-form and general call-tail cores. Each flag is a grammar gate: when off the tail keyword is left unconsumed and surfaces as a clean parse error, or the restriction does not fire.

Fields§

§group_concat_separator: bool

Accept the MySQL GROUP_CONCAT(<args> [ORDER BY …] SEPARATOR <string>) delimiter tail — the trailing SEPARATOR '<sep>' inside an aggregate call’s parentheses, after any in-parenthesis ORDER BY. It rides the shared FunctionCall shape’s new separator field, gated by grammar position like the always-parsed in-parenthesis ORDER BY. When off (ANSI/PostgreSQL, which write the delimiter as an ordinary string_agg argument), the SEPARATOR keyword is left unconsumed and the unmatched ) surfaces as a clean parse error.

§within_group: bool

Accept the WITHIN GROUP (ORDER BY …) ordered-set-aggregate tail (SQL:2008 T612/T614), as in percentile_cont(0.5) WITHIN GROUP (ORDER BY x). On for ANSI/PostgreSQL/DuckDB/Lenient. Neither SQLite nor MySQL has ordered-set aggregates (both engine-measured-rejected), so it is off for both; the WITHIN keyword is then left unconsumed and surfaces as a clean parse error. Only the WITHIN GROUP pair opens the clause, so a bare within stays a usable alias regardless.

§aggregate_filter: bool

Accept the FILTER (WHERE <predicate>) aggregate-filter tail (SQL:2003 T612), as in sum(x) FILTER (WHERE x > 1). On for ANSI/PostgreSQL/SQLite (3.30+)/DuckDB/ Lenient. MySQL has no aggregate FILTER clause (engine-measured-rejected on mysql:8), so it is off there; the FILTER keyword is then left unconsumed and surfaces as a clean parse error. Only FILTER immediately followed by ( opens the clause, so a bare filter after a call stays a usable alias.

§filter_optional_where: bool

Accept an aggregate FILTER (…) tail whose predicate is not preceded by the SQL-standard WHERE keyword, as in DuckDB’s sum(x) FILTER (x > 1) (probed on 1.5.4). On for DuckDb/Lenient; the presence of the keyword round-trips via FunctionCall::filter_where. Off for ANSI/PostgreSQL/SQLite, which require FILTER (WHERE …) — a keyword-less body then surfaces as a clean “expected WHERE” parse error. Independent of aggregate_filter: this only widens the body of a clause that gate already admits, so it is inert when the filter clause itself is off (MySQL).

§aggregate_args_require_adjacent_paren: bool

Require a built-in aggregate’s argument parentheses to be adjacent to its name for the aggregate-only argument forms — a leading *, a DISTINCT/ALL quantifier, the in-parenthesis ORDER BY, or the SEPARATOR tail. On for MySQL, off everywhere else. MySQL’s default (IGNORE_SPACE off) tokenizer treats a space before the ( as demoting a built-in aggregate to an ordinary/stored-function reference, where that aggregate-only argument grammar is illegal: COUNT ( * ) / MAX ( ALL 1 ) / COUNT ( DISTINCT 1 ) are engine-measured ER_PARSE_ERROR (1064) on mysql:8, while the adjacent COUNT(*) accepts. A normal-argument spaced call is unaffected — count (1) still parses (it fails only at name resolution, a binding not a syntax error), so this narrowly rejects the aggregate-only forms rather than blanket-forbidding a space (which would over-reject the valid general-call form). When off, the name/paren gap is irrelevant and every dialect admits the aggregate forms with or without the space. Only the default IGNORE_SPACE-off mode is modelled; the runtime sql_mode toggle to IGNORE_SPACE on (which would accept the spaced aggregate forms) is out of scope.

§null_treatment: bool

Accept the IGNORE NULLS / RESPECT NULLS null-treatment written inside a window/aggregate call’s parentheses (DuckDB’s last(s IGNORE NULLS) OVER (…)), riding the shared FunctionCall’s null_treatment field. On for DuckDb/Lenient. DuckDB spells it inside the parentheses (the SQL:2016 post-) position engine-rejects on 1.5.4), so it is parsed at the in-parenthesis tail after any ORDER BY. When off, IGNORE/RESPECT is left unconsumed and the unmatched ) surfaces as a clean parse error. PostgreSQL has no null-treatment clause, so this stays a DuckDB extension rather than a shared PG form.

§aggregate_calls_reject_empty_arguments: bool

Reject an empty argument list f() on a MySQL built-in aggregate function — the closed set MYSQL_AGGREGATE_FUNCTIONS in the parser crate (COUNT, SUM, AVG, MIN, MAX, the BIT_*/STD*/VAR*/VARIANCE family, GROUP_CONCAT, JSON_ARRAYAGG/JSON_OBJECTAGG). MySQL’s dedicated aggregate grammar requires at least one argument (or the COUNT(*) wildcard), so COUNT() is ER_PARSE_ERROR (1064) on mysql:8, while a niladic non-aggregate built-in (NOW(), UUID(), PI()) and an empty user-function call are accepted (the latter fails only at name resolution — a binding, not a syntax error — and a CONCAT()/ABS() empty call is a wrong-parameter-count semantic reject, also not a syntax error). On for MySQL, off elsewhere. When off, an empty aggregate call parses as an ordinary empty function call (every non-MySQL dialect admits it). Only a single unquoted name in the set matches — a backtick-quoted `count`() is a general call MySQL rejects at binding, not a syntax error, so it stays accepted — and the COUNT(*) wildcard and any argumented/quantified call are unaffected.

§over_requires_windowable_function: bool

Restrict the OVER (…) window clause to MySQL’s windowable functions — the built-in aggregates (MYSQL_AGGREGATE_FUNCTIONS) ∪ the dedicated window functions (MYSQL_WINDOW_FUNCTIONS: ROW_NUMBER, RANK, DENSE_RANK, PERCENT_RANK, CUME_DIST, NTILE, LEAD, LAG, FIRST_VALUE, LAST_VALUE, NTH_VALUE), both in the parser crate. MySQL grammatically admits OVER only on this set: OVER on an ordinary scalar built-in or a user function (ABS(x) OVER (), PERCENTILE_CONT(x, 0.5) OVER (), ANY_VALUE(x) OVER ()) is ER_PARSE_ERROR (1064) on mysql:8, while SUM(x) OVER () / ROW_NUMBER() OVER () / GROUP_CONCAT(x) OVER () parse (they fail only at binding or a not-supported-yet semantic reject). On for MySQL, off elsewhere.

The vocabulary must stay complete: an omission would over-reject a valid windowed call (the worse failure — no coverage-gap pin catches an over-rejection), so it is the engine-verified full MySQL 8.0 aggregate + window function list. A qualified name (db.f(x) OVER (), engine-rejected too) is not a single-part member and is likewise rejected. When off, OVER attaches to any call, matching every non-MySQL dialect.

This flag also gates the converse half of MySQL’s dedicated window-function grammar — the requirements the pure window functions (MYSQL_WINDOW_FUNCTIONS, admitted as call heads by carving them out of MYSQL_RESERVED_FUNCTION_NAME) carry once admitted. Unlike the aggregates (whose OVER is optional), each window function requires an OVER clause, takes a fixed positional argument arity (ROW_NUMBER/RANK/DENSE_RANK/PERCENT_RANK/CUME_DIST exactly 0, NTILE/ FIRST_VALUE/LAST_VALUE exactly 1, LEAD/LAG 1–3, NTH_VALUE exactly 2), and rejects the aggregate-only argument forms (*, a DISTINCT/ALL quantifier, an in-parenthesis ORDER BY, a SEPARATOR) — each violation an ER_PARSE_ERROR (1064) on mysql:8 (ROW_NUMBER() without OVER, ROW_NUMBER(1) OVER (), NTILE() OVER (), RANK(DISTINCT a) OVER ()). These are one indivisible dialect grammar, so they share the flag rather than a second knob that would have to co-vary with it. The parser enforces them in parse_function_call.

§window_function_tail: bool

Accept MySQL’s window-function post-) tail — the SQL:2016 [FROM {FIRST | LAST}] [{RESPECT | IGNORE} NULLS] clauses written between a null-treatment window function’s argument ) and its OVER clause, riding the shared FunctionCall’s window_tail field. On for MySQL, off everywhere else. Engine-verified on mysql:8, the accepted surface is narrow: the null treatment is admitted only on LEAD/LAG/FIRST_VALUE/LAST_VALUE/ NTH_VALUE and only as RESPECT NULLS (IGNORE NULLS grammar-admits but feature-rejects, ER_NOT_SUPPORTED_YET 1235); FROM {FIRST | LAST} is admitted only on NTH_VALUE and only as FROM FIRST (FROM LAST likewise 1235); the two clauses appear in that fixed order (the reverse is ER_PARSE_ERROR, 1064), and both sit strictly after the ) (the in-paren spelling MySQL rejects, unlike DuckDB’s null_treatment). Keyed on a single unquoted window-function name — a quoted `nth_value` or qualified db.nth_value takes the general-call path (rejected there), matching the engine. When off, the tail keywords are left unconsumed and the trailing text surfaces as a clean parse error. The parser enforces the per-function admission in parse_window_function_tail.

§standalone_argument_order_by: bool

Accept a bare in-parenthesis ORDER BY as the sole content of a call’s argument list — no positional argument preceding it (rank(ORDER BY x) OVER w, cume_dist(ORDER BY x DESC) OVER w). DuckDB lets a window/rank function carry its ordering inside the call parentheses instead of the OVER (ORDER BY …) clause; the order_by list is the same field the arguments-then-ORDER BY form (array_agg(x ORDER BY y)) already fills, so the call shape is unchanged — only the empty positional list is new. On for DuckDb/Lenient, off elsewhere: standard SQL / PostgreSQL / MySQL require at least one argument before an aggregate ORDER BY (engine-verified), so when off the leading ORDER keyword falls into the argument-expression grammar where the reserved word surfaces as a clean parse error.

A parse-level gate only. The per-function validity of the standalone form is a binding concern DuckDB enforces after parsing — sum/array_agg/string_agg and a bare rank(ORDER BY x) with no OVER are DuckDB binder/catalog rejects (the standalone form parses), so a parse-only parser correctly accepts them here; the one exception is DuckDB’s parser-level “ORDER BY is not supported for the window function dense_rank”, a fine-grained per-function restriction this gate deliberately does not model (see duckdb-order-by-in-agg-args-trailing-comma).

Implementations§

Source§

impl AggregateCallSyntax

Source

pub const ANSI: Self

The ANSI predefined value.

Source§

impl AggregateCallSyntax

Source

pub const DUCKDB: Self

Available on crate feature duckdb only.

The DUCKDB preset for aggregate call syntax.

Source§

impl AggregateCallSyntax

Source

pub const LENIENT: Self

Available on crate feature lenient only.

The LENIENT preset for aggregate call syntax.

Source§

impl AggregateCallSyntax

Source

pub const MYSQL: Self

Available on crate feature mysql only.

The MYSQL preset for aggregate call syntax.

Source§

impl AggregateCallSyntax

Source

pub const POSTGRES: Self

Available on crate feature postgres only.

The POSTGRES preset for aggregate call syntax.

Source§

impl AggregateCallSyntax

Source

pub const SQLITE: Self

Available on crate feature sqlite only.

The SQLITE preset for aggregate call syntax.

Trait Implementations§

Source§

impl Clone for AggregateCallSyntax

Source§

fn clone(&self) -> AggregateCallSyntax

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for AggregateCallSyntax

Source§

impl Debug for AggregateCallSyntax

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for AggregateCallSyntax

Source§

impl PartialEq for AggregateCallSyntax

Source§

fn eq(&self, other: &AggregateCallSyntax) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for AggregateCallSyntax

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.