2006-04-27 Francisco Figueiredo Jr. <fxjrlists@yahoo.com.br>
authorFrancisco Figueiredo Jr. <fxjr@mono-cvs.ximian.com>
Thu, 27 Apr 2006 14:11:18 +0000 (14:11 -0000)
committerFrancisco Figueiredo Jr. <fxjr@mono-cvs.ximian.com>
Thu, 27 Apr 2006 14:11:18 +0000 (14:11 -0000)
    * Npgsql_test.dll.sources,
      Npgsql.dll.sources,
      Npgsql/NpgsqlError.cs,
      Npgsql/NpgsqlCommandBuilder.resx,
      Npgsql/NpgsqlConnectedState.cs,
      Npgsql/NpgsqlBind.cs,
      Npgsql/NpgsqlTransaction.cs,
      Npgsql/NpgsqlConnectionString.cs,
      Npgsql/NpgsqlConnection.cs,
      Npgsql/NpgsqlClosedState.cs,
      Npgsql/NpgsqlState.cs,
      Npgsql/NpgsqlAsciiRow.cs,
      Npgsql/NpgsqlConnector.cs,
      Npgsql/NpgsqlParameterCollection.cs,
      Npgsql/NpgsqlCancelRequest.cs,
      Npgsql/NpgsqlCommandBuilder.cs,
      Npgsql/NpgsqlException.cs,
      Npgsql/NpgsqlMediator.cs,
      Npgsql/NpgsqlReadyState.cs,
      Npgsql/PGUtil.cs,
      ChangeLog,
      Npgsql.dll.resources,
      NpgsqlTypes/NpgsqlDbType.cs,
      NpgsqlTypes/NpgsqlTypeConverters.cs,
      NpgsqlTypes/NpgsqlTypes.cs,
      NpgsqlTypes/NpgsqlTypesHelper.cs,
      Makefile: Updated to RC1 version.

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

26 files changed:
mcs/class/Npgsql/ChangeLog
mcs/class/Npgsql/Makefile
mcs/class/Npgsql/Npgsql.dll.resources
mcs/class/Npgsql/Npgsql.dll.sources
mcs/class/Npgsql/Npgsql/NpgsqlAsciiRow.cs
mcs/class/Npgsql/Npgsql/NpgsqlBind.cs
mcs/class/Npgsql/Npgsql/NpgsqlCancelRequest.cs [new file with mode: 0644]
mcs/class/Npgsql/Npgsql/NpgsqlClosedState.cs
mcs/class/Npgsql/Npgsql/NpgsqlCommandBuilder.cs
mcs/class/Npgsql/Npgsql/NpgsqlCommandBuilder.resx
mcs/class/Npgsql/Npgsql/NpgsqlConnectedState.cs
mcs/class/Npgsql/Npgsql/NpgsqlConnection.cs
mcs/class/Npgsql/Npgsql/NpgsqlConnectionString.cs
mcs/class/Npgsql/Npgsql/NpgsqlConnector.cs
mcs/class/Npgsql/Npgsql/NpgsqlError.cs
mcs/class/Npgsql/Npgsql/NpgsqlException.cs
mcs/class/Npgsql/Npgsql/NpgsqlMediator.cs
mcs/class/Npgsql/Npgsql/NpgsqlParameterCollection.cs
mcs/class/Npgsql/Npgsql/NpgsqlReadyState.cs
mcs/class/Npgsql/Npgsql/NpgsqlState.cs
mcs/class/Npgsql/Npgsql/NpgsqlTransaction.cs
mcs/class/Npgsql/Npgsql/PGUtil.cs
mcs/class/Npgsql/NpgsqlTypes/NpgsqlDbType.cs
mcs/class/Npgsql/NpgsqlTypes/NpgsqlTypeConverters.cs
mcs/class/Npgsql/NpgsqlTypes/NpgsqlTypes.cs
mcs/class/Npgsql/NpgsqlTypes/NpgsqlTypesHelper.cs

index 61f6e8c25172789f37062fefa80db7085fb41b9f..ecc472548e668d35ec45ea9ccea446d315c3555c 100644 (file)
@@ -1,11 +1,75 @@
 
+2006-04-27  Francisco Figueiredo Jr.  <fxjrlists@yahoo.com.br>
+
+    * Npgsql_test.dll.sources,
+      Npgsql.dll.sources,
+      Npgsql/NpgsqlError.cs,
+      Npgsql/NpgsqlCommandBuilder.resx,
+      Npgsql/NpgsqlConnectedState.cs,
+      Npgsql/NpgsqlBind.cs,
+      Npgsql/NpgsqlTransaction.cs,
+      Npgsql/NpgsqlConnectionString.cs,
+      Npgsql/NpgsqlConnection.cs,
+      Npgsql/NpgsqlClosedState.cs,
+      Npgsql/NpgsqlState.cs,
+      Npgsql/NpgsqlAsciiRow.cs,
+      Npgsql/NpgsqlConnector.cs,
+      Npgsql/NpgsqlParameterCollection.cs,
+      Npgsql/NpgsqlCancelRequest.cs,
+      Npgsql/NpgsqlCommandBuilder.cs,
+      Npgsql/NpgsqlException.cs,
+      Npgsql/NpgsqlMediator.cs,
+      Npgsql/NpgsqlReadyState.cs,
+      Npgsql/PGUtil.cs,
+      ChangeLog,
+      Npgsql.dll.resources,
+      NpgsqlTypes/NpgsqlDbType.cs,
+      NpgsqlTypes/NpgsqlTypeConverters.cs,
+      NpgsqlTypes/NpgsqlTypes.cs,
+      NpgsqlTypes/NpgsqlTypesHelper.cs,
+      Makefile: Updated to RC1 version.
+
+
 Thu Feb 23 10:29:13 CET 2006 Paolo Molaro <lupus@ximian.com>
 
