sqlite

package
v0.0.0-...-14f0675 Latest Latest
Warning

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

Go to latest
Published: Jun 9, 2026 License: MIT Imports: 14 Imported by: 0

README

Contract-Driven SQLite Module

This module provides a way to auto-wire SQLite database operations using a contract-driven approach, inspired by weed/driven/rest. It uses github.com/glebarez/sqlite (pure Go, no CGO) and gorm.io/gorm.

Features

  • Interface-Driven: Define your data access layer as an interface or a struct with function fields.
  • Auto-Conversion: Methods following the pattern Method(ctx, *Params) (*Result, error) are automatically converted to GORM operations.
  • Reflection-Based: Uses reflection to map struct fields and tags to SQL queries.
  • Zero CGO: Built on top of the pure Go SQLite driver.
  • Flexible Queries: Use struct tags for where, page, order, preload, and update logic.

Usage

1. Define your Models and Params
type User struct {
    ID   uint   `gorm:"primaryKey"`
    Name string
}

type CreateUserParams struct {
    Data *User
}

type FindUserParams struct {
    ID uint `where:"id"`
}

type ListUsersParams struct {
    Limit int `page:"limit"`
}
2. Define a Repository Struct
type UserRepo struct {
    CreateUser func(ctx context.Context, p *CreateUserParams) (*User, error)
    FindUser   func(ctx context.Context, p *FindUserParams) (*User, error)
    ListUsers  func(ctx context.Context, p *ListUsersParams) (*[]User, error)
}
3. Bind and Use
db := sqlite.MustOpen(sqlite.Config{
    Path: "app.db",
    AutoMigrate: []any{&User{}},
})

repo := &UserRepo{}
sqlite.Bind(db, repo)

// Now use it!
user, err := repo.CreateUser(ctx, &CreateUserParams{Data: &User{Name: "Alice"}})

Struct Tags

  • where:"column_name [op]": Adds a WHERE clause. Operators: =, !=, >, <, >=, <=, like, in, is null.
  • page:"limit|offset|page": Handles pagination.
  • order:"clause": Static or dynamic ordering.
  • preload:"associations|*": Preloads GORM associations.
  • update:"column_name": Specifies fields for UPDATE operations.
  • db:"table:name": Overrides the table name on a field.

Operation Inference

Operations are inferred from method/field name prefixes:

  • Create*, Insert*, Add*, New* -> Create
  • Get*, Find*, Fetch*, Load* -> Find (single)
  • List*, Search*, All*, Query* -> List (multiple)
  • Update*, Save*, Modify*, Patch* -> Update
  • Delete*, Remove*, Drop* -> Delete
  • Count* -> Count
  • Exec*, Raw* -> Raw SQL

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = NewError(404, "record not found")

ErrNotFound is a sentinel error for record-not-found.

Functions

func Bind

func Bind(db *gorm.DB, service any) error

Bind creates a repository by scanning the service struct and auto-wiring all exported function fields that match the contract pattern. The function fields should be named like: CreateUser, FindUser, ListUsers, etc. Their type must be: func(context.Context, *Params) (*Result, error)

func Handler

func Handler[Req any, Resp any](db *gorm.DB, op Op) func(context.Context, *Req) (*Resp, error)

Handler is a generic wrapper that converts a strongly-typed contract method into a GORM-backed database operation. It inspects the Req struct tags to determine the operation and builds the query.

func Mount

func Mount(db *gorm.DB, service any) error

Mount scans a service struct and auto-wires all contract methods to GORM operations. Each method must follow the pattern: Method(ctx, *Params) (*Result, error) The Params struct must embed or contain an `Op` field tagged with `db:"op"`.

Alternatively, if no Op field exists in Params, the method name prefix is used:

  • Create*, Insert* -> OpCreate
  • Get*, Find* -> OpFind
  • List*, Search* -> OpList
  • Update*, Save* -> OpUpdate
  • Delete*, Remove* -> OpDelete
  • Count* -> OpCount
  • Exec*, Raw* -> OpExec

Types

type Config

