Missing 2.0 APIs
[mono.git] / mcs / class / System.Data / System.Data.Odbc / OdbcConnection.cs
index 1703554bb4021d2b73e5c8f4d8a73bc8371e9dcc..d9c6be93603ced82ea31355c4aceb25d1cb21fcc 100644 (file)
@@ -35,12 +35,15 @@ using System.Data;
 using System.Data.Common;
 using System.Runtime.InteropServices;
 using System.EnterpriseServices;
+#if NET_2_0 && !TARGET_JVM
+using System.Transactions;
+#endif
 
 namespace System.Data.Odbc
 {
-       [DefaultEvent("InfoMessage")]
+       [DefaultEvent ("InfoMessage")]
 #if NET_2_0
-        public sealed class OdbcConnection : DbConnection, ICloneable
+       public sealed class OdbcConnection : DbConnection, ICloneable
 #else
        public sealed class OdbcConnection : Component, ICloneable, IDbConnection
 #endif //NET_2_0
@@ -50,8 +53,8 @@ namespace System.Data.Odbc
                string connectionString;
                int connectionTimeout;
                internal OdbcTransaction transaction;
-               IntPtr henv=IntPtr.Zero, hdbc=IntPtr.Zero;
-               bool disposed = false;                  
+               IntPtr henv =IntPtr.Zero, hdbc=IntPtr.Zero;
+               bool disposed;
                
                #endregion
 
@@ -63,142 +66,144 @@ namespace System.Data.Odbc
 
                public OdbcConnection (string connectionString)
                {
-                        Init (connectionString);
+                       connectionTimeout = 15;
+                       ConnectionString = connectionString;
                }
 
-                private void Init (string connectionString)
-                {
-                        connectionTimeout = 15;
-                        ConnectionString = connectionString;
-                }
-
                #endregion // Constructors
 
                #region Properties
 
-               internal IntPtr hDbc
-               {
+               internal IntPtr hDbc {
                        get { return hdbc; }
                }
 
-               [OdbcCategoryAttribute ("DataCategory_Data")]           
+               [OdbcCategoryAttribute ("DataCategory_Data")]
                [DefaultValue ("")]
                [OdbcDescriptionAttribute ("Information used to connect to a Data Source")]     
                [RefreshPropertiesAttribute (RefreshProperties.All)]
                [EditorAttribute ("Microsoft.VSDesigner.Data.Odbc.Design.OdbcConnectionStringEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
-                [RecommendedAsConfigurableAttribute (true)]
-               public 
+               [RecommendedAsConfigurableAttribute (true)]
+               public
 #if NET_2_0
                override
 #endif
                string ConnectionString {
                        get {
+                               if (connectionString == null)
+                                       return string.Empty;
                                return connectionString;
                        }
-                       set {
-                               connectionString = value;
-                       }
+                       set { connectionString = value; }
                }
                
                [OdbcDescriptionAttribute ("Current connection timeout value, not settable  in the ConnectionString")]
-               [DefaultValue (15)]     
+               [DefaultValue (15)]
+#if NET_2_0
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+#endif
                public
 #if NET_2_0
-                new
+               new
 #endif // NET_2_0
-                int ConnectionTimeout {
+               int ConnectionTimeout {
                        get {
                                return connectionTimeout;
                        }
                        set {
-                               if (value < 0) {
+                               if (value < 0)
                                        throw new ArgumentException("Timout should not be less than zero.");
-                               }
                                connectionTimeout = value;
                        }
                }
 
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
-                [OdbcDescriptionAttribute ("Current data source Catlog value, 'Database=X' in the ConnectionString")]
+               [OdbcDescriptionAttribute ("Current data source Catlog value, 'Database=X' in the ConnectionString")]
                public
 #if NET_2_0
-                override
+               override
 #endif // NET_2_0
-                string Database {
+               string Database {
                        get {
-                                return GetInfo (OdbcInfo.DatabaseName);
+                               if (State == ConnectionState.Closed)
+                                       return string.Empty;
+                               return GetInfo (OdbcInfo.DatabaseName);
                        }
                }
 
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
-                [OdbcDescriptionAttribute ("The ConnectionState indicating whether the connection is open or closed")]
-                [BrowsableAttribute (false)]           
+               [OdbcDescriptionAttribute ("The ConnectionState indicating whether the connection is open or closed")]
+               [BrowsableAttribute (false)]
                public
 #if NET_2_0
-                override
+               override
 #endif // NET_2_0
-                ConnectionState State
-               {
+               ConnectionState State {
                        get {
-                               if (hdbc!=IntPtr.Zero) {
+                               if (hdbc!=IntPtr.Zero)
                                        return ConnectionState.Open;
-                               }
                                else
                                        return ConnectionState.Closed;
                        }
                }
 
-               [MonoTODO]
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
-                [OdbcDescriptionAttribute ("Current data source, 'Server=X' in the ConnectionString")]
+               [OdbcDescriptionAttribute ("Current data source, 'Server=X' in the ConnectionString")]
+#if NET_2_0
+               [Browsable (false)]
+#endif
                public
 #if NET_2_0
-                override
+               override
 #endif // NET_2_0
-                string DataSource {
+               string DataSource {
                        get {
-                                return GetInfo (OdbcInfo.DataSourceName);
+                               if (State == ConnectionState.Closed)
+                                       return string.Empty;
+                               return GetInfo (OdbcInfo.DataSourceName);
                        }
                }
 
-               [MonoTODO]
+#if NET_2_0
+               [Browsable (false)]
+#endif
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
-                [OdbcDescriptionAttribute ("Current ODBC Driver")]
-                public string Driver {
-                        get {
-                                return GetInfo (OdbcInfo.DriverName);
-                        }
-                }
+               [OdbcDescriptionAttribute ("Current ODBC Driver")]
+               public string Driver {
+                       get {
+                               if (State == ConnectionState.Closed)
+                                       return string.Empty;
+                               return GetInfo (OdbcInfo.DriverName);
+                       }
+               }
                
-               [MonoTODO]
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
-                [OdbcDescriptionAttribute ("Version of the product accessed by the ODBC Driver")]
-                [BrowsableAttribute (false)]
-                public
+               [OdbcDescriptionAttribute ("Version of the product accessed by the ODBC Driver")]
+               [BrowsableAttribute (false)]
+               public
 #if NET_2_0
-                override
+               override
 #endif // NET_2_0
-                string ServerVersion {
-                        get {
-                                return GetInfo (OdbcInfo.DbmsVersion);
-                        }
-                }
+               string ServerVersion {
+                       get {
+                               return GetInfo (OdbcInfo.DbmsVersion);
+                       }
+               }
 
-               
                #endregion // Properties
        
                #region Methods
        
                public
 #if NET_2_0
-                new
+               new
 #endif // NET_2_0
-                OdbcTransaction BeginTransaction ()
+               OdbcTransaction BeginTransaction ()
                {
                        return BeginTransaction(IsolationLevel.Unspecified);
-                }
+               }
 
-#if ONLY_1_1              
+#if ONLY_1_1
                IDbTransaction IDbConnection.BeginTransaction ()
                {
                        return (IDbTransaction) BeginTransaction();
@@ -213,62 +218,60 @@ namespace System.Data.Odbc
                
                public
 #if NET_2_0
-                new
+               new
 #endif // NET_2_0
-                OdbcTransaction BeginTransaction (IsolationLevel level)
+               OdbcTransaction BeginTransaction (IsolationLevel level)
                {
-                       if (transaction==null)
-                       {
-                               transaction=new OdbcTransaction(this,level);
+                       if (State == ConnectionState.Closed)
+                               throw ExceptionHelper.ConnectionClosed ();
+
+                       if (transaction == null) {
+                               transaction = new OdbcTransaction (this,level);
                                return transaction;
-                       }
-                       else
+                       } else
                                throw new InvalidOperationException();
                }
 
 #if ONLY_1_1
                IDbTransaction IDbConnection.BeginTransaction (IsolationLevel level)
                {
-                       return (IDbTransaction) BeginTransaction(level);
+                       return (IDbTransaction) BeginTransaction (level);
                }
 #endif // ONLY_1_1
 
                public
 #if NET_2_0
-                override
+               override
 #endif // NET_2_0
-                void Close ()
+               void Close ()
                {
                        OdbcReturn ret = OdbcReturn.Error;
                        if (State == ConnectionState.Open) {
                                // disconnect
                                ret = libodbc.SQLDisconnect (hdbc);
-                               if ( (ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
-                                       throw new OdbcException (new OdbcError ("SQLDisconnect", OdbcHandleType.Dbc,hdbc));
+                               if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo))
+                                       throw new OdbcException (new OdbcError ("SQLDisconnect", OdbcHandleType.Dbc, hdbc));
 
                                FreeHandles ();
-
                                transaction = null;
-
-                                RaiseStateChange (ConnectionState.Open, ConnectionState.Closed);
+                               RaiseStateChange (ConnectionState.Open, ConnectionState.Closed);
                        }
                }
 
                public
 #if NET_2_0
-                new
+               new
 #endif // NET_2_0
-                OdbcCommand CreateCommand ()
+               OdbcCommand CreateCommand ()
                {
-                       return new OdbcCommand("", this, transaction); 
+                       return new OdbcCommand (string.Empty, this, transaction);
                }
 
-               [MonoTODO]
                public
 #if NET_2_0
-                override
+               override
 #endif // NET_2_0
-                void ChangeDatabase(string Database)
+               void ChangeDatabase(string Database)
                {
                        IntPtr ptr = IntPtr.Zero;
                        OdbcReturn ret = OdbcReturn.Error;
@@ -288,16 +291,13 @@ namespace System.Data.Odbc
                protected override void Dispose (bool disposing)
                {
                        if (!this.disposed) {
-                               try 
-                               {
+                               try {
                                        // release the native unmananged resources
                                        this.Close();
                                        this.disposed = true;
-                               }
-                               finally 
-                               {
+                               } finally {
                                        // call Dispose on the base class
-                                       base.Dispose(disposing);                        
+                                       base.Dispose(disposing);
                                }
                        }
                }
@@ -324,72 +324,76 @@ namespace System.Data.Odbc
 
                public
 #if NET_2_0
-                override
+               override
 #endif // NET_2_0
-                void Open ()
+               void Open ()
                {
                        if (State == ConnectionState.Open)
                                throw new InvalidOperationException ();
 
                        OdbcReturn ret = OdbcReturn.Error;
+                       OdbcException e = null;
                
-                        try {
-                                // allocate Environment handle 
-                                ret = libodbc.SQLAllocHandle (OdbcHandleType.Env, IntPtr.Zero, ref henv);
-                                if ( (ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
-                                        throw new OdbcException (new OdbcError ("SQLAllocHandle"));
-               
-                                ret=libodbc.SQLSetEnvAttr (henv, OdbcEnv.OdbcVersion, (IntPtr) libodbc.SQL_OV_ODBC3 , 0); 
-                                if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
-                                        throw new OdbcException (new OdbcError ("SQLSetEnvAttr", OdbcHandleType.Env,henv));
-               
-                                // allocate connection handle
-                                ret=libodbc.SQLAllocHandle (OdbcHandleType.Dbc, henv, ref hdbc);
-                                if ( (ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
-                                        throw new OdbcException (new OdbcError ("SQLAllocHandle",OdbcHandleType.Env,henv));
-                       
-                                // DSN connection
-                                if (ConnectionString.ToLower().IndexOf("dsn=")>=0)
-                                {
-                                        string _uid="", _pwd="", _dsn="";
-                                        string[] items=ConnectionString.Split(new char[1]{';'});
-                                        foreach (string item in items)
-                                        {
-                                                string[] parts=item.Split(new char[1] {'='});
-                                                switch (parts[0].Trim().ToLower())
-                                                {
+                       try {
+                               // allocate Environment handle
+                               ret = libodbc.SQLAllocHandle (OdbcHandleType.Env, IntPtr.Zero, ref henv);
+                               if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo)) {
+                                       e = new OdbcException (new OdbcError ("SQLAllocHandle"));
+                                       MessageHandler (e);
+                                       throw e;
+                               }
+
+                               ret = libodbc.SQLSetEnvAttr (henv, OdbcEnv.OdbcVersion, (IntPtr) libodbc.SQL_OV_ODBC3 , 0); 
+                               if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo))
+                                       throw new OdbcException (new OdbcError ("SQLSetEnvAttr", OdbcHandleType.Env, henv));
+
+                               // allocate connection handle
+                               ret = libodbc.SQLAllocHandle (OdbcHandleType.Dbc, henv, ref hdbc);
+                               if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo))
+                                       throw new OdbcException (new OdbcError ("SQLAllocHandle", OdbcHandleType.Env, henv));
+
+                               // DSN connection
+                               if (ConnectionString.ToLower ().IndexOf ("dsn=") >= 0)
+                               {
+                                       string _uid = string.Empty, _pwd = string.Empty, _dsn = string.Empty;
+                                       string [] items = ConnectionString.Split (new char[1]{';'});
+                                       foreach (string item in items)
+                                       {
+                                               string [] parts = item.Split (new char[1] {'='});
+                                               switch (parts [0].Trim ().ToLower ())
+                                               {
                                                case "dsn":
-                                                       _dsn=parts[1].Trim();
+                                                       _dsn = parts [1].Trim ();
                                                        break;
                                                case "uid":
-                                                       _uid=parts[1].Trim();
+                                                       _uid = parts [1].Trim ();
                                                        break;
                                                case "pwd":
-                                                       _pwd=parts[1].Trim();
+                                                       _pwd = parts [1].Trim ();
                                                        break;
-                                                }
-                                        }
-                                        ret=libodbc.SQLConnect(hdbc, _dsn, -3, _uid, -3, _pwd, -3);
-                                        if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
-                                                throw new OdbcException(new OdbcError("SQLConnect",OdbcHandleType.Dbc,hdbc));
-                                }
-                                else 
-                                {
-                                        // DSN-less Connection
-                                        string OutConnectionString=new String(' ',1024);
-                                        short OutLen=0;
-                                        ret=libodbc.SQLDriverConnect(hdbc, IntPtr.Zero, ConnectionString, -3, 
-                                                                     OutConnectionString, (short) OutConnectionString.Length, ref OutLen, 0);
-                                        if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
-                                                throw new OdbcException(new OdbcError("SQLDriverConnect",OdbcHandleType.Dbc,hdbc));
-                                }
-
-                                RaiseStateChange (ConnectionState.Closed, ConnectionState.Open);
-                        } catch (Exception) {
-                                // free handles if any.
-                                FreeHandles ();
-                                throw;
-                        }
+                                               }
+                                       }
+                                       ret = libodbc.SQLConnect(hdbc, _dsn, -3, _uid, -3, _pwd, -3);
+                                       if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo)) 
+                                               throw new OdbcException (new OdbcError ("SQLConnect", OdbcHandleType.Dbc, hdbc));
+                               }
+                               else 
+                               {
+                                       // DSN-less Connection
+                                       string OutConnectionString = new String (' ',1024);
+                                       short OutLen = 0;
+                                       ret = libodbc.SQLDriverConnect (hdbc, IntPtr.Zero, ConnectionString, -3, 
+                                                                    OutConnectionString, (short) OutConnectionString.Length, ref OutLen, 0);
+                                       if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo)) 
+                                               throw new OdbcException (new OdbcError ("SQLDriverConnect", OdbcHandleType.Dbc, hdbc));
+                               }
+
+                               RaiseStateChange (ConnectionState.Closed, ConnectionState.Open);
+                       } catch {
+                               // free handles if any.
+                               FreeHandles ();
+                               throw;
+                       }
                        disposed = false;
                }
 
@@ -399,61 +403,95 @@ namespace System.Data.Odbc
                        throw new NotImplementedException ();
                }
 
-                private void FreeHandles ()
-                {
-                        OdbcReturn ret = OdbcReturn.Error;
-                        if (hdbc != IntPtr.Zero) {
-                                ret = libodbc.SQLFreeHandle ( (ushort) OdbcHandleType.Dbc, hdbc);      
-                                if ( (ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
-                                        throw new OdbcException (new OdbcError ("SQLFreeHandle", OdbcHandleType.Dbc,hdbc));
-                        }
-                        hdbc = IntPtr.Zero;
-
-                        if (henv != IntPtr.Zero) {
-                                ret = libodbc.SQLFreeHandle ( (ushort) OdbcHandleType.Env, henv);      
-                                if ( (ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
-                                        throw new OdbcException (new OdbcError ("SQLFreeHandle", OdbcHandleType.Env,henv));
-                        }
-                        henv = IntPtr.Zero;
-                                
-                }
-                
+               private void FreeHandles ()
+               {
+                       OdbcReturn ret = OdbcReturn.Error;
+                       if (hdbc != IntPtr.Zero) {
+                               ret = libodbc.SQLFreeHandle ((ushort) OdbcHandleType.Dbc, hdbc);
+                               if ( (ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo)) 
+                                       throw new OdbcException (new OdbcError ("SQLFreeHandle", OdbcHandleType.Dbc, hdbc));
+                       }
+                       hdbc = IntPtr.Zero;
+
+                       if (henv != IntPtr.Zero) {
+                               ret = libodbc.SQLFreeHandle ((ushort) OdbcHandleType.Env, henv);
+                               if ( (ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo)) 
+                                       throw new OdbcException (new OdbcError ("SQLFreeHandle", OdbcHandleType.Env, henv));
+                       }
+                       henv = IntPtr.Zero;
+               }
+
+#if NET_2_0
+               public override DataTable GetSchema ()
+               {
+                       if (State == ConnectionState.Closed)
+                               throw ExceptionHelper.ConnectionClosed ();
+                       return MetaDataCollections.Instance;
+               }
+
+               public override DataTable GetSchema (string collectionName)
+               {
+                       return GetSchema (collectionName, null);
+               }
+
+               public override DataTable GetSchema (string collectionName, string [] restrictionValues)
+               {
+                       if (State == ConnectionState.Closed)
+                               throw ExceptionHelper.ConnectionClosed ();
+                       return GetSchema (collectionName, null);
+               }
+
+               [MonoTODO]
+               public override void EnlistTransaction (Transaction transaction)
+               {
+                       throw new NotImplementedException ();
+               }
+#endif
 
                [MonoTODO]
                public void EnlistDistributedTransaction ( ITransaction transaction) 
                {
-                
                        throw new NotImplementedException ();
                }
 
-                internal string GetInfo (OdbcInfo info)
-                {
-                        if (State == ConnectionState.Closed)
-                                throw new InvalidOperationException ("The connection is closed.");
-                        
-                        OdbcReturn ret = OdbcReturn.Error;
-                        short max_length = 256;
-                        byte [] buffer = new byte [max_length];
-                        short actualLength = 0;
-                        
-                        ret = libodbc.SQLGetInfo (hdbc, info, buffer, max_length, ref actualLength);
-                        if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
-                                throw new OdbcException (new OdbcError ("SQLGetInfo",
-                                                                        OdbcHandleType.Dbc,
-                                                                        hdbc));
-
-                        return System.Text.Encoding.Default.GetString (buffer);
-                }
-
-                private void RaiseStateChange (ConnectionState from, ConnectionState to)
-                {
+               internal string GetInfo (OdbcInfo info)
+               {
+                       if (State == ConnectionState.Closed)
+                               throw new InvalidOperationException ("The connection is closed.");
+
+                       OdbcReturn ret = OdbcReturn.Error;
+                       short max_length = 256;
+                       byte [] buffer = new byte [max_length];
+                       short actualLength = 0;
+
+                       ret = libodbc.SQLGetInfo (hdbc, info, buffer, max_length, ref actualLength);
+                       if (ret != OdbcReturn.Success && ret != OdbcReturn.SuccessWithInfo)
+                               throw new OdbcException (new OdbcError ("SQLGetInfo",
+                                                                       OdbcHandleType.Dbc,
+                                                                       hdbc));
+
+                       return System.Text.Encoding.Default.GetString (buffer);
+               }
+
+               private void RaiseStateChange (ConnectionState from, ConnectionState to)
+               {
 #if ONLY_1_1
-                        if (StateChange != null)
-                                StateChange (this, new StateChangeEventArgs (from, to));
+                       if (StateChange != null)
+                               StateChange (this, new StateChangeEventArgs (from, to));
 #else
                        base.OnStateChange (new StateChangeEventArgs (from, to));
 #endif
-                }
+               }
+
+               private OdbcInfoMessageEventArgs CreateOdbcInfoMessageEvent (OdbcErrorCollection errors)
+               {
+                       return new OdbcInfoMessageEventArgs (errors);
+               }
+
+               private void OnOdbcInfoMessage (OdbcInfoMessageEventArgs e) {
+                       if (InfoMessage != null)
+                               InfoMessage (this, e);
+               }
 
                #endregion
 
@@ -461,14 +499,19 @@ namespace System.Data.Odbc
 
 #if ONLY_1_1
                [OdbcDescription ("DbConnection_StateChange")]
-                [OdbcCategory ("DataCategory_StateChange")]
+               [OdbcCategory ("DataCategory_StateChange")]
                public event StateChangeEventHandler StateChange;
 #endif // ONLY_1_1
 
                [OdbcDescription ("DbConnection_InfoMessage")]
-                [OdbcCategory ("DataCategory_InfoMessage")]
+               [OdbcCategory ("DataCategory_InfoMessage")]
                public event OdbcInfoMessageEventHandler InfoMessage;
 
+               private void MessageHandler (OdbcException e)
+               {
+                       OnOdbcInfoMessage (CreateOdbcInfoMessageEvent (e.Errors));
+               }
+
                #endregion
        }
 }