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.

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.