Skip to content

Simplifies working with the pgx library, providing convenient scanning of nested structures.

License

Notifications You must be signed in to change notification settings

Arlandaren/pgxWrappy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PgxWrappy

Go Reference Go Report Card License: MIT Go Version Issues GitHub Last Commit GitHub Contributors Repo Size GitHub Stars GitHub Forks

PostgreSQL Wrapper Library for Convenient Scanning of Nested Structures

This library provides a convenient wrapper around the pgx library developed by Jack Christensen. It simplifies database interactions with PostgreSQL by allowing easy scanning of query results into nested Go structures and slices.

If you've ever encountered the inconvenience of scanning and retrieving lists with pgx, this tool allows you to fully enjoy the pgx library by simplifying these operations.

Key Features

  • Easy Scanning into Nested Structures: Automatically maps SQL query results to Go structs, including nested structs.
  • Convenient Handling of Slices: Supports scanning multiple rows into slices of structs or pointers to structs.
  • Transaction Support: Provides wrappers for transactional operations with methods for beginning, committing, and rolling back transactions.
  • Integration with pgx: Built on top of the high-performance pgx PostgreSQL driver, leveraging its robust features and reliability.

And even Jacks has mentioned this lib here.

Table of Contents


Documentation can be found here.


Installation

To use this library, you need to have Go installed and set up. Import the package into your project:

go get -u github.com/Arlandaren/pgxWrappy

Usage

import package

import "github.com/Arlandaren/pgxWrappy/pkg/postgres"

Initializing the Wrapper

First, you need to initialize a connection pool using pgxpool and then create a new wrapper instance.

import (
    "context"
    "github.com/jackc/pgx/v5/pgxpool"
    "github.com/Arlandaren/pgxWrappy/pkg/postgres"
)

func main() {
    ctx := context.Background()
    pool, err := pgxpool.New(ctx, "postgres://username:password@localhost:5432/database")
    if err != nil {
        // Handle error
    }
    dbWrapper := pgxwrappy.NewWrapper(pool)
    // Use dbWrapper for database operations
}

Executing Queries

You can execute queries using the QueryRow, Query, and Exec methods, which are wrappers around the corresponding pgx methods.

// Executing a query that returns a single row
row := dbWrapper.QueryRow(ctx, "SELECT id, name FROM users WHERE id=$1", userID)

// Executing a query that returns multiple rows
rows, err := dbWrapper.Query(ctx, "SELECT id, name FROM users")

// Executing a command that doesn't return rows
_, err := dbWrapper.Exec(ctx, "UPDATE users SET name=$1 WHERE id=$2", newName, userID)

Scanning into Structs

Get Method

The Get method executes a query that is expected to return a single row and scans the result into a struct.

type User struct {
    ID   int    `db:"id"`
    Name string `db:"name"`
}

var user User
err := dbWrapper.Get(ctx, &user, "SELECT id, name FROM users WHERE id=$1", userID)
if err != nil {
    // Handle error
}
// Use the 'user' struct

Select Method

The Select method executes a query that returns multiple rows and scans the results into a slice of structs.

var users []User
err := dbWrapper.Select(ctx, &users, "SELECT id, name FROM users")
if err != nil {
    // Handle error
}
// Use the 'users' slice

Transactions

You can perform transactional operations using the Begin, BeginTx, Commit, and Rollback methods.

txWrapper, err := dbWrapper.Begin(ctx)
if err != nil {
    // Handle error
}

defer func() {
    if err != nil {
        txWrapper.Rollback(ctx)
    } else {
        txWrapper.Commit(ctx)
    }
}()

// Perform transactional operations using txWrapper
err = txWrapper.Exec(ctx, "UPDATE accounts SET balance=balance-$1 WHERE id=$2", amount, fromAccountID)
if err != nil {
    return err
}

err = txWrapper.Exec(ctx, "UPDATE accounts SET balance=balance+$1 WHERE id=$2", amount, toAccountID)
if err != nil {
    return err
}

Field Tag Naming

Note: To ensure correct scanning of query results into your structs, it's important to use the db struct tags to match the column names in your database. The tags should correspond exactly to the column names or use appropriate mapping if the names differ.

type User struct {
    ID        int    `db:"id"`
    FirstName string `db:"first_name"`
    LastName  string `db:"last_name"`
    Email     string `db:"email"`
}

For nested structs, the field tags are used to flatten the structure during scanning.

type Address struct {
    Street  string `db:"street"`
    City    string `db:"city"`
    ZipCode string `db:"zip_code"`
}

type User struct {
    ID      int     `db:"id"`
    Name    string  `db:"name"`
    Address Address `db:"-"`
}

