sqlite

package module
v0.2.1 Latest Latest
Warning

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

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

README

sqlite

Doc Go Test License

SQLite driver module for rio, the zero-surprise Go ORM. Built on the pure-Go modernc.org/sqlite driver — no cgo.

Driver modules are deliberately thin: constructors, precise error translation and DSN hygiene. All SQL grammar lives in rio itself.

Install

go get github.com/go-rio/sqlite

Usage

import (
	"github.com/go-rio/rio"
	"github.com/go-rio/sqlite"
)

db, err := sqlite.Open("app.db")
if err != nil {
	// ...
}
defer db.Close()

users, err := rio.From[User]().Where("age > ?", 18).All(ctx, db)

Bring your own *sql.DB (and pool configuration) with New:

sqlDB, err := sql.Open("sqlite", dsn) // modernc.org/sqlite
db := sqlite.New(sqlDB)

Default DSN parameters

Open appends two pragmas and one driver parameter to the DSN unless the DSN already sets the same key itself:

Parameter Default Why
_pragma=foreign_keys 1 SQLite ships with foreign key enforcement off — constraints parse but never fire. Without this pragma, rio.ErrForeignKeyViolated could never happen on SQLite.
_pragma=busy_timeout 5000 Concurrent writers wait up to five seconds for the database lock instead of failing immediately with SQLITE_BUSY.
_time_format sqlite Anything writing time.Time outside rio (raw database/sql through db.Unwrap()) stores SQLite-parseable text instead of Go's time.String() form, keeping the column format uniform. rio's own writes always use its canonical text encoding, with or without this parameter.

Set any key yourself to override a default:

db, err := sqlite.Open("app.db?_pragma=busy_timeout(10000)")

New never touches the DSN — configure pragmas and driver parameters on the pool you pass in.

In-memory databases

A plain :memory: DSN gives each pooled connection its own private empty database — SQLite's own behavior, and a classic footgun, because database/sql opens several connections by default: a table created on one is missing on the next. For an in-memory database that acts like a single shared store, use a shared cache and pin the pool to one connection:

db, _ := sqlite.Open("file:app?mode=memory&cache=shared")
db.Unwrap().SetMaxOpenConns(1) // rio never tunes the pool for you

A file-backed DSN has no such caveat.

Error translation

Unique and primary key violations come back as rio.ErrDuplicateKey, foreign key violations as rio.ErrForeignKeyViolated. The driver's own *sqlite.Error stays in the chain, so errors.As keeps working:

if err := rio.Insert(ctx, db, &user); errors.Is(err, rio.ErrDuplicateKey) {
	// email already taken
}

License

MIT

Documentation

Overview

Package sqlite connects rio, the zero-surprise Go ORM, to SQLite through the pure-Go modernc.org/sqlite driver — no cgo required.

Driver modules are deliberately thin. This package contains exactly three things, and nothing else:

  • Constructors: Open (from a DSN) and New (bring your own *sql.DB), both returning a *rio.DB speaking the built-in rio.SQLite dialect.
  • Precise error translation: SQLite constraint failures become rio.ErrDuplicateKey and rio.ErrForeignKeyViolated, with the driver error kept in the chain for errors.As.
  • DSN hygiene: Open enables foreign key enforcement, a busy timeout, and the driver's SQLite-text time format (_time_format=sqlite, for non-rio writers sharing the handle) unless the DSN sets those keys itself.

All SQL grammar lives in github.com/go-rio/rio; this package never implements a dialect.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New(db *sql.DB, opts ...rio.Option) *rio.DB

New wraps an existing *sql.DB — bring your own connection pool — in a *rio.DB speaking the rio.SQLite dialect with this package's error translator installed. A rio.WithErrorTranslator among opts wins over the built-in translator.

New performs no DSN hygiene, because the pool already exists. In particular, foreign key enforcement is whatever the caller's DSN says — and SQLite's historical default is off, in which case rio.ErrForeignKeyViolated can never happen (see Open).

func Open

func Open(dsn string, opts ...rio.Option) (*rio.DB, error)

Open opens a SQLite database and returns a *rio.DB speaking the rio.SQLite dialect with this package's error translator installed.

Before handing the DSN to modernc.org/sqlite, Open appends the default pragmas described on defaultPragmas — foreign_keys(1) and busy_timeout(5000) — plus the _time_format=sqlite driver parameter (see defaultParams). A key the DSN already sets is respected, never overridden. An empty DSN — SQLite's private, per-connection temporary on-disk database — is respelled as the equivalent "file:" URI first, so the defaults apply to it too.

Like database/sql itself, Open validates nothing eagerly: a bad path or DSN surfaces on first use (or on an explicit Ping).

In-memory databases: a plain ":memory:" (or "file::memory:" without a shared cache) gives every pooled connection its own private, empty database, so a table created on one connection is invisible to the next — the default database/sql pool opens several. For an in-memory database that behaves like one shared store, use a shared-cache DSN and pin the pool to a single connection:

db, _ := sqlite.Open("file:app?mode=memory&cache=shared")
db.Unwrap().SetMaxOpenConns(1) // rio never tunes the pool for you

Types

This section is empty.

Jump to

Keyboard shortcuts

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