From d861eff3779568aa58f255113d575edddf73120d Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 9 Jun 2015 07:26:50 -0800 Subject: [PATCH] Move url param to list func, search meas. --- characteristics.go | 10 +++++-- entities.go | 4 ++- handlers.go | 9 ++----- measurements.go | 65 ++++++++++++++++++++++++++++++++++++++-------- species.go | 11 +++++--- strains.go | 11 +++++--- 6 files changed, 83 insertions(+), 27 deletions(-) diff --git a/characteristics.go b/characteristics.go index 873d93a..efa2608 100644 --- a/characteristics.go +++ b/characteristics.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "net/url" "strings" "time" ) @@ -52,10 +53,15 @@ func (c *Characteristics) marshal() ([]byte, error) { return json.Marshal(&CharacteristicsJSON{Characteristics: c}) } -func (c CharacteristicService) list(opt *ListOptions) (entity, error) { - if opt == nil { +func (c CharacteristicService) list(val *url.Values) (entity, error) { + if val == nil { return nil, errors.New("must provide options") } + var opt ListOptions + if err := schemaDecoder.Decode(&opt, *val); err != nil { + return nil, err + } + var vals []interface{} sql := `SELECT c.*, ct.characteristic_type_name, array_agg(m.id) AS measurements, array_agg(st.id) AS strains diff --git a/entities.go b/entities.go index f291968..66a09e4 100644 --- a/entities.go +++ b/entities.go @@ -1,5 +1,7 @@ package main +import "net/url" + type entity interface { marshal() ([]byte, error) } @@ -9,7 +11,7 @@ type getter interface { } type lister interface { - list(*ListOptions) (entity, error) + list(*url.Values) (entity, error) } type updater interface { diff --git a/handlers.go b/handlers.go index ec479a8..16d497a 100644 --- a/handlers.go +++ b/handlers.go @@ -132,13 +132,8 @@ func handleGetter(g getter) http.HandlerFunc { func handleLister(l lister) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var opt ListOptions - if err := schemaDecoder.Decode(&opt, r.URL.Query()); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - opt.Genus = mux.Vars(r)["genus"] + opt := r.URL.Query() + opt.Add("Genus", mux.Vars(r)["genus"]) es, err := l.list(&opt) if err != nil { diff --git a/measurements.go b/measurements.go index 00a21aa..3232a1f 100644 --- a/measurements.go +++ b/measurements.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "net/url" "strings" "time" ) @@ -63,10 +64,18 @@ func (m *Measurements) marshal() ([]byte, error) { return json.Marshal(&MeasurementsJSON{Measurements: m}) } -func (m MeasurementService) list(opt *ListOptions) (entity, error) { - if opt == nil { +func (m MeasurementService) list(val *url.Values) (entity, error) { + if val == nil { return nil, errors.New("must provide options") } + var opt struct { + ListOptions + Strain *int64 + Characteristic *int64 + } + if err := schemaDecoder.Decode(&opt, *val); err != nil { + return nil, err + } var vals []interface{} sql := `SELECT m.*, t.text_measurement_name AS text_measurement_type_name, @@ -81,17 +90,51 @@ func (m MeasurementService) list(opt *ListOptions) (entity, error) { LEFT OUTER JOIN test_methods te ON te.id=m.test_method_id` vals = append(vals, opt.Genus) - if len(opt.Ids) != 0 { - var conds []string + strainId := opt.Strain != nil + charId := opt.Characteristic != nil + ids := len(opt.Ids) != 0 - m := "m.id IN (" - for i, id := range opt.Ids { - m = m + fmt.Sprintf("$%v,", i+2) // start param index at 2 - vals = append(vals, id) + if strainId || charId || ids { + paramsCounter := 2 + sql += "\nWHERE (" + + // Filter by strain + if strainId { + sql += fmt.Sprintf("st.id=$%v", paramsCounter) + vals = append(vals, *opt.Strain) + paramsCounter++ } - m = m[:len(m)-1] + ")" - conds = append(conds, m) - sql += " WHERE (" + strings.Join(conds, ") AND (") + ")" + + if strainId && (charId || ids) { + sql += " AND " + } + + // Filter by characteristic + if charId { + sql += fmt.Sprintf("c.id=$%v", paramsCounter) + vals = append(vals, *opt.Characteristic) + paramsCounter++ + } + + if charId && ids { + sql += " AND " + } + + // Get specific records + if ids { + var conds []string + + m := "m.id IN (" + for _, id := range opt.Ids { + m = m + fmt.Sprintf("$%v,", paramsCounter) + vals = append(vals, id) + paramsCounter++ + } + m = m[:len(m)-1] + ")" + conds = append(conds, m) + sql += strings.Join(conds, ") AND (") + } + sql += ")" } sql += ";" diff --git a/species.go b/species.go index 2730953..f24900d 100644 --- a/species.go +++ b/species.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "net/url" "strings" ) @@ -67,12 +68,16 @@ func (s SpeciesService) unmarshal(b []byte) (entity, error) { return sj.Species, err } -func (s SpeciesService) list(opt *ListOptions) (entity, error) { - if opt == nil { +func (s SpeciesService) list(val *url.Values) (entity, error) { + if val == nil { return nil, errors.New("must provide options") } - var vals []interface{} + var opt ListOptions + if err := schemaDecoder.Decode(&opt, *val); err != nil { + return nil, err + } + var vals []interface{} sql := `SELECT sp.*, g.genus_name, array_agg(st.id) AS strains, COUNT(st) AS total_strains FROM species sp diff --git a/strains.go b/strains.go index f772b01..2b117d3 100644 --- a/strains.go +++ b/strains.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "net/url" "strings" ) @@ -68,12 +69,16 @@ func (s StrainService) unmarshal(b []byte) (entity, error) { return sj.Strain, err } -func (s StrainService) list(opt *ListOptions) (entity, error) { - if opt == nil { +func (s StrainService) list(val *url.Values) (entity, error) { + if val == nil { return nil, errors.New("must provide options") } - var vals []interface{} + var opt ListOptions + if err := schemaDecoder.Decode(&opt, *val); err != nil { + return nil, err + } + var vals []interface{} sql := `SELECT st.*, array_agg(m.id) AS measurements, COUNT(m) AS total_measurements FROM strains st INNER JOIN species sp ON sp.id=st.species_id