InfluxElixir.Client.Local.SQLParser (InfluxElixir v0.1.22)

Copy Markdown View Source

SQL parser for InfluxElixir.Client.Local.

Recognises the SQL subset documented on InfluxElixir.Client.Local and produces a parsed_query/0 for the executor. It is deliberately strict: anything the real InfluxDB v3 engine would reject — or that the double cannot execute faithfully — is refused with a Client.Local:-prefixed 400 so a query cannot pass tests here and fail in production.

Pure functions only: no ETS, no connection state.

Summary

Types

Plain aggregates; :stddev/:var are the sample forms, as in InfluxDB.

An arithmetic expression inside an aggregate: a field reference, a numeric literal, or a binary operation over two expressions.

ORDER BY <column> [ASC|DESC]; the column may be time or any output alias.

A time comparand: nanoseconds since the epoch, or now() plus an offset in nanoseconds, resolved when the query runs.

Functions

Parses a SELECT statement into a parsed_query/0.

Parses the WHERE ... clause (if any) out of the text after FROM <table>.

Substitutes $name placeholders with SQL literals built from params.

Types

aggregate()

@type aggregate() ::
  :avg | :sum | :count | :min | :max | :stddev | :stddev_pop | :var | :var_pop

Plain aggregates; :stddev/:var are the sample forms, as in InfluxDB.

expr()

@type expr() ::
  {:field, binary()}
  | {:lit, number()}
  | {:op, :+ | :- | :* | :/, expr(), expr()}

An arithmetic expression inside an aggregate: a field reference, a numeric literal, or a binary operation over two expressions.

order_by()

@type order_by() :: {binary(), :asc | :desc} | nil

ORDER BY <column> [ASC|DESC]; the column may be time or any output alias.

parsed_query()

@type parsed_query() :: %{
  measurement: binary(),
  where: [where_clause()],
  order_by: order_by(),
  limit: pos_integer() | nil,
  group_by_interval: pos_integer() | nil,
  group_by_columns: [binary()] | nil,
  select_columns: [select_column()] | nil,
  distinct_columns: [binary()] | nil,
  projection_columns: [{binary(), binary()}] | nil
}

select_column()

@type select_column() ::
  {:time_bucket, binary()}
  | {:aggregate, aggregate(), expr(), binary()}
  | {:count_star, binary()}
  | {:count_distinct, binary(), binary()}
  | {:ordered_aggregate, :first | :last, binary(), binary(), binary()}
  | {:selector, :first | :last | :min | :max, binary(), binary(),
     :value | :time, binary()}
  | {:grouping_column, binary(), binary()}

time_value()

@type time_value() :: integer() | {:now, integer()}

A time comparand: nanoseconds since the epoch, or now() plus an offset in nanoseconds, resolved when the query runs.

where_clause()

@type where_clause() :: {where_op(), binary(), term()}

where_op()

@type where_op() ::
  :eq | :gt | :lt | :gte | :lte | :ne | :in | :not_in | :is_null | :is_not_null

Functions

parse_select(sql)

@spec parse_select(binary()) :: {:ok, parsed_query()} | {:error, term()}

Parses a SELECT statement into a parsed_query/0.

parse_where(rest)

@spec parse_where(binary()) :: {:ok, [where_clause()]} | {:error, map()}

Parses the WHERE ... clause (if any) out of the text after FROM <table>.

resolve_params(sql, params)

@spec resolve_params(binary(), map()) :: binary()

Substitutes $name placeholders with SQL literals built from params.