[ASTERIXDB-2871][COMP] Improve UDF recursion detection

- user model changes: no
- storage format changes: no
- interface changes: no

Details:
- Improve UDF recursion detection
- Rewrite UDF body expression only once
- Add testcases

Change-Id: I7886404bfa47d1d89674df1200f30ad6ad0e0fc6
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/10905
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index faee227..b93ab87 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -384,7 +384,7 @@
     }
 
     @Override
-    public FunctionDecl parseFunctionBody(FunctionSignature signature, List<String> paramNames)
+    public FunctionDecl parseFunctionBody(FunctionSignature signature, List<String> paramNames, boolean isStored)
       throws CompilationException {
         return parseImpl(new ParseFunction<FunctionDecl>() {
             @Override
@@ -399,7 +399,7 @@
                 Expression functionBodyExpr = SQLPPParser.this.FunctionBody();
                 removeCurrentScope();
                 defaultDataverse = dataverse;
-                return new FunctionDecl(signature, paramVars, functionBodyExpr);
+                return new FunctionDecl(signature, paramVars, functionBodyExpr, isStored);
             }
         });
     }
@@ -2701,7 +2701,7 @@
     for (Pair<VarIdentifier,TypeExpression> p: paramList) {
         params.add(p.getFirst());
     }
-    FunctionDecl stmt = new FunctionDecl(signature, params, funcBody);
+    FunctionDecl stmt = new FunctionDecl(signature, params, funcBody, false);
     removeCurrentScope();
     return addSourceLocation(stmt, startToken);
   }