2004-11-25 Francisco Figueiredo Jr. <fxjrlists@yahoo.com.br>
[mono.git] / mcs / class / Npgsql / Npgsql / NpgsqlState.cs
index b553532073f7d307f00c18f614abcabd81cecffa..2f6abc49ce74e0b8fc32148fbd1c0063117c1321 100755 (executable)
@@ -43,91 +43,73 @@ namespace Npgsql
     internal abstract class NpgsqlState
     {
         private readonly String CLASSNAME = "NpgsqlState";
-        protected ResourceManager resman = null;
+        protected static ResourceManager resman = new ResourceManager(typeof(NpgsqlState));
 
-        public virtual void Open(NpgsqlConnection context)
+        public virtual void Open(NpgsqlConnector context)
         {
             throw new InvalidOperationException("Internal Error! " + this);
         }
-        public virtual void Startup(NpgsqlConnection context)
+        public virtual void Startup(NpgsqlConnector context)
         {
             throw new InvalidOperationException("Internal Error! " + this);
         }
-        public virtual void Authenticate(NpgsqlConnection context, string password)
+        public virtual void Authenticate(NpgsqlConnector context, string password)
         {
             throw new InvalidOperationException("Internal Error! " + this);
         }
-        public virtual void Query(NpgsqlConnection context, NpgsqlCommand command)
+        public virtual void Query(NpgsqlConnector context, NpgsqlCommand command)
         {
             throw new InvalidOperationException("Internal Error! " + this);
         }
-        public virtual void Ready( NpgsqlConnection context )
+        public virtual void Ready( NpgsqlConnector context )
         {
             throw new InvalidOperationException("Internal Error! " + this);
         }
-        public virtual void FunctionCall(NpgsqlConnection context, NpgsqlCommand command)
+        public virtual void FunctionCall(NpgsqlConnector context, NpgsqlCommand command)
         {
             throw new InvalidOperationException("Internal Error! " + this);
         }
-        public virtual void Parse(NpgsqlConnection context, NpgsqlParse parse)
+        public virtual void Parse(NpgsqlConnector context, NpgsqlParse parse)
         {
             throw new InvalidOperationException("Internal Error! " + this);
         }
-        public virtual void Flush(NpgsqlConnection context)
+        public virtual void Flush(NpgsqlConnector context)
         {
             throw new InvalidOperationException("Internal Error! " + this);
         }
-        public virtual void Sync(NpgsqlConnection context)
+        public virtual void Sync(NpgsqlConnector context)
         {
             throw new InvalidOperationException("Internal Error! " + this);
         }
-        public virtual void Bind(NpgsqlConnection context, NpgsqlBind bind)
+        public virtual void Bind(NpgsqlConnector context, NpgsqlBind bind)
         {
             throw new InvalidOperationException("Internal Error! " + this);
         }
-        public virtual void Execute(NpgsqlConnection context, NpgsqlExecute execute)
+        public virtual void Execute(NpgsqlConnector context, NpgsqlExecute execute)
         {
             throw new InvalidOperationException("Internal Error! " + this);
         }
 
-        public NpgsqlState()
+        public virtual void Close( NpgsqlConnector context )
         {
-            resman = new ResourceManager(this.GetType());
-        }
-
-        public virtual void Close( NpgsqlConnection context )
-        {
-            /*NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Close");
-            if ( context.State == ConnectionState.Open )
+            if (this != NpgsqlClosedState.Instance)
             {
-                Stream stream = context.Stream;
-                if ( stream.CanWrite )
+                try
                 {
-                    stream.WriteByte((Byte)'X');
-                    if (context.BackendProtocolVersion >= ProtocolVersion.Version3)
-                        PGUtil.WriteInt32(stream, 4);
-                    stream.Flush();
-                }
-            }*/
-
-            // CHECKME!!!
-            // The close logic is pretty messed up I think.  Needs lots of work.
-/*
-            if (! context.Connector.Shared) {
-                if (context.Connector.Stream != null) {
-                    try {
-                        context.Connector.Stream.Close();
-                    } catch {}
+                    context.Stream.Close();
                 }
+                catch {}
+
+                context.Stream = null;
+            ChangeState( context, NpgsqlClosedState.Instance )
+                ;
             }
-*/
-            //ChangeState( context, NpgsqlClosedState.Instance );
         }
 
         ///<summary>
         ///This method is used by the states to change the state of the context.
         /// </summary>
-        protected virtual void ChangeState(NpgsqlConnection context, NpgsqlState newState)
+        protected virtual void ChangeState(NpgsqlConnector context, NpgsqlState newState)
         {
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ChangeState");
             context.CurrentState = newState;
@@ -140,13 +122,13 @@ namespace Npgsql
         /// to handle backend requests.
         /// </summary>
         ///
-        protected virtual void ProcessBackendResponses( NpgsqlConnection context )
+        protected virtual void ProcessBackendResponses( NpgsqlConnector context )
         {
-            // reset any responses just before getting new ones
-            context.Mediator.ResetResponses();
 
-            try {
-                switch (context.BackendProtocolVersion) {
+            try
+            {
+                switch (context.BackendProtocolVersion)
+                {
                 case ProtocolVersion.Version2 :
                     ProcessBackendResponses_Ver_2(context);
                     break;
@@ -156,13 +138,15 @@ namespace Npgsql
                     break;
 
                 }
-            } finally {
+            }
+            finally
+            {
                 // reset expectations right after getting new responses
                 context.Mediator.ResetExpectations();
             }
         }
 
-        protected virtual void ProcessBackendResponses_Ver_2( NpgsqlConnection context )
+        protected virtual void ProcessBackendResponses_Ver_2( NpgsqlConnector context )
         {
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ProcessBackendResponses");
 
@@ -197,7 +181,8 @@ namespace Npgsql
                     // Possible error in the NpgsqlConnectedState:
                     //         No pg_hba.conf configured.
 
-                    if (! mediator.RequireReadyForQuery) {
+                    if (! mediator.RequireReadyForQuery)
+                    {
                         return;
                     }
 
@@ -289,8 +274,8 @@ namespace Npgsql
                         }
 
                         // Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now.
-                        NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationOK", LogLevel.Debug);
-                        mediator.Errors.Add(String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType));
+
+                        mediator.Errors.Add(new NpgsqlError(context.BackendProtocolVersion, String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType)));
                     }
 
                     return;
@@ -301,7 +286,7 @@ namespace Npgsql
 
                     {
                         NpgsqlRowDescription rd = new NpgsqlRowDescription(context.BackendProtocolVersion);
-                        rd.ReadFromStream(stream, context.Encoding);
+                        rd.ReadFromStream(stream, context.Encoding, context.OidToNameMapping);
 
                         // Initialize the array list which will contain the data from this rowdescription.
                         mediator.AddRowDescription(rd);
@@ -315,7 +300,7 @@ namespace Npgsql
                     NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "AsciiRow");
 
                     {
-                        NpgsqlAsciiRow asciiRow = new NpgsqlAsciiRow(context.Mediator.LastRowDescription, context.OidToNameMapping, context.BackendProtocolVersion);
+                        NpgsqlAsciiRow asciiRow = new NpgsqlAsciiRow(context.Mediator.LastRowDescription, context.BackendProtocolVersion);
                         asciiRow.ReadFromStream(stream, context.Encoding);
 
                         // Add this row to the rows array.
@@ -427,7 +412,7 @@ namespace Npgsql
             }
         }
 
-        protected virtual void ProcessBackendResponses_Ver_3( NpgsqlConnection context )
+        protected virtual void ProcessBackendResponses_Ver_3( NpgsqlConnector context )
         {
             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ProcessBackendResponses");
 
@@ -443,7 +428,8 @@ namespace Npgsql
             while (!readyForQuery)
             {
                 // Check the first Byte of response.
-                switch ( stream.ReadByte() )
+                Int32 message = stream.ReadByte();
+                switch ( message )
                 {
                 case NpgsqlMessageTypes_Ver_3.ErrorResponse :
 
@@ -463,7 +449,8 @@ namespace Npgsql
                     // Possible error in the NpgsqlConnectedState:
                     //         No pg_hba.conf configured.
 
-                    if (! mediator.RequireReadyForQuery) {
+                    if (! mediator.RequireReadyForQuery)
+                    {
                         return;
                     }
 
@@ -478,7 +465,7 @@ namespace Npgsql
                     PGUtil.ReadInt32(stream, inputBuffer);
 
                     {
-                    Int32 authType = PGUtil.ReadInt32(stream, inputBuffer);
+                        Int32 authType = PGUtil.ReadInt32(stream, inputBuffer);
 
                         if ( authType == NpgsqlMessageTypes_Ver_3.AuthenticationOk )
                         {
@@ -557,8 +544,7 @@ namespace Npgsql
                         }
 
                         // Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now.
-                        NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationOK", LogLevel.Debug);
-                        mediator.Errors.Add(String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType));
+                        mediator.Errors.Add(new NpgsqlError(context.BackendProtocolVersion, String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType)));
                     }
 
                     return;
@@ -568,7 +554,7 @@ namespace Npgsql
                     NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "RowDescription");
                     {
                         NpgsqlRowDescription rd = new NpgsqlRowDescription(context.BackendProtocolVersion);
-                        rd.ReadFromStream(stream, context.Encoding);
+                        rd.ReadFromStream(stream, context.Encoding, context.OidToNameMapping);
 
                         mediator.AddRowDescription(rd);
                     }
@@ -580,7 +566,7 @@ namespace Npgsql
                     // This is the AsciiRow message.
                     NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "DataRow");
                     {
-                        NpgsqlAsciiRow asciiRow = new NpgsqlAsciiRow(context.Mediator.LastRowDescription, context.OidToNameMapping, context.BackendProtocolVersion);
+                        NpgsqlAsciiRow asciiRow = new NpgsqlAsciiRow(context.Mediator.LastRowDescription, context.BackendProtocolVersion);
                         asciiRow.ReadFromStream(stream, context.Encoding);
 
                         // Add this row to the rows array.
@@ -695,15 +681,24 @@ namespace Npgsql
 
                     mediator.AddParameterStatus(parameterStatus.Parameter, parameterStatus);
 
-                    if (parameterStatus.Parameter == "server_version") {
+                    if (parameterStatus.Parameter == "server_version")
+                    {
                         // Add this one under our own name so that if the parameter name
-                        // changes in a future backend version, we can handle it here in the 
+                        // changes in a future backend version, we can handle it here in the
                         // protocol handler and leave everybody else put of it.
                         mediator.AddParameterStatus("__npgsql_server_version", parameterStatus);
-//                        context.ServerVersionString = parameterStatus.ParameterValue;
+                        //                        context.ServerVersionString = parameterStatus.ParameterValue;
                     }
 
                     break;
+                case NpgsqlMessageTypes_Ver_3.NoData :
+                    // This nodata message may be generated by prepare commands issued with queries which doesn't return rows
+                    // for example insert, update or delete.
+                    // Just eat the message.
+                    NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "ParameterStatus");
+                    PGUtil.ReadInt32(stream, inputBuffer);
+                    break;
+
 
                 default :
                     // This could mean a number of things
@@ -712,7 +707,7 @@ namespace Npgsql
                     //   Backend has gone insane?
                     // FIXME
                     // what exception should we really throw here?
-                    throw new NotSupportedException("Backend sent unrecognized response type");
+                    throw new NotSupportedException(String.Format("Backend sent unrecognized response type: {0}", (Char)message));
 
                 }
             }