-       * Npgsql/NpgsqlCommand.cs: return count for fetch and move, too,
-       patch from Federico Di Gregorio <fog@initd.org>.
+    * Npgsql/NpgsqlCommand.cs: return count for fetch and move, too,
+    patch from Federico Di Gregorio <fog@initd.org>.
+
+
+2006-01-05  Francisco Figueiredo Jr.  <fxjrlists@yahoo.com.br>
+
+    * PGUtil.cs: [#1000517] ServerVersion operator overload. Fixed. Thanks Otto for heads up.
+
+
+2006-01-01  Francisco Figueiredo Jr.  <fxjrlists@yahoo.com.br>
+       
+    * NpgsqlCommand.cs: [#1000497] Dot in parameter name causes exception. Added performance patch for GetClearCommandText() thanks Bryan Mayland.
+    * NpgsqlParameterCollection.cs: Added performance patch for GetClearCommandText() thanks Bryan Mayland.
+    * [#1000454] Getting identifier of an inserted row. Added property LastInsertedOID to NpgsqlCommand. This property only works when using a single insert command and the table was created with oids else it returns 0.
+
+2005-12-29  Francisco Figueiredo Jr.  <fxjrlists@yahoo.com.br>
+
+    * NpgsqlCommand.cs: [#1000500] Fixed problem when parsing parameter names with NpgsqlCommand.Prepare(), [#1000497] Fixed problem with dot in parameter names.
+
+2005-12-25  Francisco Figueiredo Jr.  <fxjrlists@yahoo.com.br>
+
+    * NpgsqlTransaction.cs: [#1000491] Fixed transaction isolation level setting. Thanks Ottó Havasvölgyi for heads up.
+    * NpgsqlTransaction.cs.resx: Removed unused key.
+
+2005-12-14  Francisco Figueiredo Jr.  <fxjrlists@yahoo.com.br>
+
+    * NpgsqlAsciiRow.cs,
+      NpgsqlBind.cs,
+      NpgsqlCommand.cs,
+      NpgsqlConnector.cs,
+      NpgsqlReadyState.cs,
+      NpgsqlState.cs,
+      NpgsqlTypesHelper.cs: [#1000458] Enormous memory increase (and application crash) with large BYTEA parameter. Added binary support.  Thanks Hubert FONGARNAND for patch. Improved network performance by removing some Stream.Flush() calls.
+
 
 2005-12-13  Francisco Figueiredo Jr.  <fxjrlists@yahoo.com.br>
 
+
        * NpgsqlClosedState.cs:  Added a performance improvement fix. Npgsql now use a buffered stream for all server interactions.
 
 2005-12-12  Francisco Figueiredo Jr.  <fxjrlists@yahoo.com.br>
index 9a4d68dd120fb09974f5ffb25f6d2525d0646aea..1dafe2da7d1be154f21cf4f9d7c2ee3ed237d317 100755 (executable)
@@ -44,6 +44,7 @@ RESX_RES = \
        Npgsql/NpgsqlClosedState.resources                      \
        Npgsql/NpgsqlParameterCollection.resources              \
        Npgsql/NpgsqlCommand.resources                          \
+       Npgsql/NpgsqlCommandBuilder.resources                   \
        Npgsql/NpgsqlConnectedState.resources                   \
        Npgsql/NpgsqlParameter.resources                        \
        Npgsql/NpgsqlConnection.resources                       \
@@ -52,7 +53,7 @@ RESX_RES = \
        Npgsql/NpgsqlEventLog.resources                         \
        Npgsql/NpgsqlException.resources                        \
        Npgsql/PGUtil.resources                                 \
-       Npgsql/NpgsqlConnectionString.resources                                 \
+       Npgsql/NpgsqlConnectionString.resources                 \
        NpgsqlTypes/NpgsqlTypesHelper.resources                 
 
 include ../../build/library.make
index 95a224c5da7b782ae65a4c39c1e883ade878926f..d8eb490aedcfbb8bf766b227df36b6bc458c663f 100644 (file)
@@ -3,6 +3,7 @@
 -resource:Npgsql/NpgsqlParameterCollection.resources,Npgsql.NpgsqlParameterCollection.resources
 -resource:Npgsql/NpgsqlParameter.resources,Npgsql.NpgsqlParameter.resources
 -resource:Npgsql/NpgsqlCommand.resources,Npgsql.NpgsqlCommand.resources
+-resource:Npgsql/NpgsqlCommandBuilder.resources,Npgsql.NpgsqlCommandBuilder.resources
 -resource:Npgsql/NpgsqlConnectedState.resources,Npgsql.NpgsqlConnectedState.resources
 -resource:Npgsql/NpgsqlConnection.resources,Npgsql.NpgsqlConnection.resources
 -resource:Npgsql/NpgsqlReadyState.resources,Npgsql.NpgsqlReadyState.resources
index 0a045b7a17dc1f506033a530130410cb4de97c8d..f06885583461e82198feba00d96016600fd62040 100755 (executable)
@@ -7,6 +7,7 @@ Npgsql/NpgsqlAsciiRow.cs
 Npgsql/NpgsqlBackEndKeyData.cs
 Npgsql/NpgsqlBinaryRow.cs
 Npgsql/NpgsqlBind.cs
+Npgsql/NpgsqlCancelRequest.cs
 Npgsql/NpgsqlClosedState.cs
 Npgsql/NpgsqlCommand.cs
 Npgsql/NpgsqlCommandBuilder.cs
index d5ccfc8bb4cabd7d14d0d72d3f376895e9ccbfa4..995e48815508a1a661451b59c1acb620e0e51b5e 100644 (file)
@@ -132,7 +132,7 @@ namespace Npgsql
                                }
 
                                NpgsqlRowDescriptionFieldData field_descr = row_desc[field_count];
-
+    
                                if (row_desc[field_count].format_code == FormatCode.Text)
                                {
                                        string result = ReadStringFromStream(inputStream, field_value_size, decoder);
@@ -141,9 +141,9 @@ namespace Npgsql
                                }
                                else
                                {
-                                       PGUtil.CheckedStreamRead(inputStream, _inputBuffer, 0, Math.Min(field_value_size, _inputBuffer.Length));
-                                       // FIXME: _inputBuffer isn't holding all the field value. This code isn't handling binary data correctly.
-                                       data.Add(NpgsqlTypesHelper.ConvertBackendBytesToSystemType(field_descr.type_info, _inputBuffer, encoding, field_value_size, field_descr.type_modifier));
+                    Byte[] binary_data = ReadBytesFromStream(inputStream, field_value_size);
+
+                    data.Add(NpgsqlTypesHelper.ConvertBackendBytesToSystemType(field_descr.type_info, binary_data, encoding,field_value_size, field_descr.type_modifier));
                                }
             }
         }
@@ -199,5 +199,26 @@ namespace Npgsql
                                return new String(_chars, 0,charCount);
                        }
                }
+  
+        private byte[] ReadBytesFromStream(Stream inputStream, int field_value_size)
+        {
+            byte[] binary_data = new byte[field_value_size];
+            int bytes_left = field_value_size;
+            if (field_value_size > _inputBuffer.Length)
+            {
+                int i=0;
+                while (bytes_left > READ_BUFFER_SIZE)
+                {
+                    PGUtil.CheckedStreamRead(inputStream, _inputBuffer, 0, READ_BUFFER_SIZE);
+                    _inputBuffer.CopyTo(binary_data, i*READ_BUFFER_SIZE);
+                    i++;
+                    bytes_left -= READ_BUFFER_SIZE;
+                }
+            }
+            PGUtil.CheckedStreamRead(inputStream, _inputBuffer, 0, bytes_left);
+            Int32 offset = field_value_size - bytes_left;
+            Array.Copy(_inputBuffer, 0, binary_data, offset, bytes_left);
+            return binary_data;
+        }
     }
 }
index d1f8d48d9402ba2226952e9915dc9c0fa920c42b..91056afc587c815442eacc67d4baf8145846061b 100644 (file)
@@ -48,7 +48,8 @@ namespace Npgsql
         private Int16[] _parameterFormatCodes;
         private Object[] _parameterValues;
         private Int16[] _resultFormatCodes;
-
+        
+        
 
         public NpgsqlBind(String portalName,
                           String preparedStatementName,
@@ -63,6 +64,8 @@ namespace Npgsql
             _parameterValues = parameterValues;
             _resultFormatCodes = resultFormatCodes;
 
+            
+
 
         }
 
@@ -73,6 +76,27 @@ namespace Npgsql
                 return _portalName;
             }
         }
+        
+        public String PreparedStatementName
+        {
+            get
+            {
+                return _preparedStatementName;
+            }
+        }
+
+        public Int16[] ResultFormatCodes
+        {
+            get
+            {
+                return _resultFormatCodes;
+            }
+            set
+            {
+                _resultFormatCodes = value;
+                
+            }
+        }
 
         public Int16[] ParameterFormatCodes
         {
@@ -84,6 +108,7 @@ namespace Npgsql
             set
             {
                 _parameterFormatCodes = value;
+                
             }
         }
 
@@ -107,11 +132,11 @@ namespace Npgsql
 
 
             Int32 messageLength = 4 +
-                                  encoding.GetByteCount(_portalName) + 1 +
-                                  encoding.GetByteCount(_preparedStatementName) + 1 +
-                                  2 +
-                                  (_parameterFormatCodes.Length * 2) +
-                                  2;
+                    encoding.GetByteCount(_portalName) + 1 +
+                    encoding.GetByteCount(_preparedStatementName) + 1 +
+                    2 +
+                    (_parameterFormatCodes.Length * 2) +
+                    2;
 
 
             // Get size of parameter values.
@@ -169,9 +194,9 @@ namespace Npgsql
                             PGUtil.WriteInt32(outputStream, -1);
                         else
                         {
-                            String parameterValue = (String)_parameterValues[i];
-                            PGUtil.WriteInt32(outputStream, encoding.GetByteCount(parameterValue));
-                            outputStream.Write(encoding.GetBytes(parameterValue), 0, encoding.GetByteCount(parameterValue));
+                            Byte[] parameterValueBytes = encoding.GetBytes((String)_parameterValues[i]);
+                            PGUtil.WriteInt32(outputStream, parameterValueBytes.Length);
+                            outputStream.Write(parameterValueBytes, 0, parameterValueBytes.Length);
                         }
                     }
 
