From 343663458677a06808488cb1f4dfc502eff18d07 Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Sun, 18 Mar 2018 19:03:14 +0000 Subject: [PATCH] Add SQL either function for simplified IF ELSE clauses --- sql/funcs.go | 1 + util/fncs/either.go | 51 ++++++++++++++++++++++++++++++++ util/fncs/either_test.go | 64 ++++++++++++++++++++++++++++++++++++++++ util/fncs/fnc.go | 2 ++ 4 files changed, 118 insertions(+) create mode 100644 util/fncs/either.go create mode 100644 util/fncs/either_test.go diff --git a/sql/funcs.go b/sql/funcs.go index cdec2277..1657ac70 100644 --- a/sql/funcs.go +++ b/sql/funcs.go @@ -103,6 +103,7 @@ var funcs = map[string]map[int]interface{}{ "binary": {1: nil}, "difference": {-1: nil}, "distinct": {1: nil}, + "either": {-1: nil}, "get": {2: nil}, "if": {3: nil}, "intersect": {-1: nil}, diff --git a/util/fncs/either.go b/util/fncs/either.go new file mode 100644 index 00000000..b041f699 --- /dev/null +++ b/util/fncs/either.go @@ -0,0 +1,51 @@ +// Copyright © 2016 Abcum Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fncs + +import ( + "context" +) + +func either(ctx context.Context, args ...interface{}) (interface{}, error) { + for _, a := range args { + switch v := a.(type) { + case nil: + continue + default: + return v, nil + case string: + if v != "" { + return v, nil + } + case int64: + if v != 0 { + return v, nil + } + case float64: + if v != 0 { + return v, nil + } + case []interface{}: + if len(v) != 0 { + return v, nil + } + case map[string]interface{}: + if len(v) != 0 { + return v, nil + } + } + } + return nil, nil +} diff --git a/util/fncs/either_test.go b/util/fncs/either_test.go new file mode 100644 index 00000000..a06dbc26 --- /dev/null +++ b/util/fncs/either_test.go @@ -0,0 +1,64 @@ +// Copyright © 2016 Abcum Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fncs + +import ( + "context" + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestEither(t *testing.T) { + + var res interface{} + + Convey("either() works properly", t, func() { + + res, _ = Run(context.Background(), "either", nil, true) + So(res, ShouldResemble, true) + + res, _ = Run(context.Background(), "either", int64(0), "two") + So(res, ShouldResemble, "two") + res, _ = Run(context.Background(), "either", int64(1), "two") + So(res, ShouldResemble, int64(1)) + res, _ = Run(context.Background(), "either", int64(-1), "two") + So(res, ShouldResemble, int64(-1)) + + res, _ = Run(context.Background(), "either", float64(0), "two") + So(res, ShouldResemble, "two") + res, _ = Run(context.Background(), "either", float64(1), "two") + So(res, ShouldResemble, float64(1)) + res, _ = Run(context.Background(), "either", float64(-1), "two") + So(res, ShouldResemble, float64(-1)) + + res, _ = Run(context.Background(), "either", "", "two") + So(res, ShouldResemble, "two") + res, _ = Run(context.Background(), "either", "one", "two") + So(res, ShouldResemble, "one") + + res, _ = Run(context.Background(), "either", []interface{}{}, []interface{}{"two"}) + So(res, ShouldResemble, []interface{}{"two"}) + res, _ = Run(context.Background(), "either", []interface{}{"one"}, []interface{}{"two"}) + So(res, ShouldResemble, []interface{}{"one"}) + + res, _ = Run(context.Background(), "either", map[string]interface{}{}, map[string]interface{}{"two": true}) + So(res, ShouldResemble, map[string]interface{}{"two": true}) + res, _ = Run(context.Background(), "either", map[string]interface{}{"one": true}, map[string]interface{}{"two": true}) + So(res, ShouldResemble, map[string]interface{}{"one": true}) + + }) + +} diff --git a/util/fncs/fnc.go b/util/fncs/fnc.go index 1eb37864..c9cbb141 100644 --- a/util/fncs/fnc.go +++ b/util/fncs/fnc.go @@ -28,6 +28,8 @@ func Run(ctx context.Context, name string, args ...interface{}) (interface{}, er return difference(ctx, args...) case "distinct": return distinct(ctx, args...) + case "either": + return either(ctx, args...) case "get": return get(ctx, args...) case "if":