Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pgmem

pgmem is a process-local PostgreSQL emulator for fast Go tests. It ports the database-and-schema testing model popularized by oguimbal/pg-mem to an idiomatic Go API, with no PostgreSQL server. SQL is parsed into PostgreSQL's own AST through pg_query_go, then translated for the embedded execution engine; syntax is never classified with regular expressions.

database := pgmem.MustNew()
defer database.Close()

public := database.Public()
if err := public.None(`
  CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
  )
`); err != nil {
  panic(err)
}

if err := public.None(`INSERT INTO users (name) VALUES ($1)`, "Ada"); err != nil {
  panic(err)
}

user, err := public.One(`SELECT id, name FROM users`)

The same database can back code written against database/sql:

pool := database.Open()
defer pool.Close()

ctx := context.Background()
var name string
err = pool.QueryRowContext(ctx,
  `SELECT name FROM users WHERE id = $1`,
  1,
).Scan(&name)

DB.Open uses the public schema. Use schema.Open when unqualified statements should target a named schema. Close every returned pool before closing the owning DB.

Backups are reusable restore points for the public schema and every named schema:

backup, err := database.Backup()
if err != nil {
  panic(err)
}

// Run a test that changes rows, then reset its data for the next case.
if err := backup.Restore(); err != nil {
  panic(err)
}

Data-only changes can be restored repeatedly. Restore returns ErrSchemaChanged if DDL or the named-schema topology changed after the backup, without modifying the current data. Context cancellation is honored while validating the restore; once its commit point starts, the already validated public and named-schema swap runs to completion without cancellation. Exceptional engine failures during that internal multi-schema swap are not a transactional rollback boundary.

Schema-local interceptors can supply ad-hoc results before parsing or execution:

subscription := public.InterceptQueries(func(
  ctx context.Context,
  statement string,
  arguments []any,
) (pgmem.Result, bool, error) {
  if statement != "current user" {
    return pgmem.Result{}, false, nil // pass through
  }
  return pgmem.Result{
    Rows: []pgmem.Row{{"name": "Ada"}},
  }, true, nil
})
defer subscription.Unsubscribe()

Interceptors run in registration order and the first handled result wins. They currently apply to Schema methods only, not calls made through DB.Open, Schema.Open, or DB.SQLDB.

Scalar functions can be registered after the database is already in use. A function registered on DB belongs to public; register on a Schema for a schema-local function:

err := database.RegisterFunction(pgmem.Function{
  Name:  "greet",
  Arity: 1,
  Implementation: func(arguments ...any) (any, error) {
    return "hello " + arguments[0].(string), nil
  },
})
if err != nil {
  panic(err)
}

row, err := public.One(`SELECT greet('Ada') AS greeting`)

Fixed arities may be overloaded; a variadic definition uses Arity as its minimum. Registrations and replacements are isolated per database and schema. Callback errors and panics become query errors instead of escaping through the embedded engine. Callbacks run synchronously inside the database's sole executor connection: they must be prompt and must not query, back up, restore, or close their owning database.

Compatibility target

The v0.1 contract covers the database/schema API, isolated schemas, typed errors, materialized query results, PostgreSQL AST/type translation, backups, query interception, schema-local scalar functions, raw table fixtures, and the translating database/sql adapter. See COMPATIBILITY.md for the exact tested surface and known gaps.

Like upstream pg-mem, this is a best-effort unit-test emulator rather than a production PostgreSQL replacement. Always validate migrations and integration behavior against the PostgreSQL versions your application supports.

Development

The module requires Go 1.26 and a C compiler because pg_query_go embeds the PostgreSQL parser through cgo. Behavior tests use Ginkgo v2 and Gomega; expectation-based interface mocks use gomock.

go test -race ./...
go generate ./...

License and origin

Licensed under the MIT License. This is an independent Go implementation inspired by pg-mem's documented behavior; see UPSTREAM.md for the compatibility and attribution boundary.

About

Managed by candace-component-export v1: f042c63d27468ad87c0ae2ce81703a964eb60a74b72e38c45ffdfbc570fae700

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages