2004-04-21 Francisco Figueiredo Jr. <fxjrlists@yahoo.com.br>
authorFrancisco Figueiredo Jr. <fxjr@mono-cvs.ximian.com>
Wed, 21 Apr 2004 15:39:50 +0000 (15:39 -0000)
committerFrancisco Figueiredo Jr. <fxjr@mono-cvs.ximian.com>
Wed, 21 Apr 2004 15:39:50 +0000 (15:39 -0000)
        * Npgsql/NpgsqlDataAdapter.cs: Changed RowUpdated and RowUpdating prefix to Npgsql.
* Npgsql/NpgsqlClosedState.cs: Removed dependency in TlsException. Carlos Guzman will change this excpetion to internal.
* Npgsql/NpgsqlCommand.cs                                                       * Npgsql/NpgsqlCommand.resx                                                     * Npgsql/NpgsqlConnection.cs                                                    * Npgsql/NpgsqlConnection.resx                                                  * Npgsql/NpgsqlDataAdapter.cs                                                   * Npgsql/NpgsqlError.cs                                                         * Npgsql/NpgsqlException.cs                                                     * Npgsql/NpgsqlException.resx                                                   * Npgsql/NpgsqlMediator.cs                                                      * Npgsql/NpgsqlState.cs                                                         * Npgsql/NpgsqlState.resx                                                       * Npgsql/PGUtil.cs : Added initial error handling code improvements. Thanks Glen Parker (glenebob@nwlink.com) for the patch. NpgsqlException now gives aceess to error collection through the Errors property. This property return a collection of NpgsqlErrors objects. Also it gives access to error message, hint, severity and code. This fixes the feature request 689 in gborg.

svn path=/trunk/mcs/; revision=25786

26 files changed:
mcs/class/Npgsql/ChangeLog
mcs/class/Npgsql/Npgsql/NpgsqlAsciiRow.cs
mcs/class/Npgsql/Npgsql/NpgsqlBinaryRow.cs
mcs/class/Npgsql/Npgsql/NpgsqlClosedState.cs
mcs/class/Npgsql/Npgsql/NpgsqlCommand.cs
mcs/class/Npgsql/Npgsql/NpgsqlCommand.resx
mcs/class/Npgsql/Npgsql/NpgsqlConnection.cs
mcs/class/Npgsql/Npgsql/NpgsqlConnection.resx
mcs/class/Npgsql/Npgsql/NpgsqlConnector.cs
mcs/class/Npgsql/Npgsql/NpgsqlConnectorPool.cs
mcs/class/Npgsql/Npgsql/NpgsqlDataAdapter.cs
mcs/class/Npgsql/Npgsql/NpgsqlDataReader.cs
mcs/class/Npgsql/Npgsql/NpgsqlError.cs
mcs/class/Npgsql/Npgsql/NpgsqlEventLog.cs
mcs/class/Npgsql/Npgsql/NpgsqlException.cs
mcs/class/Npgsql/Npgsql/NpgsqlException.resx
mcs/class/Npgsql/Npgsql/NpgsqlMediator.cs
mcs/class/Npgsql/Npgsql/NpgsqlParameter.cs
mcs/class/Npgsql/Npgsql/NpgsqlRowDescription.cs
mcs/class/Npgsql/Npgsql/NpgsqlStartupPacket.cs
mcs/class/Npgsql/Npgsql/NpgsqlState.cs
mcs/class/Npgsql/Npgsql/NpgsqlState.resx
mcs/class/Npgsql/Npgsql/NpgsqlTransaction.cs
mcs/class/Npgsql/Npgsql/PGUtil.cs
mcs/class/Npgsql/Test/CommandTests.cs
mcs/class/Npgsql/Test/DataReaderTests.cs

index 6dfd19487e462fc4b5accef00e1b596ffd89aa7a..35ef6f8e83b64ca6b569b80a43b40b9446b4c85a 100644 (file)
@@ -1,3 +1,22 @@
+2004-04-21  Francisco Figueiredo Jr.  <fxjrlists@yahoo.com.br>
+       * Npgsql/NpgsqlDataAdapter.cs: Changed RowUpdated and RowUpdating prefix to Npgsql.
+       * Npgsql/NpgsqlClosedState.cs: Removed dependency in TlsException. Carlos Guzman will change this excpetion to internal.
+
+       * Npgsql/NpgsqlCommand.cs
+       * Npgsql/NpgsqlCommand.resx
+       * Npgsql/NpgsqlConnection.cs
+       * Npgsql/NpgsqlConnection.resx
+       * Npgsql/NpgsqlDataAdapter.cs
+       * Npgsql/NpgsqlError.cs
+       * Npgsql/NpgsqlException.cs
+       * Npgsql/NpgsqlException.resx
+       * Npgsql/NpgsqlMediator.cs
+       * Npgsql/NpgsqlState.cs
+       * Npgsql/NpgsqlState.resx
+       * Npgsql/PGUtil.cs : Added initial error handling code improvements. Thanks Glen Parker (glenebob@nwlink.com) for the patch. NpgsqlException now gives aceess to error collection through the Errors property. This property return a collection of NpgsqlErrors objects. Also it gives access to error message, hint, severity and code. This fixes the feature request 689 in gborg.
+
+
+
 2004-04-09  Francisco Figueiredo Jr.  <fxjrlists@yahoo.com.br>
        * Npgsql/NpgsqlDataAdapter.cs: Fixed DataAdapter to raise the RowUpdating and RowUpdated events. This also fixes some issues in gborg 710 bug. This modification may have broken CommandBuilder support. Working on that.
 
index 06dcf95494fadcc6132eb21724fcdca78d46afdb..7f12f2463932b6cc5decfb0d29c4456cb893a3bd 100755 (executable)
@@ -190,7 +190,7 @@ namespace Npgsql
         // We only need to do this for version 2 protocol.
         private static Boolean IsBackendNull(Byte[] null_map_array, Int32 index)
         {
-            
+
             // Get the byte that holds the bit index position.
             Byte test_byte = null_map_array[index/8];
 
@@ -221,7 +221,7 @@ namespace Npgsql
 
                 if ((index < 0) || (index >= row_desc.NumFields))
                     throw new ArgumentOutOfRangeException("this[] index value");
-                
+
                 return data[index];
 
 
index 3aab7efe7cedc265b19d6ba08dac15bdb46aad83..88769bf7328ef8e33dad8ff87843a5dc0e5214f5 100755 (executable)
@@ -80,7 +80,7 @@ namespace Npgsql
                 if (IsBackendNull(null_map_array, field_count))
                 {
                     // Field is null just keep next field.
-                   
+
                     data.Add(DBNull.Value);
                     continue;
                 }
index 41a64a8683480c75480a54e3814be588b0a3097b..2b959f0b510503c9a6a81b7238d17dbefad7f903 100755 (executable)
@@ -52,53 +52,47 @@ namespace Npgsql
                 return _instance;
             }
         }
-        
-        
+
+
         public override void Open(NpgsqlConnection context)
         {
 
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Open");
 
-            try
+            TcpClient tcpc = new TcpClient(context.ServerName, Int32.Parse(context.ServerPort));
+            Stream stream = tcpc.GetStream();
+            // If the PostgreSQL server has SSL connections enabled Open SslClientStream if (response == 'S') {
+            if (context.SSL == "yes")
             {
-                
-                TcpClient tcpc = new TcpClient(context.ServerName, Int32.Parse(context.ServerPort));
-                Stream stream = tcpc.GetStream();
-                // If the PostgreSQL server has SSL connections enabled Open SslClientStream if (response == 'S') {
-                if (context.SSL == "yes")
+                PGUtil.WriteInt32(stream, 8);
+                PGUtil.WriteInt32(stream,80877103);
+                // Receive response
+                Char response = (Char)stream.ReadByte();
+                if (response == 'S')
                 {
-                    PGUtil.WriteInt32(stream, 8);
-                    PGUtil.WriteInt32(stream,80877103);
-                    // Receive response
-                    Char response = (Char)stream.ReadByte();
-                    if (response == 'S')
-                    {
-                        stream = new SslClientStream(tcpc.GetStream(), context.ServerName, true, Mono.Security.Protocol.Tls.SecurityProtocolType.Default);
-                        /*stream = new SslClientStream(
-                            tcpc.GetStream(),
-                            context.ServerName,
-                            true,
-                            Tls.SecurityProtocolType.Tls|
-                            Tls.SecurityProtocolType.Ssl3);*/
-                        
-                            
-                        ((SslClientStream)stream).ServerCertValidationDelegate = context.CertificateValidationCallback;
-                        ((SslClientStream)stream).ClientCertSelectionDelegate = context.CertificateSelectionCallback;
-                        ((SslClientStream)stream).PrivateKeyCertSelectionDelegate = context.PrivateKeySelectionCallback;
-
-                    }
+                    stream = new SslClientStream(tcpc.GetStream(),
+                                                 context.ServerName,
+                                                 true,
+                                                 Mono.Security.Protocol.Tls.SecurityProtocolType.Default);
+                    /*stream = new SslClientStream(
+                        tcpc.GetStream(),
+                        context.ServerName,
+                        true,
+                        Tls.SecurityProtocolType.Tls|
+                        Tls.SecurityProtocolType.Ssl3);*/
+
+
+                    ((SslClientStream)stream).ServerCertValidationDelegate = context.CertificateValidationCallback;
+                    ((SslClientStream)stream).ClientCertSelectionDelegate = context.CertificateSelectionCallback;
+                    ((SslClientStream)stream).PrivateKeyCertSelectionDelegate = context.PrivateKeySelectionCallback;
+
                 }
-                
-                
+            }
 
-                context.Connector.Stream = stream;
 
 
-            }
-            catch (TlsException e)
-            {
-                throw new NpgsqlException(e.ToString());
-            }
+            context.Connector.Stream = stream;
+
 
             NpgsqlEventLog.LogMsg(resman, "Log_ConnectedTo", LogLevel.Normal, context.ServerName, context.ServerPort);
             ChangeState(context, NpgsqlConnectedState.Instance);
index 75571bc6651943f382f490fe932e8970d1cdb5cf..6fee9d6b778aa337e6e371a822e7696ccc57757e 100755 (executable)
@@ -343,16 +343,8 @@ namespace Npgsql
 
             // Check if there were any errors.
             if (connection.Mediator.Errors.Count > 0)
-            {
-                StringWriter sw = new StringWriter();
-                sw.WriteLine(String.Format(resman.GetString("Exception_MediatorErrors"), "ExecuteNonQuery"));
-                uint i = 1;
-                foreach(string error in connection.Mediator.Errors)
-                {
-                    sw.WriteLine("{0}. {1}", i++, error);
-                }
-                throw new NpgsqlException(sw.ToString());
-            }
+                throw new NpgsqlException(resman.GetString("Exception_BackendErrors"), connection.Mediator.Errors);
+
 
             CheckNotification();
 
@@ -364,13 +356,13 @@ namespace Npgsql
             if(connection.Mediator.GetCompletedResponses().Count == 0)
                 return -1;
 
-            
+
             // Check if the response is available.
             String firstCompletedResponse = (String)connection.Mediator.GetCompletedResponses()[0];
-            
+
             if (firstCompletedResponse == null)
                 return -1;
-                                                                                                      
+
             String[] ret_string_tokens = firstCompletedResponse.Split(null);        // whitespace separator.
 
 
@@ -378,8 +370,8 @@ namespace Npgsql
             // Only theses commands return rows affected.
             // [FIXME] Is there a better way to check this??
             if ((String.Compare(ret_string_tokens[0], "INSERT", true) == 0) ||
-                (String.Compare(ret_string_tokens[0], "UPDATE", true) == 0) ||
-                (String.Compare(ret_string_tokens[0], "DELETE", true) == 0))
+                    (String.Compare(ret_string_tokens[0], "UPDATE", true) == 0) ||
+                    (String.Compare(ret_string_tokens[0], "DELETE", true) == 0))
 
                 // The number of rows affected is in the third token for insert queries
                 // and in the second token for update and delete queries.
@@ -458,20 +450,12 @@ namespace Npgsql
 
             // Check if there were any errors.
             if (connection.Mediator.Errors.Count > 0)
-            {
-                StringWriter sw = new StringWriter();
-                sw.WriteLine(String.Format(resman.GetString("Exception_MediatorErrors_1P"), "ExecuteReader", cb));
-                uint i = 1;
-                foreach(string error in connection.Mediator.Errors)
-                {
-                    sw.WriteLine("{0}. {1}", i++, error);
-                }
-                throw new NpgsqlException(sw.ToString());
-            }
+                throw new NpgsqlException(resman.GetString("Exception_BackendErrors"), connection.Mediator.Errors);
+
 
             CheckNotification();
 
-            
+
             // Get the resultsets and create a Datareader with them.
             return new NpgsqlDataReader(connection.Mediator.GetResultSets(), connection.Mediator.GetCompletedResponses(), connection, cb);
         }
@@ -531,16 +515,9 @@ namespace Npgsql
             // Check if there were any errors.
             // [FIXME] Just check the first error.
             if (connection.Mediator.Errors.Count > 0)
-            {
-                StringWriter sw = new StringWriter();
-                sw.WriteLine(String.Format(resman.GetString("Exception_MediatorErrors"), "ExecuteScalar"));
-                uint i = 1;
-                foreach(string error in connection.Mediator.Errors)
-                {
-                    sw.WriteLine("{0}. {1}", i++, error);
-                }
-                throw new NpgsqlException(sw.ToString());
-            }
+                throw new NpgsqlException(resman.GetString("Exception_BackendErrors"), connection.Mediator.Errors);
+
+
 
             CheckNotification();
 
@@ -554,9 +531,9 @@ namespace Npgsql
             // First data is the RowDescription object.
             // Check all resultsets as insert commands could have been sent along
             // with resultset queries. The insert commands return null and and some queries
-            // may return empty resultsets, so, if we find one of these, skip to next resultset. 
+            // may return empty resultsets, so, if we find one of these, skip to next resultset.
             // If no resultset is found, return null as per specification.
-            
+
             NpgsqlAsciiRow ascii_row = null;
             foreach( NpgsqlResultSet nrs in resultSets )
             {
@@ -566,8 +543,8 @@ namespace Npgsql
                     return ascii_row[0];
                 }
             }
-            
-            
+
+
             return null;
 
 
index eca78e78f42c5da235b254e257d8b407b2fa75c5..848913ca6d1e92621b9653c3d9b946ecdba94bfd 100644 (file)
        <data name="Exception_CommandTypeTableDirect">
                <value>Only Text and StoredProcedure types supported!</value>
        </data>
+       <data name="Exception_BackendErrors">
+               <value>There have been errors reported by the backend.</value>
+       </data>
        <data name="Exception_MediatorErrors">
                <value>There have been errors on {0}():</value>
        </data>
index 53a64f4241d9e1a2577d212060b7ce18112ce1f2..358080815343ef28254e05991e57412d3c4ea4c6 100755 (executable)
@@ -61,14 +61,14 @@ namespace Npgsql
         /// </summary>
         public event NotificationEventHandler Notification;
 
-        
+
         // Public properties for ssl callbacks
         public CertificateValidationCallback CertificateValidationCallback;
         public CertificateSelectionCallback CertificateSelectionCallback;
         public PrivateKeySelectionCallback PrivateKeySelectionCallback;
-        
-        
-        
+
+
+
         private NpgsqlState                    state;
 
         private ConnectionState        connection_state;
@@ -93,15 +93,15 @@ namespace Npgsql
         // These are for ODBC connection string compatibility
         internal readonly String ODBC_USERID   = "UID";
         internal readonly String ODBC_PASSWORD = "PWD";
-        
+
         // These are for the connection pool
         internal readonly String MIN_POOL_SIZE = "MINPOOLSIZE";
         internal readonly String MAX_POOL_SIZE = "MAXPOOLSIZE";
-        
+
         internal readonly String CONN_ENCODING = "ENCODING";
-        
+
         internal readonly String CONN_TIMEOUT = "TIMEOUT";
-        
+
 
         // Values for possible CancelRequest messages.
         private NpgsqlBackEndKeyData backend_keydata;
@@ -116,9 +116,9 @@ namespace Npgsql
         private readonly String CLASSNAME = "NpgsqlConnection";
 
         private Stream                                 stream;
-        
+
         private Connector               _connector;
-        
+
         private Encoding                               connection_encoding;
 
         private Boolean                                        _supportsPrepare = false;
@@ -130,7 +130,7 @@ namespace Npgsql
         private System.Resources.ResourceManager resman;
 
         private Int32                   _backendProtocolVersion;
-        
+
         private Int32                   _connectionTimeout;
 
 
@@ -161,17 +161,17 @@ namespace Npgsql
 
             _mediator = new NpgsqlMediator();
             _oidToNameMapping = new Hashtable();
-            
+
             _connectionTimeout = 15;
-        
+
             CertificateValidationCallback = new CertificateValidationCallback(DefaultCertificateValidationCallback);
-                    
+
 
             if (connection_string != String.Empty)
                 ParseConnectionString();
         }
 
-        
+
         /// <summary>
         /// Gets or sets the string used to open a SQL Server database.
         /// </summary>
@@ -381,36 +381,36 @@ namespace Npgsql
             if (connection_string_values[CONN_ENCODING] == null)
                 connection_string_values[CONN_ENCODING] = "SQL_ASCII";
             if (connection_string_values[CONN_TIMEOUT] == null)
