Index: FirebirdSql.Data.Common/Charset.cs
===================================================================
RCS file: /cvsroot/firebird/NETProvider/NETProvider_17/source/FirebirdSql.Data.Common/Charset.cs,v
retrieving revision 1.14
diff -u -r1.14 Charset.cs
--- FirebirdSql.Data.Common/Charset.cs	22 Apr 2005 18:19:25 -0000	1.14
+++ FirebirdSql.Data.Common/Charset.cs	17 Oct 2006 19:13:32 -0000
@@ -109,20 +109,29 @@
 		#endregion
 
 		#region Private Methods
+		
+		private Encoding cachedEncoding = null;
 
 		private Encoding GetEncoding()
 		{
-			switch (this.systemName)
-			{
-				case "NONE":
-					return Encoding.Default;
-
-				case "OCTETS":
-					return new BinaryEncoding();
-
-				default:
-					return Encoding.GetEncoding(this.systemName);
-			}
+		  if (cachedEncoding == null)
+		  {
+  			switch (this.systemName)
+  			{
+  				case "NONE":
+  					cachedEncoding = Encoding.Default;
+  					break;
+  
+  				case "OCTETS":
+  					cachedEncoding = new BinaryEncoding();
+  					break;
+  
+  				default:
+  					cachedEncoding = Encoding.GetEncoding(this.systemName);
+  					break;
+  			}
+  		}
+  		return cachedEncoding;
 		}
 
 		#endregion
Index: FirebirdSql.Data.Embedded/FesStatement.cs
===================================================================
RCS file: /cvsroot/firebird/NETProvider/NETProvider_17/source/FirebirdSql.Data.Embedded/FesStatement.cs,v
retrieving revision 1.26
diff -u -r1.26 FesStatement.cs
--- FirebirdSql.Data.Embedded/FesStatement.cs	11 Oct 2006 18:36:27 -0000	1.26
+++ FirebirdSql.Data.Embedded/FesStatement.cs	17 Oct 2006 23:22:02 -0000
@@ -37,7 +37,8 @@
 		private DbStatementType statementType;
 		private bool			allRowsFetched;
 		private Queue			outputParams;
-		private int				recordsAffected;
+		private int				recordsAffected;	
+		private IntPtr			fetchSqlDa = IntPtr.Zero;
 
 		#endregion
 
@@ -363,6 +364,18 @@
 			}
 		}
 
+
+		public override void Release() {
+			if (fetchSqlDa != IntPtr.Zero) {
+				if (!Environment.HasShutdownStarted) {					   
+					XsqldaMarshaler marshaler = XsqldaMarshaler.GetInstance();
+					marshaler.CleanUpNativeData(ref fetchSqlDa);
+				}
+			}
+			base.Release();
+		}
+
+
 		public override DbValue[] Fetch()
 		{
 			DbValue[] row = null;
@@ -387,7 +400,10 @@
 					// Reset actual	field values
 					this.fields.ResetValues();
 
-					IntPtr sqlda = marshaler.MarshalManagedToNative(this.db.Charset, fields);
+					if (fetchSqlDa == IntPtr.Zero) 
+					{
+						fetchSqlDa = marshaler.MarshalManagedToNative(this.db.Charset, fields);
+					}
 
 					int[] statusVector = FesConnection.GetNewStatusVector();
 					int stmtHandle = this.handle;
@@ -396,10 +412,10 @@
 						statusVector,
 						ref	stmtHandle,
 						IscCodes.SQLDA_VERSION1,
-						sqlda);
+						fetchSqlDa);
 
 					// Obtain values
