diff --git a/src/visitor/FoldConstantExprVisitor.cpp b/src/visitor/FoldConstantExprVisitor.cpp
index 6d3e036ccb673a67df17442b5c19e9bed033b234..7fafff0498f383742b96c73479e181abd21084c8 100644
--- a/src/visitor/FoldConstantExprVisitor.cpp
+++ b/src/visitor/FoldConstantExprVisitor.cpp
@@ -4,6 +4,8 @@
  * attached with Common Clause Condition 1.0, found in the LICENSES directory.
  */
 
+#include "common/function/FunctionManager.h"
+
 #include "visitor/FoldConstantExprVisitor.h"
 
 #include "context/QueryExpressionContext.h"
@@ -75,6 +77,14 @@ void FoldConstantExprVisitor::visit(FunctionCallExpression *expr) {
             }
         }
     }
+    auto result = FunctionManager::getIsPure(*expr->name(), expr->args()->args().size());
+    if (!result.ok()) {
+        canBeFolded = false;
+    }
+    if (!result.value()) {
+        // stateful so can't fold
+        canBeFolded = false;
+    }
     canBeFolded_ = canBeFolded;
 }
 
diff --git a/src/visitor/test/FoldConstantExprVisitorTest.cpp b/src/visitor/test/FoldConstantExprVisitorTest.cpp
index e59badf642024fc5989b8dc70aff26a449ad6d81..f35131dc5974a3ae847fd36b19648dd94134e537 100644
--- a/src/visitor/test/FoldConstantExprVisitorTest.cpp
+++ b/src/visitor/test/FoldConstantExprVisitorTest.cpp
@@ -215,6 +215,29 @@ TEST_F(FoldConstantExprVisitorTest, TestMapExpr) {
     ASSERT(visitor.canBeFolded());
 }
 
+TEST_F(FoldConstantExprVisitorTest, TestFoldFunction) {
+    // pure function
+    // abs(-1) + 1 => 1 + 1
+    {
+        auto expr = pool.add(addExpr(fnExpr("abs", {constantExpr(-1)}), constantExpr(1)));
+        auto expected = pool.add(addExpr(constantExpr(1), constantExpr(1)));
+        FoldConstantExprVisitor visitor;
+        expr->accept(&visitor);
+        ASSERT_TRUE(visitor.canBeFolded());
+        ASSERT_EQ(*expr, *expected) << expr->toString() << " vs. " << expected->toString();
+    }
+    // not pure function
+    // rand32(4) + 1 => rand32(4) + 1
+    {
+        auto expr = pool.add(addExpr(fnExpr("rand32", {constantExpr(4)}), constantExpr(1)));
+        auto expected = pool.add(addExpr(fnExpr("rand32", {constantExpr(4)}), constantExpr(1)));
+        FoldConstantExprVisitor visitor;
+        expr->accept(&visitor);
+        ASSERT_FALSE(visitor.canBeFolded());
+        ASSERT_EQ(*expr, *expected) << expr->toString() << " vs. " << expected->toString();
+    }
+}
+
 TEST_F(FoldConstantExprVisitorTest, TestFoldFailed) {
     // function call
     {