=== modified file 'src/com/goldencode/p2j/persist/AbstractTempTable.java'
--- old/src/com/goldencode/p2j/persist/AbstractTempTable.java	2023-01-10 09:20:39 +0000
+++ new/src/com/goldencode/p2j/persist/AbstractTempTable.java	2023-01-13 10:21:10 +0000
@@ -156,9 +156,9 @@
    /** Default prefix for the name of a temp-table copied with COPY-TEMP-TABLE. */
    protected static final String DEFAULT_COPY_TEMP_TABLE_PREFIX = "cpy";
    
-   /** Default buffer handle. */
-   protected handle defaultBufferHandle = null;
-   
+   /** Default buffer. */
+   protected BufferImpl defaultBuffer = null;
+
    /** Corresponds ERROR-STRING attribute. */
    protected final character errorString = new character();
    
@@ -259,13 +259,12 @@
    @Override
    public character primaryIndex()
    {
-      BufferImpl defBuf = (BufferImpl) defaultBufferHandle.getResource();
-      if (defBuf == null)
+      if (defaultBuffer == null)
       {
          return new character();
       }
       
-      return defBuf.primaryIndex();
+      return defaultBuffer.primaryIndex();
    }
    
    /**
@@ -557,18 +556,18 @@
       }
       
       // delegate to default buffer
-      return  defaultBufferHandle.unwrapDereferenceable().derefPoly(memberName);
+      return defaultBuffer.derefPoly(memberName);
    }
    
    /**
     * All kind of temp-tables can be dereferenced. This should be propagated to the 
-    * {@link #defaultBufferHandle} if not null. Otherwise, the table was not prepared
+    * {@link #defaultBuffer} if not null. Otherwise, the table was not prepared
     * (for dynamic temp-tables).
     * 
     * @param   memberName
     *          The name of the member to be extracted.
     *
-    * @return  The value of the member - processed by the {@link #defaultBufferHandle}.
+    * @return  The value of the member - processed by the {@link #defaultBuffer}.
     */
    @Override
    public BaseDataType dereference(String memberName)
@@ -579,12 +578,12 @@
          return null;
       }
       
-      return defaultBufferHandle.unwrapDereferenceable().dereference(memberName);
+      return defaultBuffer.dereference(memberName);
    }
    
    /**
     * All kind of temp-tables can be dereferenced. This should be propagated to the 
-    * {@link #defaultBufferHandle} if not null. Otherwise, the table was not prepared
+    * {@link #defaultBuffer} if not null. Otherwise, the table was not prepared
     * (for dynamic temp-tables).
     * 
     * @param   type
@@ -592,7 +591,7 @@
     * @param   memberName
     *          The name of the member to be extracted.
     *
-    * @return  The value of the member - processed by the {@link #defaultBufferHandle}.
+    * @return  The value of the member - processed by the {@link #defaultBuffer}.
     */
    @Override
    public <T extends BaseDataType> T dereference(Class<T> type, String memberName)
@@ -603,12 +602,12 @@
          return null;
       }
       
-      return defaultBufferHandle.unwrapDereferenceable().dereference(type, memberName);
+      return defaultBuffer.dereference(type, memberName);
    }
    
    /**
     * All kind of temp-tables can be dereferenced. This should be propagated to the 
-    * {@link #defaultBufferHandle} if not null. Otherwise, the table was not prepared
+    * {@link #defaultBuffer} if not null. Otherwise, the table was not prepared
     * (for dynamic temp-tables) and the uninitialized error should be displayed.
     * 
     * @param   memberName
@@ -625,7 +624,7 @@
          return;
       }
 
-      defaultBufferHandle.unwrapDereferenceable().dereference(memberName, value);
+      defaultBuffer.dereference(memberName, value);
    }
    
    /**
@@ -844,15 +843,14 @@
          return new logical(false);
       }
       
-      BufferImpl defBuff = (BufferImpl) defaultBufferHandle.unwrapBuffer();
-      if (computeTableType() == BeforeType.BEFORE && defBuff.hasBeforeBufferConstraints())
+      if (computeTableType() == BeforeType.BEFORE && defaultBuffer.hasBeforeBufferConstraints())
       {
          ErrorManager.recordOrShowError(11946);
          // You cannot EMPTY a BEFORE-TABLE, Use ACCEPT-CHANGES or EMPTY the AFTER-TABLE.
          return new logical(false);
       }
       
-      AbstractTempTable bTable = (AbstractTempTable) getBeforeTable().getResource();
+      AbstractTempTable bTable = (AbstractTempTable) getBeforeTableNative();
       if (bTable != null)
       {
          ((BufferImpl) bTable.defaultBuffer().getDMOProxy()).setUpBeforeBuffer(true);
@@ -1162,8 +1160,8 @@
          return;
       }
       
-      handle bt = getBeforeTable();
-      if (bt.isUnknown())
+      TempTable bt = getBeforeTableNative();
+      if (bt == null)
       {
          if (_dynamic())
          {
@@ -1193,14 +1191,26 @@
    @Override
    public handle getBeforeTable()
    {
+      return new handle(getBeforeTableNative());
+   }
+
+   /**
+    * Get the handle of the before-image table that corresponds to the after-image table
+    * currently associated with this temp-table handle.
+    *
+    * @return  the value of {@code BEFORE-TABLE} as described above.
+    */
+   @Override
+   public TempTable getBeforeTableNative()
+   {
       if (computeTableType() == BeforeType.AFTER)
       {
-         return new handle(peerTable);
+         return peerTable;
       }
-      
-      return new handle();
+
+      return null;
    }
-   
+
    /**
     * Get the handle of the after-image table that corresponds to the before-image table
     * currently associated with this temp-table handle.
@@ -1210,14 +1220,26 @@
    @Override
    public handle getAfterTable()
    {
+      return new handle(getAfterTableNative());
+   }
+
+   /**
+    * Get the handle of the after-image table that corresponds to the before-image table
+    * currently associated with this temp-table handle.
+    *
+    * @return  the value of {@code AFTER-TABLE} as described above.
+    */
+   @Override
+   public TempTable getAfterTableNative()
+   {
       if (computeTableType() == BeforeType.BEFORE)
       {
-         return new handle(peerTable);
+         return peerTable;
       }
-      
-      return new handle();
+
+      return null;
    }
