Help us shape the future of Go! Take the 2026 Go Developer Survey

postgres

package module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 16, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

README

ledgo/postgres

PostgreSQL store for ledgo, on database/sql with the pgx driver. It is the reference implementation, and passes the ledgotest conformance suite.

Also works with PostgreSQL-compatible services such as Aurora, AlloyDB, Neon and Supabase.

Installation

go get github.com/izzyblues/ledgo/postgres@v0.0.2

Usage

db, err := sql.Open("pgx", "postgres://user:pass@localhost:5432/app")

store := postgres.New(db)
err = store.Migrate(ctx) // or copy schema.sql into your own migrations

ledger := ledgo.New(store) // each Commit runs in its own transaction

To commit postings atomically with your own changes, bind the store to your transaction:

sqlTx, err := db.BeginTx(ctx, nil)
defer sqlTx.Rollback()

// ... your business changes on sqlTx ...
err = ledgo.New(postgres.InTx(sqlTx)).Commit(ctx, tx)

err = sqlTx.Commit() // postings and business changes commit together

If Commit fails, roll back sqlTx.

Schema

schema.sql creates three tables: ledgo_accounts, ledgo_transactions and ledgo_entries. Amounts are NUMERIC, so any precision a currency allows fits.

Concurrency

Commits lock only accounts with a balance limit, always in ID order, so concurrent commits cannot deadlock on the default READ COMMITTED isolation and need no retry loop. Accounts without a limit (clearing, FX, revenue) are insert-only and never locked.

Development

docker compose up -d  # from the repository root
go test ./...

Documentation

Overview

Package postgres is a PostgreSQL ledgo.Store.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store keeps accounts and transactions in PostgreSQL.

Commits lock only the accounts that have a balance limit, always in ID order, so concurrent commits cannot deadlock on READ COMMITTED and need no retry loop.

func InTx

func InTx(tx *sql.Tx) *Store

InTx returns a Store that writes into tx, so postings commit or roll back together with the caller's own changes. The caller commits tx, and must roll it back if a Commit fails.

func New

func New(db *sql.DB) *Store

New returns a Store on db, opened with sql.Open("pgx", dsn). Each Commit runs in its own database transaction.

func (*Store) Balance

func (s *Store) Balance(ctx context.Context, account string) (decimal.Decimal, error)

Balance is the account's debits minus credits: cached for accounts with a limit, summed from entries otherwise.

func (*Store) Commit

func (s *Store) Commit(ctx context.Context, tx ledgo.Transaction) error

Commit stores tx. See ledgo.Store.Commit.

func (*Store) CreateAccount

func (s *Store) CreateAccount(ctx context.Context, account ledgo.Account) error

CreateAccount registers account. Creating the same account again is a no-op; with different settings it returns ledgo.ErrAccountConflict.

func (*Store) Migrate

func (s *Store) Migrate(ctx context.Context) error

Migrate creates the ledgo tables if they don't exist.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL