Giter VIP home page Giter VIP logo

pmx's Introduction

pmx

Golang data mapping library for postgres and pgx.

Install

go get -u github.com/wcamarao/pmx

Features

  • Simple data mapping with struct tags
  • Explicit by design, no magic or conventions
  • Select database records into an annotated struct or slice
  • Insert and update database records from an annotated struct
  • Compatible with pgx Exec/Query interface i.e. pgxpool.Pool, pgx.Conn, pgx.Tx
  • Support transient fields and auto generated values

Data Mapping

Given the following table:

create table events (
    id uuid primary key,
    recorded_at timestamptz
);

Annotate a data model with struct tags:

type Event struct {
    ID         string    `db:"id" table:"events"`
    RecordedAt time.Time `db:"recorded_at"`
    Transient  string    // ignored by pmx
    transient  string    // ignored by pmx
}
  • The first struct field must be annotated with table for insert and update operations
  • Struct fields annotated with db must be exported
  • Transient fields can be optionally exported

Insert

Always provide a struct pointer.

type Event struct {
    ID         string    `db:"id" table:"events"`
    RecordedAt time.Time `db:"recorded_at"`
}

func main() {
    ctx := context.Background()

    conn, err := pgx.Connect(ctx, "postgresql://...")
    if err != nil {
        panic(err)
    }
    defer conn.Close(ctx)

    event := Event{
        ID:         "a1eff19b-4624-46c6-9e09-5910e7b2938d",
        RecordedAt: time.Now(),
    }

    // Generated query: insert into events (id, recorded_at) values ($1, $2)
    _, err = pmx.Insert(ctx, conn, &event)
    if err != nil {
        panic(err)
    }

    fmt.Printf("%+v\n", event)
}

Select into struct

Always provide a struct pointer.

Selecting into a struct will error with pgx.ErrNoRows if an empty dataset is returned from the query.

type Event struct {
    ID         string    `db:"id" table:"events"`
    RecordedAt time.Time `db:"recorded_at"`
}

func main() {
    ctx := context.Background()

    conn, err := pgx.Connect(ctx, "postgresql://...")
    if err != nil {
        panic(err)
    }
    defer conn.Close(ctx)

    var event Event
    err = pmx.Select(ctx, conn, &event, "select * from events where id = $1", "a1eff19b-4624-46c6-9e09-5910e7b2938d")
    if errors.Is(err, pgx.ErrNoRows) {
        panic("event not found")
    }
    if err != nil {
        panic(err)
    }

    fmt.Printf("%+v\n", event)
}

Select into slice

Always provide a slice pointer. The underlying slice type must be a struct pointer.

Selecting into a slice won't error if an empty dataset is returned from the query.

type Event struct {
    ID         string    `db:"id" table:"events"`
    RecordedAt time.Time `db:"recorded_at"`
}

func main() {
    ctx := context.Background()

    conn, err := pgx.Connect(ctx, "postgresql://...")
    if err != nil {
        panic(err)
    }
    defer conn.Close(ctx)

    var events []*Event
    err = pmx.Select(ctx, conn, &events, "select * from events limit 3")
    if err != nil {
        panic(err)
    }
    if len(events) == 0 {
        panic("no events found")
    }

    fmt.Printf("%+v\n", events)
}

Update

Always provide a struct pointer.

The last argument UpdateOptions specifies:

  • Set: explicit struct fields to be updated
  • By: explicit struct fields to be matched by equality in the where clause
type Event struct {
    ID         string    `db:"id" table:"events"`
    RecordedAt time.Time `db:"recorded_at"`
}

func main() {
    ctx := context.Background()

    conn, err := pgx.Connect(ctx, "postgresql://...")
    if err != nil {
        panic(err)
    }
    defer conn.Close(ctx)

    event := Event{
        ID:         "a1eff19b-4624-46c6-9e09-5910e7b2938d",
        RecordedAt: time.Now(),
    }

    // Generated query: update events set recorded_at = $1 where id = $2
    _, err = pmx.Update(ctx, conn, &event, &pmx.UpdateOptions{
        Set: []string{"RecordedAt"},
        By:  []string{"ID"},
    })
    if err != nil {
        panic(err)
    }

    fmt.Printf("%+v\n", event)
}

Auto Generated Values

Given the following table with an auto generated value, e.g. serial/sequence:

create table events (
    id bigserial primary key,
    recorded_at timestamptz
);

Annotate the ID struct field with a generated:"auto" struct tag:

type Event struct {
    ID         string    `db:"id" generated:"auto" table:"events"`
    RecordedAt time.Time `db:"recorded_at"`
}

The id column will be excluded from insert values and update set statements.

ErrInvalidRef

The error pmx.ErrInvalidRef ("invalid ref") means you provided an invalid pointer reference.

pmx's People

Contributors

wcamarao avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.