data

package module
v0.32.0 Latest Latest
Warning

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

Go to latest
Published: Jun 21, 2026 License: Apache-2.0 Imports: 3 Imported by: 10

README

Data 📚

GoDoc Version Build Status Go Report Card Codecov

Swappable Database Adapters for Go

This library provides a common interface for making simple database calls. The goal of this package is to provide simple CRUD operations only, so each database will support many advanced features that are not available through this library. Other modules (such as data-mongo and data-mock) implement specific database adapters.

The "Object" interface

The data library works with any object that implements the Object interface. To implement this quickly in existing data models, you can just attach the journal.Journal object to your domain objects, and most of your work is already done.

// Object defines all of the methods that a domain object must provide to the data library
type Object interface {

    // ID returns the primary key of the object
    ID() string

    // Created and Updated return the Unix epoch (milliseconds) when the object was created/updated
    Created() int64
    Updated() int64

    // IsNew returns TRUE if the object has not yet been saved to the database
    IsNew() bool

    // IsDeleted returns TRUE if the object has been virtually deleted
    IsDeleted() bool

    // SetCreated stamps the CreateDate and UpdateDate of the object, and adds a note to the Journal.
    SetCreated(comment string)

    // SetUpdated stamps the UpdateDate of the object, and adds a note to the Journal.
    SetUpdated(comment string)

    // SetDeleted marks the object virtually "deleted", and adds a note to the Journal.
    SetDeleted(comment string)

    // ETag returns the signature or revision number of the object
    ETag() string
}
Datasource Interface

// Configure your database
server := mongodb.New(uri, dbname)

// Create a new session, one per server request
session, err := server.Session(ctx)
defer session.Close()

// Get a reference to the table/collection you're working with
collection := session.Collection("Person")

// LOAD the first person that matches the criteria into a person object
err := collection.Load(criteria, &person)

// INSERT/UPDATE a person object in the database - writing a "note" to the journal.
err := collection.Save(person, note)

// DELETE a person from the database. This is a "soft" delete that marks values as deleted but leaves them in the database.
err := collection.Delete(person, note)

// HARD DELETE all records that match the criteria, actually removing them from the database.
err := collection.HardDelete(criteria)

// QUERY many records from the database, by populating a slice of results
err := collection.Query(&people, criteria, options...)

// ITERATE over many records, using a more memory-friendly iterator to loop through a very large dataset.
it, err := collection.Iterator(criteria, options...)

for it.Next(&person) {
    // do stuff with person.
}

// COUNT the number of records that match a particular criteria
count, err := collection.Count(criteria)

Expression Builder

Every database has its own query language, so this library uses the exp module to represent query expressions in an efficient intermediate format that should be easy to convert into whatever specific language you need to use.

// build single predicate expressions
c := exp.Equal("name", "John Connor")

// or chain logical expressions together
c := exp.Equal("name", "John Connor").OrEqual("name", "Sarah Connor")
Query Options

There's a package for managing optional query arguments, such as sorting and row limits. These options just encapsulate data. It is the responsibility of each database adapter to implement each of these in its own query engine.


// get a new iterator.  Sort results by name.  Return at most 100 rows.
it, err := collection.Iterator(criteria, option.SortAsc("name"), option.MaxRows(100))

SortAsc(fieldname) tells the database to sort by a particular field, in ascending order

SortDesc(fieldname) tells the database to sort by a particular field, in descending order

FirstRow() tells the database to return only the first matching row

MaxRows(count) tells the database to limit the number of records to the designated number of rows.

Fields(names...) tells the database to return only the named fields for each record

CaseSensitive(bool) tells the database whether string comparisons should consider letter case

What matters here

This package contains interfaces and data only — there is no database logic. CRUD behavior lives entirely in the adapter packages (data-mongo, data-mock, data-slice). When changing this package, remember that every adapter must continue to satisfy the interfaces.

  • option.FirstRow() means "return only the first matching row" — it is not a pagination offset. Despite the name, it carries no row number (FirstRowOption is an empty struct). Adapters translate it to a limit of one row (Mongo SetLimit(1), slice value[:1]). Reaching for it to "skip to row N" will silently do the wrong thing.
  • Options only encapsulate intent; adapters decide what they mean. An adapter is free to ignore an option it doesn't support, so a query that relies on CaseSensitive or Fields may behave differently across backends. Verify support in the specific adapter, not here.
  • Delete is a soft delete; HardDelete is permanent. Delete(object, note) stamps the journal's DeleteDate and leaves the record in place; HardDelete(criteria) removes matching rows outright and takes no object or note.
  • The journal is the source of truth for object lifecycle. Embedding journal.Journal satisfies all of Object except ID(). SetUpdated/SetDeleted bump Revision (the ETag); SetCreated does not. The Revision field serializes as "signature" for backward compatibility — don't rename the tag.

