3
0

Add proper handling of unique-constraint errors

This commit is contained in:
Denis Arh
2020-08-19 15:26:33 +02:00
parent 6bfb1eebd9
commit b0ea1da89f
22 changed files with 212 additions and 136 deletions

View File

@@ -281,7 +281,7 @@ func (s Store) Search{{ pubIdent $.Types.Plural }}(ctx context.Context, f {{ $.T
{{ end -}}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
{{ end }}
@@ -309,7 +309,7 @@ func (s Store) Create{{ pubIdent $.Types.Singular }}(ctx context.Context, rr ...
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.{{ $.Types.Singular }}Table()).SetMap(s.internal{{ pubIdent $.Types.Singular }}Encoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -319,7 +319,7 @@ func (s Store) Create{{ pubIdent $.Types.Singular }}(ctx context.Context, rr ...
// Update{{ pubIdent $.Types.Singular }} updates one or more existing rows in {{ $.RDBMS.Table }}
func (s Store) Update{{ pubIdent $.Types.Singular }}(ctx context.Context, rr ... *{{ $.Types.GoType }}) error {
return s.PartialUpdate{{ pubIdent $.Types.Singular }}(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdate{{ pubIdent $.Types.Singular }}(ctx, nil, rr...))
}
// PartialUpdate{{ pubIdent $.Types.Singular }} updates one or more existing rows in {{ $.RDBMS.Table }}
@@ -343,7 +343,7 @@ func (s Store) PartialUpdate{{ pubIdent $.Types.Singular }}(ctx context.Context,
{{- end -}}
).Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -361,7 +361,7 @@ func (s Store) Remove{{ pubIdent $.Types.Singular }}(ctx context.Context, rr ...
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.{{ $.Types.Singular }}Table({{ printf "%q" .RDBMS.Alias }})).Where({{ template "filterByPrimaryKeys" $.Fields }},))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -372,19 +372,19 @@ func (s Store) Remove{{ pubIdent $.Types.Singular }}(ctx context.Context, rr ...
// Remove{{ pubIdent $.Types.Singular }}By{{ template "primaryKeySuffix" $.Fields }} removes row from the {{ $.RDBMS.Table }} table
func (s Store) Remove{{ pubIdent $.Types.Singular }}By{{ template "primaryKeySuffix" $.Fields }}(ctx context.Context {{ template "primaryKeyArgs" $.Fields }}) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.{{ $.Types.Singular }}Table({{ printf "%q" .RDBMS.Alias }})).Where({{ template "filterByPrimaryKeysWithArgs" $.Fields }},))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.{{ $.Types.Singular }}Table({{ printf "%q" .RDBMS.Alias }})).Where({{ template "filterByPrimaryKeysWithArgs" $.Fields }},)))
}
// Truncate{{ pubIdent $.Types.Plural }} removes all rows from the {{ $.RDBMS.Table }} table
func (s Store) Truncate{{ pubIdent $.Types.Plural }}(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.{{ $.Types.Singular }}Table())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.{{ $.Types.Singular }}Table()))
}
// ExecUpdate{{ pubIdent $.Types.Plural }} updates all matched (by cnd) rows in {{ $.RDBMS.Table }} with given data
func (s Store) ExecUpdate{{ pubIdent $.Types.Plural }}(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.{{ $.Types.Singular }}Table({{ printf "%q" .RDBMS.Alias }})).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.{{ $.Types.Singular }}Table({{ printf "%q" .RDBMS.Alias }})).Where(cnd).SetMap(set)))
}
// {{ $.Types.Singular }}Lookup prepares {{ $.Types.Singular }} query and executes it,

View File

