Selecto.Types (Selecto v0.4.5)

Copy Markdown

Comprehensive type definitions for the Selecto query builder.

This module defines all the types used throughout Selecto for better developer experience and Dialyzer support.

Summary

Types

t()

Types

advanced_join_type()

@type advanced_join_type() ::
  :hierarchical | :tagging | :dimension | :star_dimension | :snowflake_dimension

association()

@type association() :: %{
  :queryable => atom(),
  :field => atom(),
  :owner_key => atom(),
  :related_key => atom(),
  optional(:cardinality) => :one | :many,
  optional(:through) => [atom()]
}

atom_or_string()

@type atom_or_string() :: atom() | String.t()

basic_filter()

@type basic_filter() :: {field_name(), term()}

basic_join_config()

@type basic_join_config() :: %{
  :type => basic_join_type(),
  optional(:name) => String.t(),
  optional(:on) => term(),
  optional(:joins) => %{required(atom()) => join_config()}
}

basic_join_type()

@type basic_join_type() :: :left | :right | :inner | :full

basic_selector()

@type basic_selector() :: field_name()

builder_result()

@type builder_result() :: {iodata_with_markers(), sql_params(), join_dependencies()}

case_selector()

@type case_selector() ::
  {:case, conditions :: [{condition :: term(), value :: term()}],
   else_value :: term()}

column_definition()

@type column_definition() :: %{
  :type => column_type(),
  optional(:icon) => atom() | String.t(),
  optional(:icon_family) => atom() | String.t(),
  optional(:presentation_type) =>
    :date | :datetime | :utc_datetime | :naive_datetime,
  optional(:presentation) => %{
    optional(:semantic_type) => :measurement | :temporal | :number,
    optional(:quantity) => atom() | String.t(),
    optional(:canonical_unit) => atom() | String.t(),
    optional(:available_units) => [atom() | String.t()],
    optional(:default_unit) => atom() | String.t(),
    optional(:temporal_kind) =>
      :instant | :local_date | :local_time | :naive_datetime,
    optional(:storage_timezone) => String.t(),
    optional(:display_timezone) => :viewer | String.t(),
    optional(:format) => map()
  },
  optional(:datetime_storage) =>
    :unix
    | :unix_s
    | :unix_seconds
    | :unix_ms
    | :unix_milliseconds
    | :javascript_ms,
  optional(:precision) => pos_integer(),
  optional(:scale) => non_neg_integer(),
  optional(:default) => term(),
  optional(:null) => boolean()
}

column_type()

@type column_type() ::
  :integer
  | :string
  | :text
  | :boolean
  | :decimal
  | :float
  | :date
  | :time
  | :utc_datetime
  | :naive_datetime
  | :binary
  | :uuid
  | :json
  | :jsonb
  | :array
  | :geometry
  | :geography
  | :point
  | :linestring
  | :polygon
  | :multipoint
  | :multilinestring
  | :multipolygon
  | :geometrycollection

comparison_filter()

@type comparison_filter() :: {field_name(), {comparison_operator(), term()}}

comparison_operator()

@type comparison_operator() ::
  :eq
  | :not_eq
  | :gt
  | :gte
  | :lt
  | :lte
  | :like
  | :ilike
  | :not_like
  | :not_ilike
  | :is_null
  | :not_null
  | :in
  | :not_in
  | :between
  | :not_between

configure_options()

@type configure_options() :: [
  validate: boolean(),
  pool: boolean(),
  pool_options: keyword(),
  adapter: module(),
  rollup_sort_fix: boolean() | :auto
]

cte_builder_result()

@type cte_builder_result() ::
  {iodata_with_markers(), sql_params(), [cte_definition()]}

cte_definition()

@type cte_definition() :: %{
  name: String.t(),
  sql: iodata_with_markers(),
  params: sql_params(),
  recursive: boolean()
}

cte_marker()

@type cte_marker() :: {:cte, name :: String.t(), iodata_fragment()}

custom_selector()

@type custom_selector() :: {:custom, sql :: String.t(), params :: [term()]}

detail_action()

