diff options
| author | Stefan Majewsky <majewsky@gmx.net> | 2026-04-12 19:13:50 +0200 |
|---|---|---|
| committer | Stefan Majewsky <majewsky@gmx.net> | 2026-04-12 19:13:55 +0200 |
| commit | a23dd12a27237a5e0d6883cd30373408a2f28f6e (patch) | |
| tree | 633264b882173c21c93b0325a15f9c53398ba05b /oblast.go | |
| parent | 9b5b72a549643a9e611f55ae8154fa801c808e5b (diff) | |
| download | go-oblast-a23dd12a27237a5e0d6883cd30373408a2f28f6e.tar.gz | |
add initial sketches for Store.Insert, Store.Update
Currently extremely bad performance for some reason. Need to investigate.
Diffstat (limited to 'oblast.go')
| -rw-r--r-- | oblast.go | 51 |
1 files changed, 51 insertions, 0 deletions
@@ -43,6 +43,7 @@ package oblast // import "go.xyrillian.de/oblast" import ( "database/sql" "errors" + "reflect" "go.xyrillian.de/oblast/internal" ) @@ -79,3 +80,53 @@ var ( // ErrMultipleRows is returned by [Store.SelectOne] if the query returned multiple rows. var ErrMultipleRows = errors.New("sql: multiple rows in result set") + +// Store is the main interface of this library. +// +// It holds information on how to read and write data into record type R, +// and can also be used to execute autogenerated queries if the respective [PlanOption] values were provided during [NewStore]. +type Store[R any] struct { + dialect Dialect + plan internal.Plan +} + +// NewStore initializes a store for record type R. +// Returns an error if R is not a struct type. +// +// For the purpose of loading and storing records (i.e. instances of type R) into the database, +// this function establishes a mapping between fields of type R and database columns by inspecting the "db" tag. +// For example: +// +// type MyRecord struct { +// ID int64 `db:"record_id,auto"` +// Foo string `db:"foo"` +// Bar string +// Cache map[string]any `db:"-"` +// action func() +// } +// +// In this type: +// - The fields "ID" and "Foo" correspond to the database columns "record_id" and "foo" because of the declaration in the "db" tag. +// - The field "Bar" corresponds to the database column "Bar" because, when no "db" tag is given, the column name is set equal to the field name. +// - The field "Cache" is not mapped to any database column because it is declared with a "db" tag of "-". Loads and stores will ignore it. +// - The field "action" is private, so loads and stores will ignore it, too. +// +// Besides the declaration of a column name, the following extra tags are understood (as a comma-separated list following the column name): +// - "auto": During [Store.Insert], do not store this field's value. Instead, the database will auto-generate a value, which will be read back into the record. +func NewStore[R any](dialect Dialect, opts ...PlanOption) (Store[R], error) { + var popts internal.PlanOpts + for _, opt := range opts { + opt(&popts) + } + plan, err := internal.BuildPlan(reflect.TypeFor[R](), dialect, popts) + return Store[R]{dialect, plan}, err +} + +// MustNewStore is like [NewStore], but panics on error. +func MustNewStore[R any](dialect Dialect, opts ...PlanOption) Store[R] { + store, err := NewStore[R](dialect, opts...) + if err != nil { + panic(err.Error()) + } + return store +} |
