database

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2025 License: Apache-2.0 Imports: 17 Imported by: 0

README

Database Package

A flexible, SQL-first database package for Go applications with optional GORM support and zero CGO dependencies.

Features

  • Pure Go Implementation - No CGO required, all drivers are pure Go
  • SQL-First Design - Direct access to *sql.DB for maximum control
  • Optional GORM Support - Enable ORM functionality when needed
  • Multi-Database Support - PostgreSQL, MySQL, SQLite, and Turso/LibSQL
  • Environment Configuration - Easy setup via environment variables
  • Fluent Interface - Chain configuration methods for clean API
  • Connection Pooling - Built-in connection pool management
  • Custom Prefixes - Configurable environment variable prefixes
  • Unified Database Wrapper - Access both SQL and GORM through single interface

Installation

go get github.com/gobeaver/beaver-kit/database

All database drivers are pure Go implementations, ensuring easy cross-compilation and deployment without CGO dependencies.

Quick Start

Fluent Interface API

The package provides a clean fluent interface for configuration and initialization:

package main

import (
    "log"
    "github.com/gobeaver/beaver-kit/database"
)

func main() {
    // Global initialization with fluent interface
    if err := database.WithGORM().Init(); err != nil {
        log.Fatal(err)
    }
    
    // Custom prefix + GORM
    if err := database.WithPrefix("APP_").WithGORM().Init(); err != nil {
        log.Fatal(err)
    }
    
    // Create instance connections
    db, err := database.WithGORM().Connect()
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    
    // Access SQL database
    sqlDB := db.SQL()
    rows, err := sqlDB.Query("SELECT * FROM users")
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close()
    
    // Access GORM (if enabled)
    gormDB, err := db.GORM()
    if err != nil {
        log.Fatal(err)
    }
    
    var users []User
    gormDB.Find(&users)
}
Traditional Global API
// Traditional initialization (still supported)
if err := database.Init(); err != nil {
    log.Fatal(err)
}

// Get global instances
db := database.DB()
gormDB, err := database.GORM()

// Enable GORM explicitly
if err := database.InitWithGORM(); err != nil {
    log.Fatal(err)
}

Configuration

Environment Variables
# Database driver: postgres, mysql, sqlite, turso, libsql
BEAVER_DB_DRIVER=postgres

# Connection details (for traditional databases)
BEAVER_DB_HOST=localhost
BEAVER_DB_PORT=5432
BEAVER_DB_DATABASE=myapp
BEAVER_DB_USERNAME=user
BEAVER_DB_PASSWORD=secret

# Or use a connection URL (overrides individual settings)
BEAVER_DB_URL=postgres://user:pass@localhost:5432/myapp

# For Turso/LibSQL
BEAVER_DB_URL=libsql://your-database.turso.io
BEAVER_DB_AUTH_TOKEN=your-auth-token

# Connection pool settings
BEAVER_DB_MAX_OPEN_CONNS=25
BEAVER_DB_MAX_IDLE_CONNS=5
BEAVER_DB_CONN_MAX_LIFETIME=300  # seconds
BEAVER_DB_CONN_MAX_IDLE_TIME=60  # seconds

# SSL/TLS
BEAVER_DB_SSL_MODE=require      # For PostgreSQL
BEAVER_DB_TLS_CONFIG=true       # For MySQL

# Debug mode
BEAVER_DB_DEBUG=false

# ORM Support (optional)
BEAVER_DB_ORM=gorm              # Enable GORM
BEAVER_DB_DISABLE_ORM_LOG=true  # Disable GORM logging

# Migrations (optional, for GORM)
BEAVER_DB_AUTO_MIGRATE=false
BEAVER_DB_MIGRATIONS_PATH=migrations
Programmatic Configuration
cfg := database.Config{
    Driver:   "postgres",
    Host:     "localhost",
    Port:     "5432",
    Database: "myapp",
    Username: "user",
    Password: "secret",
    MaxOpenConns: 25,
    MaxIdleConns: 5,
}

db, err := database.New(cfg)

Database Drivers

All drivers are pure Go implementations:

  • PostgreSQL - Uses jackc/pgx/v5 (high-performance, pure Go)
  • MySQL - Uses go-sql-driver/mysql (pure Go)
  • SQLite - Uses modernc.org/sqlite (pure Go, no CGO)
  • Turso/LibSQL - Uses tursodatabase/libsql-client-go (pure Go)

API Reference

Fluent Interface

The new fluent interface provides a clean, chainable API:

