Xqlite.TypeExtension behaviour (Xqlite v0.7.0)

View Source

Behaviour for converting between Elixir types and SQLite storage values.

SQLite supports five storage types: NULL, INTEGER, REAL, TEXT, and BLOB. Type extensions bridge the gap between richer Elixir types (DateTime, Date, custom structs) and these storage types.

Callbacks

  • encode/1 — converts an Elixir term to a SQLite-compatible value. Return {:ok, sqlite_value} on success or :skip to pass to the next extension in the chain.

  • decode/1 — converts a SQLite value back to an Elixir term. Return {:ok, elixir_term} on success or :skip to pass to the next extension.

Built-in extensions

Extension ordering

Extensions are applied in list order. The first extension that returns {:ok, value} wins — remaining extensions are not consulted. This matters most for decode/1, where multiple extensions might match the same string format. Place more specific extensions before general ones.

Example

defmodule MyApp.DecimalExtension do
  @behaviour Xqlite.TypeExtension

  @impl true
  def encode(%Decimal{} = d), do: {:ok, Decimal.to_string(d)}
  def encode(_), do: :skip

  @impl true
  def decode(_), do: :skip
end

# Usage with Xqlite.stream/4:
Xqlite.stream(conn, "SELECT amount FROM payments", [],
  type_extensions: [MyApp.DecimalExtension, Xqlite.TypeExtension.DateTime])

Summary

Callbacks

Converts a SQLite storage value back to an Elixir term.

Converts an Elixir term to a SQLite-compatible storage value.

Functions

Decodes result rows through the extension chain.

Decodes a single value through the extension chain.

Encodes a list of query parameters through the extension chain.

Encodes a single value through the extension chain.

Callbacks

decode(value)

@callback decode(value :: Xqlite.sqlite_value()) :: {:ok, term()} | :skip

Converts a SQLite storage value back to an Elixir term.

Return {:ok, elixir_term} on successful conversion. Return :skip if this extension does not handle the given value.

encode(value)

@callback encode(value :: term()) :: {:ok, Xqlite.sqlite_value()} | :skip

Converts an Elixir term to a SQLite-compatible storage value.

Return {:ok, sqlite_value} where sqlite_value is an integer, float, binary, or nil. Return :skip if this extension does not handle the given value.

Functions

decode_rows(rows, extensions)

@spec decode_rows(rows :: [[term()]], extensions :: [module()]) :: [[term()]]

Decodes result rows through the extension chain.

Each cell in each row is passed through the extension chain. Values that no extension handles pass through unchanged.

decode_value(value, list)

@spec decode_value(value :: term(), extensions :: [module()]) :: term()

Decodes a single value through the extension chain.

Returns the decoded value from the first extension that handles it, or the original value if no extension matches.

encode_params(params, extensions)

@spec encode_params(params :: list() | keyword(), extensions :: [module()]) ::
  list() | keyword()

Encodes a list of query parameters through the extension chain.

Handles both positional parameter lists and keyword parameter lists. Values that no extension handles pass through unchanged.

encode_value(value, list)

@spec encode_value(value :: term(), extensions :: [module()]) :: term()

Encodes a single value through the extension chain.

Returns the encoded value from the first extension that handles it, or the original value if no extension matches.