=== modified file 'src/com/goldencode/p2j/persist/AbstractQuery.java'
--- old/src/com/goldencode/p2j/persist/AbstractQuery.java	2023-04-05 18:08:41 +0000
+++ new/src/com/goldencode/p2j/persist/AbstractQuery.java	2023-04-20 11:02:33 +0000
@@ -233,6 +233,7 @@
 **                           does not match.   Also, buffer match check must include the DMO alias.
 ** 088 CA  20230323          Prevent NPE if the field in EXCEPT/FIELDS can't be resolved in that buffer.
 ** 089 IAS 20230405          Fixed FILL support for recursive DATA-RELATION
+** 090 AL2 20230411          Support query close listeners.
 */
 
 /*
@@ -377,7 +378,7 @@
    private WeakList<RepositionListener> repoRegistry = null;
    
    /** Registry of listeners who are notified of query is about to (re-)open. */
-   private List<QueryOpenListener> openListeners = null;
+   private List<QueryEventListener> eventListeners = null;
    
    /** Flag to avoid infinite recursion in reposition notification */
    private boolean notificationActive = false;
@@ -963,14 +964,14 @@
     *          The listener to be notified.
     */
    @Override
-   public void addQueryOpenListener(QueryOpenListener listener)
+   public void addQueryEventListener(QueryEventListener listener)
    {
-      if (openListeners == null)
+      if (eventListeners == null)
       {
-         openListeners = new LinkedList<>();
+         eventListeners = new LinkedList<>();
       }
    
-      openListeners.add(listener);
+      eventListeners.add(listener);
    }
    
    /**
@@ -983,9 +984,9 @@
    @Override
    public void notifyQueryOpenListeners(boolean evaluate)
    {
-      if (openListeners != null)
+      if (eventListeners != null)
       {
-         Iterator<QueryOpenListener> iter = openListeners.iterator();
+         Iterator<QueryEventListener> iter = eventListeners.iterator();
          while (iter.hasNext())
          {
             iter.next().onQueryOpen(evaluate);
@@ -994,6 +995,22 @@
    }
    
    /**
+    * Notifies the registered QUERY-CLOSE listeners that the event is about to happen.
+    */
+   @Override
+   public void notifyQueryCloseListeners()
+   {
+      if (eventListeners != null)
+      {
+         Iterator<QueryEventListener> iter = eventListeners.iterator();
+         while (iter.hasNext())
+         {
+            iter.next().onQueryClose();
+         }
+      }
+   }
+   
+   /**
     * Register a listener to receive notifications reposition events for this
     * query.
     *

=== modified file 'src/com/goldencode/p2j/persist/DynamicQueryHelper.java'
--- old/src/com/goldencode/p2j/persist/DynamicQueryHelper.java	2023-04-06 02:34:19 +0000
+++ new/src/com/goldencode/p2j/persist/DynamicQueryHelper.java	2023-04-20 11:04:15 +0000
@@ -84,6 +84,7 @@
 **     SVL 20230113 Improved performance by replacing some "for-each" loops with indexed "for" loops.
 **     CA  20230116 Avoid using handle.unwrap, handle.getReference or other BDT usage from within FWD runtime.
 ** 043 OM  20230215 Handled collision of temporary buffers and tables with same name.
+** 044 AL2 20230411 Ensure delayed execute is run only once. The flag is reset on query close. 
 */
 
 /*
@@ -154,6 +155,7 @@
 import com.goldencode.p2j.convert.*;
 import com.goldencode.p2j.directory.*;
 import com.goldencode.p2j.jmx.*;
+import com.goldencode.p2j.persist.P2JQuery.QueryEventListener;
 import com.goldencode.p2j.persist.lock.LockType;
 import com.goldencode.p2j.schema.*;
 import com.goldencode.p2j.security.*;
@@ -625,21 +627,38 @@
          
          if (processor.delayedExecute() && query0 != null)
          {
-            query0.addQueryOpenListener((evaluate) -> 
-            {
-               interpreter.processInstancesWith((o) -> 
-               {
-                  if (o instanceof P2JQuery)
-                  {
-                     ((P2JQuery) o).setDynamicPredicate(query0.isDynamicPredicate());
-                  }
-               });
-               interpreter.interpret("execute");
-               
-               if (evaluate)
-               {
-                  interpreter.evaluateDynamicCalls();
-               }
+            query0.addQueryEventListener(new QueryEventListener() {
+               
+               private boolean executedOnce = false;
+
+               @Override
+               public void onQueryOpen(boolean evaluate)
+               {
+                  if (!executedOnce || evaluate)
+                  {
+                     executedOnce = true;
+                     interpreter.processInstancesWith((o) -> 
+                     {
+                        if (o instanceof P2JQuery)
+                        {
+                           ((P2JQuery) o).setDynamicPredicate(query0.isDynamicPredicate());
+                        }
+                     });
+                     interpreter.interpret("execute");
+                  }
+                  
+                  if (evaluate)
+                  {
+                     interpreter.evaluateDynamicCalls();
+                  }
+               }
+
+               @Override
+               public void onQueryClose()
+               {
+                  executedOnce = false;
+               }
+               
             });
          }
          return query0;

=== modified file 'src/com/goldencode/p2j/persist/P2JQuery.java'
--- old/src/com/goldencode/p2j/persist/P2JQuery.java	2023-03-28 11:01:11 +0000
+++ new/src/com/goldencode/p2j/persist/P2JQuery.java	2023-04-20 11:02:51 +0000
@@ -134,6 +134,7 @@
 **                           buffer list).
 **     OM  20220112          Added default implementation for new property 'fillingBrowseRows'.
 ** 062 IAS 20230105          Fixed FILL support for recursive DATA-RELATION
+** 063 AL2 20230411          Added query close listeners.
 */
 
 /*
@@ -2263,14 +2264,14 @@
    public void clearDynamicFilters();
    
    /**
-    * Adds a listener to be notified when this query is open.
+    * Adds a listener to be notified when this query is opened or closed.
     * <p> 
     * Note that this method is only called for dynamic queries only (for the moment).
     *  
-    * @param   qol
+    * @param   qel
     *          The listener to be notified.
     */