-   
+
    /**
     * Get the handle of the TEMP-TABLE in the original source {@code DataSet} object that
     * corresponds to the TEMP-TABLE currently associated with this TEMP-TABLE handle.
@@ -1229,7 +1251,19 @@
    {
       return new handle(originTable);
    }
-   
+
+   /**
+    * Get the handle of the TEMP-TABLE in the original source {@code DataSet} object that
+    * corresponds to the TEMP-TABLE currently associated with this TEMP-TABLE handle.
+    *
+    * @return  the current origin table.
+    */
+   @Override
+   public TempTable getOriginTable()
+   {
+      return originTable;
+   }
+
    /**
     * Implementation of the READ-XML method. Reads XML data from the specified data source into
     * this object.
@@ -1658,15 +1692,21 @@
          // Dynamic temp-table must be in PREPARED state for WRITE-XML Methods.
          return new logical(false);
       }
-      
-      return defaultBufferHandle().unwrapBuffer().writeXml(target,
-                                                           formatted,
-                                                           encoding,
-                                                           schemaLocation,
-                                                           writeXmlSchema,
-                                                           minXmlSchema,
-                                                           beforeImage,
-                                                           noInitialVals);
+
+      Buffer buf = defaultBufferHandleNative();
+      if (buf == null)
+      {
+         return new logical(false);
+      }
+
+      return buf.writeXml(target,
+                          formatted,
+                          encoding,
+                          schemaLocation,
+                          writeXmlSchema,
+                          minXmlSchema,
+                          beforeImage,
+                          noInitialVals);
    }
    
    /**
@@ -1769,9 +1809,15 @@
          // Dynamic temp-table must be in PREPARED state for WRITE-XML Methods.
          return new logical(false);
       }
-      
-      return defaultBufferHandle().unwrapBuffer().writeXmlSchema(
-            target, formatted, encoding, minXmlSchema, omitInitVal);
+
+
+      Buffer buf = defaultBufferHandleNative();
+      if (buf == null)
+      {
+         return new logical(false);
+      }
+
+      return buf.writeXmlSchema(target, formatted, encoding, minXmlSchema, omitInitVal);
    }
    
    /**
@@ -2150,9 +2196,14 @@
          // throw something?
          return new logical(false);
       }
-      
-      return defaultBufferHandle().unwrapBuffer().writeJson(
-            target, formatted, encoding, omitInitialValues, omitOuterObject, writeBeforeImage);
+
+      Buffer buf = defaultBufferHandleNative();
+      if (buf == null)
+      {
+         return new logical(false);
+      }
+
+      return buf.writeJson(target, formatted, encoding, omitInitialValues, omitOuterObject, writeBeforeImage);
    }
    
    /**
@@ -2453,7 +2504,7 @@
     */
    public String tableDefinition()
    {
-      WrappedResource r = this.defaultBufferHandle.getResource();
+      WrappedResource r = this.defaultBuffer;
       if (r != null && r.valid())
       {
          return ((BufferImpl) r).tableDefinition();
@@ -2518,12 +2569,12 @@
     */
    TemporaryBuffer defaultBuffer()
    {
-      if (defaultBufferHandle == null)
+      if (defaultBuffer == null)
       {
          return null;
       }
       
-      return (TemporaryBuffer) RecordBuffer.get((DataModelObject) defaultBufferHandle.getResource());
+      return (TemporaryBuffer) RecordBuffer.get((DataModelObject) defaultBuffer);
    }
    
    /**

=== modified file 'src/com/goldencode/p2j/persist/BufferFieldImpl.java'
--- old/src/com/goldencode/p2j/persist/BufferFieldImpl.java	2022-10-07 13:36:22 +0000
+++ new/src/com/goldencode/p2j/persist/BufferFieldImpl.java	2023-01-13 10:21:10 +0000
@@ -320,8 +320,7 @@
    @Override
    public logical available() 
    {
-      handle buf = bufferHandle();
-      if (!buf.unwrapBuffer()._available())
+      if (!getBuffer()._available())
       {
          return new logical();
       }
@@ -533,10 +532,10 @@
    @Override
    public BaseDataType value()
    {
-      handle buf = bufferHandle();
-      if (buf._isValid())
+      Buffer buf = getBuffer();
+      if (buf != null && buf.valid())
       {
-         if (buf.unwrapBuffer()._available())
+         if (buf._available())
          {
             if (fieldRef.getExtent() != null)
             {
@@ -550,13 +549,13 @@
             }
             return retVal;
          }
-         else if (((BufferImpl) buf.unwrapBuffer()).buffer().isUnknownMode())
+         else if (((BufferImpl) buf).buffer().isUnknownMode())
          {
             return fieldRef.unknownValue();
          }
       }
       
-      String bn = !buf._isValid() ? "<UNKNOWN>" : buf.unwrap().name().toStringMessage();
+      String bn = buf == null || !buf.valid() ? "<UNKNOWN>" : buf.name().toStringMessage();
       ErrorManager.recordOrShowError(
             91,
             String.format("No %s record is available", bn),
@@ -799,9 +798,19 @@
    @Override
    public handle bufferHandle()
    {
-      return new handle((Buffer) getParentBuffer().getDMOProxy());
-   }
-   
+      return new handle(getBuffer());
+   }
+
+   /**
+    * Returns the handle of the buffer object to which the buffer-field belongs.
+    *
+    * @return the handle of the buffer object to which the buffer-field belongs.
+    */
+   public Buffer getBuffer()
+   {
+      return (Buffer) getParentBuffer().getDMOProxy();
+   }
+
    /**
     * Conversion of LITERAL-QUESTION attribute (KW_LIT_QSTN).
     *

=== modified file 'src/com/goldencode/p2j/persist/BufferHandle.java'
--- old/src/com/goldencode/p2j/persist/BufferHandle.java	2017-04-01 23:33:34 +0000
+++ new/src/com/goldencode/p2j/persist/BufferHandle.java	2023-01-13 10:21:10 +0000
@@ -85,4 +85,19 @@
     */
    @LegacyAttribute(name = "DEFAULT-BUFFER-HANDLE")
    public handle defaultBufferHandle();
+
+   /**
+    * Obtain the buffer that was created by default for this temporary table. Every
+    * dynamic temp-table is created with at least one buffer. This buffer object is
+    * returned by this method.
+    *
+    * Note that it cannot be called until the table has been prepared using
+    * <code>tempTablePrepare()</code> method.
+    *
+    * This method is the P2J equivalent of <code>DEFAULT-BUFFER-HANDLE</code>
+    * attribute.
+    *
+    * @return  The default buffer for the temporary table.
+    */
+   public Buffer defaultBufferHandleNative();
 }
\ No newline at end of file

=== modified file 'src/com/goldencode/p2j/persist/BufferImpl.java'
--- old/src/com/goldencode/p2j/persist/BufferImpl.java	2023-01-10 09:20:39 +0000
+++ new/src/com/goldencode/p2j/persist/BufferImpl.java	2023-01-13 10:21:10 +0000
@@ -414,7 +414,7 @@
    private boolean deleting;
    
    /** The last query this buffer was added/set to. */
-   private handle lastQuery = null;
+   private QueryWrapper lastQuery = null;
    
    /** The current dataset. May be {@code null}. */
    private DataSet dataSet = null;
@@ -2279,23 +2279,39 @@
    @Override
    public handle bufferField(String fieldName)
    {
+      return new handle(bufferFieldNative(fieldName));
+   }
+
+   /**
+    * Implementation of BUFFER-FIELD() method (KW_BUF_FLD).
+    *
+    * Gets a particular field within a buffer.
+    *
+    * @param   fieldName
+    *          The legacy field name. A CHARACTER string expression representing the name
+    *          of the field in the buffer.
+    *
+    * @return  a particular field in the buffer.
+    */
+   public BufferField bufferFieldNative(String fieldName)
+   {
       Property property = buffer().getDmoInfo().byLegacyName(fieldName);
       if (property != null)
       {
          BufferFieldImpl field = bufferFieldForProperty(property.name);
          if (field != null)
          {
-            return new handle(field);
+            return field;
          }
       }
 
       String msg = "BUFFER-FIELD " + fieldName + " was not found in buffer " + doGetName();
       ErrorManager.recordOrShowError(7351, msg, false, false, false);
-      
+
       // return unknown handle
-      return new handle();
+      return null;
    }
-   
+
    /**
     * Conversion of BUFFER-COPY() method (KW_BUF_COPY).
     *
@@ -6413,13 +6429,7 @@
    @Override
    public handle getQueryAsHandle()
    {
-      // bit of maintenance
-      if (lastQuery != null && !lastQuery._isValid())
-      {
-         lastQuery = null;
-      }
-      
-      return lastQuery == null ? new handle() : new handle(lastQuery.getResource());
+      return lastQuery == null ? new handle() : new handle(lastQuery);
    }
    
    /**
@@ -6588,7 +6598,7 @@
       if (crtState == Buffer.ROW_MODIFIED || crtState == Buffer.ROW_CREATED)
       {
          // find and update the after-image/record
-         BufferImpl after = (BufferImpl) afterBuffer().unwrapBuffer();
+         BufferImpl after = afterBufferNative();
          after.findByRowID(this.afterRowid());
          RecordBuffer afterRecBuf = after.buffer();
          afterRecBuf.peerRowid(new rowid());
@@ -6627,7 +6637,7 @@
       }
       
       // find and update the after-image/record
-      BufferImpl after = (BufferImpl) afterBuffer().unwrapBuffer();
+      BufferImpl after = afterBufferNative();
       TemporaryBuffer afterImage = (TemporaryBuffer) after.buffer();
       RecordBuffer recBuf = buffer();
       switch (recBuf.rowState().toJavaIntegerType())
@@ -7079,7 +7089,7 @@
          BufferImpl ref = null;
          for (int k = 1; k <= newDSrc._getNumSourceBuffers(); k++)
          {
-            BufferImpl buffer = (BufferImpl) newDSrc.getSourceBuffer(k).unwrapBuffer();
+            BufferImpl buffer = newDSrc.getSourceBufferNative(k);
             if (buffer.hasField(myFieldName))
             {
                // if multiple buffers have the same field, then the last buffer having this field will be used
@@ -7155,7 +7165,7 @@
             BufferImpl buffer = null;
             for (int j = 1; j <= newDSrc._getNumSourceBuffers(); j++)
             {
-               buffer = (BufferImpl) newDSrc.getSourceBuffer(j).unwrapBuffer();
+               buffer = newDSrc.getSourceBufferNative(j);
                if (buffer.hasFieldEx(fld2NoEx))
                {
                   found = true;
@@ -7294,15 +7304,26 @@
    @Override
    public handle afterBuffer()
    {
+      return new handle(afterBufferNative());
+   }
+
+   /**
+    * Obtain the default buffer of the after-image table that corresponds to
+    * the buffer of the before-image table currently associated with this buffer.
+    *
+    * @return  The value of {@code AFTER-BUFFER} attribute as described above.
+    */
+   public BufferImpl afterBufferNative()
+   {
       if (!isBeforeBuffer())
       {
          // permanent and simple temp-tables do not have BEFORE/AFTER buffers
-         return new handle();
+         return null;
       }
-      
-      return new handle(peerBuffer);
+
+      return peerBuffer;
    }
-   
+
    /**
     * Obtain the {@code rowid} of the row in the original before-image table that corresponds to
     * the row in the change table currently associated with this buffer handle.
@@ -7355,15 +7376,26 @@
    @Override
    public handle beforeBuffer()
    {
+      return new handle(beforeBufferNative());
+   }
+
+   /**
+    * Obtain the default buffer of the before-image table that corresponds to
+    * the buffer of the after-image table currently associated with this buffer.
+    *
+    * @return  The value of {@code BEFORE-BUFFER} attribute as described above.
+    */
+   public BufferImpl beforeBufferNative()
+   {
       if (!isAfterBuffer())
       {
          // permanent and simple temp-tables do not have BEFORE/AFTER buffers
-         return new handle();
+         return null;
       }
-      
-      return new handle(peerBuffer);
+
+      return peerBuffer;
    }
-   
+
    /**
     * The list of field name pairs for all fields  (in comm-delimited format) in a {@code DataSet}
     * temp-table buffer that are mapped to corresponding fields in an attached data-source object.
@@ -7811,8 +7843,7 @@
          return new logical(false);
       }
       
-      return new logical(((TemporaryBuffer) buffer()).markNew(
-            (BufferImpl) beforeBuffer().unwrapBuffer()));
+      return new logical(((TemporaryBuffer) buffer()).markNew(beforeBufferNative()));
    }
    
    /**
@@ -7939,7 +7970,7 @@
          return new logical(true); // already has before image/record
       }
       
-      BufferImpl b4Buffer = (BufferImpl) beforeBuffer().unwrapBuffer();
+      BufferImpl b4Buffer = beforeBufferNative();
       RecordBuffer b4RecBuf = b4Buffer.buffer();
       RecordBuffer recBuf = buffer();
       b4Buffer.setUpBeforeBuffer(true);
@@ -8226,7 +8257,7 @@
          BufferImpl[] srcBuffs = new BufferImpl[srcBufCount];
          for (int k = 0; k < srcBufCount; k++)
          {
-            srcBuffs[k] = (BufferImpl) dataSource.getSourceBuffer(k + 1).unwrapBuffer();
+            srcBuffs[k] = dataSource.getSourceBufferNative(k + 1);
             srcBuffs[k].buffer().initialize();
          }
          
@@ -8850,11 +8881,11 @@
       // check the argument first: it must be an AFTER or BEFORE buffer:
       BufferImpl srcBefore = (BufferImpl) original.unwrapBuffer();
       BufferImpl srcAfter = null;
-      handle xHandle = srcBefore.beforeBuffer();
-      if (xHandle.isUnknown())
+      BufferImpl buf = srcBefore.beforeBufferNative();
+      if (buf == null)
       {
-         xHandle = srcBefore.afterBuffer();
-         if (xHandle.isUnknown())
+         buf = srcBefore.afterBufferNative();
+         if (buf == null)
          {
             ErrorManager.recordOrShowError(11925, srcBefore.doGetName());
             // GET/MERGE-CHANGES require a BEFORE-TABLE for table <name>.
@@ -8862,24 +8893,24 @@
          }
          else
          {
-            srcAfter = (BufferImpl) xHandle.unwrapBuffer(); 
+            srcAfter = buf;
          }
       }
       else
       {
          // oops, [xHandle] is the BEFORE buffer and [srcBefore] is the AFTER buffer, fixing:
          srcAfter = srcBefore;
-         srcBefore = (BufferImpl) xHandle.unwrapBuffer();
+         srcBefore = buf;
       }
       
       // now check the current buffer: it also must be an AFTER or BEFORE buffer:
       BufferImpl dstBefore = null;
       BufferImpl dstAfter = null;
-      xHandle = beforeBuffer();
-      if (xHandle.isUnknown())
+      buf = beforeBufferNative();
+      if (buf == null)
       {
-         xHandle = afterBuffer();
-         if (xHandle.isUnknown())
+         buf = afterBufferNative();
+         if (buf == null)
          {
             ErrorManager.recordOrShowError(11925, doGetName());
             // GET/MERGE-CHANGES require a BEFORE-TABLE for table <name>.
@@ -8888,12 +8919,12 @@
          else 
          {
             dstBefore = this;
-            dstAfter = (BufferImpl) xHandle.unwrapBuffer();
+            dstAfter = buf;
          }
       }
       else
       {
-         dstBefore = (BufferImpl) xHandle.unwrapBuffer();
+         dstBefore = buf;
          dstAfter = this;
       }
       
@@ -9050,7 +9081,7 @@
       }
       else
       {
-         afterBufferChanges = (BufferImpl) afterBuffer().unwrapBuffer();
+         afterBufferChanges = peerBuffer;
       }
       
       BufferImpl origBuffer;
@@ -9058,15 +9089,14 @@
       if (original == null)
       {
          TempTable parentTable = this.buffer().getParentTable();
-         handle originTableHandle = parentTable.getOriginHandle();
-         if (originTableHandle.isUnknown() || !originTableHandle._isValid())
+         originTable = parentTable.getOriginTable();
+         if (originTable == null || !originTable.valid())
          {
             ErrorManager.recordOrShowError(11944, afterBufferChanges.doGetName());
             // MERGE-ROW-CHANGES finds ORIGIN-HANDLE in table <name> is no longer valid.
             return new logical(false);
          }
-         originTable = originTableHandle.unwrapTempTable();
-         origBuffer = (BufferImpl) originTable.defaultBufferHandle().unwrapBuffer(); 
+         origBuffer = (BufferImpl) originTable.defaultBufferHandleNative();
       }
       else
       {
@@ -9228,7 +9258,7 @@
       
       RecordBuffer beforeBuf = buffer();
       Persistence persistence = beforeBuf.getPersistence();
-      BufferImpl after = (BufferImpl) afterBuffer().unwrapBuffer();
+      BufferImpl after = afterBufferNative();
       RecordBuffer afterBuf = after.buffer();
       
       // invalidate index-based caches because of low-level operations:
@@ -9310,7 +9340,7 @@
          // TODO: but if it still happens? which error we we throw?
          return new logical(false);
       }
-      return new logical(buffer.rejectChanges((BufferImpl) afterBuffer().unwrapBuffer()));
+      return new logical(buffer.rejectChanges(afterBufferNative()));
    }
    
    /**
@@ -9389,7 +9419,7 @@
          return;
       }
       
-      this.lastQuery = new handle(qry.getResource());
+      this.lastQuery = (QueryWrapper) qry.getResource();
    }
    
    /**
@@ -9400,7 +9430,7 @@
     */
    protected void resetLastQuery(QueryWrapper qry)
    {
-      if (lastQuery != null && (lastQuery.isUnknown() || lastQuery.get() == qry))
+      if (lastQuery == qry)
       {
          this.lastQuery = null;
       }
@@ -9506,20 +9536,20 @@
       }
       
       TempTable tempTable = TempTableBuilder.asTempTable((Temporary) this);
-      
-      handle ttBefore = tempTable.getBeforeTable();
-      if (!ttBefore.isUnknown())
+
+      TempTable ttBefore = tempTable.getBeforeTableNative();
+      if (ttBefore != null)
       {
-         peerBuffer = (BufferImpl) ttBefore.unwrapTempTable().defaultBufferHandle().getResource();
+         peerBuffer = (BufferImpl) ttBefore.defaultBufferHandle().getResource();
          peerBuffer = peerBuffer.ref();
          beforeBufferType = BeforeType.AFTER;
          return;
       }
       
-      handle ttAfter = tempTable.getAfterTable();
-      if (!ttAfter.isUnknown())
+      TempTable ttAfter = tempTable.getAfterTableNative();
+      if (ttAfter != null)
       {
-         peerBuffer = (BufferImpl) ttAfter.unwrapTempTable().defaultBufferHandle().getResource();
+         peerBuffer = (BufferImpl) ttAfter.defaultBufferHandle().getResource();
          peerBuffer = peerBuffer.ref();
          beforeBufferType = BeforeType.BEFORE;
          return;
@@ -11141,7 +11171,7 @@
       peerBuffer.error(true);    // the AFTER-IMAGE of this BEFORE-IMAGE
       
       TempTable beforeTable = TempTableBuilder.asTempTable((Temporary) this);
-      TempTable afterTable = (TempTable) beforeTable.getAfterTable().getResource();
+      TempTable afterTable = beforeTable.getAfterTableNative();
       
       beforeTable.error(true);   // the TEMP-TABLE of current BUFFER
       afterTable.error(true);    // the TEMP-TABLE of the AFTER-BUFFER

=== modified file 'src/com/goldencode/p2j/persist/DBUtils.java'
--- old/src/com/goldencode/p2j/persist/DBUtils.java	2022-07-07 00:22:57 +0000
+++ new/src/com/goldencode/p2j/persist/DBUtils.java	2023-01-13 10:43:46 +0000
@@ -690,7 +690,7 @@
     *         If <code>fieldHandle</code> references an extent field, multiple field references
     *         for each extent element are returned.
     */
-   public static FieldReference[] getFieldForAddLikeColumn(P2JQuery query, handle fieldHandle)
+   public static FieldReference[] getFieldForAddLikeColumn(QueryWrapper query, handle fieldHandle)
    {
       if (!fieldHandle._isValid())
       {
@@ -713,7 +713,7 @@
       int bufferCount = query.numBuffers().intValue();
       for (int i = 1; i <= bufferCount; i++)
       {
-         Buffer buffer = query.bufferHandle(i).unwrapBuffer();
+         Buffer buffer = query.bufferHandleNative(i);
          if (buffer.equals(srcBuffer))
          {
             match = true;
@@ -763,7 +763,7 @@
     *         If the field expression references an extent field, multiple field references
     *         for each extent element are returned.
     */
-   public static FieldReference[] getFieldForAddLikeColumn(P2JQuery query, character fieldExpression)
+   public static FieldReference[] getFieldForAddLikeColumn(QueryWrapper query, character fieldExpression)
    {
       String fullSource = fieldExpression.getValue();
       if (fullSource == null)
@@ -799,7 +799,7 @@
       int bufferCount = query.numBuffers().intValue();
       for (int i = 1; i <= bufferCount; i++)
       {
-         Buffer buffer = query.bufferHandle(i).unwrapBuffer();
+         Buffer buffer = query.bufferHandleNative(i);
          RecordBuffer recordBuffer = ((BufferImpl) buffer).buffer();
          
          String bufferName = buffer.name().getValue();
@@ -924,10 +924,10 @@
     *         <p>Error with code <code>2</code>: if the buffer name is not specified, there are multiple
     *         buffers containing the field with the give name.</p>
     */
-   public static BufferField getMatchingBufferField(P2JQuery query, String fullFieldName)
+   public static BufferField getMatchingBufferField(QueryWrapper query, String fullFieldName)
    throws NumberedException
    {
-      Buffer targetBuffer = null;
+      BufferImpl targetBuffer = null;
       String fieldName;
       String bufName      = null;
 
@@ -946,14 +946,14 @@
       int numBuffers = query.numBuffers().intValue();
       for (int i = 1; i <= numBuffers; i++)
       {
-         Buffer buffer = query.bufferHandle(i).unwrapBuffer();
+         BufferImpl buffer = (BufferImpl) query.bufferHandleNative(i);
          if (bufName != null && !bufName.equalsIgnoreCase(buffer.name().getValue()))
          {
             // mismatching buffer name
             continue;
          }
 
-         String property = TableMapper.getPropertyName(((BufferImpl)buffer).buffer(), fieldName);
+         String property = TableMapper.getPropertyName(buffer.buffer(), fieldName);
          if (property == null)
          {
             // mismatching field name
@@ -963,7 +963,7 @@
          if (bufName != null)
          {
             // matching field name and buffer name
-            return buffer.bufferField(fieldName).unwrapBufferField();
+            return buffer.bufferFieldNative(fieldName);
          }
          else
          {
@@ -985,7 +985,7 @@
          throw new NumberedException("", 1);
       }
 
-      return targetBuffer.bufferField(fieldName).unwrapBufferField();
+      return targetBuffer.bufferFieldNative(fieldName);
    }
 
    /**

=== modified file 'src/com/goldencode/p2j/persist/DataRelation.java'
--- old/src/com/goldencode/p2j/persist/DataRelation.java	2022-11-30 00:14:15 +0000
+++ new/src/com/goldencode/p2j/persist/DataRelation.java	2023-01-13 10:21:10 +0000
@@ -363,7 +363,18 @@
    {
       return new handle(childBuffer);
    }
-   
+
+   /**
+    * Obtain the buffer of the child member of this data-relation object. This method
+    * corresponds to the real-only {@code CHILD-BUFFER} attribute.
+    *
+    * @return  the buffer of the child member.
+    */
+   public Buffer getChildBufferNative()
+   {
+      return childBuffer;
+   }
+
    /**
     * Obtain the handle to the {@code DataSet} query that contains the currently selected row in
     * the {@code BindingSource}. Corresponds to {@code CURRENT-QUERY} ABL method.
@@ -675,7 +686,18 @@
    {
       return new handle(parentBuffer);
    }
-   
+
+   /**
+    * Obtain the buffer of the parent member. This is the FWD implementation of
+    * {@code PARENT-BUFFER} ABL read-only attribute
+    *
+    * @return  the buffer of the parent member.
+    */
+   public Buffer getParentBufferNative()
+   {
+      return parentBuffer;
+   }
+
    /**
     * Checks whether child rows of a {@code DataSet} temp-table buffer are nested within their
     * parent rows when writing the XML representation of {@code DataSet} object that contains
@@ -1104,9 +1126,7 @@
          query.delete();
       }
       
-      handle hQuery = TypeFactory.handle();
-      QueryWrapper.createQuery(hQuery);
-      query = (QueryWrapper) hQuery.unwrapQuery();
+      query = QueryWrapper.createQueryNative(null);
       query.setBuffers(childBuffer);
       query.setSubstitutionBuffers(parentBuffer);
       return query.prepare(sb.toString()).booleanValue();

=== modified file 'src/com/goldencode/p2j/persist/DataSet.java'
--- old/src/com/goldencode/p2j/persist/DataSet.java	2023-01-07 22:47:28 +0000
+++ new/src/com/goldencode/p2j/persist/DataSet.java	2023-01-13 10:21:10 +0000
@@ -628,9 +628,9 @@
                for (int k = 1; k <= bufCnt; k++)
                {
                   // copy data for each corresponding temp-table
-                  Buffer srcBuf = dsSource.bufferHandle(k).unwrapBuffer();
+                  Buffer srcBuf = dsSource.getBufferByIndex(k);
                   Temporary srcDMO = TemporaryBuffer.getDefaultBuffer(srcBuf.tableHandle());
-                  BufferImpl targetDmo = (BufferImpl) dsTarget.bufferHandle(k).getResource();
+                  BufferImpl targetDmo = dsTarget.getBufferByIndex(k);
                   rowid srcRec = dsTarget.isReferenceOnly() && srcBuf._available() ? srcBuf.rowID() : null;
                   boolean res = TemporaryBuffer.copyAllRows(
                                     srcRec,
@@ -1307,7 +1307,7 @@
          TempTable srcTempTable = TempTableBuilder.asTempTable((Temporary) src);
          
          // this is a matter if there is a before-table, not if TRACKING-CHANGES is set...
-         if (srcTempTable.getBeforeTable().isUnknown())
+         if (srcTempTable.getBeforeTableNative() != null)
          {
             continue;
          }
@@ -2127,7 +2127,7 @@
             continue;
          }
          
-         logical ok = buffer.beforeBuffer().unwrapBuffer().acceptChanges();
+         logical ok = buffer.beforeBufferNative().acceptChanges();
          if (!ok.booleanValue())
          {
             return ok;
@@ -2156,7 +2156,7 @@
             continue;
          }
          
-         logical ok = buffer.beforeBuffer().unwrapBuffer().rejectChanges();
+         logical ok = buffer.beforeBufferNative().rejectChanges();
          if (!ok.booleanValue())
          {
             return ok;
@@ -2745,22 +2745,34 @@
    @Override
    public handle getTopBuffer(long index)
    {
+      return new handle(getTopBufferNative(index));
+   }
+
+   /**
+    * Gets the top-level buffer of this {@code DataSet} object at the specified index position.
+    *
+    * @param   index
+    *          The 1-based index of the top-level buffer.
+    *
+    * @return  the top-level buffer at the specified index position.
+    */
+   public BufferImpl getTopBufferNative(long index)
+   {
       if (index < 1)
       {
-         return new handle();
+         return null;
       }
-      
+
       List<Buffer> candidates = getTopBufferList();
       if (_getNumTopBuffers() != candidates.size())
       {
          // well, this should NEVER happen!
          throw new RuntimeException("The size of TOP-BUFFER list does not match NUM-TOP-BUFFER");
       }
-      
-      return index - 1 >= candidates.size() ? new handle() 
-                                            : new handle(candidates.get((int) (index - 1)));
+
+      return index - 1 >= candidates.size() ? null : (BufferImpl) candidates.get((int) (index - 1));
    }
-   
+
    /**
     * Gets the top-level buffer of this {@code DataSet} object at the specified index position.
     *
@@ -2808,12 +2820,12 @@
          return new handle();
       }
       
-      handle topBuffer = getTopBuffer(index);
-      if (topBuffer.isUnknown())
+      BufferImpl topBuffer = getTopBufferNative(index);
+      if (topBuffer == null)
       {
          return new handle();
       }
-      return getTopNavQuery((BufferImpl) topBuffer.unwrapBuffer());
+      return getTopNavQuery(topBuffer);
    }
    
    /**
@@ -2908,7 +2920,7 @@
          return;
       }
       
-      BufferImpl topBuffer = (BufferImpl) getTopBuffer(index).unwrapBuffer();
+      BufferImpl topBuffer = getTopBufferNative(index);
       _setTopBufferQuery(queryHandle, topBuffer);
    }
    
@@ -3026,7 +3038,11 @@
          for (int i = 0; i < relations.size(); i++)
          {
             DataRelation rel = relations.get(i);
-            Buffer cb = rel.getChildBuffer().unwrapBuffer();
+            Buffer cb = rel.getChildBufferNative();
+            if (cb == null)
+            {
+               continue;
+            }
             int uuid = cb.getUniqueID().intValue();
             if (childBuffers.contains(uuid))
             {
@@ -3580,9 +3596,8 @@
       else
       {
          // and, if so, it is of the proper type (RECID)
-         handle hfparent = bufChild.bufferField(parLink);
-         if (hfparent.isUnknown() ||
-             !"RECID".equalsIgnoreCase(hfparent.unwrapBufferField().getDataType().getValue()))
+         BufferField fparent = bufChild.bufferFieldNative(parLink);
+         if (fparent == null || !"RECID".equalsIgnoreCase(fparent.getDataType().getValue()))
          {
             ErrorManager.recordOrShowError(16028, parLink);
             // ADD-PARENT-ID-RELATION parent-id-field <field> is not valid.
@@ -4284,15 +4299,7 @@
    public handle bufferHandle(int64 bufIndex)
    {
       int idx = bufIndex.isUnknown() ? 0 : bufIndex.intValue();
-      
-      if (idx < 1 || idx > buffers.size())
-      {
-         return new handle();
-      }
-      
-      handle h = new handle();
-      h.assign(buffers.get(idx - 1));
-      return h;
+      return new handle(getBufferByIndex(idx));
    }
    
    /**
@@ -5538,7 +5545,25 @@
    {
       return ref().buffers;
    }
-   
+
+   /**
+    * Lookup a buffer by its index.
+    *
+    * @param   bufIndex
+    *          The index to search among the list of buffers.
+    *
+    * @return  The buffer whose index was specified or {@code null} when there is no match.
+    */
+   public BufferImpl getBufferByIndex(int bufIndex)
+   {
+      if (bufIndex < 1 || bufIndex > buffers.size())
+      {
+         return null;
+      }
+
+      return buffers.get(bufIndex - 1);
+   }
+
    /**
     * Copy output data for the linked {@code DataSet} parameter, if any.
     *
@@ -5689,7 +5714,8 @@
          DataRelation relation = relations.get(i);
          if (relation._isActive()      &&
              !relation._isReposition() &&
-             relation.getChildBuffer().unwrapBuffer().getUniqueID().intValue() == childUid)
+             // HC: can getChildBufferNative() return null in this case? should this case be handled?
+             relation.getChildBufferNative().getUniqueID().intValue() == childUid)
          {
             return relation;
          }
@@ -5727,11 +5753,11 @@
          {
             continue;
          }
-         if (child && rel.getChildBuffer().unwrapBuffer() == buffer)
+         if (child && rel.getChildBufferNative() == buffer)
          {
             ret.add(rel);
          }
-         if (parent && rel.getParentBuffer().unwrapBuffer() == buffer)
+         if (parent && rel.getParentBufferNative() == buffer)
          {
             ret.add(rel);
          }
@@ -6109,7 +6135,7 @@
       }
       return null;
    }
-   
+
    /**
     * Obtain the current {@code TOP-NAV-QUERY} for a specified buffer. Uses lazy initialization:
     * if not exist one is created (and prepared, but not open) now. 
@@ -6126,9 +6152,7 @@
       QueryWrapper query = topNavQueries.get(buffer);
       if (query == null || !query.valid())
       {
-         handle hQuery = TypeFactory.handle();
-         QueryWrapper.createQuery(hQuery);
-         query = (QueryWrapper) hQuery.unwrapQuery();
+         query = QueryWrapper.createQueryNative(null);
          query.setBuffers(buffer);
          query.prepare("FOR EACH " + buffer.name().toStringMessage());
          topNavQueries.put(buffer, query);
@@ -6344,7 +6368,7 @@
          DataRelation relation = relations.get(i);
          if (relation._isActive() && !relation._isReposition())
          {
-            topBuffers.remove(relation.getChildBuffer().unwrapBuffer());
+            topBuffers.remove(relation.getChildBufferNative());
          }
       }
       
@@ -6405,8 +6429,9 @@
          
          // TODO: anything to copy at the before-table?
          copyTempTableOptions((AbstractTempTable) srcAfterBuff.tableHandle().getResource(), newAtt);
-         
-         newBuffers[i] = (BufferImpl) newAtt.defaultBufferHandle().unwrapBuffer();
+
+         // HC: should null be handled here?
+         newBuffers[i] = (BufferImpl) newAtt.defaultBufferHandleNative();
       }
       setBuffers(newBuffers);
       // in OE 11.6 the [xmlNodeName] was observed to be copied in a different fashion 
@@ -6424,8 +6449,8 @@
       for (int i = 0; i < dataRelations.size(); i++)
       {
          DataRelation srcRel = dataRelations.get(i);
-         Buffer srcChBuffer = srcRel.getChildBuffer().unwrapBuffer();
-         Buffer srcParBuffer = srcRel.getParentBuffer().unwrapBuffer();
+         Buffer srcChBuffer = srcRel.getChildBufferNative();
+         Buffer srcParBuffer = srcRel.getParentBufferNative();
          
          Buffer bufParent = newBuffers[positionOf(srcBuffers, srcParBuffer)];
          Buffer bufChild = newBuffers[positionOf(srcBuffers, srcChBuffer)];

=== modified file 'src/com/goldencode/p2j/persist/DataSetContainer.java'
--- old/src/com/goldencode/p2j/persist/DataSetContainer.java	2022-11-14 15:55:42 +0000
+++ new/src/com/goldencode/p2j/persist/DataSetContainer.java	2023-01-13 10:21:10 +0000
@@ -288,7 +288,7 @@
       for (int k = 0; k < bufCnt; k++)
       {
          tableDefinitions.add(
-               new DsTableDefinition((BufferImpl) ds.bufferHandle(k + 1).getResource(), copyRows));
+               new DsTableDefinition(ds.getBufferByIndex(k + 1), copyRows));
       }
    }
 

=== modified file 'src/com/goldencode/p2j/persist/DataSource.java'
--- old/src/com/goldencode/p2j/persist/DataSource.java	2022-11-30 00:14:15 +0000
+++ new/src/com/goldencode/p2j/persist/DataSource.java	2023-01-13 10:21:10 +0000
@@ -147,7 +147,7 @@
    private BufferImpl datasetBuffer = null;
    
    /** The query that defines the buffers for the data-source object. */
-   private final handle query = new handle();
+   private QueryWrapper query = null;
    
    /**
     * The current value of the {@code PREFER-DATASET} attribute. Default value is {@code false}.
@@ -387,7 +387,7 @@
    @Override
    public handle getQueryAsHandle()
    {
-      return query._isValid() ? new handle(query.getResource()) : new handle();
+      return new handle(query);
    }
    
    /**
@@ -1124,7 +1124,7 @@
             return new character();
          }
          
-         TempTable bt = (TempTable) datasetBuffer.buffer().getParentTable().getBeforeTable().getResource();
+         TempTable bt = datasetBuffer.buffer().getParentTable().getBeforeTableNative();
          return new character(String.join(bt.name().toStringMessage(), ret));
       }
       
@@ -1183,8 +1183,7 @@
                   return new character();
                }
                
-               TempTable bt =
-                     (TempTable) datasetBuffer.buffer().getParentTable().getBeforeTable().getResource();
+               TempTable bt = datasetBuffer.buffer().getParentTable().getBeforeTableNative();
                return new character(String.join(bt.name().toStringMessage(), ret));
             }
             
@@ -1618,14 +1617,28 @@
    @Override
    public handle getSourceBuffer(long bufIndex)
    {
+      return new handle(getSourceBufferNative(bufIndex));
+   }
+
+   /**
+    * Gets the handle to the source buffer in the data-source object at the specified index
+    * position.
+    *
+    * @param   bufIndex
+    *          The index of the requested buffer.
+    *
+    * @return  the specified buffer.
+    */
+   public BufferImpl getSourceBufferNative(long bufIndex)
+   {
       if (bufIndex < 1 || bufIndex > buffers.size())
       {
-         return new handle();
+         return null;
       }
-      
-      return new handle(buffers.get((int) (bufIndex - 1)));
+
+      return buffers.get((int) (bufIndex - 1));
    }
-   
+
    /**
     * Gets the handle to the source buffer in the data-source object at the specified index
     * position.
@@ -1705,13 +1718,12 @@
     */
    int _getNumSourceBuffers()
    {
-      if (buffers.isEmpty() && query._isValid())
+      if (buffers.isEmpty() && query != null && query.valid())
       {
-         QueryWrapper qw = (QueryWrapper) query.getResource();
-         int n = (int) qw.numBuffers().getValue();
+         int n = (int) query.numBuffers().getValue();
          for (int k = 1; k <= n; k++)
          {
-            addSourceBufferImpl((BufferImpl) qw.bufferHandle(k).getResource(), null);
+            addSourceBufferImpl((BufferImpl) query.bufferHandle(k).getResource(), null);
          }
       }
       
@@ -1837,7 +1849,7 @@
       
       for (DataRelation rel : rels)
       {
-         String parBuff = rel.getParentBuffer().unwrapBuffer().name().toStringMessage();
+         String parBuff = rel.getParentBufferNative().name().toStringMessage();
          if (rel.isParentIdRelation().booleanValue())
          {
             // in PARENT-ID relations, the FILL WHERE is unknown
@@ -1926,7 +1938,7 @@
          }
       }
       
-      this.query.assign(qry);
+      this.query = ((QueryWrapper) qry);
       setParentBuffer();
    }
    
@@ -2072,8 +2084,8 @@
       if (saveWhere != null)
       {
          TempTable tempTable = TempTableBuilder.asTempTable((Temporary) datasetBuffer);
-         handle bt = tempTable.getBeforeTable();
-         if (bt == null || bt.isUnknown())
+         TempTable bt = tempTable.getBeforeTableNative();
+         if (bt == null)
          {
             if (!tempTable.isTrackingChanges().booleanValue())
             {
@@ -2097,8 +2109,8 @@
       }
       
       TempTable tempTable = TempTableBuilder.asTempTable((Temporary) datasetBuffer);
-      handle bt = tempTable.getBeforeTable();
-      if (bt == null || bt.isUnknown())
+      TempTable bt = tempTable.getBeforeTableNative();
+      if (bt == null)
       {
          if (!tempTable.isTrackingChanges().booleanValue())
          {
@@ -2123,7 +2135,7 @@
          }
       }
       
-      String btName = bt.unwrap().name().toStringMessage();
+      String btName = bt.name().toStringMessage();
       List<String> tokens = new ArrayList<>(6);
       StringBuilder sb = new StringBuilder();
       
@@ -2202,13 +2214,12 @@
     */
    private void setParentBuffer()
    {
-      if (datasetBuffer != null && query != null && query._isValid())
+      if (datasetBuffer != null && query != null && query.valid())
       {
          DataRelation relation = (DataRelation) datasetBuffer.parentRelation().getResource();
          if (relation != null)
          {
-            ((QueryWrapper) query.getResource())
-                  .setSubstitutionBuffers((Buffer) relation.getParentBuffer().getResource());
+            query.setSubstitutionBuffers((Buffer) relation.getParentBuffer().getResource());
          }
       }
    }

=== modified file 'src/com/goldencode/p2j/persist/DsRelationDefinition.java'
--- old/src/com/goldencode/p2j/persist/DsRelationDefinition.java	2021-01-13 21:04:41 +0000
+++ new/src/com/goldencode/p2j/persist/DsRelationDefinition.java	2023-01-13 10:43:46 +0000
@@ -129,8 +129,8 @@
    public DsRelationDefinition(DataRelation rel)
    {
       this.name = rel.name().toStringMessage();
-      this.parentBuffer = rel.getParentBuffer().unwrap().name().toStringMessage();
-      this.childBuffer = rel.getChildBuffer().unwrap().name().toStringMessage();
+      this.parentBuffer = rel.getParentBufferNative().name().toStringMessage();
+      this.childBuffer = rel.getChildBufferNative().name().toStringMessage();
       this.whereString = rel.getWhereString().toStringMessage();
       this.active = rel._isActive();
       this.parentId = rel.isParentIdRelation().booleanValue();

=== modified file 'src/com/goldencode/p2j/persist/DynamicValidationHelper.java'
--- old/src/com/goldencode/p2j/persist/DynamicValidationHelper.java	2022-09-18 17:16:17 +0000
+++ new/src/com/goldencode/p2j/persist/DynamicValidationHelper.java	2023-01-13 10:46:46 +0000
@@ -151,7 +151,7 @@
     *
     * @return {@link JastValidationExpr} instance representing the given validation expression.
     */
-   public static JastValidationExpr parseValidationExpression(P2JQuery query,
+   public static JastValidationExpr parseValidationExpression(QueryWrapper query,
                                                               RecordBuffer validatedBuffer,
                                                               String validatedProperty,
                                                               String validateExpression)
@@ -162,7 +162,7 @@
       List<Buffer> buffers = new ArrayList<>(numBuffers);
       for (int i = 1; i <= numBuffers; i++)
       {
-         buffers.add(query.bufferHandle(i).unwrapBuffer());
+         buffers.add(query.bufferHandleNative(i));
       }
       
       JavaAst        javaAst;

=== modified file 'src/com/goldencode/p2j/persist/QueryWrapper.java'
--- old/src/com/goldencode/p2j/persist/QueryWrapper.java	2023-01-07 22:47:28 +0000
+++ new/src/com/goldencode/p2j/persist/QueryWrapper.java	2023-01-13 12:34:42 +0000
@@ -655,6 +655,31 @@
    {
       createQuery(hQuery, (character) null);
    }
+
+   /**
+    * Dynamically creates a query in the specified widget pool.
+    *
+    * This method is the equivalent of <code>CREATE QUERY</code> from 4GL.
+    *
+    * @param   widgetPool
+    *          The name of the widget pool that contains the dynamic query. <code>null</code> if
+    *          the unnamed pool must be used.
+    *
+    * @return  the newly created query.
+    */
+   public static QueryWrapper createQueryNative(String widgetPool)
+   {
+      // validate widget pool before anything else!!!
+      if (!WidgetPool.validWidgetPool(widgetPool))
+      {
+         return null;
+      }
+
+      // create the query; use an empty string as its name
+      QueryWrapper res = new QueryWrapper("", true, true);
+      WidgetPool.addResourceNative(res, widgetPool);
+      return res;
+   }
    
    /**
     * Conversion of DYNAMIC attribute. Returns <code>true</code> if the buffer is dynamic.
@@ -3671,21 +3696,34 @@
    public handle bufferHandle(int64 bufferSequenceNumber)
    {
       int idx = bufferSequenceNumber.isUnknown() ? 0 : bufferSequenceNumber.intValue();
-      
-      if (idx >= 1 && idx <= buffers.size())
+      return new handle(bufferHandleNative(idx));
+   }
+
+   /**
+    * Conversion of GET-BUFFER-HANDLE() method (KW_GET_BUFH).
+    *
+    * Returns a particular buffer of a query object.
+    *
+    * @param   bufferSequenceNumber
+    *          buffer-sequence-number. An INTEGER that represents the sequence
+    *          number of the desired buffer.
+    *
+    * @return buffer object
+    */
+   public Buffer bufferHandleNative(int bufferSequenceNumber)
+   {
+      if (bufferSequenceNumber >= 1 && bufferSequenceNumber <= buffers.size())
       {
-         handle h = new handle();
-         h.assign(buffers.get(idx - 1));
-         return h;
+         return buffers.get(bufferSequenceNumber - 1);
       }
-      
+
       String errMsg = "Query method argument must be the name of a query buffer or an integer " +
-                      "from 1 to %d for query %s";
+         "from 1 to %d for query %s";
       errMsg = String.format(errMsg, numBuffers().intValue(), qname);
 
       ErrorManager.recordOrShowError(7361, errMsg, false, false, false);
 
-      return new handle();
+      return null;
    }
 
    /**

=== modified file 'src/com/goldencode/p2j/persist/RecordBuffer.java'
--- old/src/com/goldencode/p2j/persist/RecordBuffer.java	2022-11-03 00:24:27 +0000
+++ new/src/com/goldencode/p2j/persist/RecordBuffer.java	2023-01-13 11:07:29 +0000
@@ -7206,7 +7206,7 @@
       }
       
       TempTable table = getParentTable();
-      Buffer buf = table.defaultBufferHandle().unwrapBuffer();
+      Buffer buf = table.defaultBufferHandleNative();
       return get((DataModelObject) buf);
    }
    
@@ -9760,11 +9760,10 @@
              after.isAfterBuffer()    &&
              TempTableBuilder.asTempTable((Temporary) after).isTrackingChanges().getValue())
          {
-            handle hBefore = after.beforeBuffer();
-            if (hBefore != null && !hBefore.isUnknown())
+            BufferImpl before = after.beforeBufferNative();
+            if (before != null)
             {
                // create new before record image, then update my before-rowid and row-state
-               BufferImpl before = (BufferImpl) hBefore.unwrapBuffer();
                before.setUpBeforeBuffer(true);
                before.create();
                RecordBuffer beforeBuf = before.buffer();
@@ -11933,14 +11932,13 @@
                    after.isAfterBuffer()    &&
                    TempTableBuilder.asTempTable((Temporary) after).isTrackingChanges().getValue())
                {
-                  handle hBefore = after.beforeBuffer();
-                  if (!hBefore.isUnknown()) // should not be 
+                  BufferImpl before = after.beforeBufferNative();
+                  if (before != null) // should not be
                   {
                      rowid beforeRowid = peerRowid();
                      if (beforeRowid.isUnknown())
                      {
                         // create new before record image,
-                        BufferImpl before = (BufferImpl) hBefore.unwrapBuffer();
                         before.setUpBeforeBuffer(true);
                         before.create();
                         before.bufferCopy(after);

=== modified file 'src/com/goldencode/p2j/persist/StaticTempTable.java'
--- old/src/com/goldencode/p2j/persist/StaticTempTable.java	2022-06-18 06:25:58 +0000
+++ new/src/com/goldencode/p2j/persist/StaticTempTable.java	2023-01-13 10:21:10 +0000
@@ -155,8 +155,7 @@
          super.namespacePrefix(dmoInfo.namespacePrefix);
       }
       
-      defaultBufferHandle = new handle();
-      defaultBufferHandle.assign(defaultBuffer);
+      this.defaultBuffer = (BufferImpl) defaultBuffer;
       
       TableMapper.mapTemporaryTable(this);
       this.name.assign(dmoInfo.legacyTable);
@@ -1314,11 +1313,29 @@
     */
    public handle defaultBufferHandle()
    {
+      return new handle(defaultBufferHandleNative());
+   }
+
+   /**
+    * Obtain the buffer that was created by default for this temporary table. Every
+    * dynamic temp-table is created with at least one buffer. This buffer object is
+    * returned by this method.
+    *
+    * Note that it cannot be called until the table has been prepared using
+    * <code>tempTablePrepare()</code> method.
+    *
+    * This method is the P2J equivalent of <code>DEFAULT-BUFFER-HANDLE</code>
+    * attribute.
+    *
+    * @return  The default buffer for the temporary table.
+    */
+   public Buffer defaultBufferHandleNative()
+   {
       if (!valid())
          throw new IllegalStateException("Cannot get default buffer handle for the static temp " +
-               "table, the table scope is already closed");
+                                            "table, the table scope is already closed");
 
-      return defaultBufferHandle;
+      return defaultBuffer;
    }
 
    /**
@@ -1423,7 +1440,7 @@
     */
    public boolean valid()
    {
-      return defaultBufferHandle != null;
+      return defaultBuffer != null;
    }
    
    /**
@@ -1496,8 +1513,8 @@
       }
       
       deleteAllBuffers();
-      
-      defaultBufferHandle = null;
+
+      defaultBuffer = null;
       return true;
    }
 

=== modified file 'src/com/goldencode/p2j/persist/TempTable.java'
--- old/src/com/goldencode/p2j/persist/TempTable.java	2022-07-07 16:25:48 +0000
+++ new/src/com/goldencode/p2j/persist/TempTable.java	2023-01-13 10:21:10 +0000
@@ -1059,7 +1059,15 @@
     */
    @LegacyAttribute(name = "BEFORE-TABLE")
    public handle getBeforeTable();
-   
+
+   /**
+    * Get the handle of the before-image table that corresponds to the after-image table
+    * currently associated with this temp-table handle.
+    *
+    * @return  the value of {@code BEFORE-TABLE} as described above.
+    */
+   public TempTable getBeforeTableNative();
+
    /**
     * Get the handle of the after-image table that corresponds to the before-image table
     * currently associated with this temp-table handle.
@@ -1068,7 +1076,15 @@
     */
    @LegacyAttribute(name = "AFTER-TABLE")
    public handle getAfterTable();
-   
+
+   /**
+    * Get the handle of the after-image table that corresponds to the before-image table
+    * currently associated with this temp-table handle.
+    *
+    * @return  the value of {@code AFTER-TABLE} as described above.
+    */
+   public TempTable getAfterTableNative();
+
    /**
     * Set code page supplier for the specified CLOB field.
     *
@@ -1118,7 +1134,15 @@
     */
    @LegacyAttribute(name = "ORIGIN-HANDLE")
    public handle getOriginHandle();
-   
+
+   /**
+    * Get the handle of the TEMP-TABLE in the original source {@code DataSet} object that
+    * corresponds to the TEMP-TABLE currently associated with this TEMP-TABLE handle.
+    *
+    * @return  the current origin table.
+    */
+   public TempTable getOriginTable();
+
    /**
     * Implements the {@code NO-SCHEMA-MARSHAL} attribute getter.
     *

=== modified file 'src/com/goldencode/p2j/persist/TempTableBuilder.java'
--- old/src/com/goldencode/p2j/persist/TempTableBuilder.java	2022-11-21 11:26:19 +0000
+++ new/src/com/goldencode/p2j/persist/TempTableBuilder.java	2023-01-13 10:21:10 +0000
@@ -2846,17 +2846,16 @@
       indexProvider.run();
       
       tempTablePrepare(tableName);
-      BufferImpl buff = (BufferImpl) defaultBufferHandle.getResource();
       if (xmlns != null)
       {
-         buff.namespaceURI(xmlns);
+         defaultBuffer.namespaceURI(xmlns);
       }
       if (xmlPrefix != null)
       {
-         buff.namespacePrefix(xmlPrefix);
+         defaultBuffer.namespacePrefix(xmlPrefix);
       }
       
-      return buff;
+      return defaultBuffer;
    }
 
    /**
@@ -2914,13 +2913,32 @@
     */
    public handle defaultBufferHandle()
    {
+      return new handle(defaultBufferHandleNative());
+   }
+
+   /**
+    * Obtain the buffer that was created by default for this temporary table. Every
+    * dynamic temp-table is created with at least one buffer. This buffer object is
+    * returned by this method.
+    *
+    * Note that it cannot be called until the table has been prepared using
+    * <code>tempTablePrepare()</code> method.
+    *
+    * This method is the P2J equivalent of <code>DEFAULT-BUFFER-HANDLE</code>
+    * attribute.
+    *
+    * @return  The default buffer for the temporary table.
+    */
+   @Override
+   public Buffer defaultBufferHandleNative()
+   {
       if (!_prepared())
       {
          displayNotPrepared();
-         return new handle();
+         return null;
       }
-      
-      return defaultBufferHandle;
+
+      return defaultBuffer;
    }
    
    /**
@@ -2950,7 +2968,7 @@
       
       super.name(name);
       
-      ((BufferImpl) defaultBufferHandle.get()).nameInternal(name);
+      defaultBuffer.nameInternal(name);
    }
    
    /**
@@ -3053,11 +3071,10 @@
    {
       forceClear();
       
-      handle before = getBeforeTable();
-      if (before._isValid())
+      TempTable before = getBeforeTableNative();
+      if (before != null && before.valid())
       {
-         TempTableBuilder ttb = (TempTableBuilder) before.getResource();
-         ttb.delete();
+         before.delete();
       }
       
       deleted = true;
@@ -3482,11 +3499,10 @@
     */
    private void createDefaultBuffer()
    {
-      if (defaultBufferHandle == null)
+      if (defaultBuffer == null)
       {
          Temporary buffer = TemporaryBuffer.createDefaultDynamicBufferForTempTable(this);
-         defaultBufferHandle = new handle();
-         defaultBufferHandle.assign(buffer);
+         defaultBuffer = (BufferImpl) buffer;
       }
    }
    
@@ -3660,7 +3676,7 @@
          helper.deregisterDmoUser(this);
          
          deleteAllBuffers();
-         defaultBufferHandle = null;
+         defaultBuffer = null;
       }
       
       // keep UNIQUE-ID attribute

=== modified file 'src/com/goldencode/p2j/persist/TemporaryBuffer.java'
--- old/src/com/goldencode/p2j/persist/TemporaryBuffer.java	2023-01-10 09:20:39 +0000
+++ new/src/com/goldencode/p2j/persist/TemporaryBuffer.java	2023-01-13 12:29:30 +0000
@@ -2759,12 +2759,10 @@
       TempTable dstTempTable = dstBuf.getParentTable();
       TemporaryBuffer dstB4Buf = null;
       boolean processB4 = false;
-      handle beforeTT = dstTempTable.getBeforeTable();
-      if (beforeTT._isValid())
+      TempTable beforeTT = dstTempTable.getBeforeTableNative();
+      if (beforeTT != null && beforeTT.valid())
       {
-         Temporary dstB4DMO = (Temporary) beforeTT.unwrapTempTable()
-                                                  .defaultBufferHandle()
-                                                  .getResource();
+         Temporary dstB4DMO = (Temporary) beforeTT.defaultBufferHandle().getResource();
          dstB4Buf = (TemporaryBuffer) ((BufferReference) dstB4DMO).buffer();
          processB4 = true;
       }
@@ -4891,10 +4889,8 @@
       //          create parentDst.
       //          copy parentSrc to parentDst
       
-      BufferImpl childSrcBefore = (BufferImpl) childSrc.beforeBuffer().unwrapBuffer();
-      handle hQuery = new handle();
-      QueryWrapper.createQuery(hQuery);
-      P2JQuery query = hQuery.unwrapQuery();
+      BufferImpl childSrcBefore = childSrc.beforeBufferNative();
+      QueryWrapper query = QueryWrapper.createQueryNative(null);
       query.setBuffers(childSrcBefore, parentSrc);
       StringBuilder sb = new StringBuilder();
       sb.append("FOR EACH ");
@@ -4942,7 +4938,7 @@
       finally
       {
          query.queryClose();
-         HandleOps.delete(hQuery);
+         query.delete();
       }
       
       return true;
@@ -6651,9 +6647,10 @@
             // create a copy of this temp-table and assign it to this handle
             TempTableBuilder.create(outputParameter.getTableHandle());
             TempTableBuilder ttDst = (TempTableBuilder) outputParameter.getTableHandle().getResource();
-            handle htSrc = ((TemporaryBuffer) ((BufferReference) tempDMO).buffer()).tableHandle();
+            TempTable tSrc = (((BufferReference) tempDMO).buffer()).tableHandleResource();
+            handle htSrc = new handle(tSrc);
             ttDst.createLike(htSrc);
-            ttDst.tempTablePrepare(htSrc.unwrapTempTable().name());
+            ttDst.tempTablePrepare(tSrc.name());
             logical res = ttDst.copyTempTable(htSrc);
             if (!res.booleanValue())
             {
@@ -7209,10 +7206,9 @@
          // if this is the buffer of an active AFTER-BUFFER, update the BEFORE-TABLE, too:
          if (b4Copy != null)
          {
-            handle hBefore = after.beforeBuffer();
-            if (!hBefore.isUnknown()) 
+            BufferImpl before = after.beforeBufferNative();
+            if (before != null)
             {
-               BufferImpl before = (BufferImpl) hBefore.unwrapBuffer();
                before.setUpBeforeBuffer(true);
                RecordBuffer b4Buffer = before.buffer();
                if (b4Rowid != null && !b4Rowid.isUnknown())

=== modified file 'src/com/goldencode/p2j/persist/serial/JsonExport.java'
--- old/src/com/goldencode/p2j/persist/serial/JsonExport.java	2022-10-06 08:18:44 +0000
+++ new/src/com/goldencode/p2j/persist/serial/JsonExport.java	2023-01-13 10:21:10 +0000
@@ -756,7 +756,7 @@
       for (int k = 0; k < ttCount; k++)
       {
          // if there are no active relation with [after] as child buffer, serialize it now
-         BufferImpl after = (BufferImpl) dataSet.bufferHandle(k + 1).getResource();
+         BufferImpl after = dataSet.getBufferByIndex(k + 1);
          TemporaryBuffer buffer = (TemporaryBuffer) after.buffer();
          if (buffer.count() > 0)
          {
@@ -1028,7 +1028,7 @@
       boolean hasChanges = false;
       for (int k = 0; k < ttCount; k++)
       {
-         BufferImpl after = (BufferImpl) dataSet.bufferHandle(k + 1).getResource();
+         BufferImpl after = dataSet.getBufferByIndex(k + 1);
          if (!after.isAfterBuffer())
          {
             continue; // SIMPLE buffers don't have changes

=== modified file 'src/com/goldencode/p2j/persist/serial/XmlExport.java'
--- old/src/com/goldencode/p2j/persist/serial/XmlExport.java	2022-11-23 11:45:42 +0000
+++ new/src/com/goldencode/p2j/persist/serial/XmlExport.java	2023-01-13 12:32:10 +0000
@@ -356,7 +356,7 @@
          boolean hasChanges = false;
          nextBuffer: for (int k = 0; k < ttCount; k++)
          {
-            BufferImpl after = (BufferImpl) dataSet.bufferHandle(k + 1).getResource();
+            BufferImpl after = dataSet.getBufferByIndex(k + 1);
             List<DataRelation> rels = dataSet.getRelations(after, false, true, true);
             for (DataRelation rel : rels)
             {
@@ -1402,7 +1402,7 @@
             {
                indent();
                String prefix1 = nsPrefix == null || "".equals(nsPrefix) ? "" : nsPrefix + ":";
-               String prefix2 = tables.get(rel.getChildBuffer().unwrapBuffer().name().toJavaType()).
+               String prefix2 = tables.get(rel.getChildBufferNative().name().toJavaType()).
                                        namespacePrefix();
                if (prefix2 == null || "".equals(prefix2))
                {
@@ -1423,8 +1423,7 @@
                   indent();
                   writer.writeStartElement("xsd:selector");
                   writer.writeAttribute("xpath", 
-                           ".//" + prefix2 + rel.getChildBuffer().unwrapBuffer().
-                           name().toJavaType());
+                           ".//" + prefix2 + rel.getChildBufferNative().name().toJavaType());
                   writer.writeEndElement();
                   lineBreak();
                   
@@ -1540,8 +1539,10 @@
                         {
                            writer.writeAttribute("prodata:nested", "true");
                         }
-                        writer.writeAttribute("prodata:parent", rel.getParentBuffer().unwrap().name().toStringMessage());
-                        writer.writeAttribute("prodata:child", rel.getChildBuffer().unwrap().name().toStringMessage());
+                        writer.writeAttribute("prodata:parent",
+                                              rel.getParentBufferNative().name().toStringMessage());
+                        writer.writeAttribute("prodata:child",
+                                              rel.getChildBufferNative().name().toStringMessage());
                         writer.writeAttribute("prodata:relationFields", rel.getRelationFields().toStringMessage());
                         lineBreak();
                      }

=== modified file 'src/com/goldencode/p2j/persist/serial/XmlImport.java'
--- old/src/com/goldencode/p2j/persist/serial/XmlImport.java	2022-11-23 11:45:42 +0000
+++ new/src/com/goldencode/p2j/persist/serial/XmlImport.java	2023-01-13 10:21:10 +0000
@@ -484,7 +484,7 @@
                            boolean found = false;
                            for (int i = 1; i <= numBuf; i++)
                            {
-                              buffer = (BufferImpl) ds.bufferHandle(i).getResource();
+                              buffer = ds.getBufferByIndex(i);
                               if (buffer.getSerializeName().toStringMessage().equalsIgnoreCase(name) || 
                                   buffer.name().toStringMessage().equalsIgnoreCase(name))
                               {
@@ -1267,7 +1267,7 @@
                         // fields are matching each other:
                         for (int k = 0; k < numTables; k++)
                         {
-                           BufferImpl buff = (BufferImpl) ds.bufferHandle(k + 1).getResource();
+                           BufferImpl buff = ds.getBufferByIndex(k + 1);
                            
                            TempTableSchema schema =
                                  new TempTableSchema((TemporaryBuffer) buff.buffer(), false);

=== modified file 'src/com/goldencode/p2j/ui/BrowseColumnWidget.java'
--- old/src/com/goldencode/p2j/ui/BrowseColumnWidget.java	2022-08-25 23:57:15 +0000
+++ new/src/com/goldencode/p2j/ui/BrowseColumnWidget.java	2023-01-13 10:27:02 +0000
@@ -3456,8 +3456,9 @@
    {
       try
       {
-         BufferFieldImpl field = (BufferFieldImpl) DBUtils.getMatchingBufferField(getBrowse().getQuery(),
-                                                                                  fullFieldName);
+         BufferFieldImpl field =
+            (BufferFieldImpl) DBUtils.getMatchingBufferField((QueryWrapper) getBrowse().getQuery(),
+                                                             fullFieldName);
          BufferImpl buffer = (BufferImpl) field.bufferHandle().unwrapBuffer();
          return new FieldReference(buffer.buffer().getDMOProxy(), field.getProperty());
       }

=== modified file 'src/com/goldencode/p2j/util/AppServerHelper.java'
--- old/src/com/goldencode/p2j/util/AppServerHelper.java	2022-11-14 15:55:42 +0000
+++ new/src/com/goldencode/p2j/util/AppServerHelper.java	2023-01-13 10:21:10 +0000
@@ -3273,7 +3273,7 @@
                      int bufCnt = ds.numBuffers().intValue();
                      for (int k = 0; k < bufCnt; k++)
                      {
-                        Buffer dstBuf = ds.bufferHandle(k + 1).unwrapBuffer();
+                        Buffer dstBuf = ds.getBufferByIndex(k + 1);
                         Temporary dstDMO = TemporaryBuffer.getDefaultBuffer(dstBuf.tableHandle());
                         TableWrapper src = remoteResult.getTableWrapper(k);
                         

=== modified file 'src/com/goldencode/p2j/util/WidgetPool.java'
--- old/src/com/goldencode/p2j/util/WidgetPool.java	2022-10-10 09:11:45 +0000
+++ new/src/com/goldencode/p2j/util/WidgetPool.java	2023-01-13 18:20:44 +0000
@@ -461,21 +461,43 @@
     */
    public static void addResource(WrappedResource resource, character name)
    {
+      addResourceNative(resource, name == null || name.isUnknown() ? null : name.toStringMessage());
+   }
+
+   /**
+    * Adds the specified resource to the pool. Although this is exposed for the public, do not
+    * used outside of P2J code. Is made public because access to it is needed from any P2J
+    * package.
+    *
+    * @param    resource
+    *           The resource to be pooled.
+    * @param    name
+    *           The pool name, set to <code>null</code> if the unnamed pool is to be used.
+    *
+    * @throws   IllegalStateException
+    *           The exception is throw if the call of this method targets a named pool (the
+    *           <code>name</code> parameter is specified) and either the name is unknown or a pool
+    *           with the specified name does not exist.
+    *           <p>
+    *           If the exception is thrown, there must be an error in the code which creates the
+    *           resource. That code must validate the pool name (by calling
+    *           {@link WidgetPool#validWidgetPool}) before any other resource-related validation
+    *           and before the resource is created.
+    */
+   public static void addResourceNative(WrappedResource resource, String name)
+   {
       WorkArea wa = locate();
-      
-      boolean unnamed = (name == null);
-      String sname = (unnamed ? null : name.toStringMessage());
-      
-      WidgetPoolData data = (name != null && name.isUnknown() ? null 
-                                                              : findActivePool(wa, sname, false));
+
+      WidgetPoolData data = (name == null ? null
+         : findActivePool(wa, name, false));
       if (data == null)
       {
-         if (!unnamed)
+         if (name != null)
          {
-            final String msg = 
+            final String msg =
                "Could not determine named pool '%s'. You need to validate before adding the " +
-               "resource!";
-            throw new IllegalStateException(String.format(msg, sname));
+                  "resource!";
+            throw new IllegalStateException(String.format(msg, name));
          }
 
          // no pool is active, return
@@ -512,23 +534,42 @@
          ErrorManager.recordOrThrowError(3177, errMsg, false);
          return false;
       }
-      
-      String sname = name.toStringMessage();
-      
-      WidgetPoolData data = findActivePool(locate(), sname, false);
+
+      return validWidgetPool(name.toStringMessage());
+   }
+
+   /**
+    * Determine if the specified <code>name</code> targets a known widget pool.
+    * <p>
+    * A missing unnamed pool will be an error.
+    *
+    * @param    name
+    *           The pool name, set to <code>null</code> if the unnamed pool is to be used.
+    *
+    * @return   <code>true</code> if a pool was found with the specified name.
+    */
+   public static boolean validWidgetPool(String name)
+   {
+      // an unnamed widget-pool name is always valid.
+      if (name == null)
+      {
+         return true;
+      }
+
+      WidgetPoolData data = findActivePool(locate(), name, false);
       if (data == null)
       {
          // error is shown only if named pool is not found
-         final String msg = 
+         final String msg =
             "Trying to create a widget in widget-pool '%s', but pool does not exist";
-         ErrorManager.recordOrThrowError(3178, String.format(msg, sname), false);
+         ErrorManager.recordOrThrowError(3178, String.format(msg, name), false);
 
          return false;
       }
-      
+
       return true;
    }
-   
+
    /**
     * Delete all the non-persistent widget-pools associated with the specified procedure.
     * 
@@ -1171,4 +1212,4 @@
          }
       }
    }
-}
\ No newline at end of file
+}

