debefix

package module
v2.0.6 Latest Latest
Warning

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

Go to latest
Published: Nov 30, 2024 License: MIT Imports: 17 Imported by: 5

README

debefix - Database seeding and fixtures

GoDoc

debefix is a Go library to seed database data and/or create fixtures for DB tests.

Tables can reference each other using string ids (called RefID), and generated fields (like database auto increment or generated UUID) are supported and can be resolved and used by other table's references.

Dependencies between tables can be detected automatically by reference ids, or manually. This is used to generate a dependency graph and output the insert statements in the correct order.

Row values can reference each other using Value or ValueMultiple interface implementations. They are referenced after they are resolved, so it can reference values generated on execution like autoincrement fields.

Install

go get -u github.com/rrgmc/debefix/v2

Goals

  • For developer seeding or test fixtures, not for inserting a huge amount of records.

Example

import (
    "context"
    "os"

    "github.com/rrgmc/debefix-db/v2/sql"
    "github.com/rrgmc/debefix-db/v2/sql/postgres"
    "github.com/rrgmc/debefix/v2"
)

func ExampleResolve() {
    ctx := context.Background()
    data := debefix.NewData()

    tableTags := debefix.TableName("public.tags")
    tableUsers := debefix.TableName("public.users")
    tablePosts := debefix.TableName("public.posts")
    tablePostTags := debefix.TableName("public.post_tags")

    data.AddValues(tableTags,
        debefix.MapValues{
            // this field value will be generated at resolve time, for example as a database autoincrement.
            "tag_id": debefix.ResolveValueResolve(),
            // sets the RefID to be targeted by `ValueRefID(tableTags, "go", "tag_id")`. Field is not added to the row values.
            "_refid": debefix.SetValueRefID("go"),
            "name":   "Go",
            // set the value as the resolver base time plus 1 hour.
            "created_at": debefix.ValueBaseTimeAdd(debefix.WithAddHours(1)),
            "updated_at": debefix.ValueBaseTimeAdd(debefix.WithAddHours(1)),
        },
        debefix.MapValues{
            "tag_id":     debefix.ResolveValueResolve(),
            "_refid":     debefix.SetValueRefID("javascript"),
            "name":       "JavaScript",
            "created_at": debefix.ValueBaseTimeAdd(debefix.WithAddHours(1), debefix.WithAddMinutes(2)),
            "updated_at": debefix.ValueBaseTimeAdd(debefix.WithAddHours(1), debefix.WithAddMinutes(2)),
        },
        debefix.MapValues{
            "tag_id":     debefix.ResolveValueResolve(),
            "_refid":     debefix.SetValueRefID("cpp"),
            "name":       "C++",
            "created_at": debefix.ValueBaseTimeAdd(debefix.WithAddHours(1), debefix.WithAddMinutes(2)),
            "updated_at": debefix.ValueBaseTimeAdd(debefix.WithAddHours(1), debefix.WithAddMinutes(2)),
        },
    )

    data.AddValues(tableUsers,
        debefix.MapValues{
            "user_id": 1, // fixed ID, not generated by the database
            // sets the RefID to be targeted by `ValueRefID(tableUsers, "johndoe", "user_id")`. Field is not added to the row values.
            "_refid":     debefix.SetValueRefID("johndoe"),
            "name":       "John Doe",
            "email":      "john@example.com",
            "created_at": debefix.ValueBaseTimeAdd(debefix.WithAddMinutes(30)),
            "updated_at": debefix.ValueBaseTimeAdd(debefix.WithAddMinutes(30)),
        },
        debefix.MapValues{
            "user_id":    2,
            "_refid":     debefix.SetValueRefID("janedoe"),
            "name":       "Jane Doe",
            "email":      "jane@example.com",
            "created_at": debefix.ValueBaseTimeAdd(debefix.WithAddMinutes(30)),
            "updated_at": debefix.ValueBaseTimeAdd(debefix.WithAddMinutes(30)),
        },
    )

    // AddWithID returns an internal ID reference that can be used later.
    post1IID := data.AddWithID(tablePosts,
        debefix.MapValues{
            "post_id": debefix.ValueUUIDRandom(), // generates a random UUID value.
            "title":   "First post",
            "text":    "This is the text of the first post",
            // returns the value of the "user_id" field of the row with the "johndoe" RefID in the tableUsers table.
            // this also adds a dependency between "posts" and "users", so "users" will always be resolved before "posts".
            "user_id":    debefix.ValueRefID(tableUsers, "johndoe", "user_id"),
            "created_at": debefix.ValueBaseTimeAdd(debefix.WithAddHours(2)),
            "updated_at": debefix.ValueBaseTimeAdd(debefix.WithAddHours(2)),
        })
    post2IID := data.AddWithID(tablePosts,
        debefix.MapValues{
            "post_id": debefix.ValueUUIDRandom(), // generates a random UUID value.
            // data is inserted in the order they were added, so it is possible to reference another row in the same table.
            "parent_post_id": post1IID.ValueForField("post_id"),
            "title":          "Second post",
            "text":           "This is the text of the second post",
            "user_id":        debefix.ValueRefID(tableUsers, "johndoe", "user_id"),
            "created_at":     debefix.ValueBaseTimeAdd(debefix.WithAddHours(2)),
            "updated_at":     debefix.ValueBaseTimeAdd(debefix.WithAddHours(2)),
        },
    )

    data.AddValues(debefix.TableName(tablePostTags),
        debefix.MapValues{
            // returns the value of the "post_id" field of the row referenced by "post1IID", after it was resolved.
            "post_id": post1IID.ValueForField("post_id"),
            // tag_id is generated by the database, so the value will be resolved before being set here.
            "tag_id": debefix.ValueRefID(tableTags, "go", "tag_id"),
        },
        debefix.MapValues{
            "post_id": post1IID.ValueForField("post_id"),
            "tag_id":  debefix.ValueRefID(tableTags, "cpp", "tag_id"),
        },
        debefix.MapValues{
            // returns the value of the "post_id" field of the row referenced by "post2IID", after it was resolved.
            "post_id": post2IID.ValueForField("post_id"),
            "tag_id":  debefix.ValueRefID(tableTags, "javascript", "tag_id"),
        },
    )

    if data.Err() != nil {
        panic(data.Err())
    }

    // outputs all generated queries
    qi := sql.NewDebugQueryInterface(os.Stdout)

    // resolve the rows using a SQL query resolver.
    _, err := debefix.Resolve(ctx, data,
        postgres.ResolveFunc(qi))
    if err != nil {
        panic(err)
    }

    // =============== public.tags ===============
    // INSERT INTO "public.tags" ("created_at", "name", "updated_at") VALUES ($1, $2, $3) RETURNING "tag_id"
    // $$ ARGS: [0:"2024-11-29 08:30:16.028185 -0300 -03 m=+3600.002859876"] [1:"Go"] [2:"2024-11-29 08:30:16.028185 -0300 -03 m=+3600.002859876"]
    // --------------------INSERT INTO "public.tags" ("created_at", "name", "updated_at") VALUES ($1, $2, $3) RETURNING "tag_id"
    // $$ ARGS: [0:"2024-11-29 08:32:16.028185 -0300 -03 m=+3720.002859876"] [1:"JavaScript"] [2:"2024-11-29 08:32:16.028185 -0300 -03 m=+3720.002859876"]
    // --------------------INSERT INTO "public.tags" ("created_at", "name", "updated_at") VALUES ($1, $2, $3) RETURNING "tag_id"
    // $$ ARGS: [0:"2024-11-29 08:32:16.028185 -0300 -03 m=+3720.002859876"] [1:"C++"] [2:"2024-11-29 08:32:16.028185 -0300 -03 m=+3720.002859876"]
    // =============== public.users ===============
    // INSERT INTO "public.users" ("created_at", "email", "name", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5)
    // $$ ARGS: [0:"2024-11-29 08:00:16.028185 -0300 -03 m=+1800.002859876"] [1:"john@example.com"] [2:"John Doe"] [3:"2024-11-29 08:00:16.028185 -0300 -03 m=+1800.002859876"] [4:"1"]
    // --------------------INSERT INTO "public.users" ("created_at", "email", "name", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5)
    // $$ ARGS: [0:"2024-11-29 08:00:16.028185 -0300 -03 m=+1800.002859876"] [1:"jane@example.com"] [2:"Jane Doe"] [3:"2024-11-29 08:00:16.028185 -0300 -03 m=+1800.002859876"] [4:"2"]
    // =============== public.posts ===============
    // INSERT INTO "public.posts" ("created_at", "post_id", "text", "title", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5, $6)
    // $$ ARGS: [0:"2024-11-29 09:30:16.028185 -0300 -03 m=+7200.002859876"] [1:"91a27c77-ff00-4f3b-90d6-51e335b7ad36"] [2:"This is the text of the first post"] [3:"First post"] [4:"2024-11-29 09:30:16.028185 -0300 -03 m=+7200.002859876"] [5:"1"]
    // --------------------INSERT INTO "public.posts" ("created_at", "parent_post_id", "post_id", "text", "title", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5, $6, $7)
    // $$ ARGS: [0:"2024-11-29 09:30:16.028185 -0300 -03 m=+7200.002859876"] [1:"91a27c77-ff00-4f3b-90d6-51e335b7ad36"] [2:"c06a1f3e-3578-4b56-bf51-9fb949ae5dbf"] [3:"This is the text of the second post"] [4:"Second post"] [5:"2024-11-29 09:30:16.028185 -0300 -03 m=+7200.002859876"] [6:"1"]
    // =============== public.post_tags ===============
    // INSERT INTO "public.post_tags" ("post_id", "tag_id") VALUES ($1, $2)
    // $$ ARGS: [0:"91a27c77-ff00-4f3b-90d6-51e335b7ad36"] [1:"223eca8c-d2c3-46ef-bb1f-d175916c97a2"]
    // --------------------INSERT INTO "public.post_tags" ("post_id", "tag_id") VALUES ($1, $2)
    // $$ ARGS: [0:"91a27c77-ff00-4f3b-90d6-51e335b7ad36"] [1:"d5c6e911-f38e-4cef-958b-cd5d8fc787f2"]
    // --------------------INSERT INTO "public.post_tags" ("post_id", "tag_id") VALUES ($1, $2)
    // $$ ARGS: [0:"c06a1f3e-3578-4b56-bf51-9fb949ae5dbf"] [1:"bd2d497f-af58-4338-a040-a24002492436"]
}

Samples

Extra

License

MIT

Author

Rangel Reale (rangelreale@gmail.com)

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ResolveRowsStop         = errors.New("stop resolve")
	ResolveNoRows           = errors.New("no rows found")
	ResolveUnknownFieldName = errors.New("unknown field name")
	ResolveLater            = errors.New("resolve later")
)
View Source
var (
	ErrNotFound = errors.New("not found")
)

Functions

func AssertIsResolveError

func AssertIsResolveError(t *testing.T, err error)

AssertIsResolveError assets that the error is a ResolveError.

func AssertRowValuesDeepEqual

func AssertRowValuesDeepEqual(t *testing.T, x []map[string]any, y []*Row)

AssertRowValuesDeepEqual asserts that a slice of maps is deep-equal to a list of Row.

func AssertValuesDeepEqual

func AssertValuesDeepEqual(t *testing.T, x map[string]any, y Values)

AssertValuesDeepEqual asserts that a map is deep-equal to a Values.

func ResolveCheck added in v2.0.2

func ResolveCheck(ctx context.Context, data *Data, options ...ResolveOption) error

ResolveCheck checks if all dependencies between rows are resolvable.

func ResolveCheckCallback added in v2.0.2

func ResolveCheckCallback(ctx context.Context, resolveInfo ResolveInfo, values ValuesMutable) error

ResolveCheckCallback is the callback for the ResolveCheck function.

func ValuesGet added in v2.0.6

func ValuesGet[T any](values Values, fieldName string) (val T, exists bool, isType bool)

ValuesGet gets a value from values casting to the T type.

Types

type Data

type Data struct {
	Tables  map[string]*Table // map key is TableID.TableID()
	Updates []Update          // list of updates to be executed after all rows were added.
	// contains filtered or unexported fields
}

Data contains a list of tables and their row values.

func NewData

func NewData() *Data

NewData creates a new Data instance.

func (*Data) Add

func (d *Data) Add(tableID TableID, value ValuesMutable, options ...DataAddOption)

Add adds a row to a table.

func (*Data) AddDependencies

func (d *Data) AddDependencies(tableID TableID, dependencies ...TableID)

AddDependencies adds dependencies on other tables to the passed table.

func (*Data) AddValues

func (d *Data) AddValues(tableID TableID, values ...ValuesMutable)

AddValues adds a list of row to a table.

func (*Data) AddWithID

func (d *Data) AddWithID(tableID TableID, values ValuesMutable, options ...DataAddOption) InternalIDRef

AddWithID adds a row to a table, returning a reference to the added row.

func (*Data) Err

func (d *Data) Err() error

Err returns any error generated in processing.

func (*Data) FindInternalIDRow

func (d *Data) FindInternalIDRow(tableID TableID, internalID uuid.UUID) (*Row, error)

FindInternalIDRow returns a row of a table based on its internal id.

func (*Data) FindInternalIDValue

func (d *Data) FindInternalIDValue(value ValueInternalIDData) (any, error)

FindInternalIDValue resolves a field value referenced in a ValueInternalID.

func (*Data) FindRefIDRow

func (d *Data) FindRefIDRow(tableID TableID, refID RefID) (*Row, error)

FindRefIDRow returns a row from a table using a RefID.

func (*Data) FindRefIDRowValue

func (d *Data) FindRefIDRowValue(value ValueRefIDData) (any, error)

FindRefIDRowValue resolves a field value from a table using a RefID.

func (*Data) FindTableRow

func (d *Data) FindTableRow(tableID TableID, f func(*Row) (bool, error)) (*Row, error)

FindTableRow returns one row for a table where the callback returns true. If no rows where found, returns the error ResolveNoRows.

func (*Data) FindTableRowValue

func (d *Data) FindTableRowValue(tableID TableID, fieldName string, f func(*Row) (bool, error)) (any, error)

FindTableRowValue uses FindTableRow to find a row, and returns one of its field's value. If no rows where found, returns the error ResolveNoRows.

func (*Data) FindTableRows

func (d *Data) FindTableRows(tableID TableID, f func(*Row) (bool, error)) (ret []*Row, err error)

FindTableRows returns a list of rows for a table where the callback returns true.

func (*Data) Update

func (d *Data) Update(query UpdateQuery, action UpdateAction)

Update adds an update do be done after all records were added.

func (*Data) UpdateAfter

