lofidb

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 10, 2026 License: MIT Imports: 8 Imported by: 0

README

lofidb

A small, embeddable database browser for Go. Drop a *sql.DB into it and you get a Bulma-styled web UI that lists tables, shows their schema (columns, primary keys, foreign keys, indexes), and lets you page and sort through rows.

Works against:

  • PostgreSQL natively, via github.com/jackc/pgx/v5
  • pglike (codeberg.org/hum3/go-postgres) — a SQLite-backed driver that speaks PG SQL, so the same UI runs on a single in-memory *sql.DB with no external service
  • WASM: pglike runs under GOOS=wasip1 GOARCH=wasm, so lofidb can serve a fully in-browser DB browser via lofigui

A single set of PG-style information_schema queries powers everything — pglike installs PG-compatible catalog views per connection so the same SQL runs on either backend.

Install

go install codeberg.org/hum3/lofidb/cmd/lofidb@latest

Or import the library:

go get codeberg.org/hum3/lofidb

Quick start (CLI)

lofidb                                  # in-memory pglike scratchpad
lofidb file:/tmp/data.db                # browse a pglike on-disk file
lofidb postgres://localhost/myapp       # browse PostgreSQL
lofidb --addr :9000 file:/tmp/data.db   # custom port

Open the printed URL — by default http://localhost:8080/explorer.

Quick start (library)

package main

import (
    "database/sql"
    "log"
    "net/http"

    "codeberg.org/hum3/lofidb"
    _ "codeberg.org/hum3/go-postgres" // or _ "github.com/jackc/pgx/v5/stdlib"
)

func main() {
    db, _ := sql.Open("pglike", ":memory:")
    defer db.Close()

    // ... create tables, load data ...

    http.Handle("/explorer", lofidb.HTTPHandler(db, lofidb.Options{}))
    http.Handle("/explorer/", lofidb.HTTPHandler(db, lofidb.Options{}))
    log.Fatal(http.ListenAndServe(":8080", nil))
}

HTTPHandler mounts the index at the prefix and table-detail pages at <prefix>/<table>.

WASM mode

In WASM (e.g. via lofigui), call the HTML builders directly and pipe the strings into your renderer:

import "codeberg.org/hum3/lofigui"

lofigui.Reset()
lofigui.HTML(lofidb.IndexHTML(db, lofidb.Options{}))
// or, for a specific table:
lofigui.HTML(lofidb.TableHTML(db, "users", page, sort, dir, lofidb.Options{}))

The builders are pure functions: they take a *sql.DB and return an HTML fragment. The sample example under examples/ runs an entire pglike DB plus this UI in the browser.

Options

type Options struct {
    Schema     string   // default "public"
    URLPrefix  string   // default "/explorer"
    PageSize   int      // default 50
    HideTables []string // tables to hide in addition to internal ones
}

Schema is "public" for both PostgreSQL (default) and pglike (which reports 'public' from its catalog views and current_schema()). For multi-schema PostgreSQL setups, set this to the schema you want to browse.

How it works

The HTML pages render from a small set of catalog queries:

Information Query target
Table list information_schema.tables
Column info information_schema.columns
Primary keys information_schema.table_constraintsinformation_schema.key_column_usage
Foreign keys information_schema.referential_constraintskey_column_usageconstraint_column_usage
Indexes pg_indexes (+ pglike-specific pg_index_columns for column lists)

These views exist natively in PostgreSQL. pglike installs TEMP VIEW shims with the same names and shapes per connection, so the queries are unchanged across backends.

For index columns, lofidb prefers a pg_index_columns helper view that pglike exposes. Real PostgreSQL doesn't expose this view by default — the index list still shows up, but column lists may be empty until you create an equivalent helper view. (See examples/02_postgres_index_columns_view.sql.)

Data-size testing

wasm_soak_test.go measures how much data fits in a pglike :memory: database under WASM. It runs natively or under wasip1+wazero and emits JSON-line metrics. Run:

# native (sanity check)
WASM_SOAK_ROWS=100000 task test
# wasm (real measurement)
task test:wasm:soak WASM_SOAK_ROWS=200000
# capture metrics
task test:wasm:soak WASM_SOAK_ROWS=500000 WASM_SOAK_OUTPUT=wasm-soak.jsonl

