=== modified file 'src/com/goldencode/p2j/persist/DataSet.java'
--- src/com/goldencode/p2j/persist/DataSet.java	2022-10-31 12:20:33 +0000
+++ src/com/goldencode/p2j/persist/DataSet.java	2022-11-08 09:46:28 +0000
@@ -92,6 +92,7 @@
 **                  an APPEND option.
 **     CA  20220918 Automatically delete top-nav queries created dynamically by the DATASET.
 **     CA  20221031 Added JMX instrumentation for DATASET[-HANDLE] parameter processing.
+**     IAS 20221108 Fixed support for SCHEMA-MARSHAL == NONE.
 */
 
 /*
@@ -151,6 +152,7 @@
 
 import com.goldencode.p2j.jmx.*;
 import com.goldencode.p2j.persist.TemporaryBuffer.CopyTableMode;
+import com.goldencode.p2j.persist.orm.*;
 import com.goldencode.p2j.persist.serial.*;
 import com.goldencode.p2j.security.*;
 import com.goldencode.p2j.util.*;
@@ -673,6 +675,15 @@
                   wrapper = dsSrc.getDatasetWrapper().getTableWrapper(k - 1);
                }
                
+               if (dsSrc.isRemoteParameter()  && !wrapper.isReceivedSchema())
+               {
+                  RecordBuffer rb = ((BufferReference) targetDmo).buffer();
+                  DmoMeta meta = rb.getDmoInfo();
+                  Iterator<Property> props = meta.getFields(false);
+                  List<PropertyDefinition> pdl = new ArrayList<>();
+                  props.forEachRemaining(p -> pdl.add(new PropertyDefinition(p)));
+                  wrapper.setProperties(pdl);
+               }
                TemporaryBuffer.insertAllRows(
                      wrapper,
                      (Temporary) targetDmo,
@@ -851,6 +862,12 @@
          {
             if (dsParam.isByReference() || dsParam.isRemoteParameter())
             {
+               // check if all tables contain schema.
+               if (!dsParam.getDatasetWrapper().getTableDefs().stream().
+                        allMatch(DsTableDefinition::isReceivedSchema))
+               {
+                  ErrorManager.recordOrThrowError(12323);
+               }
                // if [dsParam] is remote, the dataset was rehydrated when [dsParam] was created
                // do not copy now for 2nd time. Since it is an [input] param we can use the 
                // dataset handle directly.
@@ -3899,6 +3916,10 @@
       List<BufferImpl> localBuffers = new ArrayList<>(bufs.length);
       for (Buffer buf : bufs)
       {
+         if (buf == null)
+         {
+            continue;
+         }
          BufferImpl bufRef = ((BufferImpl) buf).ref();
          if (initClass == null)
          {

=== modified file 'src/com/goldencode/p2j/persist/DataSetParameter.java'
--- src/com/goldencode/p2j/persist/DataSetParameter.java	2022-07-27 08:56:51 +0000
+++ src/com/goldencode/p2j/persist/DataSetParameter.java	2022-11-08 09:48:10 +0000
@@ -39,6 +39,7 @@
 **                  INPUT-OUTPUT mode, and the DATASET-HANDLE, DATASET, TABLE-HANDLE or TABLE versions.
 **     CA  20220727 Fixed OO dataset/table parameters (at the method definition and method call) when there is
 **                  an APPEND option.
+**     IAS 20221108 Fixed support for SCHEMA-MARSHAL == NONE. Re-worked indexes (de)serialization.
 */
 
 /*
@@ -541,14 +542,29 @@
          for (int k = 0; k < tableDefs.size(); k++)
          {
             DsTableDefinition tableDef = tableDefs.get(k);
-            
+            if (!tableDef.isReceivedSchema())
+            {
+               continue;
+            }
             if (!tableDef.isBeforeTable())
             {
                Iterator<PropertyDefinition> props = tableDef.propertyIterator();
                String idx = tableDef.getIndexes();
                String xmlns = tableDef.getXmlns();
                String prefix = tableDef.getXmlPrefix();
-               buffs[k] = TempTableBuilder.createRemoteTable(tableDef.getName(), props, idx, xmlns, prefix);
+               List<IndexDefinition> indexDefs = tableDef.getIndexDefs();
+               TempTableBuilder ttb = new TempTableBuilder(); 
+               if (indexDefs != null)
+               {
+                  buffs[k] = ttb.createRemoteTable(tableDef.getName(), 
+                           props, () -> indexDefs.stream().forEach(ix -> ix.addTo(ttb)), 
+                           xmlns, prefix);
+               }
+               else
+               {
+                  buffs[k] = ttb.createRemoteTable(tableDef.getName(), 
+                           props, idx, xmlns, prefix);
+               }
                
                if (tableDef.isAfterTable() && tableDef.getPeerDef() != null)
                {

=== modified file 'src/com/goldencode/p2j/persist/DatasetWrapper.java'
--- src/com/goldencode/p2j/persist/DatasetWrapper.java	2022-11-02 18:21:56 +0000
+++ src/com/goldencode/p2j/persist/DatasetWrapper.java	2022-11-08 09:49:02 +0000
@@ -17,6 +17,7 @@
 **                  (so that relations, schema, etc is done on the server-side).
 **     CA  20221102 Added a static serialization ID - required when enabling AOP method tracing (see 
 **                  p2j.aspects.ltw.MethodTraceAspect).
+**     IAS 20221108 Fixed support for SCHEMA-MARSHAL == NONE.
 */
 
 /*
@@ -572,7 +573,7 @@
          oos.close();
          tw = new TableWrapper();
          tw.readExternal(new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())));
-         
+         tw.receivedSchema = tdef.receivedSchema;
          if (bres != null)
          {
             TableWrapper btw = new TableWrapper(bres);

=== modified file 'src/com/goldencode/p2j/persist/DsTableDefinition.java'
--- src/com/goldencode/p2j/persist/DsTableDefinition.java	2021-07-01 10:04:17 +0000
+++ src/com/goldencode/p2j/persist/DsTableDefinition.java	2022-11-08 09:51:59 +0000
@@ -2,7 +2,7 @@
 ** Module   : DsTableDefinition.java
 ** Abstract : A container for a DataSet Table metadata.
 **
-** Copyright (c) 2019-2021, Golden Code Development Corporation.
+** Copyright (c) 2019-2022, Golden Code Development Corporation.
 **
 ** -#- -I- --Date-- ---------------------------------------Description---------------------------------------
 ** 001 OM  20130708 Created initial version.
@@ -20,6 +20,7 @@
 **     OM  20210309 Do not use DmoMeta as key in TableMapper because temp-tables share the same DmoMeta.
 **     SVL 20210614 Added copyRows parameter.
 **     SVL 20210701 Added clearRows.
+**     IAS 20221108 Fixed support for SCHEMA-MARSHAL == NONE. Re-worked (de)serialization.
 */
 
 /*
@@ -79,6 +80,8 @@
 
 import java.io.*;
 import java.util.*;
+import java.util.stream.*;
+
 import com.goldencode.p2j.util.*;
 import static com.goldencode.p2j.persist.AbstractTempTable.*;
 import static com.goldencode.util.NativeTypeSerializer.*;
@@ -90,6 +93,9 @@
 public class DsTableDefinition
 implements Externalizable
 {
+   /** Flag indicating that table schema was received */  
+   boolean receivedSchema = false;
+
    /** The name of this table. */
    private String name;
    
@@ -126,6 +132,9 @@
    /** The ERROR-STRING attribute for this table definition. */
    private String errorString = null;
    
+   /** List of indexes' descriptors */
+   private List<IndexDefinition> indexDefs = null;
+
    /**
     * A string with all indexes of this table definition encoded as a {@code String}.
     * 
@@ -188,20 +197,16 @@
          case SM_FULL:
          case SM_DEFAULT:
             // full table schema is serialized with table parameter
-            this.indexes = TableMapper.getLegacyIndexInfo(parentTable);
-            this.numIndexes = this.indexes.split("\\.").length;
             this.xmlns = parentTable.namespaceURI().toStringMessage();
             this.xmlPrefix = parentTable.namespacePrefix().toStringMessage();
             this.xmlNodeName = parentTable.getXmlNodeName().toStringMessage();
             // no break, fall through
             
          case SM_MIN:
-            // marshals:
-            //    field names, data types, and extents;
-            //    temp-table ERROR-STRING
-            // does NOT marshal:
-            //    index descriptions
-            //    field information (label, help, field validation expression, and so on (?))
+            this.indexes = TableMapper.getLegacyIndexInfo(parentTable);
+            this.numIndexes = this.indexes.split("\\.").length;
+            this.indexDefs = TableMapper.getLegacyIndexes(parentTable).map(lif -> new IndexDefinition(lif)).
+                     collect(Collectors.toList());
             this.errorString = defBuff.errorString().toStringMessage();
             // no break, fall through
          
@@ -277,6 +282,16 @@
       this.name = name;
    }
    
+   /** 
+    * Check that table schema was received.
+    * 
+    * @return <code>true</code> if table schema was received.
+    */
+   public boolean isReceivedSchema() 
+   {
+      return receivedSchema;
+   }
+
    /**
     * Check whether this is a definition of an AFTER-TABLE.
     * 
@@ -386,6 +401,15 @@
    }
    
    /**
+    * Get List of indexes' descriptors.
+    * @return the List of indexes' descriptors.
+    */
+   public List<IndexDefinition> getIndexDefs()
+   {
+      return indexDefs;
+   }
+
+   /**
     * Sets the XML namespace for this table definition.
     * 
     * @param   xmlns
@@ -502,7 +526,7 @@
                "A custom result set must not be specified when calling this method!");
       }
       
-      return new ArrayList<>(properties);
+      return new ArrayList<>(properties != null ? properties : Collections.emptyList());
    }
    
    /**
@@ -562,39 +586,52 @@
    public final void writeExternal(ObjectOutput out)
    throws IOException
    {
+      boolean writeSchema = schemaMarshalLevel != SM_NONE;
+      out.writeByte(schemaMarshalLevel);
       writeString(out, name);
       out.writeByte(tableType);
-      out.writeByte(numIndexes);
-      writeString(out, indexes);
-      writeString(out, xmlns);
-      writeString(out, xmlPrefix);
-      writeString(out, xmlNodeName);
-      writeString(out, errorString);
-      
-      // write properties as a byte(1) separated list, ended with a byte(0)
-      Set<Integer> blobProps = null;
+      if (writeSchema)
+      {
+         out.writeByte(numIndexes);
+         writeString(out,indexes);
+         writeList(out, indexDefs);
+         writeString(out,xmlns);
+         writeString(out,xmlPrefix);
+      }
+
+      // write properties
+      Set<Integer> blobProps = new HashSet<>();
+      Set<Integer> objectProps = new HashSet<>();
       if (resultSet != null)
       {
          int idx = 0;
          while (resultSet.hasMoreProperties())
          {
             PropertyDefinition property = resultSet.nextProperty();
-            property.setMarshalLevel(schemaMarshalLevel);
-            out.writeByte(1);
-            property.writeExternal(out);
-            
+            if (writeSchema)
+            {
+               property.setMarshalLevel(schemaMarshalLevel);
+               out.writeByte(1);
+               property.writeExternal(out);
+            }
+
             if (property.getType() == blob.class)
             {
-               if (blobProps == null)
-               {
-                  blobProps = new HashSet<>();
-               }
                blobProps.add(idx);
             }
+            else if (object.class.isAssignableFrom(property.getType()))
+            {
+               objectProps.add(idx);
+            }
             idx = idx + 1;
          }
       }
-      out.writeByte(0);
+      if (writeSchema)
+      {
+         out.writeByte(0);
+      }
+      writeIntSet(out, blobProps);
+      writeIntSet(out, objectProps);
       
       // write data 
       if (resultSet != null)
@@ -647,40 +684,29 @@
    throws IOException,
           ClassNotFoundException
    {
+      receivedSchema = in.readByte() != SM_NONE;
       name = readString(in);
       tableType = in.readByte();
-      numIndexes = in.readByte();
-      indexes = readString(in);
-      xmlns = readString(in);
-      xmlPrefix = readString(in);
-      xmlNodeName = readString(in);
-      errorString = readString(in);
-      
-      // read meta info separated by byte(1). The list ends with a byte(0).
-      properties = new ArrayList<>();
-      Set<Integer> blobProps = null;
-      int idx = 0;
-      boolean moreProperties = (in.readByte() == 1); 
-      while (moreProperties) 
+      if (receivedSchema)
       {
-         PropertyDefinition pd = new PropertyDefinition();
-         pd.readExternal(in);
-         properties.add(pd);
-         
-         // check if there are more to read:
-         moreProperties = (in.readByte() == 1);
-
-         if (pd.getType() == blob.class)
+         numIndexes = in.readByte();
+         indexes = readString(in);
+         indexDefs = readList(in, () -> new IndexDefinition());
+         xmlns = readString(in);
+         xmlPrefix = readString(in);
+         properties = new ArrayList<>();
+         while (in.readByte() != 0)
          {
-            if (blobProps == null)
-            {
-               blobProps = new HashSet<>();
-            }
-            blobProps.add(idx);
+            PropertyDefinition pd = new PropertyDefinition();
+            pd.readExternal(in);
+            properties.add(pd);
+            
          }
-         idx = idx + 1;
       }
       
+      Set<Integer> blobProps = readIntSet(in);
+      Set<Integer> objectProps = readIntSet(in);
+      
       // read data
       rows = new ArrayList<>();
       rowsMeta = new ArrayList<>();

=== modified file 'src/com/goldencode/p2j/persist/DynamicTablesHelper.java'
--- src/com/goldencode/p2j/persist/DynamicTablesHelper.java	2022-10-14 12:38:17 +0000
+++ src/com/goldencode/p2j/persist/DynamicTablesHelper.java	2022-11-02 07:54:50 +0000
@@ -79,6 +79,7 @@
 **     OM  20220914 Use MAX-WIDTH to generate custom sized varchar columns.
 **     IAS 20221006 Added RAW type to the switch in the 'generateSchemaAst'.
 **     IAS 20221013 Fixed setting of "serialize-name" and "serialize-hidden annotations".
+**     IAS 20221014 Fixed 'column-codepage' support.
 */
 
 /*
@@ -831,10 +832,10 @@
          {
             tableField.putAnnotation("col_lab", field.getColumnLabel());
          }
-         
-         if (field.getCodePage() != null)
+         String cp = field.getCodePage();
+         if (cp != null && !cp.trim().equals(""))
          {
-            tableField.putAnnotation("codePage", field.getCodePage());
+            tableField.putAnnotation("column-codepage", cp);
          }
 
          if (field.isSerializeHidden())

=== added file 'src/com/goldencode/p2j/persist/IndexDefinition.java'
--- src/com/goldencode/p2j/persist/IndexDefinition.java	1970-01-01 00:00:00 +0000
+++ src/com/goldencode/p2j/persist/IndexDefinition.java	2022-11-04 14:40:16 +0000
@@ -0,0 +1,253 @@
+/*
+** Module   : IndexDefinition.java
+** Abstract : A container for a table index metadata.
+**
+** Copyright (c) 2022, Golden Code Development Corporation.
+**
+** -#- -I- --Date-- ---------------------------------------Description---------------------------------------
+** 001 IAS 20221104 Created initial version.
+*/
+
+/*
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU Affero General Public License as
+** published by the Free Software Foundation, either version 3 of the
+** License, or (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU Affero General Public License for more details.
+**
+** You may find a copy of the GNU Affero GPL version 3 at the following
+** location: https://www.gnu.org/licenses/agpl-3.0.en.html
+** 
+** Additional terms under GNU Affero GPL version 3 section 7:
+** 
+**   Under Section 7 of the GNU Affero GPL version 3, the following additional
+**   terms apply to the works covered under the License.  These additional terms
+**   are non-permissive additional terms allowed under Section 7 of the GNU
+**   Affero GPL version 3 and may not be removed by you.
+** 
+**   0. Attribution Requirement.
+** 
+**     You must preserve all legal notices or author attributions in the covered
+**     work or Appropriate Legal Notices displayed by works containing the covered
+**     work.  You may not remove from the covered work any author or developer
+**     credit already included within the covered work.
+** 
+**   1. No License To Use Trademarks.
+** 
+**     This license does not grant any license or rights to use the trademarks
+**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
+**     of Golden Code Development Corporation. You are not authorized to use the
+**     name Golden Code, FWD, or the names of any author or contributor, for
+**     publicity purposes without written authorization.
+** 
+**   2. No Misrepresentation of Affiliation.
+** 
+**     You may not represent yourself as Golden Code Development Corporation or FWD.
+** 
+**     You may not represent yourself for publicity purposes as associated with
+**     Golden Code Development Corporation, FWD, or any author or contributor to
+**     the covered work, without written authorization.
+** 
+**   3. No Misrepresentation of Source or Origin.
+** 
+**     You may not represent the covered work as solely your work.  All modified
+**     versions of the covered work must be marked in a reasonable way to make it
+**     clear that the modified work is not originating from Golden Code Development
+**     Corporation or FWD.  All modified versions must contain the notices of
+**     attribution required in this license.
+*/
+
+
+package com.goldencode.p2j.persist;
+
+import static com.goldencode.util.NativeTypeSerializer.*; 
+import java.io.*;
+import java.util.*;
+import java.util.stream.*;
+
+import com.goldencode.p2j.persist.TableMapper.*;
+import com.goldencode.p2j.util.*;
+
+/**
+ * Container for a table index metadata. Used to send the metadata of a
+ * DMO to a remote side, when remote appserver calls are involved.
+ */
+public class IndexDefinition
+implements Externalizable
+{
+   /** The legacy name of this index. */
+   private String legacyName;
+   
+   /**
+    * Determine if the index is a primary index: the one with the "primary" annotation or, if
+    * there is no such one, the first in the definition order.
+    */
+   private boolean effectivePrimary;
+   
+   /** Determine if the index is an unique index. */
+   private boolean unique;
+   
+   /** Determine if the index is a word-index index. */
+   private boolean word;
+   
+   /** Index components (fields with sorting directions). */
+   private List<IndexComponentDefinition> components;
+
+   /**
+    * Default c'tor
+    */
+   public IndexDefinition()
+   {
+      
+   }
+
+   /**
+    * Constructor 
+    * @param lii
+    *        ORM index info
+    *        
+    */
+   public IndexDefinition(LegacyIndexInfo lii)
+   {
+      this.legacyName = lii.getLegacyName();
+      this.effectivePrimary = lii.isEffectivePrimary();
+      this.unique = lii.isUnique();
+      this.word = lii.isWord();
+      this.components = lii.indexComponents().map(lici -> new IndexComponentDefinition(lici)).
+                                              collect(Collectors.toList());
+   }
+   
+   /**
+    * Add index to the <code>TableBuilder</code>
+    * @param tb
+    *        <code>TableBuilder</code> instance.
+    */
+   public void addTo(TempTableBuilder tb)
+   {
+      
+      tb.addNewIndex(new character(legacyName),
+                     new logical(unique),
+                     new logical(effectivePrimary),
+                     new logical(word));
+      components.stream().forEach(
+               c -> tb.addFieldToIndex(legacyName, 
+                                       c.fieldLegacyName, 
+                                       c.effectiveDescending ? "desc" : "asc"));
+   }
+   
+   /**
+    * Read the index definition from the specified input source.
+    * 
+    * @param    in
+    *           The input source from which the index definition will be read.
+    *
+    * @throws   IOException
+    *           In case of I/O errors.
+    *
+    * @throws  ClassNotFoundException
+    *          If the class of property could not be found/loaded.
+    */
+   @Override
+   public void readExternal(ObjectInput in) 
+   throws IOException, 
+          ClassNotFoundException
+   {
+      legacyName = readString(in);
+      byte flags = in.readByte();
+      effectivePrimary = (flags & 1) != 0;
+      unique = (flags & 2) != 0;
+      word = (flags & 4) != 0;
+      components = readList(in, () -> new IndexComponentDefinition());
+   }
+
+   /**
+    * Send the index definition to the specified output destination.
+    * 
+    * @param    out
+    *           The output destination to which the index definition will be sent.
+    *
+    * @throws   IOException
+    *           In case of I/O errors.
+    */
+   @Override
+   public void writeExternal(ObjectOutput out) 
+   throws IOException
+   {
+      writeString(out, legacyName);
+      out.writeByte((effectivePrimary ? 1 : 0) | (unique ? 2 : 0) | (word ? 1 : 0));
+      writeList(out, components);
+   }
+
+   /** A container with an index component information. */
+   public static class IndexComponentDefinition
+   implements Externalizable
+   {
+      /** The legacy name of the field participating in the index. */
+      private String fieldLegacyName;
+      
+      /** Determines if this component has descending sorting. */
+      private boolean effectiveDescending;
+      
+      /**
+       * Default c'tor
+       */
+      public IndexComponentDefinition()
+      {
+         
+      }
+      /**
+       * Constructor
+       * @param lici
+       *        DMO ORM index component info.
+       */
+      public IndexComponentDefinition(LegacyIndexComponentInfo lici)
+      {
+         this.fieldLegacyName = lici.fieldLegacyName;
+         this.effectiveDescending = lici.effectiveDescending;
+      }
+      
+
+      
+      /**
+       * Read the index definition from the specified input source.
+       * 
+       * @param    in
+       *           The input source from which the index component definition will be read.
+       *
+       * @throws   IOException
+       *           In case of I/O errors.
+       *
+       * @throws  ClassNotFoundException
+       *          If the class of property could not be found/loaded.
+       */
+      @Override
+      public void readExternal(ObjectInput in) 
+      throws IOException, 
+             ClassNotFoundException
+      {
+         fieldLegacyName = readString(in);
+         effectiveDescending = in.readByte() != 0;
+      }
+
+      /**
+       * Send the index definition to the specified output destination.
+       * 
+       * @param    out
+       *           The output destination to which the index component definition will be sent.
+       *
+       * @throws   IOException
+       *           In case of I/O errors.
+       */
+      @Override
+      public void writeExternal(ObjectOutput out) 
+               throws IOException
+      {
+         writeString(out, fieldLegacyName);
+         out.writeByte(effectiveDescending ? 1 : 0);
+      }
+   }
+}

=== modified file 'src/com/goldencode/p2j/persist/PropertyDefinition.java'
--- src/com/goldencode/p2j/persist/PropertyDefinition.java	2022-09-09 15:48:28 +0000
+++ src/com/goldencode/p2j/persist/PropertyDefinition.java	2022-11-02 10:39:37 +0000
@@ -17,6 +17,8 @@
 **     SVL 20201030 Added format, label and columnLabel fields.
 **     OM  20201120 Added SCHEMA-MARSHAL implementation.
 **     CA  20220909 Always marshal the schema, otherwise the remote side will not be able to rebuild the table.
+**     IAS 20221029 Added support for missed properties.
+**     IAS 20221102 Re-worked serialization for SCHEMA-MARSHAL == NONE.
 */
 
 /*
@@ -76,6 +78,10 @@
 
 import java.io.*;
 import java.util.*;
+
+import com.goldencode.p2j.persist.orm.*;
+import com.goldencode.p2j.util.*;
+
 import static com.goldencode.p2j.persist.AbstractTempTable.*;
 import static com.goldencode.util.NativeTypeSerializer.*; 
 
@@ -117,7 +123,25 @@
    
    /** The column label of this property. */
    private String columnLabel;
-   
+
+   /** HELP attribute of this field. */
+   private String help;
+   
+   /** INITIAL attribute of this field. */
+   private String initial;
+
+   /** Flag indicating the field should not be included in serialized output. */
+   private boolean serializeHidden;
+   
+   /** Flag indicating the field is case-sensitive. */
+   private boolean caseSensitive;
+
+   /** Node type of field in XML output. */
+   private String xmlNodeType;
+   
+   /** Code page of the CLOB field. */
+   private String codePage;
+
    /**
     * The SCHEMA-MARSHAL level for the parent  temp-table. It is never {@code SM_DEFAULT} when object is to
     * be serialized. Always {@code SM_DEFAULT} for a read object.
@@ -303,7 +327,31 @@
       this.label = label;
       this.columnLabel = columnLabel;
    }
-   
+
+   /**
+    * Create a new property definition.
+    *
+    * @param    prop
+    *           The ORM field <code>Property</code>.
+    */           
+   public PropertyDefinition(Property prop)
+   {
+      this.name = prop.name;
+      verifyType(prop._fwdType);
+      this.type = prop._fwdType;
+      int extent = prop.index > 0 ? 0 : prop.extent;
+      this.extent = extent == 0 ? NO_EXTENT : extent;
+      this.legacyName = prop.legacy;
+      this.format = prop.format;
+      this.label = prop.label;
+      this.columnLabel = prop.columnLabel;
+      this.help = prop.help;
+      this.initial = prop.initial;
+      this.serializeHidden = prop.serializeHidden;
+      this.caseSensitive = prop.caseSensitive;
+      this.xmlNodeType = prop.xmlNodeType;
+      this.codePage = prop.codePage;
+   }
    /**
     * Get the type of this property.
     * 
@@ -385,6 +433,67 @@
    }
 
    /**
+    * Get help text of this property.
+    *
+    * @return help text of this property.
+    */
+   public String getHelp()
+   {
+      return help;
+   }
+
+   /**
+    * Get initial value of this property.
+    *
+    * @return initial value of this property.
+    */
+   public String getInitial()
+   {
+      return initial;
+   }
+
+   /**
+    * Get 'serialize hidden' flag of this property.
+    *
+    * @return 'serialize hidden' flag of this property.
+    */
+   public boolean isSerializeHidden()
+   {
+      return serializeHidden;
+   }
+
+   /**
+    * Get 'case-sensitive' flag of this property.
+    *
+    * @return 'case-sensitive' flag of this property.
+    */
+   public boolean isCaseSensitive()
+   {
+      return caseSensitive;
+   }
+
+   
+   /**
+    * Get XML node type of this property.
+    *
+    * @return XML node type of this property.
+    */
+   public String getXmlNodeType()
+   {
+      return xmlNodeType;
+   }
+
+   /**
+    * Get code page of this property.
+    *
+    * @return code page of this property.
+    */
+   public String getCodePage()
+   {
+      return codePage;
+   }
+
+   /**
     * Send the property definition to the specified output destination.
     * 
     * @param    out
@@ -396,18 +505,30 @@
    public final void writeExternal(ObjectOutput out)
    throws IOException
    {
+      if (schemaMarshalLevel == SM_NONE)
+      {
+         throw new IllegalStateException("Should not be called if schemaMarshalLevel == SM_NONE");
+      }
       boolean full = schemaMarshalLevel == SM_FULL || schemaMarshalLevel == SM_DEFAULT;
-      // we can't omit the schema-related field information, as otherwise the remote side will not be able to
-      // recreate the temp-table.
-      boolean none = false; // schemaMarshalLevel == SM_NONE;
       
-      writeString(out, none ? null : name);
-      writeString(out, (type == null || none) ? null : type.getName());
-      out.writeInt(none ? 0 : extent);
-      writeString(out, none ? null : legacyName);
-      writeString(out, full ? format : null);
-      writeString(out, full ? label : null);
-      writeString(out, full ? columnLabel : null);
+      writeString(out, name);
+      writeString(out, legacyName);
+      writeString(out, type == null ? null : type.getName());
+      out.writeInt(extent);
+      writeString(out, initial);
+      out.writeByte(serializeHidden ? 1 : 0);
+      out.writeByte(caseSensitive ? 1 : 0);
+      writeString(out, xmlNodeType);
+      writeString(out, codePage);
+      out.writeByte(full ? 1 : 0);
+      if (!full )
+      {
+         return;
+      }
+      writeString(out, format);
+      writeString(out, label);
+      writeString(out, columnLabel);
+      writeString(out, help);
    }
    
    /**
@@ -427,13 +548,24 @@
           ClassNotFoundException
    {
       name = readString(in);
+      legacyName = readString(in);
       String tn = readString(in);
       type = (tn == null) ? null : Class.forName(tn);
       extent = in.readInt();
-      legacyName = readString(in);
+      initial = readString(in);
+      serializeHidden = in.readByte() == 1;
+      caseSensitive = in.readByte() == 1;
+      xmlNodeType = readString(in);
+      codePage = readString(in);
+      boolean full = in.readByte() == 1;
+      if (!full)
+      {
+         return;
+      }
       format = readString(in);
       label = readString(in);
       columnLabel = readString(in);
+      help = readString(in);
    }
    
    /**

=== modified file 'src/com/goldencode/p2j/persist/TableMapper.java'
--- src/com/goldencode/p2j/persist/TableMapper.java	2022-10-31 12:20:33 +0000
+++ src/com/goldencode/p2j/persist/TableMapper.java	2022-11-04 14:15:48 +0000
@@ -102,7 +102,9 @@
 **     CA  20220601 getIndexFieldNames must return lowercased legacy names.
 **     OM  20220914 Added MAX-WIDTH support for CHARACTER fields.
 **     IAS 20221006 Added 'definedFormat' and 'definedLabel'.
+**     IAS 20221018 Fixed processing of 'now' and 'today' INITIAL attribute value.
 **     CA  20221031 Added JMX instrumentation for 'mapTemporaryTable'.
+*      IAS 20222204 Added 'indexComponents()' and 'getLegacyIndexes' methods.
 */
 
 /*
@@ -163,6 +165,7 @@
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.stream.Stream;
 
 import com.goldencode.p2j.persist.annotation.*;
 import com.goldencode.p2j.persist.annotation.Trigger;
@@ -788,6 +791,22 @@
    }
    
    /**
+    * Get stream for the indexes associated with the given temporary table.
+    *
+    * @param    tt
+    *           Temp table object.
+    * @return   stream for the indexes associated with the given temporary table.
+    */
+   public static Stream<TableMapper.LegacyIndexInfo> getLegacyIndexes(TempTable tt)
+   {
+      TempTableMapper mapper = locateTemp(tt);
+      
+      synchronized (mapper)
+      {
+         return mapper.legacyIndexInfo(tt);
+      }
+   }
+   /**
     * Get information about the index associated with the DMO referenced by the given buffer,
     * as a string.
     *
@@ -2663,6 +2682,19 @@
       }
       
       /**
+       * Get stream for the indexes associated with the given temporary table.
+       *
+       * @param    tt
+       *           Temp table object.
+       * @return   stream for the indexes associated with the given temporary table.
+       */
+      private Stream<LegacyIndexInfo> legacyIndexInfo(TempTable tt)
+      {
+         LegacyTableInfo tableInfo = p2j.get(tt);
+         return new ArrayList<>(tableInfo.idx).stream();
+      }
+
+      /**
        * Get the legacy index name of converted index, which is defined by the specified backing
        * temp table.
        *
@@ -2882,7 +2914,7 @@
                   {
                      if ("today".equalsIgnoreCase(text))
                      {
-                        initialValue = date.today();
+                        initialValue = new character(text);
                      }
                      else
                      {
@@ -2893,7 +2925,7 @@
                   {
                      if ("now".equalsIgnoreCase(text))
                      {
-                        initialValue = datetime.now();
+                        initialValue = new character(text);
                      }
                      else if (text.toUpperCase().indexOf('T') > 0)
                      {
@@ -2910,7 +2942,7 @@
                   {
                      if ("now".equalsIgnoreCase(text))
                      {
-                        initialValue = datetimetz.now();
+                        initialValue = new character(text);
                      }
                      else if (text.toUpperCase().indexOf('T') > 0)
                      {
@@ -3118,6 +3150,15 @@
       }
       
       /**
+       * Get a stream for the index components.
+       * 
+       * @return iterator for the index components.
+       */
+      public Stream<LegacyIndexComponentInfo> indexComponents()
+      {
+         return Arrays.stream(components);
+      }
+      /**
        * Returns index information as a string. Format of this string is described in
        * {@link Buffer#indexInformation(int)}
        *
@@ -3216,10 +3257,10 @@
    static class LegacyIndexComponentInfo
    {
       /** The legacy name of the field participating in the index. */
-      private final String fieldLegacyName;
+      public final String fieldLegacyName;
       
       /** Determines if this component has descending sorting. */
-      private final boolean effectiveDescending;
+      public final boolean effectiveDescending;
       
       /**
        * Create a new index component information container, holding field name and sorting

=== modified file 'src/com/goldencode/p2j/persist/TableWrapper.java'
--- src/com/goldencode/p2j/persist/TableWrapper.java	2022-06-02 12:57:09 +0000
+++ src/com/goldencode/p2j/persist/TableWrapper.java	2022-11-07 14:08:36 +0000
@@ -28,6 +28,9 @@
 **                  (so that relations, schema, etc is done on the server-side).
 **     CA  20220428 Allow null peerDef at setPeerDef.
 **     CA  20220602 Added basic support for transport of object instances over appserver call.
+**     IAS 20221029 Added support for the SCHEMA-MARSHAL attribute.
+**     IAS 20221102 Re-worked (de)serialization.
+**     IAS 20221104 Added structured indexes data.
 */
 
 /*
@@ -86,11 +89,16 @@
 package com.goldencode.p2j.persist;
 
 import static com.goldencode.util.NativeTypeSerializer.*; 
+import static com.goldencode.p2j.persist.AbstractTempTable.*;
+
 import java.io.*;
 import java.lang.reflect.Array;
 import java.util.*;
+import java.util.stream.*;
 
+import com.goldencode.p2j.oo.lang.*;
 import com.goldencode.p2j.util.*;
+import com.goldencode.util.*;
 
 /**
  * Any {@link TableResultSet} instance will be wrapped in a {@link TableWrapper} instance before
@@ -122,6 +130,12 @@
 
    /** Table name. */
    private String tableName;
+   
+   /** Flag indicating that table schema was received */  
+   boolean receivedSchema = false;
+   
+   /** Table SCHEMA-MARSHAL attribute value encodes as int */ 
+   private int schemaMarshalLevel;
 
    /**
     * Determines if this wrapper wraps data from a TABLE-HANDLE parameter. Necessary because of
@@ -159,6 +173,9 @@
     */
    private String indexes = null;
 
+   /** List of indexes' descriptors */
+   private List<IndexDefinition> indexDefs = null;
+   
    /** Flag indicating if the source is a JSON table. */
    private boolean fromJson = false;
    
@@ -423,6 +440,15 @@
    }
    
    /**
+    * Get List of indexes' descriptors.
+    * @return the List of indexes' descriptors.
+    */
+   public List<IndexDefinition> getIndexDefs()
+   {
+      return indexDefs;
+   }
+
+   /**
     * Get the {@link #xmlns XML namespace}.
     * 
     * @return   See above.
@@ -573,7 +599,8 @@
            "A custom result set must not be specified when calling this method!");
       }
 
-      return new ArrayList<PropertyDefinition>(properties);
+      return new ArrayList<PropertyDefinition>(
+               properties != null ? properties : Collections.emptyList());
    }
 
    /**
@@ -682,53 +709,60 @@
          return;
       }
 
-      writeString(out, tableName);
-      out.writeByte(tableType);
-      out.writeByte(numIndexes);
-      writeString(out,indexes);
-      writeString(out,xmlns);
-      writeString(out,xmlPrefix);
+      boolean writeSchema = schemaMarshalLevel != SM_NONE;
+      out.writeByte(schemaMarshalLevel);
+      if (writeSchema)
+      {
+         writeString(out, tableName);
+         out.writeByte(tableType);
+         out.writeByte(numIndexes);
+         writeString(out,indexes);
+         writeList(out, indexDefs);
+         writeString(out,xmlns);
+         writeString(out,xmlPrefix);
+      }
 
       // write properties
-      Set<Integer> blobProps = null;
-      Set<Integer> objectProps = null;
+      Set<Integer> blobProps = new HashSet<>();
+      Set<Integer> objectProps = new HashSet<>();
       if (resultSet != null)
       {
          int idx = 0;
          while (resultSet.hasMoreProperties())
          {
             PropertyDefinition property = resultSet.nextProperty();
-            out.writeByte(1);
-            property.writeExternal(out);
+            if (writeSchema)
+            {
+               property.setMarshalLevel(schemaMarshalLevel);
+               out.writeByte(1);
+               property.writeExternal(out);
+            }
 
             if (property.getType() == blob.class)
             {
-               if (blobProps == null)
-               {
-                  blobProps = new HashSet<>();
-               }
                blobProps.add(idx);
             }
             else if (object.class.isAssignableFrom(property.getType()))
             {
-               if (objectProps == null)
-               {
-                  objectProps = new HashSet<>();
-               }
                objectProps.add(idx);
             }
             idx = idx + 1;
          }
       }
-      out.writeByte(0);
-   
+      if (writeSchema)
+      {
+         out.writeByte(0);
+      }
+      writeIntSet(out, blobProps);
+      writeIntSet(out, objectProps);
+
       // write data 
       if (resultSet != null)
       {
          while (resultSet.hasMoreRows())
          {
             Object[] row = resultSet.nextRow();
-            if (blobProps != null)
+            if (!blobProps.isEmpty())
             {
                Object[] row2 = new Object[row.length];
                System.arraycopy(row, 0, row2, 0, row2.length);
@@ -743,7 +777,7 @@
                row = row2;
             }
             
-            if (objectProps != null)
+            if (!objectProps.isEmpty())
             {
                Object[] row2 = new Object[row.length];
                System.arraycopy(row, 0, row2, 0, row2.length);
@@ -751,7 +785,7 @@
                {
                   if (row2[idx] instanceof object)
                   {
-                     row2[idx] = new LegacyObject((object) row2[idx]);
+                     row2[idx] = new LegacyObject((object<?>) row2[idx]);
                   }
                }
                
@@ -781,7 +815,9 @@
     * @throws   IOException
     *           In case of I/O errors.
     * @throws   ClassNotFoundException 
+    *          If the class of property could not be found/loaded.
     */
+   @Override
    public final void readExternal(ObjectInput in)
    throws IOException,
           ClassNotFoundException
@@ -802,47 +838,28 @@
          return;
       }
       
-      tableName = readString(in);
-      tableType = in.readByte();
-
-      numIndexes = in.readByte();
-      indexes = readString(in);
-      xmlns = readString(in);
-      xmlPrefix = readString(in);
-      
-      Set<Integer> blobProps = null;
-      Set<Integer> objectProps = null;
-      int idx = 0;
-      properties = new ArrayList<>();
-      do
+      receivedSchema = in.readByte() != SM_NONE;
+      if (receivedSchema)
       {
-         if (in.readByte() == 0)
-         {
-            break;
-         }
-         PropertyDefinition pd = new PropertyDefinition();
-         pd.readExternal(in);
-         properties.add(pd);
-         
-         if (pd.getType() == blob.class)
-         {
-            if (blobProps == null)
-            {
-               blobProps = new HashSet<>();
-            }
-            blobProps.add(idx);
-         }
-         if (object.class.isAssignableFrom(pd.getType()))
-         {
-            if (objectProps == null)
-            {
-               objectProps = new HashSet<>();
-            }
-            objectProps.add(idx);
-         }
-         idx = idx + 1;
+         tableName = readString(in);
+         tableType = in.readByte();
+         numIndexes = in.readByte();
+         indexes = readString(in);
+         indexDefs = readList(in, () -> new IndexDefinition());
+         xmlns = readString(in);
+         xmlPrefix = readString(in);
+         properties = new ArrayList<>();
+         while (in.readByte() != 0)
+         {
+            PropertyDefinition pd = new PropertyDefinition();
+            pd.readExternal(in);
+            properties.add(pd);
+            
+         }
       }
-      while (true);
+      
+      Set<Integer> blobProps = readIntSet(in);
+      Set<Integer> objectProps = readIntSet(in);
       
       // read data
       rows = new ArrayList<>();
@@ -857,23 +874,13 @@
          
          Object[] row = (Object[]) next;
          rows.add(row);
-         if (blobProps != null)
-         {
-            for (Integer i : blobProps)
-            {
-               row[i] = new blob(((MemoryBuffer) row[i]).getValue());
-            }
-         }
-         if (objectProps != null)
-         {
-            for (Integer i : objectProps)
-            {
-               LegacyObject ref = (LegacyObject) row[i];
-               ObjectVar v = new ObjectVar(ref.getType());
-               v.assign(ref.restore());
-               row[i] = v;
-            }
-         }
+         blobProps.stream().forEach(i -> row[i] = new blob(((MemoryBuffer) row[i]).getValue()));
+         objectProps.stream().forEach(i -> {
+            LegacyObject ref = (LegacyObject) row[i];
+            ObjectVar<? extends _BaseObject_> v = new ObjectVar<>(ref.getType());
+            v.assign(ref.restore());
+            row[i] = v;
+         });
 
          next = in.readObject();
          rowsMeta.add((Object[]) next);
@@ -890,6 +897,16 @@
       }
    }
 
+   /** 
+    * Check that table schema was received.
+    * 
+    * @return <code>true</code> if table schema was received.
+    */
+   public boolean isReceivedSchema() 
+   {
+      return receivedSchema;
+   }
+
    /**
     * Determines if this wrapper wraps data from a TABLE-HANDLE parameter.
     *
@@ -921,6 +938,25 @@
       this.tableHandle = tableHandle;
    }
 
+   /** Get encoded table SCHEMA-MARSHAL attribute value.
+    * 
+    * @return encoded table SCHEMA-MARSHAL attribute value.
+    */
+   public int getSchemaMarshalLevel()
+   {
+      return schemaMarshalLevel;
+   }
+
+   /** Set encoded table SCHEMA-MARSHAL attribute value.
+    * 
+    * @param schemaMarshalLevel 
+    *        encoded table SCHEMA-MARSHAL attribute value.
+    */
+   public void setSchemaMarshalLevel(int schemaMarshalLevel)
+   {
+      this.schemaMarshalLevel = schemaMarshalLevel;
+   }
+
    /**
     * Initialize this wrapper with the info from the given temp-table.
     * 
@@ -933,6 +969,8 @@
       Buffer defBuff = (Buffer) table.defaultBufferHandle().getResource();
       this.indexes = TableMapper.getLegacyIndexInfo(table);
       this.numIndexes = indexes.split("\\.").length; // TODO: "." or "\\." ?
+      this.indexDefs = TableMapper.getLegacyIndexes(table).map(lif -> new IndexDefinition(lif)).
+                                                           collect(Collectors.toList());
       this.xmlns = defBuff.namespaceURI().toStringMessage();
       this.xmlPrefix = defBuff.namespacePrefix().toStringMessage();
    }

=== modified file 'src/com/goldencode/p2j/persist/TempTableBuilder.java'
--- src/com/goldencode/p2j/persist/TempTableBuilder.java	2022-10-14 12:38:17 +0000
+++ src/com/goldencode/p2j/persist/TempTableBuilder.java	2022-11-08 09:26:37 +0000
@@ -122,6 +122,9 @@
 **     OM  20220914 Added MAX-WIDTH support for CHARACTER fields.
 **     IAS 20221003 Fixed default value of the PRIMARY attribute
 **     IAS 20221014 Added COMHANDLE to the 'datatypesMatchLen' map
+**     IAS 20221029 Added support for missed properties.
+**     IAS 20221104 Added indexes parsing for input remote table.
+**     IAS 20221108 Replaced static 'createRemoteTable' with a regular one.
 */
 
 /*
@@ -313,55 +316,40 @@
     *           The XML namespace.
     * @param    xmlPrefix
     *           The XML prefix.
+    * @return   default buffer for the table
     */
-   public static BufferImpl createRemoteTable(String tableName,
+   public BufferImpl createRemoteTable(String tableName,
                                               Iterator<PropertyDefinition> props,
                                               String tableIndexes, 
                                               String xmlns,
                                               String xmlPrefix)
    {
-      TempTableBuilder ttb = new TempTableBuilder();
-      props.forEachRemaining(ttb::addNewField);
-      
-      if (tableIndexes != null)
-      {
-         String[] indexes = tableIndexes.split("\\.");
-         for (int i = 0; i < indexes.length; i++)
-         {
-            String indexDef = indexes[i];
-            if (indexDef.isEmpty())
-            {
-               continue;
-            }
-            String[] compAndName = indexDef.split(":");
-            String typeAndComps = compAndName[0];
-            String idxName = compAndName[1];
-            String[] comps = typeAndComps.split(",");
-            boolean unique = (i != 0) || "1".equals(comps[0]);
-            boolean primary = (i == 0) && ("1".equals(comps[0]) || "0".equals(comps[0]));
-            
-            ttb.addNewIndex(new character(idxName),
-                            new logical(unique),
-                            new logical(primary));
-            for (int j = (primary ? 1 : 0); j < comps.length; j++)
-            {
-               ttb.addFieldToIndex(idxName, comps[j]);
-            }
-         }
-      }
-      
-      ttb.tempTablePrepare(tableName);
-      BufferImpl buff = (BufferImpl) ttb.defaultBufferHandle().getResource();
-      if (xmlns != null)
-      {
-         buff.namespaceURI(xmlns);
-      }
-      if (xmlPrefix != null)
-      {
-         buff.namespacePrefix(xmlPrefix);
-      }
-      
-      return buff;
+      return createTable(tableName, props, 
+               () -> parseIndexString(tableIndexes), xmlns, xmlPrefix);
+   }
+   
+   /**
+    * Create a temp-table with the specified definition, as received from a remote side.
+    * 
+    * @param    tableName
+    *           The table name.
+    * @param    props
+    *           The property definitions.
+    * @param    indexProvider
+    *           indexes' provider.
+    * @param    xmlns
+    *           The XML namespace.
+    * @param    xmlPrefix
+    *           The XML prefix.
+    * @return   default buffer for the table
+    */
+   public BufferImpl createRemoteTable(String tableName,
+                                              Iterator<PropertyDefinition> props,
+                                              Runnable indexProvider, 
+                                              String xmlns,
+                                              String xmlPrefix)
+   {
+      return createTable(tableName, props, indexProvider, xmlns, xmlPrefix);
    }
    
    /**
@@ -1340,6 +1328,55 @@
                               character    label,
                               character    columnLabel)
    {
+      return addNewField(name, type, extent, format, initial, label, columnLabel,
+               null, null, null, false, false);
+   }
+   /**
+    * Adds a field with the specified properties to the temp-table.
+    * This method is the P2J equivalent of <code>ADD-NEW-FIELD</code> method
+    * of Progress 4GL.
+    * <p>
+    * When a parameter is set to null, it means it was not specified by the business logic.
+    *
+    * @param   name
+    *          The name of the field to be created in the temp-table.
+    * @param   type
+    *          The data type of the specified field.
+    * @param   extent
+    *          An integer expression specifying the extent of an array.
+    * @param   format
+    *          The data format for the defined data type. If empty or unknown, format is
+    *          replaced with default format. Null value means that format is not used in
+    *          ADD-NEW-FIELD.
+    * @param   initial
+    *          An expression that evaluates to the initial value of the defined field.
+    *          TODO: this method will probably be overloaded because of this.
+    * @param   label
+    *          The label of the defined field. If <code>null</code> or unknown the name
+    *          parameter will be used.
+    * @param   columnLabel
+    *          The label of the column associated with the defined field
+    * @param   help 
+    * @param   xmlNodeType 
+    * @param   codePage 
+    * @param   serializeHidden 
+    * @param   caseSensitive 
+    *
+    * @return  <code>true</code> on success.
+    */
+   public logical addNewField(character    name,
+                              character    type,
+                              integer      extent,
+                              character    format,
+                              BaseDataType initial,
+                              character    label,
+                              character    columnLabel,
+                              character    help,
+                              character    xmlNodeType,
+                              character    codePage,
+                              boolean      serializeHidden,
+                              boolean      caseSensitive)
+   {
       addFunctionCalled = true;
       
       if (_prepared())
@@ -1397,12 +1434,16 @@
       
       String labelStr = label != null ? label.getValue() : null;
       String columnLabelStr = columnLabel != null ? columnLabel.getValue() : null;
+      String helpStr = help != null ? help.getValue() : null;
+      String codePageStr = codePage != null ? codePage.getValue() : null;
+      String xmlNodeTypeStr = xmlNodeType != null ? xmlNodeType.getValue() : null;
       
       // Note: case-sensitivity and CLOB code page cannot be specified using P4GL ADD-NEW-FIELD method
       long ext = extent == null || extent.getValue() == 1 ? 0 : extent.getValue();
       P2JField field = new P2JField(fieldName, parmType, ext, formatStr,
-                                    initial, labelStr, columnLabelStr, false, null, null, false, null, null,
-                                    null, null, false, 0, 0);
+                                    initial, labelStr, columnLabelStr, caseSensitive, 
+                                    codePageStr, helpStr, serializeHidden, null, null,
+                                    null, xmlNodeTypeStr, false, 0, 0);
       addField(field);
       return new logical(true);
    }
@@ -2727,6 +2768,70 @@
    }
    
    /**
+    * Create a temp-table with the specified definition.
+    * 
+    * @param    tableName
+    *           The table name.
+    * @param    props
+    *           The property definitions.
+    * @param    tableIndexes
+    *           The index definitions.
+    * @param    xmlns
+    *           The XML namespace.
+    * @param    xmlPrefix
+    *           The XML prefix.
+    * @return   default buffer for the table
+    */
+   public BufferImpl createTable(String tableName,
+                                 Iterator<PropertyDefinition> props,
+                                 String tableIndexes, 
+                                 String xmlns,
+                                 String xmlPrefix)
+   {
+      return  createTable(tableName, props, 
+                          () -> parseIndexString(tableIndexes), xmlns, xmlPrefix);
+   }
+
+   /**
+    * Create a temp-table with the specified definition.
+    * 
+    * @param    tableName
+    *           The table name.
+    * @param    props
+    *           The property definitions.
+    * @param    indexProvider
+    *           indexes' provider.
+    * @param    xmlns
+    *           The XML namespace.
+    * @param    xmlPrefix
+    *           The XML prefix.
+    * @return   default buffer for the table
+    */
+   public BufferImpl createTable(String tableName,
+                                 Iterator<PropertyDefinition> props,
+                                 Runnable indexProvider, 
+                                 String xmlns,
+                                 String xmlPrefix)
+   {
+      props.forEachRemaining(this::addNewField);
+      
+      indexProvider.run();
+      
+      tempTablePrepare(tableName);
+      BufferImpl buff = (BufferImpl) defaultBufferHandle.getResource();
+      if (xmlns != null)
+      {
+         buff.namespaceURI(xmlns);
+      }
+      if (xmlPrefix != null)
+      {
+         buff.namespacePrefix(xmlPrefix);
+      }
+      
+      return buff;
+   }
+
+   /**
     * Build temporary table from a table wrapper object.
     *
     * @param tableWrapper
@@ -2742,14 +2847,23 @@
       {
          return;
       }
-
-      Iterator<PropertyDefinition> iter = tableWrapper.propertyIterator();
-      while(iter.hasNext())
-      {
-         PropertyDefinition propertyDefinition = iter.next();
-         addNewField(propertyDefinition);
-      }
-      tempTablePrepare(tableWrapper.getTableName());
+      List<IndexDefinition> indexDefs = tableWrapper.getIndexDefs();
+      if (indexDefs != null)
+      {
+         createTable(tableWrapper.getTableName(), 
+                  tableWrapper.propertyIterator(), 
+                  () -> indexDefs.stream().forEach(idx -> idx.addTo(this)), 
+                  tableWrapper.getXmlns(), 
+                  tableWrapper.getXmlPrefix());
+      }
+      else
+      {
+         createTable(tableWrapper.getTableName(), 
+                  tableWrapper.propertyIterator(), 
+                  tableWrapper.getIndexes(), 
+                  tableWrapper.getXmlns(), 
+                  tableWrapper.getXmlPrefix());
+      }
       TemporaryBuffer.insertAllRows(tableWrapper,
                                     (Temporary) defaultBufferHandle().getResource(),
                                     true,
@@ -3114,9 +3228,14 @@
                   new character(dataType),
                   extent,
                   new character(propertyDefinition.getFormat()),
-                  null,
+                  new character(propertyDefinition.getInitial()),
                   new character(propertyDefinition.getLabel()),
-                  new character(propertyDefinition.getColumnLabel()));
+                  new character(propertyDefinition.getColumnLabel()),
+                  new character(propertyDefinition.getHelp()),
+                  new character(propertyDefinition.getXmlNodeType()),
+                  new character(propertyDefinition.getCodePage()),
+                  propertyDefinition.isSerializeHidden(),
+                  propertyDefinition.isCaseSensitive());
    }
    
    /**
@@ -3760,6 +3879,42 @@
    }
    
    /**
+    * Add indexes based on multiIxCols string.
+    * 
+    * @param tableIndexes
+    *        multiIxCols string to be parsed.
+    */
+   private void parseIndexString(String tableIndexes)
+   {
+      if (tableIndexes != null)
+      {
+         String[] indexes = tableIndexes.split("\\.");
+         for (int i = 0; i < indexes.length; i++)
+         {
+            String indexDef = indexes[i];
+            if (indexDef.isEmpty())
+            {
+               continue;
+            }
+            String[] compAndName = indexDef.split(":");
+            String typeAndComps = compAndName[0];
+            String idxName = compAndName[1];
+            String[] comps = typeAndComps.split(",");
+            boolean unique = (i != 0) || "1".equals(comps[0]);
+            boolean primary = (i == 0) && ("1".equals(comps[0]) || "0".equals(comps[0]));
+            
+            addNewIndex(new character(idxName),
+                            new logical(unique),
+                            new logical(primary));
+            for (int j = (primary ? 1 : 0); j < comps.length; j++)
+            {
+               addFieldToIndex(idxName, comps[j]);
+            }
+         }
+      }
+   }
+
+   /**
     * Returns a string representation of the object.
     *
     * @return string representation of the object.

=== modified file 'src/com/goldencode/p2j/persist/TempTableResultSet.java'
--- src/com/goldencode/p2j/persist/TempTableResultSet.java	2022-10-06 08:18:44 +0000
+++ src/com/goldencode/p2j/persist/TempTableResultSet.java	2022-11-04 08:12:06 +0000
@@ -31,6 +31,7 @@
 **     SVL 20210701 Added clearRows.
 **     CA  20221006 Do not access tableHandle() in the FWD runtime, get the TempTable instance directly.  
 **                  Refs #6826
+**     IAS 20221029 Re-worked 'init' method.
 */
 
 /*
@@ -189,11 +190,8 @@
     * @param    append
     *           Flag indicating this table is sent in APPEND mode.
     *           
-    * @throws   ClassNotFoundException
-    *           If the type of a property can not be resolved to a class.
     */
    public TempTableResultSet(Temporary dmo, boolean input, boolean output, boolean append)
-//   throws ClassNotFoundException
    {
       this(dmo, input, output, append, true);
    }
@@ -358,11 +356,8 @@
     * TODO: improve this (i.e. use an open cursor or some other alternative to not read the data
     *       in memory)
     * 
-    * @throws   ClassNotFoundException
-    *           If the type of a property can not be resolved to a class.
     */
    private void init(boolean copyRows)
-//   throws ClassNotFoundException
    {
       TemporaryBuffer buffer = (TemporaryBuffer) ((BufferReference) dmo).buffer();
       
@@ -387,45 +382,11 @@
       {
          dmoPropIndex.put(dmoProps[i], i);
       }
-      PropertyDefinition[] props = new PropertyDefinition[dmoProps.length];
       
       Iterator<Property> iter = dmoInfo.getFields(false); // skip properties that are not accessible via the DMO's API.
-      while (iter.hasNext())
-      {
-         Property prop = iter.next();
-         // the Properties whose extent fields were denormalized are treated as simple ones 
-         int extent = prop.index > 0 ? 0 : prop.extent;
-         if (extent == 0)
-         {
-            props[dmoPropIndex.get(prop.name)] = 
-               new PropertyDefinition(prop.name,
-                                      prop._fwdType,
-                                      prop.legacy,
-                                      prop.format,
-                                      prop.label,
-                                      prop.columnLabel);
-         }
-         else
-         {
-            props[dmoPropIndex.get(prop.name)] = 
-               new PropertyDefinition(prop.name,
-                                      prop._fwdType,
-                                      extent,
-                                      prop.legacy,
-                                      prop.format,
-                                      prop.label,
-                                      prop.columnLabel);
-         }
-      }
-      
-      java.util.List<PropertyDefinition> lprops = new ArrayList<>();
-      for (int i = 0; i < props.length; i++)
-      {
-         if (props[i] != null)
-         {
-            lprops.add(props[i]);
-         }
-      }
+      Map<Integer, PropertyDefinition> mprops = new TreeMap<>();
+      iter.forEachRemaining(prop -> mprops.put(dmoPropIndex.get(prop.name), new PropertyDefinition(prop)));
+      List<PropertyDefinition> lprops = new ArrayList<>(mprops.values());
 
       if (copyRows)
       {

=== modified file 'src/com/goldencode/p2j/persist/TemporaryBuffer.java'
--- src/com/goldencode/p2j/persist/TemporaryBuffer.java	2022-11-03 00:24:27 +0000
+++ src/com/goldencode/p2j/persist/TemporaryBuffer.java	2022-11-07 15:44:16 +0000
@@ -623,7 +623,9 @@
 **                           they are not.
 **     OM  20221027          Use Dialect API to create and drop sequences.
 **     CA  20221031          Added JMX instrumentation for TABLE[-HANDLE] parameter processing.
+**     IAS 20221102          Added error reporting for SCHEMA-MARSHAL == NONE.
 **     OM  20221103          New class names for FQLPreprocessor, FQLExpression, FQLBundle, and FQLCache.
+**     IAS 20221103          Fixed support for a binded table parameter.
 */
 
 /*
@@ -2209,6 +2211,16 @@
          return;
       }
       
+      if (src.isRemoteParameter()  && !src.getResultSet().isReceivedSchema())
+      {
+         RecordBuffer rb = ((BufferReference) dstDMO).buffer();
+         DmoMeta meta = rb.getDmoInfo();
+         Iterator<Property> props = meta.getFields(false);
+         List<PropertyDefinition> pdl = new ArrayList<>();
+         props.forEachRemaining(p -> pdl.add(new PropertyDefinition(p)));
+         src.getResultSet().setProperties(pdl);
+      }
+      
       boolean bind = src.isBind() || options.contains(ParameterOption.BIND);
       
       if (src.isByReference() || bind || (!src.isRemoteParameter() && buffer.referenceOnly))
@@ -2600,6 +2612,10 @@
          else
          {
             TableWrapper resultSet = src.getResultSet();
+            if (!resultSet.isReceivedSchema())
+            {
+               ErrorManager.recordOrThrowError(12323);
+            }
             if (resultSet != null && resultSet.isValid() && resultSet.getTableName() != null)
             {
                TempTableBuilder builder = new TempTableBuilder();

=== modified file 'src/com/goldencode/p2j/persist/orm/DmoMeta.java'
--- src/com/goldencode/p2j/persist/orm/DmoMeta.java	2022-09-17 01:08:47 +0000
+++ src/com/goldencode/p2j/persist/orm/DmoMeta.java	2022-10-18 08:44:59 +0000
@@ -39,6 +39,7 @@
 **                  to a better suited name.
 **     OM  20220706 The objects returned by getDatabaseIndexes() carry the legacy names, too.
 **     OM  20220914 Use MAX-WIDTH to generate custom sized varchar columns.
+**     IAS 20221018 Fixed processing of 'now' and 'today' INITIAL attribute value.
 */
 
 /*
@@ -1591,13 +1592,13 @@
                      {
                         if (bdtType == date.class)
                         {
-                           init = "today".equalsIgnoreCase(p.initial) ? date.today() : new date(p.initial);
+                           init = "today".equalsIgnoreCase(p.initial) ? new character(p.initial) : new date(p.initial);
                         }
                         else if (bdtType == datetime.class)
                         {
                            if ("now".equalsIgnoreCase(p.initial))
                            {
-                              init = datetime.now();
+                              init =  new character(p.initial);
                            }
                            else if (p.initial.toUpperCase().indexOf('T') > 0)
                            {
@@ -1614,7 +1615,7 @@
                         {
                            if ("now".equalsIgnoreCase(p.initial))
                            {
-                              init = datetimetz.now();
+                              init = new character(p.initial);
                            }
                            else if (p.initial.toUpperCase().indexOf('T') > 0)
                            {

=== modified file 'src/com/goldencode/p2j/persist/serial/XmlExport.java'
--- src/com/goldencode/p2j/persist/serial/XmlExport.java	2022-10-14 12:38:17 +0000
+++ src/com/goldencode/p2j/persist/serial/XmlExport.java	2022-11-06 18:32:07 +0000
@@ -1668,8 +1668,19 @@
             String defVal = Util.defaultValuesMap.get(columnType);
             if (initial != null && !initial.equals(defVal))
             { 
-               writer.writeAttribute("prodata:initial",
-                                     initial.equals("?") ? "prodata:unknown" : initial);
+               if (type.startsWith("xsd:date") && 
+                        ("today".equalsIgnoreCase(initial) || "now".equalsIgnoreCase(initial)))
+               {
+                  writer.writeAttribute("prodata:initial", "prodata:" + initial.toLowerCase());
+               }
+               else if (initial.equals("?"))
+               {
+                  writer.writeAttribute("prodata:initial", "prodata:unknown");
+               }
+               else
+               {
+                  writer.writeAttribute("default", initial);
+               }
             }
          }
       }

=== modified file 'src/com/goldencode/p2j/persist/serial/XmlImport.java'
--- src/com/goldencode/p2j/persist/serial/XmlImport.java	2022-10-14 12:38:17 +0000
+++ src/com/goldencode/p2j/persist/serial/XmlImport.java	2022-10-18 08:45:19 +0000
@@ -42,6 +42,7 @@
 **     OM  20220914 Use MAX-WIDTH to generate custom sized varchar columns.
 **     IAS 20220926 Fixed READ-XMLSCHEMA support.
 **     IAS 20221014 More fixes to READ-XMLSCHEMA support.
+**     IAS 20221018 Fixed processing of 'now' and 'today' INITIAL attribute value.
 */
 
 /*
@@ -1866,19 +1867,30 @@
                               // Unable to set initial value '<value>' from XML Schema for field '<field>'.
                               return false;
                            }
-                           
-                           try
-                           {
-                              Constructor<? extends BaseDataType> ctor = 
-                                 (Constructor<? extends BaseDataType>) fwdType.getConstructor(String.class);
-                              defVal = ctor.newInstance(defaultStrVal);
-                           }
-                           catch (NoSuchMethodException | IllegalAccessException | 
-                                  InstantiationException | InvocationTargetException e)
-                           {
-                              ErrorManager.recordOrShowError(13143, defaultStrVal, fieldName);
-                              // Unable to set initial value '<value>' from XML Schema for field '<field>'.
-                              return false;
+                           if (fwdType == date.class && "today".equalsIgnoreCase(defaultStrVal))
+                           {
+                                defVal = new character("today"); 
+                           }
+                           else if ((fwdType == datetime.class || fwdType == datetimetz.class) &&
+                                     "now".equalsIgnoreCase(defaultStrVal))
+                           {
+                              defVal = new character("now"); 
+                           }
+                           else
+                           {
+                              try
+                              {
+                                 Constructor<? extends BaseDataType> ctor = 
+                                    (Constructor<? extends BaseDataType>) fwdType.getConstructor(String.class);
+                                 defVal = ctor.newInstance(defaultStrVal);
+                              }
+                              catch (NoSuchMethodException | IllegalAccessException | 
+                                     InstantiationException | InvocationTargetException e)
+                              {
+                                 ErrorManager.recordOrShowError(13143, defaultStrVal, fieldName);
+                                 // Unable to set initial value '<value>' from XML Schema for field '<field>'.
+                                 return false;
+                              }
                            }
                         }
                         

=== modified file 'src/com/goldencode/p2j/util/AppServerHelper.java'
--- src/com/goldencode/p2j/util/AppServerHelper.java	2022-09-12 07:16:17 +0000
+++ src/com/goldencode/p2j/util/AppServerHelper.java	2022-11-02 07:58:35 +0000
@@ -77,6 +77,7 @@
 **     CA  20220428 Fixed memptr, extent, table arguments when the request is remote.
 **     CA  20220602 Added basic support for transport of object instances over appserver call.
 **     CA  20220912 If a dataset from the call has no buffers added to it, set it to unknown.
+**     IAS 20221029 Fixed TableParameter processing.
 */
 
 /*
@@ -2660,20 +2661,18 @@
 
                   boolean input = (mode == 'I' || mode == 'U');
                   boolean output = (mode == 'O' || mode == 'U');
+                  
+                  int schemaMarshalLevel = tableParam.getSchemaMarshalLevel();
 
-//               try
-//               {
                   arg = new TableWrapper(new TempTableResultSet(tempDMO, input, output, append, input));
                   String tableName = ((BufferImpl) tempDMO).buffer().getDmoInfo().legacyTable;
                   ((TableWrapper) arg).setTableName(tableName);
-//               }
-//               catch (ClassNotFoundException e)
-//               {
-//                  String err = String.format("Could not process temp DMO %s as a parameter!", 
-//                                              tempDMO.getClass().getName());
-//                  
-//                  throw new IllegalArgumentException(err, e);
-//               }
+                  ((TableWrapper) arg).setSchemaMarshalLevel(schemaMarshalLevel);
+                  handle tableHandle = ((Buffer) tempDMO).tableHandle();
+                  if (tableHandle._isValid())
+                  {
+                     ((TableWrapper) arg).init((TempTable) tableHandle.getResource());
+                  }
 
                   try
                   {

=== modified file 'src/com/goldencode/p2j/util/ErrorManager.java'
--- src/com/goldencode/p2j/util/ErrorManager.java	2022-10-06 17:56:26 +0000
+++ src/com/goldencode/p2j/util/ErrorManager.java	2022-11-02 11:52:19 +0000
@@ -247,6 +247,7 @@
 **                           with namesakes in DMO. See #6694.
 **     IAS 20221003          Fixed error message for error 3131
 **     IAS 20221006          Reverted error message for error 3131 change.
+**     IAS 20221102          Added error 12323 support.
 */
 
 /*
@@ -3083,7 +3084,7 @@
          case 12301: msg = "Source and target are the same table in temp-table copy operation for %1"; break;     // dataset-copy (itself)
          case 12303: msg = "COPY-TEMP-TABLE requires %1 and %2 columns to match exactly unless the fourth loose-mode parameter is passed as TRUE"; break; // dataset-copy (table structure not matching)
          case 12310: msg = "Caller and called dataset parameters have different number of members"; break;
-         
+         case 12323: msg = "A NO-SCHEMA-MARSHAL table cannot be used as a parameter where the receiving side does not have a pre-prepared schema"; break;
          case 12344: msg = "Cannot turn on TRACKING-CHANGES for a static temp-table unless DEFINED with a BEFORE-TABLE phrase"; break;
          case 12352: msg = "Argument %1 to query callback method must be a valid query event name such as OFF-END"; break;
          case 12355: msg = "TRACKING-CHANGES may not be turned on for a non-dataset temp-table"; break;

=== modified file 'src/com/goldencode/p2j/util/TableParameter.java'
--- src/com/goldencode/p2j/util/TableParameter.java	2022-10-06 11:27:04 +0000
+++ src/com/goldencode/p2j/util/TableParameter.java	2022-11-08 09:27:47 +0000
@@ -38,6 +38,8 @@
 **                  INPUT-OUTPUT mode, and the DATASET-HANDLE, DATASET, TABLE-HANDLE or TABLE versions.
 **     CA  20220727 Fixed OO dataset/table parameters (at the method definition and method call) when there is
 **                  an APPEND option.
+**     IAS 20221029 Added SCHEMA-MARSHAL attribute support.
+**     IAS 20221108 Replaced static 'TempTableBuilder.createRemoteTable' with a regular one.
 */
 
 /*
@@ -134,6 +136,9 @@
    /** {@code true} if the parameter mode is OUTPUT or INPUT-OUTPUT. */
    private boolean output = false;
    
+   /** Table SCHEMA-MARSHAL attribute value encodes as int */ 
+   private int schemaMarshalLevel;
+   
    /** Flag indicating this is a TABLE-HANDLE argument. */
    private boolean isTableHandle = false;
    
@@ -218,6 +223,8 @@
       this.options     = options;
       this.input       = input;
       this.output      = output;
+      this.schemaMarshalLevel = ((AbstractTempTable)this.tableHandle.unwrapTempTable()).
+                                       getSchemaMarshalLevel();
    }
    
    /**
@@ -390,7 +397,7 @@
       // if INPUT, create a dynamic table
       if (resultSet.isInput() && !resultSet.isFromJson() && resultSet.isAfterTable())
       {
-         BufferImpl buff = TempTableBuilder.createRemoteTable(resultSet.getTableName(),
+         BufferImpl buff = new TempTableBuilder().createRemoteTable(resultSet.getTableName(),
                                                               resultSet.propertyIterator(),
                                                               resultSet.getIndexes(),
                                                               resultSet.getXmlns(),
@@ -596,6 +603,15 @@
       return parameterIndex;
    }
    
+   /** Get encoded table SCHEMA-MARSHAL attribute value.
+    * 
+    * @return encoded table SCHEMA-MARSHAL attribute value.
+    */
+   public int getSchemaMarshalLevel()
+   {
+      return schemaMarshalLevel;
+   }
+
    /**
     * Set 1-based index of the table parameter (in declaration of the function).
     *