func (d *Data) UpdateAfter(afterRow QueryRow, query UpdateQuery, action UpdateAction)

UpdateAfter will add an update to be done right after the "afterRow" record is added.

func (*Data) WalkRows

func (d *Data) WalkRows(f func(TableID, *Row) bool)

WalkRows calls the callback function for all tables and rows, until the callback return false.

func (*Data) WalkTableRows

func (d *Data) WalkTableRows(tableID TableID, f func(*Row) bool) error

WalkTableRows calls the callback function for all tables and rows, until the callback return false.

type DataAddOption

type DataAddOption func(options *dataAddOptions)

DataAddOption are options for Data.Add and Data.AddWithID.

func WithDataAddResolvedCallback

func WithDataAddResolvedCallback(f ResolvedCallback) DataAddOption

WithDataAddResolvedCallback adds a callback to be called when this row is resolved.

type InternalIDRef

type InternalIDRef struct {
	NotAValue
	TableID    TableID
	InternalID uuid.UUID
}

InternalIDRef is a reference to one table's row by internal id. It refers to an entire row instead of a specific field, so it don't implement Value. Use ValueForField to return a Value implementation for one of its fields. It implements QueryRow, and can return a UpdateQuery.

func NewInternalIDRef

func NewInternalIDRef(tableID TableID, internalID uuid.UUID) InternalIDRef

func (InternalIDRef) QueryRow

func (v InternalIDRef) QueryRow(data *Data) (QueryRowResult, error)

QueryRow is the implementation of the QueryRow interface.

func (InternalIDRef) UpdateQuery

func (v InternalIDRef) UpdateQuery(keyFields []string) UpdateQuery

UpdateQuery returns an UpdateQuery targetting the referenced table row.

func (InternalIDRef) ValueForField

func (v InternalIDRef) ValueForField(fieldName string) ValueInternalIDData

ValueForField returns a Value that resolves one specific field of the referenced table row.

type IsNotAValue added in v2.0.4

type IsNotAValue interface {
	// contains filtered or unexported methods
}

IsNotAValue marks structs that may be confused with values to avoid using them as such.

type MapValues

type MapValues map[string]any

MapValues is a ValuesMutable implementation using a map[string]any

func (MapValues) All

func (v MapValues) All(yield func(string, any) bool)

func (MapValues) Delete

func (v MapValues) Delete(fieldName ...string)

func (MapValues) Get

func (v MapValues) Get(fieldName string) (val any, exists bool)

func (MapValues) GetDefault

func (v MapValues) GetDefault(fieldName string, def any) any

func (MapValues) GetOrNil

func (v MapValues) GetOrNil(fieldName string) any

func (MapValues) Insert

func (v MapValues) Insert(seq iter.Seq2[string, any])

func (MapValues) Len

func (v MapValues) Len() int

func (MapValues) Set

func (v MapValues) Set(fieldName string, val any)

type NotAValue added in v2.0.4

type NotAValue struct{}

NotAValue implements IsNotAValue.

type Process

type Process interface {
	Start(ctx context.Context) (context.Context, error)
	Finish(ctx context.Context) error
}

Process define processes that can run alongside a Resolve operation, like a kind of plugin.

type QueryRow

type QueryRow interface {
	// QueryRow returns a single Row, or ErrNotFound if none found.
	QueryRow(data *Data) (QueryRowResult, error)
}

type QueryRowInternalID

type QueryRowInternalID struct {
	TableID    TableID
	InternalID uuid.UUID
}

QueryRowInternalID finds one row by a table and an internal id.

func NewQueryRowInternalID

func NewQueryRowInternalID(tableID TableID, internalID uuid.UUID) QueryRowInternalID

func (QueryRowInternalID) Row

func (u QueryRowInternalID) Row(data *Data) (QueryRowResult, error)

type QueryRowRefID

type QueryRowRefID struct {
	TableID TableID
	RefID   RefID
}

QueryRowRefID finds one row by a table and a RefID.

func NewQueryRowRefID

func NewQueryRowRefID(tableID TableID, refID RefID) QueryRowRefID

func (QueryRowRefID) Row

func (u QueryRowRefID) Row(data *Data) (QueryRowResult, error)

type QueryRowResult

type QueryRowResult struct {
	TableID TableID
	Row     *Row
}

QueryRowResult represents a row and its table.

type QueryRows

type QueryRows interface {
	// QueryRows returns a list of rows.
	QueryRows(data *Data) ([]QueryRowResult, error)
}

type RefID

type RefID string

RefID is a string value that uniquely identifies one row of one table. It is meant to be a meaningful string to be easy to reference.

type ResolveCallback

type ResolveCallback func(ctx context.Context, resolveInfo ResolveInfo, values ValuesMutable) error

ResolveCallback is a callback used to resolve ResolveValue values.

type ResolveError

type ResolveError struct {
	Err error
}

ResolveError is the base of all returned errors.

func NewResolveError

func NewResolveError(msg string) *ResolveError

func NewResolveErrorf

