postgres

package module
v0.0.0-...-bafa4fe Latest Latest
Warning

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

Go to latest
Published: Sep 2, 2018 License: MIT Imports: 5 Imported by: 0

README

gokv/postgres

GoDoc Build Status

A reflectionless gokv/store PostgreSQL client.

This package is not ready for production use.


The aim of this package is to provide an idiomatic Go API to the SQL persistence. The data is accepted in a key/value format, where the value implements JSON marshaler/unmarshaler, and is persisted as JSONb.

A typical approach to database abstraction is the ORM (Object-Relational Mapper): a piece of software that maps your domain models to some SQL code. In this case, the actual mapping functions are defined by the consumer: the persisted types need to provide an explicit implementation of MarhalJSON and UnmarshalJSON.

Here is how the usage experience was designed:

// Instantiate a new PostgreSQL store
s, _ = postgres.New(db, "table_name")

// store defines the methods required in this function, or in this package.
type store interface {
  Set(ctx context.Context, id string, v json.Marshaler) error
}

// SaveNewBook accepts the postgres.Store as a locally-defined interface.
// Later on, another Store implementation could be passed instead, for example
// using Redis.
//
// The `book` type must explicitly implement `json.Marshaler`
func SaveNewBook(s store, newBook book) error {
  return s.Set(req.Context(), uuid.New(), newBook)
}

Requisites

  • Go v1.8 (for context.Context integration in the stdlib)
  • Postgres v9.5 (first version to provide upsert via the ON CONFLICT clause)

Use

The New initialisator prepares SQL statements against the given *sql.DB, and exposes methods that act upon those prepared statements.

Here's how to use it:

package main

import (
	"context"
	"database/sql"
	"encoding/json"
	"log"
	"time"

	"github.com/gokv/postgres"
	"github.com/google/uuid"
	_ "github.com/lib/pq"
)

// User is the type to persist
type User struct {
	Firstname string
	Lastname  string
	CreatedAt time.Time
}

// The type has to explicitly implement json.Marshaler
func (u User) MarshalJSON() ([]byte, error) {
	return json.Marshal(struct {
		Firstname string    `json:"firstname"`
		Lastname  string    `json:"lastname"`
		CreatedAt time.Time `json:"created_at"`
	}{
		Firstname: u.Firstname,
		Lastname:  u.Lastname,
		CreatedAt: u.CreatedAt,
	})
}

func main() {
	// Create the connection abstraction
	db, err := sql.Open("postgres", "host=postgres user=username password=secret dbname=store")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// Pass the *sql.DB and the name of the table the Store will be bound to.
	// WithCreateTable is the option for creating the table if it doesn't exist
	// already.
	s, err := postgres.New(db, "users", WithCreateTable)
	if err != nil {
		log.Fatal(err)
	}
	defer s.Close()

	// Add a new entry
	id, err := s.Add(context.Context(), User{
		Firstname: "Giacomo",
		Lastname:  "Leopardi",
		CreatedAt: time.Now(),
	})
	if err != nil {
		log.Fatal(err)
	}

  fmt.Println("The new user's unique ID is %q", id)
}

Roadmap

  • Basic CRUD
  • Search

Documentation

Overview

Package postgres defines Store, a Postgres client that partially implements the Store interface defined in "github.com/gokv/store".

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func WithCreateTable

func WithCreateTable(db *sql.DB, tablename string) error

Types

type Option

type Option func(db *sql.DB, tablename string) error

type Store

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

Store holds the SQL statements prepared against a Postgresql table. Initialise with New.

func New

func New(db *sql.DB, tablename string, options ...Option) (s Store, err error)

New creates a table of name tablename if it does not exist, and prepares statements against it. The table has two columms: "k" is the TEXT primary key and "v" is a JSONb column holding the values.

func (Store) Add

func (s Store) Add(ctx context.Context, v json.Marshaler) (string, error)

Add persists a new object and returns its unique UUIDv4 key. Err is non-nil in case of failure.

func (Store) Close

func (s Store) Close() (err error)

Close releases the resources associated with the Store. Returns the first error encountered while closing the prepared statements.

func (Store) Delete

func (s Store) Delete(ctx context.Context, k string) error

func (Store) Get

func (s Store) Get(ctx context.Context, k string, v json.Unmarshaler) (bool, error)

Get retrieves a new item by key and unmarshals it into v, or returns false if not found. Err is non-nil in case of failure.

func (Store) GetAll

func (s Store) GetAll(ctx context.Context, c store.Collection) error

GetAll appends to c every item in the store. Err is non-nil in case of failure.

func (Store) Ping

func (s Store) Ping(ctx context.Context) error

func (Store) Set

func (s Store) Set(ctx context.Context, k string, v json.Marshaler) error

func (Store) Update

func (s Store) Update(ctx context.Context, k string, v json.Marshaler) error

Update assigns the given value to the given key, if it exists. Err is non-nil if the key was not already present, or in case of failure.

Jump to

Keyboard shortcuts

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