Beancount.Query (beancount_ex v0.6.0)

Copy Markdown View Source

Low-level wrapper around the bean-query command-line tool.

Query is the only place that shells out to bean-query, mirroring how Beancount.Checker wraps bean-check. It runs a BQL query against a ledger with CSV output and parses the result into a neutral Beancount.Query.Result.

The path to bean-query is configurable:

config :beancount_ex, bean_query_path: "bean-query"

Summary

Functions

Whether the configured bean-query executable is available on this machine.

Return the configured path to the bean-query executable.

Parse RFC-4180-style CSV text into {columns, rows}.

Run bql against a .bean file on disk.

Run bql against ledger text, writing it to a temporary file first.

Functions

available?()

@spec available?() :: boolean()

Whether the configured bean-query executable is available on this machine.

Examples

iex> is_boolean(Beancount.Query.available?())
true

bean_query_path()

@spec bean_query_path() :: String.t()

Return the configured path to the bean-query executable.

Examples

iex> is_binary(Beancount.Query.bean_query_path())
true

parse_csv(csv)

@spec parse_csv(binary()) :: {[String.t()], [[String.t()]]}

Parse RFC-4180-style CSV text into {columns, rows}.

The first non-empty line is treated as the header. Empty input yields {[], []}. Quoted fields may contain embedded newlines.

Examples

iex> Beancount.Query.parse_csv("account,balance\nAssets:Bank,100 USD\n")
{["account", "balance"], [["Assets:Bank", "100 USD"]]}

iex> Beancount.Query.parse_csv("")
{[], []}

query_file(path, bql)

@spec query_file(Path.t(), binary()) ::
  {:ok, Beancount.Query.Result.t()} | {:error, Beancount.Result.t()}

Run bql against a .bean file on disk.

Raises Beancount.Query.NotInstalledError if bean-query is not available.

Examples

path = Path.join(System.tmp_dir!(), "query_file_example.bean")
File.write!(path, "2026-01-01 open Assets:Bank USD\n")

if Beancount.Query.available?() do
  {:ok, _} = Beancount.Query.query_file(path, "SELECT account GROUP BY account")
end

query_text(text, bql)

@spec query_text(binary(), binary()) ::
  {:ok, Beancount.Query.Result.t()} | {:error, Beancount.Result.t()}

Run bql against ledger text, writing it to a temporary file first.

Examples

Requires bean-query on PATH:

text = "2026-01-01 open Assets:Bank USD\n"

if Beancount.Query.available?() do
  {:ok, %Beancount.Query.Result{}} =
    Beancount.Query.query_text(text, "SELECT account GROUP BY account")
end