func NewResolveErrorf(format string, args ...any) *ResolveError

func (*ResolveError) Error

func (e *ResolveError) Error() string

func (*ResolveError) Unwrap

func (e *ResolveError) Unwrap() error

type ResolveInfo

type ResolveInfo struct {
	Type            ResolveType // type of the resolve (add, update).
	TableID         TableID     // table being resolved.
	UpdateKeyFields []string    // if type is update, the names of the key fields to be used to update.
}

ResolveInfo is a context for resolve callbacks.

type ResolveOption

type ResolveOption func(options *resolveOptions)

func WithResolveOptionProcess

func WithResolveOptionProcess(process Process) ResolveOption

WithResolveOptionProcess adds a Process to the resolver.

type ResolveType

type ResolveType int
const (
	ResolveTypeAdd ResolveType = iota
	ResolveTypeUpdate
)

type ResolveValue

type ResolveValue interface {
	ResolveValueParse(ctx context.Context, value any) (any, error)
}

ResolveValue is a value that should be resolved by the user of the library in a callback. Usually this is used to return values generated by the database, like last insert id or created date.

type ResolveValueFunc added in v2.0.4

type ResolveValueFunc func(ctx context.Context, value any) (any, error)

ResolveValueFunc is a functional implementation of ResolveValue.

func (ResolveValueFunc) ResolveValueParse added in v2.0.4

func (f ResolveValueFunc) ResolveValueParse(ctx context.Context, value any) (any, error)

type ResolveValueResolveData

type ResolveValueResolveData struct {
}

ResolveValueResolveData is a value to be resolved, without any parsing.

func ResolveValueResolve

func ResolveValueResolve() ResolveValueResolveData

ResolveValueResolve is a value to be resolved, without any parsing.

func (ResolveValueResolveData) ResolveValueParse added in v2.0.4

func (v ResolveValueResolveData) ResolveValueParse(ctx context.Context, value any) (any, error)

type ResolveValueTypeOption added in v2.0.4

type ResolveValueTypeOption func(*resolveValueTypeOptions)

func WithResolveValueTypeAllowBlank added in v2.0.4

func WithResolveValueTypeAllowBlank(allowBlank bool) ResolveValueTypeOption

WithResolveValueTypeAllowBlank sets whether to allow blank values.

func WithResolveValueTypeAllowNull added in v2.0.4

func WithResolveValueTypeAllowNull(allowNull bool) ResolveValueTypeOption

WithResolveValueTypeAllowNull sets whether to allow null (nil) values.

type ResolveValueUUIDData added in v2.0.4

type ResolveValueUUIDData struct {
	AllowNull  bool
	AllowBlank bool
}

ResolveValueUUIDData parses the returned value as uuid.UUID if it isn't already.

func ResolveValueUUID added in v2.0.4

func ResolveValueUUID(options ...ResolveValueTypeOption) ResolveValueUUIDData

ResolveValueUUID parses the returned value as uuid.UUID if it isn't already.

func (ResolveValueUUIDData) ResolveValueParse added in v2.0.4

func (r ResolveValueUUIDData) ResolveValueParse(ctx context.Context, value any) (any, error)

type ResolvedCallback

type ResolvedCallback func(ctx context.Context, resolvedData *ResolvedData, resolveInfo ResolveInfo, resolvedRow *Row) error

ResolvedCallback is called for each resolved row.

type ResolvedData

type ResolvedData struct {
	Data
	BaseTime   time.Time
	TableOrder []string
}

ResolvedData is Data after being resolved by the Resolve function.

func NewResolvedData

func NewResolvedData() *ResolvedData

func Resolve

func Resolve(ctx context.Context, data *Data, resolveFunc ResolveCallback, options ...ResolveOption) (*ResolvedData, error)

Resolve resolves Value and ValueMultiple field values for all rows in "data", using a dependency graph to make sure tables are resolved in dependency order.

func (*ResolvedData) ResolveArgs

func (d *ResolvedData) ResolveArgs(ctx context.Context, values Values, args ...any) ([]any, bool, error)

ResolveArgs resolves a list of arguments. It is used by the ValueFormat value to create a string value from other values.

func (*ResolvedData) ResolveMapArgs

func (d *ResolvedData) ResolveMapArgs(ctx context.Context, values Values, args map[string]any) (map[string]any, bool, error)

ResolveMapArgs resolves a list of arguments using a map source.

type Row

type Row struct {
	InternalID        uuid.UUID          // internal id that uniquely identifies this row in its table. It is randomly generated.
	RefID             RefID              // RefID of the row, if set. Should not be duplicated in any other row of the same table.
	Values            ValuesMutable      // the row field values.
	Updates           []Update           // updates to be done after the row is resolved.
	ResolvedCallbacks []ResolvedCallback // a callback called after the row is resolved.
}

Row represents a single row of one table.

func (*Row) ResolveFieldName

func (r *Row) ResolveFieldName(fieldName string) (any, error)

ResolveFieldName resolves the value of a field, or returns an error if the field don't exist.

