postgresql

package module
v0.0.0-...-111dbc0 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2021 License: Apache-2.0 Imports: 14 Imported by: 1

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Connection

type Connection interface {
	ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
	QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
	QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
}

type ConnectionManager

type ConnectionManager interface {
	io.Closer
	// Connection returns the current context's connection.
	// This can be a *sql.DB or if we are within a transaction, then an *sql.Tx
	Connection(ctx context.Context) (Connection, error)

	BeginTx(ctx context.Context) (context.Context, error)
	CommitTx(ctx context.Context) error
	RollbackTx(ctx context.Context) error
}
Example
package main

import (
	"context"

	"github.com/adamluzsi/frameless/postgresql"
)

func main() {
	connectionManager := postgresql.NewConnectionManager(`dsn`)
	defer connectionManager.Close()

	ctx := context.Background()

	c, err := connectionManager.Connection(ctx)
	if err != nil {
		panic(err)
	}

	_, err = c.ExecContext(ctx, `SELECT VERSION()`)
	if err != nil {
		panic(err)
	}
}
Output:

func NewConnectionManager

func NewConnectionManager(dsn string) ConnectionManager

type ListenNotifySubscriptionManager

type ListenNotifySubscriptionManager struct {
	T       interface{}
	Mapping Mapping

	MetaAccessor      MetaAccessor
	ConnectionManager ConnectionManager

	Listener             *pq.Listener
	DSN                  string
	ReconnectMinInterval time.Duration
	ReconnectMaxInterval time.Duration
	// contains filtered or unexported fields
}

func NewListenNotifySubscriptionManager

func NewListenNotifySubscriptionManager(T T, m Mapping, dsn string, cm ConnectionManager) *ListenNotifySubscriptionManager

func (*ListenNotifySubscriptionManager) Close

func (*ListenNotifySubscriptionManager) Init

func (sm *ListenNotifySubscriptionManager) Init() (rErr error)

Init will initialize the ListenNotifySubscriptionManager The ctx argument must represent a process lifetime level context.Context. Otherwise, context.Background() is expected for it.

func (*ListenNotifySubscriptionManager) ListenerEventCallback

func (sm *ListenNotifySubscriptionManager) ListenerEventCallback(_ pq.ListenerEventType, err error)

func (*ListenNotifySubscriptionManager) Notify

func (sm *ListenNotifySubscriptionManager) Notify(ctx context.Context, c Connection, event interface{}) error

func (*ListenNotifySubscriptionManager) PublishCreateEvent

func (*ListenNotifySubscriptionManager) PublishDeleteAllEvent

func (*ListenNotifySubscriptionManager) PublishDeleteByIDEvent

func (*ListenNotifySubscriptionManager) PublishUpdateEvent

func (*ListenNotifySubscriptionManager) SubscribeToCreatorEvents

func (*ListenNotifySubscriptionManager) SubscribeToDeleterEvents

func (*ListenNotifySubscriptionManager) SubscribeToUpdaterEvents

type Mapper

type Mapper struct {
	// Table is the entity's table name
	Table string
	// ID is the entity's id column name
	ID string
	// Columns hold the entity's column names
	Columns []string

	NewIDFn  func(ctx context.Context) (interface{}, error)
	ToArgsFn func(ptr interface{}) ([]interface{}, error)
	MapFn    iterators.SQLRowMapperFunc
}
Example
package main

import (
	"context"
	"time"

	"github.com/adamluzsi/frameless/iterators"
	"github.com/adamluzsi/frameless/postgresql"
)

func main() {
	type ExampleEntity struct {
		ID   int64
		Col1 int
		Col2 string
		Col3 bool
	}
	_ = postgresql.Mapper /* [ExampleEntity] */ {
		Table:   `"public"."entities"`,
		ID:      "entity_id",
		Columns: []string{"entity_id", "col1", "col2", "col3"},
		NewIDFn: func(ctx context.Context) (interface{}, error) {
			// a really bad way to make id,
			// but this is only an example
			return time.Now().UnixNano(), nil
		},
		ToArgsFn: func(ptr interface{}) ([]interface{}, error) {
			ent := ptr.(*ExampleEntity) // Go1.18 will solve this with generics
			return []interface{}{ent.ID, ent.Col1, ent.Col2, ent.Col3}, nil
		},
		MapFn: func(scanner iterators.SQLRowScanner, ptr interface{}) error {
			ent := ptr.(*ExampleEntity)
			return scanner.Scan(&ent.ID, &ent.Col1, &ent.Col2, &ent.Col3)
		},
	}
}
Output:

func (Mapper) ColumnRefs

func (m Mapper) ColumnRefs() []string

func (Mapper) IDRef

func (m Mapper) IDRef() string

func (Mapper) Map

func (m Mapper) Map(s iterators.SQLRowScanner, ptr interface{}) error

func (Mapper) NewID

func (m Mapper) NewID(ctx context.Context) (interface{}, error)

func (Mapper) TableRef

func (m Mapper) TableRef() string

func (Mapper) ToArgs

func (m Mapper) ToArgs(ptr interface{}) ([]interface{}, error)

type Mapping

