postgres

package
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Dec 16, 2025 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package postgres provides functionality for interacting with PostgreSQL databases.

The postgres package offers a robust interface for working with PostgreSQL databases, built on top of the standard database/sql package. It includes connection management, query execution, transaction handling, and migration tools.

Core Features:

  • Connection pooling and management
  • Parameterized query execution
  • Transaction support with automatic rollback on errors
  • Schema migration tools
  • Row scanning utilities
  • Basic CRUD operations

Basic Usage:

import (
	"github.com/Aleph-Alpha/std/v1/postgres"
	"github.com/Aleph-Alpha/std/v1/logger"
)

// Create a logger
log, _ := logger.NewLogger(logger.Config{Level: "info"})

// Create a new database connection
db, err := postgres.New(postgres.Config{
	Host:     "localhost",
	Port:     5432,
	Username: "postgres",
	Password: "password",
	Database: "mydb",
}, log)
if err != nil {
	log.Fatal("Failed to connect to database", err, nil)
}
defer db.Close()

// Execute a query
rows, err := db.Query(context.Background(), "SELECT id, name FROM users WHERE age > $1", 18)
if err != nil {
	log.Error("Query failed", err, nil)
}
defer rows.Close()

// Scan the results
var users []User
for rows.Next() {
	var user User
	if err := rows.Scan(&user.ID, &user.Name); err != nil {
		log.Error("Scan failed", err, nil)
	}
	users = append(users, user)
}

Transaction Example:

err = db.WithTransaction(context.Background(), func(tx postgres.Transaction) error {
	// Execute multiple queries in a transaction
	_, err := tx.Exec("UPDATE accounts SET balance = balance - $1 WHERE id = $2", amount, fromID)
	if err != nil {
		return err  // Transaction will be rolled back
	}

	_, err = tx.Exec("UPDATE accounts SET balance = balance + $1 WHERE id = $2", amount, toID)
	if err != nil {
		return err  // Transaction will be rolled back
	}

	return nil  // Transaction will be committed
})

Basic Operations:

// Create a record
id, err := db.Insert(ctx, "INSERT INTO users(name, email) VALUES($1, $2) RETURNING id", "John", "john@example.com")

// Check if a record exists
exists, err := db.Exists(ctx, "SELECT 1 FROM users WHERE email = $1", "john@example.com")

// Get a single record
var user User
err = db.Get(ctx, &user, "SELECT id, name, email FROM users WHERE id = $1", id)

FX Module Integration:

This package provides an fx module for easy integration:

app := fx.New(
	logger.Module,
	postgres.Module,
	// ... other modules
)
app.Run()

Performance Considerations:

  • Connection pooling is automatically handled to optimize performance
  • Prepared statements are used internally to reduce parsing overhead
  • Consider using batch operations for multiple insertions
  • Query timeouts are recommended for all database operations

Thread Safety:

All methods on the DB interface are safe for concurrent use by multiple goroutines.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrRecordNotFound is returned when a query doesn't find any matching records
	ErrRecordNotFound = errors.New("record not found")

	// ErrDuplicateKey is returned when an insert or update violates a unique constraint
	ErrDuplicateKey = errors.New("duplicate key violation")

	// ErrForeignKey is returned when an operation violates a foreign key constraint
	ErrForeignKey = errors.New("foreign key violation")

	// ErrInvalidData is returned when the data being saved doesn't meet validation rules
	ErrInvalidData = errors.New("invalid data")

	// ErrConnectionFailed is returned when database connection cannot be established
	ErrConnectionFailed = errors.New("database connection failed")

	// ErrTransactionFailed is returned when a transaction fails to commit or rollback
	ErrTransactionFailed = errors.New("transaction failed")

	// ErrQueryTimeout is returned when a query exceeds the allowed timeout
	ErrQueryTimeout = errors.New("query timeout exceeded")

	// ErrInvalidQuery is returned when the SQL query is malformed or invalid
	ErrInvalidQuery = errors.New("invalid query")

	// ErrPermissionDenied is returned when the user lacks necessary permissions
	ErrPermissionDenied = errors.New("permission denied")

	// ErrTableNotFound is returned when trying to access a non-existent table
	ErrTableNotFound = errors.New("table not found")

	// ErrColumnNotFound is returned when trying to access a non-existent column
	ErrColumnNotFound = errors.New("column not found")

	// ErrConstraintViolation is returned for general constraint violations
	ErrConstraintViolation = errors.New("constraint violation")

	// ErrCheckConstraintViolation is returned when a check constraint is violated
	ErrCheckConstraintViolation = errors.New("check constraint violation")

	// ErrNotNullViolation is returned when trying to insert null into a not-null column
	ErrNotNullViolation = errors.New("not null constraint violation")

	// ErrDataTooLong is returned when data exceeds column length limits
	ErrDataTooLong = errors.New("data too long for column")

	// ErrDeadlock is returned when a deadlock is detected during transaction
	ErrDeadlock = errors.New("deadlock detected")

	// ErrLockTimeout is returned when unable to acquire lock within timeout
	ErrLockTimeout = errors.New("lock acquisition timeout")

	// ErrInvalidDataType is returned when data type conversion fails
	ErrInvalidDataType = errors.New("invalid data type")

	// ErrDivisionByZero is returned for division by zero operations
	ErrDivisionByZero = errors.New("division by zero")

	// ErrNumericOverflow is returned when numeric operation causes overflow
	ErrNumericOverflow = errors.New("numeric value overflow")

	// ErrDiskFull is returned when database storage is full
	ErrDiskFull = errors.New("disk full")

	// ErrTooManyConnections is returned when connection pool is exhausted
	ErrTooManyConnections = errors.New("too many connections")

	// ErrInvalidJSON is returned when JSON data is malformed
	ErrInvalidJSON = errors.New("invalid JSON data")

	// ErrIndexCorruption is returned when database index is corrupted
	ErrIndexCorruption = errors.New("index corruption detected")

	// ErrConfigurationError is returned for database configuration issues
	ErrConfigurationError = errors.New("database configuration error")

	// ErrUnsupportedOperation is returned for operations not supported by the database
	ErrUnsupportedOperation = errors.New("unsupported operation")

	// ErrMigrationFailed is returned when database migration fails
	ErrMigrationFailed = errors.New("migration failed")

	// ErrBackupFailed is returned when database backup operation fails
	ErrBackupFailed = errors.New("backup operation failed")

	// ErrRestoreFailed is returned when database restore operation fails
	ErrRestoreFailed = errors.New("restore operation failed")

	// ErrSchemaValidation is returned when schema validation fails
	ErrSchemaValidation = errors.New("schema validation failed")

	// ErrSerializationFailure is returned when transaction serialization fails
	ErrSerializationFailure = errors.New("serialization failure")

	// ErrInsufficientPrivileges is returned when user lacks required privileges
	ErrInsufficientPrivileges = errors.New("insufficient privileges")

	// ErrInvalidPassword is returned for authentication failures
	ErrInvalidPassword = errors.New("invalid password")

	// ErrAccountLocked is returned when user account is locked
	ErrAccountLocked = errors.New("account locked")

	// ErrDatabaseNotFound is returned when specified database doesn't exist
	ErrDatabaseNotFound = errors.New("database not found")

	// ErrSchemaNotFound is returned when specified schema doesn't exist
	ErrSchemaNotFound = errors.New("schema not found")

	// ErrFunctionNotFound is returned when specified function doesn't exist
	ErrFunctionNotFound = errors.New("function not found")

	// ErrTriggerNotFound is returned when specified trigger doesn't exist
	ErrTriggerNotFound = errors.New("trigger not found")

	// ErrIndexNotFound is returned when specified index doesn't exist
	ErrIndexNotFound = errors.New("index not found")

	// ErrViewNotFound is returned when specified view doesn't exist
	ErrViewNotFound = errors.New("view not found")

	// ErrSequenceNotFound is returned when specified sequence doesn't exist
	ErrSequenceNotFound = errors.New("sequence not found")

	// ErrInvalidCursor is returned when cursor operation fails
	ErrInvalidCursor = errors.New("invalid cursor")

	// ErrCursorNotFound is returned when specified cursor doesn't exist
	ErrCursorNotFound = errors.New("cursor not found")

	// ErrStatementTimeout is returned when statement execution exceeds timeout
	ErrStatementTimeout = errors.New("statement timeout")

	// ErrIdleInTransaction is returned when transaction is idle too long
	ErrIdleInTransaction = errors.New("idle in transaction timeout")

	// ErrConnectionLost is returned when database connection is lost
	ErrConnectionLost = errors.New("connection lost")

	// ErrProtocolViolation is returned for database protocol violations
	ErrProtocolViolation = errors.New("protocol violation")

	// ErrInternalError is returned for internal database errors
	ErrInternalError = errors.New("internal database error")

	// ErrSystemError is returned for system-level database errors
	ErrSystemError = errors.New("system error")
)