type Config struct {
	// Path is the file path for the SQLite database.
	// Use ":memory:" for in-memory databases, or "" for a temp file.
	Path string

	// AutoMigrate is a list of model structs to auto-migrate on connection.
	AutoMigrate []any

	// Logger sets the GORM logger level.
	// 0 = Silent, 1 = Error, 2 = Warn, 3 = Info
	LogLevel int

	// WAL enables Write-Ahead Logging for better concurrent read performance.
	WAL bool

	// JournalMode overrides the default journal mode.
	JournalMode string

	// BusyTimeout sets the busy timeout in milliseconds (default: 5000).
	BusyTimeout int

	// TTL configures MongoDB-style TTL indexes for automatic document expiration.
	// When set, the TTL plugin is registered and a background worker is started.
	// The plugin instance is returned via the second return value of Open/MustOpen.
	TTL *TTLConfig
}

Config holds the SQLite connection configuration.

type ContractError

type ContractError interface {
	error
	Code() int
}

ContractError allows handlers to return specific error codes and messages.

func NewError

func NewError(code int, message string) ContractError

NewError creates a new ContractError with the specified code and message.

type Op

type Op string

Op defines the database operation type.

const (
	OpCreate Op = "create"
	OpFind   Op = "find"   // single record by conditions
	OpList   Op = "list"   // multiple records
	OpUpdate Op = "update" // update by conditions
	OpDelete Op = "delete" // delete by conditions
	OpExec   Op = "exec"   // raw execution
	OpCount  Op = "count"  // count records
)

type TTLConfig

type TTLConfig struct {
	// Indexes is the list of TTL indexes to register.
	Indexes []TTLIndex

	// CleanupInterval is how often the background worker checks for
	// expired documents. Defaults to 60 seconds if not set.
	CleanupInterval time.Duration

	// BatchSize controls how many documents are deleted per cleanup
	// batch per index. Defaults to 100 if not set.
	BatchSize int
}

TTLConfig holds configuration for MongoDB-style TTL indexes.

type TTLIndex

type TTLIndex struct {
	// Model is the GORM model struct (used to determine the table name).
	Model any

	// Field is the name of the time.Time field to index on.
	// This field must be of type time.Time or *time.Time.
	Field string

	// ExpireAfterSeconds is the number of seconds after the field value
	// at which the document expires and becomes eligible for deletion.
	ExpireAfterSeconds int64
}

TTLIndex defines a TTL index on a model field, similar to MongoDB's db.collection.createIndex({ field: 1 }, { expireAfterSeconds: N }).

The background worker periodically deletes records where:

field_value + ExpireAfterSeconds <= now

Example:

sqlite.TTLIndex{
    Model:              &Session{},
    Field:              "CreatedAt",
    ExpireAfterSeconds: 3600, // delete 1 hour after CreatedAt
}

type TTLPlugin

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

TTLPlugin is a GORM plugin that provides MongoDB-style TTL index support. It runs a background worker that periodically deletes expired documents based on registered TTL indexes.

Usage:

db, ttl := sqlite.MustOpen(sqlite.Config{
    Path: "app.db",
    AutoMigrate: []any{&Session{}},
    TTL: &sqlite.TTLConfig{
        Indexes: []sqlite.TTLIndex{
            {Model: &Session{}, Field: "CreatedAt", ExpireAfterSeconds: 3600},
        },
        CleanupInterval: 60 * time.Second,
    },
})
defer ttl.Stop()

func MustOpen

func MustOpen(cfg Config) (*gorm.DB, *TTLPlugin)

MustOpen is like Open but panics on error. If cfg.TTL is set, the TTL plugin is returned as the second value.

func Open

func Open(cfg Config) (*gorm.DB, *TTLPlugin, error)

Open creates a new GORM DB connection to an SQLite database using pure Go driver. If cfg.TTL is set, the TTL plugin is registered and returned as the second value.

func (*TTLPlugin) Initialize

func (p *TTLPlugin) Initialize(db *gorm.DB) error

Initialize registers TTL indexes and starts the background cleanup worker.

func (*TTLPlugin) Name

func (p *TTLPlugin) Name() string

Name returns the plugin name for GORM registration.

func (*TTLPlugin) PurgeNow

func (p *TTLPlugin) PurgeNow() int64

PurgeNow immediately deletes all expired documents across all registered TTL indexes. Returns the total number of deleted documents.

func (*TTLPlugin) Stop

func (p *TTLPlugin) Stop()

Stop gracefully shuts down the background cleanup goroutine.

Jump to

Keyboard shortcuts

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