-                connection_string_values[CONN_TIMEOUT] = "15";                
-            
+                connection_string_values[CONN_TIMEOUT] = "15";
+
             try
             {
-            
+
                 // Check if the connection is already open.
                 if (connection_state == ConnectionState.Open)
                     throw new NpgsqlException(resman.GetString("Exception_ConnOpen"));
 
                 lock(ConnectorPool.ConnectorPoolMgr)
                 {
-                    Connector = ConnectorPool.ConnectorPoolMgr.RequestConnector(ConnectionString, 
-                                                                                Int32.Parse((String)connection_string_values[MAX_POOL_SIZE]),
-                                                                                Int32.Parse((String)connection_string_values[CONN_TIMEOUT]),
-                                                                                false);
+                    Connector = ConnectorPool.ConnectorPoolMgr.RequestConnector(ConnectionString,
+                                Int32.Parse((String)connection_string_values[MAX_POOL_SIZE]),
+                                Int32.Parse((String)connection_string_values[CONN_TIMEOUT]),
+                                false);
                     Connector.InUse = true;
                 }
-                
+
                 if (!Connector.IsInitialized)
                 {
-                    
+
                     // Reset state to initialize new connector in pool.
                     CurrentState = NpgsqlClosedState.Instance;
 
                     // Try first connect using the 3.0 protocol...
                     CurrentState.Open(this);
-                    
+
                     // Change the state of connection to open.
                     connection_state = ConnectionState.Open;
-        
+
                     // Check if there were any errors.
                     if (_mediator.Errors.Count > 0)
                     {
@@ -418,7 +418,7 @@ namespace Npgsql
                         // As the message can be localized, just check the initial unlocalized part of the
                         // message. If it is an error other than protocol error, when connecting using
                         // version 2.0 we shall catch the error again.
-                        if (((String)_mediator.Errors[0]).StartsWith("FATAL"))
+                        if (((NpgsqlError)_mediator.Errors[0]).Message.StartsWith("FATAL"))
                         {
                             // Try using the 2.0 protocol.
                             _mediator.Reset();
@@ -426,23 +426,13 @@ namespace Npgsql
                             BackendProtocolVersion = ProtocolVersion.Version2;
                             CurrentState.Open(this);
                         }
-    
+
                         // Keep checking for errors...
                         if(_mediator.Errors.Count > 0)
-                        {
-                            StringWriter sw = new StringWriter();
-                            sw.WriteLine(resman.GetString("Exception_OpenError"));
-                            uint i = 1;
-                            foreach(string error in _mediator.Errors)
-                            {
-                                sw.WriteLine("{0}. {1}", i++, error);
-                            }
-                            CurrentState = NpgsqlClosedState.Instance;
-                            _mediator.Reset();
-                            throw new NpgsqlException(sw.ToString());
-                        }
+                            throw new NpgsqlException(resman.GetString("Exception_BackendErrors"), _mediator.Errors);
+
                     }
-    
+
                     backend_keydata = _mediator.GetBackEndKeyData();
 
                     // Get version information to enable/disable server version features.
@@ -452,37 +442,37 @@ namespace Npgsql
                         NpgsqlCommand command = new NpgsqlCommand("select version();set DATESTYLE TO ISO;", this);
                         _serverVersion = (String) command.ExecuteScalar();
                     }
-                    
-                    // Adjust client encoding. 
-                
+
+                    // Adjust client encoding.
+
                     //NpgsqlCommand commandEncoding = new NpgsqlCommand("show client_encoding", this);
                     //String clientEncoding = (String)commandEncoding.ExecuteScalar();
-    
+
                     if (connection_string_values[CONN_ENCODING].Equals("UNICODE"))
                         connection_encoding = Encoding.UTF8;
-                  
-                    
+
+
                     Connector.ServerVersion = ServerVersion;
                     Connector.BackendProtocolVersion = BackendProtocolVersion;
                     Connector.Encoding = connection_encoding;
-                    
+
                 }
-                                
-                // Connector was obtained from pool. 
+
+                // Connector was obtained from pool.
                 // Do a mini initialization in the state machine.
-                
+
                 connection_state = ConnectionState.Open;
                 ServerVersion = Connector.ServerVersion;
                 BackendProtocolVersion = Connector.BackendProtocolVersion;
                 Encoding = Connector.Encoding;
-                
+
                 CurrentState = NpgsqlReadyState.Instance;
-                
+
                 ProcessServerVersion();
                 _oidToNameMapping = NpgsqlTypesHelper.LoadTypesMapping(this);
-                
-                
-                
+
+
+
 
             }
 
@@ -504,7 +494,7 @@ namespace Npgsql
         public void Close()
         {
             Dispose(true);
-            
+
         }
 
         /// <summary>
@@ -540,7 +530,7 @@ namespace Npgsql
         {
             if (disposing)
             {
-                // Only if explicitly calling Close or dispose we still have access to 
+                // Only if explicitly calling Close or dispose we still have access to
                 // managed resources.
                 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Dispose", disposing);
 
@@ -550,7 +540,7 @@ namespace Npgsql
                     {
                         CurrentState.Close(this);
                     }
-                    
+
                 }
                 catch (IOException e)
                 {
@@ -563,12 +553,12 @@ namespace Npgsql
                         stream.Close();*/
                     connection_state = ConnectionState.Closed;
                 }
-                                
+
             }
             base.Dispose (disposing);
         }
-        
-        
+
+
         public Object Clone()
         {
             return new NpgsqlConnection(ConnectionString);
@@ -650,7 +640,7 @@ namespace Npgsql
                 // 3.0+ version is set by ParameterStatus message.
                 // On protocol 3.0, 7.4 and above support it.
                 SupportsPrepare = (_serverVersion.IndexOf("7.4") != -1)
-                                    || (_serverVersion.IndexOf("7.5") != -1);
+                                  || (_serverVersion.IndexOf("7.5") != -1);
             }
         }
 
@@ -664,7 +654,7 @@ namespace Npgsql
                 stream = value;
             }
         }
-        
+
         internal Connector Connector
         {
             get
@@ -727,17 +717,17 @@ namespace Npgsql
         {
             CurrentState.Execute(this, execute);
         }
-        
-        
+
+
         // Default SSL Callbacks implementation.
         private Boolean DefaultCertificateValidationCallback(
-                                                    X509Certificate certificate,
-                                                    int[]        certificateErrors)
+            X509Certificate certificate,
+            int[]        certificateErrors)
         {
             return true;
         }
-        
-        
+
+
 
         internal NpgsqlState CurrentState {
             get
@@ -808,7 +798,7 @@ namespace Npgsql
             {
                 return connection_encoding;
             }
-            
+
             set
             {
                 connection_encoding = value;
@@ -877,14 +867,14 @@ namespace Npgsql
                 _backendProtocolVersion = value;
             }
         }
-        
+
         internal Int32 MinPoolSize {
             get
             {
                 return Int32.Parse((String)connection_string_values[MIN_POOL_SIZE]);
             }
         }
-        
+
         internal Int32 MaxPoolSize {
             get
             {
index 2dd52c9710bedab70983f915a9bdfa3b86477b98..78b5a14e8a6e637052e08c62a9096e3e61c50a9c 100644 (file)
        <data name="Exception_ChangeDatabaseOnOpenConn">
                <value>The connection is not open. Use 'Database=X;' in the connection string to set the database for a closed connection.</value>
        </data>
-</root>
\ No newline at end of file
+    <data name="Exception_BackendErrors">
+               <value>There have been errors reported by the backend.</value>
+       </data>
+</root>
index 9d5487b62c5ee2d4eb2547caef4f0ccc3b734e92..4868e3b715a7312c7ebcf10ad4a306475ab915c0 100755 (executable)
@@ -33,7 +33,7 @@ namespace Npgsql
     /// <summary>
     /// !!! Helper class, for compilation only.
     /// </summary>
-    
+
     /// <summary>
     /// Connector implements the logic for the Connection Objects to
     /// access the physical connection to the database, and isolate
@@ -46,19 +46,19 @@ namespace Npgsql
 
 
         private Stream _stream;
-        
+
         // This is information about the connection
         // this connector is holding. For while only the server version is used.
         // Change later for a more generic way to keep it. (Hashtable)
         private String _serverVersion;
-        
+
         private Int32 _backendProtocolVersion;
-        
+
         private Encoding _encoding;
-        
-        
+
+
         private Boolean _isInitialized;
-        
+
         private Boolean mPooled;
         private Boolean mOpen;
 
@@ -88,46 +88,46 @@ namespace Npgsql
                 this.mPooled = value;
             }
         }
-        
+
         internal String ServerVersion
         {
             get
             {
                 return _serverVersion;
             }
-            
+
             set
             {
                 _serverVersion = value;
             }
         }
