View Source Electric.Replication.Eval.Lookups (electric v0.9.5)

Summary

Functions

Given multiple possible function overloads (same name and arity), try to find a concrete implementation that matches the argument types.

Given multiple possible operator overloads (same name and arity), try to find a concrete implementation that matches the argument types.

Given a list of types, get a candidate type that best represents the union of all types.

Functions

Link to this function

pick_concrete_function_overload(choices, args, env)

View Source
@spec pick_concrete_function_overload(
  list(),
  [struct()],
  Electric.Replication.Eval.Env.t()
) ::
  {:ok, term()} | :error

Given multiple possible function overloads (same name and arity), try to find a concrete implementation that matches the argument types.

Rules for picking a function overload closely mimic those outlined in postgres documentation:

  1. Check if there is an overload where all variable types match exactly
  2. Check if only one overload remains based on implicit conversion rules (unknowns are considered always matching), discard those that cannot be applied even after implicit conversion
  3. Check if only one overload remains based on most exact type matches
  4. Keep overloads that accept most preferred types in each conversion spot
  5. If there are any unknowns, for each position first look for any overloads that accept string category, and if none found, check if all overloads accept the same type category. If that fails, keep all overloads, or pick any that don't accept picked category
  6. If there are both unknown and known arguments, and all known arguments have the same type category, assume unknowns have the same type category and look for overloads that fit.

If exactly one overload matched after those steps, pick it, otherwise fail.

Link to this function

pick_concrete_operator_overload(choices, args, env)

View Source
@spec pick_concrete_operator_overload(
  list(),
  [struct()],
  Electric.Replication.Eval.Env.t()
) ::
  {:ok, term()} | :error

Given multiple possible operator overloads (same name and arity), try to find a concrete implementation that matches the argument types.

Operators can only be 1 or 2-arity.

Rules for picking a operation overload closely mimic those outlined in postgres documentation, and mostly match pick_concrete_function_overload/3.

Link to this function

pick_union_type(args, env)

View Source

Given a list of types, get a candidate type that best represents the union of all types.

Algorithm implements Postgres type resolution for UNION, CASE, and related constructs, like ARRAY[] constructor syntax. They are outlined in documentation.

  1. If all inputs are of the same type, and it is not unknown, resolve as that type.
  2. If any input is of a domain type, treat it as being of the domain's base type for all subsequent steps.
  3. If all inputs are of type unknown, resolve as type text (the preferred type of the string category). Otherwise, unknown inputs are ignored for the purposes of the remaining rules.
  4. If the non-unknown inputs are not all of the same type category, fail.
  5. Select the first non-unknown input type as the candidate type, then consider each other non-unknown input type, left to right. If the candidate type can be implicitly converted to the other type but not vice-versa, select the other type as the new candidate type. Then continue considering the remaining inputs. If, at any stage of this process, a preferred type is selected, stop considering additional inputs.
  6. Convert all inputs to the final candidate type. Fail if there is not an implicit conversion from a given input type to the candidate type.