@type detail_action() :: %{
  :name => String.t(),
  :type => detail_action_type(),
  optional(:description) => String.t(),
  optional(:required_fields) => [field_name()],
  optional(:payload) => map()
}

detail_action_type()

@type detail_action_type() ::
  :modal | :iframe_modal | :external_link | :live_component

dimension_join_config()

@type dimension_join_config() :: %{
  :type => :dimension | :star_dimension | :snowflake_dimension,
  :display_field => atom(),
  optional(:dimension_key) => atom(),
  optional(:normalization_joins) => [
    %{table: String.t(), key: atom(), foreign_key: atom()}
  ],
  optional(:joins) => %{required(atom()) => join_config()}
}

domain()

@type domain() :: %{
  :name => String.t(),
  :source => source(),
  :schemas => %{required(atom()) => schema()},
  :joins => %{required(atom()) => join_config()},
  optional(:default_selected) => [selector()],
  optional(:required_filters) => [filter()],
  optional(:required_selected) => [selector()],
  optional(:required_order_by) => [order_spec()],
  optional(:required_group_by) => [field_name()],
  optional(:filters) => %{required(String.t()) => term()},
  optional(:detail_actions) => %{
    optional(atom() | String.t()) => detail_action()
  },
  optional(:domain_data) => term(),
  optional(:extensions) => [term()],
  optional(:functions) => function_registry(),
  optional(:query_members) => query_member_registry(),
  optional(:published_views) => published_view_registry()
}

domain_option_provider()

@type domain_option_provider() :: %{
  type: :domain,
  domain: atom(),
  value_field: atom(),
  display_field: atom(),
  filters: [filter()],
  order_by: [order_spec()]
}

enum_option_provider()

@type enum_option_provider() :: %{type: :enum, schema: module(), field: atom()}

execute_one_result_error()

@type execute_one_result_error() :: {:error, Selecto.Error.t()}

execute_one_result_ok()

@type execute_one_result_ok() :: {:ok, single_row_result()}

execute_options()

@type execute_options() :: [
  timeout: timeout(),
  log: boolean(),
  max_rows: pos_integer(),
  receive_timeout: timeout(),
  queue_timeout: timeout(),
  stream_timeout: timeout(),
  analyze_complexity: boolean(),
  format: term(),
  format_options: keyword() | map(),
  cache: boolean(),
  cache_ttl: pos_integer(),
  cache_namespace: String.t(),
  stream_producer: function()
]

execute_result_error()

@type execute_result_error() :: {:error, Selecto.Error.t()}

execute_result_ok()

@type execute_result_ok() :: {:ok, query_result()}

execute_stream_result_error()

@type execute_stream_result_error() :: {:error, Selecto.Error.t()}

execute_stream_result_ok()

@type execute_stream_result_ok() :: {:ok, Enumerable.t()}

extract_selector()

@type extract_selector() :: {:extract, part :: String.t(), from_field :: field_name()}

field_name()

@type field_name() :: atom() | String.t()

filter()

@type filter() :: basic_filter() | comparison_filter() | logical_filter()

function_arg_spec()

@type function_arg_spec() :: %{
  name: atom() | String.t(),
  type: term(),
  source: :selector | :value | :literal
}

function_kind()

@type function_kind() :: :scalar | :predicate | :table

function_registry()

@type function_registry() :: %{optional(atom() | String.t()) => function_spec()}

function_selector()

@type function_selector() ::
  {:func, function_name :: String.t(), args :: [field_name() | term()]}

function_spec()

@type function_spec() :: %{
  :kind => function_kind(),
  :sql_name => String.t(),
  optional(:args) => [function_arg_spec()],
  optional(:returns) => term(),
  optional(:allowed_in) => [atom()]
}

hierarchical_join_config()

@type hierarchical_join_config() :: %{
  :type => :hierarchical,
  :hierarchy_type => hierarchy_type(),
  optional(:depth_limit) => pos_integer(),
  optional(:path_field) => atom(),
  optional(:path_separator) => String.t(),
  optional(:root_condition) => term(),
  optional(:joins) => %{required(atom()) => join_config()}
}

hierarchy_type()

@type hierarchy_type() :: :adjacency_list | :materialized_path | :closure_table