-        
+
         internal Encoding Encoding
         {
             get
             {
                 return _encoding;
             }
-            
+
             set
             {
                 _encoding = value;
             }
         }
-        
+
         internal Int32 BackendProtocolVersion
         {
             get
             {
                 return _backendProtocolVersion;
             }
-            
+
             set
             {
                 _backendProtocolVersion = value;
             }
         }
-        
+
         internal Stream Stream {
             get
             {
@@ -139,16 +139,16 @@ namespace Npgsql
                 _isInitialized = true;
             }
         }
-        
+
         internal Boolean IsInitialized
         {
             get
             {
                 return _isInitialized;
             }
-            
+
         }
-        
+
 
         /// <value>Buffer for the public Shared property</value>
         private bool mShared;
@@ -204,7 +204,7 @@ namespace Npgsql
         // !!! to be fixed
         //private Npgsql.Socket Socket;
 
-        
+
         /// <summary>
         /// Default constructor. Creates a pooled Connector by default.
         /// </summary>
@@ -235,8 +235,8 @@ namespace Npgsql
             //this.Socket.Open(); // !!! to be fixed
             //this.mOpen = true;
         }
-        
-        
+
+
         internal Boolean InUse {
             get
             {
@@ -246,7 +246,7 @@ namespace Npgsql
             {
                 _inUse = value;
             }
-            
+
         }
 
         /// <summary>
index 9bcf314ded8a16c245227eda7424b57975656712..dfb698d8e37af78c8296ca1426c470b151b74894 100755 (executable)
@@ -33,12 +33,12 @@ namespace Npgsql
         /// <value>Unique static instance of the connector pool
         /// mamager.</value>
         internal static ConnectorPool ConnectorPoolMgr = new Npgsql.ConnectorPool();
-        
+
         public ConnectorPool()
         {
             PooledConnectors = new Hashtable();
         }
-        
+
 
         /// <value>Map of index to unused pooled connectors, avaliable to the
         /// next RequestConnector() call.</value>
@@ -107,8 +107,8 @@ namespace Npgsql
             // point the list to the new head
             this.PooledConnectors = Connector;
         }*/
-        
-        
+
+
         internal Int32 GetPoolSize(String connectionString)
         {
             ArrayList pool = (ArrayList)PooledConnectors[connectionString];
@@ -116,8 +116,8 @@ namespace Npgsql
                 return 0;
             else
                 return pool.Count;
-            
-                       
+
+
         }
 
         /// <summary>
@@ -130,9 +130,9 @@ namespace Npgsql
         /// on a single connector. </param>
         /// <returns>A pooled connector object.</returns>
         internal Npgsql.Connector RequestConnector (String connectionString,
-                                                    Int32 maxPoolSize,
-                                                    Int32 timeout,
-                                                    Boolean shared )
+                Int32 maxPoolSize,
+                Int32 timeout,
+                Boolean shared )
         {
             Connector connector;
             ArrayList connectorPool = null;
@@ -152,7 +152,7 @@ namespace Npgsql
                         return Connector;
                     }
                 }*/
-                
+
                 return null;
             }
             else
@@ -160,42 +160,42 @@ namespace Npgsql
                 // if a shared connector could not be found or a
                 // nonshared connector is requested, then the pooled
                 // (unused) connectors are beeing searched.
-                
-                
+
+
                 connectorPool = (ArrayList)PooledConnectors[connectionString];
-                
+
                 if (connectorPool == null)
                 {
                     connectorPool = new ArrayList();
                     PooledConnectors[connectionString] = connectorPool;
                 }
-                
-                
+
+
                 // Now look for an available connector.
-                
+
                 Connector freeConnector = FindFreeConnector(connectorPool);
                 if (freeConnector != null)
                     return freeConnector;
-                
+
                 // No suitable connector could be found, so create new one
                 // if there is room available.
-                
+
                 if (connectorPool.Count < maxPoolSize)
                 {
                     connector = new Npgsql.Connector(connectionString, shared);
 
                     connectorPool.Add(connector);
-            
+
 
                     // and then returned to the caller
-                    return connector;                
+                    return connector;
                 }
                 else
                 {
                     // keep checking in the pool until some connector is available or
                     // a timeout occurs.
                     Int32 timeoutMilliseconds = timeout * 1000;
-                    
+
                     while (timeoutMilliseconds > 0)
                     {
                         Connector freeConnector2 = FindFreeConnector(connectorPool);
@@ -205,15 +205,15 @@ namespace Npgsql
                             Thread.Sleep((timeoutMilliseconds > 900) ? 900 : timeoutMilliseconds);
                         timeoutMilliseconds -= 900;
                     }
-                    
+
                     throw new NpgsqlException("Timeout while getting a connection from pool.");
-                    
+
                 }
-                
+
             }
 
         }
-        
+
         private Connector FindFreeConnector(ArrayList connectorPool)
         {
             foreach (Connector c in connectorPool)
@@ -221,7 +221,7 @@ namespace Npgsql
                 if (!c.InUse)
                     return c;
             }
-            
+
             return null;
         }
     }
index 37bd04da47d9024582c81cc093520a6980d35f52..02397261a1ca574f251b0e1dd783982c5b7a1a40 100755 (executable)
@@ -36,16 +36,16 @@ namespace Npgsql
     /// </summary>
     /// <param name="sender">The source of the event.</param>
     /// <param name="e">A <see cref="Npgsql.NpgsqlRowUpdatedEventArgs">NpgsqlRowUpdatedEventArgs</see> that contains the event data.</param>
-    public delegate void RowUpdatedEventHandler(Object sender, NpgsqlRowUpdatedEventArgs e);
-    
+    public delegate void NpgsqlRowUpdatedEventHandler(Object sender, NpgsqlRowUpdatedEventArgs e);
+
     /// <summary>
     /// Represents the method that handles the <see cref="Npgsql.NpgsqlDataAdapter.RowUpdating">RowUpdating</see> events.
     /// </summary>
     /// <param name="sender">The source of the event.</param>
     /// <param name="e">A <see cref="Npgsql.NpgsqlRowUpdatingEventArgs">NpgsqlRowUpdatingEventArgs</see> that contains the event data.</param>
-    public delegate void RowUpdatingEventHandler(Object sender, NpgsqlRowUpdatingEventArgs e);
-    
-    
+    public delegate void NpgsqlRowUpdatingEventHandler(Object sender, NpgsqlRowUpdatingEventArgs e);
+
+
     public sealed class NpgsqlDataAdapter : DbDataAdapter, IDbDataAdapter
     {
 
@@ -58,10 +58,10 @@ namespace Npgsql
 
         // Log support
         private static readonly String CLASSNAME = "NpgsqlDataAdapter";
-        
-        
-        public event RowUpdatedEventHandler RowUpdated;
-        public event RowUpdatingEventHandler RowUpdating;        
+
+
+        public event NpgsqlRowUpdatedEventHandler RowUpdated;
+        public event NpgsqlRowUpdatingEventHandler RowUpdating;
 
         public NpgsqlDataAdapter()
         {}
@@ -123,7 +123,7 @@ namespace Npgsql
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "OnRowUpdating");
             if ((RowUpdating != null) && (value is NpgsqlRowUpdatingEventArgs))
                 RowUpdating(this, (NpgsqlRowUpdatingEventArgs) value);
-                        
+
             /*switch (value.StatementType)
             {
                 case StatementType.Insert:
@@ -157,7 +157,7 @@ namespace Npgsql
                 parameter.Value = value.Row [dsColumnName, rowVersion];
             }
             value.Row.AcceptChanges ();*/
-            
+
         }
 
         ITableMappingCollection IDataAdapter.TableMappings
@@ -293,8 +293,7 @@ public class NpgsqlRowUpdatingEventArgs : RowUpdatingEventArgs
         DataTableMapping tableMapping
     ) : base(dataRow, command, statementType, tableMapping)
 
-    {
-    }
+    {}
 
 }
 
@@ -307,7 +306,6 @@ public class NpgsqlRowUpdatedEventArgs : RowUpdatedEventArgs
         DataTableMapping tableMapping
     ) : base(dataRow, command, statementType, tableMapping)
 
-    {
-    }
+    {}
 
 }
index c21dcfaa25f47c781ea02d72d5bb99ff945b5e18..290805a222252e602234535639adb7d1fa5e0268 100755 (executable)
@@ -46,7 +46,7 @@ namespace Npgsql
         private DataTable                      _currentResultsetSchema;
         private CommandBehavior     _behavior;
         private Boolean             _isClosed;
-        
+
 
 
         // Logging related values
@@ -59,10 +59,10 @@ namespace Npgsql
             _connection = connection;
             _rowIndex = -1;
             _resultsetIndex = 0;
-            
+
             if (_resultsets.Count > 0)
                 _currentResultset = (NpgsqlResultSet)_resultsets[_resultsetIndex];