Common database error types that can be used by consumers of this package. These provide a standardized set of errors that abstract away the underlying database-specific error details.

FXModule is an fx module that provides the Postgres database component. It registers the Postgres constructor for dependency injection and sets up lifecycle hooks to properly initialize and shut down the database connection.

Functions

func RegisterPostgresLifecycle

func RegisterPostgresLifecycle(params PostgresLifeCycleParams)

RegisterPostgresLifecycle registers lifecycle hooks for the Postgres database component. It sets up: 1. Connection monitoring on the application starts 2. Automatic reconnection mechanism on application start 3. Graceful shutdown of database connections on application stop

The function uses a WaitGroup to ensure that all goroutines complete before the application terminates.

Types

type Config

type Config struct {
	// Connection contains the essential parameters needed to establish a database connection
	Connection Connection

	// ConnectionDetails contains configuration for the connection pool behavior
	ConnectionDetails ConnectionDetails
}

Config represents the complete configuration for a PostgresSQL database connection. It encapsulates both the basic connection parameters and detailed connection pool settings.

type Connection

type Connection struct {
	// Host specifies the database server hostname or IP address
	Host string

	// Port specifies the TCP port on which the database server is listening to
	Port string

	// User specifies the database username for authentication
	User string

	// Password specifies the database user password for authentication
	Password string

	// DbName specifies the name of the database to connect to
	DbName string

	// SSLMode specifies the SSL mode for the connection (e.g., "disable", "require", "verify-ca", "verify-full")
	// For production environments, it's recommended to use at least "require"
	SSLMode string
}

Connection holds the basic parameters required to connect to a PostgresSQL database. These parameters are used to construct the database connection string.

type ConnectionDetails

type ConnectionDetails struct {
	// MaxOpenConns controls the maximum number of open connections to the database.
	// Setting this appropriately helps prevent overwhelming the database with too many connections.
	// Default is 0 (unlimited).
	MaxOpenConns int

	// MaxIdleConns controls the maximum number of connections in the idle connection pool.
	// A higher value can improve performance under a concurrent load but consumes more resources.
	// Default is 2.
	MaxIdleConns int

	// ConnMaxLifetime is the maximum amount of time a connection may be reused.
	// Expired connections are closed and removed from the pool during connection acquisition.
	// This helps ensure database-enforced timeouts are respected.
	// Default is 0 (unlimited).
	ConnMaxLifetime time.Duration
}

ConnectionDetails holds configuration settings for the database connection pool. These settings help optimize performance and resource usage by controlling how database connections are created, reused, and expired.

type ErrorCategory

type ErrorCategory int

ErrorCategory represents different categories of database errors

const (
	CategoryUnknown ErrorCategory = iota
	CategoryConnection
	CategoryQuery
	CategoryData
	CategoryConstraint
	CategoryPermission
	CategoryTransaction
	CategoryResource
	CategorySystem
	CategorySchema
	CategoryOperation
)

type Migration

type Migration struct {
	// ID is a unique identifier for the migration, typically a timestamp (YYYYMMDDHHMMSS)
	// that also helps establish the execution order.
	ID string

	// Name is a descriptive label for the migration, typically describing what it does.
	Name string

	// Type categorizes the migration as either schema or data.
	Type MigrationType

	// Direction indicates whether this is an up (apply) or down (rollback) migration.
	Direction MigrationDirection

	// SQL contains the actual SQL statements to execute for this migration.
	SQL string
}

Migration represents a single database migration with all its metadata and content. Each migration contains the SQL to execute and information about its purpose and identity.

type MigrationDirection

type MigrationDirection string

MigrationDirection specifies the direction of the migration, indicating whether it's applying a change or reverting one.

const (
	// UpMigration indicates a forward migration that applies a change.
	UpMigration MigrationDirection = "up"

	// DownMigration indicates a rollback migration that reverts a change.
	DownMigration MigrationDirection = "down"
)

type MigrationHistoryRecord

type MigrationHistoryRecord struct {
	// ID matches the migration ID that was applied.
	ID string

	// Name is the descriptive name of the migration.
	Name string

	// Type indicates whether this was a schema or data migration.
	Type string

	// ExecutedAt records when the migration was applied.
	ExecutedAt time.Time

	// ExecutedBy tracks who or what system applied the migration.
	ExecutedBy string

	// Duration measures how long the migration took to execute in milliseconds.
	Duration int64

	// Status indicates whether the migration completed successfully or failed.
	Status string

	// ErrorMessage contains details if the migration failed.
	ErrorMessage string `gorm:"type:text"`
}

