=== modified file 'src/com/goldencode/p2j/persist/AbstractTempTable.java'
--- src/com/goldencode/p2j/persist/AbstractTempTable.java	2022-05-31 19:11:54 +0000
+++ src/com/goldencode/p2j/persist/AbstractTempTable.java	2022-11-11 09:09:20 +0000
@@ -56,6 +56,7 @@
 **     CA  20220920 Buffer implicit deletion performed on temp-table delete must use a ProcedureManager to 
 **                  delete it instead of handle.delete.
 **     IAS 20221003 Fixed error message for error 3131
+**     IAS 20221111 Added setter for the 'schemaMarshalLevel', fixed one for the 'namespaceURI'.
 */
 
 /*
@@ -882,6 +883,15 @@
    }
    
    /**
+    * Set the current {@code SCHEMA-MARSHAL} level. Refer to {@code SM_DEFAULT}, {@code SM_NONE},
+    * {@code SM_MIN}, and {@code SM_FULL} static constants for details. 
+    */
+   public void setSchemaMarshalLevel(int schemaMarshalLevel)
+   {
+      this.schemaMarshal = schemaMarshalLevel;
+   }
+
+   /**
     * Implements the {@code NO-SCHEMA-MARSHAL} attribute getter.
     * 
     * @return  {@code true} when {@code SCHEMA-MARSHAL} attribute is set to {@code "NONE"}.
@@ -2314,7 +2324,7 @@
    @Override
    public void namespaceURI(character uri)
    {
-      namespaceURI(uri.toJavaType());
+      namespaceURI(uri.isUnknown() ? "" : uri.toJavaType());
    }
    
    /**

=== 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-11 15:04:56 +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,14 @@
          {
             if (dsParam.isByReference() || dsParam.isRemoteParameter())
             {
+               // check if all tables contain schema.
+               if (!dsParam.getDatasetWrapper().getTableDefs().stream().
+                        allMatch(DsTableDefinition::isReceivedSchema))
+               {
+                  // A NO-SCHEMA-MARSHAL table cannot be used as a parameter where the receiving side
+                  // does not have a pre-prepared schema
+                  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.
@@ -2347,7 +2366,7 @@
    @Override
    public void namespaceURI(character uri)
    {
-      namespaceURI(uri.toJavaType());
+      namespaceURI(uri == null & uri.isUnknown() ? "" : uri.toJavaType());
    }
    
    /**
@@ -3899,6 +3918,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/DataSetContainer.java'
--- src/com/goldencode/p2j/persist/DataSetContainer.java	2021-07-01 10:04:17 +0000
+++ src/com/goldencode/p2j/persist/DataSetContainer.java	2022-11-11 09:10:40 +0000
@@ -2,7 +2,7 @@
 ** Module   : DataSetContainer.java
 ** Abstract : A container used to serialize a dataset and send it to a remote side. 
 **
-** Copyright (c) 2019-2021, Golden Code Development Corporation.
+** Copyright (c) 2019-2022, Golden Code Development Corporation.
 **
 ** -#- -I- --Date-- ---------------------------------Description----------------------------------
 ** 001 OM  20190708 Created initial version.
@@ -10,6 +10,7 @@
 **     CA  20190812 Added toString().
 ** 002 SVL 20210614 Added copyRows parameter.
 **     SVL 20210701 Added clearRows.
+** 003 IAS 20221111 Added 'xmlNodeName', 'nsURI', and 'nsPrefix' fields. 
 */
 
 /*
@@ -92,6 +93,15 @@
    /** The definitions for all relations between the tables in the dataset. */
    private List<DsRelationDefinition> relationDefinitions = null;
    
+   /** The XML namespace for this dataset. */
+   private String xmlns = null;
+   
+   /** The XML prefix for this dataset. */
+   private String xmlPrefix = null;
+   
+   /** The XML-NODE-NAME attribute for this dataset. */
+   private String xmlNodeName = null;
+
    /**
     * Default c'tor, explicitly added to allow instances of this class to be created on 
     * deserialization. Not for public use.
@@ -257,6 +267,13 @@
       
       setStructureName(ds.name().toStringMessage());
       
+      character tmp = ds.namespaceURI();
+      this.xmlns = tmp.isUnknown() ? "" : tmp.toJavaType();
+      tmp = ds.namespacePrefix();
+      this.xmlPrefix = ds.namespacePrefix().toJavaType(); 
+      tmp = ds.getXmlNodeName();
+      this.xmlNodeName = ds.getXmlNodeName().toJavaType();
+      
       // prepare relation data
       int relCnt = ds.getNumRelations().intValue();
       relationDefinitions = new ArrayList<>(relCnt);
@@ -276,6 +293,33 @@
    }
 
    /**
+    * Get the XML namespace of the DATASET.
+    * @return XML namespace of the DATASET
+    */
+   public String namespaceURI()
+   {
+      return xmlns;
+   }
+
+   /**
+    * Get the XML prefix of the DATASET.
+    * @return XML prefix of the DATASET
+    */
+   public String namespacePrefix()
+   {
+      return xmlPrefix;
+   }
+
+   /**
+    * Get the XML node name of the DATASET.
+    * @return XML node name of the DATASET
+    */
+   public String getXmlNodeName()
+   {
+      return xmlNodeName;
+   }
+
+   /**
     * Delete row data.
     */
    public void clearRows()

=== 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-11 09:17:33 +0000
@@ -39,6 +39,9 @@
 **                  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.
+**     IAS 20221111 Fixed support of relations' for SCHEMA-MARSHAL == NONE and issues with 
+**                  processing 'schemaMarshalLevel', 'xmlNodeName', 'nsURI', and 'nsPrefix'. 
 */
 
 /*
@@ -324,6 +327,7 @@
    {
       BufferManager.registerScopeable(null);
       
+      this.originalDataSet = (DataSet)dsHandle.getResource();
       this.dataset = dsHandle;
       this.options = options; // TODO: check default value for mode if ParameterOption.NONE is passed in
       this.input   = input;
@@ -533,22 +537,42 @@
       DataSet.create(dataset);
       DataSet newDS = (DataSet) dataset.getResource();
       newDS.name(wrapper.getDatasetName());
+      newDS.namespaceURI(wrapper.namespaceURI());
+      newDS.namespacePrefix(wrapper.namespacePrefix());
+      newDS.setXmlNodeName(wrapper.getXmlNodeName());
       
       List<DsTableDefinition> tableDefs = wrapper.getTableDefs();
+      Set<String> tablesWithoutSchema = new HashSet<>();
       if (tableDefs != null && !tableDefs.isEmpty())
       {
          BufferImpl[] buffs = new BufferImpl[tableDefs.size()];
          for (int k = 0; k < tableDefs.size(); k++)
          {
             DsTableDefinition tableDef = tableDefs.get(k);
-            
+            if (!tableDef.isReceivedSchema())
+            {
+               tablesWithoutSchema.add(tableDef.getName());
+               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, tableDef.getSchemaMarshalLevel());
+               }
+               else
+               {
+                  buffs[k] = ttb.createRemoteTable(tableDef.getName(), 
+                           props, idx, xmlns, prefix, tableDef.getSchemaMarshalLevel());
+               }
                
                if (tableDef.isAfterTable() && tableDef.getPeerDef() != null)
                {
@@ -574,6 +598,11 @@
       {
          for (DsRelationDefinition relDef : relationsDefs)
          {
+            if (tablesWithoutSchema.contains(relDef.getParentBuffer()) ||
+                tablesWithoutSchema.contains(relDef.getChildBuffer()))
+            {
+               continue;
+            }
             handle hRel = newDS.addRelation(
                   newDS.bufferHandle(relDef.getParentBuffer()),
                   newDS.bufferHandle(relDef.getChildBuffer()),

=== 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-11 09:20:49 +0000
@@ -17,8 +17,9 @@
 **                  (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.
+**     IAS 20221111 Added 'xmlNodeName', 'nsURI', and 'nsPrefix' fields and fixed 
+**                  'schemaMarshalLevel' support.
 /*
 ** This program is free software: you can redistribute it and/or modify
 ** it under the terms of the GNU Affero General Public License as
@@ -121,6 +122,15 @@
    /** The name of the DataSet. */
    private String dsName = null;
    
