trait LazyUnaryFunc {
    // Required methods
    fn eval<'a>(
        &'a self,
        datums: &[Datum<'a>],
        temp_storage: &'a RowArena,
        a: &'a MirScalarExpr
    ) -> Result<Datum<'a>, EvalError>;
    fn output_type(&self, input_type: ColumnType) -> ColumnType;
    fn propagates_nulls(&self) -> bool;
    fn introduces_nulls(&self) -> bool;
    fn preserves_uniqueness(&self) -> bool;
    fn inverse(&self) -> Option<UnaryFunc>;
    fn is_monotone(&self) -> bool;

    // Provided method
    fn could_error(&self) -> bool { ... }
}
Expand description

A description of an SQL unary function that has the ability to lazy evaluate its arguments

Required Methods§

source

fn eval<'a>( &'a self, datums: &[Datum<'a>], temp_storage: &'a RowArena, a: &'a MirScalarExpr ) -> Result<Datum<'a>, EvalError>

source

fn output_type(&self, input_type: ColumnType) -> ColumnType

The output ColumnType of this function.

source

fn propagates_nulls(&self) -> bool

Whether this function will produce NULL on NULL input.

source

fn introduces_nulls(&self) -> bool

Whether this function will produce NULL on non-NULL input.

source

fn preserves_uniqueness(&self) -> bool

Whether this function preserves uniqueness.

Uniqueness is preserved when if f(x) = f(y) then x = y is true. This is used by the optimizer when a guarantee can be made that a collection with unique items will stay unique when mapped by this function.

Note that error results are not covered: Even with preserves_uniqueness = true, it can happen that two different inputs produce the same error result. (e.g., in case of a narrowing cast)

Functions should conservatively return false unless they are certain the above property is true.

source

fn inverse(&self) -> Option<UnaryFunc>

The inverse of this function, if it has one and we have determined it.

The optimizer can use this information when selecting indexes, e.g. an indexed column has a cast applied to it, by moving the right inverse of the cast to another value, we can select the indexed column.

Note that a value of None does not imply that the inverse does not exist; it could also mean we have not yet invested the energy in representing it. For example, in the case of complex casts, such as between two list types, we could determine the right inverse, but doing so is not immediately necessary as this information is only used by the optimizer.

Right vs. left vs. inverses
  • Right inverses are when the inverse function preserves uniqueness. These are the functions that the optimizer uses to move casts between expressions.
  • Left inverses are when the function itself preserves uniqueness.
  • Inverses are when a function is both a right and a left inverse (e.g., bit_not_int64 is both a right and left inverse of itself).

We call this function inverse for simplicity’s sake; it doesn’t always correspond to the mathematical notion of “inverse.” However, in conjunction with checks to preserves_uniqueness you can determine which type of inverse we return.

source

fn is_monotone(&self) -> bool

Returns true if the function is monotone. (Non-strict; either increasing or decreasing.) Monotone functions map ranges to ranges: ie. given a range of possible inputs, we can determine the range of possible outputs just by mapping the endpoints.

This property describes the behaviour of the function over ranges where the function is defined: ie. the argument and the result are non-error datums.

Provided Methods§

source

fn could_error(&self) -> bool

Whether this function might error on non-error input.

Implementors§