type SetValueRefIDData

type SetValueRefIDData struct {
	RefID RefID
}

SetValueRefIDData is a special ValueMultiple which sets the RefID for the current row. The field containing it is not added to the row.

func SetValueRefID

func SetValueRefID(refID RefID) SetValueRefIDData

SetValueRefID is a special ValueMultiple which sets the RefID for the current row. The field containing it is not added to the row.

func (SetValueRefIDData) Resolve

func (v SetValueRefIDData) Resolve(ctx context.Context, resolvedData *ResolvedData, tableID TableID, fieldName string, values ValuesMutable) error

type Table

type Table struct {
	TableID TableID
	Depends []TableID
	Rows    []*Row
}

Table represents a table, its dependencies, and list of rows.

func (*Table) AddDependencies

func (t *Table) AddDependencies(deps ...TableID)

AddDependencies adds dependencies on another tables.

type TableID

type TableID interface {
	TableID() string
	TableName() string
}

TableID is a table identification, usually a table name. Users of the library may want to add more fields, like a database name.

type TableName

type TableName string

TableName implements TableID with a simple table name.

func (TableName) TableID

func (t TableName) TableID() string

func (TableName) TableName

func (t TableName) TableName() string

type TableNameID

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

TableNameID implement TableID with separate id and table name values.

func NewTableNameID

func NewTableNameID(id string, tableName string) TableNameID

NewTableNameID implement TableID with separate id and table name values.

func (TableNameID) TableID

func (t TableNameID) TableID() string

func (TableNameID) TableName

func (t TableNameID) TableName() string

type Update

type Update struct {
	Query  UpdateQuery
	Action UpdateAction
}

Update is an updated query and its corresponding action.

type UpdateAction

type UpdateAction interface {
	UpdateRow(ctx context.Context, resolvedData *ResolvedData, tableID TableID, row *Row) error
}

UpdateAction do an update on a row returned by UpdateQuery.

type UpdateActionSetValues

type UpdateActionSetValues struct {
	Values Values
}

UpdateActionSetValues is an update action which sets the field values in Values to the row being updated.

func (UpdateActionSetValues) UpdateRow

func (u UpdateActionSetValues) UpdateRow(ctx context.Context, resolvedData *ResolvedData, tableID TableID, row *Row) error

type UpdateData

type UpdateData struct {
	TableID   TableID
	KeyFields []string
	Row       *Row
}

UpdateData represents one row of one table to be updated.

type UpdateQuery

type UpdateQuery interface {
	Rows(ctx context.Context, resolvedData *ResolvedData) ([]UpdateData, error)
}

UpdateQuery returns the list of rows that should be updated.

type UpdateQueryQueryRow

type UpdateQueryQueryRow struct {
	QueryRow  QueryRow
	KeyFields []string
}

UpdateQueryQueryRow wraps a QueryRow in an UpdateQuery.

func UpdateQueryRow

func UpdateQueryRow(queryRow QueryRow, keyFields []string) *UpdateQueryQueryRow

UpdateQueryRow wraps a QueryRow in an UpdateQuery.

func (UpdateQueryQueryRow) Rows

func (u UpdateQueryQueryRow) Rows(ctx context.Context, resolvedData *ResolvedData) ([]UpdateData, error)

type UpdateQueryQueryRows

type UpdateQueryQueryRows struct {
	QueryRows QueryRows
	KeyFields []string
}

UpdateQueryQueryRows wraps a QueryRows in an UpdateQuery.

func UpdateQueryRows

func UpdateQueryRows(queryRows QueryRows, keyFields []string) *UpdateQueryQueryRows

UpdateQueryRows wraps a QueryRows in an UpdateQuery.

func (UpdateQueryQueryRows) Rows

func (u UpdateQueryQueryRows) Rows(ctx context.Context, resolvedData *ResolvedData) ([]UpdateData, error)

type Value

type Value interface {
	ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)
}

Value represents a field value for a row that can be loaded at resolve time. It can use the current row values, or load any previously loaded rows.

type ValueBaseTimeAddData

type ValueBaseTimeAddData struct {
	AddDays    int
	AddHours   int
	AddMinutes int
	AddSeconds int
}

ValueBaseTimeAddData is a Value that calculates a date based on the Data base time.

func ValueBaseTimeAdd

func ValueBaseTimeAdd(options ...ValueBaseTimeAddDataOption) ValueBaseTimeAddData

ValueBaseTimeAdd is a Value that calculates a date based on the Data base time.

func (ValueBaseTimeAddData) ResolveValue

func (v ValueBaseTimeAddData) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

type ValueBaseTimeAddDataOption

type ValueBaseTimeAddDataOption func(*ValueBaseTimeAddData)

func WithAddDate

func WithAddDate(days, hours, minutes, seconds int) ValueBaseTimeAddDataOption

func WithAddDays

func WithAddDays(days int) ValueBaseTimeAddDataOption

func WithAddHours

func WithAddHours(hours int) ValueBaseTimeAddDataOption

