Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions docs/user/ppl/functions/condition.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ PPL conditional functions enable global filtering of query results based on spec

Returns `TRUE` if the field is `NULL`, `FALSE` otherwise.

The `field IS NULL` predicate syntax is also supported as a synonym.

The `isnull()` function is commonly used:
- In `eval` expressions to create conditional fields.
- With the `if()` function to provide default values.
Expand Down Expand Up @@ -69,6 +71,14 @@ source=accounts
| where isnull(employer)
| fields account_number, firstname, employer
```

The `IS NULL` predicate syntax can be used as an equivalent alternative:

```ppl
source=accounts
| where employer IS NULL
| fields account_number, firstname, employer
```

The query returns the following results:

Expand All @@ -87,6 +97,8 @@ fetched rows / total rows = 1/1

Returns `TRUE` if the field is NOT `NULL`, `FALSE` otherwise.

The `field IS NOT NULL` predicate syntax is also supported as a synonym.

The `isnotnull()` function is commonly used:
- In `eval` expressions to create Boolean flags.
- In `where` clauses to filter out null values.
Expand Down Expand Up @@ -141,6 +153,27 @@ fetched rows / total rows = 1/1
| 18 | null |
+----------------+----------+
```

The `IS NOT NULL` predicate syntax is equivalent to `isnotnull()`:

```ppl
source=accounts
| where employer IS NOT NULL
| fields account_number, employer
```

The query returns the following results:

```text
fetched rows / total rows = 3/3
+----------------+----------+
| account_number | employer |
|----------------+----------|
| 1 | Pyrami |
| 6 | Netagy |
| 13 | Quility |
+----------------+----------+
```

The following example demonstrates using `isnotnull` with the `if` function to create validation messages:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,27 @@ public void testIsNotNullFunction() throws IOException {
verifyDataRows(result, rows("Amber JOHnny"));
}

@Test
public void testIsNullPredicate() throws IOException {
JSONObject result =
executeQuery(
String.format(
"source=%s | where age IS NULL | fields firstname",
TEST_INDEX_BANK_WITH_NULL_VALUES));
verifyDataRows(result, rows("Virginia"));
}

@Test
public void testIsNotNullPredicate() throws IOException {
JSONObject result =
executeQuery(
String.format(
"source=%s | where age IS NOT NULL and like(firstname, 'Ambe_%%') | fields"
+ " firstname",
TEST_INDEX_BANK_WITH_NULL_VALUES));
verifyDataRows(result, rows("Amber JOHnny"));
}

@Test
public void testWhereWithMetadataFields() throws IOException {
JSONObject result =
Expand Down
2 changes: 2 additions & 0 deletions ppl/src/main/antlr/OpenSearchPPLLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ PATH: 'PATH';
CASE: 'CASE';
ELSE: 'ELSE';
IN: 'IN';
IS: 'IS';
EXISTS: 'EXISTS';
NULL: 'NULL';

// Geo IP eval function
GEOIP: 'GEOIP';
Expand Down
7 changes: 7 additions & 0 deletions ppl/src/main/antlr/OpenSearchPPLParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,11 @@ expression
| left = expression comparisonOperator right = expression # compareExpr
| expression NOT? IN LT_PRTHS valueList RT_PRTHS # inExpr
| expression NOT? BETWEEN expression AND expression # between
| expression IS nullNotnull # isNullPredicate
;

nullNotnull
: NOT? NULL
;


Expand Down Expand Up @@ -1594,6 +1599,8 @@ wildcard
keywordsCanBeId
: searchableKeyWord
| IN
| IS
| NULL
;

searchableKeyWord
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,15 @@ public UnresolvedExpression visitInExpr(InExprContext ctx) {
return ctx.NOT() != null ? new Not(expr) : expr;
}

@Override
public UnresolvedExpression visitIsNullPredicate(OpenSearchPPLParser.IsNullPredicateContext ctx) {
return new Function(
ctx.nullNotnull().NOT() == null
? IS_NULL.getName().getFunctionName()
: IS_NOT_NULL.getName().getFunctionName(),
Arrays.asList(visit(ctx.expression())));
}

/** Value Expression. */
@Override
public UnresolvedExpression visitBinaryArithmetic(BinaryArithmeticContext ctx) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,24 @@ public void testBooleanIsNotNullFunction() {
filter(relation("t"), function("is not null", field("a"))));
}

@Test
public void testIsNullPredicate() {
assertEqual(
"source=t | where a is null", filter(relation("t"), function("is null", field("a"))));
assertEqual(
"source=t | where a IS NULL", filter(relation("t"), function("is null", field("a"))));
}

@Test
public void testIsNotNullPredicate() {
assertEqual(
"source=t | where a is not null",
filter(relation("t"), function("is not null", field("a"))));
assertEqual(
"source=t | where a IS NOT NULL",
filter(relation("t"), function("is not null", field("a"))));
}

/** Todo. search operator should not include functionCall, need to change antlr. */
@Ignore("search operator should not include functionCall, need to change antlr")
public void testEvalExpr() {
Expand Down
Loading