Skip to content

Connecting to a database

Every LiteORM program starts by opening a database. Each backend lives in its own liteorm.org/dialect/... package and exposes an Open that returns a *liteorm.DB — the session that both the query and orm front-ends accept. This page covers how to open each backend, the DSN shapes, in-memory SQLite, and passing options at open time; for the option catalog see Configuration, and for the per-backend capability matrix see Backends.

Every backend returns the same *liteorm.DB, so the rest of your code is identical no matter which one you opened. SQLite takes a filesystem path and no context; the network backends take a context.Context and a DSN string:

db, err := sqlite.Open("app.db") // path (or ":memory:")
db, err := postgres.Open(ctx, "postgres://…") // DSN
db, err := mysql.Open(ctx, "user:pass@tcp(host:3306)/db") // DSN
db, err := mssql.Open(ctx, "sqlserver://…") // DSN

Always defer db.Close() once you have a handle, and check the error — a bad DSN or an unreachable server surfaces here.

The SQLite backend wraps the pure-Go driver gosqlite.org — no cgo, so you cross-compile with plain go build and ship static binaries. Open applies a production pragma preset (WAL, a busy timeout, foreign keys on) and takes a filesystem path:

import "liteorm.org/dialect/sqlite"
db, err := sqlite.Open("app.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()

For full control over the underlying driver — a custom VFS, your own pragmas, connection pooling — pass a gosqlite.Config to OpenConfig:

db, err := sqlite.OpenConfig(cfg) // cfg is a gosqlite.Config

To open a database that is encrypted at rest, use sqlite.OpenEncrypted(path, key) with a 32-byte key; see Encryption for cipher choice and key handling.

Pass ":memory:" as the path for a private, in-process database that vanishes when the connection closes. It needs no file, applies the same pragmas, and is the fast, isolated default for tests:

db, err := sqlite.Open(":memory:")

See Testing for the one-database-per-test pattern built on this.

The same backend can connect to a remote SQLite server — quicSQL — instead of a local file. Any scheme:// DSN other than file: opens remote; blank-import the driver once to register the quicsql:// scheme:

import _ "quicsql.net/client/sqldriver"
db, err := sqlite.Open("quicsql://host:7777/app?transport=h2&token=…")

Your models and queries are unchanged. See Remote SQLite with quicSQL for mTLS / keyring auth (sqlite.WrapDB) and which features work over the wire.

The Postgres backend runs over the native pgx/v5 API (pgxpool), giving the binary protocol scan path rather than a database/sql wrapper. The DSN is a libpq connection string or URL, as accepted by pgx:

import "liteorm.org/dialect/postgres"
db, err := postgres.Open(ctx, "postgres://user:pass@host:5432/dbname?sslmode=disable")

See Postgres features for LISTEN/NOTIFY, typed JSONB and array predicates, and bulk insert with CopyFrom.

The MySQL backend runs over go-sql-driver/mysql via database/sql, and Open pings the database before returning. The DSN is the go-sql-driver format — include parseTime=true so time.Time columns scan correctly:

import "liteorm.org/dialect/mysql"
db, err := mysql.Open(ctx, "user:pass@tcp(host:3306)/dbname?parseTime=true")

The MSSQL backend targets SQL Server. The DSN is a sqlserver:// URL:

import "liteorm.org/dialect/mssql"
db, err := mssql.Open(ctx, "sqlserver://user:pass@host:1433?database=dbname")

Every Open variant takes a trailing ...liteorm.Option, so cross-cutting concerns are configured the same way on every backend. The common ones attach a logger, an observer, or turn on SQL-argument logging:

db, err := sqlite.Open("app.db",
liteorm.WithLogger(slog.Default()), // slog statement logging
liteorm.WithObserver(metrics), // one seam around every statement
liteorm.WithSQLArgs(true), // include bound args in log events
)

These options apply to the connection and to every transaction opened from it. The full list of open-time and DB options, with their effects, is in Configuration.

  • Configuration — every open-time option and its effect.
  • Backends — DSN shapes and the per-dialect capability matrix.
  • Query or ORM? — pick a front-end for the handle you just opened.
  • Context & session — how *DB and a transaction both act as a Session.