Add ‘purge’ SQL function
This commit is contained in:
parent
671e59d13f
commit
7afe14ab1a
5 changed files with 166 additions and 6 deletions
|
@ -88,6 +88,12 @@ var funcs = map[string]map[int]interface{}{
|
|||
"count.if": {2: nil},
|
||||
"count.not": {2: nil},
|
||||
|
||||
// Purge implementation
|
||||
|
||||
"purge": {1: nil},
|
||||
"purge.if": {2: nil},
|
||||
"purge.not": {2: nil},
|
||||
|
||||
// Json implementation
|
||||
"json.decode": {1: nil},
|
||||
"json.encode": {1: nil},
|
||||
|
|
|
@ -25,6 +25,12 @@ import (
|
|||
|
||||
var defaultTime = time.Unix(0, 0)
|
||||
|
||||
func copySlice(arr []interface{}) (out []interface{}) {
|
||||
out = make([]interface{}, len(arr))
|
||||
copy(out, arr)
|
||||
return
|
||||
}
|
||||
|
||||
func outputFloat(val float64) (interface{}, error) {
|
||||
switch {
|
||||
case math.IsNaN(val):
|
||||
|
@ -176,20 +182,18 @@ func ensureDuration(val interface{}) (out time.Duration, ok bool) {
|
|||
|
||||
func ensureSlice(args interface{}) (out []interface{}, ok bool) {
|
||||
if i, ok := args.([]interface{}); ok {
|
||||
out = i
|
||||
return i, true
|
||||
} else {
|
||||
out = []interface{}{args}
|
||||
return []interface{}{args}, false
|
||||
}
|
||||
return out, true
|
||||
}
|
||||
|
||||
func ensureObject(args interface{}) (out map[string]interface{}, ok bool) {
|
||||
if i, ok := args.(map[string]interface{}); ok {
|
||||
out = i
|
||||
return i, true
|
||||
} else {
|
||||
out = map[string]interface{}{}
|
||||
return map[string]interface{}{}, false
|
||||
}
|
||||
return out, true
|
||||
}
|
||||
|
||||
func ensureInts(args interface{}) (out []int64) {
|
||||
|
|
|
@ -55,6 +55,14 @@ func Run(ctx context.Context, name string, args ...interface{}) (interface{}, er
|
|||
case "count.not":
|
||||
return countNot(ctx, args...)
|
||||
|
||||
// Purge implementation
|
||||
case "purge":
|
||||
return purge(ctx, args...)
|
||||
case "purge.if":
|
||||
return purgeIf(ctx, args...)
|
||||
case "purge.not":
|
||||
return purgeNot(ctx, args...)
|
||||
|
||||
// Json implementation
|
||||
case "json.decode":
|
||||
return jsonDecode(ctx, args...)
|
||||
|
|
73
util/fncs/purge.go
Normal file
73
util/fncs/purge.go
Normal file
|
@ -0,0 +1,73 @@
|
|||
// 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 purge(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if arr, ok := ensureSlice(args[0]); ok {
|
||||
arr = copySlice(arr)
|
||||
for i := len(arr) - 1; i >= 0; i-- {
|
||||
if arr[i] == nil {
|
||||
copy(arr[i:], arr[i+1:])
|
||||
arr[len(arr)-1] = nil
|
||||
arr = arr[:len(arr)-1]
|
||||
}
|
||||
}
|
||||
return arr, nil
|
||||
}
|
||||
if args[0] == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return args[0], nil
|
||||
}
|
||||
|
||||
func purgeIf(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if arr, ok := ensureSlice(args[0]); ok {
|
||||
arr = copySlice(arr)
|
||||
for i := len(arr) - 1; i >= 0; i-- {
|
||||
if arr[i] == args[1] {
|
||||
copy(arr[i:], arr[i+1:])
|
||||
arr[len(arr)-1] = nil
|
||||
arr = arr[:len(arr)-1]
|
||||
}
|
||||
}
|
||||
return arr, nil
|
||||
}
|
||||
if args[0] == args[1] {
|
||||
return nil, nil
|
||||
}
|
||||
return args[0], nil
|
||||
}
|
||||
|
||||
func purgeNot(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if arr, ok := ensureSlice(args[0]); ok {
|
||||
arr = copySlice(arr)
|
||||
for i := len(arr) - 1; i >= 0; i-- {
|
||||
if arr[i] != args[1] {
|
||||
copy(arr[i:], arr[i+1:])
|
||||
arr[len(arr)-1] = nil
|
||||
arr = arr[:len(arr)-1]
|
||||
}
|
||||
}
|
||||
return arr, nil
|
||||
}
|
||||
if args[0] != args[1] {
|
||||
return nil, nil
|
||||
}
|
||||
return args[0], nil
|
||||
}
|
69
util/fncs/purge_test.go
Normal file
69
util/fncs/purge_test.go
Normal file
|
@ -0,0 +1,69 @@
|
|||
// 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 TestPurge(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
|
||||
var test = []interface{}{int(1), int(2), nil, float64(3.5), "testing string"}
|
||||
|
||||
Convey("purge() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "purge", nil)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "purge", "test")
|
||||
So(res, ShouldResemble, "test")
|
||||
res, _ = Run(context.Background(), "purge", test)
|
||||
So(res, ShouldResemble, []interface{}{int(1), int(2), float64(3.5), "testing string"})
|
||||
})
|
||||
|
||||
Convey("purge.if() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "purge.if", "test", nil)
|
||||
So(res, ShouldResemble, "test")
|
||||
res, _ = Run(context.Background(), "purge.if", "test", "none")
|
||||
So(res, ShouldResemble, "test")
|
||||
res, _ = Run(context.Background(), "purge.if", "test", "test")
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "purge.if", test, "testing string")
|
||||
So(res, ShouldResemble, []interface{}{int(1), int(2), nil, float64(3.5)})
|
||||
res, _ = Run(context.Background(), "purge.if", test, 3.5)
|
||||
So(res, ShouldResemble, []interface{}{int(1), int(2), nil, "testing string"})
|
||||
res, _ = Run(context.Background(), "purge.if", test, nil)
|
||||
So(res, ShouldResemble, []interface{}{int(1), int(2), float64(3.5), "testing string"})
|
||||
})
|
||||
|
||||
Convey("purge.not() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "purge.not", "test", nil)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "purge.not", "test", "none")
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "purge.not", "test", "test")
|
||||
So(res, ShouldResemble, "test")
|
||||
res, _ = Run(context.Background(), "purge.not", test, "testing string")
|
||||
So(res, ShouldResemble, []interface{}{"testing string"})
|
||||
res, _ = Run(context.Background(), "purge.not", test, 3.5)
|
||||
So(res, ShouldResemble, []interface{}{float64(3.5)})
|
||||
res, _ = Run(context.Background(), "purge.not", test, nil)
|
||||
So(res, ShouldResemble, []interface{}{nil})
|
||||
})
|
||||
|
||||
}
|
Loading…
Reference in a new issue