MigrationHistoryRecord represents a record in the migration history table. It tracks when and how each migration was applied, enabling the system to determine which migrations have been run and providing an audit trail.

type MigrationType

type MigrationType string

MigrationType defines the type of migration, categorizing the purpose of the change. This helps track and organize migrations based on their impact on the database.

const (
	// SchemaType represents schema changes (tables, columns, indexes, etc.)
	// These migrations modify the structure of the database.
	SchemaType MigrationType = "schema"

	// DataType represents data manipulations (inserts, updates, etc.)
	// These migrations modify the content within the database.
	DataType MigrationType = "data"
)

type Postgres

type Postgres struct {
	Client *gorm.DB
	// contains filtered or unexported fields
}

Postgres is a thread-safe wrapper around gorm.DB that provides connection monitoring, automatic reconnection, and standardized database operations. It guards all database operations with a mutex to ensure thread safety and includes mechanisms for graceful shutdown and connection health monitoring.

func NewPostgres

func NewPostgres(cfg Config) (*Postgres, error)

NewPostgres creates a new Postgres instance with the provided configuration and Logger. It establishes the initial database connection and sets up the internal state for connection monitoring and recovery. If the initial connection fails, it logs a fatal error and terminates.

func NewPostgresClientWithDI

func NewPostgresClientWithDI(params PostgresParams) (*Postgres, error)

NewPostgresClientWithDI creates a new Postgres Client using dependency injection. This function is designed to be used with Uber's fx dependency injection framework where the Config and Logger dependencies are automatically provided via the PostgresParams struct.

Parameters:

  • params: A PostgresParams struct containing the Config and Logger instances required to initialize the Postgres Client. This struct embeds fx.In to enable automatic injection of these dependencies.

Returns:

  • *Postgres: A fully initialized Postgres Client ready for use.

Example usage with fx:

app := fx.New(
    postgres.FXModule,
    fx.Provide(
        func() postgres.Config {
            return loadPostgresConfig() // Your config loading function
        },
        func() postgres.Logger {
            return initLogger() // Your logger initialization
        },
    ),
)

This function delegates to the standard NewPostgres function, maintaining the same initialization logic while enabling seamless integration with dependency injection.

func (*Postgres) AutoMigrate

func (p *Postgres) AutoMigrate(models ...interface{}) error

AutoMigrate is a wrapper around GORM's AutoMigrate with additional features. It tracks migrations in the migration history table and provides better error handling.

Parameters:

  • models: The GORM models to auto-migrate

Returns an error if any part of the migration process fails.

This method is useful during development or for simple applications, but for production systems, explicit migrations are recommended.

func (*Postgres) Count

func (p *Postgres) Count(ctx context.Context, model interface{}, count *int64, conditions ...interface{}) error

Count determines the number of records that match the given conditions. It populates the count parameter with the result.

Parameters:

  • ctx: Context for the database operation
  • model: The model type to count
  • count: Pointer to an int64 where the count will be stored
  • conditions: Query conditions to filter the records to count

Returns an error if the query fails or nil on success.

Example:

var count int64
err := db.Count(ctx, &User{}, &count, "age > ?", 18)

func (*Postgres) Create

func (p *Postgres) Create(ctx context.Context, value interface{}) error

Create inserts a new record into the database. It processes the value parameter according to GORM conventions, performing hooks and validations defined on the model.

Parameters:

  • ctx: Context for the database operation
  • value: The struct or slice of structs to be created

Returns an error if the creation fails or nil on success.

Example:

user := User{Name: "John", Email: "john@example.com"}
err := db.Create(ctx, &user)

func (*Postgres) CreateMigration

func (p *Postgres) CreateMigration(migrationsDir, name string, migrationType MigrationType) (string, error)

CreateMigration generates a new migration file. It creates both up and down migration files with appropriate names and timestamps.

Parameters:

  • migrationsDir: Directory where migration files should be created
  • name: Descriptive name for the migration
  • migrationType: Whether this is a schema or data migration

Returns the base filename of the created migration or an error if creation fails.

Example:

filename, err := db.CreateMigration("./migrations", "create_users_table", postgres.SchemaType)
if err == nil {
    fmt.Printf("Created migration: %s\n", filename)
}

func (*Postgres) DB

func (p *Postgres) DB() *gorm.DB

DB returns the underlying GORM DB Client instance. This method provides direct access to the database connection while maintaining thread safety through a read lock.

Use this method when you need to perform operations not covered by the wrapper methods or when you need to access specific GORM functionality. Note that direct usage bypasses some of the safety mechanisms, so use it with care.

func (*Postgres) Delete

func (p *Postgres) Delete(ctx context.Context, value interface{}, conditions ...interface{}) (int64, error)

Delete removes records that match the given value and conditions from the database. It respects soft delete if implemented on the model.

Parameters:

  • ctx: Context for the database operation
  • value: The model to delete or a slice for batch delete
  • conditions: Additional conditions to filter records to delete

Returns:

  • int64: Number of rows affected by the delete operation
  • error: Error if the deletion fails, nil on success

Example:

// Delete user with ID=1
rowsAffected, err := db.Delete(ctx, &User{}, "id = ?", 1)
if err != nil {
    return err
}
fmt.Printf("Deleted %d rows\n", rowsAffected)

// Or with a model instance
user := User{ID: 1}
rowsAffected, err := db.Delete(ctx, &user)

func (*Postgres) Exec

func (p *Postgres) Exec(ctx context.Context, sql string, values ...interface{}) (int64, error)

Exec executes raw SQL directly against the database. This is useful for operations not easily expressed through GORM's API or for performance-critical code.

Parameters:

  • ctx: Context for the database operation
  • sql: The SQL statement to execute
  • values: Parameters for the SQL statement

Returns:

  • int64: Number of rows affected by the SQL execution
  • error: Error if the execution fails, nil on success

Example:

rowsAffected, err := db.Exec(ctx, "UPDATE users SET status = ? WHERE last_login < ?",
                             "inactive", time.Now().AddDate(0, -6, 0))
if err != nil {
    return err
}
fmt.Printf("Updated %d users\n", rowsAffected)

func (*Postgres) Find

func (p *Postgres) Find(ctx context.Context, dest interface{}, conditions ...interface{}) error

Find retrieves records from the database that match the given conditions. It populates the dest parameter with the query results.

Parameters:

  • ctx: Context for the database operation
  • dest: Pointer to a slice where the results will be stored
  • conditions: Optional query conditions (follows GORM conventions)

Return an error if the query fails or nil on success.

Example:

var users []User
err := db.Find(ctx, &users, "name LIKE ?", "%john%")

func (*Postgres) First

func (p *Postgres) First(ctx context.Context, dest interface{}, conditions ...interface{}) error

First retrieves the first record that matches the given conditions. It populates the dest parameter with the result or returns an error if no matching record exists.

Parameters:

  • ctx: Context for the database operation
  • dest: Pointer to a struct where the result will be stored
  • conditions: Optional query conditions (follows GORM conventions)

Return ErrRecordNotFound if no matching record exists, or another error if the query fails.

Example:

var user User
err := db.First(ctx, &user, "email = ?", "user@example.com")

func (*Postgres) GetErrorCategory

func (p *Postgres) GetErrorCategory(err error) ErrorCategory

GetErrorCategory returns the category of the given error

func (*Postgres) GetMigrationStatus

func (p *Postgres) GetMigrationStatus(ctx context.Context, migrationsDir string) ([]map[string]interface{}, error)

GetMigrationStatus returns the status of all migrations. It compares available migrations with those that have been applied to build a comprehensive status report.

Parameters:

  • ctx: Context for database operations
  • migrationsDir: Directory containing the migration SQL files

Returns a slice of maps with status information for each migration, or an error if the status cannot be determined.

Example:

status, err := db.GetMigrationStatus(ctx, "./migrations")
if err == nil {
    for _, m := range status {
        fmt.Printf("Migration %s: %v\n", m["id"], m["applied"])
    }
}

func (*Postgres) GracefulShutdown

func (p *Postgres) GracefulShutdown() error

func (*Postgres) IsCritical

func (p *Postgres) IsCritical(err error) bool

IsCritical returns true if the error indicates a serious system problem

func (*Postgres) IsRetryable

func (p *Postgres) IsRetryable(err error) bool

IsRetryable returns true if the error might be resolved by retrying the operation

func (*Postgres) IsTemporary

func (p *Postgres) IsTemporary(err error) bool

IsTemporary returns true if the error is likely temporary and might resolve itself

func (*Postgres) MigrateDown

func (p *Postgres) MigrateDown(ctx context.Context, migrationsDir string) error

MigrateDown rolls back the last applied migration. It finds the most recently applied migration and executes its corresponding down migration to revert the changes.

Parameters:

  • ctx: Context for database operations
  • migrationsDir: Directory containing the migration SQL files

Returns an error if the rollback fails or if the down migration can't be found.

Example:

err := db.MigrateDown(ctx, "./migrations")

func (*Postgres) MigrateUp

func (p *Postgres) MigrateUp(ctx context.Context, migrationsDir string) error

MigrateUp applies all pending migrations from the specified directory. It identifies which migrations haven't been applied yet, sorts them by ID, and applies them in order within transactions.

Parameters:

  • ctx: Context for database operations
  • migrationsDir: Directory containing the migration SQL files

Returns an error if any migration fails or if there are issues accessing the migrations.

Example:

err := db.MigrateUp(ctx, "./migrations")

func (*Postgres) MonitorConnection

func (p *Postgres) MonitorConnection(ctx context.Context)

MonitorConnection periodically checks the health of the database connection and triggers reconnection attempts when necessary. It runs as a goroutine that performs health checks at regular intervals (10 seconds) and signals the RetryConnection goroutine when a failure is detected.

The function respects context cancellation and shutdown signals, ensuring proper resource cleanup and graceful termination when requested.

func (*Postgres) Query

func (p *Postgres) Query(ctx context.Context) *QueryBuilder

Query provides a flexible way to build complex queries. It returns a QueryBuilder which can be used to chain query methods in a fluent interface. The method acquires a read lock on the database connection that will be automatically released when a terminal method is called or Done() is invoked.

Parameters:

  • ctx: Context for the database operation

Returns a QueryBuilder instance that can be used to construct the query.

Example:

users := []User{}
err := db.Query(ctx).
    Where("age > ?", 18).
    Order("created_at DESC").
    Limit(10).
    Find(&users)

func (*Postgres) RetryConnection

func (p *Postgres) RetryConnection(ctx context.Context)

RetryConnection continuously attempts to reconnect to the PostgresSQL database when notified of a connection failure. It operates as a goroutine that waits for signals on retryChanSignal before attempting reconnection. The function respects context cancellation and shutdown signals, ensuring graceful termination when requested.

It implements two nested loops: - The outer loop waits for retry signals - The inner loop attempts reconnection until successful

func (*Postgres) Save

func (p *Postgres) Save(ctx context.Context, value interface{}) error

Save updates the database record if the primary key exists, otherwise it creates a new record. It performs a full update of all fields, not just changed fields.

Parameters:

  • ctx: Context for the database operation
  • value: The struct to be saved

Returns an error if the operation fails or nil on success.

Example:

user.Name = "Updated Name"
err := db.Save(ctx, &user)

func (*Postgres) Transaction

func (p *Postgres) Transaction(ctx context.Context, fn func(pg *Postgres) error) error

Transaction executes the given function within a database transaction. It creates a transaction-specific Postgres instance and passes it to the provided function. If the function returns an error, the transaction is rolled back; otherwise, it's committed.

This method provides a clean way to execute multiple database operations as a single atomic unit, with automatic handling of commit/rollback based on the execution result.

Example usage:

err := pg.Transaction(ctx, func(txPg *Postgres) error {
	if err := txPg.Create(ctx, user); err != nil {
		return err
	}
	return txPg.Create(ctx, userProfile)
})

func (*Postgres) TranslateError

func (p *Postgres) TranslateError(err error) error

TranslateError converts GORM/database-specific errors into standardized application errors. This function provides abstraction from the underlying database implementation details, allowing application code to handle errors in a database-agnostic way.

It maps common database errors to the standardized error types defined above. If an error doesn't match any known type, it's returned unchanged.

func (*Postgres) Update

func (p *Postgres) Update(ctx context.Context, model interface{}, attrs interface{}) (int64, error)

Update updates records that match the given model's non-zero fields or primary key. It only updates the fields provided in attrs and only affects records that match the model's primary key or query conditions.

Parameters:

  • ctx: Context for the database operation
  • model: The model instance with primary key set, or struct with query conditions
  • attrs: Map, struct, or individual field values to update

Returns:

  • int64: Number of rows affected by the update operation
  • error: Error if the update fails, nil on success

