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.if": {2: nil},
|
||||||
"count.not": {2: nil},
|
"count.not": {2: nil},
|
||||||
|
|
||||||
|
// Purge implementation
|
||||||
|
|
||||||
|
"purge": {1: nil},
|
||||||
|
"purge.if": {2: nil},
|
||||||
|
"purge.not": {2: nil},
|
||||||
|
|
||||||
// Json implementation
|
// Json implementation
|
||||||
"json.decode": {1: nil},
|
"json.decode": {1: nil},
|
||||||
"json.encode": {1: nil},
|
"json.encode": {1: nil},
|
||||||
|
|
|
@ -25,6 +25,12 @@ import (
|
||||||
|
|
||||||
var defaultTime = time.Unix(0, 0)
|
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) {
|
func outputFloat(val float64) (interface{}, error) {
|
||||||
switch {
|
switch {
|
||||||
case math.IsNaN(val):
|
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) {
|
func ensureSlice(args interface{}) (out []interface{}, ok bool) {
|
||||||
if i, ok := args.([]interface{}); ok {
|
if i, ok := args.([]interface{}); ok {
|
||||||
out = i
|
return i, true
|
||||||
} else {
|
} else {
|
||||||
out = []interface{}{args}
|
return []interface{}{args}, false
|
||||||
}
|
}
|
||||||
return out, true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureObject(args interface{}) (out map[string]interface{}, ok bool) {
|
func ensureObject(args interface{}) (out map[string]interface{}, ok bool) {
|
||||||
if i, ok := args.(map[string]interface{}); ok {
|
if i, ok := args.(map[string]interface{}); ok {
|
||||||
out = i
|
return i, true
|
||||||
} else {
|
} else {
|
||||||
out = map[string]interface{}{}
|
return map[string]interface{}{}, false
|
||||||
}
|
}
|
||||||
return out, true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureInts(args interface{}) (out []int64) {
|
func ensureInts(args interface{}) (out []int64) {
|
||||||
|
|
|
@ -55,6 +55,14 @@ func Run(ctx context.Context, name string, args ...interface{}) (interface{}, er
|
||||||
case "count.not":
|
case "count.not":
|
||||||
return countNot(ctx, args...)
|
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
|
// Json implementation
|
||||||
case "json.decode":
|
case "json.decode":
|
||||||
return jsonDecode(ctx, args...)
|
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