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

Copy Markdown View Source

The numbers a SQL expression computes with in InfluxElixir.Client.Local, typed as the engine types them (verified against InfluxDB 3 Core).

A value is one of:

  • an Int64 as a bare integer, wrapping in two's complement
  • a UInt64 as {:u, n}, wrapping at 2^64
  • a Float64 as a bare float, or :inf, :neg_inf, :nan where the IEEE result is not a float Elixir can hold (an overflow raises there)
  • a Decimal128 as {:dec, coefficient, scale}, the value coefficient / 10^scale
  • an Int8, Int16 or Int32 (what a CAST to TINYINT, SMALLINT or INTEGER makes) as {:int, bits, n}, wrapping at its own width

Mixing types follows the engine's coercion: a Float64 with anything is a Float64; two Int64s are an Int64 and two UInt64s a UInt64; two narrow integers are the wider of the two (an Int32 and an Int16 are an Int32), and a narrow integer with an Int64 is an Int64; an Int64 with a UInt64, or anything with a decimal, is a decimal. A narrow integer with a UInt64 or a decimal is refused by name. A decimal sum, difference and remainder keep the larger scale, a product adds the scales, and a quotient has four places more than its dividend and is truncated toward zero. A decimal that needs more than 38 digits is outside what the double models and is refused by name.

An infinity or a NaN shows as null in a response. An infinity compares as a number (it is larger than every finite value); a NaN is ordered by its sign bit, which the CPU that produced it chooses, so a comparison of a NaN is refused by name. A float compares as the engine's total order does: -0.0 is less than 0.0.

Summary

Types

A Decimal128: {:dec, coefficient, scale}.

An Int8, Int16 or Int32: {:int, bits, n}.

An arithmetic operator.

A float Elixir cannot hold.

t()

A number the evaluator computes with.

Functions

left op right as the engine computes it. An integer divided by zero, and the Int64 minimum by -1, close the engine's connection; a decimal that needs more than 38 digits is refused by name.

Orders two numbers as the engine does: exactly for integers and decimals, as doubles when either is a float (-0.0 below 0.0, an infinity beyond every finite value). A NaN is refused by name.

The smallest value of a signed integer type, or 0 for :uint64.

The number negated. The Int64 minimum overflows: the engine folds a constant (constant?) and fails the query, closing the connection; over a column the kernel wraps and the minimum is its own negation (both verified).

The float negated; an infinity turns around, a NaN stays a NaN.

Whether the value is a number the evaluator computes with.

The Arrow type name of an arithmetic result given its operands' type names; "Decimal128(?)" stands for a decimal whose precision is not tracked.

The value as a response carries it: a UInt64 and a scale-0 decimal as an integer, another decimal as a float, an infinity or a NaN as nil (a null that is there), anything else as it is.

The number as a Float64: a float, or a special. A decimal is its coefficient as a double over 10^scale as a double, as the engine converts it (verified: it differs from the nearest double of the decimal value for a coefficient past 2^53).

The Arrow type name of a number.

Types

decimal()

@type decimal() :: {:dec, integer(), non_neg_integer()}

A Decimal128: {:dec, coefficient, scale}.

narrow()

@type narrow() :: {:int, 8 | 16 | 32, integer()}

An Int8, Int16 or Int32: {:int, bits, n}.

op()

@type op() :: :+ | :- | :* | :/ | :rem

An arithmetic operator.

special()

@type special() :: :inf | :neg_inf | :nan

A float Elixir cannot hold.

t()

@type t() ::
  integer()
  | float()
  | special()
  | {:u, non_neg_integer()}
  | decimal()
  | narrow()

A number the evaluator computes with.

Functions

arithmetic(op, left, right)

@spec arithmetic(op(), t(), t()) :: t()

left op right as the engine computes it. An integer divided by zero, and the Int64 minimum by -1, close the engine's connection; a decimal that needs more than 38 digits is refused by name.

compare(left, right)

@spec compare(t(), t()) :: :lt | :eq | :gt

Orders two numbers as the engine does: exactly for integers and decimals, as doubles when either is a float (-0.0 below 0.0, an infinity beyond every finite value). A NaN is refused by name.

minimum(bits)

@spec minimum(:int64 | :uint64 | 8 | 16 | 32) :: integer()

The smallest value of a signed integer type, or 0 for :uint64.

negate(value, constant?)

@spec negate(t(), boolean()) :: t()

The number negated. The Int64 minimum overflows: the engine folds a constant (constant?) and fails the query, closing the connection; over a column the kernel wraps and the minimum is its own negation (both verified).

negate_float(value)

@spec negate_float(float() | special()) :: float() | special()

The float negated; an infinity turns around, a NaN stays a NaN.

numeric?(value)

@spec numeric?(term()) :: boolean()

Whether the value is a number the evaluator computes with.

result_type(left, right)

@spec result_type(binary(), binary()) :: binary()

The Arrow type name of an arithmetic result given its operands' type names; "Decimal128(?)" stands for a decimal whose precision is not tracked.

row_value(value)

@spec row_value(term()) :: term()

The value as a response carries it: a UInt64 and a scale-0 decimal as an integer, another decimal as a float, an infinity or a NaN as nil (a null that is there), anything else as it is.

to_float(value)

@spec to_float(t()) :: float() | special()

The number as a Float64: a float, or a special. A decimal is its coefficient as a double over 10^scale as a double, as the engine converts it (verified: it differs from the nearest double of the decimal value for a coefficient past 2^53).

type_name(value)

@spec type_name(t()) :: binary()

The Arrow type name of a number.