+   /** The XML namespace for this dataset. */
+   private String xmlns = null;
+   
+   /** The XML prefix for this dataset. */
+   private String xmlPrefix = null;
+   
+   /** The XML-NODE-NAME attribute for this dataset. */
+   private String xmlNodeName = null;
+
    /** Flag indicating if the source is a JSON dataset. */
    private boolean fromJson;
    
@@ -172,6 +182,9 @@
    public DatasetWrapper(DataSetContainer resource)
    {
       this.resource = resource;
+      this.xmlns = resource.namespaceURI();
+      this.xmlPrefix = resource.namespacePrefix();
+      this.xmlNodeName = resource.getXmlNodeName();
    }
 
    /**
@@ -184,7 +197,7 @@
     */
    public DatasetWrapper(boolean fromJson, DataSetContainer resource)
    {
-      this.resource = resource;
+      this(resource);
       this.fromJson = fromJson;
    }
    
@@ -260,6 +273,33 @@
    {
       return resource;
    }
+
+   /**
+    * Get the XML namespace of the DATASET.
+    * @return XML namespace of the DATASET
+    */
+   public String namespaceURI()
+   {
+      return xmlns;
+   }
+
+   /**
+    * Get the XML prefix of the DATASET.
+    * @return XML prefix of the DATASET
+    */
+   public String namespacePrefix()
+   {
+      return xmlPrefix;
+   }
+
+   /**
+    * Get the XML node name of the DATASET.
+    * @return XML node name of the DATASET
+    */
+   public String getXmlNodeName()
+   {
+      return xmlNodeName;
+   }
    
    /**
     * Returns the list of table definitions for the temp-tables from this {@code DataSet}.
@@ -437,6 +477,9 @@
 
          writeString(out, dsName);
       }
+      writeString(out, xmlns);
+      writeString(out, xmlPrefix);
+      writeString(out, xmlNodeName);
       
       // write properties
       if (resource != null)
@@ -504,6 +547,9 @@
       }
       
       dsName = readString(in);
+      xmlns = readString(in);
+      xmlPrefix = readString(in);
+      xmlNodeName = readString(in);
       
       int n = in.readInt(); 
       if (n != 0)
@@ -566,13 +612,14 @@
       {
          TableWrapper tw = new TableWrapper(fromJson, res);
          tw.setTableName(tdef.getName());
+         tw.setSchemaMarshalLevel(tdef.getSchemaMarshalLevel());
          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          ObjectOutputStream oos = new ObjectOutputStream(baos);
          tw.writeExternal(oos);
          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-11 11:52:54 +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,8 @@
 **     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.
+**     IAS 20221111 Fixed 'schemaMarshalLevel', 'xmlNodeName', 'nsURI', and 'nsPrefix' support.
 */
 
 /*
@@ -79,6 +81,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 +94,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 +133,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}.
     * 
@@ -136,9 +146,9 @@
    
    /**
     * The SCHEMA-MARSHAL level for the serialized temp-table. It is never {@code SM_DEFAULT} when object is to
-    * be serialized. Always {@code SM_DEFAULT} for a read object.
+    * be serialized. 
     */
-   private final int schemaMarshalLevel;
+   private int schemaMarshalLevel;
    
    /**
     * Default c'tor, explicitly added to allow instances of this class to be created on 
@@ -186,23 +196,19 @@
       switch (sml)
       {
          case SM_FULL:
+         case SM_MIN:
+            this.errorString = defBuff.errorString().toStringMessage();
+            // no break, fall through
          case SM_DEFAULT:
             // full table schema is serialized with table parameter
+            character tmp = parentTable.namespaceURI(); 
+            this.xmlns = tmp.isUnknown() ? "" : tmp.toJavaType(); 
+            this.xmlPrefix = parentTable.namespacePrefix().toJavaType(); 
+            this.xmlNodeName = parentTable.namespacePrefix().toJavaType();
             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.errorString = defBuff.errorString().toStringMessage();
+            this.indexDefs = TableMapper.getLegacyIndexes(parentTable).map(lif -> new IndexDefinition(lif)).
+                     collect(Collectors.toList());
             // no break, fall through
          
          case SM_NONE:
@@ -267,6 +273,14 @@
    }
    
    /**
+    * The SCHEMA-MARSHAL level for the serialized temp-table. 
+    */
+   public int getSchemaMarshalLevel()
+   {
+      return schemaMarshalLevel;
+   }
+   
+   /**
     * Sets the name of this table.
     *
     * @param   name
@@ -277,6 +291,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 +410,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 +535,7 @@
                "A custom result set must not be specified when calling this method!");
       }
       
-      return new ArrayList<>(properties);
+      return properties != null ? new ArrayList<>(properties) : Collections.emptyList();
    }
    
    /**
@@ -562,39 +595,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 +693,30 @@
    throws IOException,
           ClassNotFoundException
    {
+      schemaMarshalLevel = in.readByte(); 
+      receivedSchema = schemaMarshalLevel != 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-11 11:51:27 +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,29 @@
    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);
+      writeString(out, xmlNodeType);
+      writeString(out, codePage);
+      int flags = (serializeHidden ? 1 : 0) | (caseSensitive ? 2 : 0) | (full ? 4 : 0);
+      out.writeByte(flags);
+      if (!full )
+      {
+         return;
+      }
+      writeString(out, format);
+      writeString(out, label);
+      writeString(out, columnLabel);
+      writeString(out, help);
    }
    
    /**
@@ -427,13 +547,25 @@
           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);
+      xmlNodeType = readString(in);
+      codePage = readString(in);
+      int flags = in.readByte();
+      serializeHidden = (flags & 1) != 0;
+      caseSensitive = (flags & 2) != 0;
+      boolean full = (flags & 4) != 0;
+      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-11 09:28:43 +0000
@@ -102,7 +102,10 @@
 **     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.
+**     IAS 20221111 Minor cleanup of the LegacyFieldInfo c'tor.
 */
 
 /*
@@ -163,6 +166,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 +792,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 +2683,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 +2915,7 @@
                   {
                      if ("today".equalsIgnoreCase(text))
                      {
-                        initialValue = date.today();
+                        initialValue = new character(text);
                      }
                      else
                      {
@@ -2893,7 +2926,7 @@
                   {
                      if ("now".equalsIgnoreCase(text))
                      {
-                        initialValue = datetime.now();
+                        initialValue = new character(text);
                      }
                      else if (text.toUpperCase().indexOf('T') > 0)
                      {
@@ -2910,7 +2943,7 @@
                   {
                      if ("now".equalsIgnoreCase(text))
                      {
-                        initialValue = datetimetz.now();
+                        initialValue = new character(text);
                      }
                      else if (text.toUpperCase().indexOf('T') > 0)
                      {
@@ -3118,6 +3151,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 +3258,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
@@ -3546,6 +3588,7 @@
          else
          {
             this.format = defaultFormat;
+            this.definedFormat = null;
          }
          
          this.dataType = dataType;

=== 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-11 12:09:56 +0000
@@ -28,6 +28,10 @@
 **                  (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.
+**     IAS 20221111 Fixed 'schemaMarshalLevel' support.
 */
 
 /*
@@ -86,11 +90,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 +131,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 +174,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 +441,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 +600,8 @@
            "A custom result set must not be specified when calling this method!");
       }
 
-      return new ArrayList<PropertyDefinition>(properties);
+      return properties != null ? new ArrayList<PropertyDefinition>(properties) : 
+                                 Collections.emptyList();
    }
 
    /**
@@ -682,53 +710,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 +778,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 +786,7 @@
                {
                   if (row2[idx] instanceof object)
                   {
-                     row2[idx] = new LegacyObject((object) row2[idx]);
+                     row2[idx] = new LegacyObject((object<?>) row2[idx]);
                   }
                }
                
@@ -781,7 +816,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 +839,29 @@
          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
+      schemaMarshalLevel = in.readByte(); 
+      receivedSchema =  schemaMarshalLevel != 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 +876,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 +899,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 +940,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 +971,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-11-08 19:25:33 +0000
+++ src/com/goldencode/p2j/persist/TempTableBuilder.java	2022-11-11 12:09:01 +0000
@@ -122,7 +122,11 @@
 **     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.
 **     CA  20221108 BEFORE-TABLE's name is always trimmed to max 32 chars length.
+**     IAS 20221111 Fixed 'schemaMarshalLevel' support.
 */
 
 /*
@@ -314,55 +318,46 @@
     *           The XML namespace.
     * @param    xmlPrefix
     *           The XML prefix.
+    * @param    schemaMarshalLevel
+    *           The SCHEMA-MARSHAL level for the serialized temp-table. 
+    * @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;
+                                              String xmlPrefix,
+                                              int schemaMarshalLevel)
+   {
+      return createTable(tableName, props, 
+               () -> parseIndexString(tableIndexes), xmlns, xmlPrefix, schemaMarshalLevel);
+   }
+   
+   /**
+    * 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.
+    * @param    schemaMarshalLevel
+    *           The SCHEMA-MARSHAL level for the serialized temp-table.      
+    * @return   default buffer for the table
+    */
+   public BufferImpl createRemoteTable(String tableName,
+                                              Iterator<PropertyDefinition> props,
+                                              Runnable indexProvider, 
+                                              String xmlns,
+                                              String xmlPrefix,
+                                              int schemaMarshalLevel)
+   {
+      return createTable(tableName, props, indexProvider, xmlns, xmlPrefix, schemaMarshalLevel);
    }
    
    /**
@@ -1341,6 +1336,60 @@
                               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 
+    *          Field HELP attribute value.
+    * @param   xmlNodeType
+    *          Field XML node type. 
+    * @param   codePage 
+    *          Field code page. 
+    * @param   serializeHidden
+    *          Field SERIALIZE-HIDDEN attribute value.
+    * @param   caseSensitive 
+    *          Field CASE-SENSITIVE attribute value.
+    *
+    * @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())
@@ -1398,12 +1447,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);
    }
@@ -2733,6 +2786,78 @@
    }
    
    /**
+    * 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.
+    * @param    schemaMarshalLevel
+    *           The SCHEMA-MARSHAL level for the serialized temp-table. 
+    * @return   default buffer for the table
+    */
+   public BufferImpl createTable(String tableName,
+                                 Iterator<PropertyDefinition> props,
+                                 String tableIndexes, 
+                                 String xmlns,
+                                 String xmlPrefix,
+                                 int schemaMarshalLevel)
+   {
+      return  createTable(tableName, props, 
+                          () -> parseIndexString(tableIndexes), 
+                          xmlns, xmlPrefix, schemaMarshalLevel);
+   }
+
+   /**
+    * 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.
+    * @param    schemaMarshalLevel
+    *           The SCHEMA-MARSHAL level for the serialized temp-table. 
+    * @return   default buffer for the table
+    */
+   public BufferImpl createTable(String tableName,
+                                 Iterator<PropertyDefinition> props,
+                                 Runnable indexProvider, 
+                                 String xmlns,
+                                 String xmlPrefix,
+                                 int schemaMarshalLevel)
+   {
+      setSchemaMarshalLevel(schemaMarshalLevel);
+      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
@@ -2748,14 +2873,25 @@
       {
          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(),
+                  tableWrapper.getSchemaMarshalLevel());
+      }
+      else
+      {
+         createTable(tableWrapper.getTableName(), 
+                  tableWrapper.propertyIterator(), 
+                  tableWrapper.getIndexes(), 
+                  tableWrapper.getXmlns(), 
+                  tableWrapper.getXmlPrefix(),
+                  tableWrapper.getSchemaMarshalLevel());
+      }
       TemporaryBuffer.insertAllRows(tableWrapper,
                                     (Temporary) defaultBufferHandle().getResource(),
                                     true,
@@ -3120,9 +3256,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());
    }
    
    /**
@@ -3766,6 +3907,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-11 12:01:31 +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,12 @@
          else
          {
             TableWrapper resultSet = src.getResultSet();
+            if (!resultSet.isReceivedSchema())
+            {
+               // A NO-SCHEMA-MARSHAL table cannot be used as a parameter where the receiving side
+               // does not have a pre-prepared schema
+               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/TempTableSchema.java'
--- src/com/goldencode/p2j/persist/serial/TempTableSchema.java	2022-10-07 11:11:20 +0000
+++ src/com/goldencode/p2j/persist/serial/TempTableSchema.java	2022-11-11 09:19:05 +0000
@@ -27,7 +27,10 @@
 **                  state in MutableFieldInfo, for the actual TempTable instance. Refs #6825
 **     CA  20220520 Added support for TEXT and ATTRIBUTE XML-NODE-TYPE values.
 **     OM  20220525 Fixed case-sensitivity for column lookup.
-**     IAS 20221006 Added ' getCodePage()', 'getDefinedFormat()', and 'getDefinedLabel()' .
+**     IAS 20221006 Added 'getCodePage()', 'getDefinedFormat()', and 'getDefinedLabel()' .
+**     IAS 20221111 Added 'buffer', 'xmlNodeName', 'nsURI', and 'nsPrefix' fields. This is 
+**                  required for tables in the the DATASET parameters' support since they are 
+**                  processed differently from the standalone tables.
 */
 
 /*
@@ -99,12 +102,24 @@
  */
 public class TempTableSchema
 {
+   /* RecordBuffer on the temp-table */
+   private final RecordBuffer buffer;
+   
    /** Legacy name of the temp-table */
    private final String name;
    
    /** XML serialization name of the temp-table */
    private final String xmlName;
+ 
+   /** XML node name of the temp-table */
+   private final String xmlNodeName;
    
+   /** XML namespace URI of the temp-table */
+   private final String nsURI;
+
+   /** XML prefix of the temp-table */
+   private final String nsPrefix;
+
    /** Schema information needed for serialization of all columns/fields, in the DMO order. */
    private final List<Column> columnList = new ArrayList<>();
    
@@ -142,6 +157,7 @@
       BufferImpl buf = (BufferImpl) recBuf.getDMOProxy();
       
       // the table name is used for serialization, regardless of the individual buffer name
+      this.buffer = recBuf;
       this.name = TableMapper.getLegacyName(recBuf);
       this.xmlName = buf.getSerializeName().toJavaType();
       
@@ -150,6 +166,10 @@
       Map<String, Method> setterMap = PropertyHelper.allSettersByProperty(dmoIface);
       
       TempTable tt = recBuf.getParentTable();
+      this.xmlNodeName = tt.getXmlNodeName().toJavaType();
+      this.nsURI = tt.namespaceURI().isUnknown() ? "" : tt.namespaceURI().toJavaType();
+      this.nsPrefix = tt.namespacePrefix().toJavaType();
+      
       List<TableMapper.LegacyFieldInfo> fields = TableMapper.getAllLegacyFieldInfo(tt);
       Iterator<TableMapper.LegacyFieldInfo> iter = fields.iterator();
       this.noUndo = !tt.canUndo().toJavaType();
@@ -238,6 +258,46 @@
    }
    
    /**
+    * Get the RecordBuffer on the temp-table.
+    * 
+    * @return RecordBuffer on the temp-table.
+    */
+   public RecordBuffer buffer()
+   {
+      return buffer;
+   }
+
+   /**
+    * Get the XML node name of the temp-table.
+    * 
+    * @return XML node name of the temp-table.
+    */
+   public String xmlNodeName()
+   {
+      return xmlNodeName;
+   }
+
+   /**
+    * Get the XML namespace URI of the temp-table.
+    * 
+    * @return XML namespace URI of the temp-table.
+    */
+   public String namespaceURI()
+   {
+      return nsURI;
+   }
+
+   /**
+    * Get the XML prefix of the temp-table.
+    * 
+    * @return  XML prefix of the temp-table.
+    */
+   public String namespacePrefix()
+   {
+      return nsPrefix;
+   }
+   
+   /**
     * Get the legacy name of this temp-table.
     * 
     * @return  Legacy table name.

=== 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-11 18:30:41 +0000
@@ -40,6 +40,9 @@
 **     IAS 20220926 Fixed WRITE-XMLSCHEMA support.
 **     IAS 20221013 Case-insensitive comparing of FORMAT value with a default one.
 **     IAS 20221014 Do not add prefix to the attribute name.
+**     IAS 20221110 Multiple fixes in the WRITE-XMLSCHEMA support. The most important one is the
+**                  external schema support for DATASETs
+**     IAS 20221111 Fixed WRITE-XML for DATASET.
 */
 
 /*
@@ -100,13 +103,17 @@
 import java.io.*;
 import java.lang.reflect.*;
 import java.math.*;
+import java.nio.file.*;
 import java.util.*;
+import java.util.stream.*;
+
 import javax.xml.stream.*;
 
 import org.apache.commons.lang3.*;
 import org.apache.commons.lang3.tuple.*;
 import com.ctc.wstx.api.*;
 import com.goldencode.p2j.persist.*;
+import com.goldencode.p2j.persist.orm.*;
 import com.goldencode.p2j.persist.serial.SerializeOptions.XmlNodeType;
 import com.goldencode.p2j.util.*;
 
@@ -143,6 +150,9 @@
    /** Character encoding (not currently used). */
    private final String encoding;
    
+   /** Flag indicating that we're creating external schema */
+   private boolean external = false;
+   
    /** XML stream writer */
    private XMLStreamWriter writer = null;
    
@@ -273,20 +283,36 @@
       }
       final String dsName = dsName1;
       character nsUri = dataSet.namespaceURI();
-      String nsUriStr = (nsUri.isUnknown()) ? "" : nsUri.toStringMessage();
+      character nsPrefix = dataSet.namespacePrefix();
+      String nsUriStr = (nsUri.isUnknown()) ? "" : nsUri.toJavaType();
+      String nsPrefixStr = nsPrefix.toJavaType();
       String nodeNameStr = dataSet.getXmlNodeNameInternal();
+      Map<String, TempTableSchema> tables = tables(dataSet, nsUriStr, false);
+      if (tables == null)
+      {
+         return false;
+      }
       this.ds = dataSet;
       
       return write(() -> {
-         writer.writeStartElement(nodeNameStr);
+         writer.writeStartElement((nsPrefixStr == null ? "" : nsPrefixStr + ":") + nodeNameStr);
          if (!nsUriStr.isEmpty())
          {
-            writer.writeAttribute("xmlns", nsUriStr);
+            writer.writeAttribute(
+                     "xmlns" + (nsPrefixStr == null ? "" : ":" + nsPrefixStr), 
+                     nsUriStr);
          }
          writer.writeAttribute(ATTR_NS_XSI, NS_URI);
-         if (schemaLocation != null && !schemaLocation.isEmpty())
+         if (schemaLocation != null)
          {
-            writer.writeAttribute("xsi:noNamespaceSchemaLocation", schemaLocation);
+            if (nsUriStr.isEmpty())
+            {
+               writer.writeAttribute("xsi:noNamespaceSchemaLocation", schemaLocation);
+            }
+            else
+            {
+               writer.writeAttribute("xsi:schemaLocation", nsUriStr + " " + schemaLocation);
+            }
          }
          lineBreak();
          ++indentLevel;
@@ -294,7 +320,8 @@
          if (writeXmlSchema)
          {
             if (!writeDatasetSchemaImpl(
-                     dataSet, minXmlSchema, !omitInitialValues, dsName, nsUriStr, nodeNameStr))
+                     dataSet, minXmlSchema, !omitInitialValues, dsName, nsUriStr, 
+                     nsPrefixStr, nodeNameStr, tables))
             {
                return false;
             }
@@ -341,11 +368,18 @@
             }
             
             TemporaryBuffer buffer = (TemporaryBuffer) after.buffer();
+
             TempTableSchema schema = new TempTableSchema(buffer, false);
-            if (!serializeTempTable(null, buffer, schema.getXmlName(), nsUriStr, 
-                                    omitInitialValues, false, writeBeforeImage, false))
-            {
-               return false;
+            ttNsPrefix = schema.namespacePrefix();
+            String ttNsUri = schema.namespaceURI();
+            if (ttNsUri.isEmpty())
+            {
+               ttNsPrefix = nsPrefixStr;
+            }
+            if (!serializeTempTable(null, buffer, schema.getXmlName(), ttNsUri, 
+                     omitInitialValues, false, writeBeforeImage, false))
+            {
+                return false;
             }
             
             if (!hasChanges && after.isAfterBuffer())
@@ -390,17 +424,23 @@
                }
                
                String bufName = after.name().toStringMessage();
-               if (!serializeTempTable(null, buffer, bufName, nsUriStr, 
-                                       omitInitialValues, false, writeBeforeImage, true))
+               TempTableSchema schema = new TempTableSchema(buffer, false);
+               ttNsPrefix = schema.namespacePrefix();
+               String ttNsUri = schema.namespaceURI();
+               if (ttNsUri.isEmpty())
+               {
+                  ttNsPrefix = nsPrefixStr;
+               }
+               if (!serializeTempTable(null, buffer, bufName, ttNsUri, 
+                        omitInitialValues, false, writeBeforeImage, true))
                {
                   return false;
                }
+               --indentLevel;
+               indent();
+               writer.writeEndElement(); // prods:before
+               lineBreak();
             }
-            
-            --indentLevel;
-            indent();
-            writer.writeEndElement(); // prods:before
-            lineBreak();
          }
          
          if (!prodsErrors.isEmpty())
@@ -531,7 +571,14 @@
          
          if (schemaLocation != null && !schemaLocation.isEmpty())
          {
-            writer.writeAttribute("xsi:noNamespaceSchemaLocation", schemaLocation);
+            if (nsUri.isEmpty())
+            {
+               writer.writeAttribute("xsi:noNamespaceSchemaLocation", schemaLocation);
+            }
+            else
+            {
+               writer.writeAttribute("xsi:schemaLocation", nsUri + " " + schemaLocation);
+            }
          }
          lineBreak();
          ++indentLevel;
@@ -589,13 +636,52 @@
       
       String dsName = dataSet.name().toStringMessage();
       character nsUri = dataSet.namespaceURI();
+      character nsPrefix = dataSet.namespacePrefix();
       String nsUriStr = (nsUri.isUnknown()) ? "" : nsUri.toStringMessage();
+      String nsPrefixStr = (nsPrefix.isUnknown()) ? null : nsPrefix.toStringMessage();
       String nodeNameStr = dataSet.getXmlNodeNameInternal();
       this.ds = dataSet;
+      Map<String, TempTableSchema> tables = tables(dataSet, nsUriStr, true);
+      if (tables == null)
+      {
+         return false;
+      }
 //      this.isSchemaOnly = true;
       
       return write(() -> writeDatasetSchemaImpl(
-            dataSet, minSchema, !noInitial, dsName, nsUriStr, nodeNameStr));
+            dataSet, minSchema, !noInitial, dsName, nsUriStr, nsPrefixStr, nodeNameStr, tables));
+   }
+   
+   /**
+    * Extract tables from the DATASET 
+    * @param dataSet
+    *        DATASET to be processed
+    * @param nsUriStr
+    *        DATASET XML namespace URI
+    * @return map of tables by legacy name
+    */
+   private Map<String, TempTableSchema> tables(DataSet dataSet, String nsUriStr, boolean forSchema)
+   {
+      Map<String, TempTableSchema> tables = dataSet.getBuffers().stream().
+               map(BufferImpl::buffer).
+               map(buffer -> new TempTableSchema(buffer, false)).
+               collect(Collectors.toMap(TempTableSchema::getTableName, tts -> tts));
+      boolean multipleURIs = tables.values().stream().
+               map(TempTableSchema::namespaceURI).
+               filter(uri -> uri != null).anyMatch(uri -> !nsUriStr.equals(uri));
+      if (!Serializator.TYPE_FILE.equals(target.getType().toUpperCase()) && 
+          multipleURIs && forSchema)
+      {
+         ErrorManager.recordOrShowError(new int[] { 13095 },
+                  new String[] { ErrorManager.replaceTokens(13095)},
+                  false,    // not modal
+                  false,    // no prefix
+                  false,    // not an error
+                  false,    // not as message
+                  true);    // add final dot
+         return null;
+      }
+      return tables;
    }
    
    /**
@@ -741,13 +827,54 @@
                                     boolean defaultValues)
    throws XMLStreamException
    {
+      return writeTableSchema(buffer, schema, minSchema, defaultValues, false);
+   }
+   /**
+    * Performs the export of a TEMP-TABLE schema.
+    *
+    * @param   buffer
+    *          A buffer of a {@code TempTable} to be described.
+    * @param   schema
+    *          The schema of the TEMP-TABLE.
+    * @param   minSchema
+    *          {@code true} to write minimal schema information; {@code false} to write verbose
+    *          schema information. Ignored if {@code writeXmlSchema} is {@code false}. Not
+    *          currently honored.
+    * @param   defaultValues
+    *          If {@code true}, record values which match default initial values will be omitted
+    *          from serialized output, else they will be included.
+    *          NOTE: actually setting [defaultValues] to [TRUE] which is the [omit-initial-values] from 
+    *                ABL will cause some extra info to be added in field description (see + attributes):
+    *                <pre>{@code
+    *                   <xsd:element name="f11" type="xsd:string" nillable="true"  +minOccurs="0" +default=""/>
+    *                   <xsd:element name="f12" type="xsd:int" nillable="true"     +minOccurs="0" +default="0"/>
+    *                   <xsd:element name="f13" type="xsd:date" nillable="true"    +minOccurs="0" +prodata:initial="prodata:unknown"/>
+    *                   <xsd:element name="f14" type="xsd:decimal" nillable="true" +minOccurs="0" +default="0.0"/>}
+    *                </pre>
+    * @param   inDataset
+    *          If {@code true}, this is part of a dataset SCHEMA and additional attributes will
+    *          be written.
+    *
+    * @return  {@code true} on success. Otherwise the error is already dispatched to 
+    *          {@code ErrorManager} before returning.
+    * 
+    * @throws  XMLStreamException
+    *          If XML-related issued occur.
+    */
+   private boolean writeTableSchema(BufferImpl buffer,
+                                    TempTableSchema schema,
+                                    boolean minSchema,
+                                    boolean defaultValues,
+                                    boolean inDataset)
+   throws XMLStreamException
+   {
       String tableName = schema.getTableName();
       String legacyName = schema.getName();
       AbstractTempTable tempTable = (AbstractTempTable) buffer.buffer().getParentTable();
       String xmlNodeName = tempTable.getXmlNodeName().toJavaType();
       String nsPrefix = tempTable.namespacePrefix().toJavaType();
       String nsUri = tempTable.namespaceURI().toJavaType();
-      boolean isDataSet = buffer.isBeforeBuffer() || buffer.isAfterBuffer();
+      boolean isDataSet = inDataset || buffer.isBeforeBuffer() || buffer.isAfterBuffer();
       
       indent();
       writer.writeStartElement("xsd:schema");
@@ -766,7 +893,10 @@
          indent();
          writer.writeStartElement("xsd:element");
          writer.writeAttribute("name", xmlNodeName == null ? tableName : xmlNodeName);
-         writer.writeAttribute("prodata:proTempTable", "true"); // String.valueOf(isDataSet)); TODO: when is this attribute 'false' ? 
+         if (!external)
+         {
+            writer.writeAttribute("prodata:proTempTable", "true"); // String.valueOf(isDataSet)); TODO: when is this attribute 'false' ? 
+         }
          if (isDataSet && !legacyName.equals(tableName))
          {
             writer.writeAttribute("prodata:tableName", legacyName);
@@ -800,8 +930,10 @@
                lineBreak();
                ++indentLevel;
                {
-                  String rowName = (xmlNodeName == null ? tableName : xmlNodeName) + "Row";
-                  if (!writeTableSchemaImpl(buffer, schema, rowName, defaultValues, minSchema, false))
+                  String rowName = (xmlNodeName == null ? tableName : xmlNodeName) + 
+                           (inDataset ? "" : "Row");
+                  if (!writeTableSchemaImpl(buffer, schema, rowName, 
+                           defaultValues, minSchema, inDataset))
                   {
                      return false;
                   }
@@ -817,7 +949,7 @@
             lineBreak();
             
             // in case of standalone TEMP-TABLE schema serialization unique indexes go here:
-            if (!minSchema && this.ds == null && !indexes.isEmpty())
+            if (!external && /*!minSchema &&*/ this.ds == null && !indexes.isEmpty())
             {
                for (Map.Entry<Integer, Pair<String, TableMapper.LegacyIndexInfo>> indexEntry : 
                     indexes.entrySet())
@@ -879,7 +1011,8 @@
          writer.writeEndElement(); // xsd:element
          lineBreak();
          
-         boolean hasIndexes = !minSchema && this.ds == null /*&& !this.isSchemaOnly*/ && !indexes.isEmpty();
+         boolean hasIndexes = !external && !minSchema && this.ds == null 
+                              /*&& !this.isSchemaOnly*/ && !indexes.isEmpty();
          int idxCounter = 0;
          if (hasIndexes)
          {
@@ -967,10 +1100,13 @@
             lineBreak();
          }
       }
-      --indentLevel;
-      indent();
-      writer.writeEndElement(); // xsd:schema
-      lineBreak();
+      if (!external)
+      {
+         --indentLevel;
+         indent();
+         writer.writeEndElement(); // xsd:schema
+         lineBreak();
+      }
       
       return true;
    }
@@ -1004,7 +1140,9 @@
                                           boolean defaultValues,
                                           String dsName,
                                           String nsUri,
-                                          String nodeName)
+                                          String nsPrefix,
+                                          String nodeName,
+                                          Map<String, TempTableSchema> tables)
    throws XMLStreamException
    {
       indent();
@@ -1013,18 +1151,60 @@
       writer.writeAttribute("xmlns", nsUri);
       if (!nsUri.isEmpty())
       {
-         writer.writeAttribute("xmlns:tns", nsUri);
+         writer.writeAttribute("xmlns:" + (nsPrefix != null ? nsPrefix : "tns"), nsUri);
          writer.writeAttribute("targetNamespace", nsUri);
          writer.writeAttribute("elementFormDefault", "qualified");
       }
       writer.writeAttribute("xmlns:prodata", "urn:schemas-progress-com:xml-prodata:0001");
+      for (TempTableSchema tts: tables.values())
+      {
+         String ns = tts.namespaceURI();
+         String prefix = tts.namespacePrefix();
+         if (ns != null && !"".equals(ns) && !nsUri.equals(ns) &&  
+             prefix != null && !"".equals(prefix))
+         {
+            writer.writeAttribute("xmlns:" + prefix, ns);
+         }
+      }
       lineBreak();
       ++indentLevel;
       {
          indent();
+         Map<String, String> external = new HashMap<>();
+         boolean hasImport = false;
+         for (TempTableSchema tts: tables.values())
+         {
+            String ns = tts.namespaceURI();
+            if (ns != null && !"".equals(ns) && !nsUri.equals(ns))
+            {
+               String fn = writeExternalSchema(tts, minSchema, defaultValues);
+               if (fn == null)
+               {
+                  return false;
+               }
+               external.put(tts.getName(), fn);
+               indent();
+               hasImport = true;
+               writer.writeStartElement("xsd:import");
+               writer.writeAttribute("namespace", ns);
+               writer.writeAttribute("schemaLocation", fn);
+               writer.writeEndElement();
+               lineBreak();
+            }
+         }
+         if (hasImport)
+         {
+            ++indentLevel;
+            indent();
+         }
+         ++indentLevel;
          writer.writeStartElement("xsd:element");
          writer.writeAttribute("name", nodeName);
          writer.writeAttribute("prodata:proDataSet", "true");
+         if (nsPrefix != null)
+         {
+            writer.writeAttribute("prodata:prefix", nsPrefix);
+         }
          if (!nodeName.equals(dsName))
          {
             writer.writeAttribute("prodata:datasetName", dsName);
@@ -1060,7 +1240,19 @@
                      
                      TemporaryBuffer buffer = (TemporaryBuffer) after.buffer();
                      TempTableSchema schema = new TempTableSchema(buffer, false);
-                     
+                     if (external.containsKey(schema.getName()))
+                     {
+                        // already serialized to external schema
+                        indent();
+                        writer.writeStartElement("xsd:element");
+                        writer.writeAttribute("ref", 
+                                 schema.namespacePrefix() + ":" + schema.getName());
+                        writer.writeAttribute("minOccurs", "0");
+                        writer.writeAttribute("maxOccurs", "unbounded");
+                        writer.writeEndElement();
+                        lineBreak();
+                        continue nextBuffer;
+                     }
                      if (!writeTableSchemaImpl(
                             after, schema, schema.getTableName(), defaultValues, minSchema, true))
                      {
@@ -1120,9 +1312,17 @@
             lineBreak();
             ++indentLevel;
             {
+               TempTableSchema tts = tables.get(idxPair.getLeft());
+               String prefix = tts.namespacePrefix();
+               if (prefix == null || "".equals(prefix))
+               {
+                  prefix = nsPrefix;
+               }
+               prefix = (prefix != null && !"".equals(prefix)) ? (prefix + ":") : "";
+               
                indent();
                writer.writeEmptyElement("xsd:selector");
-               writer.writeAttribute("xpath", ".//" + idxPair.getLeft());
+               writer.writeAttribute("xpath", ".//" + prefix + idxPair.getLeft());
                lineBreak();
                
                String[] comps = index.getComponents();
@@ -1131,7 +1331,7 @@
                {
                   indent();
                   writer.writeEmptyElement("xsd:field");
-                  writer.writeAttribute("xpath", comps[i]);
+                  writer.writeAttribute("xpath", prefix + comps[i]);
                   if (!dirs[i])
                   {
                      writer.writeAttribute("prodata:descending", "true");
@@ -1206,9 +1406,18 @@
             if (isKeyref)
             {
                indent();
+               String prefix1 = nsPrefix == null || "".equals(nsPrefix) ? "" : nsPrefix + ":";
+               String prefix2 = tables.get(rel.getChildBuffer().unwrapBuffer().name().toJavaType()).
+                                       namespacePrefix();
+               if (prefix2 == null || "".equals(prefix2))
+               {
+                  prefix2 = nsPrefix;
+               }
+               prefix2 = (prefix2 != null && !"".equals(prefix2)) ? (prefix2 + ":") : "";
+
                writer.writeStartElement("xsd:keyref");
                writer.writeAttribute("name", rel.name().toJavaType());
-               writer.writeAttribute("refer", idxName);
+               writer.writeAttribute("refer", prefix1 + idxName);
                if (rel.isNested().toJavaType())
                {
                   writer.writeAttribute("prodata:nested", "true");
@@ -1218,7 +1427,9 @@
                {
                   indent();
                   writer.writeStartElement("xsd:selector");
-                  writer.writeAttribute("xpath", ".//" + rel.getChildBuffer().unwrapBuffer().name().toJavaType());
+                  writer.writeAttribute("xpath", 
+                           ".//" + prefix2 + rel.getChildBuffer().unwrapBuffer().
+                           name().toJavaType());
                   writer.writeEndElement();
                   lineBreak();
                   
@@ -1226,7 +1437,7 @@
                   {
                      indent();
                      writer.writeStartElement("xsd:field");
-                     writer.writeAttribute("xpath", field);
+                     writer.writeAttribute("xpath", prefix2 + field);
                      writer.writeEndElement();
                      lineBreak();
                   }
@@ -1249,106 +1460,109 @@
          writer.writeEndElement(); // xsd:element
          lineBreak();
          
-         if (prodataRelationCount > 0 || (/* !this.isSchemaOnly  && */ !indexes.isEmpty()))
+         if (!minSchema)
          {
-            indent();
-            writer.writeStartElement("xsd:annotation");
-            lineBreak();
-            ++indentLevel;
+            if (prodataRelationCount > 0 || (/* !this.isSchemaOnly  && */ !indexes.isEmpty()))
             {
                indent();
-               writer.writeStartElement("xsd:appinfo");
+               writer.writeStartElement("xsd:annotation");
                lineBreak();
                ++indentLevel;
                {
-//                  if (!isSchemaOnly)
-//                  {
-                     for (Map.Entry<Integer, Pair<String, TableMapper.LegacyIndexInfo>> indexEntry :
-                           indexes.entrySet())
-                     {
-                        Pair<String, TableMapper.LegacyIndexInfo> idxPair = indexEntry.getValue();
-                        TableMapper.LegacyIndexInfo index = idxPair.getRight();
-                        if (index.isUnique())
-                        {
-                           continue; // only NON-unique indexes here
-                        }
-                        
-                        indent();
-                        writer.writeStartElement("prodata:index");
-                        writer.writeAttribute("name", index.getLegacyName());
-                        if (index.isEffectivePrimary())
-                        {
-                           writer.writeAttribute("prodata:primaryIndex", "true");
-                        }
-                        if (index.isWord())
-                        {
-                           writer.writeAttribute("prodata:wordIndex", "true");
-                        }
-                        lineBreak();
-                        ++indentLevel;
-                        {
-                           indent();
-                           writer.writeEmptyElement("prodata:table");
-                           writer.writeAttribute("name", idxPair.getLeft());
-                           lineBreak();
+                  indent();
+                  writer.writeStartElement("xsd:appinfo");
+                  lineBreak();
+                  ++indentLevel;
+                  {
+//                     if (!isSchemaOnly)
+//                     {
+                        for (Map.Entry<Integer, Pair<String, TableMapper.LegacyIndexInfo>> indexEntry :
+                              indexes.entrySet())
+                        {
+                           Pair<String, TableMapper.LegacyIndexInfo> idxPair = indexEntry.getValue();
+                           TableMapper.LegacyIndexInfo index = idxPair.getRight();
+                           if (index.isUnique())
+                           {
+                              continue; // only NON-unique indexes here
+                           }
                            
-                           String[] comps = index.getComponents();
-                           boolean[] dirs = index.getComponentsDirection();
-                           for (int i = 0; i < comps.length; i++)
+                           indent();
+                           writer.writeStartElement("prodata:index");
+                           writer.writeAttribute("name", index.getLegacyName());
+                           if (index.isEffectivePrimary())
+                           {
+                              writer.writeAttribute("prodata:primaryIndex", "true");
+                           }
+                           if (index.isWord())
+                           {
+                              writer.writeAttribute("prodata:wordIndex", "true");
+                           }
+                           lineBreak();
+                           ++indentLevel;
                            {
                               indent();
-                              writer.writeEmptyElement("prodata:field");
-                              writer.writeAttribute("name", comps[i]);
-                              if (!dirs[i])
+                              writer.writeEmptyElement("prodata:table");
+                              writer.writeAttribute("name", idxPair.getLeft());
+                              lineBreak();
+                              
+                              String[] comps = index.getComponents();
+                              boolean[] dirs = index.getComponentsDirection();
+                              for (int i = 0; i < comps.length; i++)
                               {
-                                 writer.writeAttribute("prodata:descending", "true");
+                                 indent();
+                                 writer.writeEmptyElement("prodata:field");
+                                 writer.writeAttribute("name", comps[i]);
+                                 if (!dirs[i])
+                                 {
+                                    writer.writeAttribute("prodata:descending", "true");
+                                 }
+                                 lineBreak();
                               }
-                              lineBreak();
                            }
-                        }
-                        --indentLevel;
+                           --indentLevel;
+                           indent();
+                           writer.writeEndElement(); // prodata:index
+                           lineBreak();
+                        }
+                     }
+                     
+                     for (int k = 0; k < relCount; k++)
+                     {
+                        DataRelation rel = (DataRelation) dataSet.getRelation(k + 1).getResource();// base-1
+                        if (keyrefs.contains(rel))
+                        {
+                           continue; // this relation was serialized as a [xsd:keyref] above
+                        }
+                        if (rel.isParentIdRelation().getValue())
+                        {
+                           continue;
+                        }
+                        
                         indent();
-                        writer.writeEndElement(); // prodata:index
+                        writer.writeEmptyElement("prodata:relation");
+                        writer.writeAttribute("name", rel.name().toStringMessage());
+                        if (rel.isNested().booleanValue())
+                        {
+                           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:relationFields", rel.getRelationFields().toStringMessage());
                         lineBreak();
                      }
                   }
-                  
-                  for (int k = 0; k < relCount; k++)
-                  {
-                     DataRelation rel = (DataRelation) dataSet.getRelation(k + 1).getResource();// base-1
-                     if (keyrefs.contains(rel))
-                     {
-                        continue; // this relation was serialized as a [xsd:keyref] above
-                     }
-                     if (rel.isParentIdRelation().getValue())
-                     {
-                        continue;
-                     }
-                     
-                     indent();
-                     writer.writeEmptyElement("prodata:relation");
-                     writer.writeAttribute("name", rel.name().toStringMessage());
-                     if (rel.isNested().booleanValue())
-                     {
-                        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:relationFields", rel.getRelationFields().toStringMessage());
-                     lineBreak();
-                  }
+                  --indentLevel;
+                  indent();
+                  writer.writeEndElement(); // xsd:appinfo
+                  lineBreak();
                }
                --indentLevel;
                indent();
-               writer.writeEndElement(); // xsd:appinfo
+               writer.writeEndElement(); // xsd:annotation
                lineBreak();
             }
-            --indentLevel;
-            indent();
-            writer.writeEndElement(); // xsd:annotation
-            lineBreak();
+//         }
          }
-//      }
       --indentLevel;
       indent();
       writer.writeEndElement(); // xsd:schema
@@ -1358,6 +1572,47 @@
    }
    
    /**
+    * Write external schema for a table
+    * @param tts
+    *        table in question
+    * @param   minSchema
+    *          {@code true} to write minimal schema information; {@code false} to write verbose
+    *          schema information. Ignored if {@code writeXmlSchema} is {@code false}. Not
+    *          currently honored.
+    * @param   defaultValues
+    *          If {@code true}, the initial values for the fields will be written. 
+    * @return name of the schema file
+    * 
+    * @throws  XMLStreamException
+    *          If XML-related issued occur.
+    */
+   private String writeExternalSchema(TempTableSchema tts, 
+            boolean minSchema, boolean defaultValues) 
+   throws XMLStreamException
+   {
+      Path path = Paths.get(((character) target.getDestination()).toJavaType());
+      Path fileName = path.getFileName();
+      String fn = fileName.toString();
+      String extSchema = fn.substring(0, fn.length() - ".xsd".length()) + "_" + tts.getName() + ".xsd";
+      String extPath = path.getParent().toString() + "/" + extSchema;
+      XmlExport export = new XmlExport(new TargetData("file", extPath), format, encoding);
+      export.external = true;
+      TemporaryBuffer tb = (TemporaryBuffer)tts.buffer();
+      boolean ok = export.write(
+               () -> export.writeTableSchema((BufferImpl)tb.getDMOProxy(), tts, 
+                        minSchema, defaultValues, true)
+      );
+      if (!ok)
+      {
+         return null;
+      }
+      this.indexes.putAll(export.indexes);
+      this.uidxByUniqueNames.putAll(export.uidxByUniqueNames);
+      this.uidxUniqueNames.putAll(export.uidxUniqueNames);
+      return extSchema;
+   }
+
+   /**
     * Writes the XML-SCHEMA of a TEMP-TABLE to XML stream.
     *
     * @param   buffer
@@ -1391,52 +1646,61 @@
    {
       String legacyName = schema.getName();
       boolean isDataset = (ds != null);
+      Iterable<TempTableSchema.Column> elements = schema.elementColumns();
+      Iterable<TempTableSchema.Column> attributes = schema.attributeColumns();
+      boolean hasAttrs = attributes.iterator().hasNext();
+      SortedSet<Integer> fields = new TreeSet<>();
+      if (hasAttrs)
+      {
+         for (TempTableSchema.Column column : schema.columns())
+         {
+            if (column.getNodeType() != XmlNodeType.HIDDEN)
+            {
+               fields.add(column.getOrder());
+            }
+         }
+      }
       
-      indent();
-      writer.writeStartElement("xsd:element");
-      writer.writeAttribute("name", tableName);
-      writer.writeAttribute("minOccurs", "0");
-      writer.writeAttribute("maxOccurs", "unbounded");
-      if (isDataset && !legacyName.equals(tableName))
-      {
-         writer.writeAttribute("prodata:tableName", legacyName);
-      }
-      if (inDataset && !minSchema && !schema.isNoUndo())
-      {
-         writer.writeAttribute("prodata:undo", "true");
-         if (buffer.isAfterBuffer())
-         {
-            // using [buffer.beforeBuffer().unwrap().name()] will raise a [DeferredLegacyErrorException]
-            String beforeName = ((BufferImpl) buffer.beforeBuffer().getResource()).doGetName();
-            writer.writeAttribute("prodata:beforeTable", beforeName);
-         }
-      }
-      lineBreak();
-      ++indentLevel;
+      if (!external)
       {
          indent();
-         writer.writeStartElement("xsd:complexType");
+         writer.writeStartElement("xsd:element");
+         writer.writeAttribute("name", tableName);
+         writer.writeAttribute("minOccurs", "0");
+         writer.writeAttribute("maxOccurs", "unbounded");
+         if (isDataset && !legacyName.equals(tableName))
+         {
+            writer.writeAttribute("prodata:tableName", legacyName);
+         }
+         if (inDataset && !minSchema && !schema.isNoUndo())
+         {
+            writer.writeAttribute("prodata:undo", "true");
+            if (buffer.isAfterBuffer())
+            {
+               // using [buffer.beforeBuffer().unwrap().name()] will raise a [DeferredLegacyErrorException]
+               String beforeName = ((BufferImpl) buffer.beforeBuffer().getResource()).doGetName();
+               writer.writeAttribute("prodata:beforeTable", beforeName);
+            }
+         }
          lineBreak();
          ++indentLevel;
-         Iterable<TempTableSchema.Column> elements = schema.elementColumns();
-         Iterable<TempTableSchema.Column> attributes = schema.attributeColumns();
-         boolean hasAttrs = attributes.iterator().hasNext();
-         SortedSet<Integer> fields = new TreeSet<>();
-         if (hasAttrs)
-         {
-            for (TempTableSchema.Column column : schema.columns())
-            {
-               if (column.getNodeType() != XmlNodeType.HIDDEN)
-               {
-                  fields.add(column.getOrder());
-               }
-            }
-         }
+      }
+      {
+         if (!external)
          {
             indent();
-            writer.writeStartElement("xsd:sequence");
+            writer.writeStartElement("xsd:complexType");
             lineBreak();
             ++indentLevel;
+         }
+         {
+            if (!external)
+            {
+               indent();
+               writer.writeStartElement("xsd:sequence");
+               lineBreak();
+               ++indentLevel;
+            }
             {
                for (TempTableSchema.Column column : elements)
                {
@@ -1537,18 +1801,23 @@
             }
             lineBreak();
          }
-
+         if (!external)
+         {
+            --indentLevel;
+            indent();
+            writer.writeEndElement(); // xsd:complexType
+            lineBreak();
+         }
+      }
+      
+      if (!external)
+      {
          --indentLevel;
          indent();
-         writer.writeEndElement(); // xsd:complexType
+         writer.writeEndElement(); // xsd:element
          lineBreak();
       }
       
-      --indentLevel;
-      indent();
-      writer.writeEndElement(); // xsd:element
-      lineBreak();
-      
       int keyPrefix = (this.ds == null) ? 0 : ds.getIndexOf(buffer);
       int i = 0;
       // save now the index list to be processed later 
@@ -1583,7 +1852,6 @@
     * @param   isDataset
     *          If {@code true}, this is part of a dataset SCHEMA and additional attributes will
     *          be written.
-    *
     * @return  {@code true} on success. Otherwise the error is already dispatched to 
     *          {@code ErrorManager} before returning.
     *          
@@ -1634,7 +1902,7 @@
       {
          writer.writeAttribute("nillable", String.valueOf(column.isNillable()));
       }
-      if (addType != null)
+      if (addType != null && defaultValues)
       {
          writer.writeAttribute("prodata:dataType", addType);
       }
@@ -1643,42 +1911,68 @@
       {
          if (extent != null && extent > 0)
          {
-            writer.writeAttribute("minOccurs", String.valueOf(extent));
+            writer.writeAttribute("minOccurs", defaultValues ? String.valueOf(extent) : "0");
             writer.writeAttribute("maxOccurs", String.valueOf(extent));
          }
+         else if (!defaultValues && !isAttr)
+         {
+            writer.writeAttribute("minOccurs", "0");
+         }
       }
       else
       {
-         if (!defaultValues)
+         if (extent != null && extent > 0)
+         {
+            writer.writeAttribute("minOccurs", defaultValues ? String.valueOf(extent) : "0");
+            writer.writeAttribute("maxOccurs", String.valueOf(extent));
+         }
+         else if (!defaultValues && !isAttr)
          {
             writer.writeAttribute("minOccurs", "0");
          }
-         else if (extent != null && extent > 0)
-         {
-            writer.writeAttribute("minOccurs", String.valueOf(extent));
-            writer.writeAttribute("maxOccurs", String.valueOf(extent));
-         }
-
-      }
-      if (isDataset)
-      {
-         if (defaultValues)
-         {
+
+      }
+      if (addType != null && !defaultValues)
+      {
+         writer.writeAttribute("prodata:dataType", addType);
+      }
+
+      if (isDataset && defaultValues)
+      {
+//         if (!defaultValues)
+//         {
             String initial = column.getInitial();
             String defVal = Util.defaultValuesMap.get(columnType);
+            if (initial == null && !minSchema)
+            {
+               initial = defVal;
+            }
             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("?") || 
+                        (column.getType().equals(raw.class) && "".equals(initial)))
+               {
+                  writer.writeAttribute("prodata:initial", "prodata:unknown");
+               }
+               else
+               {
+                  writer.writeAttribute("default", initial);
+               }
             }
-         }
+//         }
       }
       else
       {
          String initial = column.getInitial();
          if (initial != null)
          {
-            boolean initialNull = "?".equals(initial);
+            boolean initialNull = "?".equals(initial) || 
+                     (column.getType().equals(raw.class) && "".equals(initial));
             if (!defaultValues || !initial.equals(Util.defaultValuesMap.get(columnType)))
             {
                if (!initialNull && type.contains("decimal") && !initial.contains("."))
@@ -1693,7 +1987,8 @@
                }
                else
                {
-                  writer.writeAttribute("default", initialNull ? "prodata:unknown" : initial);
+                  writer.writeAttribute(initialNull ? "prodata:initial" : "default", 
+                                        initialNull ? "prodata:unknown" : initial);
                }
             }
          }
@@ -1720,13 +2015,13 @@
       {
          writer.writeAttribute("prodata:fieldName", fieldName);
       }
-      if (hasAttributes)
+      if (!minSchema && hasAttributes)
       {
          int userOrder = fields.headSet(column.getOrder()).size() + 1;
          writer.writeAttribute("prodata:userOrder", String.valueOf(userOrder));
       }
 
-      if ("prodata:clob".equals(addType))
+      if (!minSchema && "prodata:clob".equals(addType))
       {
          String cp = column.getCodePage();
          if (!StringUtils.isEmpty(cp))
@@ -1736,16 +2031,17 @@
       }
 
 
-//      if (!isSchemaOnly)
-//      {
+      if (!minSchema )
+      {
          String fmt = column.getDefinedFormat();
          
          BaseDataType defValue = BaseDataType.generateDefault(columnType);
-         if (!StringUtils.isEmpty(fmt) && !fmt.equalsIgnoreCase(defValue.defaultFormatString()))
+         if (!StringUtils.isEmpty(fmt) && (
+                  /* defaultValues || */ !fmt.equalsIgnoreCase(defValue.defaultFormatString())))
          {
             writer.writeAttribute("prodata:format", fmt);
          }
-//      }
+      }
       
       
       if (!minSchema)
@@ -1909,10 +2205,10 @@
          
          indent();
          boolean hasTextNodes = schema.textColumns().iterator().hasNext();
-         writer.writeStartElement(rowName);
+         writer.writeStartElement((ttNsPrefix == null || rowName.contains(":") ? "" : ttNsPrefix + ":") + rowName);
          if (xmlns != null && !xmlns.isEmpty())
          {
-            writer.writeAttribute("xmlns", xmlns);
+            writer.writeAttribute("xmlns" + (ttNsPrefix == null ? "" : ":" + ttNsPrefix) , xmlns);
          }
          
          // NOTE: the next conditional is half commented out because, in some cases which we were not able to
@@ -2342,8 +2638,11 @@
        * 
        * @return  {@code true} on success. Otherwise the errors encountered were already notified
        *          to {@code ErrorManager}.
+       * @throws XMLStreamException 
+       *         on unexpected processing error.
+       * @throws IOException
+       *         on I/O error 
        *
-       * @see     java.lang.Thread#run()
        */
       public abstract boolean run()
       throws XMLStreamException, IOException;

=== 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-08 15:02:19 +0000
@@ -247,6 +247,8 @@
 **                           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 message for error 12323.
+**     IAS 20221100          Added message for warning 13095.
 */
 
 /*
@@ -3083,7 +3085,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;
@@ -3146,6 +3148,7 @@
          case 13090: msg = "XML Schema definition for field '%1' in table '%2' not found"; break;
          case 13091: msg = "XML Schema definition for table '%1' contains extra field '%2'"; break;
          case 13093: msg = "Write temp-table data failed for WRITE-XML"; break;
+         case 13095: msg = "WRITE-XML target-type must be 'FILE' when buffers of a dataset have a different NAMESPACE-URI"; break;
          case 13097: msg = "Write schema failed for WRITE-XMLSCHEMA"; break;
          case 13138: msg = "Temp-table '%1' not found in XML Schema"; break;
 case 13139: msg = "Field '%1' already added from XML Schema"; 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-11 09:23:16 +0000
@@ -38,6 +38,9 @@
 **                  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.
+**     IAS 20221111 Fixed 'schemaMarshalLevel' support.
 */
 
 /*
@@ -134,6 +137,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 +224,8 @@
       this.options     = options;
       this.input       = input;
       this.output      = output;
+      this.schemaMarshalLevel = ((AbstractTempTable)this.tableHandle.unwrapTempTable()).
+                                       getSchemaMarshalLevel();
    }
    
    /**
@@ -390,11 +398,12 @@
       // 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(),
-                                                              resultSet.getXmlPrefix());
+                                                              resultSet.getXmlPrefix(),
+                                                              resultSet.getSchemaMarshalLevel());
          
          TemporaryBuffer.insertAllRows(resultSet,
                                        (Temporary) buff,
@@ -596,6 +605,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).
     *