Note: The current implementation has a bug where it executes the query twice. This should be fixed to execute only once and return both values properly.

Example:

// Update user with ID=1
rowsAffected, err := db.Update(ctx, &User{ID: 1}, map[string]interface{}{
    "name": "New Name",
    "age": 30,
})
if err != nil {
    return err
}
fmt.Printf("Updated %d rows\n", rowsAffected)

func (*Postgres) UpdateColumn

func (p *Postgres) UpdateColumn(ctx context.Context, model interface{}, columnName string, value interface{}) (int64, error)

UpdateColumn updates a single column's value for records that match the given model. Unlike Update, it doesn't run hooks and can be used to update fields that are zero values (like setting a string to empty or a number to zero).

Parameters:

  • ctx: Context for the database operation
  • model: The model instance with primary key set, or struct with query conditions
  • columnName: Name of the column to update
  • value: New value for the column

Returns:

  • int64: Number of rows affected by the update operation
  • error: Error if the update fails, nil on success

Example:

// Set status to "inactive" for user with ID=1
rowsAffected, err := db.UpdateColumn(ctx, &User{ID: 1}, "status", "inactive")
if err != nil {
    return err
}
fmt.Printf("Updated %d rows\n", rowsAffected)

func (*Postgres) UpdateColumns

func (p *Postgres) UpdateColumns(ctx context.Context, model interface{}, columnValues map[string]interface{}) (int64, error)

UpdateColumns updates multiple columns with name/value pairs for records that match the given model. Like UpdateColumn, it doesn't run hooks and can update zero-value fields.

Parameters:

  • ctx: Context for the database operation
  • model: The model instance with primary key set, or struct with query conditions
  • columnValues: Map of column names to their new values

Returns:

  • int64: Number of rows affected by the update operation
  • error: Error if the update fails, nil on success

Example:

// Update multiple fields for user with ID=1
rowsAffected, err := db.UpdateColumns(ctx, &User{ID: 1}, map[string]interface{}{
    "status": "inactive",
    "last_login": time.Now(),
})
if err != nil {
    return err
}
fmt.Printf("Updated %d rows\n", rowsAffected)

func (*Postgres) UpdateWhere

func (p *Postgres) UpdateWhere(ctx context.Context, model interface{}, attrs interface{}, condition string, args ...interface{}) (int64, error)

UpdateWhere updates records that match the specified WHERE condition. This method provides more flexibility than Update for complex conditions.

Parameters:

  • ctx: Context for the database operation
  • model: The model type to update
  • attrs: Fields to update (map, struct, or name/value pairs)
  • condition: WHERE condition as a string
  • args: Arguments for the WHERE condition

Returns:

  • int64: Number of rows affected by the update operation
  • error: Error if the update fails, nil on success

Example:

// Update all users who haven't logged in for 6 months
rowsAffected, err := db.UpdateWhere(ctx, &User{},
                                    map[string]interface{}{"status": "inactive"},
                                    "last_login < ?",
                                    time.Now().AddDate(0, -6, 0))
if err != nil {
    return err
}
fmt.Printf("Updated %d users to inactive status\n", rowsAffected)

type PostgresLifeCycleParams

type PostgresLifeCycleParams struct {
	fx.In

	Lifecycle fx.Lifecycle
	Postgres  *Postgres
}

PostgresLifeCycleParams groups the dependencies needed for Postgres lifecycle management. This struct combines all the components required to properly manage the lifecycle of a Postgres Client within an fx application, including startup, monitoring, and graceful shutdown.

The embedded fx.In marker enables automatic injection of the struct fields from the dependency container when this struct is used as a parameter in lifecycle registration functions.

type PostgresParams

type PostgresParams struct {
	fx.In

	Config Config
}

PostgresParams groups the dependencies needed to create a Postgres Client via dependency injection. This struct is designed to work with Uber's fx dependency injection framework and provides the necessary parameters for initializing a Postgres database connection.

The embedded fx.In marker enables automatic injection of the struct fields from the dependency container when this struct is used as a parameter in provider functions.

type QueryBuilder

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

QueryBuilder provides a fluent interface for building complex database queries. It wraps GORM's query building capabilities with thread-safety and automatic resource cleanup. The builder maintains a chain of query modifiers that are applied when a terminal method is called.

func (*QueryBuilder) Clauses

func (qb *QueryBuilder) Clauses(conds ...clause.Expression) *QueryBuilder

Clauses adds custom clauses to the query. This is a generic method for adding any GORM clause type.

Parameters:

  • conds: One or more clause expressions

Returns the QueryBuilder for method chaining.

Example:

qb.Clauses(clause.OrderBy{
    Expression: clause.Expr{SQL: "RANDOM()"},
}).Find(&users) // Random order

qb.Clauses(clause.GroupBy{
    Columns: []clause.Column{{Name: "department"}},
}).Find(&users)

func (*QueryBuilder) Count

func (qb *QueryBuilder) Count(count *int64) error

Count counts records that match the query conditions. This is a terminal method that executes the query and releases the mutex lock.

Parameters:

  • count: Pointer to an int64 where the count will be stored

Returns an error if the query fails or nil on success.

Example:

var count int64
err := qb.Where("active = ?", true).Count(&count)

func (*QueryBuilder) CreateInBatches

func (qb *QueryBuilder) CreateInBatches(value interface{}, batchSize int) (int64, error)

CreateInBatches creates records in batches to avoid memory issues with large datasets. This is a terminal method that executes the operation and releases the mutex lock.

Parameters:

  • value: Slice of records to create
  • batchSize: Number of records to process in each batch

Returns:

  • int64: Number of rows affected (records created)
  • error: Error if the operation fails, nil on success

Example:

users := []User{{Name: "John"}, {Name: "Jane"}, {Name: "Bob"}}
rowsAffected, err := qb.CreateInBatches(&users, 100)
if err != nil {
    return err
}
fmt.Printf("Created %d records\n", rowsAffected)

func (*QueryBuilder) Delete

func (qb *QueryBuilder) Delete(value interface{}) (int64, error)

Delete deletes records that match the query conditions. This is a terminal method that executes the query and releases the mutex lock.

Parameters:

  • value: Model value or pointer to specify what to delete

Returns:

  • int64: Number of rows affected by the delete operation
  • error: Error if the deletion fails, nil on success

Example:

rowsAffected, err := qb.Where("created_at < ?", time.Now().AddDate(-1, 0, 0)).Delete(&User{})
if err != nil {
    return err
}
fmt.Printf("Deleted %d rows\n", rowsAffected)

func (*QueryBuilder) Distinct