@@ -15,10 +15,16 @@ func (e *storeError) Unwrap() error {
return e.err
}
func (e *storeError) Wrap(err error) error {
e.err = err
return e
}
var (
ErrNotFound = &storeError{msg: "not found"}
ErrNotFound = &storeError{msg: "not found"}
ErrNotUnique = &storeError{msg: "not unique"}
)
func Error(msg string, err error) error {
func WrappedError(err error, msg string, a ...interface{}) error {
return &storeError{msg, err}
}

View File

@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"github.com/Masterminds/squirrel"
"github.com/cortezaproject/corteza-server/store"
"github.com/cortezaproject/corteza-server/store/rdbms"
"github.com/go-sql-driver/mysql"
"go.uber.org/zap"
@@ -26,6 +27,7 @@ func New(ctx context.Context, dsn string) (s *Store, err error) {
cfg.PlaceholderFormat = squirrel.Question
cfg.TxRetryErrHandler = txRetryErrHandler
cfg.ErrorHandler = errorHandler
s = new(Store)
if s.Store, err = rdbms.New(ctx, cfg); err != nil {
@@ -105,3 +107,18 @@ func txRetryErrHandler(try int, err error) bool {
return false
}
func errorHandler(err error) error {
if err != nil {
if implErr, ok := err.(*mysql.MySQLError); ok {
// https://www.fromdual.com/de/mysql-error-codes-and-messages
switch implErr.Number {
case 1062: // Can't write, because of unique constraint, to table '%s'
return store.ErrNotUnique.Wrap(implErr)
}
}
}
return err
}

View File

@@ -4,8 +4,9 @@ import (
"context"
"fmt"
"github.com/Masterminds/squirrel"
"github.com/cortezaproject/corteza-server/store"
"github.com/cortezaproject/corteza-server/store/rdbms"
_ "github.com/lib/pq"
"github.com/lib/pq"
"go.uber.org/zap"
"net/url"
"strings"
@@ -25,6 +26,7 @@ func New(ctx context.Context, dsn string) (s *Store, err error) {
}
cfg.PlaceholderFormat = squirrel.Dollar
cfg.ErrorHandler = errorHandler
s = new(Store)
if s.Store, err = rdbms.New(ctx, cfg); err != nil {
@@ -68,3 +70,16 @@ func ProcDataSourceName(dsn string) (c *rdbms.Config, err error) {
DBName: strings.Trim(u.Path, "/"),
}, nil
}
func errorHandler(err error) error {
if err != nil {
if implErr, ok := err.(*pq.Error); ok {
switch implErr.Code.Name() {
case "unique_violation":
return store.ErrNotUnique.Wrap(implErr)
}
}
}
return err
}

View File

@@ -188,7 +188,7 @@ func (s Store) SearchActionlogs(ctx context.Context, f actionlog.Filter) (action
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// CreateActionlog creates one or more rows in actionlog table
@@ -201,7 +201,7 @@ func (s Store) CreateActionlog(ctx context.Context, rr ...*actionlog.Action) err
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ActionlogTable()).SetMap(s.internalActionlogEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -211,7 +211,7 @@ func (s Store) CreateActionlog(ctx context.Context, rr ...*actionlog.Action) err
// UpdateActionlog updates one or more existing rows in actionlog
func (s Store) UpdateActionlog(ctx context.Context, rr ...*actionlog.Action) error {
return s.PartialUpdateActionlog(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateActionlog(ctx, nil, rr...))
}
// PartialUpdateActionlog updates one or more existing rows in actionlog
@@ -229,7 +229,7 @@ func (s Store) PartialUpdateActionlog(ctx context.Context, onlyColumns []string,
squirrel.Eq{s.preprocessColumn("alg.id", ""): s.preprocessValue(res.ID, "")},
s.internalActionlogEncoder(res).Skip("id").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -247,7 +247,7 @@ func (s Store) RemoveActionlog(ctx context.Context, rr ...*actionlog.Action) err
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ActionlogTable("alg")).Where(squirrel.Eq{s.preprocessColumn("alg.id", ""): s.preprocessValue(res.ID, "")}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -257,17 +257,17 @@ func (s Store) RemoveActionlog(ctx context.Context, rr ...*actionlog.Action) err
// RemoveActionlogByID removes row from the actionlog table
func (s Store) RemoveActionlogByID(ctx context.Context, ID uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ActionlogTable("alg")).Where(squirrel.Eq{s.preprocessColumn("alg.id", ""): s.preprocessValue(ID, "")}))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ActionlogTable("alg")).Where(squirrel.Eq{s.preprocessColumn("alg.id", ""): s.preprocessValue(ID, "")})))
}
// TruncateActionlogs removes all rows from the actionlog table
func (s Store) TruncateActionlogs(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.ActionlogTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.ActionlogTable()))
}
// ExecUpdateActionlogs updates all matched (by cnd) rows in actionlog with given data
func (s Store) ExecUpdateActionlogs(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ActionlogTable("alg")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.ActionlogTable("alg")).Where(cnd).SetMap(set)))
}
// ActionlogLookup prepares Actionlog query and executes it,

View File

@@ -219,7 +219,7 @@ func (s Store) SearchApplications(ctx context.Context, f types.ApplicationFilter
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// LookupApplicationByID searches for application by ID
@@ -241,7 +241,7 @@ func (s Store) CreateApplication(ctx context.Context, rr ...*types.Application)
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ApplicationTable()).SetMap(s.internalApplicationEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -251,7 +251,7 @@ func (s Store) CreateApplication(ctx context.Context, rr ...*types.Application)
// UpdateApplication updates one or more existing rows in applications
func (s Store) UpdateApplication(ctx context.Context, rr ...*types.Application) error {
return s.PartialUpdateApplication(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateApplication(ctx, nil, rr...))
}
// PartialUpdateApplication updates one or more existing rows in applications
@@ -269,7 +269,7 @@ func (s Store) PartialUpdateApplication(ctx context.Context, onlyColumns []strin
squirrel.Eq{s.preprocessColumn("app.id", ""): s.preprocessValue(res.ID, "")},
s.internalApplicationEncoder(res).Skip("id").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -287,7 +287,7 @@ func (s Store) RemoveApplication(ctx context.Context, rr ...*types.Application)
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ApplicationTable("app")).Where(squirrel.Eq{s.preprocessColumn("app.id", ""): s.preprocessValue(res.ID, "")}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -297,17 +297,17 @@ func (s Store) RemoveApplication(ctx context.Context, rr ...*types.Application)
// RemoveApplicationByID removes row from the applications table
func (s Store) RemoveApplicationByID(ctx context.Context, ID uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ApplicationTable("app")).Where(squirrel.Eq{s.preprocessColumn("app.id", ""): s.preprocessValue(ID, "")}))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ApplicationTable("app")).Where(squirrel.Eq{s.preprocessColumn("app.id", ""): s.preprocessValue(ID, "")})))
}
// TruncateApplications removes all rows from the applications table
func (s Store) TruncateApplications(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.ApplicationTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.ApplicationTable()))
}
// ExecUpdateApplications updates all matched (by cnd) rows in applications with given data
func (s Store) ExecUpdateApplications(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ApplicationTable("app")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.ApplicationTable("app")).Where(cnd).SetMap(set)))
}
// ApplicationLookup prepares Application query and executes it,

View File

