diff --git a/runtime/vam/expr/function/errors.go b/runtime/vam/expr/function/errors.go new file mode 100644 index 0000000000..f59df290fd --- /dev/null +++ b/runtime/vam/expr/function/errors.go @@ -0,0 +1,34 @@ +package function + +import ( + "github.com/brimdata/zed" + "github.com/brimdata/zed/vector" +) + +// https://github.com/brimdata/zed/blob/main/docs/language/functions.md#quiet +type Quiet struct { + zctx *zed.Context +} + +func (q *Quiet) Call(args ...vector.Any) vector.Any { + arg, ok := args[0].(*vector.Error) + if !ok { + return args[0] + } + if _, ok := arg.Typ.Type.(*zed.TypeOfString); !ok { + return args[0] + } + n := arg.Len() + vec := vector.NewStringEmpty(n, vector.NewBoolEmpty(n, nil)) + for i := uint32(0); i < n; i++ { + s, isnull := vector.StringValue(arg.Vals, i) + if isnull { + vec.Nulls.Set(i) + } + if s == "missing" { + s = "quiet" + } + vec.Append(s) + } + return vector.NewError(arg.Typ, vec, arg.Nulls) +} diff --git a/runtime/vam/expr/function/function.go b/runtime/vam/expr/function/function.go index 93c634b806..d0eb147cf7 100644 --- a/runtime/vam/expr/function/function.go +++ b/runtime/vam/expr/function/function.go @@ -30,6 +30,8 @@ func New(zctx *zed.Context, name string, narg int) (expr.Function, field.Path, e f = &Levenshtein{zctx} case "lower": f = &ToLower{zctx} + case "quiet": + f = &Quiet{} case "replace": argmin, argmax = 3, 3 f = &Replace{zctx} diff --git a/runtime/vam/op/yield.go b/runtime/vam/op/yield.go index ee337279c5..ac99b6d84d 100644 --- a/runtime/vam/op/yield.go +++ b/runtime/vam/op/yield.go @@ -44,11 +44,6 @@ func (y *Yield) Pull(done bool) (vector.Any, error) { } } -func filterQuiet(val vector.Any) vector.Any { - // XXX this can't happen until we have functions - return val -} - // XXX should work for vector.Dynamic func interleave(vals []vector.Any) vector.Any { if len(vals) < 2 { @@ -63,3 +58,59 @@ func interleave(vals []vector.Any) vector.Any { } return vector.NewDynamic(tags, vals) } + +func filterQuiet(vec vector.Any) vector.Any { + var filtered bool + mask := vector.Apply(true, func(vecs ...vector.Any) vector.Any { + mask, hasfiltered := quietMask(vecs[0]) + filtered = filtered || hasfiltered + return mask + }, vec) + if !filtered { + return vec + } + n := vec.Len() + var index []uint32 + for k := uint32(0); k < n; k++ { + if vector.BoolValue(mask, k) { + index = append(index, k) + } + } + if len(index) == 0 { + return nil + } + if len(index) == int(n) { + return vec + } + return vector.NewView(index, vec) +} + +func quietMask(vec vector.Any) (vector.Any, bool) { + errtyp, ok := vec.Type().(*zed.TypeError) + if !ok { + return vector.NewConst(zed.True, vec.Len(), nil), false + } + if _, ok := errtyp.Type.(*zed.TypeOfString); !ok { + return vector.NewConst(zed.True, vec.Len(), nil), false + } + n := vec.Len() + mask := vector.NewBoolEmpty(n, nil) + switch vec := vec.(type) { + case *vector.View: + vecerr := vec.Any.(*vector.Error) + for k, slot := range vec.Index { + if s, _ := vector.StringValue(vecerr.Vals, slot); s == "quiet" { + continue + } + mask.Set(uint32(k)) + } + case *vector.Error: + for i := uint32(0); i < n; i++ { + if s, _ := vector.StringValue(vec.Vals, i); s == "quiet" { + continue + } + mask.Set(i) + } + } + return mask, true +} diff --git a/runtime/ztests/expr/function/quiet.yaml b/runtime/ztests/expr/function/quiet.yaml new file mode 100644 index 0000000000..47cfb7f8b3 --- /dev/null +++ b/runtime/ztests/expr/function/quiet.yaml @@ -0,0 +1,19 @@ +zed: quiet(this) + +vector: true + +input: | + error("missing") + error("missing")(=foo) + error("missing"(=bar)) + null(error(string)) + error(null(string)) + error("quiet") + error({x:"missing"}) + +output: | + error("missing")(=foo) + error("missing")(error(bar=string)) + null(error(string)) + null(error(string)) + error({x:"missing"}) diff --git a/runtime/sam/op/yield/ztests/quiet.yaml b/runtime/ztests/op/yield-quiet.yaml similarity index 86% rename from runtime/sam/op/yield/ztests/quiet.yaml rename to runtime/ztests/op/yield-quiet.yaml index 692f43a2ec..066258216f 100644 --- a/runtime/sam/op/yield/ztests/quiet.yaml +++ b/runtime/ztests/op/yield-quiet.yaml @@ -1,5 +1,7 @@ zed: yield quiet(a) +vector: true + input: | {a:1} {b:1} diff --git a/type.go b/type.go index 0fa00a69c4..e22cc5eea6 100644 --- a/type.go +++ b/type.go @@ -469,7 +469,7 @@ func CompareTypes(a, b Type) int { } return 0 case ErrorKind: - ea, eb := a.(*TypeError), b.(*TypeError) + ea, eb := TypeUnder(a).(*TypeError), TypeUnder(b).(*TypeError) return CompareTypes(ea.Type, eb.Type) } return 0 diff --git a/vector/error.go b/vector/error.go index 1601b492b3..a5e5a77c34 100644 --- a/vector/error.go +++ b/vector/error.go @@ -42,9 +42,8 @@ func NewStringError(zctx *zed.Context, msg string, len uint32) *Error { } func NewMissing(zctx *zed.Context, len uint32) *Error { - missing := zctx.Missing() - vals := NewConst(missing, len, nil) - return &Error{Typ: missing.Type().(*zed.TypeError), Vals: vals} + vals := NewConst(zed.NewString("missing"), len, nil) + return &Error{Typ: zctx.LookupTypeError(zed.TypeString), Vals: vals} } func NewWrappedError(zctx *zed.Context, msg string, val Any) *Error {