Pull Requests Welcome

This library is a work in progress, and will benefit from your experience reports, use cases, and contributions. If you have an idea for making this library better, send in a pull request. We're all in this together! 📚

Documentation

Overview

Package data defines a minimal set of interfaces for abstracting database access (servers, sessions, collections, and the objects they store) so that application code can perform CRUD operations without depending on a specific database driver.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Collection added in v0.3.8

type Collection interface {

	// Context returns the context.Context that scopes this collection's transaction
	Context() context.Context

	// Count returns the number of records that match the provided criteria
	Count(criteria exp.Expression, options ...option.Option) (int64, error)

	// Query populates the target (typically a slice) with all records that match the criteria
	Query(target any, criteria exp.Expression, options ...option.Option) error

	// Iterator returns an Iterator over all records that match the criteria
	Iterator(criteria exp.Expression, options ...option.Option) (Iterator, error)

	// Load populates the target with the first record that matches the criteria
	Load(criteria exp.Expression, target Object, options ...option.Option) error

	// Save inserts or updates the object, recording the note in its journal
	Save(object Object, note string) error

	// Delete virtually ("soft") deletes the object, recording the note in its journal
	Delete(object Object, note string) error

	// HardDelete permanently removes all records that match the criteria
	HardDelete(criteria exp.Expression) error
}

Collection represents a single database collection (or table) that is opened to support a single transactional request, and then closed when this transaction is complete

type Iterator added in v0.2.5

type Iterator interface {

	// Next populates the provided target with the next item, returning FALSE when the iterator is exhausted
	Next(any) bool

	// Error returns the first error (if any) encountered while iterating
	Error() error

	// Count returns the number of records contained by this iterator
	Count() int

	// Close releases any resources held by the iterator
	Close() error
}

Iterator interface allows callers to iterate over a large number of items in a data structure

type Object

type Object interface {

	// ID returns the unique identifier for this object
	ID() string

	// Created returns the Unix epoch (in milliseconds) when this object was created
	Created() int64

	// Updated returns the Unix epoch (in milliseconds) when this object was updated
	Updated() int64

	// IsNew returns TRUE if the object has not yet been saved to the database
	IsNew() bool

	// IsDeleted returns TRUE if the object has been virtually deleted
	IsDeleted() bool

	// SetCreated stamps the CreateDate and UpdateDate of the object, and makes a note
	SetCreated(comment string)

	// SetUpdated stamps the UpdateDate of the object, and makes a note
	SetUpdated(comment string)

	// SetDeleted marks the object virtually "deleted", and makes a note
	SetDeleted(comment string)

	// ETag returns the signature or revision number of the object
	ETag() string
}

Object interface defines all of the methods required for the `data` library to create, read, update, and delete objects in the database.

type Server added in v0.3.6

type Server interface {

	// Session opens a new Session against the database, scoped to the provided context
	Session(context.Context) (Session, error)

	// WithTransaction opens a session, runs the callback, and commits or rolls back based on its result
	WithTransaction(context.Context, TransactionCallbackFunc) (any, error)
}

Server is an abstract representation of a database and its connection information.

type Session

type Session interface {

	// Collection returns a handle to the named collection (or table) within this session
	Collection(collection string) Collection

	// Context returns the context.Context that scopes this session
	Context() context.Context

	// Close releases any resources held by this session
	Close()
}

Session represents a single database session, that is opened to support a single transactional request, and then closed when this transaction is complete

type TransactionCallbackFunc added in v0.31.0

type TransactionCallbackFunc func(Session) (any, error)

TransactionCallbackFunc is a function that is called after a transaction session is created. The callback function can return a value (which is passed through) and an error. If the error is nil then the transaction is committed to the database. Otherwise, the transaction is rolled back.

Directories

Path Synopsis
Package journal provides a simple implementation of a change-tracking "journal" that can be embedded into other data objects to track their creation, update, and deletion history.
Package journal provides a simple implementation of a change-tracking "journal" that can be embedded into other data objects to track their creation, update, and deletion history.
Package option provides an interface for query options that can be used to modify database queries.
Package option provides an interface for query options that can be used to modify database queries.

Jump to

Keyboard shortcuts

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