/** * file: types/productSearch.go * author: Theo Technicguy * license: Apache 2.0 * * product searching type and functions */ package types import ( "errors" "fmt" "strings" ) var ( ErrInvalidSearch = errors.New("invalid search") ) type ProductSearch struct { Ean string Names []string TagIds []uint Oprators ProductSearchOperators } type ProductSearchOperators struct { Master string Names string TagIds string } /* *** Validators *** */ func (pso *ProductSearchOperators) ValidOperators() bool { return ((pso.Master == "AND" || pso.Master == "OR") && (pso.Names == "AND" || pso.Names == "OR") && (pso.TagIds == "AND" || pso.TagIds == "OR")) } func (pso *ProductSearchOperators) Valid() bool { return pso.ValidOperators() } func (ps *ProductSearch) Valid() bool { return ps.Oprators.Valid() } /* *** Type functions *** */ func (pso *ProductSearchOperators) FillDefaults() { if pso.Master == "" { pso.Master = "AND" } if pso.Names == "" { pso.Names = "AND" } if pso.TagIds == "" { pso.TagIds = "AND" } } func (ps *ProductSearch) BuildNamesSearch() string { nameSearch := []string{} for _, name := range ps.Names { nameSearch = append(nameSearch, fmt.Sprintf("p.name LIKE '%%%s%%'", name)) } return "(" + strings.Join(nameSearch, " "+ps.Oprators.Names+" ") + ")" } func (ps *ProductSearch) BuildTagSearch() string { tagSearch := []string{} for _, tag := range ps.TagIds { tagSearch = append(tagSearch, fmt.Sprintf("%d", tag)) } return "ptg.tid IN (" + strings.Join(tagSearch, ", ") + ")" } func (ps *ProductSearch) BuildSearch() string { sql := `SELECT DISTINCT p.* FROM Product p LEFT OUTER JOIN ProductTagging ptg ON p.ProductID = ptg.ProductID LEFT OUTER JOIN ProductTag pt ON ptg.TagID = pt.TagID ` filters := []string{} if ps.Ean != "" { filters = append(filters, fmt.Sprintf("p.ean LIKE '%%%s%%'", ps.Ean)) } if len(ps.Names) > 0 { filters = append(filters, ps.BuildNamesSearch()) } if len(ps.TagIds) > 0 { filters = append(filters, ps.BuildTagSearch()) } if len(filters) > 0 { sql = sql + "WHERE (" + strings.Join(filters, " "+ps.Oprators.Master+" ") + ")\n" } if len(ps.TagIds) > 0 { sql = sql + "GROUP BY p.id" if ps.Oprators.TagIds == "AND" { sql = sql + fmt.Sprintf("\nHAVING COUNT(p.id) = %d", len(ps.TagIds)) } } sql = sql + ";" return sql }