sql

package module
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Nov 29, 2025 License: MPL-2.0 Imports: 7 Imported by: 2

README

SQL Event Store

The sql eventstore is a module containing multiple sql based event stores that are all based on the database/sql interface in go standard library. The different event stores has specific database schemas that support the different databases.

SQLite

Supports the SQLite database https://www.sqlite.org/

Database Schema
    CREATE TABLE IF NOT EXISTS events (
        seq        INTEGER PRIMARY KEY AUTOINCREMENT,
        id         VARCHAR NOT NULL,
        version    INTEGER,
        reason     VARCHAR,
        type       VARCHAR,
        timestamp  VARCHAR,
        data       BLOB,
        metadata   BLOB,
        UNIQUE (id, type, version)
    );

    CREATE INDEX IF NOT EXISTS id_type ON events (id, type);
Constructor
// NewSQLite connection to database
NewSQLite(db *sql.DB) (*SQLite, error) 

// NewSQLiteSingelWriter prevents multiple writers to save events concurrently
//
// Multiple go routines writing concurrently to sqlite could produce sqlite to lock.
// https://www.sqlite.org/cgi/src/doc/begin-concurrent/doc/begin_concurrent.md
//
// "If there is significant contention for the writer lock, this mechanism can
// be inefficient. In this case it is better for the application to use a mutex
// or some other mechanism that supports blocking to ensure that at most one
// writer is attempting to COMMIT a BEGIN CONCURRENT transaction at a time.
// This is usually easier if all writers are part of the same operating system process."
NewSQLiteSingelWriter(db *sql.DB) (*SQLite, error)
Example of use
import (
	// have to alias the sql package as it use the same name
	gosql "database/sql"
	"github.com/hallgren/eventsourcing/eventstore/sql"
	// use the sqlite driver from mattn in this example
	_ "github.com/mattn/go-sqlite3"
)

db, err := gosql.Open("sqlite3", "file::memory:?cache=shared")
if err != nil {
	return nil, nil, errors.New(fmt.Sprintf("could not open database %v", err))
}
err = db.Ping()
if err != nil {
	return nil, nil, errors.New(fmt.Sprintf("could not ping database %v", err))
}
sqliteEventStore, err := sql.NewSQLiteSingelWriter(db)
if err != nil {
	return nil, nil, err
}

Postgres

Supports the Postgres database https://www.postgresql.org

Database Schema
CREATE TABLE IF NOT EXISTS events (
	seq SERIAL PRIMARY KEY,
	id VARCHAR NOT NULL,
	version INTEGER,
	reason VARCHAR,
	type VARCHAR,
	timestamp VARCHAR,
	data BYTEA,
	metadata BYTEA,
	UNIQUE (id, type, version)
);