-                
+
             _behavior = behavior;
             _isClosed = false;
 
@@ -73,8 +73,8 @@ namespace Npgsql
             //NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "CanRead");
             /*if (_currentResultset == null)
                return false;*/
-            return ((_currentResultset != null) && 
-                    (_currentResultset.Count > 0) && 
+            return ((_currentResultset != null) &&
+                    (_currentResultset.Count > 0) &&
                     (_rowIndex < _currentResultset.Count));
 
         }
@@ -89,7 +89,7 @@ namespace Npgsql
         {
             Dispose(true);
         }
-        
+
         /// <summary>
         /// Releases the resources used by the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see>.
         /// </summary>
@@ -125,7 +125,7 @@ namespace Npgsql
             {
                 NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "RecordsAffected");
 
-            
+
                 if (CanRead())
                     return -1;
 
@@ -138,7 +138,7 @@ namespace Npgsql
 
         public void Close()
         {
-           if ((_behavior & CommandBehavior.CloseConnection) == CommandBehavior.CloseConnection)
+            if ((_behavior & CommandBehavior.CloseConnection) == CommandBehavior.CloseConnection)
             {
                 _connection.Close();
                 _isClosed = true;
@@ -149,7 +149,7 @@ namespace Npgsql
         public Boolean NextResult()
         {
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "NextResult");
-            
+
             if((_resultsetIndex + 1) < _resultsets.Count)
             {
                 _resultsetIndex++;
@@ -167,7 +167,7 @@ namespace Npgsql
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Read");
 
             _rowIndex++;
-            
+
             if (!CanRead())
                 return false;
             else
@@ -193,7 +193,7 @@ namespace Npgsql
             {
 
                 NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "FieldCount");
-                
+
                 if (_currentResultset == null) //Executed a non return rows query.
                     return -1;
                 else
@@ -375,14 +375,14 @@ namespace Npgsql
         public Single GetFloat(Int32 i)
         {
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetFloat");
-            
+
             return (Single) GetValue(i);
         }
 
         public Double GetDouble(Int32 i)
         {
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetDouble");
-            
+
             return (Double) GetValue(i);
         }
 
index 93bd19f2ff1ab256ef2b8d8f1f7c414c20b974c4..9c3d71e9ed80d5a1a24b665886d2b253edab72a5 100644 (file)
@@ -31,28 +31,42 @@ namespace Npgsql
 {
 
     /// <summary>
-    /// This class represents the ErrorResponse message sent from PostgreSQL
-    /// server.
+    /// This class represents the ErrorResponse and NoticeResponse
+    /// message sent from PostgreSQL server.
     /// </summary>
     ///
-    internal sealed class NpgsqlError
+    public sealed class NpgsqlError
     {
         // Logging related values
         private static readonly String CLASSNAME = "NpgsqlError";
 
-        private Int32 _protocolVersion;
-        private String _severity;
-        private String _code;
-        private String _message;
+        private Int32 protocol_version;
+        private String _severity = "";
+        private String _code = "";
+        private String _message = "";
         private String _detail;
-        private String _hint;
+        private String _hint = "";
         private String _position;
         private String _where;
         private String _file;
         private String _line;
         private String _routine;
 
+        public String Severity
+        {
+            get
+            {
+                return _severity;
+            }
+        }
 
+        public String Code
+        {
+            get
+            {
+                return _code;
+            }
+        }
 
         public String Message
         {
@@ -62,91 +76,119 @@ namespace Npgsql
             }
         }
 
+        public String Hint
+        {
+            get
+            {
+                return _hint;
+            }
+        }
+
 
+        private NpgsqlError()
+        {}
 
 
-        public NpgsqlError(Int32 protocolVersion)
+        internal NpgsqlError(Int32 protocolVersion)
         {
-            _protocolVersion = protocolVersion;
+            protocol_version = protocolVersion;
 
         }
 
-        public void ReadFromStream(Stream inputStream, Encoding encoding)
+        internal void ReadFromStream(Stream inputStream, Encoding encoding)
         {
-
-            if (_protocolVersion == ProtocolVersion.Version2)
+            if (protocol_version == ProtocolVersion.Version2)
             {
-                _message = PGUtil.ReadString(inputStream, encoding);
+                ReadFromStream_Ver_2(inputStream, encoding);
+            }
+            else
+            {
+                ReadFromStream_Ver_3(inputStream, encoding);
+            }
+        }
+
+        private void ReadFromStream_Ver_2(Stream inputStream, Encoding encoding)
+        {
+            String Raw;
+            String[] Parts;
+
+            Raw = PGUtil.ReadString(inputStream, encoding);
+
+            Parts = Raw.Split(new char[] {':'}, 2);
 
+            if (Parts.Length == 2)
+            {
+                _severity = Parts[0];
+                _message = Parts[1].Trim();
             }
             else
             {
-                Int32 messageLength = PGUtil.ReadInt32(inputStream, new Byte[4]);
+                _message = Parts[0];
+            }
+        }
 
-                //[TODO] Would this be the right way to do?
-                // Check the messageLength value. If it is 1178686529, this would be the
-                // "FATA" string, which would mean a protocol 2.0 error string.
+        private void ReadFromStream_Ver_3(Stream inputStream, Encoding encoding)
+        {
+            Int32 messageLength = PGUtil.ReadInt32(inputStream, new Byte[4]);
 
-                if (messageLength == 1178686529)
-                {
-                    _message = "FATA" + PGUtil.ReadString(inputStream, encoding);
-                    return;
-                }
+            //[TODO] Would this be the right way to do?
+            // Check the messageLength value. If it is 1178686529, this would be the
+            // "FATA" string, which would mean a protocol 2.0 error string.
+            if (messageLength == 1178686529)
+            {
+                _severity = "FATAL";
+                _message = "FATA" + PGUtil.ReadString(inputStream, encoding);
+                return;
+            }
 
-                Char field;
-                String fieldValue;
+            Char field;
+            String fieldValue;
 
-                field = (Char) inputStream.ReadByte();
+            field = (Char) inputStream.ReadByte();
 
-                // Now start to read fields.
-                while (field != 0)
-                {
+            // Now start to read fields.
+            while (field != 0)
+            {
+                fieldValue = PGUtil.ReadString(inputStream, encoding);
 
-                    fieldValue = PGUtil.ReadString(inputStream, encoding);
-
-                    switch (field)
-                    {
-                    case 'S':
-                        _severity = fieldValue;
-                        break;
-                    case 'C':
-                        _code = fieldValue;
-                        break;
-                    case 'M':
-                        _message = fieldValue;
-                        break;
-                    case 'D':
-                        _detail = fieldValue;
-                        break;
-                    case 'H':
-                        _hint = fieldValue;
-                        break;
-                    case 'P':
-                        _position = fieldValue;
-                        break;
-                    case 'W':
-                        _where = fieldValue;
-                        break;
-                    case 'F':
-                        _file = fieldValue;
-                        break;
-                    case 'L':
-                        _line = fieldValue;
-                        break;
-                    case 'R':
-                        _routine = fieldValue;
-                        break;
-
-                    }
-
-                    field = (Char) inputStream.ReadByte();
+                switch (field)
+                {
+                case 'S':
+                    _severity = fieldValue;
+                    break;
+                case 'C':
+                    _code = fieldValue;
+                    break;
+                case 'M':
+                    _message = fieldValue;
+                    break;
+                case 'D':
+                    _detail = fieldValue;
+                    break;
+                case 'H':
+                    _hint = fieldValue;
+                    break;
+                case 'P':
+                    _position = fieldValue;
+                    break;
+                case 'W':
+                    _where = fieldValue;
+                    break;
+                case 'F':
+                    _file = fieldValue;
+                    break;
+                case 'L':
+                    _line = fieldValue;
+                    break;
+                case 'R':
+                    _routine = fieldValue;
+                    break;
 
                 }
 
-                // Read 0 byte terminator.
-                //inputStream.ReadByte();
-            }
+                field = (Char) inputStream.ReadByte();
 
+            }
         }
     }
 }
index cfaa0762876c4246f7c3fb1efa792cc997d814ab..9df92da4f3cacdaad384c0ccfe60c0f17cc06639 100755 (executable)
@@ -146,7 +146,7 @@ namespace Npgsql
             {
                 Console.WriteLine(message);
             }
-            
+
             if (logfile != null)
             {
                 if (logfile != "")
index 619aa874a0ad9e16d43af3678526e8a08bfa37ee..4bbcc029ef48c8919234bc8be180c9e0821c899b 100755 (executable)
 
 using System;
 using System.Resources;
+using System.IO;
+using System.Text;
+using System.Collections;
 
 namespace Npgsql
 {
     [Serializable]
     public class NpgsqlException : Exception
     {
+        private IList errors;
+
 
         // Logging related values
         private static readonly String CLASSNAME = "NpgsqlException";
@@ -52,5 +57,61 @@ namespace Npgsql
         {
             NpgsqlEventLog.LogMsg(resman, "Log_ExceptionOccured", LogLevel.Normal, message + " (" + inner.Message + ")");
         }
+
+        public NpgsqlException(String message, IList errors) : base(message)
+        {
+            NpgsqlEventLog.LogMsg(resman, "Log_ExceptionOccured", LogLevel.Normal, message);
+            this.errors = errors;
+        }
+
+        public String Severity
+        {
+            get
+            {
+                return (errors != null) ? ((NpgsqlError)errors[0]).Severity : String.Empty;
+            }
+        }
+
+        public String Code
+        {
+            get
+            {
+                return (errors != null) ? ((NpgsqlError)errors[0]).Code : String.Empty;
+            }
+        }
+
+        public override String Message
+        {
+            get
+            {
+                return (errors != null) ? ((NpgsqlError)errors[0]).Message : String.Empty;
+            }
+        }
+
+        public String Hint
+        {
+            get
+            {
+                return (errors != null) ? ((NpgsqlError)errors[0]).Hint : String.Empty;
+            }
+        }
+
+        public IList Errors
+        {
+            get
+            {
+                return errors;
+            }
+
+        }
+
+        public override String ToString()
+        {
+            return String.Format(base.Message + "Severity: {0} \nCode: {1} \nMessage: {2} \nHint: {3}", Severity, Code, Message, Hint);
+        }
+
     }
+
+
+
 }
index eb113de219d8ef80067aa11b219fa09ce1222910..1698867f759ab18c346b912c6e434f66dc4a52eb 100644 (file)
        <data name="Log_ExceptionOccured">
                <value>An NpgsqlException occured: {0}.</value>
        </data>
+       <data name="Log_BackendExceptionOccured">
+               <value>An NpgsqlBackendException occured: {0}.</value>
+       </data>
 </root>
index d1e7767f23fb37b5db9cc28ce000f374a44ba53f..be93fa3d908cf2bb00a0896cb3fc84dcde12afc4 100755 (executable)
@@ -38,7 +38,8 @@ namespace Npgsql
 
     internal sealed class NpgsqlMediator
     {
-        private ArrayList                                                      _errorMessages;
+        private ArrayList                                                      _errors;
+        private ArrayList                                                      _notices;
         private        ArrayList                                                       _resultSets;
         private ArrayList                                                      _responses;
         private ArrayList             _notifications;
@@ -49,7 +50,8 @@ namespace Npgsql
 
         public NpgsqlMediator()
         {
-            _errorMessages = new ArrayList();
+            _errors = new ArrayList();
+            _notices = new ArrayList();
             _resultSets = new ArrayList();
             _responses = new ArrayList();
             _notifications = new ArrayList();
@@ -57,7 +59,8 @@ namespace Npgsql
 
         public void Reset()
         {
-            _errorMessages.Clear();
+            _errors.Clear();
+            _notices.Clear();
             _resultSets.Clear();
             _responses.Clear();
             _notifications.Clear();
@@ -68,7 +71,15 @@ namespace Npgsql
         {
             get
             {
-                return _errorMessages;
+                return _errors;
+            }
+        }
+
+        public ArrayList Notices
+        {
+            get
+            {
+                return _notices;
             }
         }
 
index cd5e05523b6e2bea7363be0042486ac377da69a9..2f68782ca29271e90cc869215e790d7fb3d49515 100755 (executable)
@@ -97,13 +97,13 @@ namespace Npgsql
         {
             resman = new System.Resources.ResourceManager(this.GetType());
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME, parameterName, value);
-            
-            
+
+
             this.value = value;
 
             this.ParameterName = parameterName;
-            
-            
+
+
             // Set db_type according to:
             // http://msdn.microsoft.com/library/en-us/cpguide/html/cpconusingparameterswithdataadapters.asp
             // Should this be in this.Value.set{}?
@@ -192,7 +192,7 @@ namespace Npgsql
                 throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), type.ToString()));
             }
 
-            
+
 
         }
 
index c79f41a6b8df2fd61d4d64007e825d3e53bbe88d..9549d5bc86ea569ee4fcf75e944e729d5695c879 100755 (executable)
@@ -165,19 +165,19 @@ namespace Npgsql
         public Int16 FieldIndex(String fieldName)
         {
             Int16 result = 0;
-                       
+
             foreach (String name in fields_index)
             {
-                
+
                 if (name.Equals(fieldName))
                 {
                     return result;
                 }
                 result++;
             }
-            
-            return -1;            
-            
+
+            return -1;
+
         }
 
     }
