Lantern (Lantern v0.6.0)

Copy Markdown View Source

An embeddable Postgres viewer/editor.

Lantern is a self-contained data layer plus a Phoenix.LiveComponent (Lantern.Explorer) that lets you browse and edit any Postgres database from a connection you supply. It is connection-agnostic: hand it a URL string, keyword options, or a struct exposing host/port/username/password (see Lantern.Source) and it opens short-lived connections on demand.

This module is the public data API. It performs introspection (list_schemas/1, list_tables/2, columns/3, primary_keys/3), reads (query/3), and safe, primary-key-scoped writes (insert/3, update/4, delete/3). Writes send values as text parameters cast to each column's type, so no value is ever interpolated into SQL.

Summary

Functions

Adds a column. column is a column spec. Returns :ok or {:error, message}.

Changes a column's type. Returns :ok or {:error, message}.

Applies update/delete changes in one database transaction.

Returns column metadata (name, type, udt, nullability) for a table.

Creates an index on a table. Returns :ok or {:error, message}.

Creates a table. columns is a list of column specs (see Lantern.SQL.column/0); at least one is required.

Deletes one or more rows. keys is a list of %{pk_column => value} maps.

Drops a column. Returns :ok or {:error, message}.

Drops a table constraint. Returns :ok or {:error, message}.

Drops an index. Returns :ok or {:error, message}.

Drops a table. Returns :ok or {:error, message}.

Inserts a row. values is a %{column => value} map (value nil → NULL).

Lists enum types in a schema. Defaults to public.

Lists user-visible schemas that contain base tables.

Lists base tables in a schema. Defaults to public.

Lists views in a schema. Defaults to public.

Returns the ordered primary-key column names for a table (may be empty).

Reads rows from table with optional filtering, sorting, and pagination.

Returns up to limit {value, label} options from a referenced table, for rendering a foreign-key lookup. Labels prefer a human-readable column (name/title/email/…) and fall back to the referenced key itself.

Renames a column. Returns :ok or {:error, message}.

Renames a table. Returns :ok or {:error, message}.

Runs an operator-supplied SQL statement and returns its columns and rows.

Loads everything Lantern.Explorer needs to display a table — columns (typed), primary keys, and pre-fetched FK lookup options — using a single Postgres connection instead of N+1.

Sets whether a column accepts NULL. Returns :ok or {:error, message}.

Returns detailed metadata for one table.

Lists base tables with total/table/index size metadata.

Updates one row identified by its primary key.

Types

column()

@type column() :: %{
  name: String.t(),
  type: String.t(),
  udt: String.t(),
  nullable: boolean(),
  enum_values: [String.t()] | nil,
  fk: %{schema: String.t(), table: String.t(), column: String.t()} | nil
}

source()

@type source() :: Lantern.Source.t() | String.t() | keyword() | map()

table_info()

@type table_info() :: %{
  schema: String.t(),
  name: String.t(),
  stats: table_stat() | nil,
  estimated_rows: non_neg_integer(),
  row_level_security?: boolean(),
  columns: [column()],
  primary_keys: [String.t()],
  constraints: [%{name: String.t(), type: String.t(), definition: String.t()}],
  indexes: [%{name: String.t(), definition: String.t()}]
}

table_stat()

@type table_stat() :: %{
  name: String.t(),
  total_bytes: non_neg_integer(),
  table_bytes: non_neg_integer(),
  index_bytes: non_neg_integer(),
  total_size: String.t(),
  table_size: String.t(),
  index_size: String.t()
}

Functions

add_column(source, table, column, opts \\ [])

@spec add_column(source(), String.t(), Lantern.SQL.column(), keyword()) ::
  :ok | {:error, String.t()}

Adds a column. column is a column spec. Returns :ok or {:error, message}.

alter_column_type(source, table, column, type, opts \\ [])

@spec alter_column_type(source(), String.t(), String.t(), String.t(), keyword()) ::
  :ok | {:error, String.t()}

Changes a column's type. Returns :ok or {:error, message}.

apply_changes(source, table, changes, opts \\ [])

@spec apply_changes(source(), String.t(), [map()], keyword()) ::
  {:ok, non_neg_integer()} | {:error, term()}

Applies update/delete changes in one database transaction.

Changes are maps with either %{action: :update, changes: map, key: map} or %{action: :delete, keys: [map]}. Returns {:ok, count} for applied change groups, or rolls the transaction back and returns the first error.

columns(source, table, opts \\ [])

@spec columns(source(), String.t(), keyword()) ::
  {:ok, [column()]} | {:error, String.t()}

Returns column metadata (name, type, udt, nullability) for a table.

create_index(source, table, index_name, columns, opts \\ [])

@spec create_index(source(), String.t(), String.t(), [String.t()], keyword()) ::
  :ok | {:error, String.t()}

Creates an index on a table. Returns :ok or {:error, message}.

create_table(source, table, columns, opts \\ [])

@spec create_table(source(), String.t(), [Lantern.SQL.column()], keyword()) ::
  :ok | {:error, String.t()}

Creates a table. columns is a list of column specs (see Lantern.SQL.column/0); at least one is required.

Returns :ok or {:error, message} — both validation failures (blank name, no columns, unsupported type) and Postgres errors come back as a message string ready to show the operator.

delete(source, table, keys, opts \\ [])

@spec delete(source(), String.t(), [map()], keyword()) ::
  {:ok, non_neg_integer()} | {:error, term()}

Deletes one or more rows. keys is a list of %{pk_column => value} maps.

