#finance-ledger #ledger #accounting #beancount #double-entry

rustledger-query

Beancount query engine (BQL) with SQL-like syntax for ledger queries

24 releases (9 breaking)

Uses new Rust 2024

new 0.11.0 Apr 3, 2026
0.10.1 Mar 13, 2026
0.9.1 Feb 18, 2026

#309 in Finance

Download history 65/week @ 2026-01-15 105/week @ 2026-01-22 53/week @ 2026-01-29 18/week @ 2026-02-05 87/week @ 2026-02-12 50/week @ 2026-02-19 61/week @ 2026-02-26 43/week @ 2026-03-05 11/week @ 2026-03-12 24/week @ 2026-03-19 53/week @ 2026-03-26

136 downloads per month
Used in 3 crates

GPL-3.0-only

1MB
23K SLoC

Beancount Query Language (BQL) engine.

This crate provides a SQL-like query language for analyzing Beancount ledger data.

Overview

BQL is a specialized query language designed for financial data analysis. It operates on transaction postings while respecting double-entry bookkeeping constraints.

Query Types

  • SELECT - General purpose queries with filtering, grouping, and ordering
  • JOURNAL - Shorthand for account statements
  • BALANCES - Shorthand for account balance tables
  • PRINT - Output filtered transactions in Beancount syntax

Example

use rustledger_query::parse;

let query = parse("SELECT account, SUM(position) WHERE account ~ \"Expenses:\" GROUP BY account").unwrap();
println!("{:?}", query);

rustledger-query

Beancount Query Language (BQL) engine with SQL-like syntax.

Supported Syntax

SELECT account, SUM(position)
WHERE account ~ 'Expenses:'
GROUP BY account
ORDER BY SUM(position) DESC
LIMIT 10

Features

  • Full BQL support (SELECT, FROM, WHERE, GROUP BY, ORDER BY, LIMIT, PIVOT BY)
  • FROM clause for system tables (#entries, #postings, etc.)
  • Regex pattern matching (~ operator)
  • Aggregate functions (SUM, COUNT, FIRST, LAST, MIN, MAX)
  • Date functions (YEAR, MONTH, DAY, QUARTER)
  • String functions (LENGTH, UPPER, LOWER)
  • Account functions (ROOT, LEAF, PARENT)

Example

use rustledger_query::{parse, Executor};

let query = parse("SELECT account, SUM(position) GROUP BY account")?;
let mut executor = Executor::new(&directives);
let results = executor.execute(&query)?;

for row in &results.rows {
    println!("{:?}", row);
}

License

GPL-3.0

Dependencies

~11–23MB
~315K SLoC