Each line is one of:

{"stage":"start", "target_rows":N,"batch_size":B,"heap_alloc_mb":...}
{"stage":"progress","inserted_rows":N,"wall_secs":...,"heap_alloc_mb":...,"batch_latency_secs":...}
{"stage":"done",  "inserted_rows":N,"wall_secs":...,"heap_alloc_mb":...}

A single representative row is ~120 bytes (id + 80-byte payload + timestamp + 10-byte key); WASM heap is dominated by SQLite's page cache and Go's GC. Initial measurements on wazero put the practical ceiling between 200k and 1M rows per :memory: DB before the WASM module hits its memory limit; results vary by browser engine and module config. The harness records the last successful batch on OOM so you can chart the curve rather than just "it crashed".

Development

task check        # fmt + vet + test
task build        # build cmd/lofidb
task test:wasm    # run tests under wasip1/wasm
Documentation https://h3-lofidb.statichost.page/
Source (Codeberg) https://codeberg.org/hum3/lofidb
Mirror (GitHub) https://github.com/drummonds/lofidb

License

MIT

Documentation

Overview

Package lofidb is a small database browser that renders Bulma-styled HTML for a *sql.DB. It works against PostgreSQL natively and against pglike (codeberg.org/hum3/go-postgres) — the same SQL runs unchanged on both because pglike installs PG-compatible catalog views.

Two modes of consumption:

  • Server mode: http.Handler from HTTPHandler() mounted under URLPrefix.
  • WASM mode: call IndexHTML / TableHTML and pipe the strings into your existing rendering pipeline (e.g. lofigui.HTML()).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func HTTPHandler

func HTTPHandler(db *sql.DB, opts Options) http.Handler

HTTPHandler returns an http.Handler that serves the explorer UI. It mounts at opts.URLPrefix; the index is served at the prefix itself and individual tables at "<prefix>/<table>". The handler does not impose authentication — wrap it with whatever middleware your application already uses.

func IndexHTML

func IndexHTML(db *sql.DB, opts Options) string

IndexHTML renders the explorer landing page: the list of tables with row/column counts and a relationship summary. The result is HTML fragment (no <html>/<body> wrapper) suitable for embedding inside a host page.

func TableHTML

func TableHTML(db *sql.DB, name string, page int, sort, dir string, opts Options) string

TableHTML renders the detail view for a single table: schema, foreign keys, indexes, and a paginated, sortable data browser. `sort` and `dir` are validated against the actual column list — invalid values are silently ignored, so this is safe to wire to URL query parameters.

Types

type Column

type Column struct {
	Name     string
	DataType string
	Nullable string  // "YES" or "NO"
	Default  *string // nil if no default
	Position int     // 1-based ordinal_position
}

Column describes a single column from information_schema.columns.

type ForeignKey

type ForeignKey struct {
	From, FromCol      string
	To, ToCol          string // RefTable / RefCol below; To/ToCol kept for clarity
	RefTable, RefCol   string
	OnUpdate, OnDelete string
}

ForeignKey describes one column's FK relationship.

type Index

type Index struct {
	Name    string
	Columns []string
	Unique  bool
}

Index describes one index on a table.

type Options

type Options struct {
	// Schema is the database schema to browse. Defaults to "public", which is
	// what pglike's catalog views report and the default schema for most PG
	// installations.
	Schema string

	// URLPrefix is the path under which the explorer is mounted. Links emitted
	// by the HTML builders use this prefix. Defaults to "/explorer".
	// Must not end with a trailing slash.
	URLPrefix string

	// PageSize is the number of rows per page in table-detail views. Default 50.
	PageSize int

	// HideTables lists tables that should not be shown. Internal tables
	// (sqlite_*, pglike helpers) are always hidden in addition to this list.
	HideTables []string
}

Options controls the explorer's behaviour. The zero value is valid; missing fields are filled in from defaults.

Directories

Path Synopsis
cmd
lofidb command
lofidb serves a small DB browser for any *sql.DB-compatible PostgreSQL or pglike database.
lofidb serves a small DB browser for any *sql.DB-compatible PostgreSQL or pglike database.