=== modified file 'src/com/goldencode/p2j/jmx/FwdJMX.java'
--- old/src/com/goldencode/p2j/jmx/FwdJMX.java	2023-03-16 11:17:28 +0000
+++ new/src/com/goldencode/p2j/jmx/FwdJMX.java	2023-04-24 12:33:00 +0000
@@ -680,7 +680,9 @@
    implements OptionalQueryProfiler
    {
       /** Query profiler */
-      QueryProfiler;
+      QueryProfiler,
+      /** FQL profiler */
+      FQLProfiler;
 
       /** Profiler instance */
       private final SimpleQueryProfiler profiler = new SimpleQueryProfiler();
@@ -766,6 +768,118 @@
       }
       
       /**
+       * Update the number of meta db hits of a specified query
+       *
+       * @param   query
+       *          the query for which the update is done
+       * @param   value
+       *          the number of meta db hits
+       */
+      @Override
+      public void updateMetaDBHits(String query, long value)
+      {
+         profiler.updateMetaDBHits(query, value);
+      }
+      
+      /**
+       * Update the number of meta db misses of a specified query
+       *
+       * @param   query
+       *          the query for which the update is done
+       * @param   value
+       *          the number of meta db misses
+       */
+      @Override
+      public void updateMetaDBMisses(String query, long value)
+      {
+         profiler.updateMetaDBMisses(query, value);
+      }
+      
+      /**
+       * Update the number of temp db hits of a specified query
+       *
+       * @param   query
+       *          the query for which the update is done
+       * @param   value
+       *          the number of temp db hits
+       */
+      @Override
+      public void updateTempDBHits(String query, long value)
+      {
+         profiler.updateTempDBHits(query, value);
+      }
+      
+      /**
+       * Update the number of temp db misses of a specified query
+       *
+       * @param   query
+       *          the query for which the update is done
+       * @param   value
+       *          the number of temp db misses
+       */
+      @Override
+      public void updateTempDBMisses(String query, long value)
+      {
+         profiler.updateTempDBMisses(query, value);
+      }
+      
+      /**
+       * Update the number of dirty db hits of a specified query
+       *
+       * @param   query
+       *          the query for which the update is done
+       * @param   value
+       *          the number of dirty db hits
+       */
+      @Override
+      public void updateDirtyDBHits(String query, long value)
+      {
+         profiler.updateDirtyDBHits(query, value);
+      }
+      
+      /**
+       * Update the number of dirty db misses of a specified query
+       *
+       * @param   query
+       *          the query for which the update is done
+       * @param   value
+       *          the number of dirty db misses
+       */
+      @Override
+      public void updateDirtyDBMisses(String query, long value)
+      {
+         profiler.updateDirtyDBMisses(query, value);
+      }
+      
+      /**
+       * Update the number of persistent db hits of a specified query
+       *
+       * @param   query
+       *          the query for which the update is done
+       * @param   value
+       *          the number of persistent db hits
+       */
+      @Override
+      public void updatePersistentDBHits(String query, long value)
+      {
+         profiler.updatePersistentDBHits(query, value);
+      }
+      
+      /**
+       * Update the number of persistent db misses of a specified query
+       *
+       * @param   query
+       *          the query for which the update is done
+       * @param   value
+       *          the number of persistent db misses
+       */
+      @Override
+      public void updatePersistentDBMisses(String query, long value)
+      {
+         profiler.updatePersistentDBMisses(query, value);
+      }
+      
+      /**
        * Return the string representation of a profiled query
        * 
        * @param    ts

=== modified file 'src/com/goldencode/p2j/jmx/QueryProfiler.java'
--- old/src/com/goldencode/p2j/jmx/QueryProfiler.java	2022-08-29 08:33:20 +0000
+++ new/src/com/goldencode/p2j/jmx/QueryProfiler.java	2023-04-24 12:44:15 +0000
@@ -109,6 +109,86 @@
    public void updateHydrateTotalTime(String query, long value);
    
    /**
+    * Update the number of meta db hits of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of meta db hits
+    */
+   public void updateMetaDBHits(String query, long value);
+   
+   /**
+    * Update the number of meta db misses of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of meta db misses
+    */
+   public void updateMetaDBMisses(String query, long value);
+   
+   /**
+    * Update the number of temp db hits of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of temp db hits
+    */
+   public void updateTempDBHits(String query, long value);
+   
+   /**
+    * Update the number of temp db misses of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of temp db misses
+    */
+   public void updateTempDBMisses(String query, long value);
+   
+   /**
+    * Update the number of dirty db hits of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of dirty db hits
+    */
+   public void updateDirtyDBHits(String query, long value);
+   
+   /**
+    * Update the number of dirty db misses of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of dirty db misses
+    */
+   public void updateDirtyDBMisses(String query, long value);
+   
+   /**
+    * Update the number of persistent db hits of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of persistent db hits
+    */
+   public void updatePersistentDBHits(String query, long value);
+   
+   /**
+    * Update the number of persistent db misses of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of persistent db misses
+    */
+   public void updatePersistentDBMisses(String query, long value);
+   
+   /**
     * Return the string representation of the counter
     * 
     * @param  ts

=== modified file 'src/com/goldencode/p2j/jmx/QueryProfilerJMX.java'
--- old/src/com/goldencode/p2j/jmx/QueryProfilerJMX.java	2022-08-29 08:33:20 +0000
+++ new/src/com/goldencode/p2j/jmx/QueryProfilerJMX.java	2023-04-24 12:22:19 +0000
@@ -87,6 +87,18 @@
    
    /** Publisher for the total time spent in hydrate */
    protected final ObjLongConsumer<String> publishHydrateTotalTime;
