diff --git a/internal/pkg/bifs/types.go b/internal/pkg/bifs/types.go index 54fe8d3a0..59cb9c178 100644 --- a/internal/pkg/bifs/types.go +++ b/internal/pkg/bifs/types.go @@ -194,10 +194,10 @@ func BIF_is_notarray(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromBool(!input1.IsArray()) } func BIF_is_notnull(input1 *mlrval.Mlrval) *mlrval.Mlrval { - return mlrval.FromBool(!input1.IsAbsent() && !input1.IsVoid()) + return mlrval.FromBool(!input1.IsAbsent() && !input1.IsVoid() && !input1.IsNull()) } func BIF_is_null(input1 *mlrval.Mlrval) *mlrval.Mlrval { - return mlrval.FromBool(input1.IsAbsent() || input1.IsVoid()) + return mlrval.FromBool(input1.IsAbsent() || input1.IsVoid() || input1.IsNull()) } func BIF_is_numeric(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromBool(input1.IsInt() || input1.IsFloat()) diff --git a/internal/pkg/dsl/cst/builtin_function_manager.go b/internal/pkg/dsl/cst/builtin_function_manager.go index ce8849a8e..2b37c0286 100644 --- a/internal/pkg/dsl/cst/builtin_function_manager.go +++ b/internal/pkg/dsl/cst/builtin_function_manager.go @@ -1203,14 +1203,14 @@ strftime_local.`, { name: "is_not_null", class: FUNC_CLASS_TYPING, - help: "False if argument is null (empty or absent), true otherwise.", + help: "False if argument is null (empty, absent, or JSON null), true otherwise.", unaryFunc: bifs.BIF_is_notnull, }, { name: "is_null", class: FUNC_CLASS_TYPING, - help: "True if argument is null (empty or absent), false otherwise.", + help: "True if argument is null (empty, absent, or JSON null), false otherwise.", unaryFunc: bifs.BIF_is_null, }, diff --git a/test/cases/dsl-is-predicates/0098j/cmd b/test/cases/dsl-is-predicates/0098j/cmd new file mode 100644 index 000000000..7ecc8862a --- /dev/null +++ b/test/cases/dsl-is-predicates/0098j/cmd @@ -0,0 +1 @@ +mlr --json put -f ${CASEDIR}/mlr test/input/nullvals.json diff --git a/test/cases/dsl-is-predicates/0098j/experr b/test/cases/dsl-is-predicates/0098j/experr new file mode 100644 index 000000000..e69de29bb diff --git a/test/cases/dsl-is-predicates/0098j/expout b/test/cases/dsl-is-predicates/0098j/expout new file mode 100644 index 000000000..d15d048bf --- /dev/null +++ b/test/cases/dsl-is-predicates/0098j/expout @@ -0,0 +1,43 @@ +[ +{ + "a": "r", + "x": 1, + "y": 2, + "z": "", + "f": true +}, +{ + "a": "s", + "x": 3, + "y": 4, + "z": "", + "f": true +}, +{ + "a": "t", + "x": 5, + "y": "", + "z": "", + "f": true +}, +{ + "a": "u", + "x": "", + "y": 6, + "f": true +}, +{ + "a": "v", + "x": "", + "y": "", + "z": "null", + "f": false +}, +{ + "a": "v", + "x": "", + "y": "", + "z": null, + "f": true +} +] diff --git a/test/cases/dsl-is-predicates/0098j/mlr b/test/cases/dsl-is-predicates/0098j/mlr new file mode 100644 index 000000000..64c704004 --- /dev/null +++ b/test/cases/dsl-is-predicates/0098j/mlr @@ -0,0 +1 @@ +$f=is_null($z) diff --git a/test/input/nullvals.json b/test/input/nullvals.json new file mode 100644 index 000000000..1682929f3 --- /dev/null +++ b/test/input/nullvals.json @@ -0,0 +1,37 @@ +[ +{ + "a": "r", + "x": 1, + "y": 2, + "z": "" +}, +{ + "a": "s", + "x": 3, + "y": 4, + "z": "" +}, +{ + "a": "t", + "x": 5, + "y": "", + "z": "" +}, +{ + "a": "u", + "x": "", + "y": 6 +}, +{ + "a": "v", + "x": "", + "y": "", + "z": "null" +}, +{ + "a": "v", + "x": "", + "y": "", + "z": null +} +]