-					Descriptor rowDesc = marshaler.MarshalNativeToManaged(this.db.Charset, sqlda, true);
+					Descriptor rowDesc = marshaler.MarshalNativeToManaged(this.db.Charset, fetchSqlDa, true);
 
 					if (this.fields.Count == rowDesc.Count)
 					{
@@ -416,14 +432,13 @@
 
 					this.fields = rowDesc;
 
-					// Free	memory
-					marshaler.CleanUpNativeData(ref	sqlda);
-
 					// Parse status	vector
 					this.db.ParseStatusVector(statusVector);
 
-					if (status == 100)
-					{
+					if (status == 100) 
+					{											   
+						// Free	memory
+						marshaler.CleanUpNativeData(ref fetchSqlDa);
 						this.allRowsFetched = true;
 					}
 					else
Index: FirebirdSql.Data.Embedded/XsqldaMarshaler.cs
===================================================================
RCS file: /cvsroot/firebird/NETProvider/NETProvider_17/source/FirebirdSql.Data.Embedded/XsqldaMarshaler.cs,v
retrieving revision 1.13
diff -u -r1.13 XsqldaMarshaler.cs
--- FirebirdSql.Data.Embedded/XsqldaMarshaler.cs	1 Sep 2006 17:13:42 -0000	1.13
+++ FirebirdSql.Data.Embedded/XsqldaMarshaler.cs	17 Oct 2006 23:58:04 -0000
@@ -56,6 +56,7 @@
 		{
 			if (pNativeData	!= IntPtr.Zero)
 			{
+				/*
 				// Obtain XSQLDA information
 				XSQLDA xsqlda = new	XSQLDA();
 			
@@ -85,6 +86,7 @@
 					Marshal.DestroyStructure(
 						this.GetIntPtr(pNativeData,	this.ComputeLength(i)),	typeof(XSQLVAR));
 				}
+				*/
 
 				// Free	pointer	memory
 				Marshal.FreeHGlobal(pNativeData);
@@ -104,6 +106,10 @@
 			
 			XSQLVAR[] xsqlvar = new	XSQLVAR[descriptor.Count];
 
+			int nativeHeaderSize = ComputeLength(xsqlvar.Length);
+			int nativeSize = nativeHeaderSize;
+			byte[][] xsqlvarBuffers = new byte[xsqlvar.Length][];
+
 			for	(int i = 0;	i <	xsqlvar.Length;	i++)
 			{
 				// Create a	new	XSQLVAR	structure and fill it
@@ -114,15 +120,14 @@
 				xsqlvar[i].sqlsubtype = descriptor[i].SubType;
 				xsqlvar[i].sqllen	 = descriptor[i].Length;
 
-				// Create a	new	pointer	for	the	xsqlvar	data
+				// Cache the data byte[]
 				byte[] buffer = this.GetBytes(descriptor[i]);
-                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);				  
+				xsqlvarBuffers[i] = buffer;
 
+				// Calculate the sizes...
+				nativeSize += buffer.Length;
+				nativeSize += sizeofInt16;
+				
 				// Name
 				xsqlvar[i].sqlname		    = this.GetStringBuffer(charset,	descriptor[i].Name);
 				xsqlvar[i].sqlname_length   = (short)xsqlvar[i].sqlname.Length;
@@ -140,9 +145,31 @@
 				xsqlvar[i].aliasname_length = (short)xsqlvar[i].aliasname.Length;
 			}
 
-			return this.MarshalManagedToNative(xsqlda, xsqlvar);
+			IntPtr result = Marshal.AllocHGlobal(nativeSize);	 
+			Marshal.StructureToPtr(xsqlda, result, false); // false - no need to cleanup!!!
+
+			int dataOffset = nativeHeaderSize;						   
+			for	(int i = 0;	i <	xsqlvar.Length;	i++) {
+				byte[] buffer = xsqlvarBuffers[i];
+
+				// Set the new pointer for the xsqlvar data
+				xsqlvar[i].sqldata = GetIntPtr(result, dataOffset);
+				Marshal.Copy(buffer, 0,	xsqlvar[i].sqldata,	buffer.Length);
+				dataOffset += buffer.Length;
+
+				// Set the new pointer for the sqlind value
+				xsqlvar[i].sqlind = GetIntPtr(result, dataOffset);
+				Marshal.WriteInt16(xsqlvar[i].sqlind, descriptor[i].NullFlag);			
+				dataOffset += sizeofInt16;	  
+
+				int	offset = this.ComputeLength(i);
+				Marshal.StructureToPtr(xsqlvar[i], this.GetIntPtr(result, offset), false); // false - no need to cleanup!!!
+			}
+
+			return result;//this.MarshalManagedToNative(xsqlda, xsqlvar);
 		}
 
+		/*
 		public IntPtr MarshalManagedToNative(XSQLDA	xsqlda,	XSQLVAR[] xsqlvar)
 		{
 			int		size = this.ComputeLength(xsqlda.sqln);
@@ -158,6 +185,7 @@
 
 			return ptr;
 		}
+		*/
 
         public Descriptor MarshalNativeToManaged(Charset charset, IntPtr pNativeData)
         {
@@ -220,12 +248,21 @@
 
 		private	IntPtr GetIntPtr(IntPtr	ptr, int offset)
 		{
-			return (IntPtr)(ptr.ToInt32() +	offset);
+			return new IntPtr(ptr.ToInt64() + offset);
+			// return (IntPtr)(ptr.ToInt32() +	offset);
 		}
 
+
+		private static readonly int sizeofInt16 = Marshal.SizeOf(typeof(Int16));
+
+		private static readonly int sizeofXSQLDA = Marshal.SizeOf(typeof(XSQLDA));
+
+		private static readonly int sizeofXSQLVAR = Marshal.SizeOf(typeof(XSQLVAR));
+
+
 		private	int	ComputeLength(int n)
 		{
-			return (Marshal.SizeOf(typeof(XSQLDA)) + n * Marshal.SizeOf(typeof(XSQLVAR)));
+			return (sizeofXSQLDA + n * sizeofXSQLVAR);
 		}
 
 		private	byte[] GetBytes(XSQLVAR	xsqlvar)
@@ -414,6 +451,7 @@
 			}
 		}
 
+
 		private	byte[] GetStringBuffer(Charset charset,	string value)
 		{
 			byte[] buffer = new	byte[32];
@@ -423,11 +461,36 @@
 			return buffer;
 		}
 
+
+		private static readonly char[] trimChars = new char[]{'\0', ' ', '\t', '\n', '\r'};
+
+
 		private	string GetString(Charset charset, byte[] buffer)
 		{
-			string value = charset.GetString(buffer);
+			if (charset.BytesPerCharacter <= 1) 
+			{
+				int lastValidIdx;
+				unchecked // we know what we are doing... unsafe would still be much faster but we don't want to introduce that
+				{
+					for (lastValidIdx = buffer.Length - 1; lastValidIdx >= 0; lastValidIdx--) 
+					{
+						if (buffer[lastValidIdx] != 0 && buffer[lastValidIdx] != (byte)' ') 
+						{
+							break;
+						}
+					}
+				}
 
-			return value.Replace('\0', ' ').Trim();
+				string value = charset.GetString(buffer, 0, lastValidIdx + 1);
+				
+				return value;
+			} 
+			else 
+			{
+				string value = charset.GetString(buffer);
+				
+				return value.TrimEnd(trimChars);
+			}
 		}
 
 		#endregion