index 764d5adc907369d010ec91a85900cea6bc7fb67c..cc30c7ed438513a977ff2079571426310ccafd48 100755 (executable)
@@ -133,7 +133,7 @@ namespace Npgsql
 
                 // Database name.
                 PGUtil.WriteString(database_name, output_stream, encoding);
-                
+
                 // DateStyle.
                 PGUtil.WriteString("DateStyle", output_stream, encoding);
 
index fe61e619cda38a934d9234e23de3640875d6d17b..71093dac8c6180b7b4ca335ae62362d15570e88e 100755 (executable)
@@ -109,7 +109,7 @@ namespace Npgsql
                     stream.Flush();
                 }
             }*/
-            
+
             context.Connector.InUse = false;
             context.Connector = null;
             //ChangeState( context, NpgsqlClosedState.Instance );
@@ -134,6 +134,21 @@ namespace Npgsql
         ///
 
         protected virtual void ProcessBackendResponses( NpgsqlConnection context )
+        {
+            switch (context.BackendProtocolVersion)
+            {
+            case ProtocolVersion.Version2 :
+                ProcessBackendResponses_Ver_2(context);
+                break;
+
+            case ProtocolVersion.Version3 :
+                ProcessBackendResponses_Ver_3(context);
+                break;
+
+            }
+        }
+
+        protected virtual void ProcessBackendResponses_Ver_2( NpgsqlConnection context )
         {
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ProcessBackendResponses");
 
@@ -159,13 +174,14 @@ namespace Npgsql
                 {
                 case NpgsqlMessageTypes.ErrorResponse :
 
-                    NpgsqlError error = new NpgsqlError(context.BackendProtocolVersion);
-                    error.ReadFromStream(stream, context.Encoding);
+                    {
+                        NpgsqlError error = new NpgsqlError(context.BackendProtocolVersion);
+                        error.ReadFromStream(stream, context.Encoding);
 
-                    //mediator.Errors.Add(errorMessage);
-                    mediator.Errors.Add(error.Message);
+                        mediator.Errors.Add(error);
 
-                    NpgsqlEventLog.LogMsg(resman, "Log_ErrorResponse", LogLevel.Debug, error.Message);
+                        NpgsqlEventLog.LogMsg(resman, "Log_ErrorResponse", LogLevel.Debug, error.Message);
+                    }
 
                     // Return imediately if it is in the startup state or connected state as
                     // there is no more messages to consume.
@@ -187,9 +203,6 @@ namespace Npgsql
 
                     stream.Read(inputBuffer, 0, 4);
 
-                    if (context.BackendProtocolVersion >= ProtocolVersion.Version3)
-                        stream.Read(inputBuffer, 0, 4);
-
                     authType = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(inputBuffer, 0));
 
                     if ( authType == NpgsqlMessageTypes.AuthenticationOk )
@@ -337,8 +350,14 @@ namespace Npgsql
 
                 case NpgsqlMessageTypes.NoticeResponse :
 
-                    NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "NoticeResponse");
-                    String noticeResponse = PGUtil.ReadString( stream, context.Encoding );
+                    {
+                        NpgsqlError notice = new NpgsqlError(context.BackendProtocolVersion);
+                        notice.ReadFromStream(stream, context.Encoding);
+
+                        mediator.Notices.Add(notice);
+
+                        NpgsqlEventLog.LogMsg(resman, "Log_NoticeResponse", LogLevel.Debug, notice.Message);
+                    }
 
                     // Wait for ReadForQuery message
                     break;
@@ -348,9 +367,6 @@ namespace Npgsql
                     // Get the string returned.
 
 
-                    if (context.BackendProtocolVersion >= ProtocolVersion.Version3)
-                        PGUtil.ReadInt32(stream, new Byte[4]);
-
                     String result = PGUtil.ReadString(stream, context.Encoding);
 
                     NpgsqlEventLog.LogMsg(resman, "Log_CompletedResponse", LogLevel.Debug, result);
@@ -422,8 +438,303 @@ namespace Npgsql
             }
 
         }
