diff --git a/compose/repository/attachment.go b/compose/repository/attachment.go deleted file mode 100644 index f4ccefc67..000000000 --- a/compose/repository/attachment.go +++ /dev/null @@ -1,177 +0,0 @@ -package repository - -//import ( -// "context" -// "time" -// -// "github.com/Masterminds/squirrel" -// "github.com/pkg/errors" -// "github.com/titpetric/factory" -// -// "github.com/cortezaproject/corteza-server/compose/types" -// "github.com/cortezaproject/corteza-server/pkg/rh" -//) -// -//type ( -// AttachmentRepository interface { -// With(ctx context.Context, db *factory.DB) AttachmentRepository -// -// Find(filter types.AttachmentFilter) (types.AttachmentSet, types.AttachmentFilter, error) -// FindByID(namespaceID, attachmentID uint64) (*types.Attachment, error) -// Create(mod *types.Attachment) (*types.Attachment, error) -// DeleteByID(namespaceID, attachmentID uint64) error -// } -// -// attachment struct { -// *repository -// } -//) -// -//const ( -// ErrAttachmentNotFound = repositoryError("AttachmentNotFound") -//) -// -//func Attachment(ctx context.Context, db *factory.DB) AttachmentRepository { -// return (&attachment{}).With(ctx, db) -//} -// -//func (r attachment) With(ctx context.Context, db *factory.DB) AttachmentRepository { -// return &attachment{ -// repository: r.repository.With(ctx, db), -// } -//} -// -//func (r attachment) table() string { -// return "compose_attachment" -//} -// -//func (r attachment) columns() []string { -// return []string{ -// "a.id", -// "a.rel_namespace", -// "a.rel_owner", -// "a.kind", -// "a.url", -// "a.preview_url", -// "a.name", -// "a.meta", -// "a.created_at", -// "a.updated_at", -// "a.deleted_at", -// } -//} -// -//func (r attachment) query() squirrel.SelectBuilder { -// return squirrel. -// Select(r.columns()...). -// From(r.table() + " AS a"). -// Where("a.deleted_at IS NULL") -// -//} -// -//func (r attachment) FindByID(namespaceID, attachmentID uint64) (*types.Attachment, error) { -// return r.findOneBy(namespaceID, "id", attachmentID) -//} -// -//func (r attachment) findOneBy(namespaceID uint64, field string, value interface{}) (*types.Attachment, error) { -// var ( -// p = &types.Attachment{} -// -// q = r.query(). -// Where(squirrel.Eq{field: value, "rel_namespace": namespaceID}) -// -// err = rh.FetchOne(r.db(), q, p) -// ) -// -// if err != nil { -// return nil, err -// } else if p.ID == 0 { -// return nil, ErrAttachmentNotFound -// } -// -// return p, nil -//} -// -//func (r attachment) Find(filter types.AttachmentFilter) (set types.AttachmentSet, f types.AttachmentFilter, err error) { -// f = filter -// -// if f.Sort == "" { -// f.Sort = "id ASC" -// } -// -// query := r.query(). -// Where(squirrel.Eq{"a.kind": f.Kind}) -// -// if filter.NamespaceID > 0 { -// query = query.Where("a.rel_namespace = ?", filter.NamespaceID) -// } -// -// switch f.Kind { -// case types.PageAttachment: -// // @todo implement filtering by page -// if f.PageID > 0 { -// err = errors.New("filtering by pageID not implemented") -// return -// } -// -// case types.RecordAttachment: -// query = query. -// Join("compose_record_value AS v ON (v.ref = a.id)") -// -// if f.ModuleID > 0 { -// query = query. -// Join("compose_record AS r ON (r.id = v.record_id)"). -// Where(squirrel.Eq{"r.module_id": f.ModuleID}) -// } -// -// if f.RecordID > 0 { -// query = query.Where(squirrel.Eq{"v.record_id": f.RecordID}) -// } -// -// if f.FieldName != "" { -// query = query.Where(squirrel.Eq{"v.name": f.FieldName}) -// } -// -// default: -// err = errors.New("unsupported kind value") -// return -// } -// -// if f.Filter != "" { -// err = errors.New("filtering by filter not implemented") -// return -// } -// -// var orderBy []string -// if orderBy, err = rh.ParseOrder(f.Sort, r.columns()...); err != nil { -// return -// } else { -// query = query.OrderBy(orderBy...) -// } -// -// if f.Count, err = rh.Count(r.db(), query); err != nil || f.Count == 0 { -// return -// } -// -// return set, f, rh.FetchPaged(r.db(), query, f.PageFilter, &set) -//} -// -//func (r attachment) Create(mod *types.Attachment) (*types.Attachment, error) { -// if mod.ID == 0 { -// mod.ID = factory.Sonyflake.NextID() -// } -// -// mod.CreatedAt = time.Now() -// -// return mod, r.db().Insert(r.table(), mod) -//} -// -//func (r attachment) DeleteByID(namespaceID, attachmentID uint64) error { -// _, err := r.db().Exec( -// "UPDATE "+r.table()+" SET deleted_at = NOW() WHERE rel_namespace = ? AND id = ?", -// namespaceID, -// attachmentID, -// ) -// -// return err -//} diff --git a/compose/repository/chart.go b/compose/repository/chart.go deleted file mode 100644 index b3e64f062..000000000 --- a/compose/repository/chart.go +++ /dev/null @@ -1,151 +0,0 @@ -package repository - -//type ( -// ChartRepository interface { -// With(ctx context.Context, db *factory.DB) ChartRepository -// -// FindByID(namespaceID, chartID uint64) (*types.Chart, error) -// FindByHandle(namespaceID uint64, handle string) (c *types.Chart, err error) -// Find(filter types.ChartFilter) (set types.ChartSet, f types.ChartFilter, err error) -// Create(mod *types.Chart) (*types.Chart, error) -// Update(mod *types.Chart) (*types.Chart, error) -// DeleteByID(namespaceID, chartID uint64) error -// } -// -// chart struct { -// *repository -// } -//) -// -//const ( -// ErrChartNotFound = repositoryError("ChartNotFound") -// ErrChartHandleNotUnique = repositoryError("ChartHandleNotUnique") -//) -// -//func Chart(ctx context.Context, db *factory.DB) ChartRepository { -// return (&chart{}).With(ctx, db) -//} -// -//func (r chart) With(ctx context.Context, db *factory.DB) ChartRepository { -// return &chart{ -// repository: r.repository.With(ctx, db), -// } -//} -// -//func (r chart) table() string { -// return "compose_chart" -//} -// -//func (r chart) columns() []string { -// return []string{ -// "id", -// "rel_namespace", -// "handle", -// "name", -// "config", -// "created_at", -// "updated_at", -// "deleted_at", -// } -//} -// -//func (r chart) query() squirrel.SelectBuilder { -// return squirrel. -// Select(r.columns()...). -// From(r.table()). -// Where("deleted_at IS NULL") -//} -// -//func (r chart) FindByID(namespaceID, chartID uint64) (*types.Chart, error) { -// return r.findOneBy(namespaceID, "id", chartID) -//} -// -//func (r chart) FindByHandle(namespaceID uint64, handle string) (*types.Chart, error) { -// return r.findOneBy(namespaceID, "LOWER(handle)", strings.ToLower(strings.TrimSpace(handle))) -//} -// -//func (r chart) findOneBy(namespaceID uint64, field string, value interface{}) (*types.Chart, error) { -// var ( -// c = &types.Chart{} -// -// q = r.query(). -// Where(squirrel.Eq{field: value, "rel_namespace": namespaceID}) -// -// err = rh.FetchOne(r.db(), q, c) -// ) -// -// if err != nil { -// return nil, err -// } else if c.ID == 0 { -// return nil, ErrChartNotFound -// } -// -// return c, nil -//} -// -//func (r chart) Find(filter types.ChartFilter) (set types.ChartSet, f types.ChartFilter, err error) { -// //f = filter -// // -// //if f.Sort == "" { -// // f.Sort = "id ASC" -// //} -// // -// //query := r.query() -// // -// //if filter.NamespaceID > 0 { -// // query = query.Where(squirrel.Eq{"rel_namespace": filter.NamespaceID}) -// //} -// // -// //if f.Query != "" { -// // q := "%" + strings.ToLower(f.Query) + "%" -// // query = query.Where(squirrel.Or{ -// // squirrel.Like{"LOWER(name)": q}, -// // }) -// //} -// // -// //if f.Handle != "" { -// // query = query.Where("LOWER(handle) = LOWER(?)", f.Handle) -// //} -// // -// //if f.IsReadable != nil { -// // query = query.Where(f.IsReadable) -// //} -// // -// //var orderBy []string -// //if orderBy, err = rh.ParseOrder(f.Sort, r.columns()...); err != nil { -// // return -// //} else { -// // query = query.OrderBy(orderBy...) -// //} -// // -// //if f.Count, err = rh.Count(r.db(), query); err != nil || f.Count == 0 { -// // return -// //} -// // -// //return set, f, rh.FetchPaged(r.db(), query, f.PageFilter, &set) -// return nil, f, fmt.Errorf("deprecated") -//} -// -//func (r chart) Create(mod *types.Chart) (*types.Chart, error) { -// mod.ID = factory.Sonyflake.NextID() -// rh.SetCurrentTimeRounded(&mod.CreatedAt) -// mod.UpdatedAt = nil -// -// return mod, r.db().Insert(r.table(), mod) -//} -// -//func (r chart) Update(mod *types.Chart) (*types.Chart, error) { -// rh.SetCurrentTimeRounded(&mod.UpdatedAt) -// -// return mod, r.db().Update(r.table(), mod, "id") -//} -// -//func (r chart) DeleteByID(namespaceID, chartID uint64) error { -// _, err := r.db().Exec( -// "UPDATE "+r.table()+" SET deleted_at = NOW() WHERE rel_namespace = ? AND id = ?", -// namespaceID, -// chartID, -// ) -// -// return err -//} diff --git a/compose/repository/error.go b/compose/repository/error.go deleted file mode 100644 index 8bbbc329d..000000000 --- a/compose/repository/error.go +++ /dev/null @@ -1,21 +0,0 @@ -package repository - -type ( - repositoryError string -) - -const ( - ErrNotImplemented = repositoryError("NotImplemented") -) - -func (e repositoryError) Error() string { - return e.String() -} - -func (e repositoryError) String() string { - return "compose.repository." + string(e) -} - -func (e repositoryError) Eq(err error) bool { - return err != nil && e.Error() == err.Error() -} diff --git a/compose/repository/module.go b/compose/repository/module.go deleted file mode 100644 index 1ed5d182d..000000000 --- a/compose/repository/module.go +++ /dev/null @@ -1,275 +0,0 @@ -package repository - -import ( - "context" - "fmt" - "strings" - - "github.com/Masterminds/squirrel" - "github.com/jmoiron/sqlx" - "github.com/pkg/errors" - "github.com/titpetric/factory" - - "github.com/cortezaproject/corteza-server/compose/types" - "github.com/cortezaproject/corteza-server/pkg/rh" -) - -type ( - ModuleRepository interface { - With(ctx context.Context, db *factory.DB) ModuleRepository - - FindByID(namespaceID, moduleID uint64) (*types.Module, error) - FindByName(namespaceID uint64, name string) (*types.Module, error) - FindByHandle(namespaceID uint64, handle string) (*types.Module, error) - Find(filter types.ModuleFilter) (set types.ModuleSet, f types.ModuleFilter, err error) - FindFields(moduleIDs ...uint64) (ff types.ModuleFieldSet, err error) - Create(mod *types.Module) (*types.Module, error) - Update(mod *types.Module) (*types.Module, error) - UpdateFields(moduleID uint64, ff types.ModuleFieldSet, hasRecords bool) (err error) - DeleteByID(namespaceID, moduleID uint64) error - } - - module struct { - *repository - } -) - -const ( - ErrModuleNotFound = repositoryError("ModuleNotFound") - //ErrModuleNameNotUnique = repositoryError("ModuleNameNotUnique") - //ErrModuleHandleNotUnique = repositoryError("ModuleHandleNotUnique") -) - -func Module(ctx context.Context, db *factory.DB) ModuleRepository { - return (&module{}).With(ctx, db) -} - -func (r module) With(ctx context.Context, db *factory.DB) ModuleRepository { - return &module{ - repository: r.repository.With(ctx, db), - } -} - -func (r module) table() string { - return "compose_module" -} - -func (r module) tableFields() string { - return "compose_module_field" -} - -func (r module) columns() []string { - return []string{ - "id", - "rel_namespace", - "handle", - "name", - "json", - "created_at", - "updated_at", - "deleted_at", - } -} - -func (r module) query() squirrel.SelectBuilder { - return squirrel. - Select(r.columns()...). - From(r.table()). - Where("deleted_at IS NULL") - -} - -func (r module) FindByID(namespaceID, moduleID uint64) (*types.Module, error) { - return r.findOneBy(namespaceID, "id", moduleID) -} - -func (r module) FindByHandle(namespaceID uint64, handle string) (*types.Module, error) { - return r.findOneBy(namespaceID, "LOWER(handle)", strings.ToLower(strings.TrimSpace(handle))) -} - -func (r module) FindByName(namespaceID uint64, name string) (*types.Module, error) { - return r.findOneBy(namespaceID, "LOWER(name)", strings.ToLower(strings.TrimSpace(name))) -} - -func (r module) findOneBy(namespaceID uint64, field string, value interface{}) (*types.Module, error) { - var ( - m = &types.Module{} - - q = r.query(). - Where(squirrel.Eq{field: value, "rel_namespace": namespaceID}) - - err = rh.FetchOne(r.db(), q, m) - ) - - if err != nil { - return nil, err - } else if m.ID == 0 { - return nil, ErrModuleNotFound - } - - return m, nil -} - -func (r module) Find(filter types.ModuleFilter) (set types.ModuleSet, f types.ModuleFilter, err error) { - //f = filter - // - //if f.Sort == "" { - // f.Sort = "id ASC" - //} - // - //query := r.query() - // - //if filter.NamespaceID > 0 { - // query = query.Where("rel_namespace = ?", filter.NamespaceID) - //} - // - //if f.Query != "" { - // q := "%" + strings.ToLower(f.Query) + "%" - // query = query.Where(squirrel.Or{ - // squirrel.Like{"LOWER(name)": q}, - // squirrel.Like{"LOWER(handle)": q}, - // }) - //} - // - //if f.Name != "" { - // query = query.Where(squirrel.Eq{"LOWER(name)": strings.ToLower(f.Name)}) - //} - // - //if f.Handle != "" { - // query = query.Where(squirrel.Eq{"LOWER(handle)": strings.ToLower(f.Handle)}) - //} - // - //if f.IsReadable != nil { - // query = query.Where(f.IsReadable) - //} - // - //var orderBy []string - //if orderBy, err = rh.ParseOrder(f.Sort, r.columns()...); err != nil { - // return - //} else { - // query = query.OrderBy(orderBy...) - //} - // - //if f.Count, err = rh.Count(r.db(), query); err != nil || f.Count == 0 { - // return - //} - // - //return set, f, rh.FetchPaged(r.db(), query, f.PageFilter, &set) - return nil, f, fmt.Errorf("deprecated") -} - -func (r module) Create(mod *types.Module) (*types.Module, error) { - var err error - - mod.ID = factory.Sonyflake.NextID() - rh.SetCurrentTimeRounded(&mod.CreatedAt) - mod.UpdatedAt = nil - - if err = r.db().Insert(r.table(), mod); err != nil { - return nil, err - } - - return mod, nil -} - -func (r module) Update(mod *types.Module) (*types.Module, error) { - rh.SetCurrentTimeRounded(&mod.UpdatedAt) - - return mod, r.db().Update(r.table(), mod, "id") -} - -func (r module) UpdateFields(moduleID uint64, ff types.ModuleFieldSet, hasRecords bool) error { - if existing, err := r.FindFields(moduleID); err != nil { - return err - } else { - // Remove fields that do not exist anymore - err = existing.Walk(func(e *types.ModuleField) error { - if ff.FindByID(e.ID) == nil { - return r.deleteFieldByID(moduleID, e.ID) - } - - return nil - }) - - if err != nil { - return err - } - - for idx, f := range ff { - if e := existing.FindByID(f.ID); e != nil { - f.CreatedAt = e.CreatedAt - - // We do not have any other code in place that would handle changes of field name and kind, so we need - // to reset any changes made to the field. - // @todo remove when we are able to handle field rename & type change - if hasRecords { - f.Name = e.Name - f.Kind = e.Kind - } else { - rh.SetCurrentTimeRounded(&f.UpdatedAt) - } - } else { - f.ID = 0 - } - - if f.ID == 0 { - f.ID = factory.Sonyflake.NextID() - rh.SetCurrentTimeRounded(&f.CreatedAt) - } - - f.ModuleID = moduleID - f.Place = idx - f.DeletedAt = nil - - if err := r.db().Replace(r.tableFields(), f); err != nil { - return errors.Wrap(err, "Error updating module fields") - } - - } - } - - return nil -} - -func (r module) deleteFieldByID(moduleID, fieldID uint64) error { - _, err := r.db().Exec( - fmt.Sprintf("DELETE FROM %s WHERE rel_module = ? AND id = ?", r.tableFields()), - moduleID, - fieldID, - ) - - return err -} - -func (r module) DeleteByID(namespaceID, moduleID uint64) error { - _, err := r.db().Exec( - fmt.Sprintf("UPDATE %s SET deleted_at = NOW() WHERE rel_namespace = ? AND id = ?", r.table()), - namespaceID, - moduleID, - ) - - return err -} - -func (r module) FindFields(moduleIDs ...uint64) (ff types.ModuleFieldSet, err error) { - if len(moduleIDs) == 0 { - return - } - - query := `SELECT id, rel_module, place, - kind, name, label, options, - is_private, is_required, is_visible, is_multi, default_value, - created_at, updated_at, deleted_at - FROM %s - WHERE rel_module IN (?) - AND deleted_at IS NULL - ORDER BY rel_module, place` - - query = fmt.Sprintf(query, r.tableFields()) - - if sql, args, err := sqlx.In(query, moduleIDs); err != nil { - return nil, err - } else { - return ff, r.db().Select(&ff, sql, args...) - } -} diff --git a/compose/repository/namespace.go b/compose/repository/namespace.go deleted file mode 100644 index 7c61385dc..000000000 --- a/compose/repository/namespace.go +++ /dev/null @@ -1,154 +0,0 @@ -package repository - -import ( - "context" - "fmt" - "github.com/Masterminds/squirrel" - "github.com/titpetric/factory" - - "github.com/cortezaproject/corteza-server/compose/types" - "github.com/cortezaproject/corteza-server/pkg/rh" -) - -type ( - NamespaceRepository interface { - With(ctx context.Context, db *factory.DB) NamespaceRepository - - FindByID(id uint64) (*types.Namespace, error) - FindBySlug(slug string) (*types.Namespace, error) - Find(filter types.NamespaceFilter) (types.NamespaceSet, types.NamespaceFilter, error) - Create(mod *types.Namespace) (*types.Namespace, error) - Update(mod *types.Namespace) (*types.Namespace, error) - DeleteByID(id uint64) error - } - - namespace struct { - *repository - } -) - -const ( - ErrNamespaceNotFound = repositoryError("NamespaceNotFound") - ErrNamespaceSlugNotUnique = repositoryError("NamespaceSlugNotUnique") - ErrNamespaceInvalidSlugFormat = repositoryError("NamespaceInvalidSlugFormat") -) - -func Namespace(ctx context.Context, db *factory.DB) NamespaceRepository { - return (&namespace{}).With(ctx, db) -} - -func (r namespace) table() string { - return "compose_namespace" -} - -func (r namespace) columns() []string { - return []string{ - "id", - "name", - "slug", - "enabled", - "meta", - "created_at", - "updated_at", - "deleted_at", - } -} - -func (r namespace) query() squirrel.SelectBuilder { - return squirrel. - Select(r.columns()...). - From(r.table()). - Where("deleted_at IS NULL") - -} - -func (r *namespace) With(ctx context.Context, db *factory.DB) NamespaceRepository { - return &namespace{ - repository: r.repository.With(ctx, db), - } -} - -func (r *namespace) FindByID(namespaceID uint64) (*types.Namespace, error) { - return r.findOneBy("id", namespaceID) -} - -func (r *namespace) FindBySlug(slug string) (*types.Namespace, error) { - return r.findOneBy("slug", slug) -} - -func (r *namespace) findOneBy(field string, value interface{}) (*types.Namespace, error) { - var ( - ns = &types.Namespace{} - - q = r.query(). - Where(squirrel.Eq{field: value}) - - err = rh.FetchOne(r.db(), q, ns) - ) - - if err != nil { - return nil, err - } else if ns.ID == 0 { - return nil, ErrNamespaceNotFound - } - - return ns, nil -} - -func (r *namespace) Find(filter types.NamespaceFilter) (set types.NamespaceSet, f types.NamespaceFilter, err error) { - //f = filter - // - //if f.Sort == "" { - // f.Sort = "id ASC" - //} - // - //query := r.query() - //if f.Query != "" { - // q := "%" + strings.ToLower(f.Query) + "%" - // query = query.Where(squirrel.Or{ - // squirrel.Like{"LOWER(name)": q}, - // squirrel.Like{"LOWER(slug)": q}, - // }) - //} - // - //if f.Slug != "" { - // query = query.Where(squirrel.Eq{"LOWER(slug)": strings.ToLower(f.Slug)}) - //} - // - //if f.IsReadable != nil { - // query = query.Where(f.IsReadable) - //} - // - //var orderBy []string - //if orderBy, err = rh.ParseOrder(f.Sort, r.columns()...); err != nil { - // return - //} else { - // query = query.OrderBy(orderBy...) - //} - // - //if f.Count, err = rh.Count(r.db(), query); err != nil || f.Count == 0 { - // return - //} - // - //return set, f, rh.FetchPaged(r.db(), query, f.PageFilter, &set) - return nil, f, fmt.Errorf("deprecated") -} - -func (r *namespace) Create(mod *types.Namespace) (*types.Namespace, error) { - mod.ID = factory.Sonyflake.NextID() - rh.SetCurrentTimeRounded(&mod.CreatedAt) - mod.UpdatedAt = nil - - return mod, r.db().Insert(r.table(), mod) -} - -func (r *namespace) Update(mod *types.Namespace) (*types.Namespace, error) { - rh.SetCurrentTimeRounded(&mod.UpdatedAt) - - return mod, r.db().Update(r.table(), mod, "id") -} - -func (r *namespace) DeleteByID(namespaceID uint64) error { - _, err := r.db().Exec("UPDATE "+r.table()+" SET deleted_at = NOW() WHERE id = ?", namespaceID) - return err -} diff --git a/compose/repository/page.go b/compose/repository/page.go deleted file mode 100644 index 6ad7f5c1b..000000000 --- a/compose/repository/page.go +++ /dev/null @@ -1,217 +0,0 @@ -package repository - -import ( - "context" - "fmt" - "github.com/Masterminds/squirrel" - "github.com/titpetric/factory" - - "github.com/cortezaproject/corteza-server/compose/types" - "github.com/cortezaproject/corteza-server/pkg/rh" -) - -type ( - PageRepository interface { - With(ctx context.Context, db *factory.DB) PageRepository - - FindByID(namespaceID, pageID uint64) (*types.Page, error) - FindByHandle(namespaceID uint64, handle string) (*types.Page, error) - FindByModuleID(namespaceID, moduleID uint64) (*types.Page, error) - Find(filter types.PageFilter) (set types.PageSet, f types.PageFilter, err error) - - Create(mod *types.Page) (*types.Page, error) - Update(mod *types.Page) (*types.Page, error) - DeleteByID(namespaceID, pageID uint64) error - - Reorder(namespaceID, selfID uint64, pageIDs []uint64) error - } - - page struct { - *repository - } -) - -const ( - ErrPageNotFound = repositoryError("PageNotFound") - ErrPageHandleNotUnique = repositoryError("PageHandleNotUnique") -) - -func Page(ctx context.Context, db *factory.DB) PageRepository { - return (&page{}).With(ctx, db) -} - -func (r page) With(ctx context.Context, db *factory.DB) PageRepository { - return &page{ - repository: r.repository.With(ctx, db), - } -} - -func (r page) table() string { - return "compose_page" -} - -func (r page) columns() []string { - return []string{ - "id", - "rel_namespace", - "self_id", - "rel_module", - "handle", - "title", - "blocks", - "description", - "visible", - "weight", - "created_at", - "updated_at", - "deleted_at", - } -} - -func (r page) query() squirrel.SelectBuilder { - return squirrel. - Select(r.columns()...). - From(r.table()). - Where("deleted_at IS NULL") -} - -func (r page) FindByID(namespaceID, pageID uint64) (*types.Page, error) { - return r.findOneBy(namespaceID, "id", pageID) -} - -func (r page) FindByHandle(namespaceID uint64, handle string) (*types.Page, error) { - return r.findOneBy(namespaceID, "handle", handle) -} - -func (r page) FindByModuleID(namespaceID, moduleID uint64) (*types.Page, error) { - return r.findOneBy(namespaceID, "rel_module", moduleID) -} - -func (r page) findOneBy(namespaceID uint64, field string, value interface{}) (*types.Page, error) { - var ( - p = &types.Page{} - - q = r.query(). - Where(squirrel.Eq{field: value, "rel_namespace": namespaceID}) - - err = rh.FetchOne(r.db(), q, p) - ) - - if err != nil { - return nil, err - } else if p.ID == 0 { - return nil, ErrPageNotFound - } - - return p, nil -} - -func (r page) Find(filter types.PageFilter) (set types.PageSet, f types.PageFilter, err error) { - //f = filter - // - //if f.Sort == "" { - // f.Sort = "id ASC" - //} - // - //query := r.query() - // - //if filter.NamespaceID > 0 { - // query = query.Where("rel_namespace = ?", filter.NamespaceID) - //} - // - //if filter.ParentID > 0 { - // query = query.Where("self_id = ?", filter.ParentID) - //} else if filter.Root { - // query = query.Where("self_id = 0") - //} - // - //if f.Handle != "" { - // query = query.Where("LOWER(handle) = ?", strings.ToLower(f.Handle)) - //} - // - //if f.Query != "" { - // q := "%" + strings.ToLower(f.Query) + "%" - // query = query.Where(squirrel.Or{ - // squirrel.Like{"LOWER(title)": q}, - // squirrel.Like{"LOWER(description)": q}, - // }) - //} - // - //if f.IsReadable != nil { - // query = query.Where(f.IsReadable) - //} - // - //var orderBy []string - //if orderBy, err = rh.ParseOrder(f.Sort, r.columns()...); err != nil { - // return - //} else { - // query = query.OrderBy(orderBy...) - //} - // - //if f.Count, err = rh.Count(r.db(), query); err != nil || f.Count == 0 { - // return - //} - // - //return set, f, rh.FetchPaged(r.db(), query, f.PageFilter, &set) - return nil, f, fmt.Errorf("deprecated") -} - -func (r page) Reorder(namespaceID, parentID uint64, pageIDs []uint64) error { - var ( - pageMap = map[uint64]bool{} - filter = types.PageFilter{NamespaceID: namespaceID, ParentID: parentID} - ) - - if pages, _, err := r.Find(filter); err != nil { - return nil - } else { - for _, page := range pages { - pageMap[page.ID] = true - } - } - weight := 1 - db := r.db() - // honor parameter first - for _, pageID := range pageIDs { - if pageMap[pageID] { - pageMap[pageID] = false - if _, err := db.Exec("UPDATE compose_page SET weight = ? WHERE id = ? AND self_id = ?", weight, pageID, parentID); err != nil { - return err - } - weight++ - } - } - for pageID, update := range pageMap { - if update { - if _, err := db.Exec("UPDATE compose_page SET weight = ? WHERE id = ? AND self_id = ?", weight, pageID, parentID); err != nil { - return err - } - weight++ - } - } - return nil -} - -func (r page) Create(mod *types.Page) (*types.Page, error) { - mod.ID = factory.Sonyflake.NextID() - rh.SetCurrentTimeRounded(&mod.CreatedAt) - mod.UpdatedAt = nil - - return mod, r.db().Insert(r.table(), mod) -} - -func (r page) Update(mod *types.Page) (*types.Page, error) { - rh.SetCurrentTimeRounded(&mod.UpdatedAt) - - return mod, r.db().Update(r.table(), mod, "id") -} - -func (r page) DeleteByID(namespaceID, pageID uint64) error { - _, err := r.db().Exec( - "UPDATE "+r.table()+" SET deleted_at = NOW() WHERE rel_namespace = ? AND id = ?", - namespaceID, - pageID, - ) - - return err -} diff --git a/compose/repository/record.go b/compose/repository/record.go deleted file mode 100644 index 13c2d9844..000000000 --- a/compose/repository/record.go +++ /dev/null @@ -1,387 +0,0 @@ -package repository - -import ( - "context" - "github.com/cortezaproject/corteza-server/compose/types" - "github.com/titpetric/factory" - "strings" -) - -type ( - RecordRepository interface { - With(ctx context.Context, db *factory.DB) RecordRepository - - FindByID(namespaceID, recordID uint64) (*types.Record, error) - - Report(module *types.Module, metrics, dimensions, filter string) (results interface{}, err error) - Find(module *types.Module, filter types.RecordFilter) (set types.RecordSet, f types.RecordFilter, err error) - Export(module *types.Module, filter types.RecordFilter) (set types.RecordSet, err error) - - Create(record *types.Record) (*types.Record, error) - Update(record *types.Record) (*types.Record, error) - Delete(record *types.Record) error - - RefValueLookup(moduleID uint64, field string, ref uint64) (recordID uint64, err error) - LoadValues(fieldNames []string, IDs []uint64) (rvs types.RecordValueSet, err error) - DeleteValues(record *types.Record) error - UpdateValues(recordID uint64, rvs types.RecordValueSet) (err error) - PartialUpdateValues(rvs ...*types.RecordValue) (err error) - } - - record struct { - *repository - } -) - -// -const ( - ErrRecordNotFound = repositoryError("RecordNotFound") -) - -// -func Record(ctx context.Context, db *factory.DB) RecordRepository { - return nil //.With(ctx, db) -} - -// -//func (r record) With(ctx context.Context, db *factory.DB) RecordRepository { -// return &record{ -// repository: r.repository.With(ctx, db), -// } -//} -// -//func (r record) table() string { -// return "compose_record" -//} -// -//func (r record) columns() []string { -// return []string{ -// "r.id", -// "r.module_id", -// "r.rel_namespace", -// "r.owned_by", -// "r.created_at", -// "r.created_by", -// "r.updated_at", -// "r.updated_by", -// "r.deleted_at", -// "r.deleted_by", -// } -//} -// -//func (r record) query() squirrel.SelectBuilder { -// return squirrel. -// Select(r.columns()...). -// From(r.table() + " AS r") -//} -// -//// @todo: update to accepted DeletedAt column semantics from Messaging -// -//func (r record) FindByID(namespaceID, recordID uint64) (*types.Record, error) { -// return r.findOneBy(namespaceID, "id", recordID) -//} -// -//func (r record) findOneBy(namespaceID uint64, field string, value interface{}) (*types.Record, error) { -// var ( -// rec = &types.Record{} -// -// q = r.query(). -// Where("r.deleted_at IS NULL"). -// Where(squirrel.Eq{field: value, "rel_namespace": namespaceID}) -// -// err = rh.FetchOne(r.db(), q, rec) -// ) -// -// if err != nil { -// return nil, err -// } else if rec.ID == 0 { -// return nil, ErrRecordNotFound -// } -// -// return rec, nil -//} -// -//func (r record) Report(module *types.Module, metrics, dimensions, filter string) (results interface{}, err error) { -// crb := NewRecordReportBuilder(module) -// -// var result = make([]map[string]interface{}, 0) -// -// if query, args, err := crb.Build(metrics, dimensions, filter); err != nil { -// return nil, errors.Wrap(err, "can not generate report query") -// } else if rows, err := r.db().Query(query, args...); err != nil { -// return nil, errors.Wrapf(err, "can not execute report query (%s)", query) -// } else { -// for rows.Next() { -// result = append(result, crb.Cast(rows)) -// } -// -// return result, nil -// } -//} -// -//func (r record) Find(module *types.Module, filter types.RecordFilter) (set types.RecordSet, f types.RecordFilter, err error) { -// var query squirrel.SelectBuilder -// f = filter -// -// query, err = r.buildQuery(module, filter) -// if err != nil { -// return -// } -// -// if f.Count, err = rh.Count(r.db(), query); err != nil || f.Count == 0 { -// return -// } -// -// return set, f, rh.FetchPaged(r.db(), query, f.PageFilter, &set) -//} -// -//// Export ignores paging and does not return filter -//// -//// @todo optimize and include value loading -//func (r record) Export(module *types.Module, filter types.RecordFilter) (set types.RecordSet, err error) { -// filter.PageFilter = rh.PageFilter{} -// -// query, err := r.buildQuery(module, filter) -// if err != nil { -// return -// } -// -// return set, rh.FetchAll(r.db(), query, &set) -//} -// -//func (r record) buildQuery(module *types.Module, f types.RecordFilter) (query squirrel.SelectBuilder, err error) { -// var ( -// joinedFields = []string{} -// alreadyJoined = func(f string) bool { -// for _, a := range joinedFields { -// if a == f { -// return true -// } -// } -// -// joinedFields = append(joinedFields, f) -// return false -// } -// -// identResolver = func(i ql.Ident) (ql.Ident, error) { -// var is bool -// if i.Value, is = isRealRecordCol(i.Value); is { -// i.Value += " " -// return i, nil -// } -// -// if !module.Fields.HasName(i.Value) { -// return i, errors.Errorf("unknown field %q", i.Value) -// } -// -// if !alreadyJoined(i.Value) { -// query = query.LeftJoin(fmt.Sprintf( -// "compose_record_value AS rv_%s ON (rv_%s.record_id = r.id AND rv_%s.name = ? AND rv_%s.deleted_at IS NULL)", -// i.Value, i.Value, i.Value, i.Value, -// ), i.Value) -// } -// -// field := module.Fields.FindByName(i.Value) -// -// switch true { -// case field.IsBoolean(): -// i.Value = fmt.Sprintf("(rv_%s.value NOT IN ('', '0', 'false', 'f', 'FALSE', 'F', false))", i.Value) -// case field.IsNumeric(): -// i.Value = fmt.Sprintf("CAST(rv_%s.value AS SIGNED)", i.Value) -// case field.IsDateTime(): -// i.Value = fmt.Sprintf("CAST(rv_%s.value AS DATETIME)", i.Value) -// case field.IsRef(): -// i.Value = fmt.Sprintf("rv_%s.ref ", i.Value) -// default: -// i.Value = fmt.Sprintf("rv_%s.value ", i.Value) -// } -// -// return i, nil -// } -// ) -// -// // Create query for fetching and counting records. -// query = r.query(). -// Where("r.module_id = ?", module.ID). -// Where("r.rel_namespace = ?", module.NamespaceID) -// -// // Inc/exclude deleted records according to filter settings -// query = rh.FilterNullByState(query, "r.deleted_at", f.Deleted) -// -// // Parse filters. -// if f.Query != "" { -// var ( -// // Filter parser -// fp = ql.NewParser() -// -// // Filter node -// fn ql.ASTNode -// ) -// -// // Resolve all identifiers found in the query -// // into their table/column counterparts -// fp.OnIdent = identResolver -// -// if fn, err = fp.ParseExpression(f.Query); err != nil { -// return -// } else if filterSql, filterArgs, err := fn.ToSql(); err != nil { -// return query, err -// } else { -// query = query.Where("("+filterSql+")", filterArgs...) -// } -// } -// -// if f.Sort != "" { -// var ( -// // Sort parser -// sp = ql.NewParser() -// -// // Sort columns -// sc ql.Columns -// ) -// -// // Resolve all identifiers found in sort -// // into their table/column counterparts -// sp.OnIdent = identResolver -// -// if sc, err = sp.ParseColumns(f.Sort); err != nil { -// return -// } -// -// query = query.OrderBy(sc.Strings()...) -// } -// -// return -//} -// -//func (r record) Create(record *types.Record) (*types.Record, error) { -// record.ID = factory.Sonyflake.NextID() -// -// if err := r.db().Insert("compose_record", record); err != nil { -// return nil, errors.Wrap(err, "could not update record") -// } -// -// return record, nil -//} -// -//func (r record) Update(record *types.Record) (*types.Record, error) { -// if err := r.db().Update("compose_record", record, "id"); err != nil { -// return nil, errors.Wrap(err, "could not update record") -// } -// -// return record, nil -//} -// -//func (r record) Delete(record *types.Record) error { -// _, err := r.db().Exec( -// "UPDATE compose_record SET deleted_at = ?, deleted_by = ? WHERE rel_namespace = ? AND id = ?", -// record.DeletedAt, -// record.DeletedBy, -// record.NamespaceID, -// record.ID, -// ) -// -// return err -//} -// -//func (r record) DeleteValues(record *types.Record) error { -// _, err := r.db().Exec( -// "UPDATE compose_record_value SET deleted_at = ? WHERE record_id = ?", -// record.DeletedAt, -// record.ID) -// -// return err -//} -// -//func (r record) UpdateValues(recordID uint64, rvs types.RecordValueSet) (err error) { -// // Remove all records and prepare to be updated -// // @todo be more selective and delete only removed and update/insert changed/new values -// if _, err = r.db().Exec("DELETE FROM compose_record_value WHERE record_id = ?", recordID); err != nil { -// return errors.Wrap(err, "could not remove record values") -// } -// -// err = rvs.Walk(func(value *types.RecordValue) error { -// if value.DeletedAt != nil { -// return nil -// } -// -// value.RecordID = recordID -// return r.db().Insert("compose_record_value", value) -// }) -// -// return errors.Wrap(err, "could not insert record values") -// -//} -// -//func (r record) PartialUpdateValues(rvs ...*types.RecordValue) (err error) { -// err = types.RecordValueSet(rvs).Walk(func(value *types.RecordValue) error { -// return r.db().Replace("compose_record_value", value) -// }) -// -// return errors.Wrap(err, "could not replace record values") -//} -// -//func (r record) RefValueLookup(moduleID uint64, field string, ref uint64) (recordID uint64, err error) { -// var sql = "SELECT record_id" + -// " FROM compose_record AS r INNER JOIN compose_record_value AS v " + -// " WHERE r.module_id = ? " + -// " AND v.name = ? " + -// " AND v.ref = ? " + -// " AND r.deleted_at IS NULL " + -// " AND v.deleted_at IS NULL " + -// " LIMIT 1" -// -// return recordID, r.db().Get(&recordID, sql, moduleID, field, ref) -//} -// -//func (r record) LoadValues(fieldNames []string, IDs []uint64) (rvs types.RecordValueSet, err error) { -// if len(fieldNames) == 0 || len(IDs) == 0 { -// return -// } -// -// var sql = "SELECT record_id, name, value, ref, place, deleted_at " + -// " FROM compose_record_value " + -// " WHERE record_id IN (?) " + -// " AND name IN (?) " + -// " AND deleted_at IS NULL " + -// " ORDER BY record_id, place" -// -// if sql, args, err := sqlx.In(sql, IDs, fieldNames); err != nil { -// return nil, err -// } else { -// return rvs, r.db().Select(&rvs, sql, args...) -// } -//} -// -// Checks if field name is "real column", reformats it and returns -func isRealRecordCol(name string) (string, bool) { - switch name { - case - "recordID", - "id": - return "r.id", true - case - "module_id", - "owned_by", - "created_by", - "created_at", - "updated_by", - "updated_at", - "deleted_by", - "deleted_at": - return "r." + name, true - - case - "moduleID", - "ownedBy", - "createdBy", - "createdAt", - "updatedBy", - "updatedAt", - "deletedBy", - "deletedAt": - return "r." + name[0:len(name)-2] + "_" + strings.ToLower(name[len(name)-2:]), true - } - - return name, false -} diff --git a/compose/repository/record_report_builder.go b/compose/repository/record_report_builder.go deleted file mode 100644 index 101f31aa1..000000000 --- a/compose/repository/record_report_builder.go +++ /dev/null @@ -1,183 +0,0 @@ -package repository - -import ( - "fmt" - "strconv" - "strings" - - "github.com/Masterminds/squirrel" - "github.com/jmoiron/sqlx" - "github.com/pkg/errors" - - "github.com/cortezaproject/corteza-server/compose/types" - "github.com/cortezaproject/corteza-server/pkg/ql" - "github.com/cortezaproject/corteza-server/pkg/rh" -) - -type ( - recordReportBuilder struct { - module *types.Module - - // This is set by metric/column building to assist Cast() - numerics []string - - report squirrel.SelectBuilder - parser *ql.Parser - } -) - -// Identifiers should be names of the fields (physical table columns OR json fields, defined in module) -func stdAggregationHandler(f ql.Function) (ql.Function, error) { - switch strings.ToUpper(f.Name) { - // case "COUNTD": - // return SqlConcatExpr("COUNT(DISTINCT ", aggrFuncArgs, ")") - // - case "COUNT", "SUM", "MAX", "MIN", "AVG", "STD": - return f, nil - default: - return f, fmt.Errorf("unsupported aggregate function %q", f.Name) - } -} - -// Identifiers should be names of the fields (physical table columns OR json fields, defined in module) -func stdFilterFuncHandler(f ql.Function) (ql.Function, error) { - switch strings.ToUpper(f.Name) { - case "CONCAT", "QUARTER", "YEAR", "DATE", "NOW", "DATE_ADD", "DATE_SUB", "DATE_FORMAT": - return f, nil - - default: - return f, fmt.Errorf("unsupported group-by function %q", f.Name) - } -} - -func NewRecordReportBuilder(module *types.Module) *recordReportBuilder { - var report = squirrel. - Select(). - Column(squirrel.Alias(squirrel.Expr("COUNT(*)"), "count")). - From("compose_record AS r"). - Where("r.deleted_at IS NULL"). - Where("r.module_id = ?", module.ID) - - return &recordReportBuilder{ - parser: ql.NewParser(), - module: module, - report: report, - } -} - -func (b *recordReportBuilder) Build(metrics, dimensions, filters string) (sql string, args []interface{}, err error) { - var joinedFields = []string{} - var alreadyJoined = func(f string) bool { - for _, a := range joinedFields { - if a == f { - return true - } - } - - joinedFields = append(joinedFields, f) - return false - } - - b.parser.OnIdent = func(i ql.Ident) (ql.Ident, error) { - var is bool - if i.Value, is = isRealRecordCol(i.Value); is { - return i, nil - } - - if !b.module.Fields.HasName(i.Value) { - return i, errors.Errorf("unknown field %q", i.Value) - } - - if !alreadyJoined(i.Value) { - b.report = b.report.LeftJoin(fmt.Sprintf( - "compose_record_value AS rv_%s ON (rv_%s.record_id = r.id AND rv_%s.name = ? AND rv_%s.deleted_at IS NULL)", - i.Value, i.Value, i.Value, i.Value, - ), i.Value) - } - - // @todo switch value for ref when doing Record/Owner lookup - i.Value = fmt.Sprintf("rv_%s.value", i.Value) - - return i, nil - } - - var columns ql.Columns - b.parser.OnFunction = stdAggregationHandler - if columns, err = b.parser.ParseColumns(metrics); err != nil { - err = errors.Wrapf(err, "could not parse metrics %q", metrics) - return - } - - // Add all metrics to columns - for i, m := range columns { - if m.Alias == "" { - // Generate alias - m.Alias = fmt.Sprintf("metric_%d", i) - } - - // Wrap to cast func to ensure numeric output - col := squirrel.Alias(rh.SquirrelConcatExpr("CAST(", m.Expr, " AS DECIMAL(14,2))"), m.Alias) - b.report = b.report.Column(col) - - b.numerics = append(b.numerics, m.Alias) - } - - b.parser.OnFunction = stdFilterFuncHandler - if columns, err = b.parser.ParseColumns(dimensions); err != nil { - err = errors.Wrapf(err, "could not parse dimensions %q", dimensions) - return - } - - // Add dimensions - for i, d := range columns { - if d.Alias == "" { - d.Alias = fmt.Sprintf("dimension_%d", i) - } - - b.report = b.report. - Column(d). - GroupBy(d.Alias). - OrderBy(d.Alias) - } - - // Use a different handler for filter functions for this - b.parser.OnFunction = stdFilterFuncHandler - - if len(filters) > 0 { - var filter ql.ASTNode - if filter, err = b.parser.ParseExpression(filters); err != nil { - err = errors.Wrapf(err, "could not parse filters %q", filters) - return - } - - // We need to wrap this one level deeper, since additional filters should - // be evaluated as a whole. - // For example A AND B OR C =should be> (A AND B OR C) - // so the output becomes BASE AND (ADDITIONAL) - b.report = b.report.Where(ql.ASTNodes{filter}) - } - - return b.report.ToSql() -} - -func (b recordReportBuilder) Cast(row sqlx.ColScanner) map[string]interface{} { - out := map[string]interface{}{} - sqlx.MapScan(row, out) - for k, v := range out { - switch cv := v.(type) { - case []uint8: - out[k] = string(cv) - default: - } - } - - // Cast all metrics to float64 - for _, fname := range b.numerics { - switch num := out[fname].(type) { - case string: - out[fname], _ = strconv.ParseFloat(num, 64) - } - } - - return out -} diff --git a/compose/repository/record_report_builder_test.go b/compose/repository/record_report_builder_test.go deleted file mode 100644 index 65eabd531..000000000 --- a/compose/repository/record_report_builder_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package repository - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cortezaproject/corteza-server/compose/types" -) - -func TestRecordReportBuilder2(t *testing.T) { - builder := NewRecordReportBuilder(&types.Module{ - ID: 1000, - Fields: types.ModuleFieldSet{ - &types.ModuleField{Name: "single1"}, - &types.ModuleField{Name: "multi1", Multi: true}, - &types.ModuleField{Name: "ref1", Kind: "Record"}, - &types.ModuleField{Name: "multiRef1", Kind: "Record", Multi: true}, - }}, - ) - - expected := "SELECT (COUNT(*)) AS count, (CAST(max(rv_single1.value) AS DECIMAL(14,2))) AS metric_0, " + - "(QUARTER(rv_ref1.value)) AS dimension_0 " + - "FROM compose_record AS r " + - "LEFT JOIN compose_record_value AS rv_single1 ON (rv_single1.record_id = r.id AND rv_single1.name = ? AND rv_single1.deleted_at IS NULL) " + - "LEFT JOIN compose_record_value AS rv_ref1 ON (rv_ref1.record_id = r.id AND rv_ref1.name = ? AND rv_ref1.deleted_at IS NULL) " + - "WHERE r.deleted_at IS NULL AND r.module_id = ? AND (rv_ref1.value = 2) " + - "GROUP BY dimension_0 " + - "ORDER BY dimension_0" - - sql, _, err := builder.Build("max(single1)", "QUARTER(ref1)", "ref1 = 2") - require.NoError(t, err) - require.Equal(t, expected, sql) -} diff --git a/compose/repository/record_test.go b/compose/repository/record_test.go deleted file mode 100644 index 332bd23ff..000000000 --- a/compose/repository/record_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package repository - -import ( - "fmt" - "github.com/cortezaproject/corteza-server/pkg/rh" - "strings" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cortezaproject/corteza-server/compose/types" -) - -func TestRecordFinder(t *testing.T) { - r := record{} - m := &types.Module{ - ID: 123, - NamespaceID: 456, - Fields: types.ModuleFieldSet{ - &types.ModuleField{Name: "foo"}, - &types.ModuleField{Name: "bar"}, - &types.ModuleField{Name: "booly", Kind: "Bool"}, - }, - } - - ttc := []struct { - name string - f types.RecordFilter - match []string - noMatch []string - args []interface{} - err error - }{ - { - name: "default filter", - match: []string{ - "SELECT r.id, r.module_id, r.rel_namespace, r.owned_by, r.created_at, " + - "r.created_by, r.updated_at, r.updated_by, r.deleted_at, r.deleted_by " + - "FROM compose_record AS r " + - "WHERE r.module_id = ? AND r.rel_namespace = ? AND r.deleted_at IS NULL", - }, - }, - { - name: "simple query", - f: types.RecordFilter{Query: "id = 5 AND foo = 7"}, - match: []string{ - "r.id = 5", - "rv_foo.value = 7"}, - args: []interface{}{"foo"}, - }, - { - name: "sorting", - f: types.RecordFilter{Sort: "id ASC, bar DESC"}, - match: []string{ - " r.id ASC", - " rv_bar.value DESC", - }, - args: []interface{}{"bar"}, - }, - { - name: "exclude deleted records (def. behaviour)", - f: types.RecordFilter{Deleted: rh.FilterStateExcluded}, - match: []string{" r.deleted_at IS "}, - }, - { - name: "include deleted records", - f: types.RecordFilter{Deleted: rh.FilterStateInclusive}, - noMatch: []string{" r.deleted_at IS NULL "}, - }, - { - name: "only deleted record", - f: types.RecordFilter{Deleted: rh.FilterStateExclusive}, - match: []string{" r.deleted_at IS NOT NULL"}, - }, - { - name: "boolean", - f: types.RecordFilter{Query: "booly"}, - match: []string{"(rv_booly.value NOT IN ("}, - args: []interface{}{"booly"}, - }, - } - - for _, tc := range ttc { - t.Run(tc.name, func(t *testing.T) { - sb, err := r.buildQuery(m, tc.f) - - if tc.err != nil { - require.True(t, tc.err.Error() == fmt.Sprintf("%v", err), "buildQuery(%+v) did not return an expected error %q but %q", tc.f, tc.err, err) - } else { - require.True(t, err == nil, "buildQuery(%+v) returned an unexpected error: %v", tc.f, err) - } - - sql, args, err := sb.ToSql() - - for _, m := range tc.match { - require.True(t, strings.Contains(sql, m), - "assertion failed; query %q \n "+ - " did not contain %q", sql, m) - } - - for _, m := range tc.noMatch { - require.False(t, strings.Contains(sql, m), - "assertion failed; query %q \n "+ - " must not contain %q", sql, m) - } - - tc.args = append(tc.args, m.ID, m.NamespaceID) - require.True(t, fmt.Sprintf("%+v", args) == fmt.Sprintf("%+v", tc.args), - "assertion failed; args %+v \n "+ - " do not match expected %+v", args, tc.args) - }) - } -} diff --git a/compose/repository/repository.go b/compose/repository/repository.go deleted file mode 100644 index dd31fd889..000000000 --- a/compose/repository/repository.go +++ /dev/null @@ -1,40 +0,0 @@ -package repository - -import ( - "context" - - "github.com/titpetric/factory" -) - -type ( - repository struct { - ctx context.Context - dbh *factory.DB - } -) - -// DB produces a contextual DB handle -func DB(ctx context.Context) *factory.DB { - return factory.Database.MustGet().With(ctx) -} - -// With updates repository and database contexts -func (r *repository) With(ctx context.Context, db *factory.DB) *repository { - return &repository{ - ctx: ctx, - dbh: db, - } -} - -// Context returns current active repository context -func (r *repository) Context() context.Context { - return r.ctx -} - -// db returns context-aware db handle -func (r *repository) db() *factory.DB { - if r.dbh != nil { - return r.dbh - } - return DB(r.ctx) -}