diff --git a/src/parser/parser.yy b/src/parser/parser.yy
index 67b557067e6f8a8d2b5ff22de9cc06aca0d09e62..b42548d16d5800a576d7cff8c48a62f9d4395bcc 100644
--- a/src/parser/parser.yy
+++ b/src/parser/parser.yy
@@ -356,7 +356,6 @@ static constexpr size_t MAX_ABS_INTEGER = 9223372036854775808ULL;
 
 %type <sentence> grant_sentence revoke_sentence
 %type <sentence> set_config_sentence get_config_sentence balance_sentence
-%type <sentence> process_control_sentence return_sentence
 %type <sentence> sentence
 %type <seq_sentences> seq_sentences
 %type <explain_sentence> explain_sentence
@@ -371,7 +370,7 @@ static constexpr size_t MAX_ABS_INTEGER = 9223372036854775808ULL;
 %left KW_OR KW_XOR
 %left KW_AND
 %right KW_NOT
-%left EQ NE LT LE GT GE REG KW_IN KW_NOT_IN KW_CONTAINS KW_NOT_CONTAINS KW_STARTS_WITH KW_ENDS_WITH KW_NOT_STARTS_WITH KW_NOT_ENDS_WITH
+%left EQ NE LT LE GT GE REG KW_IN KW_NOT_IN KW_CONTAINS KW_NOT_CONTAINS KW_STARTS_WITH KW_ENDS_WITH KW_NOT_STARTS_WITH KW_NOT_ENDS_WITH KW_IS_NULL KW_IS_NOT_NULL
 %left PLUS MINUS
 %left STAR DIV MOD
 %right NOT
@@ -613,6 +612,12 @@ expression
     | expression KW_NOT_ENDS_WITH expression {
         $$ = new RelationalExpression(Expression::Kind::kNotEndsWith, $1, $3);
     }
+    | expression KW_IS_NULL {
+        $$ = new UnaryExpression(Expression::Kind::kIsNull, $1);
+    }
+    | expression KW_IS_NOT_NULL {
+        $$ = new UnaryExpression(Expression::Kind::kIsNotNull, $1);
+    }
     | expression EQ expression {
         $$ = new RelationalExpression(Expression::Kind::kRelEQ, $1, $3);
     }
@@ -3152,22 +3157,12 @@ maintain_sentence
     | sign_out_text_search_service_sentence { $$ = $1; }
     ;
 
-return_sentence
-    : KW_RETURN VARIABLE KW_IF VARIABLE KW_IS KW_NOT KW_NULL {
-        $$ = new ReturnSentence($2, $4);
-    }
-
-process_control_sentence
-    : return_sentence { $$ = $1; }
-    ;
-
 sentence
     : maintain_sentence { $$ = $1; }
     | use_sentence { $$ = $1; }
     | set_sentence { $$ = $1; }
     | assignment_sentence { $$ = $1; }
     | mutate_sentence { $$ = $1; }
-    | process_control_sentence { $$ = $1; }
     ;
 
 seq_sentences
diff --git a/src/parser/scanner.lex b/src/parser/scanner.lex
index 8ac8b03bac6afed3852004e960fbb63cf638c2f5..695a5d23fdbf13a48edfd7fe8fbf4cd3128f2a74 100644
--- a/src/parser/scanner.lex
+++ b/src/parser/scanner.lex
@@ -30,6 +30,8 @@ STARTS_WITH                 (STARTS{blanks}WITH)
 NOT_STARTS_WITH             (NOT{blanks}STARTS{blanks}WITH)
 ENDS_WITH                   (ENDS{blanks}WITH)
 NOT_ENDS_WITH               (NOT{blanks}ENDS{blanks}WITH)
+IS_NULL                     (IS{blanks}NULL)
+IS_NOT_NULL                 (IS{blanks}NOT{blanks}NULL)
 
 LABEL                       ([a-zA-Z][_a-zA-Z0-9]*)
 DEC                         ([0-9])
@@ -221,6 +223,8 @@ IP_OCTET                    ([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])
 "ENDS"                      { return TokenType::KW_ENDS;}
 {ENDS_WITH}                 { return TokenType::KW_ENDS_WITH;}
 {NOT_ENDS_WITH}             { return TokenType::KW_NOT_ENDS_WITH;}
