The GROUP BY and ORDER BY clauses of a SQL text, as DataFusion reads
them (verified against InfluxDB 3 Core).
GROUP BY 1, ORDER BY 2 DESC and GROUP BY bucket (a select alias) are
rewritten to the select items they name before anything else reads the
clauses: a position becomes the item's expression in GROUP BY and its
output name in ORDER BY, an alias in GROUP BY becomes its expression. A
position outside the select list is the engine's planning error.
A GROUP BY item that is a DATE_BIN(...) sets the bucket interval; the
others are grouping columns, and the two combine (GROUP BY DATE_BIN(...), host: one row per bucket per host).
Summary
Types
:asc / :desc (nulls last / first), or a direction with explicit NULLS placement.
ORDER BY terms in order; a target is time, a column, an output alias or an expression.
Functions
Checks the DATE_BINs of a select list against the GROUP BY bucket
(group_interval, in nanoseconds): each must be that bucket, or the double
refuses the query by name.
The bare-column GROUP BY items of a statement (a quoted name as the name
it holds), or nil when there are none.
The GROUP BY DATE_BIN bucket of a statement in nanoseconds, or nil.
The DATE_BIN is optional: without it the executor groups by columns or
produces a single scalar row; a malformed interval still surfaces.
The ORDER BY a [ASC|DESC][, b [ASC|DESC] ...] terms of the text after
the table. A target may be a column, time, an output alias (the
DATE_BIN alias, say) or an expression (CAST(level AS INTEGER) DESC); a
target the expression parser cannot read is {:expr, {:unreadable, text}},
which unreadable_order/1 refuses by name. The direction defaults to
ascending, as in SQL.
How an ORDER BY term reads as a position among count select items
(verified against InfluxDB 3 Core): a whole number from 1 to count is
that position; 0, a position past count and one past UInt64 are the
engine's planning errors, and so is a number with a fraction or an
exponent. Anything else is not a position.
Rewrites the positions and select aliases of the clauses in rest, the
text after the table, to the items they name. columns is the select list;
namer gives the output name of an item without an alias, or nil
when the double cannot write it (the item then stands for itself).
The refusal of an ORDER BY term the double cannot read (a function it
does not have, a type it does not model: CAST(x AS FLOAT)), or :ok. The
engine answers it with rows or an error of its own; naming it a column, as
a schema error would, answers neither.
Types
@type direction() :: :asc | :desc | {:asc | :desc, :nulls_first | :nulls_last}
:asc / :desc (nulls last / first), or a direction with explicit NULLS placement.
@type order_by() :: [ {binary() | {:expr, InfluxElixir.Client.Local.SQLExpr.t()}, direction()} ]
ORDER BY terms in order; a target is time, a column, an output alias or an expression.
Functions
@spec check_date_bins(binary(), non_neg_integer() | nil) :: :ok | {:error, map()}
Checks the DATE_BINs of a select list against the GROUP BY bucket
(group_interval, in nanoseconds): each must be that bucket, or the double
refuses the query by name.
The bare-column GROUP BY items of a statement (a quoted name as the name
it holds), or nil when there are none.
@spec interval(binary()) :: {:ok, non_neg_integer() | nil} | {:error, term()}
The GROUP BY DATE_BIN bucket of a statement in nanoseconds, or nil.
The DATE_BIN is optional: without it the executor groups by columns or
produces a single scalar row; a malformed interval still surfaces.
The ORDER BY a [ASC|DESC][, b [ASC|DESC] ...] terms of the text after
the table. A target may be a column, time, an output alias (the
DATE_BIN alias, say) or an expression (CAST(level AS INTEGER) DESC); a
target the expression parser cannot read is {:expr, {:unreadable, text}},
which unreadable_order/1 refuses by name. The direction defaults to
ascending, as in SQL.
@spec order_position(binary(), non_neg_integer()) :: {:ok, pos_integer()} | :not_positional | {:error, InfluxElixir.Client.Local.SQLError.t()}
How an ORDER BY term reads as a position among count select items
(verified against InfluxDB 3 Core): a whole number from 1 to count is
that position; 0, a position past count and one past UInt64 are the
engine's planning errors, and so is a number with a fraction or an
exponent. Anything else is not a position.
@spec resolve_references(binary(), binary(), (binary() -> binary() | nil)) :: {:ok, binary()} | {:error, InfluxElixir.Client.Local.SQLError.t()}
Rewrites the positions and select aliases of the clauses in rest, the
text after the table, to the items they name. columns is the select list;
namer gives the output name of an item without an alias, or nil
when the double cannot write it (the item then stands for itself).
@spec unreadable_order(order_by()) :: :ok | {:error, InfluxElixir.Client.Local.SQLError.t()}
The refusal of an ORDER BY term the double cannot read (a function it
does not have, a type it does not model: CAST(x AS FLOAT)), or :ok. The
engine answers it with rows or an error of its own; naming it a column, as
a schema error would, answers neither.