-    }
+
+        protected virtual void ProcessBackendResponses_Ver_3( NpgsqlConnection context )
+        {
+            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ProcessBackendResponses");
+
+            BufferedStream     stream = new BufferedStream(context.Stream);
+            Int32      authType;
+            Boolean readyForQuery = false;
+
+            NpgsqlMediator mediator = context.Mediator;
+
+            // Reset the mediator.
+            mediator.Reset();
+
+            Int16 rowDescNumFields = 0;
+            NpgsqlRowDescription rd = null;
+            String Str; // for various strings
+            Byte[] Buff = new Byte[4]; // for various reads
+
+            Byte[] inputBuffer = new Byte[ 500 ];
+
+
+            while (!readyForQuery)
+            {
+                // Check the first Byte of response.
+                switch ( stream.ReadByte() )
+                {
+                case NpgsqlMessageTypes.ErrorResponse :
+
+                    {
+                        NpgsqlError error = new NpgsqlError(context.BackendProtocolVersion);
+                        error.ReadFromStream(stream, context.Encoding);
+
+                        mediator.Errors.Add(error);
+
+                        NpgsqlEventLog.LogMsg(resman, "Log_ErrorResponse", LogLevel.Debug, error.Message);
+                    }
+
+                    // Return imediately if it is in the startup state or connected state as
+                    // there is no more messages to consume.
+                    // Possible error in the NpgsqlStartupState:
+                    //         Invalid password.
+                    // Possible error in the NpgsqlConnectedState:
+                    //         No pg_hba.conf configured.
+
+                    if ((context.CurrentState == NpgsqlStartupState.Instance) ||
+                            (context.CurrentState == NpgsqlConnectedState.Instance))
+                        return;
+
+                    break;
+
+
+                case NpgsqlMessageTypes.AuthenticationRequest :
+
+                    NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "AuthenticationRequest");
+
+                    stream.Read(inputBuffer, 0, 4);
+                    stream.Read(inputBuffer, 0, 4);
+
+                    authType = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(inputBuffer, 0));
+
+                    if ( authType == NpgsqlMessageTypes.AuthenticationOk )
+                    {
+                        NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationOK", LogLevel.Debug);
+
+                        break;
+                    }
+
+                    if ( authType == NpgsqlMessageTypes.AuthenticationClearTextPassword )
+                    {
+                        NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationClearTextRequest", LogLevel.Debug);
+
+                        // Send the PasswordPacket.
+
+                        ChangeState( context, NpgsqlStartupState.Instance );
+                        context.Authenticate(context.ServerPassword);
+
+                        break;
+                    }
+
+
+                    if ( authType == NpgsqlMessageTypes.AuthenticationMD5Password )
+                    {
+                        NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationMD5Request", LogLevel.Debug);
+                        // Now do the "MD5-Thing"
+                        // for this the Password has to be:
+                        // 1. md5-hashed with the username as salt
+                        // 2. md5-hashed again with the salt we get from the backend
+
+
+                        MD5 md5 = MD5.Create();
+
+
+                        // 1.
+                        byte[] passwd = context.Encoding.GetBytes(context.ServerPassword);
+                        byte[] saltUserName = context.Encoding.GetBytes(context.UserName);
+
+                        byte[] crypt_buf = new byte[passwd.Length + saltUserName.Length];
+
+                        passwd.CopyTo(crypt_buf, 0);
+                        saltUserName.CopyTo(crypt_buf, passwd.Length);
+
 
 
+                        StringBuilder sb = new StringBuilder ();
+                        byte[] hashResult = md5.ComputeHash(crypt_buf);
+                        foreach (byte b in hashResult)
+                        sb.Append (b.ToString ("x2"));
+
+
+                        String prehash = sb.ToString();
+
+                        byte[] prehashbytes = context.Encoding.GetBytes(prehash);
 
+
+
+                        byte[] saltServer = Buff;
+                        stream.Read(saltServer, 0, 4);
+                        // Send the PasswordPacket.
+                        ChangeState( context, NpgsqlStartupState.Instance );
+
+
+                        // 2.
+
+                        crypt_buf = new byte[prehashbytes.Length + saltServer.Length];
+                        prehashbytes.CopyTo(crypt_buf, 0);
+                        saltServer.CopyTo(crypt_buf, prehashbytes.Length);
+
+                        sb = new StringBuilder ("md5"); // This is needed as the backend expects md5 result starts with "md5"
+                        hashResult = md5.ComputeHash(crypt_buf);
+                        foreach (byte b in hashResult)
+                        sb.Append (b.ToString ("x2"));
+
+                        context.Authenticate(sb.ToString ());
+
+                        break;
+                    }
+
+                    // Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now.
+                    NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationOK", LogLevel.Debug);
+                    mediator.Errors.Add(String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType));
+                    return;
+
+                case NpgsqlMessageTypes.RowDescription:
+                    // This is the RowDescription message.
+                    NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "RowDescription");
+                    rd = new NpgsqlRowDescription(context.BackendProtocolVersion);
+                    rd.ReadFromStream(stream, context.Encoding);
+
+                    // Initialize the array list which will contain the data from this rowdescription.
+                    //rows = new ArrayList();
+
+                    rowDescNumFields = rd.NumFields;
+                    mediator.AddRowDescription(rd);
+
+
+                    // Now wait for the AsciiRow messages.
+                    break;
+
+                case NpgsqlMessageTypes.AsciiRow:
+
+                    // This is the AsciiRow message.
+                    NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "AsciiRow");
+                    NpgsqlAsciiRow asciiRow = new NpgsqlAsciiRow(rd, context.OidToNameMapping, context.BackendProtocolVersion);
+                    asciiRow.ReadFromStream(stream, context.Encoding);
+
+
+                    // Add this row to the rows array.
+                    //rows.Add(ascii_row);
+                    mediator.AddAsciiRow(asciiRow);
+
+                    // Now wait for CompletedResponse message.
+                    break;
+
+                case NpgsqlMessageTypes.ReadyForQuery :
+
+                    NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "ReadyForQuery");
+
+                    // Possible status bytes returned:
+                    //   I = Idle (no transaction active).
+                    //   T = In transaction, ready for more.
+                    //   E = Error in transaction, queries will fail until transaction aborted.
+                    // Just eat the status byte, we have no use for it at this time.
+                    PGUtil.ReadInt32(stream, Buff);
+                    PGUtil.ReadString(stream, context.Encoding, 1);
+
+                    readyForQuery = true;
+                    ChangeState( context, NpgsqlReadyState.Instance );
+
+                    break;
+
+                case NpgsqlMessageTypes.BackendKeyData :
+
+                    NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "BackendKeyData");
+                    // BackendKeyData message.
+                    NpgsqlBackEndKeyData backend_keydata = new NpgsqlBackEndKeyData(context.BackendProtocolVersion);
+                    backend_keydata.ReadFromStream(stream);
+                    mediator.AddBackendKeydata(backend_keydata);
+
+
+                    // Wait for ReadForQuery message
+                    break;
+
+                case NpgsqlMessageTypes.NoticeResponse :
+
+                    // Notices and errors are identical except that we
+                    // just throw notices away completely ignored.
+                    {
+                        NpgsqlError notice = new NpgsqlError(context.BackendProtocolVersion);
+                        notice.ReadFromStream(stream, context.Encoding);
+
+                        mediator.Notices.Add(notice);
+
+                        NpgsqlEventLog.LogMsg(resman, "Log_NoticeResponse", LogLevel.Debug, notice.Message);
+                    }
+
+                    // Wait for ReadForQuery message
+                    break;
+
+                case NpgsqlMessageTypes.CompletedResponse :
+                    // This is the CompletedResponse message.
+                    // Get the string returned.
+
+                    PGUtil.ReadInt32(stream, Buff);
+                    Str = PGUtil.ReadString(stream, context.Encoding);
+
+                    NpgsqlEventLog.LogMsg(resman, "Log_CompletedResponse", LogLevel.Debug, Str);
+
+                    // Add result from the processing.
+                    mediator.AddCompletedResponse(Str);
+
+                    break;
+
+                case NpgsqlMessageTypes.CursorResponse :
+                    // This is the cursor response message.
+                    // It is followed by a C NULL terminated string with the name of
+                    // the cursor in a FETCH case or 'blank' otherwise.
+                    // In this case it should be always 'blank'.
+                    // [FIXME] Get another name for this function.
+                    NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "CursorResponse");
+
+                    PGUtil.ReadString(stream, context.Encoding);
+                    // Continue waiting for ReadyForQuery message.
+                    break;
+
+                case NpgsqlMessageTypes.ParseComplete :
+                    NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "ParseComplete");
+                    // Just read up the message length.
+                    PGUtil.ReadInt32(stream, Buff);
+                    readyForQuery = true;
+                    break;
+
+                case NpgsqlMessageTypes.BindComplete :
+                    NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "BindComplete");
+                    // Just read up the message length.
+                    PGUtil.ReadInt32(stream, Buff);
+                    readyForQuery = true;
+                    break;
+
+                case NpgsqlMessageTypes.EmptyQueryResponse :
+                    NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "EmptyQueryResponse");
+                    // This is the EmptyQueryResponse.
+                    // [FIXME] Just ignore it this way?
+                    // networkStream.Read(inputBuffer, 0, 1);
+                    //GetStringFromNetStream(networkStream);
+                    PGUtil.ReadInt32(stream, Buff);
+                    break;
+
+                case NpgsqlMessageTypes.NotificationResponse  :
+
+                    NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "NotificationResponse");
+
+                    // Eat the length
+                    PGUtil.ReadInt32(stream, Buff);
+                    {
+                        Int32 PID = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(Buff, 0));
+                        // Notification string
+                        String notificationResponse = PGUtil.ReadString( stream, context.Encoding );
+                        // Additional info, currently not implemented by PG (empty string always), eat it
+                        PGUtil.ReadString( stream, context.Encoding );
+                        mediator.AddNotification(new NpgsqlNotificationEventArgs(PID, notificationResponse));
+                    }
+
+                    // Wait for ReadForQuery message
+                    break;
+
+                case NpgsqlMessageTypes.ParameterStatus :
+                    NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "ParameterStatus");
+                    NpgsqlParameterStatus parameterStatus = new NpgsqlParameterStatus();
+                    parameterStatus.ReadFromStream(stream, context.Encoding);
+
+                    NpgsqlEventLog.LogMsg(resman, "Log_ParameterStatus", LogLevel.Debug, parameterStatus.Parameter, parameterStatus.ParameterValue);
+                    if (parameterStatus.Parameter == "server_version")
+                        context.ServerVersion = parameterStatus.ParameterValue;
+                    break;
+                }
+            }
+        }
+    }
 }