+   
+   /** Publisher for the number of meta db hits */
+   protected final ObjLongConsumer<String> publishMetaDBHits;
+   
+   /** Publisher for the number of temp db hits */
+   protected final ObjLongConsumer<String> publishTempDBHits;
+   
+   /** Publisher for the number of dirty db hits */
+   protected final ObjLongConsumer<String> publishDirtyDBHits;
+   
+   /** Publisher for the number of persistent db hits */
+   protected final ObjLongConsumer<String> publishPersistentDBHits;
 
    /**
     * Create and register instance
@@ -101,7 +113,11 @@
       QueryProfilerJMX simple = new QueryProfilerJMX(profiler::updateRowsCount, 
                profiler::updateCacheHits, 
                profiler::updateCacheMisses,
-               profiler::updateHydrateTotalTime);
+               profiler::updateHydrateTotalTime,
+               profiler::updateMetaDBHits,
+               profiler::updateTempDBHits,
+               profiler::updateDirtyDBHits,
+               profiler::updatePersistentDBHits);
        simple.setEnabler(simple::setEnabled); //prevent GC
        profiler.register(simple.getEnabler());
        return simple;
@@ -122,12 +138,20 @@
    protected QueryProfilerJMX(ObjLongConsumer<String> publishRowsCount, 
                               ObjLongConsumer<String> publishCacheHits, 
                               ObjLongConsumer<String> publishCacheMisses, 
-                              ObjLongConsumer<String> publishHydrateTotalTime)
+                              ObjLongConsumer<String> publishHydrateTotalTime,
+                              ObjLongConsumer<String> publishMetaDBHits,
+                              ObjLongConsumer<String> publishTempDBHits,
+                              ObjLongConsumer<String> publishDirtyDBHits,
+                              ObjLongConsumer<String> publishPersistentDBHits)
    {
       this.publishRowsCount = publishRowsCount;
       this.publishCacheHits = publishCacheHits;
       this.publishCacheMisses = publishCacheMisses;
       this.publishHydrateTotalTime = publishHydrateTotalTime;
+      this.publishMetaDBHits = publishMetaDBHits;
+      this.publishTempDBHits = publishTempDBHits;
+      this.publishDirtyDBHits = publishDirtyDBHits;
+      this.publishPersistentDBHits = publishPersistentDBHits;
    }
    
    /**
@@ -273,4 +297,68 @@
          }
       }
    }
+   
+   /**
+    * Update the number of meta db hits of a specified query
+    *
+    * @param query
+    *        the query for which the update is done
+    * @param value
+    *        the number of meta db hits
+    */
+   public void updateMetaDBHits(String query, long value)
+   {
+      if (enabled)
+      {
+         publishMetaDBHits.accept(query, value);
+      }
+   }
+   
+   /**
+    * Update the number of temp db hits of a specified query
+    *
+    * @param query
+    *        the query for which the update is done
+    * @param value
+    *        the number of temp db hits
+    */
+   public void updateTempDBHits(String query, long value)
+   {
+      if (enabled)
+      {
+         publishTempDBHits.accept(query, value);
+      }
+   }
+   
+   /**
+    * Update the number of dirty db hits of a specified query
+    *
+    * @param query
+    *        the query for which the update is done
+    * @param value
+    *        the number of dirty db hits
+    */
+   public void updateDirtyDBHits(String query, long value)
+   {
+      if (enabled)
+      {
+         publishDirtyDBHits.accept(query, value);
+      }
+   }
+   
+   /**
+    * Update the number of persistent db hits of a specified query
+    *
+    * @param query
+    *        the query for which the update is done
+    * @param value
+    *        the number of persistent db hits
+    */
+   public void updatePersistentDBHits(String query, long value)
+   {
+      if (enabled)
+      {
+         publishPersistentDBHits.accept(query, value);
+      }
+   }
 }
