From f32da9dd7da7415cf0d85509fef424c91beb0865 Mon Sep 17 00:00:00 2001 From: Daniel Lohse Date: Tue, 1 Sep 2015 09:57:53 +0200 Subject: [PATCH 1/3] Added `recipes.RangeInterface` to make the Range object exchangeable. --- recipes/crud.go | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/recipes/crud.go b/recipes/crud.go index dda0fe9..02f6d91 100644 --- a/recipes/crud.go +++ b/recipes/crud.go @@ -14,6 +14,17 @@ import ( r "github.com/elvtechnology/gocqltable/reflect" ) +type RangeInterface interface { + LessThan(rangeKey string, value interface{}) RangeInterface + LessThanOrEqual(rangeKey string, value interface{}) RangeInterface + MoreThan(rangeKey string, value interface{}) RangeInterface + MoreThanOrEqual(rangeKey string, value interface{}) RangeInterface + EqualTo(rangeKey string, value interface{}) RangeInterface + OrderBy(fieldAndDirection string) RangeInterface + Limit(l int) RangeInterface + Fetch() (interface{}, error) +} + type CRUD struct { gocqltable.TableInterface } @@ -197,8 +208,7 @@ func (t CRUD) Delete(row interface{}) error { } -func (t CRUD) Range(ids ...interface{}) Range { - +func (t CRUD) Range(ids ...interface{}) RangeInterface { rowKeys := t.RowKeys() rangeKeys := t.RangeKeys() @@ -211,8 +221,8 @@ func (t CRUD) Range(ids ...interface{}) Range { if len(ids) == numAppended { break } - rangeObj = rangeObj.EqualTo(key, ids[idx]) - numAppended += 1 + rangeObj = rangeObj.EqualTo(key, ids[idx]).(Range) + numAppended++ } return rangeObj @@ -228,46 +238,46 @@ type Range struct { filtering bool } -func (r Range) LessThan(rangeKey string, value interface{}) Range { +func (r Range) LessThan(rangeKey string, value interface{}) RangeInterface { r.where = append(r.where, fmt.Sprintf("%q", strings.ToLower(rangeKey))+" < ?") r.whereVals = append(r.whereVals, value) r.filtering = true return r } -func (r Range) LessThanOrEqual(rangeKey string, value interface{}) Range { +func (r Range) LessThanOrEqual(rangeKey string, value interface{}) RangeInterface { r.where = append(r.where, fmt.Sprintf("%q", strings.ToLower(rangeKey))+" <= ?") r.whereVals = append(r.whereVals, value) r.filtering = true return r } -func (r Range) MoreThan(rangeKey string, value interface{}) Range { +func (r Range) MoreThan(rangeKey string, value interface{}) RangeInterface { r.where = append(r.where, fmt.Sprintf("%q", strings.ToLower(rangeKey))+" > ?") r.whereVals = append(r.whereVals, value) r.filtering = true return r } -func (r Range) MoreThanOrEqual(rangeKey string, value interface{}) Range { +func (r Range) MoreThanOrEqual(rangeKey string, value interface{}) RangeInterface { r.where = append(r.where, fmt.Sprintf("%q", strings.ToLower(rangeKey))+" >= ?") r.whereVals = append(r.whereVals, value) r.filtering = true return r } -func (r Range) EqualTo(rangeKey string, value interface{}) Range { +func (r Range) EqualTo(rangeKey string, value interface{}) RangeInterface { r.where = append(r.where, fmt.Sprintf("%q", strings.ToLower(rangeKey))+" = ?") r.whereVals = append(r.whereVals, value) return r } -func (r Range) OrderBy(fieldAndDirection string) Range { +func (r Range) OrderBy(fieldAndDirection string) RangeInterface { r.order = fieldAndDirection return r } -func (r Range) Limit(l int) Range { +func (r Range) Limit(l int) RangeInterface { r.limit = &l return r } From 90c1680b7b31537dd22ec7e292cfc48e6a54a327 Mon Sep 17 00:00:00 2001 From: Daniel Lohse Date: Tue, 1 Sep 2015 10:02:01 +0200 Subject: [PATCH 2/3] Added the ability to specify SELECT columns. `Range.Fetch()` still works, you have to be careful though to not access object members that you didn't fetch. --- recipes/crud.go | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/recipes/crud.go b/recipes/crud.go index 02f6d91..4414397 100644 --- a/recipes/crud.go +++ b/recipes/crud.go @@ -22,6 +22,7 @@ type RangeInterface interface { EqualTo(rangeKey string, value interface{}) RangeInterface OrderBy(fieldAndDirection string) RangeInterface Limit(l int) RangeInterface + Select(s []string) RangeInterface Fetch() (interface{}, error) } @@ -231,11 +232,12 @@ func (t CRUD) Range(ids ...interface{}) RangeInterface { type Range struct { table gocqltable.TableInterface - where []string - whereVals []interface{} - order string - limit *int - filtering bool + selectCols []string + where []string + whereVals []interface{} + order string + limit *int + filtering bool } func (r Range) LessThan(rangeKey string, value interface{}) RangeInterface { @@ -282,13 +284,18 @@ func (r Range) Limit(l int) RangeInterface { return r } -func (r Range) Fetch() (interface{}, error) { +func (r Range) Select(s []string) RangeInterface { + r.selectCols = s + return r +} +func (r Range) Fetch() (interface{}, error) { where := r.where whereVals := r.whereVals order := r.order limit := r.limit filtering := r.filtering + selectCols := r.selectCols whereString := "" if len(where) > 0 { @@ -310,7 +317,12 @@ func (r Range) Fetch() (interface{}, error) { filteringString = "ALLOW FILTERING" } - iter := r.table.Query(fmt.Sprintf(`SELECT * FROM %q.%q %s %s %s %s`, r.table.Keyspace().Name(), r.table.Name(), whereString, orderString, limitString, filteringString), whereVals...).Fetch() + selectString := "*" + if len(selectCols) > 0 { + selectString = strings.Join(selectCols, ", ") + } + query := fmt.Sprintf(`SELECT %s FROM %q.%q %s %s %s %s`, selectString, r.table.Keyspace().Name(), r.table.Name(), whereString, orderString, limitString, filteringString) + iter := r.table.Query(query, whereVals...).Fetch() result := reflect.Zero(reflect.SliceOf(reflect.PtrTo(reflect.TypeOf(r.table.Row())))) // Create a zero-value slice of pointers to our model type for row := range iter.Range() { From aca2000949dbb6712204aab9a494731e66ddd5e5 Mon Sep 17 00:00:00 2001 From: Daniel Lohse Date: Tue, 1 Sep 2015 10:03:13 +0200 Subject: [PATCH 3/3] Added a simple CQL WHERE a IN (x, y, z) implementation. Currently, it only works for string values. --- recipes/crud.go | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/recipes/crud.go b/recipes/crud.go index 4414397..3864ee3 100644 --- a/recipes/crud.go +++ b/recipes/crud.go @@ -23,6 +23,7 @@ type RangeInterface interface { OrderBy(fieldAndDirection string) RangeInterface Limit(l int) RangeInterface Select(s []string) RangeInterface + WhereIn(m map[string][]string) RangeInterface Fetch() (interface{}, error) } @@ -233,6 +234,7 @@ type Range struct { table gocqltable.TableInterface selectCols []string + whereIn map[string][]string where []string whereVals []interface{} order string @@ -289,6 +291,11 @@ func (r Range) Select(s []string) RangeInterface { return r } +func (r Range) WhereIn(m map[string][]string) RangeInterface { + r.whereIn = m + return r +} + func (r Range) Fetch() (interface{}, error) { where := r.where whereVals := r.whereVals @@ -296,10 +303,30 @@ func (r Range) Fetch() (interface{}, error) { limit := r.limit filtering := r.filtering selectCols := r.selectCols + whereIn := r.whereIn whereString := "" + if len(whereIn) > 0 { + numberOfInClauses := 0 + for col, in := range whereIn { + if len(in) == 0 { + continue + } + if numberOfInClauses > 0 { + whereString = whereString + " AND" + } + whereString = fmt.Sprintf("%s %q IN (%v)", whereString, col, strings.Join(in, ", ")) + numberOfInClauses++ + } + } if len(where) > 0 { - whereString = "WHERE " + strings.Join(where, " AND ") + if len(whereString) > 0 { + whereString = whereString + " AND " + } + whereString = whereString + strings.Join(where, " AND ") + } + if len(whereString) > 0 { + whereString = "WHERE " + whereString } orderString := ""