Skip to content

Commit c9a8f47

Browse files
authored
Enhance tests and doc for eval isnull/isnotnull functions (#4724)
* Enhance tests and doc for eval isnull/isnotnull functions Signed-off-by: Kai Huang <[email protected]> * fix Signed-off-by: Kai Huang <[email protected]> --------- Signed-off-by: Kai Huang <[email protected]>
1 parent e06ebc5 commit c9a8f47

File tree

2 files changed

+131
-30
lines changed

2 files changed

+131
-30
lines changed

docs/user/ppl/functions/condition.rst

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@ ISNULL
1414
Description
1515
>>>>>>>>>>>
1616

17-
Usage: isnull(field) return true if field is null.
17+
Usage: isnull(field) returns TRUE if field is NULL, FALSE otherwise.
1818

19-
Argument type: all the supported data type.
19+
The `isnull()` function is commonly used:
20+
- In `eval` expressions to create conditional fields
21+
- With the `if()` function to provide default values
22+
- In `where` clauses to filter null records
23+
24+
Argument type: all the supported data types.
2025

2126
Return type: BOOLEAN
2227

@@ -33,22 +38,64 @@ Example::
3338
| True | null | Dale |
3439
+--------+----------+-----------+
3540

41+
Using with if() to label records::
42+
43+
os> source=accounts | eval status = if(isnull(employer), 'unemployed', 'employed') | fields firstname, employer, status
44+
fetched rows / total rows = 4/4
45+
+-----------+----------+------------+
46+
| firstname | employer | status |
47+
|-----------+----------+------------|
48+
| Amber | Pyrami | employed |
49+
| Hattie | Netagy | employed |
50+
| Nanette | Quility | employed |
51+
| Dale | null | unemployed |
52+
+-----------+----------+------------+
53+
54+
Filtering with where clause::
55+
56+
os> source=accounts | where isnull(employer) | fields account_number, firstname, employer
57+
fetched rows / total rows = 1/1
58+
+----------------+-----------+----------+
59+
| account_number | firstname | employer |
60+
|----------------+-----------+----------|
61+
| 18 | Dale | null |
62+
+----------------+-----------+----------+
63+
3664
ISNOTNULL
3765
---------
3866

3967
Description
4068
>>>>>>>>>>>
4169

42-
Usage: isnotnull(field) return true if field is not null.
70+
Usage: isnotnull(field) returns TRUE if field is NOT NULL, FALSE otherwise.
4371

44-
Argument type: all the supported data type.
72+
The `isnotnull()` function is commonly used:
73+
- In `eval` expressions to create boolean flags
74+
- In `where` clauses to filter out null values
75+
- With the `if()` function for conditional logic
76+
- To validate data presence
77+
78+
Argument type: all the supported data types.
4579

4680
Return type: BOOLEAN
4781

4882
Synonyms: `ISPRESENT`_
4983

5084
Example::
5185

86+
os> source=accounts | eval has_employer = isnotnull(employer) | fields firstname, employer, has_employer
87+
fetched rows / total rows = 4/4
88+
+-----------+----------+--------------+
89+
| firstname | employer | has_employer |
90+
|-----------+----------+--------------|
91+
| Amber | Pyrami | True |
92+
| Hattie | Netagy | True |
93+
| Nanette | Quility | True |
94+
| Dale | null | False |
95+
+-----------+----------+--------------+
96+
97+
Filtering with where clause::
98+
5299
os> source=accounts | where not isnotnull(employer) | fields account_number, employer
53100
fetched rows / total rows = 1/1
54101
+----------------+----------+
@@ -57,6 +104,19 @@ Example::
57104
| 18 | null |
58105
+----------------+----------+
59106

107+
Using with if() for validation messages::
108+
109+
os> source=accounts | eval validation = if(isnotnull(employer), 'valid', 'missing employer') | fields firstname, employer, validation
110+
fetched rows / total rows = 4/4
111+
+-----------+----------+------------------+
112+
| firstname | employer | validation |
113+
|-----------+----------+------------------|
114+
| Amber | Pyrami | valid |
115+
| Hattie | Netagy | valid |
116+
| Nanette | Quility | valid |
117+
| Dale | null | missing employer |
118+
+-----------+----------+------------------+
119+
60120
EXISTS
61121
------
62122

@@ -142,32 +202,6 @@ Example::
142202
| null | null | Dale |
143203
+---------+----------+-----------+
144204

145-
146-
ISNULL
147-
------
148-
149-
Description
150-
>>>>>>>>>>>
151-
152-
Usage: isnull(field1, field2) return null if two parameters are same, otherwise return field1.
153-
154-
Argument type: all the supported data type
155-
156-
Return type: any
157-
158-
Example::
159-
160-
os> source=accounts | eval result = isnull(employer) | fields result, employer, firstname
161-
fetched rows / total rows = 4/4
162-
+--------+----------+-----------+
163-
| result | employer | firstname |
164-
|--------+----------+-----------|
165-
| False | Pyrami | Amber |
166-
| False | Netagy | Hattie |
167-
| False | Quility | Nanette |
168-
| True | null | Dale |
169-
+--------+----------+-----------+
170-
171205
IF
172206
------
173207

integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalcitePPLConditionBuiltinFunctionIT.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,4 +335,71 @@ public void testEarliestWithEval() throws IOException {
335335

336336
verifyDataRows(actual, rows(false, true));
337337
}
338+
339+
@Test
340+
public void testEvalIsNullWithIf() throws IOException {
341+
JSONObject actual =
342+
executeQuery(
343+
String.format(
344+
"source=%s | eval n=if(isnull(name), 'yes', 'no') | fields name, n",
345+
TEST_INDEX_STATE_COUNTRY_WITH_NULL));
346+
347+
verifySchema(actual, schema("name", "string"), schema("n", "string"));
348+
349+
verifyDataRows(
350+
actual,
351+
rows("John", "no"),
352+
rows("Jane", "no"),
353+
rows(null, "yes"),
354+
rows("Jake", "no"),
355+
rows("Kevin", "no"),
356+
rows("Hello", "no"),
357+
rows(" ", "no"),
358+
rows("", "no"));
359+
}
360+
361+
@Test
362+
public void testEvalIsNotNullDirect() throws IOException {
363+
JSONObject actual =
364+
executeQuery(
365+
String.format(
366+
"source=%s | eval is_not_null_name=isnotnull(name) | fields name, is_not_null_name",
367+
TEST_INDEX_STATE_COUNTRY_WITH_NULL));
368+
369+
verifySchema(actual, schema("name", "string"), schema("is_not_null_name", "boolean"));
370+
371+
verifyDataRows(
372+
actual,
373+
rows("John", true),
374+
rows("Jane", true),
375+
rows(null, false),
376+
rows("Jake", true),
377+
rows("Kevin", true),
378+
rows("Hello", true),
379+
rows(" ", true),
380+
rows("", true));
381+
}
382+
383+
@Test
384+
public void testEvalIsNullInComplexExpression() throws IOException {
385+
JSONObject actual =
386+
executeQuery(
387+
String.format(
388+
"source=%s | eval safe_name=if(isnull(name), 'Unknown', name) | fields safe_name,"
389+
+ " age",
390+
TEST_INDEX_STATE_COUNTRY_WITH_NULL));
391+
392+
verifySchema(actual, schema("safe_name", "string"), schema("age", "int"));
393+
394+
verifyDataRows(
395+
actual,
396+
rows("John", 25),
397+
rows("Jane", 20),
398+
rows("Unknown", 10),
399+
rows("Jake", 70),
400+
rows("Kevin", null),
401+
rows("Hello", 30),
402+
rows(" ", 27),
403+
rows("", 57));
404+
}
338405
}

0 commit comments

Comments
 (0)