Packages

Mix formatter plugin that reorders columns in Ecto migrations for optimal PostgreSQL column alignment

Current section

Files

Jump to
psql_tetris lib psql_tetris optimizer.ex
Raw

lib/psql_tetris/optimizer.ex

defmodule PsqlTetris.Optimizer do
@moduledoc """
Pure ordering logic. Given a list of column descriptors, returns them in the order PostgreSQL would prefer for minimal row padding.
A column descriptor is a map (or struct-shaped map) with at least:
* `:type` : the Ecto migration type (atom or tuple)
* `:opts` : keyword list passed to `add/3` (may be `[]`)
Any other keys are preserved untouched.
The sort is stable, so columns of the same alignment rank keep their author-defined order. Within a rank, `null: false` columns come first, which is a tiny CPU win during tuple deforming.
"""
alias PsqlTetris.Types
@spec optimize([map()]) :: [map()]
def optimize(columns) when is_list(columns) do
columns
|> Enum.with_index()
|> Enum.sort_by(fn {col, idx} ->
rank = Types.rank(col.type, Map.get(col, :opts, []))
not_null_first = if not_null?(col), do: 0, else: 1
{rank, not_null_first, idx}
end)
|> Enum.map(fn {col, _idx} -> col end)
end
defp not_null?(%{opts: opts}) when is_list(opts), do: Keyword.get(opts, :null) == false
defp not_null?(_), do: false
end