InfluxElixir.Client.Local.SQLBounds (InfluxElixir v0.1.40)

Copy Markdown View Source

The engine's failure on a WHERE that leaves a numeric column no value (verified against InfluxDB 3 Core).

When every top-level conjunct of the WHERE is one its interval analysis can take, and the comparisons of a bare Int64, UInt64 or Float64 column with literals leave that column an empty interval, the query fails with status 500 instead of answering []. The analysis reads:

  • <, <=, >, >=, =, either way round, BETWEEN, a one-element IN, and a NOT of those, against a number or a $param that is one
  • an integer column's exclusive bound as the next integer (v > 1 AND v < 2 is empty), a float column's as the next double
  • a bound at the end of the type's range as that end (v > 9223372036854775807 alone is not empty), except u < 0 on an unsigned column, which is

Any conjunct the analysis cannot take makes it give up, and the answer is the rows: !=, NOT IN, NOT BETWEEN, a longer IN, IS [NOT] NULL of a column, a null or text comparand, a string, tag or boolean column, a comparison of time, an OR, a constant false, two different = of one column, a negative literal against an unsigned column. An integer column compared with a float literal is cast by the engine and does not take part.

The same analysis evaluates the constants of the conjuncts it takes, and one that overflows (the negation of the smallest integer of a type) fails the query before any row is read: status 500, Arrow error: Arithmetic overflow: Overflow happened on: - -9223372036854775808. It does so only when the analysis takes every conjunct; with one it cannot take (or in a select list) the constant is read per row, and the connection is closed (SQLNumber.negate/2).

The body names the first conjunct, in the order written (BETWEEN is >= low then <= high): a lower bound or >= reads lhs:Null, rhs:<type>, an upper bound lhs:<type>, rhs:Null, an = is the intersectable variant reading lhs:Null, rhs:<type>; the type is that conjunct's column's.

What this does not pin down is refused by name: a column with two bounds one of which implies the other (the engine's choice of conjunct then changes with the set), an integer column bounded by both an integer and a float literal, a conjunct whose analysis is not known (an arithmetic expression, a comparison of two columns), and a filter over a CTE.

Summary

Types

What the engine's analysis reads a numeric column as; :other is any other column.

Looks up a column's type, or nil for a column that is not there.

Functions

Whether the engine fails the WHERE: :ok, or the engine's error, or the refusal of a shape that is not pinned down. opts may carry cte: true when the query filters a CTE, whose filter the engine may or may not push to the table: the failure is refused rather than answered.

Types

column_type()

@type column_type() :: :int64 | :uint64 | :float64 | :other

What the engine's analysis reads a numeric column as; :other is any other column.

type_of()

@type type_of() :: (binary() -> column_type() | nil)

Looks up a column's type, or nil for a column that is not there.

Functions

check(where, type_of, opts \\ [])

@spec check([term()], type_of(), keyword()) ::
  :ok | {:error, InfluxElixir.Client.Local.SQLError.t()}

Whether the engine fails the WHERE: :ok, or the engine's error, or the refusal of a shape that is not pinned down. opts may carry cte: true when the query filters a CTE, whose filter the engine may or may not push to the table: the failure is refused rather than answered.