@@ -64,7 +64,7 @@ func (s Store) SearchAttachments(ctx context.Context, f types.AttachmentFilter)
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// LookupAttachmentByID searches for attachment by its ID
@@ -86,7 +86,7 @@ func (s Store) CreateAttachment(ctx context.Context, rr ...*types.Attachment) er
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.AttachmentTable()).SetMap(s.internalAttachmentEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -96,7 +96,7 @@ func (s Store) CreateAttachment(ctx context.Context, rr ...*types.Attachment) er
// UpdateAttachment updates one or more existing rows in attachments
func (s Store) UpdateAttachment(ctx context.Context, rr ...*types.Attachment) error {
return s.PartialUpdateAttachment(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateAttachment(ctx, nil, rr...))
}
// PartialUpdateAttachment updates one or more existing rows in attachments
@@ -114,7 +114,7 @@ func (s Store) PartialUpdateAttachment(ctx context.Context, onlyColumns []string
squirrel.Eq{s.preprocessColumn("att.id", ""): s.preprocessValue(res.ID, "")},
s.internalAttachmentEncoder(res).Skip("id").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -132,7 +132,7 @@ func (s Store) RemoveAttachment(ctx context.Context, rr ...*types.Attachment) er
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.AttachmentTable("att")).Where(squirrel.Eq{s.preprocessColumn("att.id", ""): s.preprocessValue(res.ID, "")}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -142,17 +142,17 @@ func (s Store) RemoveAttachment(ctx context.Context, rr ...*types.Attachment) er
// RemoveAttachmentByID removes row from the attachments table
func (s Store) RemoveAttachmentByID(ctx context.Context, ID uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.AttachmentTable("att")).Where(squirrel.Eq{s.preprocessColumn("att.id", ""): s.preprocessValue(ID, "")}))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.AttachmentTable("att")).Where(squirrel.Eq{s.preprocessColumn("att.id", ""): s.preprocessValue(ID, "")})))
}
// TruncateAttachments removes all rows from the attachments table
func (s Store) TruncateAttachments(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.AttachmentTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.AttachmentTable()))
}
// ExecUpdateAttachments updates all matched (by cnd) rows in attachments with given data
func (s Store) ExecUpdateAttachments(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.AttachmentTable("att")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.AttachmentTable("att")).Where(cnd).SetMap(set)))
}
// AttachmentLookup prepares Attachment query and executes it,

View File

@@ -219,7 +219,7 @@ func (s Store) SearchComposeCharts(ctx context.Context, f types.ChartFilter) (ty
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// LookupComposeChartByID searches for compose chart by ID
@@ -248,7 +248,7 @@ func (s Store) CreateComposeChart(ctx context.Context, rr ...*types.Chart) error
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ComposeChartTable()).SetMap(s.internalComposeChartEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -258,7 +258,7 @@ func (s Store) CreateComposeChart(ctx context.Context, rr ...*types.Chart) error
// UpdateComposeChart updates one or more existing rows in compose_chart
func (s Store) UpdateComposeChart(ctx context.Context, rr ...*types.Chart) error {
return s.PartialUpdateComposeChart(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateComposeChart(ctx, nil, rr...))
}
// PartialUpdateComposeChart updates one or more existing rows in compose_chart
@@ -276,7 +276,7 @@ func (s Store) PartialUpdateComposeChart(ctx context.Context, onlyColumns []stri
squirrel.Eq{s.preprocessColumn("cch.id", ""): s.preprocessValue(res.ID, "")},
s.internalComposeChartEncoder(res).Skip("id").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -294,7 +294,7 @@ func (s Store) RemoveComposeChart(ctx context.Context, rr ...*types.Chart) error
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeChartTable("cch")).Where(squirrel.Eq{s.preprocessColumn("cch.id", ""): s.preprocessValue(res.ID, "")}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -304,17 +304,17 @@ func (s Store) RemoveComposeChart(ctx context.Context, rr ...*types.Chart) error
// RemoveComposeChartByID removes row from the compose_chart table
func (s Store) RemoveComposeChartByID(ctx context.Context, ID uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeChartTable("cch")).Where(squirrel.Eq{s.preprocessColumn("cch.id", ""): s.preprocessValue(ID, "")}))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeChartTable("cch")).Where(squirrel.Eq{s.preprocessColumn("cch.id", ""): s.preprocessValue(ID, "")})))
}
// TruncateComposeCharts removes all rows from the compose_chart table
func (s Store) TruncateComposeCharts(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.ComposeChartTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.ComposeChartTable()))
}
// ExecUpdateComposeCharts updates all matched (by cnd) rows in compose_chart with given data
func (s Store) ExecUpdateComposeCharts(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeChartTable("cch")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeChartTable("cch")).Where(cnd).SetMap(set)))
}
// ComposeChartLookup prepares ComposeChart query and executes it,

View File

@@ -28,7 +28,7 @@ func (s Store) CreateComposeModuleField(ctx context.Context, rr ...*types.Module
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ComposeModuleFieldTable()).SetMap(s.internalComposeModuleFieldEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -38,7 +38,7 @@ func (s Store) CreateComposeModuleField(ctx context.Context, rr ...*types.Module
// UpdateComposeModuleField updates one or more existing rows in compose_module_field
func (s Store) UpdateComposeModuleField(ctx context.Context, rr ...*types.ModuleField) error {
return s.PartialUpdateComposeModuleField(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateComposeModuleField(ctx, nil, rr...))
}
// PartialUpdateComposeModuleField updates one or more existing rows in compose_module_field
@@ -56,7 +56,7 @@ func (s Store) PartialUpdateComposeModuleField(ctx context.Context, onlyColumns
squirrel.Eq{s.preprocessColumn("cmf.id", ""): s.preprocessValue(res.ID, "")},
s.internalComposeModuleFieldEncoder(res).Skip("id").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -74,7 +74,7 @@ func (s Store) RemoveComposeModuleField(ctx context.Context, rr ...*types.Module
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeModuleFieldTable("cmf")).Where(squirrel.Eq{s.preprocessColumn("cmf.id", ""): s.preprocessValue(res.ID, "")}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -84,17 +84,17 @@ func (s Store) RemoveComposeModuleField(ctx context.Context, rr ...*types.Module
// RemoveComposeModuleFieldByID removes row from the compose_module_field table
func (s Store) RemoveComposeModuleFieldByID(ctx context.Context, ID uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeModuleFieldTable("cmf")).Where(squirrel.Eq{s.preprocessColumn("cmf.id", ""): s.preprocessValue(ID, "")}))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeModuleFieldTable("cmf")).Where(squirrel.Eq{s.preprocessColumn("cmf.id", ""): s.preprocessValue(ID, "")})))
}
// TruncateComposeModuleFields removes all rows from the compose_module_field table
func (s Store) TruncateComposeModuleFields(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.ComposeModuleFieldTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.ComposeModuleFieldTable()))
}
// ExecUpdateComposeModuleFields updates all matched (by cnd) rows in compose_module_field with given data
func (s Store) ExecUpdateComposeModuleFields(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeModuleFieldTable("cmf")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeModuleFieldTable("cmf")).Where(cnd).SetMap(set)))
}
// ComposeModuleFieldLookup prepares ComposeModuleField query and executes it,