func (qb *QueryBuilder) Distinct(args ...interface{}) *QueryBuilder

Distinct specifies that the query should return distinct results. It eliminates duplicate rows from the result set.

Parameters:

  • args: Optional columns to apply DISTINCT to

Returns the QueryBuilder for method chaining.

Example:

qb.Distinct("department").Find(&departments)
qb.Distinct().Where("age > ?", 18).Find(&users) // SELECT DISTINCT * FROM users WHERE age > 18

func (*QueryBuilder) Done

func (qb *QueryBuilder) Done()

Done releases the mutex lock without executing the query. This method should be called when you want to cancel a query building chain without executing any terminal operation.

Example:

qb := db.Query(ctx)
if someCondition {
    err := qb.Where(...).Find(&results)
} else {
    qb.Done() // Release the lock without executing
}

func (*QueryBuilder) Find

func (qb *QueryBuilder) Find(dest interface{}) error

Find finds records that match the query conditions. This is a terminal method that executes the query and releases the mutex lock.

Parameters:

  • dest: Pointer to a slice where results will be stored

Returns an error if the query fails or nil on success.

Example:

var users []User
err := qb.Where("active = ?", true).Find(&users)

func (*QueryBuilder) First

func (qb *QueryBuilder) First(dest interface{}) error

First finds the first record that matches the query conditions. This is a terminal method that executes the query and releases the mutex lock.

Parameters:

  • dest: Pointer to a struct where the result will be stored

Returns an error if no record is found or the query fails, nil on success.

Example:

var user User
err := qb.Where("email = ?", "user@example.com").First(&user)

func (*QueryBuilder) FirstOrCreate

func (qb *QueryBuilder) FirstOrCreate(dest interface{}, conds ...interface{}) error

FirstOrCreate finds the first record matching the conditions, or creates a new one if not found. This is a terminal method.

Parameters:

  • dest: Pointer to the struct where the result will be stored
  • conds: Optional conditions for the query

Returns an error if the operation fails or nil on success.

Example:

var user User
err := qb.Where("email = ?", "user@example.com").FirstOrCreate(&user)

func (*QueryBuilder) FirstOrInit

func (qb *QueryBuilder) FirstOrInit(dest interface{}, conds ...interface{}) error

FirstOrInit finds the first record matching the conditions, or initializes a new one if not found. This is a terminal method.

Parameters:

  • dest: Pointer to the struct where the result will be stored
  • conds: Optional conditions for the query

Returns an error if the operation fails or nil on success.

Example:

var user User
err := qb.Where("email = ?", "user@example.com").FirstOrInit(&user)

func (*QueryBuilder) ForKeyShare

func (qb *QueryBuilder) ForKeyShare() *QueryBuilder

ForKeyShare adds a FOR KEY SHARE clause to the query (PostgreSQL specific). This acquires a shared lock that blocks other transactions from acquiring exclusive locks but allows other key share and share locks.

Returns the QueryBuilder for method chaining.

Example:

qb.Where("id = ?", userID).ForKeyShare().First(&user) // PostgreSQL only

func (*QueryBuilder) ForNoKeyUpdate

func (qb *QueryBuilder) ForNoKeyUpdate() *QueryBuilder

ForNoKeyUpdate adds a FOR NO KEY UPDATE clause to the query (PostgreSQL specific). This acquires a weaker exclusive lock that doesn't block other transactions from acquiring key share locks on the same rows.

Returns the QueryBuilder for method chaining.

Example:

qb.Where("id = ?", userID).ForNoKeyUpdate().First(&user) // PostgreSQL only

func (*QueryBuilder) ForShare

func (qb *QueryBuilder) ForShare() *QueryBuilder

ForShare adds a FOR SHARE clause to the query for shared row-level locking. This allows other transactions to read the rows but prevents them from updating or deleting until the current transaction commits or rolls back.

Returns the QueryBuilder for method chaining.

Example:

qb.Where("id = ?", userID).ForShare().First(&user) // Shared lock for reading
qb.ForShare().Where("status = ?", "active").Find(&users) // Prevents updates but allows reads

func (*QueryBuilder) ForShareSkipLocked

func (qb *QueryBuilder) ForShareSkipLocked() *QueryBuilder

ForShareSkipLocked adds a FOR SHARE SKIP LOCKED clause to the query. This acquires shared locks but skips any rows that are already exclusively locked.

Returns the QueryBuilder for method chaining.

Example:

qb.Where("category = ?", "news").ForShareSkipLocked().Find(&articles)

func (*QueryBuilder) ForUpdate

func (qb *QueryBuilder) ForUpdate() *QueryBuilder

ForUpdate adds a FOR UPDATE clause to the query for exclusive row-level locking. This prevents other transactions from modifying the selected rows until the current transaction commits or rolls back.

Returns the QueryBuilder for method chaining.

Example:

qb.Where("id = ?", userID).ForUpdate().First(&user) // Locks the row for update
qb.ForUpdate().Where("status = ?", "pending").Find(&orders) // Locks all matching rows

func (*QueryBuilder) ForUpdateNoWait

func (qb *QueryBuilder) ForUpdateNoWait() *QueryBuilder

ForUpdateNoWait adds a FOR UPDATE NOWAIT clause to the query. This attempts to acquire exclusive locks but immediately fails if any target rows are already locked, instead of waiting.

Returns the QueryBuilder for method chaining.

Example:

qb.Where("id = ?", accountID).ForUpdateNoWait().First(&account)

func (*QueryBuilder) ForUpdateSkipLocked

func (qb *QueryBuilder) ForUpdateSkipLocked() *QueryBuilder

ForUpdateSkipLocked adds a FOR UPDATE SKIP LOCKED clause to the query. This acquires exclusive locks but skips any rows that are already locked, making it ideal for job queue processing where you want to avoid blocking.

Returns the QueryBuilder for method chaining.

Example:

qb.Where("status = ?", "pending").ForUpdateSkipLocked().Limit(10).Find(&jobs)
qb.ForUpdateSkipLocked().Where("processed = ?", false).First(&task)

func (*QueryBuilder) Group

func (qb *QueryBuilder) Group(query string) *QueryBuilder

Group adds a GROUP BY clause to the query. It is used to group rows with the same values into summary rows.

Parameters:

  • query: GROUP BY expression

Returns the QueryBuilder for method chaining.

Example:

qb.Group("status")
qb.Group("department, location")

func (*QueryBuilder) Having

func (qb *QueryBuilder) Having(query interface{}, args ...interface{}) *QueryBuilder

Having added a HAVING clause to the query. It is used to filter groups created by the GROUP BY clause.