diff --git a/mcs/class/Npgsql/Npgsql/NpgsqlCancelRequest.cs b/mcs/class/Npgsql/Npgsql/NpgsqlCancelRequest.cs
new file mode 100644 (file)
index 0000000..9b0c02a
--- /dev/null
@@ -0,0 +1,65 @@
+// Npgsql.NpgsqlCancelRequest.cs
+//
+// Author:
+//  Francisco Jr. (fxjrlists@yahoo.com.br)
+//
+//  Copyright (C) 2002-2006 The Npgsql Development Team
+//  http://pgfoundry.org/projects/npgsql
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+using System;
+using System.IO;
+using System.Text;
+
+namespace Npgsql
+{
+
+    /// <summary>
+    /// This class represents the CancelRequest message sent to PostgreSQL
+    /// server.
+    /// </summary>
+    ///
+    internal sealed class NpgsqlCancelRequest
+    {
+        // Logging related values
+        private static readonly String CLASSNAME = "NpgsqlCancelRequest";
+
+
+        private static Int32 CancelRequestMessageSize = 16;
+        private static Int32 CancelRequestCode = 1234 << 16 | 5678;
+
+        private NpgsqlBackEndKeyData BackendKeydata;
+        
+        
+        public NpgsqlCancelRequest(NpgsqlBackEndKeyData BackendKeydata)
+        {
+            this.BackendKeydata = BackendKeydata;
+            
+        }
+
+        public void WriteToStream(Stream outputStream, Encoding encoding)
+        {
+            PGUtil.WriteInt32(outputStream, CancelRequestMessageSize);
+            PGUtil.WriteInt32(outputStream, CancelRequestCode);
+            PGUtil.WriteInt32(outputStream, BackendKeydata.ProcessID);
+            PGUtil.WriteInt32(outputStream, BackendKeydata.SecretKey);
+            
+            outputStream.Flush();
+
+        }
+
+    }
+}
\ No newline at end of file
index c8f1d6af6bb7fb4f5c613a18092cc1db56d28000..4bb4d6d3203fd4a1b44e678bb59ebac0040a6cc9 100644 (file)
@@ -79,9 +79,16 @@ namespace Npgsql
             {
                 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Open");
     
-                TcpClient tcpc = new TcpClient();
+                /*TcpClient tcpc = new TcpClient();
                 tcpc.Connect(new IPEndPoint(ResolveIPHost(context.Host), context.Port));
-                Stream stream = tcpc.GetStream();
+                Stream stream = tcpc.GetStream();*/
+                
+                Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
+
+                socket.Connect(new IPEndPoint(ResolveIPHost(context.Host), context.Port));
+
+                Stream stream = new NetworkStream(socket, true);
+
     
                                
                 // If the PostgreSQL server has SSL connectors enabled Open SslClientStream if (response == 'S') {
@@ -95,7 +102,7 @@ namespace Npgsql
                     if (response == 'S')
                     {
                         stream = new SslClientStream(
-                                    tcpc.GetStream(),
+                                    stream,
                                     context.Host,
                                     true,
                                     Mono.Security.Protocol.Tls.SecurityProtocolType.Default
@@ -111,6 +118,7 @@ namespace Npgsql
                 }
     
                 context.Stream = new BufferedStream(stream);
+                context.Socket = socket;
                 
     
                 NpgsqlEventLog.LogMsg(resman, "Log_ConnectedTo", LogLevel.Normal, context.Host, context.Port);
@@ -120,7 +128,7 @@ namespace Npgsql
             }
             catch (Exception e)
             {
-                throw new NpgsqlException(e.ToString(), e);
+                throw new NpgsqlException(e.Message, e);
             }
         }
 
index 1d1d67441cdf74353e5734d30d78ccb9b222b39e..e0eeb947b0a703e789fedab11bb196598338a44b 100644 (file)
@@ -1,9 +1,9 @@
 // NpgsqlCommandBuilder.cs
 //
 // Author:
-//   Pedro Martínez Juliá (yoros@wanadoo.es)
+//   Pedro Martínez Juliá (yoros@wanadoo.es)
 //
-// Copyright (C) 2003 Pedro Martínez Juliá
+// Copyright (C) 2003 Pedro Martínez Juliá
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -26,6 +26,7 @@
 
 
 using System;
+using System.Resources;
 using System.Data;
 using System.Data.Common;
 using System.ComponentModel;
@@ -40,6 +41,10 @@ namespace Npgsql
     public sealed class NpgsqlCommandBuilder : Component
     {
 
+        // Logging related values
+        private static readonly String CLASSNAME = "NpgsqlCommandBuilder";
+        private static ResourceManager resman = new ResourceManager(typeof(NpgsqlCommandBuilder));
+        
         bool disposed = false;
 
 
@@ -48,10 +53,9 @@ namespace Npgsql
         private NpgsqlCommand update_command;
         private NpgsqlCommand delete_command;
 
-        private string table_name = String.Empty;
-
         private string quotePrefix = "\"";
         private string quoteSuffix = "\"";
+               private DataTable select_schema;
 
         public NpgsqlCommandBuilder ()
         {}
@@ -74,37 +78,21 @@ namespace Npgsql
                     throw new InvalidOperationException ("DataAdapter is already set");
                 }
                 data_adapter = value;
-                string select_text = data_adapter.SelectCommand.CommandText;
-                string[] words = select_text.Split(new char [] {' '});
-                bool from_found = false;
-                for (int i = 0; i < words.Length; i++)
-                {
-                    if (from_found && (words[i] != String.Empty))
-                    {
-                        table_name = words[i];
-                        break;
-                    }
-                    if (words[i].ToLower() == "from")
-                    {
-                        from_found = true;
-                    }
-                }
             }
         }
 
-        private void OnRowUpdating(Object sender, NpgsqlRowUpdatingEventArgs value)
-        {
+        private void OnRowUpdating(Object sender, NpgsqlRowUpdatingEventArgs value) {
             switch (value.StatementType)
             {
-            case StatementType.Insert:
-                value.Command = GetInsertCommand(value.Row);
-                break;
-            case StatementType.Update:
-                value.Command = GetUpdateCommand(value.Row);
-                break;
-            case StatementType.Delete:
-                value.Command = GetDeleteCommand(value.Row);
-                break;  
+                case StatementType.Insert:
+                    value.Command = GetInsertCommand(value.Row);
+                    break;
+                case StatementType.Update:
+                    value.Command = GetUpdateCommand(value.Row);
+                    break;
+                case StatementType.Delete:
+                    value.Command = GetDeleteCommand(value.Row);
+                    break;
             }
 
             DataColumnMappingCollection columnMappings = value.TableMapping.ColumnMappings;
@@ -131,7 +119,6 @@ namespace Npgsql
             value.Row.AcceptChanges ();
         }
 
-
         public string QuotePrefix {
             get
             {
@@ -139,11 +126,10 @@ namespace Npgsql
             }
             set
             {
-                quotePrefix = value;
-            }
+                               quotePrefix = value;
+                       }
         }
 
-
         public string QuoteSuffix {
             get
             {
@@ -151,32 +137,34 @@ namespace Npgsql
             }
             set
             {
-                quoteSuffix = value;
-            }
+                               quoteSuffix = value;
+                       }
         }
 