View File

@@ -219,7 +219,7 @@ func (s Store) SearchComposeModules(ctx context.Context, f types.ModuleFilter) (
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// LookupComposeModuleByHandle searches for compose module by handle (case-insensitive)
@@ -248,7 +248,7 @@ func (s Store) CreateComposeModule(ctx context.Context, rr ...*types.Module) err
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ComposeModuleTable()).SetMap(s.internalComposeModuleEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -258,7 +258,7 @@ func (s Store) CreateComposeModule(ctx context.Context, rr ...*types.Module) err
// UpdateComposeModule updates one or more existing rows in compose_module
func (s Store) UpdateComposeModule(ctx context.Context, rr ...*types.Module) error {
return s.PartialUpdateComposeModule(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateComposeModule(ctx, nil, rr...))
}
// PartialUpdateComposeModule updates one or more existing rows in compose_module
@@ -276,7 +276,7 @@ func (s Store) PartialUpdateComposeModule(ctx context.Context, onlyColumns []str
squirrel.Eq{s.preprocessColumn("cmd.id", ""): s.preprocessValue(res.ID, "")},
s.internalComposeModuleEncoder(res).Skip("id").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -294,7 +294,7 @@ func (s Store) RemoveComposeModule(ctx context.Context, rr ...*types.Module) err
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeModuleTable("cmd")).Where(squirrel.Eq{s.preprocessColumn("cmd.id", ""): s.preprocessValue(res.ID, "")}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -304,17 +304,17 @@ func (s Store) RemoveComposeModule(ctx context.Context, rr ...*types.Module) err
// RemoveComposeModuleByID removes row from the compose_module table
func (s Store) RemoveComposeModuleByID(ctx context.Context, ID uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeModuleTable("cmd")).Where(squirrel.Eq{s.preprocessColumn("cmd.id", ""): s.preprocessValue(ID, "")}))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeModuleTable("cmd")).Where(squirrel.Eq{s.preprocessColumn("cmd.id", ""): s.preprocessValue(ID, "")})))
}
// TruncateComposeModules removes all rows from the compose_module table
func (s Store) TruncateComposeModules(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.ComposeModuleTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.ComposeModuleTable()))
}
// ExecUpdateComposeModules updates all matched (by cnd) rows in compose_module with given data
func (s Store) ExecUpdateComposeModules(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeModuleTable("cmd")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeModuleTable("cmd")).Where(cnd).SetMap(set)))
}
// ComposeModuleLookup prepares ComposeModule query and executes it,

View File

@@ -219,7 +219,7 @@ func (s Store) SearchComposeNamespaces(ctx context.Context, f types.NamespaceFil
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// LookupComposeNamespaceBySlug searches for namespace by slug (case-insensitive)
@@ -248,7 +248,7 @@ func (s Store) CreateComposeNamespace(ctx context.Context, rr ...*types.Namespac
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ComposeNamespaceTable()).SetMap(s.internalComposeNamespaceEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -258,7 +258,7 @@ func (s Store) CreateComposeNamespace(ctx context.Context, rr ...*types.Namespac
// UpdateComposeNamespace updates one or more existing rows in compose_namespace
func (s Store) UpdateComposeNamespace(ctx context.Context, rr ...*types.Namespace) error {
return s.PartialUpdateComposeNamespace(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateComposeNamespace(ctx, nil, rr...))
}
// PartialUpdateComposeNamespace updates one or more existing rows in compose_namespace
@@ -276,7 +276,7 @@ func (s Store) PartialUpdateComposeNamespace(ctx context.Context, onlyColumns []
squirrel.Eq{s.preprocessColumn("cns.id", ""): s.preprocessValue(res.ID, "")},
s.internalComposeNamespaceEncoder(res).Skip("id").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -294,7 +294,7 @@ func (s Store) RemoveComposeNamespace(ctx context.Context, rr ...*types.Namespac
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeNamespaceTable("cns")).Where(squirrel.Eq{s.preprocessColumn("cns.id", ""): s.preprocessValue(res.ID, "")}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -304,17 +304,17 @@ func (s Store) RemoveComposeNamespace(ctx context.Context, rr ...*types.Namespac
// RemoveComposeNamespaceByID removes row from the compose_namespace table
func (s Store) RemoveComposeNamespaceByID(ctx context.Context, ID uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeNamespaceTable("cns")).Where(squirrel.Eq{s.preprocessColumn("cns.id", ""): s.preprocessValue(ID, "")}))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeNamespaceTable("cns")).Where(squirrel.Eq{s.preprocessColumn("cns.id", ""): s.preprocessValue(ID, "")})))
}
// TruncateComposeNamespaces removes all rows from the compose_namespace table
func (s Store) TruncateComposeNamespaces(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.ComposeNamespaceTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.ComposeNamespaceTable()))
}
// ExecUpdateComposeNamespaces updates all matched (by cnd) rows in compose_namespace with given data
func (s Store) ExecUpdateComposeNamespaces(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeNamespaceTable("cns")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeNamespaceTable("cns")).Where(cnd).SetMap(set)))
}
// ComposeNamespaceLookup prepares ComposeNamespace query and executes it,

View File

