database

package
v0.43.0 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2026 License: AGPL-3.0 Imports: 16 Imported by: 0

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Database

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

Database is the main entry point for the neat package.

func New

func New(cfg db.DBConfig, opts ...Option) (*Database, error)

New creates a new Database instance from a DBConfig. The cfg parameter specifies the database configuration including connections and pool settings. The opts parameter allows for functional options like WithContext, WithLogger, WithPool, etc.

Example:

config := db.DBConfig{
    Default: "default",
    Connections: map[string]db.ConnectionConfig{
        "default": {
            Driver: contractsdb.DriverSqlite,
            Database: ":memory:",
        },
    },
}
db, err := New(config, WithLogger(log.NewNoopLogger()))
if err != nil {
    log.Fatal(err)
}
defer db.Close()
Example
// Create a database instance with configuration
config := db.DBConfig{
	Default: "default",
	Connections: map[string]db.ConnectionConfig{
		"default": {
			Driver:   contractsdb.DriverSqlite,
			Database: ":memory:",
		},
	},
}

db, err := New(config, WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()

// Use the database
query := db.Query()
_ = query
Example (MultipleConnections)
// Create a database instance with multiple connections
config := db.DBConfig{
	Default: "primary",
	Connections: map[string]db.ConnectionConfig{
		"primary": {
			Driver:   contractsdb.DriverSqlite,
			Database: ":memory:",
		},
		"replica": {
			Driver:   contractsdb.DriverSqlite,
			Database: ":memory:",
		},
	},
}

db, err := New(config, WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()

// Get a specific connection
replica, err := db.Connection("replica")
if err != nil {
	panic(err)
}
_ = replica
Example (WithPoolConfig)
// Create a database instance with custom pool configuration
config := db.DBConfig{
	Default: "default",
	Connections: map[string]db.ConnectionConfig{
		"default": {
			Driver:   contractsdb.DriverSqlite,
			Database: ":memory:",
		},
	},
}

db, err := New(
	config,
	WithPool(db.PoolConfig{
		MaxIdleConns:    5,
		MaxOpenConns:    25,
		ConnMaxLifetime: 3600,
		ConnMaxIdleTime: 3600,
		QueryTimeout:    30,
	}),
	WithLogger(log.NewNoopLogger()),
)
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()
_ = db
Example (WithReadWriteConnections)
// Create a database instance with read-write separation
config := db.DBConfig{
	Default: "read",
	Connections: map[string]db.ConnectionConfig{
		"read": {
			Driver:   contractsdb.DriverSqlite,
			Database: ":memory:",
		},
		"write": {
			Driver:   contractsdb.DriverSqlite,
			Database: ":memory:",
		},
	},
}

db, err := New(config, WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()

// Use read connection for queries
readConn, err := db.Connection("read")
if err != nil {
	panic(err)
}
_ = readConn

// Use write connection for mutations
writeConn, err := db.Connection("write")
if err != nil {
	panic(err)
}
_ = writeConn

func NewFromDSN

func NewFromDSN(dsn string, opts ...Option) (*Database, error)

NewFromDSN creates a new Database instance from a DSN string. Supported DSN formats: - PostgreSQL: postgres://user:pass@localhost:5432/mydb?sslmode=require - MySQL: mysql://user:pass@tcp(localhost:3306)/mydb?charset=utf8mb4 - SQLite: sqlite://path/to/database.db - SQLite in-memory: sqlite://:memory: - Turso (SQLite edge): turso://lib-name.turso.io - SQL Server: sqlserver://user:pass@localhost:1433/mydb - Oracle: oracle://user:pass@localhost:1521/mydb

Query parameters supported: - PostgreSQL: sslmode (default: require), search_path (default: public), timezone (default: UTC) - MySQL: charset, loc

Example:

db, err := NewFromDSN("postgres://user:pass@localhost:5432/mydb?sslmode=require")
if err != nil {
    log.Fatal(err)
}
defer db.Close()
Example
// Create a database instance from a DSN string
db, err := NewFromDSN("sqlite://:memory:", WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()
_ = db
Example (Mysql)
// MySQL DSN with charset
db, err := NewFromDSN("mysql://user:pass@tcp(localhost:3306)/mydb?charset=utf8mb4", WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()
_ = db
Example (Postgres)
// PostgreSQL DSN with SSL mode
db, err := NewFromDSN("postgres://user:pass@localhost:5432/mydb?sslmode=require", WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()
_ = db
Example (Sqlite)
// SQLite DSN with file path
db, err := NewFromDSN("sqlite://./database.db", WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()
_ = db
Example (Turso)
// Turso (SQLite edge) DSN
db, err := NewFromDSN("turso://lib-name.turso.io", WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()
_ = db
Example (WithQueryParams)
// Create a database instance from DSN with query parameters
db, err := NewFromDSN("postgres://user:pass@localhost:5432/mydb?sslmode=disable&connect_timeout=10", WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()
_ = db

func NewFromSQLDB added in v0.9.0

func NewFromSQLDB(sqlDB *sql.DB, opts ...Option) (*Database, error)

NewFromSQLDB creates a new Database instance from an already-open *sql.DB. The driver is auto-detected from db.Driver() via reflection. Use WithDriver to override when auto-detection is not reliable. The caller retains full ownership of sqlDB — Neat will not close it or alter its connection-pool settings.

Example
// Create a database instance from an existing *sql.DB
sqlDB, err := sql.Open("sqlite", ":memory:")
if err != nil {
	panic(err)
}
defer func() { _ = sqlDB.Close() }()

db, err := NewFromSQLDB(sqlDB, WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()
_ = db
Example (WithDriver)
// Create a database instance from *sql.DB with explicit driver
sqlDB, err := sql.Open("sqlite", ":memory:")
if err != nil {
	panic(err)
}
defer func() { _ = sqlDB.Close() }()

db, err := NewFromSQLDB(sqlDB, WithDriver(contractsdb.DriverSqlite), WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()
_ = db

func (*Database) Close

func (d *Database) Close() error

Close closes the database connection.

When the underlying Orm implements Close() (as the concrete *orm.Orm does), this calls Orm.Close() instead of closing *sql.DB directly. Orm.Close() invokes Array.Cleanup() for array-driver connections, which removes populated/locks sync.Map entries — preventing unbounded memory growth in long-running services that create and close Database instances. If the Orm does not implement Close(), it falls back to direct *sql.DB close.

func (*Database) Connection

func (d *Database) Connection(name string) (*Database, error)

Connection returns a new Database instance for a different connection.

func (*Database) DB

func (d *Database) DB() (*sql.DB, error)

DB returns the underlying database connection.

func (*Database) DatabaseName

func (d *Database) DatabaseName() string

DatabaseName returns the name of the current database.

func (*Database) DisableDebug added in v0.10.0

func (d *Database) DisableDebug()

DisableDebug disables debug mode at runtime for all queries.

func (*Database) DisableQueryLog

func (d *Database) DisableQueryLog()

DisableQueryLog disables the capturing of executed queries.

func (*Database) EnableDebug added in v0.10.0

func (d *Database) EnableDebug()

EnableDebug enables debug mode at runtime for all queries.

func (*Database) EnableQueryLog

func (d *Database) EnableQueryLog()

EnableQueryLog enables the capturing of executed queries.

func (*Database) Factory added in v0.3.0

func (d *Database) Factory() orm.Factory

Factory returns the ORM factory for creating test data.

func (*Database) FlushQueryLog

func (d *Database) FlushQueryLog()

FlushQueryLog clears the captured queries from the log.

func (*Database) GetQueryLog

func (d *Database) GetQueryLog() []orm.QueryLog

GetQueryLog retrieves the captured queries from the log.

func (*Database) IsDebug added in v0.10.0

func (d *Database) IsDebug() bool

IsDebug returns true if debug mode is enabled.

func (*Database) Name added in v0.2.0

func (d *Database) Name() string

Name returns the name of the current connection.

func (*Database) Observe added in v0.3.0

func (d *Database) Observe(model any, observer orm.Observer)

Observe registers an observer for the given model.

func (*Database) Query

func (d *Database) Query() orm.Query

Query returns the ORM query builder for executing database operations. The returned query object can be used to perform CRUD operations, aggregations, and complex queries with joins, where clauses, and more.

Example:

query := db.Query()
var users []User
err := query.Table("users").Where("status", "=", "active").Find(&users)
if err != nil {
    log.Fatal(err)
}
Example
config := db.DBConfig{
	Default: "default",
	Connections: map[string]db.ConnectionConfig{
		"default": {
			Driver:   contractsdb.DriverSqlite,
			Database: ":memory:",
		},
	},
}

db, err := New(config, WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()

// Get the ORM query builder
query := db.Query()
_ = query

func (*Database) Schema

func (d *Database) Schema() *schema.Schema

Schema returns the schema builder for database schema operations. The returned schema object can be used to create, alter, and drop tables, indexes, and other database schema elements.

Example:

schema := db.Schema()
err := schema.CreateTable("users", func(table *schema.Blueprint) {
    table.ID()
    table.String("name")
    table.Timestamps()
})
if err != nil {
    log.Fatal(err)
}
Example
config := db.DBConfig{
	Default: "default",
	Connections: map[string]db.ConnectionConfig{
		"default": {
			Driver:   contractsdb.DriverSqlite,
			Database: ":memory:",
		},
	},
}

db, err := New(config, WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()

// Get the schema builder
schema := db.Schema()
_ = schema

func (*Database) Seed added in v0.3.0

func (d *Database) Seed(seeders []contractsseeder.Seeder) error

Seed runs the specified seeders.

func (*Database) SeedOnce added in v0.3.0

func (d *Database) SeedOnce(seeders []contractsseeder.Seeder) error

SeedOnce runs the specified seeders only once.

func (*Database) Seeder added in v0.3.0

func (d *Database) Seeder() contractsseeder.Facade

Seeder returns a seeder facade for advanced seeder operations.

func (*Database) Transaction

func (d *Database) Transaction(txFunc func(tx orm.Query) error, opts ...*sql.TxOptions) error

Transaction executes a function within a database transaction. The txFunc parameter is a callback function that receives a transaction query object. If the callback returns an error, the transaction is rolled back. If it returns nil, the transaction is committed.

The opts parameter allows specifying transaction isolation level and read-only mode. For example: &sql.TxOptions{Isolation: sql.LevelSerializable, ReadOnly: false}

This callback pattern is safer than manual Begin/Commit because it ensures transactions are always rolled back on error and never left open.

Example:

err := db.Transaction(func(tx orm.Query) error {
    // Perform database operations
    if err := tx.Table("users").Create(map[string]any{"name": "John"}); err != nil {
        return err // Transaction will be rolled back
    }
    return nil // Transaction will be committed
})

Savepoints:

Savepoints are supported through the query interface for nested transactions.
Use tx.SavePoint("name") and tx.RollbackTo("name") for partial rollbacks.

Transaction Isolation:

Use opts to control isolation level:
- sql.LevelReadUncommitted: Lowest isolation, allows dirty reads
- sql.LevelReadCommitted: Prevents dirty reads
- sql.LevelRepeatableRead: Prevents dirty and non-repeatable reads
- sql.LevelSerializable: Highest isolation, prevents all anomalies
Example
config := db.DBConfig{
	Default: "default",
	Connections: map[string]db.ConnectionConfig{
		"default": {
			Driver:   contractsdb.DriverSqlite,
			Database: ":memory:",
		},
	},
}

db, err := New(config, WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()

// Execute a transaction with automatic rollback on error
err = db.Transaction(func(tx orm.Query) error {
	// Perform database operations within the transaction
	// If an error is returned, the transaction is rolled back
	// If nil is returned, the transaction is committed
	return nil
})
if err != nil {
	panic(err)
}
Example (Nested)
config := db.DBConfig{
	Default: "default",
	Connections: map[string]db.ConnectionConfig{
		"default": {
			Driver:   contractsdb.DriverSqlite,
			Database: ":memory:",
		},
	},
}

db, err := New(config, WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()

// Nested transaction using savepoints
err = db.Transaction(func(tx orm.Query) error {
	// Outer transaction
	err := tx.Transaction(func(innerTx orm.Query) error {
		// Inner transaction (savepoint)
		return nil
	})
	return err
})
if err != nil {
	panic(err)
}
Example (WithError)
config := db.DBConfig{
	Default: "default",
	Connections: map[string]db.ConnectionConfig{
		"default": {
			Driver:   contractsdb.DriverSqlite,
			Database: ":memory:",
		},
	},
}

db, err := New(config, WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()

// Transaction with error handling - automatically rolls back on error
err = db.Transaction(func(tx orm.Query) error {
	// Simulate an error
	return fmt.Errorf("operation failed")
})
if err != nil {
	// Transaction was rolled back
	fmt.Println("Transaction rolled back:", err)
}
Example (WithIsolation)
config := db.DBConfig{
	Default: "default",
	Connections: map[string]db.ConnectionConfig{
		"default": {
			Driver:   contractsdb.DriverSqlite,
			Database: ":memory:",
		},
	},
}

db, err := New(config, WithLogger(log.NewNoopLogger()))
if err != nil {
	panic(err)
}
defer func() { _ = db.Close() }()

// Transaction with isolation level
err = db.Transaction(func(tx orm.Query) error {
	// Perform operations with specific isolation level
	return nil
}, &sql.TxOptions{
	Isolation: sql.LevelSerializable,
	ReadOnly:  false,
})
if err != nil {
	panic(err)
}

type Option

type Option func(*options)

Option is a functional option for configuring the Database.

func SkipPing added in v0.5.0

func SkipPing() Option

SkipPing skips the initial database ping during connection.

func WithContext

func WithContext(ctx context.Context) Option

WithContext sets the context for the database.

func WithDebug added in v0.7.0

func WithDebug() Option

WithDebug enables debug mode for the database.

func WithDriver added in v0.9.0

func WithDriver(driverName contractsdb.Driver) Option

WithDriver sets the database driver name for NewFromSQLDB when auto-detection is not reliable. Valid values: "mysql", "postgres", "sqlite", "sqlserver", "oracle", "turso".

func WithEventBus

func WithEventBus(eventBus *databaseorm.EventBus) Option

WithEventBus sets the event bus for the database.

func WithLogger

func WithLogger(logger log.Log) Option

WithLogger sets the logger for the database.

func WithPool

func WithPool(pool db.PoolConfig) Option

WithPool sets the connection pool configuration for the database.

Jump to

Keyboard shortcuts

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