// Top-level functions for fluent initialization
database.New()                    // Create with defaults
database.WithPrefix("APP_")       // Create with custom prefix  
database.WithGORM()              // Create with GORM enabled

// Fluent methods (chainable)
db := database.New().WithGORM().WithPrefix("CUSTOM_")

// Initialization methods
err := db.Init()                 // Global initialization
instance, err := db.Connect()    // Create new instance

// Database wrapper methods
sqlDB := db.SQL()                // Get *sql.DB
gormDB, err := db.GORM()         // Get *gorm.DB (with error)
gormDB := db.MustGORM()          // Get *gorm.DB (panic on error)
err := db.Close()                // Close connection
err := db.Ping()                 // Health check
stats := db.Stats()              // Connection stats
Traditional API (Still Supported)
// Global initialization
err := database.Init()                    // Basic init
err := database.InitWithGORM()           // With GORM
database.MustInitWithGORM()              // Panic on error

// Global instances  
db := database.DB()                      // Global SQL DB
gormDB, err := database.GORM()          // Global GORM
gormDB := database.MustGORM()           // Global GORM (panic)

// New instances
sqlDB, err := database.NewSQL(config)    // New SQL connection
gormDB, err := database.NewWithGORM()   // New GORM instance
gormDB, err := database.NewGORM(cfg, db) // GORM from existing SQL
Custom Environment Variable Prefixes

The package supports configurable environment variable prefixes for multi-tenant applications:

// Default prefix (BEAVER_)
database.New().Init()

// Custom prefix (APP_DB_DRIVER, APP_DB_HOST, etc.)
database.WithPrefix("APP_").Init()

// Multiple configurations
prodDB := database.WithPrefix("PROD_").WithGORM()
testDB := database.WithPrefix("TEST_").WithGORM()
Error Handling

The package provides specific error types:

var (
    ErrNotInitialized = errors.New("database not initialized")
    ErrInvalidDriver  = errors.New("invalid database driver")
    ErrInvalidConfig  = errors.New("invalid database configuration")
    ErrGORMNotEnabled = errors.New("GORM not enabled")
)

// Example usage
gormDB, err := db.GORM()
if err == database.ErrGORMNotEnabled {
    // Handle GORM not being enabled
}

Examples

PostgreSQL with SSL
BEAVER_DB_DRIVER=postgres
BEAVER_DB_HOST=prod-db.example.com
BEAVER_DB_PORT=5432
BEAVER_DB_DATABASE=myapp
BEAVER_DB_USERNAME=appuser
BEAVER_DB_PASSWORD=secret
BEAVER_DB_SSL_MODE=require
MySQL with Custom Parameters
BEAVER_DB_DRIVER=mysql
BEAVER_DB_HOST=localhost
BEAVER_DB_DATABASE=myapp
BEAVER_DB_USERNAME=root
BEAVER_DB_PASSWORD=secret
BEAVER_DB_PARAMS="timeout=10s&readTimeout=30s"
SQLite File Database
BEAVER_DB_DRIVER=sqlite
BEAVER_DB_DATABASE=/path/to/database.db
Turso Cloud Database
BEAVER_DB_DRIVER=turso
BEAVER_DB_URL=libsql://my-db.turso.io
BEAVER_DB_AUTH_TOKEN=your-auth-token
Fluent Interface Examples
// Global initialization patterns
database.WithGORM().Init()                      // Global with GORM
database.WithPrefix("APP_").WithGORM().Init()   // Custom prefix + GORM
database.New().WithGORM().Init()                // Explicit new + GORM

// Instance creation patterns
db, err := database.WithGORM().Connect()        // Instance with GORM
db, err := database.WithPrefix("APP_").Connect() // Custom prefix instance

// Multi-environment setup
prodDB, err := database.WithPrefix("PROD_").WithGORM().Connect()
testDB, err := database.WithPrefix("TEST_").WithGORM().Connect()

// Traditional + fluent mixing
database.Init() // Initialize global
db := database.New().WithGORM() // Create fluent instance
instance, err := db.Connect()
Using the Database Wrapper
// Create connection with fluent interface
db, err := database.WithGORM().Connect()
if err != nil {
    log.Fatal(err)
}
defer db.Close()

// Access SQL database for custom queries
sqlDB := db.SQL()
rows, err := sqlDB.Query("SELECT * FROM users WHERE active = ?", true)
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

// Access GORM for ORM operations
gormDB, err := db.GORM()
if err != nil {
    log.Fatal(err)
}