@@ -219,7 +219,7 @@ func (s Store) SearchComposePages(ctx context.Context, f types.PageFilter) (type
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// LookupComposePageByHandle searches for page chart by handle (case-insensitive)
@@ -248,7 +248,7 @@ func (s Store) CreateComposePage(ctx context.Context, rr ...*types.Page) error {
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ComposePageTable()).SetMap(s.internalComposePageEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -258,7 +258,7 @@ func (s Store) CreateComposePage(ctx context.Context, rr ...*types.Page) error {
// UpdateComposePage updates one or more existing rows in compose_page
func (s Store) UpdateComposePage(ctx context.Context, rr ...*types.Page) error {
return s.PartialUpdateComposePage(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateComposePage(ctx, nil, rr...))
}
// PartialUpdateComposePage updates one or more existing rows in compose_page
@@ -276,7 +276,7 @@ func (s Store) PartialUpdateComposePage(ctx context.Context, onlyColumns []strin
squirrel.Eq{s.preprocessColumn("cpg.id", ""): s.preprocessValue(res.ID, "")},
s.internalComposePageEncoder(res).Skip("id").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -294,7 +294,7 @@ func (s Store) RemoveComposePage(ctx context.Context, rr ...*types.Page) error {
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposePageTable("cpg")).Where(squirrel.Eq{s.preprocessColumn("cpg.id", ""): s.preprocessValue(res.ID, "")}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -304,17 +304,17 @@ func (s Store) RemoveComposePage(ctx context.Context, rr ...*types.Page) error {
// RemoveComposePageByID removes row from the compose_page table
func (s Store) RemoveComposePageByID(ctx context.Context, ID uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposePageTable("cpg")).Where(squirrel.Eq{s.preprocessColumn("cpg.id", ""): s.preprocessValue(ID, "")}))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposePageTable("cpg")).Where(squirrel.Eq{s.preprocessColumn("cpg.id", ""): s.preprocessValue(ID, "")})))
}
// TruncateComposePages removes all rows from the compose_page table
func (s Store) TruncateComposePages(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.ComposePageTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.ComposePageTable()))
}
// ExecUpdateComposePages updates all matched (by cnd) rows in compose_page with given data
func (s Store) ExecUpdateComposePages(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposePageTable("cpg")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposePageTable("cpg")).Where(cnd).SetMap(set)))
}
// ComposePageLookup prepares ComposePage query and executes it,

View File

@@ -64,7 +64,7 @@ func (s Store) SearchCredentials(ctx context.Context, f types.CredentialsFilter)
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// LookupCredentialsByID searches for credentials by ID
@@ -86,7 +86,7 @@ func (s Store) CreateCredentials(ctx context.Context, rr ...*types.Credentials)
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.CredentialsTable()).SetMap(s.internalCredentialsEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -96,7 +96,7 @@ func (s Store) CreateCredentials(ctx context.Context, rr ...*types.Credentials)
// UpdateCredentials updates one or more existing rows in credentials
func (s Store) UpdateCredentials(ctx context.Context, rr ...*types.Credentials) error {
return s.PartialUpdateCredentials(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateCredentials(ctx, nil, rr...))
}
// PartialUpdateCredentials updates one or more existing rows in credentials
@@ -114,7 +114,7 @@ func (s Store) PartialUpdateCredentials(ctx context.Context, onlyColumns []strin
squirrel.Eq{s.preprocessColumn("crd.id", ""): s.preprocessValue(res.ID, "")},
s.internalCredentialsEncoder(res).Skip("id").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -132,7 +132,7 @@ func (s Store) RemoveCredentials(ctx context.Context, rr ...*types.Credentials)
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.CredentialsTable("crd")).Where(squirrel.Eq{s.preprocessColumn("crd.id", ""): s.preprocessValue(res.ID, "")}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -142,17 +142,17 @@ func (s Store) RemoveCredentials(ctx context.Context, rr ...*types.Credentials)
// RemoveCredentialsByID removes row from the credentials table
func (s Store) RemoveCredentialsByID(ctx context.Context, ID uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.CredentialsTable("crd")).Where(squirrel.Eq{s.preprocessColumn("crd.id", ""): s.preprocessValue(ID, "")}))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.CredentialsTable("crd")).Where(squirrel.Eq{s.preprocessColumn("crd.id", ""): s.preprocessValue(ID, "")})))
}
// TruncateCredentials removes all rows from the credentials table
func (s Store) TruncateCredentials(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.CredentialsTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.CredentialsTable()))
}
// ExecUpdateCredentials updates all matched (by cnd) rows in credentials with given data
func (s Store) ExecUpdateCredentials(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.CredentialsTable("crd")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.CredentialsTable("crd")).Where(cnd).SetMap(set)))
}
// CredentialsLookup prepares Credentials query and executes it,

View File

