1 // created on 6/14/2002 at 7:56 PM
3 // Npgsql.NpgsqlState.cs
6 // Dave Joyner <d4ljoyn@yahoo.com>
8 // Copyright (C) 2002 The Npgsql Development Team
9 // npgsql-general@gborg.postgresql.org
10 // http://gborg.postgresql.org/project/npgsql/projdisplay.php
12 // This library is free software; you can redistribute it and/or
13 // modify it under the terms of the GNU Lesser General Public
14 // License as published by the Free Software Foundation; either
15 // version 2.1 of the License, or (at your option) any later version.
17 // This library is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 // Lesser General Public License for more details.
22 // You should have received a copy of the GNU Lesser General Public
23 // License along with this library; if not, write to the Free Software
24 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 using System
.Net
.Sockets
;
32 using System
.Collections
;
34 using System
.Resources
;
38 ///<summary> This class represents the base class for the state pattern design pattern
43 internal abstract class NpgsqlState
45 private readonly String CLASSNAME
= "NpgsqlState";
46 protected static ResourceManager resman
= new ResourceManager(typeof(NpgsqlState
));
48 public virtual void Open(NpgsqlConnector context
)
50 throw new InvalidOperationException("Internal Error! " + this);
52 public virtual void Startup(NpgsqlConnector context
)
54 throw new InvalidOperationException("Internal Error! " + this);
56 public virtual void Authenticate(NpgsqlConnector context
, string password
)
58 throw new InvalidOperationException("Internal Error! " + this);
60 public virtual void Query(NpgsqlConnector context
, NpgsqlCommand command
)
62 throw new InvalidOperationException("Internal Error! " + this);
64 public virtual void Ready( NpgsqlConnector context
)
66 throw new InvalidOperationException("Internal Error! " + this);
68 public virtual void FunctionCall(NpgsqlConnector context
, NpgsqlCommand command
)
70 throw new InvalidOperationException("Internal Error! " + this);
72 public virtual void Parse(NpgsqlConnector context
, NpgsqlParse parse
)
74 throw new InvalidOperationException("Internal Error! " + this);
76 public virtual void Flush(NpgsqlConnector context
)
78 throw new InvalidOperationException("Internal Error! " + this);
80 public virtual void Sync(NpgsqlConnector context
)
82 throw new InvalidOperationException("Internal Error! " + this);
84 public virtual void Bind(NpgsqlConnector context
, NpgsqlBind bind
)
86 throw new InvalidOperationException("Internal Error! " + this);
88 public virtual void Execute(NpgsqlConnector context
, NpgsqlExecute execute
)
90 throw new InvalidOperationException("Internal Error! " + this);
93 public virtual void Close( NpgsqlConnector context
)
95 if (this != NpgsqlClosedState
.Instance
)
99 context
.Stream
.Close();
103 context
.Stream
= null;
104 ChangeState( context
, NpgsqlClosedState
.Instance
)
110 ///This method is used by the states to change the state of the context.
112 protected virtual void ChangeState(NpgsqlConnector context
, NpgsqlState newState
)
114 NpgsqlEventLog
.LogMethodEnter(LogLevel
.Debug
, CLASSNAME
, "ChangeState");
115 context
.CurrentState
= newState
;
119 /// This method is responsible to handle all protocol messages sent from the backend.
120 /// It holds all the logic to do it.
121 /// To exchange data, it uses a Mediator object from which it reads/writes information
122 /// to handle backend requests.
125 protected virtual void ProcessBackendResponses( NpgsqlConnector context
)
130 switch (context
.BackendProtocolVersion
)
132 case ProtocolVersion
.Version2
:
133 ProcessBackendResponses_Ver_2(context
);
136 case ProtocolVersion
.Version3
:
137 ProcessBackendResponses_Ver_3(context
);
144 // reset expectations right after getting new responses
145 context
.Mediator
.ResetExpectations();
149 protected virtual void ProcessBackendResponses_Ver_2( NpgsqlConnector context
)
151 NpgsqlEventLog
.LogMethodEnter(LogLevel
.Debug
, CLASSNAME
, "ProcessBackendResponses");
153 BufferedStream stream
= new BufferedStream(context
.Stream
);
154 NpgsqlMediator mediator
= context
.Mediator
;
157 Byte
[] inputBuffer
= new Byte
[ 4 ];
159 Boolean readyForQuery
= false;
161 while (!readyForQuery
)
163 // Check the first Byte of response.
164 switch ( stream
.ReadByte() )
166 case NpgsqlMessageTypes_Ver_2
.ErrorResponse
:
169 NpgsqlError error
= new NpgsqlError(context
.BackendProtocolVersion
);
170 error
.ReadFromStream(stream
, context
.Encoding
);
172 mediator
.Errors
.Add(error
);
174 NpgsqlEventLog
.LogMsg(resman
, "Log_ErrorResponse", LogLevel
.Debug
, error
.Message
);
177 // Return imediately if it is in the startup state or connected state as
178 // there is no more messages to consume.
179 // Possible error in the NpgsqlStartupState:
181 // Possible error in the NpgsqlConnectedState:
182 // No pg_hba.conf configured.
184 if (! mediator
.RequireReadyForQuery
)
192 case NpgsqlMessageTypes_Ver_2
.AuthenticationRequest
:
194 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "AuthenticationRequest");
197 Int32 authType
= PGUtil
.ReadInt32(stream
, inputBuffer
);
199 if ( authType
== NpgsqlMessageTypes_Ver_2
.AuthenticationOk
)
201 NpgsqlEventLog
.LogMsg(resman
, "Log_AuthenticationOK", LogLevel
.Debug
);
206 if ( authType
== NpgsqlMessageTypes_Ver_2
.AuthenticationClearTextPassword
)
208 NpgsqlEventLog
.LogMsg(resman
, "Log_AuthenticationClearTextRequest", LogLevel
.Debug
);
210 // Send the PasswordPacket.
212 ChangeState( context
, NpgsqlStartupState
.Instance
);
213 context
.Authenticate(context
.Password
);
219 if ( authType
== NpgsqlMessageTypes_Ver_2
.AuthenticationMD5Password
)
221 NpgsqlEventLog
.LogMsg(resman
, "Log_AuthenticationMD5Request", LogLevel
.Debug
);
222 // Now do the "MD5-Thing"
223 // for this the Password has to be:
224 // 1. md5-hashed with the username as salt
225 // 2. md5-hashed again with the salt we get from the backend
228 MD5 md5
= MD5
.Create();
232 byte[] passwd
= context
.Encoding
.GetBytes(context
.Password
);
233 byte[] saltUserName
= context
.Encoding
.GetBytes(context
.UserName
);
235 byte[] crypt_buf
= new byte[passwd
.Length
+ saltUserName
.Length
];
237 passwd
.CopyTo(crypt_buf
, 0);
238 saltUserName
.CopyTo(crypt_buf
, passwd
.Length
);
242 StringBuilder sb
= new StringBuilder ();
243 byte[] hashResult
= md5
.ComputeHash(crypt_buf
);
244 foreach (byte b
in hashResult
)
245 sb
.Append (b
.ToString ("x2"));
248 String prehash
= sb
.ToString();
250 byte[] prehashbytes
= context
.Encoding
.GetBytes(prehash
);
254 byte[] saltServer
= new byte[4];
255 stream
.Read(saltServer
, 0, 4);
256 // Send the PasswordPacket.
257 ChangeState( context
, NpgsqlStartupState
.Instance
);
262 crypt_buf
= new byte[prehashbytes
.Length
+ saltServer
.Length
];
263 prehashbytes
.CopyTo(crypt_buf
, 0);
264 saltServer
.CopyTo(crypt_buf
, prehashbytes
.Length
);
266 sb
= new StringBuilder ("md5"); // This is needed as the backend expects md5 result starts with "md5"
267 hashResult
= md5
.ComputeHash(crypt_buf
);
268 foreach (byte b
in hashResult
)
269 sb
.Append (b
.ToString ("x2"));
271 context
.Authenticate(sb
.ToString ());
276 // Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now.
277 NpgsqlEventLog
.LogMsg(resman
, "Log_AuthenticationOK", LogLevel
.Debug
);
278 mediator
.Errors
.Add(String
.Format(resman
.GetString("Exception_AuthenticationMethodNotSupported"), authType
));
283 case NpgsqlMessageTypes_Ver_2
.RowDescription
:
284 // This is the RowDescription message.
285 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "RowDescription");
288 NpgsqlRowDescription rd
= new NpgsqlRowDescription(context
.BackendProtocolVersion
);
289 rd
.ReadFromStream(stream
, context
.Encoding
, context
.OidToNameMapping
);
291 // Initialize the array list which will contain the data from this rowdescription.
292 mediator
.AddRowDescription(rd
);
295 // Now wait for the AsciiRow messages.
298 case NpgsqlMessageTypes_Ver_2
.AsciiRow
:
299 // This is the AsciiRow message.
300 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "AsciiRow");
303 NpgsqlAsciiRow asciiRow
= new NpgsqlAsciiRow(context
.Mediator
.LastRowDescription
, context
.BackendProtocolVersion
);
304 asciiRow
.ReadFromStream(stream
, context
.Encoding
);
306 // Add this row to the rows array.
307 mediator
.AddAsciiRow(asciiRow
);
310 // Now wait for CompletedResponse message.
313 case NpgsqlMessageTypes_Ver_2
.BinaryRow
:
314 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "BinaryRow");
317 NpgsqlBinaryRow binaryRow
= new NpgsqlBinaryRow(context
.Mediator
.LastRowDescription
);
318 binaryRow
.ReadFromStream(stream
, context
.Encoding
);
320 mediator
.AddBinaryRow(binaryRow
);
325 case NpgsqlMessageTypes_Ver_2
.ReadyForQuery
:
327 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "ReadyForQuery");
328 readyForQuery
= true;
329 ChangeState( context
, NpgsqlReadyState
.Instance
);
332 case NpgsqlMessageTypes_Ver_2
.BackendKeyData
:
334 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "BackendKeyData");
335 // BackendKeyData message.
336 NpgsqlBackEndKeyData backend_keydata
= new NpgsqlBackEndKeyData(context
.BackendProtocolVersion
);
337 backend_keydata
.ReadFromStream(stream
);
338 mediator
.SetBackendKeydata(backend_keydata
);
341 // Wait for ReadForQuery message
345 case NpgsqlMessageTypes_Ver_2
.NoticeResponse
:
348 NpgsqlError notice
= new NpgsqlError(context
.BackendProtocolVersion
);
349 notice
.ReadFromStream(stream
, context
.Encoding
);
351 mediator
.Notices
.Add(notice
);
353 NpgsqlEventLog
.LogMsg(resman
, "Log_NoticeResponse", LogLevel
.Debug
, notice
.Message
);
356 // Wait for ReadForQuery message
359 case NpgsqlMessageTypes_Ver_2
.CompletedResponse
:
360 // This is the CompletedResponse message.
361 // Get the string returned.
364 String result
= PGUtil
.ReadString(stream
, context
.Encoding
);
366 NpgsqlEventLog
.LogMsg(resman
, "Log_CompletedResponse", LogLevel
.Debug
, result
);
367 // Add result from the processing.
369 mediator
.AddCompletedResponse(result
);
371 // Now wait for ReadyForQuery message.
374 case NpgsqlMessageTypes_Ver_2
.CursorResponse
:
375 // This is the cursor response message.
376 // It is followed by a C NULL terminated string with the name of
377 // the cursor in a FETCH case or 'blank' otherwise.
378 // In this case it should be always 'blank'.
379 // [FIXME] Get another name for this function.
380 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "CursorResponse");
382 String cursorName
= PGUtil
.ReadString(stream
, context
.Encoding
);
383 // Continue waiting for ReadyForQuery message.
386 case NpgsqlMessageTypes_Ver_2
.EmptyQueryResponse
:
387 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "EmptyQueryResponse");
388 PGUtil
.ReadString(stream
, context
.Encoding
);
391 case NpgsqlMessageTypes_Ver_2
.NotificationResponse
:
393 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "NotificationResponse");
395 Int32 PID
= PGUtil
.ReadInt32(stream
, inputBuffer
);
396 String notificationResponse
= PGUtil
.ReadString( stream
, context
.Encoding
);
397 mediator
.AddNotification(new NpgsqlNotificationEventArgs(PID
, notificationResponse
));
399 // Wait for ReadForQuery message
403 // This could mean a number of things
404 // We've gotten out of sync with the backend?
405 // We need to implement this type?
406 // Backend has gone insane?
408 // what exception should we really throw here?
409 throw new NotSupportedException("Backend sent unrecognized response type");
415 protected virtual void ProcessBackendResponses_Ver_3( NpgsqlConnector context
)
417 NpgsqlEventLog
.LogMethodEnter(LogLevel
.Debug
, CLASSNAME
, "ProcessBackendResponses");
419 BufferedStream stream
= new BufferedStream(context
.Stream
);
420 NpgsqlMediator mediator
= context
.Mediator
;
422 // Often used buffers
423 Byte
[] inputBuffer
= new Byte
[ 4 ];
426 Boolean readyForQuery
= false;
428 while (!readyForQuery
)
430 // Check the first Byte of response.
431 Int32 message
= stream
.ReadByte();
434 case NpgsqlMessageTypes_Ver_3
.ErrorResponse
:
437 NpgsqlError error
= new NpgsqlError(context
.BackendProtocolVersion
);
438 error
.ReadFromStream(stream
, context
.Encoding
);
440 mediator
.Errors
.Add(error
);
442 NpgsqlEventLog
.LogMsg(resman
, "Log_ErrorResponse", LogLevel
.Debug
, error
.Message
);
445 // Return imediately if it is in the startup state or connected state as
446 // there is no more messages to consume.
447 // Possible error in the NpgsqlStartupState:
449 // Possible error in the NpgsqlConnectedState:
450 // No pg_hba.conf configured.
452 if (! mediator
.RequireReadyForQuery
)
460 case NpgsqlMessageTypes_Ver_3
.AuthenticationRequest
:
462 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "AuthenticationRequest");
465 PGUtil
.ReadInt32(stream
, inputBuffer
);
468 Int32 authType
= PGUtil
.ReadInt32(stream
, inputBuffer
);
470 if ( authType
== NpgsqlMessageTypes_Ver_3
.AuthenticationOk
)
472 NpgsqlEventLog
.LogMsg(resman
, "Log_AuthenticationOK", LogLevel
.Debug
);
477 if ( authType
== NpgsqlMessageTypes_Ver_3
.AuthenticationClearTextPassword
)
479 NpgsqlEventLog
.LogMsg(resman
, "Log_AuthenticationClearTextRequest", LogLevel
.Debug
);
481 // Send the PasswordPacket.
483 ChangeState( context
, NpgsqlStartupState
.Instance
);
484 context
.Authenticate(context
.Password
);
490 if ( authType
== NpgsqlMessageTypes_Ver_3
.AuthenticationMD5Password
)
492 NpgsqlEventLog
.LogMsg(resman
, "Log_AuthenticationMD5Request", LogLevel
.Debug
);
493 // Now do the "MD5-Thing"
494 // for this the Password has to be:
495 // 1. md5-hashed with the username as salt
496 // 2. md5-hashed again with the salt we get from the backend
499 MD5 md5
= MD5
.Create();
503 byte[] passwd
= context
.Encoding
.GetBytes(context
.Password
);
504 byte[] saltUserName
= context
.Encoding
.GetBytes(context
.UserName
);
506 byte[] crypt_buf
= new byte[passwd
.Length
+ saltUserName
.Length
];
508 passwd
.CopyTo(crypt_buf
, 0);
509 saltUserName
.CopyTo(crypt_buf
, passwd
.Length
);
513 StringBuilder sb
= new StringBuilder ();
514 byte[] hashResult
= md5
.ComputeHash(crypt_buf
);
515 foreach (byte b
in hashResult
)
516 sb
.Append (b
.ToString ("x2"));
519 String prehash
= sb
.ToString();
521 byte[] prehashbytes
= context
.Encoding
.GetBytes(prehash
);
525 stream
.Read(inputBuffer
, 0, 4);
526 // Send the PasswordPacket.
527 ChangeState( context
, NpgsqlStartupState
.Instance
);
532 crypt_buf
= new byte[prehashbytes
.Length
+ 4];
533 prehashbytes
.CopyTo(crypt_buf
, 0);
534 inputBuffer
.CopyTo(crypt_buf
, prehashbytes
.Length
);
536 sb
= new StringBuilder ("md5"); // This is needed as the backend expects md5 result starts with "md5"
537 hashResult
= md5
.ComputeHash(crypt_buf
);
538 foreach (byte b
in hashResult
)
539 sb
.Append (b
.ToString ("x2"));
541 context
.Authenticate(sb
.ToString ());
546 // Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now.
547 NpgsqlEventLog
.LogMsg(resman
, "Log_AuthenticationOK", LogLevel
.Debug
);
548 mediator
.Errors
.Add(String
.Format(resman
.GetString("Exception_AuthenticationMethodNotSupported"), authType
));
553 case NpgsqlMessageTypes_Ver_3
.RowDescription
:
554 // This is the RowDescription message.
555 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "RowDescription");
557 NpgsqlRowDescription rd
= new NpgsqlRowDescription(context
.BackendProtocolVersion
);
558 rd
.ReadFromStream(stream
, context
.Encoding
, context
.OidToNameMapping
);
560 mediator
.AddRowDescription(rd
);
563 // Now wait for the AsciiRow messages.
566 case NpgsqlMessageTypes_Ver_3
.DataRow
:
567 // This is the AsciiRow message.
568 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "DataRow");
570 NpgsqlAsciiRow asciiRow
= new NpgsqlAsciiRow(context
.Mediator
.LastRowDescription
, context
.BackendProtocolVersion
);
571 asciiRow
.ReadFromStream(stream
, context
.Encoding
);
573 // Add this row to the rows array.
574 mediator
.AddAsciiRow(asciiRow
);
577 // Now wait for CompletedResponse message.
580 case NpgsqlMessageTypes_Ver_3
.ReadyForQuery
:
582 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "ReadyForQuery");
584 // Possible status bytes returned:
585 // I = Idle (no transaction active).
586 // T = In transaction, ready for more.
587 // E = Error in transaction, queries will fail until transaction aborted.
588 // Just eat the status byte, we have no use for it at this time.
589 PGUtil
.ReadInt32(stream
, inputBuffer
);
590 PGUtil
.ReadString(stream
, context
.Encoding
, 1);
592 readyForQuery
= true;
593 ChangeState( context
, NpgsqlReadyState
.Instance
);
597 case NpgsqlMessageTypes_Ver_3
.BackendKeyData
:
599 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "BackendKeyData");
600 // BackendKeyData message.
601 NpgsqlBackEndKeyData backend_keydata
= new NpgsqlBackEndKeyData(context
.BackendProtocolVersion
);
602 backend_keydata
.ReadFromStream(stream
);
603 mediator
.SetBackendKeydata(backend_keydata
);
606 // Wait for ReadForQuery message
609 case NpgsqlMessageTypes_Ver_3
.NoticeResponse
:
611 // Notices and errors are identical except that we
612 // just throw notices away completely ignored.
614 NpgsqlError notice
= new NpgsqlError(context
.BackendProtocolVersion
);
615 notice
.ReadFromStream(stream
, context
.Encoding
);
617 mediator
.Notices
.Add(notice
);
619 NpgsqlEventLog
.LogMsg(resman
, "Log_NoticeResponse", LogLevel
.Debug
, notice
.Message
);
622 // Wait for ReadForQuery message
625 case NpgsqlMessageTypes_Ver_3
.CompletedResponse
:
626 // This is the CompletedResponse message.
627 // Get the string returned.
629 PGUtil
.ReadInt32(stream
, inputBuffer
);
630 Str
= PGUtil
.ReadString(stream
, context
.Encoding
);
632 NpgsqlEventLog
.LogMsg(resman
, "Log_CompletedResponse", LogLevel
.Debug
, Str
);
634 // Add result from the processing.
635 mediator
.AddCompletedResponse(Str
);
639 case NpgsqlMessageTypes_Ver_3
.ParseComplete
:
640 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "ParseComplete");
641 // Just read up the message length.
642 PGUtil
.ReadInt32(stream
, inputBuffer
);
643 readyForQuery
= true;
646 case NpgsqlMessageTypes_Ver_3
.BindComplete
:
647 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "BindComplete");
648 // Just read up the message length.
649 PGUtil
.ReadInt32(stream
, inputBuffer
);
650 readyForQuery
= true;
653 case NpgsqlMessageTypes_Ver_3
.EmptyQueryResponse
:
654 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "EmptyQueryResponse");
655 PGUtil
.ReadInt32(stream
, inputBuffer
);
658 case NpgsqlMessageTypes_Ver_3
.NotificationResponse
:
659 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "NotificationResponse");
662 PGUtil
.ReadInt32(stream
, inputBuffer
);
664 // Process ID sending notification
665 Int32 PID
= PGUtil
.ReadInt32(stream
, inputBuffer
);
666 // Notification string
667 String notificationResponse
= PGUtil
.ReadString( stream
, context
.Encoding
);
668 // Additional info, currently not implemented by PG (empty string always), eat it
669 PGUtil
.ReadString( stream
, context
.Encoding
);
670 mediator
.AddNotification(new NpgsqlNotificationEventArgs(PID
, notificationResponse
));
673 // Wait for ReadForQuery message
676 case NpgsqlMessageTypes_Ver_3
.ParameterStatus
:
677 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "ParameterStatus");
678 NpgsqlParameterStatus parameterStatus
= new NpgsqlParameterStatus();
679 parameterStatus
.ReadFromStream(stream
, context
.Encoding
);
681 NpgsqlEventLog
.LogMsg(resman
, "Log_ParameterStatus", LogLevel
.Debug
, parameterStatus
.Parameter
, parameterStatus
.ParameterValue
);
683 mediator
.AddParameterStatus(parameterStatus
.Parameter
, parameterStatus
);
685 if (parameterStatus
.Parameter
== "server_version")
687 // Add this one under our own name so that if the parameter name
688 // changes in a future backend version, we can handle it here in the
689 // protocol handler and leave everybody else put of it.
690 mediator
.AddParameterStatus("__npgsql_server_version", parameterStatus
);
691 // context.ServerVersionString = parameterStatus.ParameterValue;
695 case NpgsqlMessageTypes_Ver_3
.NoData
:
696 // This nodata message may be generated by prepare commands issued with queries which doesn't return rows
697 // for example insert, update or delete.
698 // Just eat the message.
699 NpgsqlEventLog
.LogMsg(resman
, "Log_ProtocolMessage", LogLevel
.Debug
, "ParameterStatus");
700 PGUtil
.ReadInt32(stream
, inputBuffer
);
705 // This could mean a number of things
706 // We've gotten out of sync with the backend?
707 // We need to implement this type?
708 // Backend has gone insane?
710 // what exception should we really throw here?
711 throw new NotSupportedException(String
.Format("Backend sent unrecognized response type: {0}", (Char
)message
));