# `Beancount.Query`
[🔗](https://github.com/thanos/beancount_ex/blob/v0.6.0/lib/beancount/query.ex#L1)

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"

# `available?`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
