View Source Electric.Replication.Eval.Env (electric v0.9.5)
Evaluation environment for parsing PostgreSQL expressions.
We have a need to parse PG expressions, and then be able to execute them in Electric without reaching for Postgres on every operation. This is achieved by parsing Postgres expressions, however Postgres has a lot of features we're unlikely to support, and, moreover, very dynamic: new features, new data types - everything can be redefined, including so-called "preferred" data types, new type categories, implicit casts, etc. Redefining all this for normal types is quite unlikely in the wild, but may be later common for custom types.
Parsing PG expressions, we need to know what we support. It's then reasonable
to have a good set of defaults we know how to deal with, but leave an escape hatch
so that until we add support for pulling all this data from PG, we have a working
system. Even afterwards, a set of PG functions using, say PLSQL
is likely to use
default PG functions, which we still need to know how to execute.
This module defines a struct that contains information, relevant to parsing PG statements into something Electric can understand, while respecting PG types and function/operator overload selections.
It's also worth noting that our defaults, especially implicit casts specifically
omit any "system" types (e.g. regclass
or pg_ndistinct
) because we're essentially
never going to have enough context in Electric to be able to correctly utilize those
types.
Summary
Functions
Check if a list of inputs can be implicitly coerced to a list of targets.
Create a new empty environment, without any default functions or explicit casts
Get type category for the given type (possibly non-basic).
Check if one type is implicitly castable to another type in this environment.
Check if type is preferred within the type category.
Create a new environment with known defaults, merging in provided keys
Parse an unknown value constant as a known type in the current environment.
Types
@type basic_type() :: atom()
@type basic_type_registry() :: %{required(basic_type()) => type_info()}
@type cast_key() :: {from :: basic_type(), to :: basic_type()}
@type cast_registry() :: %{required(cast_key()) => cast_function()}
@type env_property() :: {:funcs, funcs()} | {:operators, funcs()} | {:explicit_casts, cast_registry()} | {:implicit_casts, implicit_cast_registry()} | {:known_basic_types, basic_type_registry()}
@type flat_pg_type() :: basic_type() | {:composite, map()} | :record | {:enum, term()}
@type func_id() :: {name :: String.t(), arity :: non_neg_integer()}
@type implicit_cast_registry() :: %{required(cast_key()) => cast_function() | :as_is}
@type pg_type() :: flat_pg_type() | {:array, flat_pg_type()} | {:range, flat_pg_type()} | {:multirange, flat_pg_type()}
@type t() :: %Electric.Replication.Eval.Env{ explicit_casts: cast_registry(), funcs: funcs(), implicit_casts: implicit_cast_registry(), known_basic_types: basic_type_registry(), operators: funcs() }
Functions
Check if a list of inputs can be implicitly coerced to a list of targets.
Note that other functions may not exactly support all of types
Create a new empty environment, without any default functions or explicit casts
Get type category for the given type (possibly non-basic).
get_unified_coercion_targets(env, inputs, targets, return_type \\ nil)
View Source@spec implicitly_castable?(t(), basic_type(), basic_type()) :: boolean()
Check if one type is implicitly castable to another type in this environment.
Check if type is preferred within the type category.
@spec new([env_property()]) :: t()
Create a new environment with known defaults, merging in provided keys
Parse an unknown value constant as a known type in the current environment.