type Mapping interface {
	// TableRef is the entity's postgresql table name.
	//   eg.:
	//     - "public"."table_name"
	//     - "table_name"
	//     - table_name
	//
	TableRef() string
	// IDRef is the entity's id column name, which can be used to access an individual record for update purpose.
	IDRef() string
	// ColumnRefs are the table's column names.
	// The order of the column names related to Row mapping and query argument passing.
	ColumnRefs() []string
	// NewID creates a stateless entity id that can be used by CREATE operation.
	// Serial and similar id solutions not supported without serialize transactions.
	NewID(context.Context) (interface{}, error)
	// ToArgs convert an entity ptr to a list of query argument that can be used for CREATE or UPDATE purpose.
	ToArgs(ptr interface{}) ([]interface{}, error)
	iterators.SQLRowMapper
}

type MetaAccessor

type MetaAccessor struct{}

func (MetaAccessor) LookupMeta

func (ma MetaAccessor) LookupMeta(ctx context.Context, key string, ptr interface{}) (_found bool, _err error)

func (MetaAccessor) SetMeta

func (ma MetaAccessor) SetMeta(ctx context.Context, key string, value interface{}) (context.Context, error)

type Storage

type Storage struct {
	T                   interface{}
	Mapping             Mapping
	ConnectionManager   ConnectionManager
	SubscriptionManager SubscriptionManager
	MetaAccessor
}

Storage is a frameless external resource supplier to store a certain entity type. The Storage supplier itself is a stateless entity.

SRP: DBA

Example
package main

import (
	"context"
	"math/rand"
	"os"

	"github.com/adamluzsi/frameless/iterators"
	"github.com/adamluzsi/frameless/postgresql"
)

func main() {
	type Entity struct {
		ID    int `ext:"ID"`
		Value string
	}

	mapping := postgresql.Mapper{
		Table:   "entities",
		ID:      "id",
		Columns: []string{`id`, `value`},
		NewIDFn: func(ctx context.Context) (interface{}, error) {
			// only example, don't do this in production code.
			return rand.Int(), nil
		},
		ToArgsFn: func(ptr interface{}) ([]interface{}, error) {
			ent := ptr.(*Entity)
			return []interface{}{ent.ID, ent.Value}, nil
		},
		MapFn: func(s iterators.SQLRowScanner, ptr interface{}) error {
			ent := ptr.(*Entity)
			return s.Scan(&ent.ID, &ent.Value)
		},
	}

	stg := postgresql.NewStorageByDSN(Entity{}, mapping, os.Getenv("DATABASE_URL"))
	defer stg.Close()
}
Output:

func NewStorageByDSN

func NewStorageByDSN(T interface{}, m Mapping, dsn string) *Storage

func (*Storage) BeginTx

func (pg *Storage) BeginTx(ctx context.Context) (context.Context, error)

func (*Storage) Close

func (pg *Storage) Close() error

func (*Storage) CommitTx

func (pg *Storage) CommitTx(ctx context.Context) error

func (*Storage) Create

func (pg *Storage) Create(ctx context.Context, ptr interface{}) (rErr error)

func (*Storage) DeleteAll

func (pg *Storage) DeleteAll(ctx context.Context) (rErr error)

func (*Storage) DeleteByID

func (pg *Storage) DeleteByID(ctx context.Context, id interface{}) (rErr error)

func (*Storage) FindAll

func (pg *Storage) FindAll(ctx context.Context) frameless.Iterator

func (*Storage) FindByID

func (pg *Storage) FindByID(ctx context.Context, ptr, id interface{}) (bool, error)

func (*Storage) RollbackTx

func (pg *Storage) RollbackTx(ctx context.Context) error

func (*Storage) SubscribeToCreatorEvents

func (pg *Storage) SubscribeToCreatorEvents(ctx context.Context, s frameless.CreatorSubscriber) (frameless.Subscription, error)

func (*Storage) SubscribeToDeleterEvents

func (pg *Storage) SubscribeToDeleterEvents(ctx context.Context, s frameless.DeleterSubscriber) (frameless.Subscription, error)

func (*Storage) SubscribeToUpdaterEvents

func (pg *Storage) SubscribeToUpdaterEvents(ctx context.Context, s frameless.UpdaterSubscriber) (frameless.Subscription, error)

func (*Storage) Update

func (pg *Storage) Update(ctx context.Context, ptr interface{}) (rErr error)

type SubscriptionManager

type SubscriptionManager interface {
	io.Closer
	PublishCreateEvent(ctx context.Context, e frameless.CreateEvent) error
	PublishUpdateEvent(ctx context.Context, e frameless.UpdateEvent) error
	PublishDeleteByIDEvent(ctx context.Context, e frameless.DeleteByIDEvent) error
	PublishDeleteAllEvent(ctx context.Context, e frameless.DeleteAllEvent) error
	SubscribeToCreatorEvents(ctx context.Context, s frameless.CreatorSubscriber) (frameless.Subscription, error)
	SubscribeToUpdaterEvents(ctx context.Context, s frameless.UpdaterSubscriber) (frameless.Subscription, error)
	SubscribeToDeleterEvents(ctx context.Context, s frameless.DeleterSubscriber) (frameless.Subscription, error)
}
Example
package main

import (
	"os"

	"github.com/adamluzsi/frameless/postgresql"
)

func main() {
	type ExampleEntity struct {
		ID string `ext:"id"`
	}

	connectionManager := postgresql.NewConnectionManager(os.Getenv(`DATABASE_URL`))
	mapping := postgresql.Mapper{ /* real mapping data here */ }

	subscriptionManager := postgresql.NewListenNotifySubscriptionManager(ExampleEntity{}, mapping, os.Getenv("DATABASE_URL"), connectionManager)
	defer subscriptionManager.Close()
}
Output:

type T

type T = interface{}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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