@@ -61,7 +61,7 @@ func (s Store) SearchRbacRules(ctx context.Context, f permissions.RuleFilter) (p
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// CreateRbacRule creates one or more rows in rbac_rules table
@@ -74,7 +74,7 @@ func (s Store) CreateRbacRule(ctx context.Context, rr ...*permissions.Rule) erro
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.RbacRuleTable()).SetMap(s.internalRbacRuleEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -84,7 +84,7 @@ func (s Store) CreateRbacRule(ctx context.Context, rr ...*permissions.Rule) erro
// UpdateRbacRule updates one or more existing rows in rbac_rules
func (s Store) UpdateRbacRule(ctx context.Context, rr ...*permissions.Rule) error {
return s.PartialUpdateRbacRule(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateRbacRule(ctx, nil, rr...))
}
// PartialUpdateRbacRule updates one or more existing rows in rbac_rules
@@ -105,7 +105,7 @@ func (s Store) PartialUpdateRbacRule(ctx context.Context, onlyColumns []string,
},
s.internalRbacRuleEncoder(res).Skip("rel_role", "resource", "operation").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -126,7 +126,7 @@ func (s Store) RemoveRbacRule(ctx context.Context, rr ...*permissions.Rule) erro
s.preprocessColumn("rls.operation", ""): s.preprocessValue(res.Operation, ""),
}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -136,22 +136,22 @@ func (s Store) RemoveRbacRule(ctx context.Context, rr ...*permissions.Rule) erro
// RemoveRbacRuleByRoleIDResourceOperation removes row from the rbac_rules table
func (s Store) RemoveRbacRuleByRoleIDResourceOperation(ctx context.Context, roleID uint64, resource string, operation string) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.RbacRuleTable("rls")).Where(squirrel.Eq{s.preprocessColumn("rls.rel_role", ""): s.preprocessValue(roleID, ""),
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.RbacRuleTable("rls")).Where(squirrel.Eq{s.preprocessColumn("rls.rel_role", ""): s.preprocessValue(roleID, ""),
s.preprocessColumn("rls.resource", ""): s.preprocessValue(resource, ""),
s.preprocessColumn("rls.operation", ""): s.preprocessValue(operation, ""),
}))
})))
}
// TruncateRbacRules removes all rows from the rbac_rules table
func (s Store) TruncateRbacRules(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.RbacRuleTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.RbacRuleTable()))
}
// ExecUpdateRbacRules updates all matched (by cnd) rows in rbac_rules with given data
func (s Store) ExecUpdateRbacRules(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.RbacRuleTable("rls")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.RbacRuleTable("rls")).Where(cnd).SetMap(set)))
}
// RbacRuleLookup prepares RbacRule query and executes it,

View File

@@ -26,6 +26,7 @@ type (
txRetryOnErrHandler func(int, error) bool
columnPreprocFn func(string, string) string
valuePreprocFn func(interface{}, string) interface{}
errorHandler func(error) error
schemaUpgradeGenerator interface {
TableExists(string) bool
@@ -58,6 +59,8 @@ type (
ColumnPreprocessors map[string]columnPreprocFn
ValuePreprocessors map[string]valuePreprocFn
ErrorHandler errorHandler
// Implementations can override internal RDBMS row scanners
RowScanners map[string]interface{}
}
@@ -122,6 +125,10 @@ func New(ctx context.Context, cfg *Config) (*Store, error) {
s.config.TxRetryErrHandler = TxNoRetry
}
if s.config.ErrorHandler == nil {
s.config.ErrorHandler = ErrHandlerFallthrough
}
if err := s.Connect(ctx); err != nil {
return nil, err
}
@@ -270,7 +277,6 @@ func ExecuteSqlizer(ctx context.Context, db sqlx.ExecerContext, sqlizer squirrel
}
_, err = db.ExecContext(ctx, query, args...)
return err
}
@@ -335,4 +341,5 @@ func Tx(ctx context.Context, db *sqlx.DB, cfg *Config, txOpt *sql.TxOptions, tas
// TxNoRetry - Transaction retry handler
//
// Only returns false so transactions will never retry
func TxNoRetry(int, error) bool { return false }
func TxNoRetry(int, error) bool { return false }
func ErrHandlerFallthrough(err error) error { return err }

View File

@@ -219,7 +219,7 @@ func (s Store) SearchReminders(ctx context.Context, f types.ReminderFilter) (typ
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// LookupReminderByID searches for reminder by its ID
@@ -241,7 +241,7 @@ func (s Store) CreateReminder(ctx context.Context, rr ...*types.Reminder) error
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ReminderTable()).SetMap(s.internalReminderEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -251,7 +251,7 @@ func (s Store) CreateReminder(ctx context.Context, rr ...*types.Reminder) error
// UpdateReminder updates one or more existing rows in reminders
func (s Store) UpdateReminder(ctx context.Context, rr ...*types.Reminder) error {
return s.PartialUpdateReminder(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateReminder(ctx, nil, rr...))
}
// PartialUpdateReminder updates one or more existing rows in reminders
@@ -269,7 +269,7 @@ func (s Store) PartialUpdateReminder(ctx context.Context, onlyColumns []string,
squirrel.Eq{s.preprocessColumn("rmd.id", ""): s.preprocessValue(res.ID, "")},
s.internalReminderEncoder(res).Skip("id").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -287,7 +287,7 @@ func (s Store) RemoveReminder(ctx context.Context, rr ...*types.Reminder) error
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ReminderTable("rmd")).Where(squirrel.Eq{s.preprocessColumn("rmd.id", ""): s.preprocessValue(res.ID, "")}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -297,17 +297,17 @@ func (s Store) RemoveReminder(ctx context.Context, rr ...*types.Reminder) error
// RemoveReminderByID removes row from the reminders table
func (s Store) RemoveReminderByID(ctx context.Context, ID uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ReminderTable("rmd")).Where(squirrel.Eq{s.preprocessColumn("rmd.id", ""): s.preprocessValue(ID, "")}))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ReminderTable("rmd")).Where(squirrel.Eq{s.preprocessColumn("rmd.id", ""): s.preprocessValue(ID, "")})))
}
// TruncateReminders removes all rows from the reminders table
func (s Store) TruncateReminders(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.ReminderTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.ReminderTable()))
}
// ExecUpdateReminders updates all matched (by cnd) rows in reminders with given data
func (s Store) ExecUpdateReminders(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ReminderTable("rmd")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.ReminderTable("rmd")).Where(cnd).SetMap(set)))
}
// ReminderLookup prepares Reminder query and executes it,

View File