-        ///<summary>
-        ///
-        /// This method is reponsible to derive the command parameter list with values obtained from function definition.
-        /// It clears the Parameters collection of command. Also, if there is any parameter type which is not supported by Npgsql, an InvalidOperationException will be thrown.
-        /// Parameters name will be parameter1, parameter2, ...
-        /// For while, only parameter name and NpgsqlDbType are obtained.
-        ///</summary>
-        /// <param name="command">NpgsqlCommand whose function parameters will be obtained.</param>
-
+       ///<summary>
+       ///
+       /// This method is reponsible to derive the command parameter list with values obtained from function definition. 
+       /// It clears the Parameters collection of command. Also, if there is any parameter type which is not supported by Npgsql, an InvalidOperationException will be thrown.
+       /// Parameters name will be parameter1, parameter2, ...
+       /// For while, only parameter name and NpgsqlDbType are obtained.
+       ///</summary>
+       /// <param name="command">NpgsqlCommand whose function parameters will be obtained.</param>
         public static void DeriveParameters (NpgsqlCommand command)
         {
             String query = "select proargtypes from pg_proc where proname = :procname";
-
+    
             NpgsqlCommand c = new NpgsqlCommand(query, command.Connection);
             c.Parameters.Add(new NpgsqlParameter("procname", NpgsqlDbType.Text));
             c.Parameters[0].Value = command.CommandText;
-
+    
             String types = (String) c.ExecuteScalar();
-
+            
+            if (types == null)
+                throw new InvalidOperationException (String.Format(resman.GetString("Exception_InvalidFunctionName"), command.CommandText));
+    
             command.Parameters.Clear();
             Int32 i = 1;
-
+            
             foreach(String s in types.Split())
             {
                 if (!c.Connector.OidToNameMapping.ContainsOID(Int32.Parse(s)))
@@ -186,9 +174,9 @@ namespace Npgsql
                 }
                 command.Parameters.Add(new NpgsqlParameter("parameter" + i++, c.Connector.OidToNameMapping[Int32.Parse(s)].NpgsqlDbType));
             }
-
+               
         }
-
         private string GetQuotedName(string str)
         {
             string result = str;
@@ -203,27 +191,41 @@ namespace Npgsql
             return result;
         }
 