Parameters:

  • query: HAVING condition with optional placeholders
  • args: Arguments for any placeholders in the query

Returns the QueryBuilder for method chaining.

Example:

qb.Group("department").Having("COUNT(*) > ?", 3)

func (*QueryBuilder) Joins

func (qb *QueryBuilder) Joins(query string, args ...interface{}) *QueryBuilder

Joins add a JOIN clause to the query. It performs an INNER JOIN by default.

Parameters:

  • query: JOIN condition string
  • args: Arguments for any placeholders in the query

Returns the QueryBuilder for method chaining.

Example:

qb.Joins("JOIN orders ON orders.user_id = users.id")

func (*QueryBuilder) Last

func (qb *QueryBuilder) Last(dest interface{}) error

Last finds the last record that matches the query conditions. This is a terminal method that executes the query and releases the mutex lock.

Parameters:

  • dest: Pointer to a struct where the result will be stored

Returns an error if no record is found or the query fails, nil on success.

Example:

var user User
err := qb.Where("department = ?", "Engineering").Order("joined_at ASC").Last(&user)

func (*QueryBuilder) LeftJoin

func (qb *QueryBuilder) LeftJoin(query string, args ...interface{}) *QueryBuilder

LeftJoin adds a LEFT JOIN clause to the query. It retrieves all records from the left table and matching records from the right table.

Parameters:

  • query: JOIN condition string without the "LEFT JOIN" prefix
  • args: Arguments for any placeholders in the query

Returns the QueryBuilder for method chaining.

Example:

qb.LeftJoin("orders ON orders.user_id = users.id")

func (*QueryBuilder) Limit

func (qb *QueryBuilder) Limit(limit int) *QueryBuilder

Limit sets the maximum number of records to return.

Parameters:

  • limit: Maximum number of records

Returns the QueryBuilder for method chaining.

Example:

qb.Limit(10) // Return at most 10 records

func (*QueryBuilder) MapRows

func (qb *QueryBuilder) MapRows(destSlice interface{}, mapFn func(*gorm.DB) error) error

MapRows executes a query and maps all rows into a destination slice using the provided mapping function. This provides a higher-level abstraction than working with raw rows, allowing for custom mapping logic while still handling the query execution and resource management automatically.

Parameters:

  • destSlice: The slice to populate with mapped rows (should be a pointer to a slice)
  • mapFn: A function that defines how to map rows from the database to your slice items

func (*QueryBuilder) Model

func (qb *QueryBuilder) Model(value interface{}) *QueryBuilder

Model specifies the model to use for the query. This is useful when the model can't be inferred from other methods.

Parameters:

  • value: Pointer to the model struct or its instance

Returns the QueryBuilder for method chaining.

Example:

qb.Model(&User{}).Where("active = ?", true).Count(&count)

func (*QueryBuilder) Not

func (qb *QueryBuilder) Not(query interface{}, args ...interface{}) *QueryBuilder

Not adds a NOT condition to the query. It negates the specified condition.

Parameters:

  • query: Condition string with optional placeholders or a map of conditions
  • args: Arguments for any placeholders in the query

Returns the QueryBuilder for method chaining.

Example:

qb.Not("status = ?", "deleted")

func (*QueryBuilder) Offset

func (qb *QueryBuilder) Offset(offset int) *QueryBuilder

Offset sets the number of records to skip. It is typically used with Limit for pagination.

Parameters:

  • offset: Number of records to skip

Returns the QueryBuilder for method chaining.

Example:

qb.Offset(20).Limit(10) // Skip 20 records and return the next 10

func (*QueryBuilder) OnConflict

func (qb *QueryBuilder) OnConflict(onConflict clause.OnConflict) *QueryBuilder

OnConflict adds an ON CONFLICT clause for UPSERT operations. This handles conflicts during INSERT operations by either updating existing records or ignoring conflicts.

Parameters:

  • onConflict: ON CONFLICT clause configuration

Returns the QueryBuilder for method chaining.

Example:

qb.OnConflict(clause.OnConflict{
    Columns:   []clause.Column{{Name: "email"}},
    DoUpdates: clause.AssignmentColumns([]string{"name", "updated_at"}),
}).Create(&user)

func (*QueryBuilder) Or

func (qb *QueryBuilder) Or(query interface{}, args ...interface{}) *QueryBuilder

Or adds an OR condition to the query. It combines with previous conditions using OR logic.

Parameters:

  • query: Condition string with optional placeholders or a map of conditions
  • args: Arguments for any placeholders in the query

Returns the QueryBuilder for method chaining.

Example:

qb.Where("status = ?", "active").Or("status = ?", "pending")

func (*QueryBuilder) Order

func (qb *QueryBuilder) Order(value interface{}) *QueryBuilder

Order adds an ORDER BY clause to the query. It is used to sort the result set.

Parameters:

  • value: ORDER BY expression

Returns the QueryBuilder for method chaining.

Example:

qb.Order("created_at DESC")
qb.Order("age ASC, name DESC")

func (*QueryBuilder) Pluck

func (qb *QueryBuilder) Pluck(column string, dest interface{}) (int64, error)

Pluck queries a single column and scans the results into a slice. This is a terminal method that executes the query and releases the mutex lock.

Parameters:

  • column: Name of the column to query
  • dest: Pointer to a slice where results will be stored

Returns:

  • int64: Number of rows found and processed
  • error: Error if the query fails, nil on success

Example:

var emails []string
rowsFound, err := qb.Where("department = ?", "Engineering").Pluck("email", &emails)
if err != nil {
    return err
}
fmt.Printf("Found %d email addresses\n", rowsFound)

func (*QueryBuilder) Preload

func (qb *QueryBuilder) Preload(query string, args ...interface{}) *QueryBuilder

Preload preloads associations for the query results. This is used to eagerly load related models to avoid N+1 query problems.

Parameters:

  • query: Name of the association to preload
  • args: Optional conditions for the preloaded association

Return the QueryBuilder for method chaining.

Example:

qb.Preload("Orders")
qb.Preload("Orders", "state = ?", "paid")

func (*QueryBuilder) QueryRow

func (qb *QueryBuilder) QueryRow() RowScanner

QueryRow executes a query expected to return a single row and returns a RowScanner for it. This method is optimized for queries that return exactly one row of data and provides a simplified interface for scanning the values from that row.

func (*QueryBuilder) QueryRows

func (qb *QueryBuilder) QueryRows() (RowsScanner, error)

QueryRows executes a query that returns multiple rows and returns a RowsScanner for them. This method provides an iterator-style interface for processing multiple rows returned by a query, allowing for efficient traversal of large result sets.