@@ -61,7 +61,7 @@ func (s Store) SearchRoleMembers(ctx context.Context, f types.RoleMemberFilter)
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// CreateRoleMember creates one or more rows in role_members table
@@ -74,7 +74,7 @@ func (s Store) CreateRoleMember(ctx context.Context, rr ...*types.RoleMember) er
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.RoleMemberTable()).SetMap(s.internalRoleMemberEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -84,7 +84,7 @@ func (s Store) CreateRoleMember(ctx context.Context, rr ...*types.RoleMember) er
// UpdateRoleMember updates one or more existing rows in role_members
func (s Store) UpdateRoleMember(ctx context.Context, rr ...*types.RoleMember) error {
return s.PartialUpdateRoleMember(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateRoleMember(ctx, nil, rr...))
}
// PartialUpdateRoleMember updates one or more existing rows in role_members
@@ -104,7 +104,7 @@ func (s Store) PartialUpdateRoleMember(ctx context.Context, onlyColumns []string
},
s.internalRoleMemberEncoder(res).Skip("rel_user", "rel_role").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -124,7 +124,7 @@ func (s Store) RemoveRoleMember(ctx context.Context, rr ...*types.RoleMember) er
s.preprocessColumn("rm.rel_role", ""): s.preprocessValue(res.RoleID, ""),
}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -134,20 +134,20 @@ func (s Store) RemoveRoleMember(ctx context.Context, rr ...*types.RoleMember) er
// RemoveRoleMemberByUserIDRoleID removes row from the role_members table
func (s Store) RemoveRoleMemberByUserIDRoleID(ctx context.Context, userID uint64, roleID uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.RoleMemberTable("rm")).Where(squirrel.Eq{s.preprocessColumn("rm.rel_user", ""): s.preprocessValue(userID, ""),
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.RoleMemberTable("rm")).Where(squirrel.Eq{s.preprocessColumn("rm.rel_user", ""): s.preprocessValue(userID, ""),
s.preprocessColumn("rm.rel_role", ""): s.preprocessValue(roleID, ""),
}))
})))
}
// TruncateRoleMembers removes all rows from the role_members table
func (s Store) TruncateRoleMembers(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.RoleMemberTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.RoleMemberTable()))
}
// ExecUpdateRoleMembers updates all matched (by cnd) rows in role_members with given data
func (s Store) ExecUpdateRoleMembers(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.RoleMemberTable("rm")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.RoleMemberTable("rm")).Where(cnd).SetMap(set)))
}
// RoleMemberLookup prepares RoleMember query and executes it,

View File

@@ -219,7 +219,7 @@ func (s Store) SearchRoles(ctx context.Context, f types.RoleFilter) (types.RoleS
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// LookupRoleByID searches for role by ID
@@ -263,7 +263,7 @@ func (s Store) CreateRole(ctx context.Context, rr ...*types.Role) error {
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.RoleTable()).SetMap(s.internalRoleEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -273,7 +273,7 @@ func (s Store) CreateRole(ctx context.Context, rr ...*types.Role) error {
// UpdateRole updates one or more existing rows in roles
func (s Store) UpdateRole(ctx context.Context, rr ...*types.Role) error {
return s.PartialUpdateRole(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateRole(ctx, nil, rr...))
}
// PartialUpdateRole updates one or more existing rows in roles
@@ -291,7 +291,7 @@ func (s Store) PartialUpdateRole(ctx context.Context, onlyColumns []string, rr .
squirrel.Eq{s.preprocessColumn("rl.id", ""): s.preprocessValue(res.ID, "")},
s.internalRoleEncoder(res).Skip("id").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -309,7 +309,7 @@ func (s Store) RemoveRole(ctx context.Context, rr ...*types.Role) error {
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.RoleTable("rl")).Where(squirrel.Eq{s.preprocessColumn("rl.id", ""): s.preprocessValue(res.ID, "")}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -319,17 +319,17 @@ func (s Store) RemoveRole(ctx context.Context, rr ...*types.Role) error {
// RemoveRoleByID removes row from the roles table
func (s Store) RemoveRoleByID(ctx context.Context, ID uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.RoleTable("rl")).Where(squirrel.Eq{s.preprocessColumn("rl.id", ""): s.preprocessValue(ID, "")}))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.RoleTable("rl")).Where(squirrel.Eq{s.preprocessColumn("rl.id", ""): s.preprocessValue(ID, "")})))
}
// TruncateRoles removes all rows from the roles table
func (s Store) TruncateRoles(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.RoleTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.RoleTable()))
}
// ExecUpdateRoles updates all matched (by cnd) rows in roles with given data
func (s Store) ExecUpdateRoles(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.RoleTable("rl")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.RoleTable("rl")).Where(cnd).SetMap(set)))
}
// RoleLookup prepares Role query and executes it,

View File

@@ -64,7 +64,7 @@ func (s Store) SearchSettings(ctx context.Context, f types.SettingsFilter) (type
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// LookupSettingByNameOwnedBy searches for settings by name and owner
@@ -85,7 +85,7 @@ func (s Store) CreateSetting(ctx context.Context, rr ...*types.SettingValue) err
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.SettingTable()).SetMap(s.internalSettingEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -95,7 +95,7 @@ func (s Store) CreateSetting(ctx context.Context, rr ...*types.SettingValue) err
// UpdateSetting updates one or more existing rows in settings
func (s Store) UpdateSetting(ctx context.Context, rr ...*types.SettingValue) error {
return s.PartialUpdateSetting(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateSetting(ctx, nil, rr...))
}
// PartialUpdateSetting updates one or more existing rows in settings
@@ -115,7 +115,7 @@ func (s Store) PartialUpdateSetting(ctx context.Context, onlyColumns []string, r
},
s.internalSettingEncoder(res).Skip("name", "rel_owner").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -135,7 +135,7 @@ func (s Store) RemoveSetting(ctx context.Context, rr ...*types.SettingValue) err
s.preprocessColumn("st.rel_owner", ""): s.preprocessValue(res.OwnedBy, ""),
}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -145,20 +145,20 @@ func (s Store) RemoveSetting(ctx context.Context, rr ...*types.SettingValue) err
// RemoveSettingByNameOwnedBy removes row from the settings table
func (s Store) RemoveSettingByNameOwnedBy(ctx context.Context, name string, ownedBy uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.SettingTable("st")).Where(squirrel.Eq{s.preprocessColumn("st.name", ""): s.preprocessValue(name, ""),
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.SettingTable("st")).Where(squirrel.Eq{s.preprocessColumn("st.name", ""): s.preprocessValue(name, ""),
s.preprocessColumn("st.rel_owner", ""): s.preprocessValue(ownedBy, ""),
}))
})))
}
// TruncateSettings removes all rows from the settings table
func (s Store) TruncateSettings(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.SettingTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.SettingTable()))
}
// ExecUpdateSettings updates all matched (by cnd) rows in settings with given data
func (s Store) ExecUpdateSettings(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.SettingTable("st")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.SettingTable("st")).Where(cnd).SetMap(set)))
}
// SettingLookup prepares Setting query and executes it,