type User struct {
    ID   uint
    Name string
}

var users []User
gormDB.Find(&users)

// Health check
if err := db.Ping(); err != nil {
    log.Printf("Database unhealthy: %v", err)
}

// Get connection statistics
stats := db.Stats()
log.Printf("Open connections: %d", stats.OpenConnections)

Testing

For testing, create isolated database instances:

func TestMyFunction(t *testing.T) {
    // Create test database instance (doesn't affect global state)
    db, err := database.New().Connect()
    if err != nil {
        // Fallback to in-memory SQLite for tests
        cfg := database.Config{
            Driver:   "sqlite",
            Database: ":memory:",
        }
        sqlDB, err := database.NewSQL(cfg)
        if err != nil {
            t.Fatal(err)
        }
        db = &database.Database{} // Create wrapper if needed
    }
    defer db.Close()
    
    // Run tests with isolated instance...
}

Migration Support

While this package focuses on database connectivity, migrations should be handled by dedicated tools:

Best Practices

  1. Use Fluent Interface - Prefer database.WithGORM().Init() for clean configuration
  2. Environment Variable Prefixes - Use custom prefixes for multi-tenant applications
  3. Instance vs Global - Use .Connect() for isolated instances, .Init() for global state
  4. Close Resources - Always close Database instances and SQL rows/statements
  5. Error Handling - Check for specific errors like ErrGORMNotEnabled
  6. Health Monitoring - Use db.Ping() for health checks
  7. Testing Isolation - Create separate instances for tests, avoid global state

Migration Patterns

Using with GORM AutoMigrate
// Initialize with GORM
db, err := database.WithGORM().Connect()
if err != nil {
    log.Fatal(err)
}

// Get GORM instance for migrations
gormDB, err := db.GORM()
if err != nil {
    log.Fatal(err)
}

// Auto-migrate your models
type User struct {
    ID   uint
    Name string
    Email string `gorm:"uniqueIndex"`
}

if err := gormDB.AutoMigrate(&User{}); err != nil {
    log.Fatal(err)
}
Integration with Migration Tools
// Get raw SQL connection for migration tools
db, err := database.New().Connect()
if err != nil {
    log.Fatal(err)
}

sqlDB := db.SQL()

// Use with golang-migrate
import "github.com/golang-migrate/migrate/v4"
import "github.com/golang-migrate/migrate/v4/database/postgres"

driver, err := postgres.WithInstance(sqlDB, &postgres.Config{})
m, err := migrate.NewWithDatabaseInstance(
    "file://migrations",
    "postgres", driver)

if err := m.Up(); err != nil {
    log.Fatal(err)
}

License

See the main Beaver Kit license.

Documentation

Overview

database/config.go

Package database database/service.go - SQL-first implementation This package uses pure Go database drivers to ensure CGO-free builds, enabling easy cross-compilation and deployment across different platforms.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNotInitialized = errors.New("database not initialized")
	ErrInvalidDriver  = errors.New("invalid database driver")
	ErrInvalidConfig  = errors.New("invalid database configuration")
	ErrGORMNotEnabled = errors.New("GORM not enabled - set BEAVER_DB_ORM=gorm or use InitWithGORM()")
)

Common errors

Functions

func DB

func DB() *sql.DB

DB returns the global SQL database instance

func GORM added in v0.1.0

func GORM() (*gorm.DB, error)

GORM returns the global GORM instance (returns error if not enabled)

func Init

func Init(configs ...Config) error

Init initializes the global SQL database instance with optional config

func InitWithGORM added in v0.1.0

func InitWithGORM(configs ...Config) error

InitWithGORM initializes the global database instance with GORM support enabled

func MustGORM added in v0.1.0

func MustGORM() *gorm.DB

MustGORM returns the global GORM instance or panics

func MustInitWithGORM added in v0.1.0

func MustInitWithGORM(configs ...Config)

MustInitWithGORM initializes with GORM and panics on error

func NewGORM added in v0.1.0

func NewGORM(cfg Config, sqlDB *sql.DB) (*gorm.DB, error)

NewGORM creates a GORM instance from an existing SQL connection

func NewSQL added in v0.1.0

func NewSQL(cfg Config) (*sql.DB, error)

NewSQL creates a new SQL database connection with given config

func NewWithGORM added in v0.1.0

func NewWithGORM(configs ...Config) (*gorm.DB, error)

NewWithGORM creates a new GORM instance without affecting global state