index cb68fbab814f1950a76f4ebf27adc0bea92d50f9..9ae9665eb598504543c0a792af98e3dbba791d5f 100644 (file)
        <data name="Log_ErrorResponse">
                <value>ErrorResponse message from Server: {0}.</value>
        </data>
+       <data name="Log_NoticeResponse">
+               <value>NoticeResponse message from Server: {0}.</value>
+       </data>
     <data name="Log_AuthenticationOk">
         <value>AAuthenticationOK received.</value>
     </data>
index e22e5ba4f5157dda3a64cd9ed84ccea735f65dfc..1a70a54e71067d763853a45f0337da76d0269d39 100755 (executable)
@@ -50,8 +50,7 @@ namespace Npgsql
 
 
         internal NpgsqlTransaction(NpgsqlConnection conn) : this(conn, IsolationLevel.ReadCommitted)
-        {
-        }
+        {}
 
         internal NpgsqlTransaction(NpgsqlConnection conn, IsolationLevel isolation)
         {
index 95fbde2691c27b2c36c13826134ca14c06fcc92a..2c4823a5d30a045208c66f765ce4c0a456f52c61 100755 (executable)
@@ -95,6 +95,33 @@ internal enum FormatCode:
             return string_read;
         }
 
+        ///<summary>
+        /// This method gets a length terminated string from a network stream.
+        /// It returns the resultant string of bytes read.
+        /// This string is sent from backend.
+        /// </summary>
+
+        public static String ReadString(Stream network_stream, Encoding encoding, Int32 length)
+        {
+            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ReadString");
+
+            // [FIXME] Is 512 enough?
+            Byte[] buffer = new Byte[512];
+            Byte b;
+            Int16 counter = 0;
+
+            while(counter < length)
+            {
+                // [FIXME] Is this cast always safe?
+                b = (Byte)network_stream.ReadByte();
+                buffer[counter] = b;
+                counter++;
+            }
+            String string_read = encoding.GetString(buffer, 0, counter);
+            NpgsqlEventLog.LogMsg(resman, "Log_StringRead", LogLevel.Debug, string_read);
+            return string_read;
+        }
+
         ///<summary>
         /// This method writes a C NULL terminated string to the network stream.
         /// It appends a NULL terminator to the end of the String.
index 963b6b3ca2e789887bc2644293c8b5554157dc8d..2aa4d566cea53ca5c8ce45fa6def0d7920775795 100755 (executable)
@@ -722,7 +722,94 @@ namespace NpgsqlTests
                }
                
                
-               
+        [Test]
+               public void MultipleQueriesFirstResultsetEmpty()
+               {
+                       _conn.Open();
+                       
+                       NpgsqlCommand command = new NpgsqlCommand("insert into tablea(field_text) values ('a'); select count(*) from tablea;", _conn);
+            
+            Object result = command.ExecuteScalar();
+                        
+            
+            command.CommandText = "delete from tablea where field_serial > 5";
+            command.ExecuteNonQuery();
+            
+            command.CommandText = "select * from tablea where field_serial = 0";
+            command.ExecuteScalar();
+            
+            
+            Assertion.AssertEquals(6, result);
+            
+            
+               }
+        
+        [Test]
+        [ExpectedException(typeof(NpgsqlException))]
+        public void ConnectionStringWithInvalidParameters()
+        {
+            NpgsqlConnection conn = new NpgsqlConnection("Server=127.0.0.1;User Id=npgsql_tests;Password=j");
+            
+            NpgsqlCommand command = new NpgsqlCommand("select * from tablea", conn);
+            
+            command.Connection.Open();
+            command.ExecuteReader();
+            command.Connection.Close();
+            
+            
+        }
+        
+               [Test]
+        [ExpectedException(typeof(NpgsqlException))]
+        public void InvalidConnectionString()
+        {
+            NpgsqlConnection conn = new NpgsqlConnection("Server=127.0.0.1;User Id=npgsql_tests");
+            
+            NpgsqlCommand command = new NpgsqlCommand("select * from tablea", conn);
+            
+            command.Connection.Open();
+            command.ExecuteReader();
+            command.Connection.Close();
+            
+            
+        }
+        
+        [Test]
+        public void AmbiguousFunctionParameterType()
+        {
+            NpgsqlConnection conn = new NpgsqlConnection("Server=127.0.0.1;User Id=npgsql_tests;Password=npgsql_tests");
+            
+            
+            NpgsqlCommand command = new NpgsqlCommand("ambiguousParameterType(:a, :b, :c, :d, :e, :f)", conn);
+            command.CommandType = CommandType.StoredProcedure;
+            NpgsqlParameter p = new NpgsqlParameter("a", DbType.Int16);
+            p.Value = 2;
+            command.Parameters.Add(p);
+            p = new NpgsqlParameter("b", DbType.Int32);
+            p.Value = 2;
+            command.Parameters.Add(p);
+            p = new NpgsqlParameter("c", DbType.Int64);
+            p.Value = 2;
+            command.Parameters.Add(p);
+            p = new NpgsqlParameter("d", DbType.String);
+            p.Value = "a";
+            command.Parameters.Add(p);
+            p = new NpgsqlParameter("e", DbType.String);
+            p.Value = "a";
+            command.Parameters.Add(p);
+            p = new NpgsqlParameter("f", DbType.String);
+            p.Value = "a";
+            command.Parameters.Add(p);
+            
+            
+            command.Connection.Open();
+            command.Prepare();
+            command.ExecuteScalar();
+            command.Connection.Close();
+            
+            
+        }
+        
                
        }
 }
index 4fc9a4e48669ef798e34ac5641f9717f0dcad31a..4051c9be7ce1992e31176c52eff96906aab12982 100755 (executable)
@@ -452,6 +452,50 @@ namespace NpgsqlTests
                        
                }
                
+        
+        [Test]
+        [ExpectedException(typeof(InvalidOperationException))]
+               public void ReadPastDataReaderEnd()
+               {
+            _conn.Open();
+            NpgsqlCommand command = new NpgsqlCommand("select * from tablea;", _conn);
+                       
+                       NpgsqlDataReader dr = command.ExecuteReader();
+            
+            while (dr.Read());
+            
+            Object o = dr[0];
+            
+        }
+        
+        [Test]
+        public void IsDBNull()
+        {
+            _conn.Open();
+            NpgsqlCommand command = new NpgsqlCommand("select field_text from tablea;", _conn);
+                       
+                       NpgsqlDataReader dr = command.ExecuteReader();
+            
+            dr.Read();
+            Assertion.AssertEquals(false, dr.IsDBNull(0));
+            dr.Read();
+            Assertion.AssertEquals(true, dr.IsDBNull(0));
+            
+                
+        }
+        
+        [Test]
+        public void IsDBNullFromScalar()
+        {
+            _conn.Open();
+            NpgsqlCommand command = new NpgsqlCommand("select max(field_serial) from tablea;", _conn);
+                       
+                       NpgsqlDataReader dr = command.ExecuteReader();
+            
+            dr.Read();
+            Assertion.AssertEquals(false, dr.IsDBNull(0));
+            
+        }