-   public default void addQueryOpenListener(QueryOpenListener qol) {}
+   public default void addQueryEventListener(QueryEventListener qel) {}
    
    /**
     * Notifies the registered QUERY-OPEN listeners that the even is about to happen.
@@ -2280,6 +2281,11 @@
     *           in the WHERE clause. 
     */
    public default void notifyQueryOpenListeners(boolean evaluate) {}
+   
+   /**
+    * Notifies the registered QUERY-CLOSE listeners that the even is about to happen.
+    */
+   public default void notifyQueryCloseListeners() {}
 
    /**
     * Getter for the BASIC-LOGGING attribute.
@@ -2345,9 +2351,9 @@
    }
    
    /**
-    * Interface for receiving query open events. 
+    * Interface for receiving query events. 
     */
-   public interface QueryOpenListener
+   public interface QueryEventListener
    {
       /**
        * Implement this method to receive the notification that the query IS ABOUT TO open.
@@ -2357,6 +2363,11 @@
        *           in the WHERE clause. 
        */
       public void onQueryOpen(boolean evaluate);
+      
+      /**
+       * Implement this method to receive the notification that the query IS ABOUT TO close.
+       */
+      public void onQueryClose();
    }
    
    /** 

=== modified file 'src/com/goldencode/p2j/persist/QueryWrapper.java'
--- old/src/com/goldencode/p2j/persist/QueryWrapper.java	2023-04-05 18:08:41 +0000
+++ new/src/com/goldencode/p2j/persist/QueryWrapper.java	2023-04-20 11:03:02 +0000
@@ -277,6 +277,7 @@
 **     HC  20230118          Eliminated some of the uses of String.toUpperCase and/or
 **                           String.toLowerCase for performance.
 ** 094 IAS 20230405          Fixed FILL support for recursive DATA-RELATION
+** 095 AL2 20230411          Notify query close listeners.
 */
 
 /*
@@ -2861,7 +2862,7 @@
    }
    
    /**
-    * Adds a listener to be notified when this query is open.
+    * Adds a listener to be notified when this query is opened or closed.
     * <p> 
     * Note that this method is only called for dynamic queries only (for the moment).
     *
@@ -2869,14 +2870,14 @@
     *          The listener to be notified.
     */
    @Override
-   public void addQueryOpenListener(QueryOpenListener listener)
+   public void addQueryEventListener(QueryEventListener listener)
    {
       // for the moment the QueryOpen notification only handles dynamic queries. The wrapper does
       // not notify about the event BUT will propagate the event to its [delegate] if any, and
       // that query will notify its listeners.
       if (delegate != null)
       {
-         getDelegate().addQueryOpenListener(listener);
+         getDelegate().addQueryEventListener(listener);
       }
    }
    
@@ -3779,6 +3780,11 @@
    {
       boolean success = true;
 
+      if (delegate != null)
+      {
+         delegate.notifyQueryCloseListeners();
+      }
+      
       try
       {
          close();

