package module
Version: v0.0.0-...-3cd0c2b Latest Latest

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

Go to latest
Published: Sep 11, 2021 License: MIT Imports: 5 Imported by: 0


Go package strongo/db

Database abstraction layer (DAL) in Go language

Build Status Go Report Card GoDoc

There are 4 main purposes for the package:

  1. To abstract work with data storage so underlying storage engine can be changed.

  2. To allow write less code that is more readable.

  3. To allow easialy add logging & hooks for tx/insert/get/query/update/delete operations across app. Think about preventing updates made outside of transaction or logging automatically what properties have changed.

  4. Allow to write unit tests without dependency on specific implementation. (do no compile AppEngine packages for examples)

The main abstraction is done though interface EntityHolder:

type EntityHolder interface {
	TypeOfID() TypeOfID            // Either `string`, `int`, or `complex`
	Kind() string                  // Defines `table` name of the entity
	NewEntity() interface{}        // Used for `get` operations to create emtity to fill with values.
	Entity() interface{}           // Entity with fields to be stored to DB (without ID)
	SetEntity(entity interface{})  //
	IntID() int64                  // Returns ID for entities identified by integer value
	StrID() string                 // Returns ID for entities identified by string value
	SetIntID(id int64)             // Sets integer ID for entities identified by integer value
	SetStrID(id string)            // Sets string ID for entities identified by string value

All methods are working with the EntityHolder.

The Database interface defines an interface to a storage that should be implemented by a specific driver. This repo contains implementation for Google AppEngine Datastore. Contributions for other engines are welcome. If the db driver does not support some of the operations it must return ErrNotSupported.

type Database interface {

where for example the Getter & MultiGetter interfaces are defined as:

type Getter interface {
	Get(c context.Context, entityHolder EntityHolder) error

type MultiGetter interface {
	GetMulti(c context.Context, entityHolders []EntityHolder) error

Note that getters are populating entities in place through calling SetEntity(entity interface{}) method.

Originally developed to support work with Google AppEngine Datastore it takes into account its specifics. This should work well for other key-value storages as well.

Used by

This package is used in production by:

Frameworks that utilise this strongo/db package




This section is empty.


View Source
var ErrNotSupported = errors.New("not supported")

ErrNotSupported - return this if db driver does not support requested operation. (for example no support for transactions)

View Source
var (
	// ErrRecordNotFound is returned when a DB record is not found
	ErrRecordNotFound = errors.New("Record not found")


func GetNonTransactionalContext

func GetNonTransactionalContext(ctx context.Context) context.Context

GetNonTransactionalContext returns non transaction context (e.g. parent of transactional context) TODO: This is can be dangerous if child context creates a new context with a deadline for example

func GetRecordKeyPath

func GetRecordKeyPath(key RecordKey) string

func GetRecordKind

func GetRecordKind(key RecordKey) string

func GetTransaction

func GetTransaction(ctx context.Context) interface{}

GetTransaction returns original transaction object

func InsertWithRandomID

func InsertWithRandomID(
	c context.Context,
	r Record,
	generateID IDGenerator,
	attempts int,
	exists func(RecordKey) error,
	insert func(Record) error,
) error

func IsNotFound

func IsNotFound(err error) bool

IsNotFound check if underlying error is ErrRecordNotFound

func NewContextWithTransaction

func NewContextWithTransaction(ctx context.Context, tx interface{}) context.Context

NewContextWithTransaction stores transaction and original context into a transactional context

func NewErrNotFoundByKey

func NewErrNotFoundByKey(record Record, cause error) error

NewErrNotFoundByKey creates an error that indicates that entity was not found by ID


type Changes

type Changes struct {
	// contains filtered or unexported fields

Changes accumulates DB changes

func (Changes) EntityHolders

func (changes Changes) EntityHolders() (entityHolders []Record)

EntityHolders returns list of entity holders

func (*Changes) FlagAsChanged

func (changes *Changes) FlagAsChanged(record Record)

FlagAsChanged flags a record as changed

func (Changes) HasChanges

func (changes Changes) HasChanges() bool

HasChanges returns true if there are changes

func (Changes) IsChanged

func (changes Changes) IsChanged(entityHolder Record) bool

IsChanged returns true if entity changed

type Database

type Database interface {

Database is an interface that define a DB provider

type Deleter

type Deleter interface {
	Delete(ctx context.Context, key RecordKey) error

Deleter is an interface that describe DB provider that can delete a single record by key

type EntityLoader

type EntityLoader interface {
	Load([]Property) error

EntityLoader loads properties to struct

type EntitySaver

type EntitySaver interface {
	Save() ([]Property, error)

EntitySaver dumps struct to properties

type ErrDuplicateUser

type ErrDuplicateUser struct {
	// TODO: Should it be moved out of this package to strongo/app/user?
	SearchCriteria   string
	DuplicateUserIDs []int64

ErrDuplicateUser indicates there is a duplicate user // TODO: move to strongo/app?

func (ErrDuplicateUser) Error

func (err ErrDuplicateUser) Error() string

Error implements error interface

type ErrNotFoundByKey

type ErrNotFoundByKey interface {
	Key() RecordKey
	Cause() error

ErrNotFoundByKey indicates error was not found by ID

type Getter

type Getter interface {
	Get(ctx context.Context, record Record) error

Getter is an interface that describe DB provider that can get a single record by key

type IDGenerator

type IDGenerator = func(ctx context.Context, record Record) error

type InsertOption

type InsertOption func(options *insertOptions)

func WithIDGenerator

func WithIDGenerator(idGenerator IDGenerator) InsertOption

func WithRandomStringID

func WithRandomStringID(length int) InsertOption

type InsertOptions

type InsertOptions interface {
	IDGenerator() IDGenerator

func NewInsertOptions

func NewInsertOptions(opts ...InsertOption) InsertOptions

type Inserter

type Inserter interface {
	Insert(c context.Context, record Record, options InsertOptions) error

Inserter is an interface that describe DB provider that can insert a single entity with a specific or random ID

type MultiDeleter

type MultiDeleter interface {
	DeleteMulti(ctx context.Context, keys []RecordKey) error

type MultiGetter

type MultiGetter interface {
	GetMulti(ctx context.Context, records []Record) error

MultiGetter is an interface that describe DB provider that can get multiple records at once (batch mode)

type MultiSetter

type MultiSetter interface {
	SetMulti(ctx context.Context, records []Record) error

MultiSetter is an interface that describe DB provider that can set multiple records at once (batch mode)

type MultiUpdater

type MultiUpdater interface {
	UpdateMulti(c context.Context, records []Record) error

MultiUpdater is an interface that describe DB provider that can update multiple records at once (batch mode)

type Property

type Property struct {
	Name    string
	Value   interface{}
	NoIndex bool

Property hold property name, value & flag to index

type RandomStringOptions

type RandomStringOptions interface {
	Length() int

type Record

type Record interface {
	Key() RecordKey
	Data() Validatable
	SetData(data Validatable)
	Validate() error

Record is an interface a struct should satisfy to comply with "strongo/db" library

func CreateEntityHoldersWithIntIDs

func CreateEntityHoldersWithIntIDs(ids []int64, newRecord func() RecordWithIntID) (records []Record)

func NewRecord

func NewRecord(key RecordKey, data Validatable) Record

type RecordKey

type RecordKey = []RecordRef

RecordKey represents a full path to a given record (1 item in case of root recordset)

func NewRecordKey

func NewRecordKey(refs ...RecordRef) RecordKey

NewRecordKey creates a new record key from a sequence of record's references

type RecordRef

type RecordRef struct {
	Kind string      `json:"kind"`
	ID   interface{} `json:"id"` // Usually string or int

RecordRef hold a reference to a single record within a root or nested recordset.

type RecordWithIntID

type RecordWithIntID interface {
	GetID() int64
	SetIntID(id int64)

type RecordWithStrID

type RecordWithStrID interface {
	GetID() string
	SetStrID(id string)

type Session

Session defines interface

type Setter

type Setter interface {
	Set(ctx context.Context, record Record) error

Setter is an interface that describe DB provider that can set a single record by key

type Transaction

type Transaction interface {

type TransactionCoordinator

type TransactionCoordinator interface {
		ctx context.Context,
		f func(ctx context.Context, tx Transaction) error,
		options ...TransactionOption,
	) error

TransactionCoordinator provides methods to work with transactions

type TransactionOption

type TransactionOption func(options *transactionOptions)

func WithCrossGroup

func WithCrossGroup() TransactionOption

func WithPassword

func WithPassword(password string) TransactionOption

func WithReadonly

func WithReadonly() TransactionOption

type TransactionOptions

type TransactionOptions interface {
	IsReadonly() bool
	IsCrossGroup() bool
	Password() string

func NewTransactionOptions

func NewTransactionOptions(opts ...TransactionOption) TransactionOptions

type TypeOfID

type TypeOfID int

TypeOfID represents type of ID: IsComplexID, IsStringID, IsIntID

type Updater

type Updater interface {
	Update(ctx context.Context, record Record) error

Updater is an interface that describe DB provider that can update a single EXISTING record by a key

type Upserter

type Upserter interface {
	Upsert(ctx context.Context, record Record) error

Upserter is an interface that describe DB provider that can upsert a single record by key

type Validatable

type Validatable interface {
	Validate() error

func VoidData

func VoidData() Validatable


Path Synopsis

Jump to

Keyboard shortcuts

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