iodata_fragment()

@type iodata_fragment() :: iolist() | String.t()

iodata_with_markers()

@type iodata_with_markers() :: [iodata_fragment() | param_marker() | cte_marker()]

join_config()

join_dependencies()

@type join_dependencies() :: [join_requirement()]

join_requirement()

@type join_requirement() :: {join_name :: atom(), required_for :: String.t()}

join_type()

@type join_type() :: basic_join_type() | advanced_join_type()

logical_filter()

@type logical_filter() :: {:and | :or, [filter()]}

maybe(t)

@type maybe(t) :: {:ok, t} | {:error, term()}

option_provider()

order_direction()

@type order_direction() :: :asc | :desc

order_spec()

@type order_spec() :: field_name() | {order_direction(), field_name()}

param_marker()

@type param_marker() :: {:param, term()}

pivot_config()

@type pivot_config() :: retarget_config()

pivot_join_path()

@type pivot_join_path() :: retarget_join_path()

processed_config()

@type processed_config() :: %{
  :source => source(),
  :source_table => table_name(),
  :primary_key => atom(),
  :columns => %{required(String.t()) => %{name: String.t()}},
  :joins => %{required(atom()) => processed_join()},
  :filters => %{required(String.t()) => term()},
  optional(:functions) => function_registry(),
  :domain_data => term(),
  optional(:extensions) => [{module(), keyword()}]
}

processed_join()

@type processed_join() :: %{
  :type => join_type(),
  :source => atom() | String.t(),
  :name => String.t(),
  optional(:fields) => %{required(String.t()) => %{name: String.t()}},
  optional(:filters) => %{required(String.t()) => term()},
  optional(:joins) => %{required(atom()) => processed_join()},
  optional(:parameters) => [term()],
  optional(:hierarchy_type) => hierarchy_type(),
  optional(:depth_limit) => pos_integer(),
  optional(:path_field) => atom(),
  optional(:path_separator) => String.t(),
  optional(:tag_field) => atom(),
  optional(:weight_field) => atom(),
  optional(:display_field) => atom(),
  optional(:dimension_key) => atom()
}

published_view_kind()

@type published_view_kind() :: :view | :materialized_view

published_view_registry()

@type published_view_registry() :: %{
  optional(atom() | String.t()) => published_view_spec()
}

published_view_spec()

@type published_view_spec() :: %{
  :database_name => String.t(),
  :kind => published_view_kind(),
  :query => function(),
  :columns => %{optional(atom() | String.t()) => map()},
  optional(:indexes) => [map()],
  optional(:refresh) => map()
}

query_member_registry()

@type query_member_registry() :: %{
  optional(:ctes) => %{optional(atom() | String.t()) => map()},
  optional(:values) => %{optional(atom() | String.t()) => map()},
  optional(:subqueries) => %{optional(atom() | String.t()) => map()},
  optional(:laterals) => %{optional(atom() | String.t()) => map()},
  optional(:unnests) => %{optional(atom() | String.t()) => map()}
}

query_option_provider()

@type query_option_provider() :: %{type: :query, query: String.t(), params: [term()]}

query_result()

@type query_result() ::
  {rows :: [[term()]], columns :: [String.t()],
   aliases :: %{required(String.t()) => String.t()}}

query_set()

@type query_set() :: %{
  :selected => [selector()],
  :filtered => [filter()],
  optional(:required_filters) => [filter()],
  optional(:post_retarget_filters) => [filter()],
  optional(:post_pivot_filters) => [filter()],
  :order_by => [order_spec()],
  :group_by => [field_name()],
  optional(:retarget_state) => retarget_config(),
  optional(:pivot_state) => retarget_config(),
  optional(:subselected) => [subselect_selector()]
}

relation_source_kind()

@type relation_source_kind() :: :table | :view | :materialized_view

result(t, e)

@type result(t, e) :: {:ok, t} | {:error, e}

retarget_config()

@type retarget_config() :: %{
  :target_schema => atom(),
  :join_path => [atom()],
  optional(:preserve_filters) => boolean(),
  optional(:subquery_strategy) => :exists | :in | :join
}

