Selecto.TypeSystem (Selecto v0.3.8)

Type inference and coercion system for Selecto SQL expressions.

This module provides:

  • Type inference for expressions (fields, functions, literals, complex expressions)
  • Type compatibility checking for comparisons and set operations
  • Type coercion rules for implicit type conversions
  • Return type determination for SQL functions and aggregates

type-categories

Type Categories

Selecto organizes SQL types into the following categories:

  • Numeric: :integer, :bigint, :smallint, :decimal, :float, :numeric
  • String: :string, :text, :varchar, :char
  • Boolean: :boolean
  • DateTime: :date, :time, :datetime, :utc_datetime, :naive_datetime, :timestamp
  • JSON: :json, :jsonb, :map
  • Array: {:array, inner_type}
  • Binary: :binary, :bytea
  • UUID: :uuid, :binary_id
  • Spatial: :geometry, :geography, :point, :polygon, etc.

usage

Usage

# Infer type of an expression
{:ok, :integer} = Selecto.TypeSystem.infer_type(selecto, {:count, "*"})
{:ok, :decimal} = Selecto.TypeSystem.infer_type(selecto, {:sum, "price"})
{:ok, :string} = Selecto.TypeSystem.infer_type(selecto, "product_name")

# Check type compatibility
true = Selecto.TypeSystem.compatible?(:integer, :decimal)
false = Selecto.TypeSystem.compatible?(:string, :boolean)

# Get coerced type for operation
{:ok, :decimal} = Selecto.TypeSystem.coerce_types(:integer, :decimal, :arithmetic)

Link to this section Summary

Functions

Determine the result type when coercing two types for an operation.

Check if two types are compatible for comparisons or assignments.

Check if a type is a date/time type.

Infer the SQL type of an expression.

Infer type and return just the type (for internal use where errors are handled upstream).

Normalize Ecto types to Selecto's internal type representation.

Check if a type is numeric.

Parse a SQL type string into an atom type.

Check if a type is a string type.

Get the type category for a given SQL type.

Link to this section Types

@type sql_type() ::
  :unknown
  | :integer
  | :bigint
  | :smallint
  | :decimal
  | :float
  | :numeric
  | :string
  | :text
  | :varchar
  | :char
  | :boolean
  | :date
  | :time
  | :datetime
  | :utc_datetime
  | :naive_datetime
  | :timestamp
  | :json
  | :jsonb
  | :map
  | :binary
  | :bytea
  | :uuid
  | :binary_id
  | :geometry
  | :geography
  | :point
  | :linestring
  | :polygon
  | :multipoint
  | :multilinestring
  | :multipolygon
  | :geometrycollection
  | {:array, sql_type()}
Link to this type

type_category()

@type type_category() ::
  :numeric
  | :string
  | :boolean
  | :datetime
  | :json
  | :array
  | :binary
  | :uuid
  | :spatial
  | :unknown

Link to this section Functions

Link to this function

coerce_types(type1, type2, operation)

@spec coerce_types(sql_type(), sql_type(), atom()) ::
  {:ok, sql_type()} | {:error, String.t()}

Determine the result type when coercing two types for an operation.

operation-types

Operation Types

  • :arithmetic - Numeric operations (+, -, *, /)
  • :comparison - Comparison operations (=, <>, <, >, etc.)
  • :concatenation - String concatenation (||)
  • :union - Set operations (UNION, INTERSECT, EXCEPT)
Link to this function

compatible?(type, type)

@spec compatible?(sql_type(), sql_type()) :: boolean()

Check if two types are compatible for comparisons or assignments.

Link to this function

datetime_type?(type)

@spec datetime_type?(sql_type()) :: boolean()

Check if a type is a date/time type.

Link to this function

infer_type(selecto, expression)

@spec infer_type(Selecto.t(), term()) :: {:ok, sql_type()} | {:error, term()}

Infer the SQL type of an expression.

Returns {:ok, type} for successfully inferred types, or {:ok, :unknown} when the type cannot be determined.

examples

Examples

iex> infer_type(selecto, "product_name")
{:ok, :string}

iex> infer_type(selecto, {:count, "*"})
{:ok, :bigint}

iex> infer_type(selecto, {:sum, "price"})
{:ok, :decimal}
Link to this function

infer_type!(selecto, expression)

@spec infer_type!(Selecto.t(), term()) :: sql_type()

Infer type and return just the type (for internal use where errors are handled upstream).

Link to this function

normalize_type(type)

@spec normalize_type(atom()) :: sql_type()

Normalize Ecto types to Selecto's internal type representation.

Link to this function

numeric_type?(type)

@spec numeric_type?(sql_type()) :: boolean()

Check if a type is numeric.

Link to this function

parse_sql_type(type_str)

@spec parse_sql_type(String.t()) :: sql_type()

Parse a SQL type string into an atom type.

Link to this function

string_type?(type)

@spec string_type?(sql_type()) :: boolean()

Check if a type is a string type.

Link to this function

type_category(type)

@spec type_category(sql_type()) :: type_category()

Get the type category for a given SQL type.