func (*QueryBuilder) Raw

func (qb *QueryBuilder) Raw(sql string, values ...interface{}) *QueryBuilder

Raw executes raw SQL as part of the query. It provides full SQL flexibility when needed.

Parameters:

  • SQL: Raw SQL statement with optional placeholders
  • values: Arguments for any placeholders in the SQL

Returns the QueryBuilder for method chaining.

Example:

qb.Raw("SELECT * FROM users WHERE created_at > ?", time.Now().AddDate(0, -1, 0))

func (*QueryBuilder) Returning

func (qb *QueryBuilder) Returning(columns ...string) *QueryBuilder

Returning adds a RETURNING clause to the query (PostgreSQL specific). This returns the specified columns from the modified rows in INSERT, UPDATE, or DELETE operations.

Parameters:

  • columns: Column names to return

Returns the QueryBuilder for method chaining.

Example:

qb.Returning("id", "created_at").Create(&user)
qb.Where("status = ?", "pending").Returning("*").Updates(map[string]interface{}{"status": "processed"})

func (*QueryBuilder) RightJoin

func (qb *QueryBuilder) RightJoin(query string, args ...interface{}) *QueryBuilder

RightJoin adds a RIGHT JOIN clause to the query. It retrieves all records from the right table and matching records from the left table.

Parameters:

  • query: JOIN condition string without the "RIGHT JOIN" prefix
  • args: Arguments for any placeholders in the query

Returns the QueryBuilder for method chaining.

Example:

qb.RightJoin("orders ON orders.user_id = users.id")

func (*QueryBuilder) Scan

func (qb *QueryBuilder) Scan(dest interface{}) error

Scan scans the result into the destination struct or slice. This is a terminal method that executes the query and releases the mutex lock.

Parameters:

  • dest: Pointer to the struct or slice where results will be stored

Returns an error if the query fails or nil on success.

Example:

var result struct{ Count int }
err := qb.Raw("SELECT COUNT(*) as count FROM users").Scan(&result)

func (*QueryBuilder) ScanRow

func (qb *QueryBuilder) ScanRow(dest interface{}) error

ScanRow is a convenience method to scan a single row directly into a struct. This is a higher-level alternative to QueryRow that automatically maps column values to struct fields based on naming conventions or field tags. It's useful when you need to map a row to a predefined data structure.

func (*QueryBuilder) Scopes

func (qb *QueryBuilder) Scopes(funcs ...func(*gorm.DB) *gorm.DB) *QueryBuilder

Scopes applies one or more scopes to the query. Scopes are reusable query conditions that can be applied to multiple queries.

Parameters:

  • funcs: One or more scope functions that modify the query

Returns the QueryBuilder for method chaining.

Example:

// Define scopes
func ActiveUsers(db *gorm.DB) *gorm.DB {
    return db.Where("active = ?", true)
}
func AdultUsers(db *gorm.DB) *gorm.DB {
    return db.Where("age >= ?", 18)
}

// Use scopes
qb.Scopes(ActiveUsers, AdultUsers).Find(&users)
qb.Scopes(ActiveUsers).Count(&count)

func (*QueryBuilder) Select

func (qb *QueryBuilder) Select(query interface{}, args ...interface{}) *QueryBuilder

Select specifies fields to be selected in the query. It corresponds to the SQL SELECT clause.

Parameters:

  • query: Field selection string or raw SQL expression
  • args: Arguments for any placeholders in the query

Returns the QueryBuilder for method chaining.

Example:

qb.Select("id, name, email")
qb.Select("COUNT(*) as user_count")

func (*QueryBuilder) Table

func (qb *QueryBuilder) Table(name string) *QueryBuilder

Table specifies the table name for the query. This overrides the default table name derived from the model.

Parameters:

  • name: Table name to use for the query

Returns the QueryBuilder for method chaining.

Example:

qb.Table("users_archive").Where("deleted_at IS NOT NULL").Find(&users)
qb.Table("custom_table_name").Count(&count)
qb.Table("user_stats").Select("department, COUNT(*) as count").Group("department").Scan(&stats)

func (*QueryBuilder) Unscoped

func (qb *QueryBuilder) Unscoped() *QueryBuilder

Unscoped disables the default scope for the query. This allows querying soft-deleted records or bypassing other default scopes. Commonly used with GORM's soft delete feature.

Returns the QueryBuilder for method chaining.

Example:

qb.Unscoped().Where("name = ?", "John").Find(&users) // Includes soft-deleted records
qb.Unscoped().Delete(&user) // Permanently deletes the record
qb.Unscoped().Count(&count) // Counts all records including soft-deleted

func (*QueryBuilder) Updates

func (qb *QueryBuilder) Updates(values interface{}) (int64, error)

Updates updates records that match the query conditions. This is a terminal method that executes the query and releases the mutex lock.

Parameters:

  • values: Map or struct with the fields to update

Returns:

  • int64: Number of rows affected by the update operation
  • error: Error if the update fails, nil on success

Example:

rowsAffected, err := qb.Where("expired = ?", true).Updates(map[string]interface{}{"active": false})
if err != nil {
    return err
}
fmt.Printf("Updated %d rows\n", rowsAffected)

func (*QueryBuilder) Where

func (qb *QueryBuilder) Where(query interface{}, args ...interface{}) *QueryBuilder

Where adds a WHERE condition to the query. Multiple Where calls are combined with AND logic.

Parameters:

  • query: Condition string with optional placeholders or a map of conditions
  • args: Arguments for any placeholders in the query

Returns the QueryBuilder for method chaining.

Example:

qb.Where("age > ?", 18)
qb.Where("status = ?", "active")

type RowScanner

type RowScanner interface {
	// Scan copies the column values from the current row into the values pointed to by dest.
	// The number of values in dest must match the number of columns in the row.
	Scan(dest ...interface{}) error
}

RowScanner provides an interface for scanning a single row of data. It abstracts the process of parsing column values into Go variables, allowing for efficient handling of individual rows returned from a query.

type RowsScanner

type RowsScanner interface {
	// Next prepares the next row for reading. It returns false when there are no more rows.
	Next() bool

	// Scan copies column values from the current row into the provided destination variables.
	Scan(dest ...interface{}) error

	// Close closes the rows iterator, releasing any associated resources.
	Close() error

	// Err returns any error encountered during iteration.
	Err() error
}

RowsScanner provides an interface for iterating through rows of data returned by a query. It extends RowScanner functionality with methods for navigation and error handling, allowing for efficient processing of result sets with multiple rows.

Jump to

Keyboard shortcuts

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