func WithGORMDeprecated added in v0.1.0

func WithGORMDeprecated(configs ...Config) (*gorm.DB, error)

DEPRECATED: WithGORMDeprecated is deprecated. Use InitWithGORM for global initialization or NewWithGORM for creating new instances. This function will be removed in v2.0.0

Types

type Config

type Config struct {
	// Driver: postgres, mysql, sqlite, turso, libsql
	Driver string `env:"DB_DRIVER,default:sqlite"`

	// Connection details (for traditional databases)
	Host     string `env:"DB_HOST,default:localhost"`
	Port     string `env:"DB_PORT"`
	Database string `env:"DB_DATABASE,default:beaver.db"`
	Username string `env:"DB_USERNAME"`
	Password string `env:"DB_PASSWORD"`

	// URL for direct connection string (overrides individual settings)
	URL string `env:"DB_URL"`

	// Auth token for Turso/LibSQL
	AuthToken string `env:"DB_AUTH_TOKEN"`

	// SSL/TLS Configuration
	SSLMode   string `env:"DB_SSL_MODE,default:disable"` // For PostgreSQL
	TLSConfig string `env:"DB_TLS_CONFIG"`               // For MySQL

	// Connection Pool Settings
	MaxOpenConns    int `env:"DB_MAX_OPEN_CONNS,default:25"`
	MaxIdleConns    int `env:"DB_MAX_IDLE_CONNS,default:5"`
	ConnMaxLifetime int `env:"DB_CONN_MAX_LIFETIME,default:300"` // seconds
	ConnMaxIdleTime int `env:"DB_CONN_MAX_IDLE_TIME,default:60"` // seconds

	// Additional driver-specific parameters
	Params string `env:"DB_PARAMS"`

	// Debug mode
	Debug bool `env:"DB_DEBUG,default:false"`

	// ORM Support (optional)
	UseORM        string `env:"DB_ORM"`                          // "gorm" or empty
	DisableORMLog bool   `env:"DB_DISABLE_ORM_LOG,default:true"` // Only applies when UseORM is set

	// Migrations (optional, mainly for GORM users)
	AutoMigrate     bool   `env:"DB_AUTO_MIGRATE,default:false"`
	MigrationsPath  string `env:"DB_MIGRATIONS_PATH,default:migrations"`
	MigrationsTable string `env:"DB_MIGRATIONS_TABLE,default:schema_migrations"`
}

Config holds database configuration

func GetConfig

func GetConfig() (*Config, error)

GetConfig loads configuration from environment variables

type Database added in v0.1.0

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

Database wraps both sql.DB and gorm.DB providing unified access

func New

func New() *Database

New creates a new Database with default settings

func WithGORM added in v0.1.0

func WithGORM() *Database

WithGORM creates a new Database with GORM enabled

func WithPrefix added in v0.1.0

func WithPrefix(prefix string) *Database

WithPrefix creates a new Database with the specified prefix

func (*Database) Close added in v0.1.0

func (db *Database) Close() error

Close closes the database connection

func (*Database) Connect added in v0.1.0

func (db *Database) Connect() (*Database, error)

Connect creates a new database connection with the configured settings

func (*Database) GORM added in v0.1.0

func (db *Database) GORM() (*gorm.DB, error)

GORM returns the GORM instance or error if not enabled

func (*Database) Init added in v0.1.0

func (db *Database) Init() error

Init initializes the global database instance with the configured settings

func (*Database) MustGORM added in v0.1.0

func (db *Database) MustGORM() *gorm.DB

MustGORM returns the GORM instance or panics if not enabled

func (*Database) Ping added in v0.1.0

func (db *Database) Ping() error

Ping verifies the database connection is alive

func (*Database) PingContext added in v0.1.0

func (db *Database) PingContext(ctx context.Context) error

PingContext verifies the database connection is alive with context

func (*Database) SQL added in v0.1.0

func (db *Database) SQL() *sql.DB

SQL returns the underlying sql.DB instance

func (*Database) Stats added in v0.1.0

func (db *Database) Stats() sql.DBStats

Stats returns connection pool statistics

func (*Database) WithGORM added in v0.1.0

func (db *Database) WithGORM() *Database

WithGORM enables GORM support and returns the database for chaining

func (*Database) WithPrefix added in v0.1.0

func (db *Database) WithPrefix(prefix string) *Database

WithPrefix sets a custom environment variable prefix and returns the database for chaining

Jump to

Keyboard shortcuts

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