From 4c10a0302f2827c07e9fb38764c52c5a8f36b1bd Mon Sep 17 00:00:00 2001 From: Mosen Date: Thu, 21 Jul 2016 22:55:58 +1000 Subject: [PATCH] Attempt to make the wherer interface type a little bit more flexible to accomodate many different field types. Tests for wherer, WhereAnd and WhereOr --- certificates/datastore.go | 23 ------------ certificates/statement.go | 64 ++++++++++++++++++++++++++++++++++ certificates/statement_test.go | 48 +++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 23 deletions(-) create mode 100644 certificates/statement.go create mode 100644 certificates/statement_test.go diff --git a/certificates/datastore.go b/certificates/datastore.go index 1295b95c..51e3dd15 100644 --- a/certificates/datastore.go +++ b/certificates/datastore.go @@ -103,29 +103,6 @@ func (store pgStore) GetCertificatesByDeviceUDID(udid string) ([]Certificate, er return certificates, nil } -// UUID is a filter that can be added as a parameter to narrow down the list of returned results -type UUID struct { - UUID string -} - -func (p UUID) where() string { - return fmt.Sprintf("certificate_uuid = '%s'", p.UUID) -} - -// Filter by a device uuid -type DeviceUUID struct { - UUID string -} - -func (p DeviceUUID) where() string { - return fmt.Sprintf("device_uuid = '%s'", p.UUID) -} - -// whereer is for building args passed into a method which finds resources -type whereer interface { - where() string -} - // add WHERE clause from params func addWhereFilters(stmt string, separator string, params ...interface{}) string { var where []string diff --git a/certificates/statement.go b/certificates/statement.go new file mode 100644 index 00000000..7b4fdab1 --- /dev/null +++ b/certificates/statement.go @@ -0,0 +1,64 @@ +package certificates + +import ( + "fmt" + "strconv" + "strings" +) + +// Where struct wraps a where clause. +// Basic usage is Where{"field","value"} for WHERE field = value +// The Operator field can be used if you need < > = != LIKE / NOT LIKE operators +type Where struct { + Field string + Value interface{} + Operator string +} + +// Stringer produces the WHERE condition +func (w Where) String() string { + var operator string = w.Operator + if w.Operator == "" { + operator = "=" + } + + var quotedValue string + switch w.Value.(type) { + case string: + quotedValue = fmt.Sprintf("'%s'", w.Value) + case nil: + operator = "IS" + quotedValue = "NULL" + case bool: + if w.Value.(bool) == true { + quotedValue = "true" + } else { + quotedValue = "false" + } + case []string: // IN("strings...") + operator = "IN" + inValues := w.Value.([]string) + quotedValue = "('" + strings.Join(inValues, "','") + "')" + case int: + quotedValue = strconv.Itoa(w.Value.(int)) + } + + return fmt.Sprintf("%s %s %s", w.Field, operator, quotedValue) +} + +// whereer is for building args passed into a method which finds resources +type whereer interface { + where() string +} + +type WhereAnd []Where + +func (wa WhereAnd) String() { + return strings.Join(wa, " AND ") +} + +type WhereOr []Where + +func (wo WhereOr) String() { + return strings.Join(wo, " OR ") +} diff --git a/certificates/statement_test.go b/certificates/statement_test.go new file mode 100644 index 00000000..faa5c0c3 --- /dev/null +++ b/certificates/statement_test.go @@ -0,0 +1,48 @@ +package certificates + +import ( + "testing" +) + +type testpair struct { + when Where + then string +} + +var tests = []testpair{ + {Where{"field", "value", "="}, "field = 'value'"}, + {Where{"field", 1, "="}, "field = 1"}, + {Where{"field", false, "="}, "field = false"}, + {Where{"field", []string{"foo", "bar"}, "IN"}, "field IN ('foo','bar')"}, + {Where{"field", "%foo%", "LIKE"}, "field LIKE '%foo%'"}, + {Where{"field", "bar", "!="}, "field != 'bar'"}, + {Where{"field", nil, "IS"}, "field IS NULL"}, +} + +func TestWhere(t *testing.T) { + for _, test := range tests { + v := test.when.String() + if v != test.then { + t.Error( + "Expected", test.then, + "got", v, + ) + } + } +} + +var waTests = []testpair{ + {WhereAnd{Where{"field", "value", "="}, Where{"field", "bar", "="}}, "field = 'value' AND field = 'bar'"}, +} + +func TestWhereAnd_String(t *testing.T) { + for _, test := range waTests { + v := test.when.String() + if v != test.then { + t.Error( + "Expected", test.then, + "got", v, + ) + } + } +}