+{IS_NULL}                   { return TokenType::KW_IS_NULL;}
+{IS_NOT_NULL}               { return TokenType::KW_IS_NOT_NULL;}
 "UNWIND"                    { return TokenType::KW_UNWIND;}
 "SKIP"                      { return TokenType::KW_SKIP;}
 "OPTIONAL"                  { return TokenType::KW_OPTIONAL;}
diff --git a/src/parser/test/ParserTest.cpp b/src/parser/test/ParserTest.cpp
index a0495c6230d55abfc2cb94acd7c3f95afd7ef46d..400c62898616eb2f51d0d00ac61b2fc6cac0cdbc 100644
--- a/src/parser/test/ParserTest.cpp
+++ b/src/parser/test/ParserTest.cpp
@@ -1910,14 +1910,6 @@ TEST(Parser, GroupBy) {
     }
 }
 
-TEST(Parser, Return) {
-    {
-        std::string query = "RETURN $A IF $A IS NOT NULL";
-        auto result = parse(query);
-        ASSERT_TRUE(result.ok()) << result.status();
-    }
-}
-
 TEST(Parser, ErrorMsg) {
     {
         std::string query = "CREATE SPACE " + std::string(4097, 'A');
diff --git a/src/visitor/DeduceTypeVisitor.cpp b/src/visitor/DeduceTypeVisitor.cpp
index 1acf16b09d2a613a79fd26b23fad73433c953dc2..dc8ee02bd3637cc56152cd113cd6ed765b71df98 100644
--- a/src/visitor/DeduceTypeVisitor.cpp
+++ b/src/visitor/DeduceTypeVisitor.cpp
@@ -129,6 +129,14 @@ void DeduceTypeVisitor::visit(UnaryExpression *expr) {
             DETECT_UNARYEXPR_TYPE(!);
             break;
         }
+        case Expression::Kind::kIsNull: {
+            type_ = Value::Type::BOOL;
+            break;
+        }
+        case Expression::Kind::kIsNotNull: {
+            type_ = Value::Type::BOOL;
+            break;
+        }
         case Expression::Kind::kUnaryIncr: {
             auto detectVal = kConstantValues.at(type_) + 1;
             if (detectVal.isBadNull()) {
diff --git a/src/visitor/ExtractPropExprVisitor.cpp b/src/visitor/ExtractPropExprVisitor.cpp
index 70d09eb624b83fd4d74705f567ef98085551c54a..277903dcb39c95314d123436ea72fe64d510ef40 100644
--- a/src/visitor/ExtractPropExprVisitor.cpp
+++ b/src/visitor/ExtractPropExprVisitor.cpp
@@ -65,7 +65,9 @@ void ExtractPropExprVisitor::visit(UnaryExpression* expr) {
     switch (expr->kind()) {
         case Expression::Kind::kUnaryPlus:
         case Expression::Kind::kUnaryNegate:
-        case Expression::Kind::kUnaryNot: {
+        case Expression::Kind::kUnaryNot:
+        case Expression::Kind::kIsNull:
+        case Expression::Kind::kIsNotNull: {
             expr->operand()->accept(this);
             break;
         }
diff --git a/src/visitor/RewriteInputPropVisitor.cpp b/src/visitor/RewriteInputPropVisitor.cpp
index 73c93dcd9b6f8f71fff1723e038e5afdde2ab1e6..c41073cb15a0c44e2425474b636cc635db7e34f6 100644
--- a/src/visitor/RewriteInputPropVisitor.cpp
+++ b/src/visitor/RewriteInputPropVisitor.cpp
@@ -79,7 +79,9 @@ void RewriteInputPropVisitor::visit(UnaryExpression* expr) {
     switch (expr->kind()) {
         case Expression::Kind::kUnaryPlus:
         case Expression::Kind::kUnaryNegate:
-        case Expression::Kind::kUnaryNot: {
+        case Expression::Kind::kUnaryNot:
+        case Expression::Kind::kIsNull:
+        case Expression::Kind::kIsNotNull: {
             visitUnaryExpr(expr);
             break;
         }
diff --git a/tests/tck/features/expression/UnaryExpr.feature b/tests/tck/features/expression/UnaryExpr.feature
new file mode 100644
index 0000000000000000000000000000000000000000..021e157b7b3c0fe33dcbd2ae6a085ecf2dd2b560
--- /dev/null
+++ b/tests/tck/features/expression/UnaryExpr.feature
@@ -0,0 +1,78 @@
+# Copyright (c) 2020 vesoft inc. All rights reserved.
+#
+# This source code is licensed under Apache 2.0 License,
+# attached with Common Clause Condition 1.0, found in the LICENSES directory.
+Feature: UnaryExpression
+
+  Background:
+    Given a graph with space named "nba"
+
+  Scenario: UnaryExpression basic
+    When executing query:
+      """
+      YIELD [1 IS NULL, 1.2 IS NULL, true IS NULL, [1, 2] IS NULL, null IS NULL] AS isNull
+      """
+    Then the result should be, in order:
+      | isNull                             |
+      | [false, false, false, false, true] |
+    When executing query:
+      """
+      YIELD [1 IS NOT NULL, 1.2 IS NOT NULL, true IS NOT NULL, [1, 2] IS NOT NULL, null IS NOT NULL] AS isNotNull
+      """
+    Then the result should be, in order:
+      | isNotNull                       |
+      | [true, true, true, true, false] |
+    When executing query:
+      """
+      RETURN [1 IS NULL, 1.2 IS NULL, true IS NULL, [1, 2] IS NULL, null IS NULL] AS isNull
+      """
+    Then the result should be, in order:
+      | isNull                             |
+      | [false, false, false, false, true] |
+    When executing query:
+      """
+      RETURN [1 IS NOT NULL, 1.2 IS NOT NULL, true IS NOT NULL, [1, 2] IS NOT NULL, null IS NOT NULL] AS isNotNull
+      """
+    Then the result should be, in order:
+      | isNotNull                       |
+      | [true, true, true, true, false] |
+
+  Scenario: UnaryExpression in match clause
+    When executing query:
+      """
+      MATCH (v:player)
+      WHERE v.name IS NULL AND v.age < 0
+      RETURN v
+      """
+    Then the result should be, in any order, with relax comparison:
+      | v                                  |
+      | ("Null1":player{age:-1,name:NULL}) |
+      | ("Null2":player{age:-2,name:NULL}) |
+      | ("Null3":player{age:-3,name:NULL}) |
+      | ("Null4":player{age:-4,name:NULL}) |
+    When executing query:
+      """
+      MATCH (v:player)
+      WHERE v.name IS NOT NULL AND v.age > 34
+      RETURN v
+      """
+    Then the result should be, in any order, with relax comparison:
+      | v                                                                                                           |
+      | ("Tim Duncan" :bachelor{name: "Tim Duncan", speciality: "psychology"} :player{age: 42, name: "Tim Duncan"}) |
+      | ("Tony Parker" :player{age: 36, name: "Tony Parker"})                                                       |
+      | ("Steve Nash" :player{age: 45, name: "Steve Nash"})                                                         |
+      | ("Shaquile O'Neal" :player{age: 47, name: "Shaquile O'Neal"})                                               |
+      | ("Ray Allen" :player{age: 43, name: "Ray Allen"})                                                           |
+      | ("Boris Diaw" :player{age: 36, name: "Boris Diaw"})                                                         |
+      | ("Paul Gasol" :player{age: 38, name: "Paul Gasol"})                                                         |
+      | ("Amar'e Stoudemire" :player{age: 36, name: "Amar'e Stoudemire"})                                           |
+      | ("Tracy McGrady" :player{age: 39, name: "Tracy McGrady"})                                                   |
+      | ("Dwyane Wade" :player{age: 37, name: "Dwyane Wade"})                                                       |
+      | ("Manu Ginobili" :player{age: 41, name: "Manu Ginobili"})                                                   |
+      | ("Grant Hill" :player{age: 46, name: "Grant Hill"})                                                         |
+      | ("David West" :player{age: 38, name: "David West"})                                                         |
+      | ("Dirk Nowitzki" :player{age: 40, name: "Dirk Nowitzki"})                                                   |
+      | ("Kobe Bryant" :player{age: 40, name: "Kobe Bryant"})                                                       |
+      | ("Jason Kidd" :player{age: 45, name: "Jason Kidd"})                                                         |
+      | ("Vince Carter" :player{age: 42, name: "Vince Carter"})                                                     |
+      | ("Yao Ming" :player{age: 38, name: "Yao Ming"})                                                             |