\ No newline at end of file

=== modified file 'src/com/goldencode/p2j/jmx/SimpleQueryProfiler.java'
--- old/src/com/goldencode/p2j/jmx/SimpleQueryProfiler.java	2022-08-29 08:33:20 +0000
+++ new/src/com/goldencode/p2j/jmx/SimpleQueryProfiler.java	2023-04-24 12:45:00 +0000
@@ -93,7 +93,23 @@
       /** Represent the number of cache misses done by each query */
       CACHE_MISSES,
       /** Represent the number nano-seconds spent to hydrate */
-      HYDRATE_TOTAL_TIME
+      HYDRATE_TOTAL_TIME,
+      /** Represent the number of meta db hits done by each query */
+      META_DB_HITS,
+      /** Represent the number of meta db misses done by each query */
+      META_DB_MISSES,
+      /** Represent the number of temp db hits done by each query */
+      TEMP_DB_HITS,
+      /** Represent the number of temp db misses done by each query */
+      TEMP_DB_MISSES,
+      /** Represent the number of dirty db hits done by each query */
+      DIRTY_DB_HITS,
+      /** Represent the number of dirty db misses done by each query */
+      DIRTY_DB_MISSES,
+      /** Represent the number of persistent db hits done by each query */
+      PERSISTENT_DB_HITS,
+      /** Represent the number of persistent db misses done by each query */
+      PERSISTENT_DB_MISSES
    }
    
    /**
@@ -156,6 +172,160 @@
              .computeIfAbsent(QueryInfo.HYDRATE_TOTAL_TIME.toString(), k -> new AtomicLong(0))
              .addAndGet(value);
    }
+   
+   /**
+    * Update the number of meta db hits of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of meta db hits
+    */
+   public void updateMetaDBHits(String query, long value)
+   {
+      if (checkExistentQuery(query))
+      {
+         queries.computeIfAbsent(query, k -> new ConcurrentHashMap<>())
+                .computeIfAbsent(QueryInfo.META_DB_HITS.toString(), k -> new AtomicLong(0))
+                .addAndGet(value);
+         return;
+      }
+      updateMetaDBMisses(query, value);
+   }
+   
+   /**
+    * Update the number of meta db misses of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of meta db misses
+    */
+   public void updateMetaDBMisses(String query, long value)
+   {
+      queries.computeIfAbsent(query, k -> new ConcurrentHashMap<>())
+             .computeIfAbsent(QueryInfo.META_DB_MISSES.toString(), k -> new AtomicLong(0))
+             .addAndGet(value);
+   }
+   
+   /**
+    * Update the number of temp db hits of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of temp db hits
+    */
+   public void updateTempDBHits(String query, long value)
+   {
+      if (checkExistentQuery(query))
+      {
+         queries.computeIfAbsent(query, k -> new ConcurrentHashMap<>())
+                .computeIfAbsent(QueryInfo.TEMP_DB_HITS.toString(), k -> new AtomicLong(0))
+                .addAndGet(value);
+         return;
+      }
+      updateTempDBMisses(query, value);
+   }
+   
+   /**
+    * Update the number of temp db misses of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of temp db misses
+    */
+   public void updateTempDBMisses(String query, long value)
+   {
+      queries.computeIfAbsent(query, k -> new ConcurrentHashMap<>())
+             .computeIfAbsent(QueryInfo.TEMP_DB_MISSES.toString(), k -> new AtomicLong(0))
+             .addAndGet(value);
+   }
+   
+   /**
+    * Update the number of dirty db hits of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of dirty db hits
+    */
+   public void updateDirtyDBHits(String query, long value)
+   {
+      if (checkExistentQuery(query))
+      {
+         queries.computeIfAbsent(query, k -> new ConcurrentHashMap<>())
+                .computeIfAbsent(QueryInfo.DIRTY_DB_HITS.toString(), k -> new AtomicLong(0))
+                .addAndGet(value);
+         return;
+      }
+      updateDirtyDBMisses(query, value);
+   }
+   
+   /**
+    * Update the number of dirty db misses of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of dirty db misses
+    */
+   public void updateDirtyDBMisses(String query, long value)
+   {
+      queries.computeIfAbsent(query, k -> new ConcurrentHashMap<>())
+             .computeIfAbsent(QueryInfo.DIRTY_DB_MISSES.toString(), k -> new AtomicLong(0))
+             .addAndGet(value);
+   }
+   
+   /**
+    * Update the number of persistent db hits of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of persistent db hits
+    */
+   public void updatePersistentDBHits(String query, long value)
+   {
+      if (checkExistentQuery(query))
+      {
+         queries.computeIfAbsent(query, k -> new ConcurrentHashMap<>())
+                .computeIfAbsent(QueryInfo.PERSISTENT_DB_HITS.toString(), k -> new AtomicLong(0))
+                .addAndGet(value);
+         return;
+      }
+      updatePersistentDBMisses(query, value);
+   }
+   
+   /**
+    * Update the number of persistent db misses of a specified query
+    *
+    * @param   query
+    *          the query for which the update is done
+    * @param   value
+    *          the number of persistent db misses
+    */
+   public void updatePersistentDBMisses(String query, long value)
+   {
+      queries.computeIfAbsent(query, k -> new ConcurrentHashMap<>())
+             .computeIfAbsent(QueryInfo.PERSISTENT_DB_MISSES.toString(), k -> new AtomicLong(0))
+             .addAndGet(value);
+   }
+   
+   /**
+    * Check if a query was already profiled.
+    * 
+    * @param   query
+    *          the query that is checked
+    *          
+    * @return  {@code true} if the query was already profiled,
+    *          {@code false} otherwise.
+    */
+   public boolean checkExistentQuery(String query)
+   {
+      return queries.containsKey(query);
+   }
 
    /**
     * Retrieve the values accumulated for each query.

=== modified file 'src/com/goldencode/p2j/persist/FQLPreprocessor.java'
--- old/src/com/goldencode/p2j/persist/FQLPreprocessor.java	2023-04-13 08:52:10 +0000
+++ new/src/com/goldencode/p2j/persist/FQLPreprocessor.java	2023-04-24 12:45:36 +0000
@@ -360,6 +360,7 @@
 import antlr.collections.*;
 import com.goldencode.ast.*;
 import com.goldencode.util.*;
+import com.goldencode.p2j.jmx.*;
 import com.goldencode.p2j.persist.dialect.*;
 import com.goldencode.p2j.persist.hql.*;
 import com.goldencode.p2j.persist.pl.*;
@@ -667,6 +668,10 @@
    /** Flag indicating that the query depends on mutable SESSION attribute(s). */
    private boolean dependsOnSessionAttribute = false;
    
