Synchronized files from gborg repository
authorFrancisco Figueiredo Jr. <fxjr@mono-cvs.ximian.com>
Thu, 22 May 2003 01:54:17 +0000 (01:54 -0000)
committerFrancisco Figueiredo Jr. <fxjr@mono-cvs.ximian.com>
Thu, 22 May 2003 01:54:17 +0000 (01:54 -0000)
svn path=/trunk/mcs/; revision=14785

mcs/class/Npgsql/NpgsqlTypes/NpgsqlTypesHelper.cs [new file with mode: 0755]

diff --git a/mcs/class/Npgsql/NpgsqlTypes/NpgsqlTypesHelper.cs b/mcs/class/Npgsql/NpgsqlTypes/NpgsqlTypesHelper.cs
new file mode 100755 (executable)
index 0000000..763c067
--- /dev/null
@@ -0,0 +1,314 @@
+
+// NpgsqlTypes.NpgsqlTypesHelper.cs
+// 
+// Author:
+//     Francisco Jr. (fxjrlists@yahoo.com.br)
+//
+//     Copyright (C) 2002 The Npgsql Development Team
+//     npgsql-general@gborg.postgresql.org
+//     http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Data;
+using Npgsql;
+
+
+
+/// <summary>
+///    This class contains helper methods for type conversion between
+/// the .Net type system and postgresql.       
+/// </summary>
+namespace NpgsqlTypes
+{
+       
+       /*internal struct NpgsqlTypeMapping
+       {
+         public String        _backendTypeName;
+         public Type          _frameworkType;
+         public Int32         _typeOid;
+         public NpgsqlDbType  _npgsqlDbType;
+         
+         public NpgsqlTypeMapping(String backendTypeName, Type frameworkType, Int32 typeOid, NpgsqlDbType npgsqlDbType)
+         {
+           _backendTypeName = backendTypeName;
+           _frameworkType = frameworkType;
+           _typeOid = typeOid;
+           _npgsqlDbType = npgsqlDbType;
+           
+         }
+       }*/
+       
+       
+       internal class NpgsqlTypesHelper
+       {
+               
+               private static Hashtable _oidToNameMappings = new Hashtable();
+               
+               // Logging related values
+    private static readonly String CLASSNAME = "NpgsqlDataReader";
+               
+               
+               public static String GetBackendTypeNameFromDbType(DbType dbType)
+               {
+                       NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetBackendTypeNameFromNpgsqlDbType(NpgsqlDbType)", Npgsql.LogLevel.Debug);
+                       
+                       switch (dbType)
+                       {
+                               case DbType.Boolean:
+                                       return "bool";
+                               case DbType.Int64:
+                                       return "int8";
+                               case DbType.Int32:
+                                       return "int4";
+                               case DbType.Decimal:
+                                       return "numeric";
+                               case DbType.Int16:
+                                       return "int2";
+                               case DbType.String:
+                                       return "text";
+                               case DbType.DateTime:
+                                       return "timestamp";
+                               default:
+                                       throw new NpgsqlException(String.Format("This type {0} isn't supported yet.", dbType));
+                               
+                       }
+               }
+               
+               
+               public static String ConvertNpgsqlParameterToBackendStringValue(NpgsqlParameter parameter)
+               {
+                       NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ConvertNpgsqlParameterToBackendStringValue(NpgsqlParameter)", Npgsql.LogLevel.Debug);
+                       
+                       if (parameter.Value == DBNull.Value)
+                               return "Null";
+                       
+                       switch(parameter.DbType)
+                       {
+                               case DbType.Boolean:
+                               case DbType.Int64:
+                               case DbType.Int32:
+                               case DbType.Int16:
+                                       return parameter.Value.ToString();
+                               
+                               case DbType.Decimal:
+                                               return ((Decimal)parameter.Value).ToString(NumberFormatInfo.InvariantInfo);
+                               
+                               case DbType.String:
+                                               return "'" + parameter.Value.ToString().Replace("'", "\\'") + "'";
+                               
+                               case DbType.DateTime:
+                               {
+                                       return "'" + ((DateTime)parameter.Value).ToString("yyyy-MM-dd HH:mm:ss.fff") + "'";
+                                       
+                               }
+                               default:
+                                       // This should not happen!
+                                       throw new NpgsqlException(String.Format("This type {0} isn't supported yet.", parameter.DbType));
+                                       
+                               
+                       }
+                       
+               }
+               
+               
+               
+               
+               
+               ///<summary>
+               /// This method is responsible to convert the string received from the backend
+               /// to the corresponding NpgsqlType.
+               /// </summary>
+               /// 
+               public static Object ConvertBackendStringToSystemType(Hashtable oidToNameMapping, String data, Int32 typeOid, Int32 typeModifier)
+               {
+                       NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ConvertBackendStringToSystemType(Hashtable, String, Int32)", Npgsql.LogLevel.Debug);
+                       //[TODO] Find a way to eliminate this checking. It is just used at bootstrap time
+                       // when connecting because we don't have yet loaded typeMapping. The switch below
+                       // crashes with NullPointerReference when it can't find the typeOid.
+                       
+                       if (!oidToNameMapping.ContainsKey(typeOid))
+                               return data;
+                       
+                       switch ((DbType)oidToNameMapping[typeOid])
+                       {
+                               case DbType.Boolean:
+                                       return (data.ToLower() == "t" ? true : false);
+                               case DbType.Int16:
+                                       return Int16.Parse(data);
+                               case DbType.Int32:
+                                       return Int32.Parse(data);
+                               
+                               case DbType.Int64:
+                                       return Int64.Parse(data);
+                               
+                               case DbType.Decimal:
+                                       // Got this manipulation of typemodifier from jdbc driver - file AbstractJdbc1ResultSetMetaData.java.html method getColumnDisplaySize
+                                       { 
+                                               typeModifier -= 4;
+                                               //Console.WriteLine("Numeric from server: {0} digitos.digitos {1}.{2}", data, (typeModifier >> 16) & 0xffff, typeModifier & 0xffff);
+                                               return Decimal.Parse(data, NumberFormatInfo.InvariantInfo);
+                                               
+                                       }
+                               
+                               case DbType.DateTime:
+                                       
+                                       // Get the date time parsed in all expected formats for timestamp.
+                                       return DateTime.ParseExact(data,
+                                                                  new String[] {"yyyy-MM-dd HH:mm:ss.fff", "yyyy-MM-dd HH:mm:ss.ff", "yyyy-MM-dd HH:mm:ss.f", "yyyy-MM-dd HH:mm:ss"}, 
+                                                                  DateTimeFormatInfo.InvariantInfo,
+                                                                  DateTimeStyles.NoCurrentDateDefault | DateTimeStyles.AllowWhiteSpaces);
+                                                               
+                               case DbType.String:
+                                       return data;
+                               default:
+                                       throw new NpgsqlException(String.Format("This type {0} isn't supported yet.", oidToNameMapping[typeOid]));
+                               
+                       
+                       }
+               }
+               
+                   
+    ///<summary>
+               /// This method gets a type oid and return the equivalent
+               /// Npgsql type.
+               /// </summary>
+               /// 
+               
+               public static Type GetSystemTypeFromTypeOid(Hashtable oidToNameMapping, Int32 typeOid)
+    {
+       NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetSystemTypeFromTypeOid(Hashtable, Int32)", Npgsql.LogLevel.Debug);
+       // This method gets a db type identifier and return the equivalent
+       // system type.
+       
+       //[TODO] Find a way to eliminate this checking. It is just used at bootstrap time
+                       // when connecting because we don't have yet loaded typeMapping. The switch below
+                       // crashes with NullPointerReference when it can't find the typeOid.
+       
+       
+       
+       if (!oidToNameMapping.ContainsKey(typeOid))
+                               return Type.GetType("System.String");
+                       
+       switch ((DbType)oidToNameMapping[typeOid])
+                       {
+                               case DbType.Boolean:
+                                       return Type.GetType("System.Boolean");
+                               case DbType.Int16:
+                                       return Type.GetType("System.Int16");
+                               case DbType.Int32:
+                                       return Type.GetType("System.Int32");
+                               case DbType.Int64:
+                                       return Type.GetType("System.Int64");
+                               case DbType.Decimal:
+                                       return Type.GetType("System.Decimal");
+                               case DbType.DateTime:
+                                       return Type.GetType("System.DateTime");
+                               case DbType.String:
+                                       return Type.GetType("System.String");
+                               default:
+                                       throw new NpgsqlException(String.Format("This type {0} isn't supported yet.", oidToNameMapping[typeOid]));
+                       
+                       }
+                       
+       
+    }
+    
+               
+               ///<summary>
+               /// This method is responsible to send query to get the oid-to-name mapping.
+               /// This is needed as from one version to another, this mapping can be changed and
+               /// so we avoid hardcoding them.
+               /// </summary>
+               public static Hashtable LoadTypesMapping(NpgsqlConnection conn)
+               {
+                       NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".LoadTypesMapping(NpgsqlConnection)", Npgsql.LogLevel.Debug);
+                       
+                       // [TODO] Verify another way to get higher concurrency.
+                       lock(typeof(NpgsqlTypesHelper))
+                       {
+                               Hashtable oidToNameMapping = (Hashtable) _oidToNameMappings[conn.ServerVersion];
+                                                                                               
+                               if (oidToNameMapping != null)
+                               {
+                                       //conn.OidToNameMapping = oidToNameMapping;
+                                       return oidToNameMapping;
+                               }
+                               
+                               
+                               oidToNameMapping = new Hashtable();
+                               //conn.OidToNameMapping = oidToNameMapping;
+                               
+                               // Bootstrap value as the datareader below will use ConvertStringToNpgsqlType above.
+                               //oidToNameMapping.Add(26, "oid");
+                                                               
+                               NpgsqlCommand command = new NpgsqlCommand("select oid, typname from pg_type where typname in ('bool', 'int2', 'int4', 'int8', 'numeric', 'text', 'timestamp');", conn);
+                               
+                               NpgsqlDataReader dr = command.ExecuteReader();
+                               
+                               // Data was read. Clear the mapping from previous bootstrap value so we don't get
+                               // exceptions trying to add duplicate key.
+                               // oidToNameMapping.Clear();
+                               
+                               while (dr.Read())
+                               {
+                                       // Add the key as a Int32 value so the switch in ConvertStringToNpgsqlType can use it
+                                       // in the search. If don't, the key is added as string and the switch doesn't work.
+                                       
+                                       DbType type;
+                                       String typeName = (String) dr[1];
+                                                                               
+                                       switch (typeName)
+                                       {
+                                               case "bool":
+                                                       type = DbType.Boolean;
+                                                       break;
+                                               case "int2":
+                                                       type = DbType.Int16;
+                                                       break;
+                                               case "int4":
+                                                       type = DbType.Int32;
+                                                       break;
+                                               case "int8":
+                                                       type = DbType.Int64;
+                                                       break;
+                                               case "numeric":
+                                                       type = DbType.Decimal;
+                                                       break;
+                                               case "timestamp":
+                                                       type = DbType.DateTime;
+                                                       break;
+                                               default:
+                                                       type = DbType.String; // Default dbtype of the oid. Unsupported types will be returned as String.
+                                                       break;
+                                       }
+                                                                               
+                                       
+                                       oidToNameMapping.Add(Int32.Parse((String)dr[0]), type);
+                               }
+                               
+                               _oidToNameMappings.Add(conn.ServerVersion, oidToNameMapping);
+                               return oidToNameMapping;
+                       }
+                       
+                       
+               }
+               
+       }
+       
+}