+
         public NpgsqlCommand GetInsertCommand (DataRow row)
         {
             if (insert_command == null)
             {
                 string fields = "";
                 string values = "";
-                for (int i = 0; i < row.Table.Columns.Count; i++)
-                {
-                    DataColumn column = row.Table.Columns[i];
-                    if (i != 0)
-                    {
-                        fields += ", ";
-                        values += ", ";
-                    }
-                    fields += GetQuotedName(column.ColumnName);
-                    values += ":param_" + column.ColumnName;
-                }
-                if (table_name == String.Empty)
-                {
-                    table_name = row.Table.TableName;
-                }
+                               bool first = true;
+                               if (select_schema == null)
+                               {
+                                       BuildSchema();
+                               }
+                               string table_name = string.Empty;
+                               foreach(DataRow schemaRow in select_schema.Rows)
+                               {
+                                       if (!(bool)schemaRow["IsAutoIncrement"])
+                                       {
+                                               if (!first)
+                                               {
+                                                       fields += ", ";
+                                                       values += ", ";
+                                               }
+                                               else
+                                               {
+                                                       table_name = (string)schemaRow["BaseTableName"];
+                                                       if (table_name == null || table_name.Length == 0)
+                                                       {
+                                                               table_name = row.Table.TableName;
+                                                       }
+                                               }
+                                               fields += GetQuotedName((string)schemaRow["BaseColumnName"]);
+                                               values += ":param_" + schemaRow["ColumnName"];
+                                               first = false;
+                                       }
+                               }
                 NpgsqlCommand cmdaux = new NpgsqlCommand("insert into " + GetQuotedName(table_name) + " (" + fields + ") values (" + values + ")", data_adapter.SelectCommand.Connection);
                 foreach (DataColumn column in row.Table.Columns)
                 {
@@ -242,22 +244,32 @@ namespace Npgsql
             if (update_command == null)
             {
                 string sets = "";
-                string wheres = "";
-                for (int i = 0; i < row.Table.Columns.Count; i++)
-                {
-                    if (i != 0)
-                    {
-                        sets += ", ";
-                        wheres += " and ";
-                    }
-                    DataColumn column = row.Table.Columns[i];
-                    sets += String.Format(GetQuotedName("{0}") + " = :s_param_{0}", column.ColumnName);
-                    wheres += String.Format("((" + GetQuotedName("{0}") + " is null) or (" + GetQuotedName("{0}") + " = :w_param_{0}))", column.ColumnName);
-                }
-                if (table_name == String.Empty)
-                {
-                    table_name = row.Table.TableName;
-                }
+                               string wheres = "";
+                               bool first = true;
+                               if (select_schema == null)
+                               {
+                                       BuildSchema();
+                               }
+                               string table_name = string.Empty;
+                               foreach(DataRow schemaRow in select_schema.Rows)
+                               {
+                                       if (!first)
+                                       {
+                                               sets += ", ";
+                                               wheres += " and ";
+                                       }
+                                       else
+                                       {
+                                               table_name = (string)schemaRow["BaseTableName"];
+                                               if (table_name == null || table_name.Length == 0)
+                                               {
+                                                       table_name = row.Table.TableName;
+                                               }
+                                       }
+                                       sets += String.Format("{0} = :s_param_{1}", GetQuotedName((string)schemaRow["BaseColumnName"]), schemaRow["ColumnName"]);
+                                       wheres += String.Format("(({0} is null) or ({0} = :w_param_{1}))", GetQuotedName((string)schemaRow["BaseColumnName"]), schemaRow["ColumnName"]);
+                                       first = false;
+                               }
                 NpgsqlCommand cmdaux = new NpgsqlCommand("update " + GetQuotedName(table_name) + " set " + sets + " where ( " + wheres + " )", data_adapter.SelectCommand.Connection);
                 foreach (DataColumn column in row.Table.Columns)
                 {
@@ -285,20 +297,30 @@ namespace Npgsql
         {
             if (delete_command == null)
             {
-                string wheres = "";
-                for (int i = 0; i < row.Table.Columns.Count; i++)
-                {
-                    DataColumn column = row.Table.Columns[i];
-                    if (i != 0)
-                    {
-                        wheres += " and ";
-                    }
-                    wheres += String.Format("((" + GetQuotedName("{0}") + " is null) or (" + GetQuotedName("{0}") + " = :param_{0}))", column.ColumnName);
-                }
-                if (table_name == String.Empty)
-                {
-                    table_name = row.Table.TableName;
-                }
+                               string wheres = "";
+                               bool first = true;
+                               if (select_schema == null)
+                               {
+                                       BuildSchema();
+                               }
+                               string table_name = string.Empty;
+                               foreach(DataRow schemaRow in select_schema.Rows)
+                               {
+                                       if (!first)
+                                       {
+                                               wheres += " and ";
+                                       }
+                                       else
+                                       {
+                                               table_name = (string)schemaRow["BaseTableName"];
+                                               if (table_name == null || table_name.Length == 0)
+                                               {
+                                                       table_name = row.Table.TableName;
+                                               }
+                                       }
+                                       wheres += String.Format("(({0} is null) or ({0} = :param_{1}))", GetQuotedName((string)schemaRow["BaseColumnName"]), schemaRow["ColumnName"]);
+                                       first = false;
+                               }
                 NpgsqlCommand cmdaux = new NpgsqlCommand("delete from " + GetQuotedName(table_name) + " where ( " + wheres + " )", data_adapter.SelectCommand.Connection);
                 foreach (DataColumn column in row.Table.Columns)
                 {
@@ -318,6 +340,7 @@ namespace Npgsql
             insert_command = null;
             update_command = null;
             delete_command = null;
+                       select_schema = null;
         }
 
         protected override void Dispose (bool disposing)
@@ -342,6 +365,33 @@ namespace Npgsql
             }
         }
 
+               private void BuildSchema()
+               {
+                       if (select_schema == null)
+                       {
+                               bool openedConnection = false;
+                               try
+                               {
+                                       if ((data_adapter.SelectCommand.Connection.State & ConnectionState.Open) != ConnectionState.Open)
+                                       {
+                                               data_adapter.SelectCommand.Connection.Open();
+                                               openedConnection = true;
+                                       }
+                                       using (NpgsqlDataReader reader = data_adapter.SelectCommand.ExecuteReader(CommandBehavior.SchemaOnly|CommandBehavior.KeyInfo))
+                                       {
+                                               select_schema = reader.GetSchemaTable();
+                                       }
+                               }
+                               finally
+                               {
+                                       if (openedConnection)
+                                       {
+                                               data_adapter.SelectCommand.Connection.Close();
+                                       }
+                               }
+                       }
+               }
+
         /*~NpgsqlCommandBuilder ()
         {
             Dispose(false);
index 7b0a5399c03d6c693bd5ef8703ada5445beb0ef3..4923fe7b2a22be90d8910d42213044b43d0a2d7f 100644 (file)
@@ -97,4 +97,7 @@
        <resheader name="writer">
                <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
        </resheader>
+       <data name="Exception_InvalidFunctionName">
+               <value>{0} does not exist in pg_proc</value>
+       </data>
 </root>
index 74ef6b41224910df7a28b3ffb64b5d1936241219..a32d89430fb14b1b31b93e1bef95fd712a88a8e7 100644 (file)
@@ -60,8 +60,20 @@ namespace Npgsql
 
             startupPacket.WriteToStream( new BufferedStream(context.Stream), context.Encoding );
             context.Mediator.RequireReadyForQuery = false;
+            context.Mediator.CommandTimeout = 20;
+            context.Stream.Flush();
             ProcessBackendResponses( context );
         }
+        
+        public override void CancelRequest(NpgsqlConnector context)
+        {
+            NpgsqlCancelRequest CancelRequestMessage = new NpgsqlCancelRequest(context.BackEndKeyData);
+            
+            
+            CancelRequestMessage.WriteToStream(context.Stream, context.Encoding);
+            
+                
+        }
 
     }
 }
index 15d74f5424045bedda2c7d68aad18e6f68d263ec..d545183d4bfb6935a05df9a428f81c446c555029 100644 (file)
@@ -140,19 +140,67 @@ namespace Npgsql
         /// <summary>
         /// Gets or sets the string used to connect to a PostgreSQL database.
         /// Valid values are:
+        /// <ul>
+        /// <li>
         /// Server:             Address/Name of Postgresql Server;
+        /// </li>
+        /// <li>
         /// Port:               Port to connect to;
+        /// </li>
+        /// <li>
         /// Protocol:           Protocol version to use, instead of automatic; Integer 2 or 3;
+        /// </li>
+        /// <li>
         /// Database:           Database name. Defaults to user name if not specified;
+        /// </li>
+        /// <li>
+        
         /// User Id:            User name;
+        /// </li>
+        /// <li>
+        
         /// Password:           Password for clear text authentication;
+        /// </li>
+        /// <li>
+        
         /// SSL:                True or False. Controls whether to attempt a secure connection. Default = False;
+        /// </li>
+        /// <li>
+        
         /// Pooling:            True or False. Controls whether connection pooling is used. Default = True;
+        /// </li>
+        /// <li>
+        
         /// MinPoolSize:        Min size of connection pool;
+        /// </li>
+        /// <li>
+        
         /// MaxPoolSize:        Max size of connection pool;
-        /// Encoding:           Encoding to be used;
-        /// Timeout:            Time to wait for connection open in seconds.
-        /// ConnectionLifeTime: Time to wait before closing unused connections in the pool.
+        /// </li>
+        /// <li>
+        
+        /// Encoding:           Encoding to be used; Can be ASCII or UNICODE. Default is ASCII. Use UNICODE if you are having problems with accents.
+        /// </li>
+        /// <li>
+        
+        /// Timeout:            Time to wait for connection open in seconds. Default is 15.
+        /// </li>
+        /// <li>
+        
+        /// Sslmode:            Mode for ssl connection control. Can be Prefer, Require, Allow or Disable. Default is Disable. Check user manual for explanation of values.
+        /// </li>
+        
+        /// <li>
+        
+        /// ConnectionLifeTime: Time to wait before closing unused connections in the pool in seconds. Default is 15.
+        /// </li>
+        /// <li>
+        
+        /// SyncNotification:   Specifies if Npgsql should use synchronous notifications.
+        /// </li>
+        /// </ul>
+        
+        
         /// </summary>
         /// <value>The connection string that includes the server name,
         /// the database name, and other parameters needed to establish
@@ -264,6 +312,18 @@ namespace Npgsql
                 return connection_string.ToString(ConnectionStringKeys.Database);
             }
         }
+        
+        /// <summary>
+        /// Gets flag indicating if we are using Synchronous notification or not.
+        /// The default value is false.
+        /// </summary>
+        public Boolean SyncNotification
+        {
+            get
+            {
+                return connection_string.ToBool(ConnectionStringKeys.SyncNotification, ConnectionStringDefaults.SyncNotification);
+            }
+        }
 
         /// <summary>
         /// Gets the current state of the connection.
@@ -400,9 +460,13 @@ namespace Npgsql
 
             // Get a Connector.  The connector returned is guaranteed to be connected and ready to go.
             connector = NpgsqlConnectorPool.ConnectorPoolMgr.RequestConnector (this);
-
+            
             connector.Notice += NoticeDelegate;
             connector.Notification += NotificationDelegate;
+            
+            if (SyncNotification)
+                connector.AddNotificationThread();
+            
         }
 
         /// <summary>
@@ -446,8 +510,14 @@ namespace Npgsql
 
                     connector.Notification -= NotificationDelegate;
                     connector.Notice -= NoticeDelegate;
+                    
+                    if (SyncNotification)
+                        connector.RemoveNotificationThread();
 
                     NpgsqlConnectorPool.ConnectorPoolMgr.ReleaseConnector(this, connector);
+                    
+                    
+                    
                     connector = null;
                 }
             }
index c054add865fdeae92e4c3e78dd928d78c17eb5dc..5b1558e63baf02cbd319f06594cf9d737844e900 100644 (file)
@@ -392,6 +392,7 @@ namespace Npgsql
         public static readonly String ConnectionLifeTime    = "CONNECTIONLIFETIME";
         public static readonly String MinPoolSize           = "MINPOOLSIZE";
         public static readonly String MaxPoolSize           = "MAXPOOLSIZE";
+        public static readonly String SyncNotification      = "SYNCNOTIFICATION";
 
         // A list of aliases for some of the above values.  If one of these aliases is
         // encountered when parsing a connection string, it's real key name will
@@ -439,6 +440,7 @@ namespace Npgsql
         public static readonly Int32 MaxPoolSize            = 20;
         public static readonly Int32 Timeout                = 15; // Seconds
         public static readonly Int32 ConnectionLifeTime     = 15; // Seconds
+        public static readonly Boolean SyncNotification     = false; 
     }
     
     internal enum SslMode
index 732da5507feafbcfeb38793520df1f2953402139..bc3cc26121e096d49d2159d705fb9e8246869fc5 100644 (file)
@@ -32,6 +32,8 @@ using System.Data;
 using System.Security;
 using System.Security.Cryptography;
 using System.Security.Cryptography.X509Certificates;
+using System.Threading;
+using System.Net.Sockets;
 
 using Mono.Security.Protocol.Tls;
 
@@ -80,6 +82,8 @@ namespace Npgsql
         // The physical network connection to the backend.
         private Stream                           _stream;
 
+        private Socket                           _socket;
+         
         // Mediator which will hold data generated from backend.
         private NpgsqlMediator                   _mediator;
 
@@ -113,6 +117,15 @@ namespace Npgsql
         private const String                     _planNamePrefix = "npgsqlplan";
         private const String                     _portalNamePrefix = "npgsqlportal";
 
+                
+        private Thread                           _notificationThread;
+        
+        // The AutoResetEvent to synchronize processing threads.
+        internal AutoResetEvent                   _notificationAutoResetEvent;
+        
+        // Counter of notification thread start/stop requests in order to 
+        internal Int16                            _notificationThreadStopCount;
+
 
 
         /// <summary>
@@ -131,6 +144,8 @@ namespace Npgsql
             _oidToNameMapping = new NpgsqlBackendTypeMapping();
             _planIndex = 0;
             _portalIndex = 0;
+            _notificationThreadStopCount = -99;
+            _notificationAutoResetEvent = new AutoResetEvent(true);
 
         }
 
@@ -234,6 +249,11 @@ namespace Npgsql
         {
             CurrentState.Bind(this, bind);
         }
+        
+        internal void Describe (NpgsqlDescribe describe)
+        {
+            CurrentState.Describe(this, describe);
+        }
 
         internal void Execute (NpgsqlExecute execute)
         {
@@ -454,6 +474,21 @@ namespace Npgsql
                 _stream = value;
             }
         }
+        
+        /// <summary>
+        /// The physical connection socket to the backend.
+        /// </summary>
+
+        internal Socket Socket {
+            get
+            {
+                return _socket;
+            }
+            set
+            {
+                _socket = value;
+            }
+        }
 
         /// <summary>
         /// Reports if this connector is fully connected.
@@ -689,12 +724,29 @@ namespace Npgsql
             }
             catch {}
         }
+        
+        internal void CancelRequest()
+        {
+            
+            NpgsqlConnector CancelConnector = new NpgsqlConnector(ConnectionString, false, false);
+            
+            CancelConnector._backend_keydata = BackEndKeyData;
+            
+            
+            // Get a raw connection, possibly SSL...
+            CancelConnector.CurrentState.Open(CancelConnector);
+            
+            // Cancel current request.
+            CancelConnector.CurrentState.CancelRequest(CancelConnector);
+            
+            
+        }
 
 
-    ///<summary>
-    /// Returns next portal index.
-    ///</summary>
-    internal String NextPortalName()
+        ///<summary>
+        /// Returns next portal index.
+        ///</summary>
+        internal String NextPortalName()    
         {
             
             return _portalNamePrefix + System.Threading.Interlocked.Increment(ref _portalIndex);
@@ -708,6 +760,110 @@ namespace Npgsql
         {
             return _planNamePrefix + System.Threading.Interlocked.Increment(ref _planIndex);
         }
+        
+        
+        internal void RemoveNotificationThread()
+        {
+            // Wait notification thread finish its work.
+            _notificationAutoResetEvent.WaitOne();
+            
+            // Kill notification thread.
+            _notificationThread.Abort();
+            _notificationThread = null;
+            
+            // Special case in order to not get problems with thread synchronization.
+            // It will be turned to 0 when synch thread is created.
+            _notificationThreadStopCount = -99;  
+            
+        }
+        
+        internal void AddNotificationThread()
+        {
+            
+            _notificationThreadStopCount = 0;
+            _notificationAutoResetEvent.Set();
+            
+            NpgsqlContextHolder contextHolder = new NpgsqlContextHolder(this, CurrentState);
+            
+            _notificationThread = new Thread(new ThreadStart(contextHolder.ProcessServerMessages));
+            
+            _notificationThread.Start();
+            
+            
+            
+        }
+        
+        internal void StopNotificationThread()
+        {
+            
+            _notificationThreadStopCount++;
+            
+            if (_notificationThreadStopCount == 1) // If this call was the first to increment.
+            {
+                
+                _notificationAutoResetEvent.WaitOne();
+                
+            }
+        }
+        
+        internal void ResumeNotificationThread()
+        {
+            _notificationThreadStopCount--;
+            if (_notificationThreadStopCount == 0)
+            {
+                // Release the synchronization handle.
+                
+                _notificationAutoResetEvent.Set();
+            }
+            
+        }
+        
+        internal Boolean IsNotificationThreadRunning
+        {
+            get
+            {
+                return _notificationThreadStopCount <= 0;
+                
+            }
+        }
+        
+        
+        internal class NpgsqlContextHolder
+        {
+        
+            private NpgsqlConnector connector;
+            private NpgsqlState     state;
+        
+            internal NpgsqlContextHolder(NpgsqlConnector connector, NpgsqlState state)
+            {
+                this.connector = connector;
+                this.state = state;
+            
+            }
+        
+            internal void ProcessServerMessages()
+            {
+                
+                while(true)
+                {
+                    this.connector._notificationAutoResetEvent.WaitOne();
+                    
+                    if (this.connector.Socket.Poll(1000, SelectMode.SelectRead))
+                    {
+                        // reset any responses just before getting new ones
+                        this.connector.Mediator.ResetResponses();
+                        this.state.ProcessBackendResponses(this.connector);
+                        this.connector.CheckErrorsAndNotifications();
+                    }
+               
+                    this.connector._notificationAutoResetEvent.Set();
+                }
+    
+                
+                
+            }
+        
+        }
 
 
 
index c428b2b52cd5e1e454cf0e87e82135b42dde3626..d9149c2ece35ddc3b0850ac1bc00a5898c6fa2f2 100644 (file)
@@ -49,6 +49,7 @@ namespace Npgsql
     /// This class represents the ErrorResponse and NoticeResponse
     /// message sent from PostgreSQL server.
     /// </summary>
+    [Serializable]
     public sealed class NpgsqlError
     {
         // Logging related values
index 7b28fe4e8985539732f1504b2afc3ac4925d460b..cabb12a9b17cb62a0caeff468e7bc0b669056816 100644 (file)
@@ -63,11 +63,14 @@ namespace Npgsql
         }
         
         
-        internal NpgsqlException(String message) : base (message)
+        internal NpgsqlException(String message) : this (message, null)
         {}
         
         internal NpgsqlException(String message, Exception innerException) : base (message, innerException)
-        {}
+        {
+            errors = new ArrayList();
+            errors.Add(new NpgsqlError(ProtocolVersion.Unknown, message));
+        }
         
         
         override public void GetObjectData(SerializationInfo info,StreamingContext context) 
index 0e08e15358e0588dfd48059e731eb6757a9cde2b..17c8d44d17bea058f3e32e1f7c74533849ea5b36 100644 (file)
@@ -59,6 +59,7 @@ namespace Npgsql
         private NpgsqlRowDescription   _rd;
         private ArrayList                              _rows;
         private String                  _sqlSent;
+        private Int32                   _commandTimeout;
         
 
         public NpgsqlMediator()
@@ -73,6 +74,7 @@ namespace Npgsql
             _parameters = new ListDictionary(CaseInsensitiveComparer.Default);
             _backend_key_data = null;
             _sqlSent = String.Empty;
+            _commandTimeout = 0;
         }
 
         public void ResetExpectations()
@@ -90,6 +92,7 @@ namespace Npgsql
             _parameters.Clear();
             _backend_key_data = null;
             _sqlSent = String.Empty;
+            _commandTimeout = 0;
         }
 
 
@@ -185,6 +188,20 @@ namespace Npgsql
                 return _sqlSent;
             }
         }
+        
+        public Int32 CommandTimeout
+        {
+            set
+            {
+                _commandTimeout = value;
+            }
+            
+            get
+            {
+                return _commandTimeout;
+            }
+        
+        }
 
         public void AddNotification(NpgsqlNotificationEventArgs data)
         {
index f690461496321c9f923b58af3fc32fc8a9e9c52e..03140387ebf4d08ac43114e0ba16944386510cf6 100644 (file)
@@ -249,14 +249,14 @@ namespace Npgsql
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "IndexOf", parameterName);
 
             // Iterate values to see what is the index of parameter.
-            Int32 index = 0;
-            if ( (parameterName[0] != ':') && (parameterName[0] != '@') )
-                parameterName = ':' + parameterName;
-
-            foreach(NpgsqlParameter parameter in this)
-            {
-                if (parameter.ParameterName.Remove(0, 1) == parameterName.Remove(0, 1))
-                    return index;
+            Int32 index = 0;\r
+            if ((parameterName[0] == ':') || (parameterName[0] == '@'))\r
+                parameterName = parameterName.Remove(0, 1);\r
+\r
+            foreach (NpgsqlParameter parameter in this)\r
+            {\r
+                if (parameter.ParameterName.Remove(0, 1) == parameterName)\r
+                    return index;\r
                 index++;
             }
             return -1;
@@ -331,7 +331,29 @@ namespace Npgsql
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Contains", value);
             CheckType(value);
             return this.InternalList.Contains(value);
-        }
+        }\r
+\r
+        /// <summary>\r
+        /// Gets a value indicating whether a <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see> with the specified parameter name exists in the collection.\r
+        /// </summary>\r
+        /// <param name="parameterName">The name of the <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see> object to find.</param>\r
+        /// <param name="parameter">A reference to the requested parameter is returned in this out param if it is found in the list.  This value is null if the parameter is not found.</param>\r
+        /// <returns><b>true</b> if the collection contains the parameter and param will contain the parameter; otherwise, <b>false</b>.</returns>\r
+        public bool TryGetValue(string parameterName, out NpgsqlParameter parameter)\r
+        {\r
+            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "TryGetValue", parameterName);\r
+            int index = IndexOf(parameterName);\r
+            if (index != -1)\r
+            {\r
+                parameter = this[index];\r
+                return true;\r
+            }\r
+            else\r
+            {\r
+                parameter = null;\r
+                return false;\r
+            }\r
+        }\r
 
         /// <summary>
         /// Removes all items from the collection.
index faf89c545c98ad6432007ff49d4c5f25f735a8d7..90b23c7ab18e3e368495eca589455e511cbb43fd 100644 (file)
@@ -71,9 +71,9 @@ namespace Npgsql
 
             NpgsqlQuery query = new NpgsqlQuery(command, context.BackendProtocolVersion);
 
-            BufferedStream stream = new BufferedStream(context.Stream);
-            query.WriteToStream(stream, context.Encoding);
-            stream.Flush();
+            query.WriteToStream(context.Stream, context.Encoding);
+            context.Stream.Flush();
+            
 
             ProcessBackendResponses(context);
 
@@ -82,9 +82,10 @@ namespace Npgsql
         public override void Parse(NpgsqlConnector context, NpgsqlParse parse)
         {
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Parse");
-            BufferedStream stream = new BufferedStream(context.Stream);
+                        
+            Stream stream = context.Stream;
             parse.WriteToStream(stream, context.Encoding);
-            stream.Flush();
+            //stream.Flush();
         }
 
 
@@ -100,27 +101,37 @@ namespace Npgsql
         {
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Flush");
             _flushMessage.WriteToStream(context.Stream, context.Encoding);
+            context.Stream.Flush();
             ProcessBackendResponses(context);
         }
 
         public override void Bind(NpgsqlConnector context, NpgsqlBind bind)
         {
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Bind");
-            BufferedStream stream = new BufferedStream(context.Stream);
+            
+            Stream stream = context.Stream;
+            
             bind.WriteToStream(stream, context.Encoding);
-            stream.Flush();
+            //stream.Flush();
 
         }
+        
+        public override void Describe(NpgsqlConnector context, NpgsqlDescribe describe)
+        {
+            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Describe");
+            describe.WriteToStream(context.Stream, context.Encoding);
+            //context.Stream.Flush();
+        }
 
         public override void Execute(NpgsqlConnector context, NpgsqlExecute execute)
         {
 
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Execute");
             NpgsqlDescribe describe = new NpgsqlDescribe('P', execute.PortalName);
-            BufferedStream stream = new BufferedStream(context.Stream);
+            Stream stream = context.Stream;
             describe.WriteToStream(stream, context.Encoding);
             execute.WriteToStream(stream, context.Encoding);
-            stream.Flush();
+            //stream.Flush();
             Sync(context);
         }
 
index c579fa9b85b8cb8ef71787cb92f0c6b4ae86f626..77e8d23e8518edfcb7e845419915f30629f1972d 100644 (file)
@@ -33,6 +33,7 @@ using System.Collections;
 using System.Text;
 using System.Resources;
 
+
 namespace Npgsql
 {
     ///<summary> This class represents the base class for the state pattern design pattern
@@ -93,6 +94,16 @@ namespace Npgsql
         {
             throw new InvalidOperationException("Internal Error! " + this);
         }
+        
+        public virtual void Describe(NpgsqlConnector context, NpgsqlDescribe describe)
+        {
+            throw new InvalidOperationException("Internal Error! " + this);
+        }
+        
+        public virtual void CancelRequest(NpgsqlConnector context)
+        {
+            throw new InvalidOperationException("Internal Error! " + this);
+        }
 
         public virtual void Close( NpgsqlConnector context )
         {
@@ -126,11 +137,18 @@ namespace Npgsql
         /// to handle backend requests.
         /// </summary>
         ///
-        protected virtual void ProcessBackendResponses( NpgsqlConnector context )
+        internal virtual void ProcessBackendResponses( NpgsqlConnector context )
         {
 
             try
             {
+                
+                // Process commandTimeout behavior.
+                
+                if ((context.Mediator.CommandTimeout > 0) && (!context.Socket.Poll(1000000 * context.Mediator.CommandTimeout, SelectMode.SelectRead)))
+                    context.CancelRequest();
+                
+                
                 switch (context.BackendProtocolVersion)
                 {
                 case ProtocolVersion.Version2 :
@@ -154,7 +172,7 @@ namespace Npgsql
         {
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ProcessBackendResponses");
 
-            BufferedStream     stream = new BufferedStream(context.Stream);
+            Stream     stream = context.Stream;
             NpgsqlMediator mediator = context.Mediator;
 
             // Often used buffer
@@ -403,6 +421,9 @@ namespace Npgsql
                     Int32 PID = PGUtil.ReadInt32(stream, inputBuffer);
                     String notificationResponse = PGUtil.ReadString( stream, context.Encoding );
                     mediator.AddNotification(new NpgsqlNotificationEventArgs(PID, notificationResponse));
+                    
+                    if (context.IsNotificationThreadRunning)
+                        readyForQuery = true;
 
                     // Wait for ReadForQuery message
                     break;
@@ -424,7 +445,7 @@ namespace Npgsql
         {
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ProcessBackendResponses");
 
-            BufferedStream     stream = new BufferedStream(context.Stream);
+            Stream     stream = context.Stream;
             NpgsqlMediator mediator = context.Mediator;
 
             // Often used buffers
@@ -573,6 +594,17 @@ namespace Npgsql
 
                     // Now wait for the AsciiRow messages.
                     break;
+                case NpgsqlMessageTypes_Ver_3.ParameterDescription:
+                    
+                    // Do nothing,for instance,  just read...
+                    int lenght = PGUtil.ReadInt32(stream, inputBuffer);
+                    int nb_param = PGUtil.ReadInt16(stream, inputBuffer);
+                    for (int i=0; i < nb_param; i++)
+                    {
+                        int typeoid = PGUtil.ReadInt32(stream, inputBuffer);
+                    }
+                    
+                    break;
 
                 case NpgsqlMessageTypes_Ver_3.DataRow:
                     // This is the AsciiRow message.
@@ -680,6 +712,9 @@ namespace Npgsql
                         PGUtil.ReadString( stream, context.Encoding );
                         mediator.AddNotification(new NpgsqlNotificationEventArgs(PID, notificationResponse));
                     }
+                    
+                    if (context.IsNotificationThreadRunning)
+                        readyForQuery = true;
 
                     // Wait for ReadForQuery message
                     break;
index aea39f362f1e66f5b8f050b201fd0723767626bf..832c1156ec6ccaf3021b318387ac5427d4f0ccb0 100644 (file)
@@ -52,21 +52,24 @@ namespace Npgsql
             resman = new System.Resources.ResourceManager(this.GetType());
 
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME);
-            if ((isolation != IsolationLevel.ReadCommitted) &&
-                    (isolation != IsolationLevel.Serializable))
-                throw new ArgumentOutOfRangeException(resman.GetString("Exception_UnsopportedIsolationLevel"), "isolation");
-
+            
             _conn = conn;
             _isolation = isolation;
 
-            StringBuilder commandText = new StringBuilder("SET TRANSACTION ISOLATION LEVEL ");
+            StringBuilder commandText = new StringBuilder("BEGIN; SET TRANSACTION ISOLATION LEVEL ");
 
-            if (isolation == IsolationLevel.ReadCommitted)
-                commandText.Append("READ COMMITTED");
-            else
+            if ( (isolation == IsolationLevel.RepeatableRead) || 
+                 (isolation == IsolationLevel.Serializable)
+               )
                 commandText.Append("SERIALIZABLE");
+            else
+            {
+                // Set isolation level default to read committed.
+                _isolation = IsolationLevel.ReadCommitted;
+                commandText.Append("READ COMMITTED");
+            }
 
-            commandText.Append("; BEGIN");
+            commandText.Append(";");
 
             NpgsqlCommand command = new NpgsqlCommand(commandText.ToString(), conn.Connector);
             command.ExecuteNonQuery();
index 63830c4487dbe97794f3100408aa2f585fb3354b..7c6c56739e15c7b7f55142a9c7c761016cfcecff 100644 (file)
@@ -83,6 +83,8 @@ namespace Npgsql
 
         public static bool operator == (ServerVersion One, ServerVersion TheOther)
         {
+            if (((Object)One == null) || ((Object)TheOther == null))
+                 return false;
             return
               One._Major == TheOther._Major &&
               One._Minor == TheOther._Minor &&
@@ -91,6 +93,9 @@ namespace Npgsql
 
         public static bool operator != (ServerVersion One, ServerVersion TheOther)
         {
+            if (((Object)One == null) || ((Object)TheOther == null))
+                return true;
+            
             return ! (One == TheOther);
         }
 
@@ -128,6 +133,9 @@ namespace Npgsql
 
         public override bool Equals(object O)
         {
+            if (O == null)
+                return false;
+            
             return (O.GetType() == this.GetType() && this == (ServerVersion)O);
         }
 
index 5d101467215edf914a74f1c24bb03155e2b4c80f..6c80362e5e2308ec7b44a7812ec567f1f577c500 100644 (file)
@@ -54,7 +54,8 @@ namespace NpgsqlTypes
         Time,
         Timestamp,
         Varchar,
-        Refcursor
+        Refcursor,
+               Inet
 
     }
 
index c50e260e7fd29cd93c100b7097d1563e114959e4..30db474286caa6953b372e30f6b0bece9645b12a 100644 (file)
@@ -251,7 +251,17 @@ namespace NpgsqlTypes
             return "$" + ((IFormattable)NativeData).ToString(null, CultureInfo.InvariantCulture.NumberFormat);
         }
         
-        
+               /// <summary>
+               /// Convert to a postgres inet.
+               /// </summary>
+               internal static String ToIPAddress(NpgsqlNativeTypeInfo TypeInfo, Object NativeData)
+               {
+                       if (NativeData is NpgsqlInet)
+                               return ((NpgsqlInet)NativeData).ToString();
+                       else
+                               return ((System.Net.IPAddress)NativeData).ToString();
+               }
+
     }
 
 
index 2a417080c340c2785a7c3e63611ee00c21b3ac48..1eb660f89a79db9f61798be021db0634c5161f6e 100644 (file)
@@ -218,4 +218,59 @@ namespace NpgsqlTypes
             return string.Format("({0}), {1}", Center, Radius);
         }
     }
+
+
+       /// <summary>
+       /// Represents a PostgreSQL inet type.
+       /// </summary>
+       public struct NpgsqlInet
+       {
+               public IPAddress addr;
+               public int mask;
+
+               public NpgsqlInet(IPAddress addr, int mask)
+               {
+                       this.addr = addr;
+                       this.mask = mask;
+               }
+
+               public NpgsqlInet(IPAddress addr)
+               {
+                       this.addr = addr;
+                       this.mask = 32;
+               }
+
+               public NpgsqlInet(string addr)
+               {
+                       if (addr.IndexOf('/') > 0)
+                       {
+                               string[] addrbits = addr.Split('/');
+                               if (addrbits.GetUpperBound(0) != 1)
+                                       throw new FormatException("Invalid number of parts in CIDR specification");
+                               this.addr = IPAddress.Parse(addrbits[0]);
+                               this.mask = int.Parse(addrbits[1]);
+                       }
+                       else
+                       {
+                               this.addr = IPAddress.Parse(addr);
+                               this.mask = 32;
+                       }
+               }
+
+               public override String ToString()
+               {
+                       if (mask != 32)
+                               return string.Format("{0}/{1}", addr.ToString(), mask);
+                       else
+                               return addr.ToString();
+               }
+
+               public static implicit operator IPAddress(NpgsqlInet x)
+               {
+                       if (x.mask != 32)
+                               throw new InvalidCastException("Cannot cast CIDR network to address");
+                       else
+                               return x.addr;
+               }
+       }
 }
index 6f3e1777c8054fc3755040d068f9424b0d259fc8..39f414026e893af66377363e28ae788bb5f3238d 100644 (file)
@@ -97,7 +97,7 @@ namespace NpgsqlTypes
         {
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ConvertBackendBytesToStytemType");
 
-            /*
+            
             // We are never guaranteed to know about every possible data type the server can send us.
             // When we encounter an unknown type, we punt and return the data without modification.
             if (TypeInfo == null)
@@ -105,9 +105,9 @@ namespace NpgsqlTypes
 
             switch (TypeInfo.NpgsqlDbType)
             {
-            case NpgsqlDbType.Binary:
+            case NpgsqlDbType.Bytea:
                 return data;
-            case NpgsqlDbType.Boolean:
+            /*case NpgsqlDbType.Boolean:
                 return BitConverter.ToBoolean(data, 0);
             case NpgsqlDbType.DateTime:
                 return DateTime.MinValue.AddTicks(IPAddress.NetworkToHostOrder(BitConverter.ToInt64(data, 0)));
@@ -121,10 +121,10 @@ namespace NpgsqlTypes
             case NpgsqlDbType.String:
             case NpgsqlDbType.AnsiString:
             case NpgsqlDbType.StringFixedLength:
-                return encoding.GetString(data, 0, fieldValueSize);
+                return encoding.GetString(data, 0, fieldValueSize);*/
             default:
                 throw new InvalidCastException("Type not supported in binary format");
-            }*/
+            }
             
             return null;
         }
@@ -268,6 +268,12 @@ namespace NpgsqlTypes
                 new ConvertNativeToBackendHandler(ExtendedNativeToBackendTypeConverter.ToCircle));
 
                 NativeTypeMapping.AddTypeAlias("circle", typeof(NpgsqlCircle));
+
+                               NativeTypeMapping.AddType("inet", NpgsqlDbType.Inet, DbType.Object, true,
+                new ConvertNativeToBackendHandler(BasicNativeToBackendTypeConverter.ToIPAddress));
+
+                               NativeTypeMapping.AddTypeAlias("inet", typeof(IPAddress));
+                               NativeTypeMapping.AddTypeAlias("inet", typeof(NpgsqlInet));
             }
         }
 
@@ -352,6 +358,9 @@ namespace NpgsqlTypes
                     new NpgsqlBackendTypeInfo(0, "numeric", NpgsqlDbType.Numeric, DbType.Decimal, typeof(Decimal),
                         null),
 
+                                       new NpgsqlBackendTypeInfo(0, "inet", NpgsqlDbType.Inet, DbType.Object, typeof(NpgsqlInet),
+                                           null),
+
                     new NpgsqlBackendTypeInfo(0, "money", NpgsqlDbType.Money, DbType.Decimal, typeof(Decimal),
                         new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToMoney)),