retarget_join_path()

@type retarget_join_path() :: [
  %{
    from_schema: atom(),
    to_schema: atom(),
    association_name: atom(),
    join_type: join_type()
  }
]

safe_execute_one_result()

@type safe_execute_one_result() ::
  execute_one_result_ok() | execute_one_result_error()

safe_execute_result()

@type safe_execute_result() :: execute_result_ok() | execute_result_error()

safe_execute_stream_result()

@type safe_execute_stream_result() ::
  execute_stream_result_ok() | execute_stream_result_error()

schema()

@type schema() :: %{
  :name => String.t(),
  :source_table => table_name(),
  :primary_key => atom(),
  :fields => [atom()],
  :redact_fields => [atom()],
  :columns => %{required(atom()) => column_definition()},
  :associations => %{required(atom()) => association()},
  optional(:source_kind) => relation_source_kind(),
  optional(:readonly) => boolean(),
  optional(:custom_filters) => %{required(atom()) => term()}
}

select_options_column()

@type select_options_column() :: %{
  :type => :select_options,
  :option_provider => option_provider(),
  :name => String.t(),
  optional(:multiple) => boolean(),
  optional(:searchable) => boolean(),
  optional(:cache_ttl) => pos_integer()
}

selector()

single_row_result()

@type single_row_result() ::
  {row :: [term()], aliases :: %{required(String.t()) => String.t()}}

source()

@type source() :: %{
  :source_table => table_name(),
  :primary_key => atom(),
  :fields => [atom()],
  :redact_fields => [atom()],
  :columns => %{required(atom()) => column_definition()},
  :associations => %{required(atom()) => association()},
  optional(:source_kind) => relation_source_kind(),
  optional(:readonly) => boolean()
}

sql_error()

@type sql_error() :: term()

sql_generation_options()

@type sql_generation_options() :: [
  include_comments: boolean(),
  pretty_print: boolean()
]

sql_params()

@type sql_params() :: [term()]

sql_result()

@type sql_result() :: {sql :: String.t(), params :: sql_params()}

static_option_provider()

@type static_option_provider() :: %{type: :static, values: [term()]}

stream_row_result()

@type stream_row_result() ::
  {row :: [term()], columns :: [String.t()], aliases :: [String.t()]}

subselect_config()

@type subselect_config() :: %{
  :target_table => table_name(),
  :join_condition => {field_name(), field_name()},
  :aggregation_type => subselect_format(),
  optional(:additional_filters) => [filter()]
}

subselect_format()

@type subselect_format() :: :json_agg | :array_agg | :string_agg | :count

subselect_selector()

@type subselect_selector() :: %{
  :fields => [field_name()],
  :target_schema => atom(),
  :format => subselect_format(),
  optional(:alias) => String.t(),
  optional(:join_path) => [atom() | String.t()],
  optional(:separator) => String.t(),
  optional(:order_by) => [order_spec()],
  optional(:filters) => [filter()]
}

t()

@type t() :: %Selecto{
  adapter: module() | nil,
  config: processed_config(),
  connection: term() | nil,
  domain: domain(),
  extensions: [{module(), keyword()}],
  postgrex_opts: term() | nil,
  set: query_set(),
  tenant: tenant_context() | nil
}

table_name()

@type table_name() :: String.t()

tagging_join_config()

@type tagging_join_config() :: %{
  :type => :tagging,
  :tag_field => atom(),
  optional(:weight_field) => atom(),
  optional(:min_weight) => number(),
  optional(:aggregation) => :string_agg | :array_agg | :count,
  optional(:separator) => String.t(),
  optional(:joins) => %{required(atom()) => join_config()}
}

tenant_context()

@type tenant_context() :: %{
  optional(:tenant_id) => term(),
  optional(:tenant_mode) => atom() | String.t(),
  optional(:tenant_field) => atom() | String.t(),
  optional(:prefix) => String.t(),
  optional(:namespace) => String.t(),
  optional(:required_filters) => [filter()]
}

window_selector()

@type window_selector() ::
  {:window, function_name :: String.t(), args :: [term()],
   window_spec :: term()}