+   /** Profiler done for FQLs */
+   private static final QueryProfilerJMX SIMPLE_FQL_PROFILER =
+      QueryProfilerJMX.getInstance(FwdJMX.QueryProfiler.FQLProfiler);
+   
    /**
     * Factory method which accepts an unprocessed where clause, the database
     * instance and the database dialect associated with the enclosing query,
@@ -1610,6 +1615,30 @@
          // Emit the preprocessed FQL expression text.
          this.fql = emit(root, false);
          
+         boolean found = false;
+         if (database.isMeta())
+         {
+            SIMPLE_FQL_PROFILER.updateMetaDBHits(this.fql.toString(), 1);
+            found = true;
+         }
+         
+         if (database.isDirty())
+         {
+            SIMPLE_FQL_PROFILER.updateDirtyDBHits(this.fql.toString(), 1);
+            found = true;
+         }
+         
+         if (database.equals(DatabaseManager.TEMP_TABLE_DB))
+         {
+            SIMPLE_FQL_PROFILER.updateTempDBHits(this.fql.toString(), 1);
+            found = true;
+         }
+         
+         if (!found)
+         {
+            SIMPLE_FQL_PROFILER.updatePersistentDBHits(this.fql.toString(), 1);
+         }
+         
          if (LOG.isLoggable(Level.FINEST))
          {
             String sep = System.getProperty("line.separator");