func WithAddMinutes

func WithAddMinutes(minutes int) ValueBaseTimeAddDataOption

func WithAddSeconds

func WithAddSeconds(seconds int) ValueBaseTimeAddDataOption

func WithAddTime

func WithAddTime(hours, minutes, seconds int) ValueBaseTimeAddDataOption

type ValueDefaultData

type ValueDefaultData struct {
	Value        Value
	DefaultValue any
}

ValueDefaultData returns the DefaultValue if the other Value don't return a valid value (returns "false" for the 2nd result value).

func ValueDefault

func ValueDefault(value Value, defaultValue any) ValueDefaultData

ValueDefault returns the DefaultValue if the other Value don't return a valid value (returns "false" for the 2nd result value).

func (ValueDefaultData) ResolveValue

func (d ValueDefaultData) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

func (ValueDefaultData) TableDependencies

func (d ValueDefaultData) TableDependencies() []TableID

type ValueDependencies

type ValueDependencies interface {
	TableDependencies() []TableID
}

ValueDependencies lists value dependencies on other tables, allowing a dependency graph to be built to ensure inserts are done in the corrector table order.

type ValueErr

type ValueErr struct {
	Err error
}

ValueErr is an implementation of Value which always returns the passed error.

func (ValueErr) ResolveValue

func (v ValueErr) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

type ValueFieldValueData

type ValueFieldValueData struct {
	FieldName string
}

ValueFieldValueData is a Value which returns the value of a field of the current row.

func ValueFieldValue

func ValueFieldValue(fieldName string) ValueFieldValueData

func (ValueFieldValueData) ResolveValue

func (d ValueFieldValueData) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

type ValueFormatCallback added in v2.0.4

type ValueFormatCallback func(ctx context.Context, resolvedData *ResolvedData, values Values, value any) (any, bool, error)

type ValueFormatData

type ValueFormatData struct {
	Format string
	Args   []any
}

ValueFormatData is a Value that formats a string based on other field's values.

func ValueFormat

func ValueFormat(format string, args ...any) ValueFormatData

ValueFormat is a Value that formats a string based on other field's values.

func (ValueFormatData) ResolveValue

func (v ValueFormatData) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

func (ValueFormatData) TableDependencies

func (v ValueFormatData) TableDependencies() []TableID

type ValueFormatFuncData

type ValueFormatFuncData struct {
	Value      Value
	FormatFunc ValueFormatCallback
}

ValueFormatFuncData resolves Value, and allows it to be changed on a callback formatting function.

func ValueFormatFunc

func ValueFormatFunc(value Value, formatFunc ValueFormatCallback) ValueFormatFuncData

ValueFormatFunc resolves Value, and allows it to be changed on a callback formatting function.

func (ValueFormatFuncData) ResolveValue

func (d ValueFormatFuncData) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

func (ValueFormatFuncData) TableDependencies

func (d ValueFormatFuncData) TableDependencies() []TableID

type ValueFunc