CREATE INDEX IF NOT EXISTS id_type ON events (id, type);
Constructor
// NewPostgres connection to database
func NewPostgres(db *sql.DB) (*Postgres, error) {
Example of use
import (
	// have to alias the sql package as it use the same name
	gosql "database/sql"
	
	// in this example we use the pg postgres driver
	_ "github.com/lib/pq"
	"github.com/hallgren/eventsourcing/eventstore/sql"
)

db, err := gosql.Open("postgres", dsn)
if err != nil {
	return nil, nil, fmt.Errorf("db open failed: %w", err)
}
// Test the connection
err = db.Ping()
if err != nil {
	return nil, nil, err
}
postgresEventStore, err := sql.NewPostgres(db)

Microsoft SQL Server

Supports Microsoft SQL Server database https://www.microsoft.com/en-us/sql-server

Database Schema
IF OBJECT_ID('[events]', 'U') IS NULL
BEGIN
    CREATE TABLE [events] (
        [seq] INT IDENTITY(1,1) PRIMARY KEY,
        [id] NVARCHAR(255) NOT NULL,
        [version] INT,
        [reason] NVARCHAR(255),
        [type] NVARCHAR(255),
        [timestamp] NVARCHAR(255),
        [data] VARBINARY(MAX),
        [metadata] VARBINARY(MAX),
        CONSTRAINT uq_events UNIQUE ([id], [type], [version])
    );
END

IF NOT EXISTS (
    SELECT 1 
    FROM sys.indexes 
    WHERE name = 'id_type' AND object_id = OBJECT_ID('events')
)
BEGIN
    CREATE INDEX id_type ON [events] ([id], [type]);
END

IF NOT EXISTS (
    SELECT 1 
    FROM sys.indexes 
    WHERE name = 'id_type' AND object_id = OBJECT_ID('events')
)
BEGIN
    CREATE INDEX id_type ON [events] ([id], [type]);
END
Constructor
// NewSQLServer connection to database
func NewSQLServer(db *sql.DB) (*SQLServer, error) {
Example of use
import (
	// alias the go sql package
	gosql "database/sql"
	 // uses the sql server driver from denisenkom
	_ "github.com/denisenkom/go-mssqldb"
	"github.com/hallgren/eventsourcing/eventstore/sql"
)

db, err := gosql.Open("sqlserver", dsn)
if err != nil {
	return err
}
err = db.Ping() {
if err != nil {
	return err
}
SqlServerEventStore, err := sql.NewSQLServer(db)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Iterator added in v0.7.0

type Iterator struct {
	Rows                 *sql.Rows
	CurrentGlobalVersion core.Version
}

func (*Iterator) Close added in v0.7.0

func (i *Iterator) Close()

Close closes the iterator

func (*Iterator) Next added in v0.7.0

func (i *Iterator) Next() bool

Next return true if there are more data

func (*Iterator) Value added in v0.7.0

func (i *Iterator) Value() (core.Event, error)

Value return the an event

type Postgres added in v0.6.0

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

Postgres event store handler

func NewPostgres added in v0.6.0

func NewPostgres(db *sql.DB) (*Postgres, error)

NewPostgres connection to database

func (*Postgres) All added in v0.6.0

func (s *Postgres) All(start core.Version) core.Fetcher

All iterate over all event in GlobalEvents order

func (*Postgres) Close added in v0.6.0

func (s *Postgres) Close()

Close the connection

func (*Postgres) Get added in v0.6.0

func (s *Postgres) Get(ctx context.Context, id string, aggregateType string, afterVersion core.Version) (core.Iterator, error)

Get the events from database

func (*Postgres) Save added in v0.6.0

func (s *Postgres) Save(events []core.Event) error

Save persists events to the database

type SQLServer added in v0.6.0

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

SQLServer event store handler

func NewSQLServer added in v0.6.0

func NewSQLServer(db *sql.DB) (*SQLServer, error)

NewSQLServer connection to database

func (*SQLServer) All added in v0.6.0

func (s *SQLServer) All(start core.Version) core.Fetcher

All iterate over all event in GlobalEvents order

func (*SQLServer) Close added in v0.6.0

func (s *SQLServer) Close()

Close the connection

func (*SQLServer) Get added in v0.6.0

func (s *SQLServer) Get(ctx context.Context, id string, aggregateType string, afterVersion core.Version) (core.Iterator, error)

Get the events from database

func (*SQLServer) Save added in v0.6.0

func (s *SQLServer) Save(events []core.Event) error

Save persists events to the database

type SQLite added in v0.6.0

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

SQLite event store handler

func NewSQLite added in v0.6.0

func NewSQLite(db *sql.DB) (*SQLite, error)

NewSQLite connection to database

func NewSQLiteSingelWriter added in v0.6.0

func NewSQLiteSingelWriter(db *sql.DB) (*SQLite, error)

NewSQLiteSingelWriter prevents multiple writers to save events concurrently

Multiple go routines writing concurrently to sqlite could produce sqlite to lock. https://www.sqlite.org/cgi/src/doc/begin-concurrent/doc/begin_concurrent.md

"If there is significant contention for the writer lock, this mechanism can be inefficient. In this case it is better for the application to use a mutex or some other mechanism that supports blocking to ensure that at most one writer is attempting to COMMIT a BEGIN CONCURRENT transaction at a time. This is usually easier if all writers are part of the same operating system process."

func (*SQLite) All added in v0.6.0

func (s *SQLite) All(start core.Version) core.Fetcher

All iterate over all event in GlobalEvents order

func (*SQLite) Close added in v0.6.0

func (s *SQLite) Close()

Close the connection

func (*SQLite) Get added in v0.6.0

func (s *SQLite) Get(ctx context.Context, id string, aggregateType string, afterVersion core.Version) (core.Iterator, error)

Get the events from database

func (*SQLite) Save added in v0.6.0

func (s *SQLite) Save(events []core.Event) error

Save persists events to the database

Jump to

Keyboard shortcuts

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