Returns {:ok, deleted_count}.

drop_column(source, table, column, opts \\ [])

@spec drop_column(source(), String.t(), String.t(), keyword()) ::
  :ok | {:error, String.t()}

Drops a column. Returns :ok or {:error, message}.

drop_constraint(source, table, constraint_name, opts \\ [])

@spec drop_constraint(source(), String.t(), String.t(), keyword()) ::
  :ok | {:error, String.t()}

Drops a table constraint. Returns :ok or {:error, message}.

drop_index(source, index_name, opts \\ [])

@spec drop_index(source(), String.t(), keyword()) :: :ok | {:error, String.t()}

Drops an index. Returns :ok or {:error, message}.

drop_table(source, table, opts \\ [])

@spec drop_table(source(), String.t(), keyword()) :: :ok | {:error, String.t()}

Drops a table. Returns :ok or {:error, message}.

insert(source, table, values, opts \\ [])

@spec insert(source(), String.t(), map(), keyword()) ::
  {:ok, map()} | {:error, term()}

Inserts a row. values is a %{column => value} map (value nil → NULL).

Returns {:ok, inserted_row_map} keyed by column name.

list_enums(source, opts \\ [])

@spec list_enums(
  source(),
  keyword()
) :: {:ok, [%{name: String.t(), values: [String.t()]}]} | {:error, String.t()}

Lists enum types in a schema. Defaults to public.

list_schemas(source)

@spec list_schemas(source()) :: {:ok, [String.t()]} | {:error, String.t()}

Lists user-visible schemas that contain base tables.

list_tables(source, opts \\ [])

@spec list_tables(
  source(),
  keyword()
) :: {:ok, [String.t()]} | {:error, String.t()}

Lists base tables in a schema. Defaults to public.

list_views(source, opts \\ [])

@spec list_views(
  source(),
  keyword()
) :: {:ok, [String.t()]} | {:error, String.t()}

Lists views in a schema. Defaults to public.

primary_keys(source, table, opts \\ [])

@spec primary_keys(source(), String.t(), keyword()) ::
  {:ok, [String.t()]} | {:error, String.t()}

Returns the ordered primary-key column names for a table (may be empty).

query(source, table, opts \\ [])

@spec query(source(), String.t(), keyword()) :: {:ok, map()} | {:error, String.t()}

Reads rows from table with optional filtering, sorting, and pagination.

Options

  • :schema — Postgres schema/namespace. Default "public"
  • :where_clause — raw SQL fragment without WHERE (operator's own DB)
  • :filters — safe filter descriptors (%{column:, op:, value:}) combined with AND
  • :sort_by — column name (validated against the live column list)
  • :sort_dir:asc (default) or :desc
  • :limit — default 100
  • :offset — default 0
  • :count:exact (default) or false to skip COUNT(*)

Returns {:ok, %{columns: [name], rows: [[value]], count: integer | nil, count_kind: atom}}.

reference_options(source, ftable, fcolumn, limit \\ 100, opts \\ [])

@spec reference_options(source(), String.t(), String.t(), pos_integer(), keyword()) ::
  {:ok, [{String.t(), String.t()}]} | {:error, term()}

Returns up to limit {value, label} options from a referenced table, for rendering a foreign-key lookup. Labels prefer a human-readable column (name/title/email/…) and fall back to the referenced key itself.

rename_column(source, table, from, to, opts \\ [])

@spec rename_column(source(), String.t(), String.t(), String.t(), keyword()) ::
  :ok | {:error, String.t()}

Renames a column. Returns :ok or {:error, message}.

rename_table(source, table, new_name, opts \\ [])

@spec rename_table(source(), String.t(), String.t(), keyword()) ::
  :ok | {:error, String.t()}

Renames a table. Returns :ok or {:error, message}.

run_query(source, sql, opts \\ [])

@spec run_query(source(), String.t(), keyword()) ::
  {:ok, map()} | {:error, String.t()}

Runs an operator-supplied SQL statement and returns its columns and rows.

This is intentionally a low-level escape hatch for trusted database workspaces. Embedders should expose it only to operators who are allowed to run arbitrary SQL against the configured connection.

schema(source, table, opts \\ [])

@spec schema(source(), String.t(), keyword()) ::
  {:ok, %{columns: [column()], primary_keys: [String.t()], fk_options: map()}}
  | {:error, String.t()}

Loads everything Lantern.Explorer needs to display a table — columns (typed), primary keys, and pre-fetched FK lookup options — using a single Postgres connection instead of N+1.

set_column_nullable(source, table, column, nullable, opts \\ [])

@spec set_column_nullable(source(), String.t(), String.t(), boolean(), keyword()) ::
  :ok | {:error, String.t()}

Sets whether a column accepts NULL. Returns :ok or {:error, message}.

table_info(source, table, opts \\ [])

@spec table_info(source(), String.t(), keyword()) ::
  {:ok, table_info()} | {:error, String.t()}

Returns detailed metadata for one table.

table_stats(source, opts \\ [])

@spec table_stats(
  source(),
  keyword()
) :: {:ok, [table_stat()]} | {:error, String.t()}

Lists base tables with total/table/index size metadata.

update(source, table, changes, key, opts \\ [])

@spec update(source(), String.t(), map(), map(), keyword()) ::
  {:ok, map()} | {:error, term()}

Updates one row identified by its primary key.

changes is %{column => value}; key is %{pk_column => value}. Requires the table to have a primary key and key to cover it exactly.