type ValueFunc func(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

ValueFunc is a functional implementation of Value.

func (ValueFunc) ResolveValue

func (f ValueFunc) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

type ValueGenUUIDData

type ValueGenUUIDData struct {
}

ValueGenUUIDData returns a new random uuid.UUID value every time it is resolved.

func ValueGenUUID

func ValueGenUUID() ValueGenUUIDData

ValueGenUUID returns a new random uuid.UUID value every time it is resolved.

func (ValueGenUUIDData) ResolveValue

func (u ValueGenUUIDData) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

type ValueInternalIDData

type ValueInternalIDData struct {
	TableID    TableID
	InternalID uuid.UUID
	FieldName  string
}

ValueInternalIDData represents a field value from a table row by internal id. It implements Value, QueryRow, and can return a UpdateQuery.

func ValueInternalID

func ValueInternalID(tableID TableID, internalID uuid.UUID, fieldName string) ValueInternalIDData

ValueInternalID represents a field value from a table row by internal id. It implements Value, QueryRow, and can return a UpdateQuery.

func (ValueInternalIDData) QueryRow

func (v ValueInternalIDData) QueryRow(data *Data) (QueryRowResult, error)

func (ValueInternalIDData) ResolveValue

func (v ValueInternalIDData) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

func (ValueInternalIDData) TableDependencies

func (v ValueInternalIDData) TableDependencies() []TableID

func (ValueInternalIDData) UpdateQuery

func (v ValueInternalIDData) UpdateQuery(keyFields []string) UpdateQuery

type ValueMultiple

type ValueMultiple interface {
	Resolve(ctx context.Context, resolvedData *ResolvedData, tableID TableID, fieldName string, values ValuesMutable) error
}

ValueMultiple can set any amount of row field values (even none) at resolve time. It can use the current row values, or load any previously loaded rows.

type ValueMultipleErr

type ValueMultipleErr struct {
	Err error
}

ValueMultipleErr is an implementation of ValueMultiple which always returns the passed error.

func (ValueMultipleErr) Resolve

func (v ValueMultipleErr) Resolve(ctx context.Context, resolvedData *ResolvedData, tableID TableID, fieldName string, values ValuesMutable) error

type ValueMultipleFunc

type ValueMultipleFunc func(ctx context.Context, resolvedData *ResolvedData, fieldName string, values ValuesMutable) error

ValueMultipleFunc is a functional implementation of ValueMultiple.

func (ValueMultipleFunc) Resolve

func (f ValueMultipleFunc) Resolve(ctx context.Context, resolvedData *ResolvedData, fieldName string, values ValuesMutable) error

type ValueRefFieldValueData

type ValueRefFieldValueData struct {
	SourceFieldName  string  // the field name of the current row to compare for equality.
	TableID          TableID // the table ID of the other table.
	CompareFieldName string  // the field name of the other table row (from TableID) to compare for equality.
	ReturnFieldName  string  // the field name of the other table row to have its value returned.
}

ValueRefFieldValueData is a Value which returns the value of a field of a row of the passed table where one of the other row's field value is equal to one of the current row's field value.

func ValueRefFieldValue

func ValueRefFieldValue(sourceFieldName string, tableID TableID, compareFieldName string,
	returnFieldName string) ValueRefFieldValueData

ValueRefFieldValue is a Value which returns the value of a field of a row of the passed table where one of the other row's field value is equal to one of the current row's field value.

func (ValueRefFieldValueData) ResolveValue

func (d ValueRefFieldValueData) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

func (ValueRefFieldValueData) TableDependencies

func (d ValueRefFieldValueData) TableDependencies() []TableID

type ValueRefIDData

type ValueRefIDData struct {
	TableID   TableID
	RefID     RefID
	FieldName string
}

ValueRefIDData represents a field value from a table row by its RefID. It implements Value, QueryRow, and can return a UpdateQuery.

func ValueRefID

func ValueRefID(tableID TableID, refID RefID, fieldName string) ValueRefIDData

ValueRefID represents a field value from a table row by its RefID. It implements Value, QueryRow, and can return a UpdateQuery.

func (ValueRefIDData) QueryRow

func (v ValueRefIDData) QueryRow(data *Data) (QueryRowResult, error)

func (ValueRefIDData) ResolveValue

func (v ValueRefIDData) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

func (ValueRefIDData) TableDependencies

func (v ValueRefIDData) TableDependencies() []TableID

func (ValueRefIDData) UpdateQuery

func (v ValueRefIDData) UpdateQuery(keyFields []string) UpdateQuery

type ValueStaticData

type ValueStaticData[T any] struct {
	Value T
}

ValueStaticData returns the passed static value every time it is resolved.

func ValueStatic

func ValueStatic[T any](value T) ValueStaticData[T]

ValueStatic returns the passed static value every time it is resolved.

func (ValueStaticData[T]) ResolveValue

func (u ValueStaticData[T]) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

type ValueTemplateData added in v2.0.6

type ValueTemplateData struct {
	Template string
	Args     map[string]any
}

ValueTemplateData is a Value that formats a string based on other field's values using "text/template".

func ValueTemplate added in v2.0.6

func ValueTemplate(template string, args map[string]any) ValueTemplateData

ValueTemplate is a Value that formats a string based on other field's values using "text/template".

func (ValueTemplateData) ResolveValue added in v2.0.6

func (v ValueTemplateData) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

func (ValueTemplateData) TableDependencies added in v2.0.6

func (v ValueTemplateData) TableDependencies() []TableID

type ValueUUIDData

type ValueUUIDData struct {
	Value uuid.UUID
}

ValueUUIDData returns a fixed uuid.UUID value.

func ValueUUID

func ValueUUID(value uuid.UUID) ValueUUIDData

ValueUUID returns a fixed uuid.UUID value.

func ValueUUIDRandom

func ValueUUIDRandom() ValueUUIDData

ValueUUIDRandom returns a fixed uuid.UUID value that was randomly generated on initialization.

func (ValueUUIDData) ResolveValue

func (u ValueUUIDData) ResolveValue(ctx context.Context, resolvedData *ResolvedData, values Values) (any, bool, error)

type Values

type Values interface {
	Get(fieldName string) (val any, exists bool) // gets the value of a field, returning whether the field exists.
	GetOrNil(fieldName string) any               // gets the value of a field, or nil if the field don't exist.
	GetDefault(fieldName string, def any) any    // gets the value of a field, or a default value if the field don't exist.
	All(yield func(string, any) bool)            // iterator of all the field values.
	Len() int                                    // returns the amount of field values.
}

Values represents a list of the row fields and values, similar to a map[string]any.

type ValuesMutable

type ValuesMutable interface {
	Values
	Set(fieldName string, val any)     // sets a field value.
	Insert(seq iter.Seq2[string, any]) // insert a list of field values.
	Delete(fieldName ...string)        // delete field values.
}

ValuesMutable is a Values that can be mutated.

func NewValues

func NewValues(val map[string]any) ValuesMutable

NewValues creates a new ValuesMutable.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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