In your SQL query, you should alias the columns appropriately:

SELECT
    id,
    name,
    street,
    city,
    zip_code
FROM users

This ensures that the scanning process correctly maps the SQL result columns to the fields in your nested structs.

  • It is also possible to give a tag db:"address", then the expected columns in the query would be: address_street, address_city, address_zip_code

Use the way that suits your situataion.

Why Choose pgx and pgxWrappy

When working with PostgreSQL in Go, developers have several driver options to choose from. pgx stands out among other drivers for several reasons, and pgxWrappy addresses some of the common inconveniences developers face.

Brief Comparison with Other PostgreSQL Drivers

database/sql Standard Library

  • Description: Go's standard library interface for SQL databases.
  • Pros:
    • Familiar interface for Go developers.
    • Supports multiple database backends.
  • Cons:
    • Requires driver-specific implementations for full PostgreSQL features.
    • Less performant due to generalized abstractions.
    • Limited support for PostgreSQL-specific data types and features.
    • Inconvenient Scanning: Requires manual scanning of rows into variables, leading to verbose and repetitive code.

pq Driver

  • Description: Pure Go driver for PostgreSQL, compatible with database/sql.
  • Pros:
    • Simple and reliable for basic operations.
    • Widely used and tested.
  • Cons:
    • No longer actively developed with new features.
    • Limited performance optimizations.
    • Doesn't support advanced PostgreSQL features out of the box.
    • Inefficient Scanning: Similar to database/sql, scanning rows can be cumbersome and boilerplate-heavy.

pgx Driver

  • Description: High-performance PostgreSQL driver and toolkit for Go, developed by Jack Christensen.
  • Pros:
    • Best-in-Class Performance: Optimized for speed and efficiency.
    • Full PostgreSQL Feature Support: Access to advanced data types and protocols.
    • Active Development: Regular updates and community support.
    • Flexibility: Can be used with or without database/sql.
  • Cons:
    • Slightly steeper learning curve due to extensive features.
    • Inconvenient Scanning of Nested Structures: While pgx is powerful, scanning query results into complex nested structs or slices requires manual code and can be cumbersome.

Conclusion

pgx is the best option for Go developers working with PostgreSQL, offering superior performance, comprehensive feature support, and active maintenance.

By using pgx in conjunction with pgxWrappy, you further enhance your development experience:

  • Ease of Development: Simplified scanning of query results into nested structures without boilerplate code.
  • Enhanced Productivity: Focus on application logic rather than handling complex data mappings.
  • High Performance: Leverage pgx's speed while enjoying a more convenient API.
  • Seamless Transactions: Intuitive methods for managing database transactions.

Example Usage with pgxWrappy:

import (
    "context"
    "github.com/jackc/pgx/v5/pgxpool"
    "github.com/Arlandaren/pgxWrappy/pkg/postgres"
)

func main() {
    ctx := context.Background()
    pool, err := pgxpool.New(ctx, "postgres://username:password@localhost:5432/database")
    if err != nil {
        // Handle error
    }
    dbWrapper := pgxwrappy.NewWrapper(pool)
    // Use dbWrapper for database operations

    // And other methods see above.
}

By choosing pgx paired with pgxWrappy, you embrace the most efficient and developer-friendly tools for PostgreSQL in Go. This combination allows you to fully enjoy the capabilities of pgx, making your database interactions smoother and more effective.


If you've ever encountered the inconvenience of scanning and retrieving lists with pgx, this tool allows you to fully enjoy the pgx library by simplifying these operations. By focusing on convenient scanning of nested structures and slices, this library aims to make database operations in Go more straightforward and efficient. It addresses common pain points that developers face when dealing with database interactions, especially the boilerplate code required for scanning query results into complex data structures.

Using this library, you can reduce code redundancy, improve readability, and maintain high performance in your applications. It's an excellent choice for developers who need more than what the standard library offers but prefer to avoid the overhead of a full ORM.


Note: This library builds upon the pgx PostgreSQL driver for Go, developed by Jack Christensen. Special thanks to him for creating and maintaining such a high-performance and feature-rich driver.


Contributing

Contributions are welcome! If you find a bug or want to add a feature, please open an issue or submit a pull request on GitHub.


License

This project is licensed under the MIT License. See the LICENSE file for details.


By integrating pgxWrappy into your projects, you streamline your database interactions and harness the full power of pgx with added convenience. Give it a try and experience more efficient and enjoyable database programming in Go, just take a first step


About

Simplifies working with the pgx library, providing convenient scanning of nested structures.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages