2009-05-27 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mcs / class / FirebirdSql.Data.Firebird / FirebirdSql.Data.Embedded / XsqldaMarshaler.cs
index 777266410762ed9345f8a693765b75f871a2a76b..5998c09360118fec4c00783542155e57597aa535 100644 (file)
-/*\r
- *     Firebird ADO.NET Data provider for .NET and     Mono \r
- * \r
- *        The contents of this file are subject to the Initial \r
- *        Developer's Public License Version 1.0 (the "License"); \r
- *        you may not use this file except in compliance with the \r
- *        License. You may obtain a copy of the License at \r
- *        http://www.firebirdsql.org/index.php?op=doc&id=idpl\r
- *\r
- *        Software distributed under the License is distributed on \r
- *        an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either \r
- *        express or implied. See the License for the specific \r
- *        language governing rights and limitations under the License.\r
- * \r
- *     Copyright (c) 2002, 2005 Carlos Guzman Alvarez\r
- *     All Rights Reserved.\r
- */\r
-\r
-using System;\r
-using System.Runtime.InteropServices;\r
-using System.Text;\r
-\r
-using FirebirdSql.Data.Common;\r
-\r
-namespace FirebirdSql.Data.Embedded\r
-{\r
-       internal sealed class XsqldaMarshaler\r
-       {\r
-               #region Static Fields\r
-\r
-               private static XsqldaMarshaler instance;\r
-\r
-               #endregion\r
-\r
-               #region Constructors\r
-\r
-               private XsqldaMarshaler()\r
-               {\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Methods\r
-\r
-               public static XsqldaMarshaler GetInstance()\r
-               {\r
-                       if (XsqldaMarshaler.instance == null)\r
-                       {\r
-                               XsqldaMarshaler.instance = new XsqldaMarshaler();\r
-                       }\r
-\r
-                       return XsqldaMarshaler.instance;\r
-               }\r
-\r
-               public void     CleanUpNativeData(ref IntPtr pNativeData)\r
-               {\r
-                       if (pNativeData != IntPtr.Zero)\r
-                       {\r
-                               // Obtain XSQLDA information\r
-                               XSQLDA xsqlda = new     XSQLDA();\r
-                       \r
-                               xsqlda = (XSQLDA)Marshal.PtrToStructure(pNativeData, typeof(XSQLDA));\r
-\r
-                               // Destroy XSQLDA structure\r
-                               Marshal.DestroyStructure(pNativeData, typeof(XSQLDA));\r
-\r
-                               // Destroy XSQLVAR structures\r
-                               for     (int i = 0;     i <     xsqlda.sqln; i++)\r
-                               {\r
-                                       // Free sqldata and     sqlind pointers if needed\r
-                                       XSQLVAR sqlvar = (XSQLVAR)Marshal.PtrToStructure(\r
-                                               this.GetIntPtr(pNativeData,     this.ComputeLength(i)), typeof(XSQLVAR));\r
-\r
-                                       if (sqlvar.sqldata != IntPtr.Zero)\r
-                                       {\r
-                                               Marshal.FreeHGlobal(sqlvar.sqldata);\r
-                                               sqlvar.sqldata = IntPtr.Zero;\r
-                                       }\r
-                                       if (sqlvar.sqlind != IntPtr.Zero)\r
-                                       {\r
-                                               Marshal.FreeHGlobal(sqlvar.sqlind);\r
-                                               sqlvar.sqlind = IntPtr.Zero;\r
-                                       }\r
-\r
-                                       Marshal.DestroyStructure(\r
-                                               this.GetIntPtr(pNativeData,     this.ComputeLength(i)), typeof(XSQLVAR));\r
-                               }\r
-\r
-                               // Free pointer memory\r
-                               Marshal.FreeHGlobal(pNativeData);\r
-\r
-                               pNativeData = IntPtr.Zero;\r
-                       }\r
-               }\r
-\r
-               public IntPtr MarshalManagedToNative(Charset charset, Descriptor descriptor)\r
-               {\r
-                       // Set up XSQLDA structure\r
-                       XSQLDA xsqlda = new XSQLDA();\r
-\r
-                       xsqlda.version = descriptor.Version;\r
-                       xsqlda.sqln      = descriptor.Count;\r
-                       xsqlda.sqld      = descriptor.ActualCount;\r
-                       \r
-                       XSQLVAR[] xsqlvar = new XSQLVAR[descriptor.Count];\r
-\r
-                       for     (int i = 0;     i <     xsqlvar.Length; i++)\r
-                       {\r
-                               // Create a     new     XSQLVAR structure and fill it\r
-                               xsqlvar[i] = new XSQLVAR();\r
-\r
-                               xsqlvar[i].sqltype       = descriptor[i].DataType;\r
-                               xsqlvar[i].sqlscale      = descriptor[i].NumericScale;\r
-                               xsqlvar[i].sqlsubtype = descriptor[i].SubType;\r
-                               xsqlvar[i].sqllen        = descriptor[i].Length;\r
-\r
-                               // Create a     new     pointer for     the     xsqlvar data\r
-                               byte[] buffer = this.GetBytes(descriptor[i]);\r
-                               if (buffer.Length > 0)\r
-                               {\r
-                                       xsqlvar[i].sqldata = Marshal.AllocHGlobal(buffer.Length);\r
-                                       Marshal.Copy(buffer, 0, xsqlvar[i].sqldata,     buffer.Length);\r
-                               }\r
-\r
-                               // Create a     new     pointer for     the     sqlind value\r
-                               xsqlvar[i].sqlind = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Int16)));\r
-                               Marshal.WriteInt16(xsqlvar[i].sqlind, descriptor[i].NullFlag);                            \r
-\r
-                               // Name\r
-                               xsqlvar[i].sqlname               = this.GetStringBuffer(charset,        descriptor[i].Name);\r
-                               xsqlvar[i].sqlname_length = (short)xsqlvar[i].sqlname.Length;\r
-\r
-                               // Relation     Name\r
-                               xsqlvar[i].relname               = this.GetStringBuffer(charset,        descriptor[i].Relation);\r
-                               xsqlvar[i].relname_length = (short)xsqlvar[i].relname.Length;\r
-\r
-                               // Owner name\r
-                               xsqlvar[i].ownername     = this.GetStringBuffer(charset,        descriptor[i].Owner);\r
-                               xsqlvar[i].ownername_length = (short)xsqlvar[i].ownername.Length;\r
-\r
-                               // Alias name\r
-                               xsqlvar[i].aliasname     = this.GetStringBuffer(charset,        descriptor[i].Alias);\r
-                               xsqlvar[i].aliasname_length = (short)xsqlvar[i].aliasname.Length;\r
-                       }\r
-\r
-                       return this.MarshalManagedToNative(xsqlda, xsqlvar);\r
-               }\r
-\r
-               public IntPtr MarshalManagedToNative(XSQLDA     xsqlda, XSQLVAR[] xsqlvar)\r
-               {\r
-                       int             size = this.ComputeLength(xsqlda.sqln);\r
-                       IntPtr  ptr      = Marshal.AllocHGlobal(size);\r
-\r
-                       Marshal.StructureToPtr(xsqlda, ptr,     true);\r
-\r
-                       for     (int i = 0;     i <     xsqlvar.Length; i++)\r
-                       {\r
-                               int     offset = this.ComputeLength(i);\r
-                               Marshal.StructureToPtr(xsqlvar[i], this.GetIntPtr(ptr, offset), true);\r
-                       }\r
-\r
-                       return ptr;\r
-               }\r
-\r
-               public Descriptor MarshalNativeToManaged(Charset charset, IntPtr pNativeData)\r
-               {\r
-                       // Obtain XSQLDA information\r
-                       XSQLDA xsqlda = new     XSQLDA();\r
-                       \r
-                       xsqlda = (XSQLDA)Marshal.PtrToStructure(pNativeData, typeof(XSQLDA));\r
-\r
-                       // Create a     new     Descriptor\r
-                       Descriptor descriptor = new Descriptor(xsqlda.sqln);\r
-                       descriptor.ActualCount = xsqlda.sqld;\r
-                       \r
-                       // Obtain XSQLVAR members information\r
-                       XSQLVAR[] xsqlvar = new XSQLVAR[xsqlda.sqln];\r
-                       \r
-                       for     (int i = 0;     i <     xsqlvar.Length; i++)\r
-                       {\r
-                               xsqlvar[i] = (XSQLVAR)Marshal.PtrToStructure(\r
-                                       this.GetIntPtr(pNativeData,     this.ComputeLength(i)), typeof(XSQLVAR));\r
-\r
-                               // Map XSQLVAR information to Descriptor\r
-                               descriptor[i].DataType   = xsqlvar[i].sqltype;\r
-                               descriptor[i].NumericScale = xsqlvar[i].sqlscale;\r
-                               descriptor[i].SubType    = xsqlvar[i].sqlsubtype;\r
-                               descriptor[i].Length     = xsqlvar[i].sqllen;\r
-\r
-                               // Decode sqlind value\r
-                               if (xsqlvar[i].sqlind == IntPtr.Zero)\r
-                               {\r
-                                       descriptor[i].NullFlag = 0;\r
-                               }\r
-                               else\r
-                               {\r
-                                       descriptor[i].NullFlag = Marshal.ReadInt16(xsqlvar[i].sqlind);\r
-                               }\r
-                               \r
-                               // Set value\r
-                               if (descriptor[i].NullFlag != -1)\r
-                               {\r
-                                       descriptor[i].SetValue(this.GetBytes(xsqlvar[i]));\r
-                               }\r
-                               \r
-                               descriptor[i].Name       = this.GetString(charset, xsqlvar[i].sqlname);\r
-                               descriptor[i].Relation = this.GetString(charset, xsqlvar[i].relname);\r
-                               descriptor[i].Owner      = this.GetString(charset, xsqlvar[i].ownername);\r
-                               descriptor[i].Alias      = this.GetString(charset, xsqlvar[i].aliasname);\r
-                       }\r
-\r
-                       return descriptor;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Private methods\r
-\r
-               private IntPtr GetIntPtr(IntPtr ptr, int offset)\r
-               {\r
-                       return (IntPtr)(ptr.ToInt32() + offset);\r
-               }\r
-\r
-               private int     ComputeLength(int n)\r
-               {\r
-                       return (Marshal.SizeOf(typeof(XSQLDA)) + n * Marshal.SizeOf(typeof(XSQLVAR)));\r
-               }\r
-\r
-               private byte[] GetBytes(XSQLVAR xsqlvar)\r
-               {\r
-                       if (xsqlvar.sqllen == 0 || xsqlvar.sqldata == IntPtr.Zero)\r
-                       {\r
-                               return null;\r
-                       }\r
-\r
-                       byte[] buffer = new     byte[xsqlvar.sqllen];\r
-\r
-                       switch (xsqlvar.sqltype & ~1)\r
-                       {\r
-                               case IscCodes.SQL_VARYING:\r
-                                       short length = Marshal.ReadInt16(xsqlvar.sqldata);\r
-\r
-                                       buffer = new byte[length];\r
-\r
-                                       IntPtr tmp = this.GetIntPtr(xsqlvar.sqldata, 2);\r
-\r
-                                       Marshal.Copy(tmp, buffer, 0, buffer.Length);\r
-\r
-                                       return buffer;\r
-\r
-                               case IscCodes.SQL_TEXT: \r
-                               case IscCodes.SQL_SHORT:\r
-                               case IscCodes.SQL_LONG:\r
-                               case IscCodes.SQL_FLOAT:\r
-                               case IscCodes.SQL_DOUBLE:\r
-                               case IscCodes.SQL_D_FLOAT:\r
-                               case IscCodes.SQL_QUAD:\r
-                               case IscCodes.SQL_INT64:\r
-                               case IscCodes.SQL_BLOB:\r
-                               case IscCodes.SQL_ARRAY:        \r
-                               case IscCodes.SQL_TIMESTAMP:\r
-                               case IscCodes.SQL_TYPE_TIME:\r
-                               case IscCodes.SQL_TYPE_DATE:\r
-                                       Marshal.Copy(xsqlvar.sqldata, buffer, 0, buffer.Length);\r
-\r
-                                       return buffer;\r
-\r
-                               default:\r
-                                       throw new NotSupportedException("Unknown data type");\r
-                       }\r
-               }\r
-\r
-               private byte[] GetBytes(DbField field)\r
-               {\r
-                       if (field.DbValue.IsDBNull())\r
-                       {\r
-                               int     length = field.Length;\r
-                               \r
-                               if (field.SqlType == IscCodes.SQL_VARYING)\r
-                               {\r
-                                       // Add two bytes more for store value length\r
-                                       length += 2;\r
-                               }\r
-\r
-                               return new byte[length];\r
-                       }\r
-\r
-                       switch (field.DbDataType)\r
-                       {\r
-                               case DbDataType.Char:\r
-                               {\r
-                                       string svalue = field.DbValue.GetString();\r
-\r
-                                       if ((field.Length %     field.Charset.BytesPerCharacter) == 0 &&\r
-                                               svalue.Length > field.CharCount)\r
-                                       {        \r
-                                               throw new IscException(335544321);       \r
-                                       }\r
-\r
-                                       byte[] buffer = new     byte[field.Length];\r
-                                       for     (int i = 0;     i <     buffer.Length; i++)\r
-                                       {\r
-                                               buffer[i] = 32;\r
-                                       }\r
-\r
-                                       byte[] bytes = field.Charset.GetBytes(svalue);\r
-\r
-                                       Buffer.BlockCopy(bytes, 0, buffer, 0, bytes.Length);\r
-\r
-                                       return buffer;\r
-                               }\r
-                               \r
-                               case DbDataType.VarChar:\r
-                               {\r
-                                       string svalue = field.Value.ToString();\r
-\r
-                                       if ((field.Length %     field.Charset.BytesPerCharacter) == 0 &&\r
-                                               svalue.Length > field.CharCount)\r
-                                       {        \r
-                                               throw new IscException(335544321);       \r
-                                       }\r
-\r
-                                       byte[] sbuffer = field.Charset.GetBytes(svalue);\r
-\r
-                                       byte[] buffer = new     byte[field.Length +     2];\r
-\r
-                                       // Copy length\r
-                                       Buffer.BlockCopy(\r
-                                               BitConverter.GetBytes((short)sbuffer.Length), \r
-                                        0, buffer, 0, 2);\r
-                                       \r
-                                       // Copy string value\r
-                                       Buffer.BlockCopy(sbuffer, 0, buffer, 2, sbuffer.Length);\r
-\r
-                                       return buffer;\r
-                               }\r
-\r
-                               case DbDataType.Numeric:\r
-                               case DbDataType.Decimal:\r
-                                       return this.GetNumericBytes(field);\r
-\r
-                               case DbDataType.SmallInt:\r
-                                       return BitConverter.GetBytes(field.DbValue.GetInt16());\r
-\r
-                               case DbDataType.Integer:\r
-                                       return BitConverter.GetBytes(field.DbValue.GetInt32());\r
-\r
-                               case DbDataType.Array:\r
-                               case DbDataType.Binary:\r
-                               case DbDataType.Text:\r
-                               case DbDataType.BigInt:\r
-                                       return BitConverter.GetBytes(field.DbValue.GetInt64());\r
-\r
-                               case DbDataType.Float:\r
-                                       return BitConverter.GetBytes(field.DbValue.GetFloat());\r
-                                                                       \r
-                               case DbDataType.Double:\r
-                                       return BitConverter.GetBytes(field.DbValue.GetDouble());\r
-\r
-                               case DbDataType.Date:\r
-                                       return BitConverter.GetBytes(\r
-                                               TypeEncoder.EncodeDate(field.DbValue.GetDateTime()));\r
-                               \r
-                               case DbDataType.Time:\r
-                                       return BitConverter.GetBytes(\r
-                                               TypeEncoder.EncodeTime(field.DbValue.GetDateTime()));\r
-                               \r
-                               case DbDataType.TimeStamp:\r
-                                       byte[] date = BitConverter.GetBytes(\r
-                                               TypeEncoder.EncodeDate(field.DbValue.GetDateTime()));\r
-                                       \r
-                                       byte[] time = BitConverter.GetBytes(\r
-                                               TypeEncoder.EncodeTime(field.DbValue.GetDateTime()));\r
-                                       \r
-                                       byte[] result = new     byte[8];\r
-\r
-                                       Buffer.BlockCopy(date, 0, result, 0, date.Length);\r
-                                       Buffer.BlockCopy(time, 0, result, 4, time.Length);\r
-\r
-                                       return result;\r
-\r
-                               case DbDataType.Guid:\r
-                                       return field.DbValue.GetGuid().ToByteArray();\r
-\r
-                               default:\r
-                                       throw new NotSupportedException("Unknown data type");\r
-                       }\r
-               }\r
-\r
-               private byte[] GetNumericBytes(DbField field)\r
-               {\r
-                       decimal value = field.DbValue.GetDecimal();\r
-                       object  numeric = TypeEncoder.EncodeDecimal(value, field.NumericScale, field.DataType);\r
-\r
-                       switch (field.SqlType)\r
-                       {\r
-                               case IscCodes.SQL_SHORT:\r
-                                       return BitConverter.GetBytes((short)numeric);\r
-\r
-                               case IscCodes.SQL_LONG:\r
-                                       return BitConverter.GetBytes((int)numeric);\r
-\r
-                               case IscCodes.SQL_INT64:\r
-                               case IscCodes.SQL_QUAD:\r
-                                       return BitConverter.GetBytes((long)numeric);\r
-\r
-                               case IscCodes.SQL_DOUBLE:\r
-                                       return BitConverter.GetBytes(field.DbValue.GetDouble());\r
-\r
-                               default:\r
-                                       return null;\r
-                       }\r
-               }\r
-\r
-               private byte[] GetStringBuffer(Charset charset, string value)\r
-               {\r
-                       byte[] buffer = new     byte[32];\r
-                       \r
-                       charset.GetBytes(value, 0, value.Length, buffer, 0);\r
-\r
-                       return buffer;\r
-               }\r
-\r
-               private string GetString(Charset charset, byte[] buffer)\r
-               {\r
-                       string value = charset.GetString(buffer);\r
-\r
-                       return value.Replace('\0', ' ').Trim();\r
-               }\r
-\r
-               #endregion\r
-       }\r
-}\r
+/*
+ *     Firebird ADO.NET Data provider for .NET and Mono 
+ * 
+ *        The contents of this file are subject to the Initial 
+ *        Developer's Public License Version 1.0 (the "License"); 
+ *        you may not use this file except in compliance with the 
+ *        License. You may obtain a copy of the License at 
+ *        http://www.firebirdsql.org/index.php?op=doc&id=idpl
+ *
+ *        Software distributed under the License is distributed on 
+ *        an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either 
+ *        express or implied. See the License for the specific 
+ *        language governing rights and limitations under the License.
+ * 
+ *     Copyright (c) 2002, 2005 Carlos Guzman Alvarez
+ *     All Rights Reserved.
+ */
+
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+using FirebirdSql.Data.Common;
+
+namespace FirebirdSql.Data.Embedded
+{
+       internal sealed class XsqldaMarshaler
+       {
+               #region Static Fields
+
+               private static XsqldaMarshaler instance;
+
+               #endregion
+
+               #region Constructors
+
+               private XsqldaMarshaler()
+               {
+               }
+
+               #endregion
+
+               #region Methods
+
+               public static XsqldaMarshaler GetInstance()
+               {
+                       if (XsqldaMarshaler.instance == null)
+                       {
+                               XsqldaMarshaler.instance = new XsqldaMarshaler();
+                       }
+
+                       return XsqldaMarshaler.instance;
+               }
+
+               public void     CleanUpNativeData(ref IntPtr pNativeData)
+               {
+                       if (pNativeData != IntPtr.Zero)
+                       {
+                               // Obtain XSQLDA information
+                               XSQLDA xsqlda = new     XSQLDA();
+                       
+                               xsqlda = (XSQLDA)Marshal.PtrToStructure(pNativeData, typeof(XSQLDA));
+
+                               // Destroy XSQLDA structure
+                               Marshal.DestroyStructure(pNativeData, typeof(XSQLDA));
+
+                               // Destroy XSQLVAR structures
+                               for     (int i = 0;     i <     xsqlda.sqln; i++)
+                               {
+                                       // Free sqldata and     sqlind pointers if needed
+                                       XSQLVAR sqlvar = (XSQLVAR)Marshal.PtrToStructure(
+                                               this.GetIntPtr(pNativeData,     this.ComputeLength(i)), typeof(XSQLVAR));
+
+                                       if (sqlvar.sqldata != IntPtr.Zero)
+                                       {
+                                               Marshal.FreeHGlobal(sqlvar.sqldata);
+                                               sqlvar.sqldata = IntPtr.Zero;
+                                       }
+                                       if (sqlvar.sqlind != IntPtr.Zero)
+                                       {
+                                               Marshal.FreeHGlobal(sqlvar.sqlind);
+                                               sqlvar.sqlind = IntPtr.Zero;
+                                       }
+
+                                       Marshal.DestroyStructure(
+                                               this.GetIntPtr(pNativeData,     this.ComputeLength(i)), typeof(XSQLVAR));
+                               }
+
+                               // Free pointer memory
+                               Marshal.FreeHGlobal(pNativeData);
+
+                               pNativeData = IntPtr.Zero;
+                       }
+               }
+
+               public IntPtr MarshalManagedToNative(Charset charset, Descriptor descriptor)
+               {
+                       // Set up XSQLDA structure
+                       XSQLDA xsqlda = new XSQLDA();
+
+                       xsqlda.version = descriptor.Version;
+                       xsqlda.sqln      = descriptor.Count;
+                       xsqlda.sqld      = descriptor.ActualCount;
+                       
+                       XSQLVAR[] xsqlvar = new XSQLVAR[descriptor.Count];
+
+                       for     (int i = 0;     i <     xsqlvar.Length; i++)
+                       {
+                               // Create a     new     XSQLVAR structure and fill it
+                               xsqlvar[i] = new XSQLVAR();
+
+                               xsqlvar[i].sqltype       = descriptor[i].DataType;
+                               xsqlvar[i].sqlscale      = descriptor[i].NumericScale;
+                               xsqlvar[i].sqlsubtype = descriptor[i].SubType;
+                               xsqlvar[i].sqllen        = descriptor[i].Length;
+
+                               // Create a     new     pointer for     the     xsqlvar data
+                               byte[] buffer = this.GetBytes(descriptor[i]);
+                               if (buffer.Length > 0)
+                               {
+                                       xsqlvar[i].sqldata = Marshal.AllocHGlobal(buffer.Length);
+                                       Marshal.Copy(buffer, 0, xsqlvar[i].sqldata,     buffer.Length);
+                               }
+
+                               // Create a     new     pointer for     the     sqlind value
+                               xsqlvar[i].sqlind = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Int16)));
+                               Marshal.WriteInt16(xsqlvar[i].sqlind, descriptor[i].NullFlag);                            
+
+                               // Name
+                               xsqlvar[i].sqlname               = this.GetStringBuffer(charset,        descriptor[i].Name);
+                               xsqlvar[i].sqlname_length = (short)xsqlvar[i].sqlname.Length;
+
+                               // Relation     Name
+                               xsqlvar[i].relname               = this.GetStringBuffer(charset,        descriptor[i].Relation);
+                               xsqlvar[i].relname_length = (short)xsqlvar[i].relname.Length;
+
+                               // Owner name
+                               xsqlvar[i].ownername     = this.GetStringBuffer(charset,        descriptor[i].Owner);
+                               xsqlvar[i].ownername_length = (short)xsqlvar[i].ownername.Length;
+
+                               // Alias name
+                               xsqlvar[i].aliasname     = this.GetStringBuffer(charset,        descriptor[i].Alias);
+                               xsqlvar[i].aliasname_length = (short)xsqlvar[i].aliasname.Length;
+                       }
+
+                       return this.MarshalManagedToNative(xsqlda, xsqlvar);
+               }
+
+               public IntPtr MarshalManagedToNative(XSQLDA     xsqlda, XSQLVAR[] xsqlvar)
+               {
+                       int             size = this.ComputeLength(xsqlda.sqln);
+                       IntPtr  ptr      = Marshal.AllocHGlobal(size);
+
+                       Marshal.StructureToPtr(xsqlda, ptr,     true);
+
+                       for     (int i = 0;     i <     xsqlvar.Length; i++)
+                       {
+                               int     offset = this.ComputeLength(i);
+                               Marshal.StructureToPtr(xsqlvar[i], this.GetIntPtr(ptr, offset), true);
+                       }
+
+                       return ptr;
+               }
+
+               public Descriptor MarshalNativeToManaged(Charset charset, IntPtr pNativeData)
+               {
+                       // Obtain XSQLDA information
+                       XSQLDA xsqlda = new     XSQLDA();
+                       
+                       xsqlda = (XSQLDA)Marshal.PtrToStructure(pNativeData, typeof(XSQLDA));
+
+                       // Create a     new     Descriptor
+                       Descriptor descriptor = new Descriptor(xsqlda.sqln);
+                       descriptor.ActualCount = xsqlda.sqld;
+                       
+                       // Obtain XSQLVAR members information
+                       XSQLVAR[] xsqlvar = new XSQLVAR[xsqlda.sqln];
+                       
+                       for     (int i = 0;     i <     xsqlvar.Length; i++)
+                       {
+                               xsqlvar[i] = (XSQLVAR)Marshal.PtrToStructure(
+                                       this.GetIntPtr(pNativeData,     this.ComputeLength(i)), typeof(XSQLVAR));
+
+                               // Map XSQLVAR information to Descriptor
+                               descriptor[i].DataType   = xsqlvar[i].sqltype;
+                               descriptor[i].NumericScale = xsqlvar[i].sqlscale;
+                               descriptor[i].SubType    = xsqlvar[i].sqlsubtype;
+                               descriptor[i].Length     = xsqlvar[i].sqllen;
+
+                               // Decode sqlind value
+                               if (xsqlvar[i].sqlind == IntPtr.Zero)
+                               {
+                                       descriptor[i].NullFlag = 0;
+                               }
+                               else
+                               {
+                                       descriptor[i].NullFlag = Marshal.ReadInt16(xsqlvar[i].sqlind);
+                               }
+                               
+                               // Set value
+                               if (descriptor[i].NullFlag != -1)
+                               {
+                                       descriptor[i].SetValue(this.GetBytes(xsqlvar[i]));
+                               }
+                               
+                               descriptor[i].Name       = this.GetString(charset, xsqlvar[i].sqlname);
+                               descriptor[i].Relation = this.GetString(charset, xsqlvar[i].relname);
+                               descriptor[i].Owner      = this.GetString(charset, xsqlvar[i].ownername);
+                               descriptor[i].Alias      = this.GetString(charset, xsqlvar[i].aliasname);
+                       }
+
+                       return descriptor;
+               }
+
+               #endregion
+
+               #region Private methods
+
+               private IntPtr GetIntPtr(IntPtr ptr, int offset)
+               {
+                       return (IntPtr)(ptr.ToInt32() + offset);
+               }
+
+               private int     ComputeLength(int n)
+               {
+                       return (Marshal.SizeOf(typeof(XSQLDA)) + n * Marshal.SizeOf(typeof(XSQLVAR)));
+               }
+
+               private byte[] GetBytes(XSQLVAR xsqlvar)
+               {
+                       if (xsqlvar.sqllen == 0 || xsqlvar.sqldata == IntPtr.Zero)
+                       {
+                               return null;
+                       }
+
+                       byte[] buffer = new     byte[xsqlvar.sqllen];
+
+                       switch (xsqlvar.sqltype & ~1)
+                       {
+                               case IscCodes.SQL_VARYING:
+                                       short length = Marshal.ReadInt16(xsqlvar.sqldata);
+
+                                       buffer = new byte[length];
+
+                                       IntPtr tmp = this.GetIntPtr(xsqlvar.sqldata, 2);
+
+                                       Marshal.Copy(tmp, buffer, 0, buffer.Length);
+
+                                       return buffer;
+
+                               case IscCodes.SQL_TEXT: 
+                               case IscCodes.SQL_SHORT:
+                               case IscCodes.SQL_LONG:
+                               case IscCodes.SQL_FLOAT:
+                               case IscCodes.SQL_DOUBLE:
+                               case IscCodes.SQL_D_FLOAT:
+                               case IscCodes.SQL_QUAD:
+                               case IscCodes.SQL_INT64:
+                               case IscCodes.SQL_BLOB:
+                               case IscCodes.SQL_ARRAY:        
+                               case IscCodes.SQL_TIMESTAMP:
+                               case IscCodes.SQL_TYPE_TIME:
+                               case IscCodes.SQL_TYPE_DATE:
+                                       Marshal.Copy(xsqlvar.sqldata, buffer, 0, buffer.Length);
+
+                                       return buffer;
+
+                               default:
+                                       throw new NotSupportedException("Unknown data type");
+                       }
+               }
+
+               private byte[] GetBytes(DbField field)
+               {
+                       if (field.DbValue.IsDBNull())
+                       {
+                               int     length = field.Length;
+                               
+                               if (field.SqlType == IscCodes.SQL_VARYING)
+                               {
+                                       // Add two bytes more for store value length
+                                       length += 2;
+                               }
+
+                               return new byte[length];
+                       }
+
+                       switch (field.DbDataType)
+                       {
+                               case DbDataType.Char:
+                               {
+                                       string svalue = field.DbValue.GetString();
+
+                                       if ((field.Length %     field.Charset.BytesPerCharacter) == 0 &&
+                                               svalue.Length > field.CharCount)
+                                       {        
+                                               throw new IscException(335544321);       
+                                       }
+
+                                       byte[] buffer = new     byte[field.Length];
+                                       for     (int i = 0;     i <     buffer.Length; i++)
+                                       {
+                                               buffer[i] = 32;
+                                       }
+
+                                       byte[] bytes = field.Charset.GetBytes(svalue);
+
+                                       Buffer.BlockCopy(bytes, 0, buffer, 0, bytes.Length);
+
+                                       return buffer;
+                               }
+                               
+                               case DbDataType.VarChar:
+                               {
+                                       string svalue = field.Value.ToString();
+
+                                       if ((field.Length %     field.Charset.BytesPerCharacter) == 0 &&
+                                               svalue.Length > field.CharCount)
+                                       {        
+                                               throw new IscException(335544321);       
+                                       }
+
+                                       byte[] sbuffer = field.Charset.GetBytes(svalue);
+
+                                       byte[] buffer = new     byte[field.Length +     2];
+
+                                       // Copy length
+                                       Buffer.BlockCopy(
+                                               BitConverter.GetBytes((short)sbuffer.Length), 
+                                        0, buffer, 0, 2);
+                                       
+                                       // Copy string value
+                                       Buffer.BlockCopy(sbuffer, 0, buffer, 2, sbuffer.Length);
+
+                                       return buffer;
+                               }
+
+                               case DbDataType.Numeric:
+                               case DbDataType.Decimal:
+                                       return this.GetNumericBytes(field);
+
+                               case DbDataType.SmallInt:
+                                       return BitConverter.GetBytes(field.DbValue.GetInt16());
+
+                               case DbDataType.Integer:
+                                       return BitConverter.GetBytes(field.DbValue.GetInt32());
+
+                               case DbDataType.Array:
+                               case DbDataType.Binary:
+                               case DbDataType.Text:
+                               case DbDataType.BigInt:
+                                       return BitConverter.GetBytes(field.DbValue.GetInt64());
+
+                               case DbDataType.Float:
+                                       return BitConverter.GetBytes(field.DbValue.GetFloat());
+                                                                       
+                               case DbDataType.Double:
+                                       return BitConverter.GetBytes(field.DbValue.GetDouble());
+
+                               case DbDataType.Date:
+                                       return BitConverter.GetBytes(
+                                               TypeEncoder.EncodeDate(field.DbValue.GetDateTime()));
+                               
+                               case DbDataType.Time:
+                                       return BitConverter.GetBytes(
+                                               TypeEncoder.EncodeTime(field.DbValue.GetDateTime()));
+                               
+                               case DbDataType.TimeStamp:
+                                       byte[] date = BitConverter.GetBytes(
+                                               TypeEncoder.EncodeDate(field.DbValue.GetDateTime()));
+                                       
+                                       byte[] time = BitConverter.GetBytes(
+                                               TypeEncoder.EncodeTime(field.DbValue.GetDateTime()));
+                                       
+                                       byte[] result = new     byte[8];
+
+                                       Buffer.BlockCopy(date, 0, result, 0, date.Length);
+                                       Buffer.BlockCopy(time, 0, result, 4, time.Length);
+
+                                       return result;
+
+                               case DbDataType.Guid:
+                                       return field.DbValue.GetGuid().ToByteArray();
+
+                               default:
+                                       throw new NotSupportedException("Unknown data type");
+                       }
+               }
+
+               private byte[] GetNumericBytes(DbField field)
+               {
+                       decimal value = field.DbValue.GetDecimal();
+                       object  numeric = TypeEncoder.EncodeDecimal(value, field.NumericScale, field.DataType);
+
+                       switch (field.SqlType)
+                       {
+                               case IscCodes.SQL_SHORT:
+                                       return BitConverter.GetBytes((short)numeric);
+
+                               case IscCodes.SQL_LONG:
+                                       return BitConverter.GetBytes((int)numeric);
+
+                               case IscCodes.SQL_INT64:
+                               case IscCodes.SQL_QUAD:
+                                       return BitConverter.GetBytes((long)numeric);
+
+                               case IscCodes.SQL_DOUBLE:
+                                       return BitConverter.GetBytes(field.DbValue.GetDouble());
+
+                               default:
+                                       return null;
+                       }
+               }
+
+               private byte[] GetStringBuffer(Charset charset, string value)
+               {
+                       byte[] buffer = new     byte[32];
+                       
+                       charset.GetBytes(value, 0, value.Length, buffer, 0);
+
+                       return buffer;
+               }
+
+               private string GetString(Charset charset, byte[] buffer)
+               {
+                       string value = charset.GetString(buffer);
+
+                       return value.Replace('\0', ' ').Trim();
+               }
+
+               #endregion
+       }
+}