View File

@@ -219,7 +219,7 @@ func (s Store) SearchUsers(ctx context.Context, f types.UserFilter) (types.UserS
}
)
return set, f, fetch()
return set, f, s.config.ErrorHandler(fetch())
}
// LookupUserByID searches for user by ID
@@ -274,7 +274,7 @@ func (s Store) CreateUser(ctx context.Context, rr ...*types.User) error {
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.UserTable()).SetMap(s.internalUserEncoder(res)))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -284,7 +284,7 @@ func (s Store) CreateUser(ctx context.Context, rr ...*types.User) error {
// UpdateUser updates one or more existing rows in users
func (s Store) UpdateUser(ctx context.Context, rr ...*types.User) error {
return s.PartialUpdateUser(ctx, nil, rr...)
return s.config.ErrorHandler(s.PartialUpdateUser(ctx, nil, rr...))
}
// PartialUpdateUser updates one or more existing rows in users
@@ -302,7 +302,7 @@ func (s Store) PartialUpdateUser(ctx context.Context, onlyColumns []string, rr .
squirrel.Eq{s.preprocessColumn("usr.id", ""): s.preprocessValue(res.ID, "")},
s.internalUserEncoder(res).Skip("id").Only(onlyColumns...))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -320,7 +320,7 @@ func (s Store) RemoveUser(ctx context.Context, rr ...*types.User) error {
for _, res := range rr {
err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.UserTable("usr")).Where(squirrel.Eq{s.preprocessColumn("usr.id", ""): s.preprocessValue(res.ID, "")}))
if err != nil {
return err
return s.config.ErrorHandler(err)
}
}
@@ -330,17 +330,17 @@ func (s Store) RemoveUser(ctx context.Context, rr ...*types.User) error {
// RemoveUserByID removes row from the users table
func (s Store) RemoveUserByID(ctx context.Context, ID uint64) error {
return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.UserTable("usr")).Where(squirrel.Eq{s.preprocessColumn("usr.id", ""): s.preprocessValue(ID, "")}))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Delete(s.UserTable("usr")).Where(squirrel.Eq{s.preprocessColumn("usr.id", ""): s.preprocessValue(ID, "")})))
}
// TruncateUsers removes all rows from the users table
func (s Store) TruncateUsers(ctx context.Context) error {
return Truncate(ctx, s.DB(), s.UserTable())
return s.config.ErrorHandler(Truncate(ctx, s.DB(), s.UserTable()))
}
// ExecUpdateUsers updates all matched (by cnd) rows in users with given data
func (s Store) ExecUpdateUsers(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return ExecuteSqlizer(ctx, s.DB(), s.Update(s.UserTable("usr")).Where(cnd).SetMap(set))
return s.config.ErrorHandler(ExecuteSqlizer(ctx, s.DB(), s.Update(s.UserTable("usr")).Where(cnd).SetMap(set)))
}
// UserLookup prepares User query and executes it,

View File

@@ -4,8 +4,9 @@ import (
"context"
"fmt"
"github.com/Masterminds/squirrel"
"github.com/cortezaproject/corteza-server/store"
"github.com/cortezaproject/corteza-server/store/rdbms"
_ "github.com/mattn/go-sqlite3"
"github.com/mattn/go-sqlite3"
"go.uber.org/zap"
"strings"
)
@@ -24,6 +25,7 @@ func New(ctx context.Context, dsn string) (s *Store, err error) {
}
cfg.PlaceholderFormat = squirrel.Dollar
cfg.ErrorHandler = errorHandler
s = new(Store)
if s.Store, err = rdbms.New(ctx, cfg); err != nil {
@@ -83,3 +85,16 @@ func ProcDataSourceName(in string) (*rdbms.Config, error) {
return c, nil
}
func errorHandler(err error) error {
if err != nil {
if implErr, ok := err.(sqlite3.Error); ok {
switch implErr.ExtendedCode {
case sqlite3.ErrConstraintUnique:
return store.ErrNotUnique.Wrap(implErr)
}
}
}
return err
}

View File

@@ -74,6 +74,22 @@ func testUsers(t *testing.T, tmp interface{}) {
req.NoError(s.CreateUser(ctx, makeNew()))
})
t.Run("create with duplicate email", func(t *testing.T) {
req := require.New(t)
req.NoError(s.TruncateUsers(ctx))
req.NoError(s.CreateUser(ctx, makeNew("a")))
req.EqualError(s.CreateUser(ctx, makeNew("a")), store.ErrNotUnique.Error())
})
t.Run("create with duplicate ID", func(t *testing.T) {
req := require.New(t)
req.NoError(s.TruncateUsers(ctx))
user := makeNew("a")
req.NoError(s.CreateUser(ctx, user))
req.EqualError(s.CreateUser(ctx, user), store.ErrNotUnique.Error())
})
t.Run("lookup by ID", func(t *testing.T) {
req, user := truncAndCreate(t)