public override void Authenticate(NpgsqlConnector context, byte[] password) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Authenticate"); NpgsqlPasswordPacket pwpck = new NpgsqlPasswordPacket(password); pwpck.WriteToStream(context.Stream); }
public override void Open(NpgsqlConnector context) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Open"); TcpClient tcpc = new TcpClient(); tcpc.Connect(new IPEndPoint(ResolveIPHost(context.Host), context.Port)); Stream stream = tcpc.GetStream(); // If the PostgreSQL server has SSL connectors enabled Open SslClientStream if (response == 'S') { if (context.SSL) { PGUtil.WriteInt32(stream, 8); PGUtil.WriteInt32(stream,80877103); // Receive response Char response = (Char)stream.ReadByte(); if (response == 'S') { stream = new SslClientStream( tcpc.GetStream(), context.Host, true, Mono.Security.Protocol.Tls.SecurityProtocolType.Default ); ((SslClientStream)stream).ClientCertSelectionDelegate = new CertificateSelectionCallback(context.DefaultCertificateSelectionCallback); ((SslClientStream)stream).ServerCertValidationDelegate = new CertificateValidationCallback(context.DefaultCertificateValidationCallback); ((SslClientStream)stream).PrivateKeyCertSelectionDelegate = new PrivateKeySelectionCallback(context.DefaultPrivateKeySelectionCallback); } } context.Stream = stream; NpgsqlEventLog.LogMsg(resman, "Log_ConnectedTo", LogLevel.Normal, context.Host, context.Port); ChangeState(context, NpgsqlConnectedState.Instance); }
public override void Parse(NpgsqlConnector context, NpgsqlParse parse) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Parse"); BufferedStream stream = new BufferedStream(context.Stream); parse.WriteToStream(stream, context.Encoding); stream.Flush(); }
public override void Close(NpgsqlConnector context) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Close"); Stream stream = context.Stream; try { stream.WriteByte((byte) FrontEndMessageCode.Termination); if (context.BackendProtocolVersion >= ProtocolVersion.Version3) { PGUtil.WriteInt32(stream, 4); } stream.Flush(); } catch { //Error writting termination message to stream, nothing we can do. } try { stream.Close(); } catch { } context.Stream = null; ChangeState(context, NpgsqlClosedState.Instance); }
public override IEnumerable<IServerResponseObject> SyncEnum(NpgsqlConnector context) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Sync"); _syncMessage.WriteToStream(context.Stream); context.Stream.Flush(); return ProcessBackendResponsesEnum(context); }
/// <summary> /// Sends given packet to server as a CopyData message. /// Does not check for notifications! Use another thread for that. /// </summary> public override void SendCopyData(NpgsqlConnector context, byte[] buf, int off, int len) { Stream toServer = context.Stream; toServer.WriteByte((byte) FrontEndMessageCode.CopyData); PGUtil.WriteInt32(toServer, len + 4); toServer.Write(buf, off, len); }
public override void CancelRequest(NpgsqlConnector context) { NpgsqlCancelRequest CancelRequestMessage = new NpgsqlCancelRequest(context.BackEndKeyData); CancelRequestMessage.WriteToStream(context.Stream); context.Stream.Flush(); }
public override void Parse(NpgsqlConnector context, NpgsqlParse parse) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Parse"); Stream stream = context.Stream; parse.WriteToStream(stream); //stream.Flush(); }
public override void Authenticate(NpgsqlConnector context, string password) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Authenticate"); NpgsqlPasswordPacket pwpck = new NpgsqlPasswordPacket(password, context.BackendProtocolVersion); BufferedStream stream = new BufferedStream(context.Stream); pwpck.WriteToStream(stream); stream.Flush(); }
public override void Startup(NpgsqlConnector context,NpgsqlConnectionStringBuilder settings) { NpgsqlStartupPacket startupPacket = new NpgsqlStartupPacket(context.Database, context.UserName, settings); startupPacket.WriteToStream(context.Stream); context.RequireReadyForQuery = false; ProcessAndDiscardBackendResponses(context); }
public override void Bind(NpgsqlConnector context, NpgsqlBind bind) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Bind"); Stream stream = context.Stream; bind.WriteToStream(stream); //stream.Flush(); }
protected override void Dispose(bool disposing) { if (!disposing) { mContext.Close(); mContext = null; } base.Dispose(disposing); }
/// <summary> /// Called from NpgsqlOutStream.Read to read copy data from server. /// </summary> public override byte[] GetCopyData(NpgsqlConnector context) { // polling in COPY would take seconds on Windows foreach (IServerResponseObject obj in ProcessBackendResponses_Ver_3(context)) { if (obj is IDisposable) { (obj as IDisposable).Dispose(); } } return context.Mediator.ReceivedCopyData; }
internal static void ExecuteBlindSuppressTimeout(NpgsqlConnector connector, NpgsqlQuery query) { // Block the notification thread before writing anything to the wire. using (var blocker = connector.BlockNotificationThread()) { // Write the Query message to the wire. connector.Query(query); // Flush, and wait for and discard all responses. connector.ProcessAndDiscardBackendResponses(); } }
public override void Startup(NpgsqlConnector context,NpgsqlConnectionStringBuilder settings) { NpgsqlStartupPacket startupPacket = NpgsqlStartupPacket.BuildStartupPacket(context.BackendProtocolVersion, context.Database, context.UserName, settings); startupPacket.WriteToStream(context.Stream); context.RequireReadyForQuery = false; // This still makes part of the connection stablishment handling. // So we use the connectiontimeout here too. context.Mediator.CommandTimeout = context.ConnectionTimeout; ProcessAndDiscardBackendResponses(context); }
public override void Startup(NpgsqlConnector context) { NpgsqlStartupPacket startupPacket = new NpgsqlStartupPacket(296, //Not used. context.BackendProtocolVersion, context.Database, context.UserName, "", "", ""); startupPacket.WriteToStream( new BufferedStream(context.Stream), context.Encoding ); context.Mediator.RequireReadyForQuery = false; ProcessBackendResponses( context ); }
public override void Startup(NpgsqlConnector context) { NpgsqlStartupPacket startupPacket = new NpgsqlStartupPacket(296, //Not used. context.BackendProtocolVersion, context.Database, context.UserName, "", "", ""); startupPacket.WriteToStream(new BufferedStream(context.Stream)); context.RequireReadyForQuery = false; // This still makes part of the connection stablishment handling. // So we use the connectiontimeout here too. context.Mediator.CommandTimeout = context.ConnectionTimeout; context.Stream.Flush(); ProcessBackendResponses(context); }
private static void ExecuteBlind(NpgsqlConnector connector, NpgsqlQuery query, int timeout) { // Block the notification thread before writing anything to the wire. using (var blocker = connector.BlockNotificationThread()) { // Set statement timeout as needed. connector.SetBackendCommandTimeout(timeout); // Write the Query message to the wire. connector.Query(query); // Flush, and wait for and discard all responses. connector.ProcessAndDiscardBackendResponses(); } }
internal ReadBuffer([CanBeNull] NpgsqlConnector connector, Stream stream, int size, Encoding textEncoding) { if (size < MinimumBufferSize) { throw new ArgumentOutOfRangeException(nameof(size), size, "Buffer size must be at least " + MinimumBufferSize); } Contract.EndContractBlock(); Connector = connector; Underlying = stream; Size = size; _buf = new byte[Size]; TextEncoding = textEncoding; _textDecoder = TextEncoding.GetDecoder(); _tempCharBuf = new char[1024]; _workspace = new byte[8]; }
public void TestNotify(NpgsqlConnector context) { //ZA Hnotifytest CNOTIFY Z //Qlisten notifytest;notify notifytest; Stream stm = context.Stream; // string uuidString = "uuid" + Guid.NewGuid().ToString("N"); string uuidString = string.Format("uuid{0:N}", Guid.NewGuid()); Queue<byte> buffer = new Queue<byte>(); byte[] convertBuffer = new byte[36]; PGUtil.WriteStringNullTerminated(stm, "Qlisten {0};notify {0};", uuidString); for (;;) { int newByte = stm.ReadByte(); if (newByte == -1) { throw new EndOfStreamException(); } buffer.Enqueue((byte) newByte); if (buffer.Count > 35) { buffer.CopyTo(convertBuffer, 0); if (BackendEncoding.UTF8Encoding.GetString(convertBuffer) == uuidString) { for (;;) { switch (stm.ReadByte()) { case -1: throw new EndOfStreamException(); case 'Z': //context.Query(new NpgsqlCommand("UNLISTEN *", context)); NpgsqlCommand.ExecuteBlind(context, "UNLISTEN *"); return; } } } else { buffer.Dequeue(); } } } }
public override IEnumerable<IServerResponseObject> QueryEnum(NpgsqlConnector context, NpgsqlCommand command) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "QueryEnum"); //String commandText = command.GetCommandText(); //NpgsqlEventLog.LogMsg(resman, "Log_QuerySent", LogLevel.Debug, commandText); // Send the query request to backend. NpgsqlQuery query = new NpgsqlQuery(command, context.BackendProtocolVersion); query.WriteToStream(context.Stream); context.Stream.Flush(); return ProcessBackendResponsesEnum(context); }
/// <summary> /// Called from NpgsqlState.ProcessBackendResponses upon CopyOutResponse. /// If CopyStream is already set, it is used to write data received from server, after which the copy ends. /// Otherwise CopyStream is set to a readable NpgsqlCopyOutStream that receives data from server. /// </summary> protected override void StartCopy(NpgsqlConnector context, NpgsqlCopyFormat copyFormat) { _copyFormat = copyFormat; Stream userFeed = context.Mediator.CopyStream; if (userFeed == null) { context.Mediator.CopyStream = new NpgsqlCopyOutStream(context); } else { byte[] buf; while ((buf = GetCopyData(context)) != null) { userFeed.Write(buf, 0, buf.Length); } userFeed.Close(); } }
/// <summary> /// Special adaptation of ExecuteBlind() that sets statement_timeout. /// This exists to prevent Connector.SetBackendCommandTimeout() from calling Command.ExecuteBlind(), /// which will cause an endless recursive loop. /// </summary> /// <param name="connector"></param> /// <param name="timeout">Timeout in seconds.</param> internal static void ExecuteSetStatementTimeoutBlind(NpgsqlConnector connector, int timeout) { NpgsqlQuery query; // Optimize for a few common timeout values. switch (timeout) { case 10 : query = NpgsqlQuery.SetStmtTimeout10Sec; break; case 20 : query = NpgsqlQuery.SetStmtTimeout20Sec; break; case 30 : query = NpgsqlQuery.SetStmtTimeout30Sec; break; case 60 : query = NpgsqlQuery.SetStmtTimeout60Sec; break; case 90 : query = NpgsqlQuery.SetStmtTimeout90Sec; break; case 120 : query = NpgsqlQuery.SetStmtTimeout120Sec; break; default : query = new NpgsqlQuery(string.Format("SET statement_timeout = {0}", timeout * 1000)); break; } // Write the Query message to the wire. connector.Query(query); // Flush, and wait for and discard all responses. connector.ProcessAndDiscardBackendResponses(); }
public override void Query( NpgsqlConnector context, NpgsqlCommand command ) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Query"); //String commandText = command.GetCommandText(); //NpgsqlEventLog.LogMsg(resman, "Log_QuerySent", LogLevel.Debug, commandText); // Send the query request to backend. NpgsqlQuery query = new NpgsqlQuery(command, context.BackendProtocolVersion); query.WriteToStream(context.Stream, context.Encoding); context.Stream.Flush(); ProcessBackendResponses(context); }
/// <summary> /// Called from NpgsqlState.ProcessBackendResponses upon CopyInResponse. /// If CopyStream is already set, it is used to read data to push to server, after which the copy is completed. /// Otherwise CopyStream is set to a writable NpgsqlCopyInStream that calls SendCopyData each time it is written to. /// </summary> protected override void StartCopy(NpgsqlConnector context, NpgsqlCopyFormat copyFormat) { _copyFormat = copyFormat; Stream userFeed = context.Mediator.CopyStream; if (userFeed == null) { context.Mediator.CopyStream = new NpgsqlCopyInStream(context); } else { // copy all of user feed to server at once int bufsiz = context.Mediator.CopyBufferSize; byte[] buf = new byte[bufsiz]; int len; while ((len = userFeed.Read(buf, 0, bufsiz)) > 0) { SendCopyData(context, buf, 0, len); } SendCopyDone(context); } }
internal NpgsqlRawCopyStream(NpgsqlConnector connector, string copyCommand) { _connector = connector; _buf = connector.Buffer; _connector.SendSingleMessage(new QueryMessage(copyCommand)); var msg = _connector.ReadSingleMessage(); switch (msg.Code) { case BackendMessageCode.CopyInResponse: var copyInResponse = (CopyInResponseMessage) msg; IsBinary = copyInResponse.IsBinary; _canWrite = true; break; case BackendMessageCode.CopyOutResponse: var copyOutResponse = (CopyOutResponseMessage) msg; IsBinary = copyOutResponse.IsBinary; _canRead = true; break; default: throw _connector.UnexpectedMessageReceived(msg.Code); } }
internal NpgsqlDataReader(IEnumerable<IServerResponseObject> dataEnumeration, CommandBehavior behavior, NpgsqlCommand command, NpgsqlConnector.NotificationThreadBlock threadBlock, bool preparedStatement = false, NpgsqlRowDescription rowDescription = null) { _behavior = behavior; _connection = (_command = command).Connection; _connector = command.Connector; _dataEnumerator = dataEnumeration.GetEnumerator(); _connector.CurrentReader = this; _threadBlock = threadBlock; _preparedStatement = preparedStatement; CurrentDescription = rowDescription; // For un-prepared statements, the first response is always a row description. // For prepared statements, we may be recycling a row description from a previous Execute. if (CurrentDescription == null) { NextResultInternal(); } UpdateOutputParameters(); }
internal NpgsqlRawCopyStream(NpgsqlConnector connector, string copyCommand) { _connector = connector; _readBuf = connector.ReadBuffer; _writeBuf = connector.WriteBuffer; _connector.SendQuery(copyCommand); var msg = _connector.ReadMessage(DataRowLoadingMode.NonSequential); switch (msg.Code) { case BackendMessageCode.CopyInResponse: var copyInResponse = (CopyInResponseMessage) msg; IsBinary = copyInResponse.IsBinary; _canWrite = true; break; case BackendMessageCode.CopyOutResponse: var copyOutResponse = (CopyOutResponseMessage) msg; IsBinary = copyOutResponse.IsBinary; _canRead = true; break; default: throw _connector.UnexpectedMessageReceived(msg.Code); } }
public virtual void Bind(NpgsqlConnector context, NpgsqlBind bind) { throw new InvalidOperationException("Internal Error! " + this); }
public virtual void Describe(NpgsqlConnector context, NpgsqlDescribe describe) { throw new InvalidOperationException("Internal Error! " + this); }
public virtual byte[] GetCopyData(NpgsqlConnector context) { throw new InvalidOperationException("Internal Error! " + this); }
public virtual void SendCopyFail(NpgsqlConnector context, String message) { throw new InvalidOperationException("Internal Error! " + this); }
///<summary> /// This method is responsible to handle all protocol messages sent from the backend. /// It holds all the logic to do it. /// To exchange data, it uses a Mediator object from which it reads/writes information /// to handle backend requests. /// </summary> /// internal void ProcessBackendResponses(NpgsqlConnector context) { IterateThroughAllResponses(ProcessBackendResponsesEnum(context, false)); }
internal void Clear() { _connector = null; Connection = null; }
public override void Describe(NpgsqlConnector context, NpgsqlDescribe describe) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Describe"); describe.WriteToStream(context.Stream); //context.Stream.Flush(); }
///<summary> /// This method is responsible to handle all protocol messages sent from the backend. /// It holds all the logic to do it. /// To exchange data, it uses a Mediator object from which it reads/writes information /// to handle backend requests. /// </summary> /// internal IEnumerable <IServerResponseObject> ProcessBackendResponsesEnum( NpgsqlConnector context, bool cancelRequestCalled) { try { // Process commandTimeout behavior. if ((context.Mediator.CommandTimeout > 0) && (!CheckForContextSocketAvailability(context, SelectMode.SelectRead))) { // If timeout occurs when establishing the session with server then // throw an exception instead of trying to cancel query. This helps to prevent loop as CancelRequest will also try to stablish a connection and sends commands. if (!((this is NpgsqlStartupState || this is NpgsqlConnectedState || cancelRequestCalled))) { try { context.CancelRequest(); foreach (IServerResponseObject obj in ProcessBackendResponsesEnum(context, true)) { if (obj is IDisposable) { (obj as IDisposable).Dispose(); } } } catch (Exception ex) { } //We should have gotten an error from CancelRequest(). Whether we did or not, what we //really have is a timeout exception, and that will be less confusing to the user than //"operation cancelled by user" or similar, so whatever the case, that is what we'll throw. // Changed message again to report about the two possible timeouts: connection or command as the establishment timeout only was confusing users when the timeout was a command timeout. } throw new NpgsqlException(resman.GetString("Exception_ConnectionOrCommandTimeout")); } switch (context.BackendProtocolVersion) { case ProtocolVersion.Version2: return(ProcessBackendResponses_Ver_2(context)); case ProtocolVersion.Version3: return(ProcessBackendResponses_Ver_3(context)); default: throw new NpgsqlException(resman.GetString("Exception_UnknownProtocol")); } } catch (ThreadAbortException) { try { context.CancelRequest(); context.Close(); } catch { } throw; } }
public virtual IEnumerable <IServerResponseObject> SyncEnum(NpgsqlConnector context) { throw new InvalidOperationException("Internal Error! " + this); }
public virtual void Flush(NpgsqlConnector context) { throw new InvalidOperationException("Internal Error! " + this); }
protected IEnumerable <IServerResponseObject> ProcessBackendResponses_Ver_2(NpgsqlConnector context) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ProcessBackendResponses"); using (new ContextResetter(context)) { Stream stream = context.Stream; NpgsqlMediator mediator = context.Mediator; NpgsqlRowDescription lastRowDescription = null; List <NpgsqlError> errors = new List <NpgsqlError>(); for (; ;) { // Check the first Byte of response. switch ((BackEndMessageCode)stream.ReadByte()) { case BackEndMessageCode.ErrorResponse: { NpgsqlError error = new NpgsqlError(context.BackendProtocolVersion, stream); error.ErrorSql = mediator.SqlSent; errors.Add(error); NpgsqlEventLog.LogMsg(resman, "Log_ErrorResponse", LogLevel.Debug, error.Message); } // Return imediately if it is in the startup state or connected state as // there is no more messages to consume. // Possible error in the NpgsqlStartupState: // Invalid password. // Possible error in the NpgsqlConnectedState: // No pg_hba.conf configured. if (!context.RequireReadyForQuery) { throw new NpgsqlException(errors); } break; case BackEndMessageCode.AuthenticationRequest: NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "AuthenticationRequest"); AuthenticationRequestType authType = (AuthenticationRequestType)PGUtil.ReadInt32(stream); switch (authType) { case AuthenticationRequestType.AuthenticationOk: NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationOK", LogLevel.Debug); break; case AuthenticationRequestType.AuthenticationClearTextPassword: NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationClearTextRequest", LogLevel.Debug); // Send the PasswordPacket. ChangeState(context, NpgsqlStartupState.Instance); context.Authenticate(context.Password); break; case AuthenticationRequestType.AuthenticationMD5Password: NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationMD5Request", LogLevel.Debug); // Now do the "MD5-Thing" // for this the Password has to be: // 1. md5-hashed with the username as salt // 2. md5-hashed again with the salt we get from the backend MD5 md5 = MD5.Create(); // 1. byte[] passwd = context.Password; byte[] saltUserName = ENCODING_UTF8.GetBytes(context.UserName); byte[] crypt_buf = new byte[passwd.Length + saltUserName.Length]; passwd.CopyTo(crypt_buf, 0); saltUserName.CopyTo(crypt_buf, passwd.Length); StringBuilder sb = new StringBuilder(); byte[] hashResult = md5.ComputeHash(crypt_buf); foreach (byte b in hashResult) { sb.Append(b.ToString("x2")); } String prehash = sb.ToString(); byte[] prehashbytes = ENCODING_UTF8.GetBytes(prehash); byte[] saltServer = new byte[4]; stream.Read(saltServer, 0, 4); // Send the PasswordPacket. ChangeState(context, NpgsqlStartupState.Instance); // 2. crypt_buf = new byte[prehashbytes.Length + saltServer.Length]; prehashbytes.CopyTo(crypt_buf, 0); saltServer.CopyTo(crypt_buf, prehashbytes.Length); sb = new StringBuilder("md5"); // This is needed as the backend expects md5 result starts with "md5" hashResult = md5.ComputeHash(crypt_buf); foreach (byte b in hashResult) { sb.Append(b.ToString("x2")); } context.Authenticate(ENCODING_UTF8.GetBytes(sb.ToString())); break; default: // Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now. errors.Add( new NpgsqlError(context.BackendProtocolVersion, String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType))); throw new NpgsqlException(errors); } break; case BackEndMessageCode.RowDescription: yield return(lastRowDescription = new NpgsqlRowDescriptionV2(stream, context.OidToNameMapping, context.CompatVersion)); ; break; case BackEndMessageCode.DataRow: yield return(new ForwardsOnlyRow(new StringRowReaderV2(lastRowDescription, stream))); break; case BackEndMessageCode.BinaryRow: throw new NotSupportedException(); case BackEndMessageCode.ReadyForQuery: ChangeState(context, NpgsqlReadyState.Instance); if (errors.Count != 0) { throw new NpgsqlException(errors); } yield break; case BackEndMessageCode.BackendKeyData: context.BackEndKeyData = new NpgsqlBackEndKeyData(context.BackendProtocolVersion, stream); break; case BackEndMessageCode.NoticeResponse: context.FireNotice(new NpgsqlError(context.BackendProtocolVersion, stream)); break; case BackEndMessageCode.CompletedResponse: yield return(new CompletedResponse(stream)); break; case BackEndMessageCode.CursorResponse: // This is the cursor response message. // It is followed by a C NULL terminated string with the name of // the cursor in a FETCH case or 'blank' otherwise. // In this case it should be always 'blank'. // [FIXME] Get another name for this function. NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "CursorResponse"); String cursorName = PGUtil.ReadString(stream); // Continue waiting for ReadyForQuery message. break; case BackEndMessageCode.EmptyQueryResponse: NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "EmptyQueryResponse"); PGUtil.ReadString(stream); break; case BackEndMessageCode.NotificationResponse: context.FireNotification(new NpgsqlNotificationEventArgs(stream, false)); if (context.IsNotificationThreadRunning) { yield break; } break; case BackEndMessageCode.IO_ERROR: // Connection broken. Mono returns -1 instead of throw an exception as ms.net does. throw new IOException(); default: // This could mean a number of things // We've gotten out of sync with the backend? // We need to implement this type? // Backend has gone insane? throw new DataException("Backend sent unrecognized response type"); } } } }
public override void Describe(NpgsqlConnector context, NpgsqlDescribe describe) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Describe"); describe.WriteToStream(context.Stream); }
public void Query(NpgsqlConnector context, NpgsqlCommand command) { IterateThroughAllResponses(QueryEnum(context, command)); }
protected IEnumerable <IServerResponseObject> ProcessBackendResponses_Ver_3(NpgsqlConnector context) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ProcessBackendResponses"); using (new ContextResetter(context)) { Stream stream = context.Stream; NpgsqlMediator mediator = context.Mediator; NpgsqlRowDescription lastRowDescription = null; List <NpgsqlError> errors = new List <NpgsqlError>(); for (; ;) { // Check the first Byte of response. BackEndMessageCode message = (BackEndMessageCode)stream.ReadByte(); switch (message) { case BackEndMessageCode.ErrorResponse: NpgsqlError error = new NpgsqlError(context.BackendProtocolVersion, stream); error.ErrorSql = mediator.SqlSent; errors.Add(error); NpgsqlEventLog.LogMsg(resman, "Log_ErrorResponse", LogLevel.Debug, error.Message); // Return imediately if it is in the startup state or connected state as // there is no more messages to consume. // Possible error in the NpgsqlStartupState: // Invalid password. // Possible error in the NpgsqlConnectedState: // No pg_hba.conf configured. if (!context.RequireReadyForQuery) { throw new NpgsqlException(errors); } break; case BackEndMessageCode.AuthenticationRequest: NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "AuthenticationRequest"); // Get the length in case we're getting AuthenticationGSSContinue int authDataLength = PGUtil.ReadInt32(stream) - 8; AuthenticationRequestType authType = (AuthenticationRequestType)PGUtil.ReadInt32(stream); switch (authType) { case AuthenticationRequestType.AuthenticationOk: NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationOK", LogLevel.Debug); break; case AuthenticationRequestType.AuthenticationClearTextPassword: NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationClearTextRequest", LogLevel.Debug); // Send the PasswordPacket. ChangeState(context, NpgsqlStartupState.Instance); context.Authenticate(context.Password); break; case AuthenticationRequestType.AuthenticationMD5Password: NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationMD5Request", LogLevel.Debug); // Now do the "MD5-Thing" // for this the Password has to be: // 1. md5-hashed with the username as salt // 2. md5-hashed again with the salt we get from the backend MD5 md5 = MD5.Create(); // 1. byte[] passwd = context.Password; byte[] saltUserName = ENCODING_UTF8.GetBytes(context.UserName); byte[] crypt_buf = new byte[passwd.Length + saltUserName.Length]; passwd.CopyTo(crypt_buf, 0); saltUserName.CopyTo(crypt_buf, passwd.Length); StringBuilder sb = new StringBuilder(); byte[] hashResult = md5.ComputeHash(crypt_buf); foreach (byte b in hashResult) { sb.Append(b.ToString("x2")); } String prehash = sb.ToString(); byte[] prehashbytes = ENCODING_UTF8.GetBytes(prehash); crypt_buf = new byte[prehashbytes.Length + 4]; stream.Read(crypt_buf, prehashbytes.Length, 4); // Send the PasswordPacket. ChangeState(context, NpgsqlStartupState.Instance); // 2. prehashbytes.CopyTo(crypt_buf, 0); sb = new StringBuilder("md5"); // This is needed as the backend expects md5 result starts with "md5" hashResult = md5.ComputeHash(crypt_buf); foreach (byte b in hashResult) { sb.Append(b.ToString("x2")); } context.Authenticate(ENCODING_UTF8.GetBytes(sb.ToString())); break; #if WINDOWS && UNMANAGED case AuthenticationRequestType.AuthenticationSSPI: { if (context.IntegratedSecurity) { // For SSPI we have to get the IP-Address (hostname doesn't work) string ipAddressString = ((IPEndPoint)context.Socket.RemoteEndPoint).Address.ToString(); context.SSPI = new SSPIHandler(ipAddressString, "POSTGRES"); ChangeState(context, NpgsqlStartupState.Instance); context.Authenticate(context.SSPI.Continue(null)); break; } else { // TODO: correct exception throw new Exception(); } } case AuthenticationRequestType.AuthenticationGSSContinue: { byte[] authData = new byte[authDataLength]; PGUtil.CheckedStreamRead(stream, authData, 0, authDataLength); byte[] passwd_read = context.SSPI.Continue(authData); if (passwd_read.Length != 0) { context.Authenticate(passwd_read); } break; } #endif default: // Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now. errors.Add( new NpgsqlError(context.BackendProtocolVersion, String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType))); throw new NpgsqlException(errors); } break; case BackEndMessageCode.RowDescription: yield return(lastRowDescription = new NpgsqlRowDescriptionV3(stream, context.OidToNameMapping, context.CompatVersion)); break; case BackEndMessageCode.ParameterDescription: // Do nothing,for instance, just read... int length = PGUtil.ReadInt32(stream); int nb_param = PGUtil.ReadInt16(stream); //WTF for (int i = 0; i < nb_param; i++) { int typeoid = PGUtil.ReadInt32(stream); } break; case BackEndMessageCode.DataRow: yield return(new ForwardsOnlyRow(new StringRowReaderV3(lastRowDescription, stream))); break; case BackEndMessageCode.ReadyForQuery: NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "ReadyForQuery"); // Possible status bytes returned: // I = Idle (no transaction active). // T = In transaction, ready for more. // E = Error in transaction, queries will fail until transaction aborted. // Just eat the status byte, we have no use for it at this time. PGUtil.ReadInt32(stream); stream.ReadByte(); ChangeState(context, NpgsqlReadyState.Instance); if (errors.Count != 0) { throw new NpgsqlException(errors); } yield break; case BackEndMessageCode.BackendKeyData: NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "BackendKeyData"); // BackendKeyData message. NpgsqlBackEndKeyData backend_keydata = new NpgsqlBackEndKeyData(context.BackendProtocolVersion, stream); context.BackEndKeyData = backend_keydata; // Wait for ReadForQuery message break; case BackEndMessageCode.NoticeResponse: // Notices and errors are identical except that we // just throw notices away completely ignored. context.FireNotice(new NpgsqlError(context.BackendProtocolVersion, stream)); break; case BackEndMessageCode.CompletedResponse: PGUtil.ReadInt32(stream); yield return(new CompletedResponse(stream)); break; case BackEndMessageCode.ParseComplete: NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "ParseComplete"); // Just read up the message length. PGUtil.ReadInt32(stream); yield break; case BackEndMessageCode.BindComplete: NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "BindComplete"); // Just read up the message length. PGUtil.ReadInt32(stream); yield break; case BackEndMessageCode.EmptyQueryResponse: NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "EmptyQueryResponse"); PGUtil.ReadInt32(stream); break; case BackEndMessageCode.NotificationResponse: // Eat the length PGUtil.ReadInt32(stream); context.FireNotification(new NpgsqlNotificationEventArgs(stream, true)); if (context.IsNotificationThreadRunning) { yield break; } break; case BackEndMessageCode.ParameterStatus: NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "ParameterStatus"); NpgsqlParameterStatus parameterStatus = new NpgsqlParameterStatus(stream); NpgsqlEventLog.LogMsg(resman, "Log_ParameterStatus", LogLevel.Debug, parameterStatus.Parameter, parameterStatus.ParameterValue); context.AddParameterStatus(parameterStatus); if (parameterStatus.Parameter == "server_version") { // Deal with this here so that if there are // changes in a future backend version, we can handle it here in the // protocol handler and leave everybody else put of it. string versionString = parameterStatus.ParameterValue.Trim(); for (int idx = 0; idx != versionString.Length; ++idx) { char c = parameterStatus.ParameterValue[idx]; if (!char.IsDigit(c) && c != '.') { versionString = versionString.Substring(0, idx); break; } } context.ServerVersion = new Version(versionString); } break; case BackEndMessageCode.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); break; case BackEndMessageCode.CopyInResponse: // Enter COPY sub protocol and start pushing data to server NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "CopyInResponse"); ChangeState(context, NpgsqlCopyInState.Instance); PGUtil.ReadInt32(stream); // length redundant context.CurrentState.StartCopy(context, ReadCopyHeader(stream)); yield break; // Either StartCopy called us again to finish the operation or control should be passed for user to feed copy data case BackEndMessageCode.CopyOutResponse: // Enter COPY sub protocol and start pulling data from server NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "CopyOutResponse"); ChangeState(context, NpgsqlCopyOutState.Instance); PGUtil.ReadInt32(stream); // length redundant context.CurrentState.StartCopy(context, ReadCopyHeader(stream)); yield break; // Either StartCopy called us again to finish the operation or control should be passed for user to feed copy data case BackEndMessageCode.CopyData: NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "CopyData"); Int32 len = PGUtil.ReadInt32(stream) - 4; byte[] buf = new byte[len]; PGUtil.ReadBytes(stream, buf, 0, len); context.Mediator.ReceivedCopyData = buf; yield break; // read data from server one chunk at a time while staying in copy operation mode case BackEndMessageCode.CopyDone: NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "CopyDone"); PGUtil.ReadInt32(stream); // CopyDone can not have content so this is always 4 // This will be followed by normal CommandComplete + ReadyForQuery so no op needed break; case BackEndMessageCode.IO_ERROR: // Connection broken. Mono returns -1 instead of throwing an exception as ms.net does. throw new IOException(); default: // This could mean a number of things // We've gotten out of sync with the backend? // We need to implement this type? // Backend has gone insane? // FIXME // what exception should we really throw here? throw new NotSupportedException(String.Format("Backend sent unrecognized response type: {0}", (Char)message)); } } } }
/* * /// <summary> * /// Find an available shared connector in the shared pool, or create * /// a new one if none found. * /// </summary> * private NpgsqlConnector GetSharedConnector(NpgsqlConnection Connection) * { * // To be implemented * * return null; * } */ /// <summary> /// Put a pooled connector into the pool queue. /// </summary> /// <param name="Connector">Connector to pool</param> private void UngetConnector(NpgsqlConnection Connection, NpgsqlConnector Connector) { ConnectorQueue queue; // Find the queue. // As we are handling all possible queues, we have to lock everything... lock (locker) { PooledConnectors.TryGetValue(Connection.ConnectionString, out queue); } if (queue == null) { Connector.Close(); // Release connection to postgres return; // Queue may be emptied by connection problems. See ClearPool below. } Connector.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate; Connector.CertificateSelectionCallback -= Connection.CertificateSelectionCallbackDelegate; Connector.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate; Connector.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate; bool inQueue = false; lock (queue) { inQueue = queue.Busy.ContainsKey(Connector); queue.Busy.Remove(Connector); } if (!Connector.IsInitialized) { if (Connector.Transaction != null) { Connector.Transaction.Cancel(); } Connector.Close(); } else { if (Connector.Transaction != null) { try { Connector.Transaction.Rollback(); } catch { Connector.Close(); } } } if (Connector.State == ConnectionState.Open) { //If thread is good if ((Thread.CurrentThread.ThreadState & (ThreadState.Aborted | ThreadState.AbortRequested)) == 0) { // Release all resources associated with this connector. try { Connector.ReleaseResources(); } catch (Exception) { //If the connector fails to release its resources then it is probably broken, so make sure we don't add it to the queue. // Usually it already won't be in the queue as it would of broken earlier inQueue = false; } if (inQueue) { lock (queue) { queue.Available.Enqueue(Connector); } } else { Connector.Close(); } } else { //Thread is being aborted, this connection is possibly broken. So kill it rather than returning it to the pool Connector.Close(); } } }
/// <summary> /// Find an available pooled connector in the non-shared pool, or create /// a new one if none found. /// </summary> private NpgsqlConnector GetPooledConnector(NpgsqlConnection Connection) { ConnectorQueue Queue; NpgsqlConnector Connector = null; // Try to find a queue. if (!PooledConnectors.TryGetValue(Connection.ConnectionString, out Queue)) { Queue = new ConnectorQueue(); Queue.ConnectionLifeTime = Connection.ConnectionLifeTime; Queue.MinPoolSize = Connection.MinPoolSize; PooledConnectors[Connection.ConnectionString] = Queue; } // Fix queue use count. Use count may be dropped below zero if Queue was cleared and there were connections open. if (Queue.UseCount < 0) { Queue.UseCount = 0; } if (Queue.Count > 0) { // Found a queue with connectors. Grab the top one. // Check if the connector is still valid. Connector = Queue.Dequeue(); /*try * { * Connector.TestConnector(); * Connector.RequireReadyForQuery = true; * } * catch //This connector is broken! * { * try * { * Connector.Close(); * } * catch * { * try * { * Connector.Stream.Close(); * } * catch * { * } * } * return GetPooledConnector(Connection); //Try again * }*/ if (!Connector.IsValid()) { try { Connector.Close(); } catch { try { Connector.Stream.Close(); } catch { } } return(GetPooledConnector(Connection)); //Try again } Queue.UseCount++; } else if (Queue.Count + Queue.UseCount < Connection.MaxPoolSize) { Connector = CreateConnector(Connection); Connector.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate; Connector.CertificateSelectionCallback += Connection.CertificateSelectionCallbackDelegate; Connector.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate; Connector.PrivateKeySelectionCallback += Connection.PrivateKeySelectionCallbackDelegate; try { Connector.Open(); } catch { try { Connector.Close(); } catch { } throw; } Queue.UseCount++; } // Meet the MinPoolSize requirement if needed. if (Connection.MinPoolSize > 0) { while (Queue.Count + Queue.UseCount < Connection.MinPoolSize) { NpgsqlConnector Spare = CreateConnector(Connection); Spare.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate; Spare.CertificateSelectionCallback += Connection.CertificateSelectionCallbackDelegate; Spare.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate; Spare.PrivateKeySelectionCallback += Connection.PrivateKeySelectionCallbackDelegate; Spare.Open(); Spare.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate; Spare.CertificateSelectionCallback -= Connection.CertificateSelectionCallbackDelegate; Spare.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate; Spare.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate; Queue.Enqueue(Spare); } } return(Connector); }
public ContextResetter(NpgsqlConnector connector) { _connector = connector; }
internal GSSPasswordMessageStream(NpgsqlConnector connector) { _connector = connector; _msg = new PasswordMessage(); }
///<summary> ///This method is used by the states to change the state of the context. /// </summary> protected static void ChangeState(NpgsqlConnector context, NpgsqlState newState) { context.CurrentState = newState; }
public NotificationThreadBlock(NpgsqlConnector connector) { (_connector = connector).StopNotificationThread(); }
public virtual void SendCopyData(NpgsqlConnector context, byte[] buf, int off, int len) { throw new InvalidOperationException("Internal Error! " + this); }
internal NpgsqlContextHolder(NpgsqlConnector connector, NpgsqlState state) { this.connector = connector; this.state = state; }
// COPY methods protected virtual void StartCopy(NpgsqlConnector context, NpgsqlCopyFormat copyFormat) { throw new InvalidOperationException("Internal Error! " + this); }
internal async ValueTask <NpgsqlConnector> AllocateLong(NpgsqlConnection conn, NpgsqlTimeout timeout, bool async, CancellationToken cancellationToken) { Debug.Assert(Monitor.IsEntered(this)); NpgsqlConnector connector; Debug.Assert(Busy <= _max); if (Busy == _max) { // TODO: Async cancellation var tcs = new TaskCompletionSource <NpgsqlConnector>(); _waiting.Enqueue(new WaitingOpenAttempt { TaskCompletionSource = tcs, IsAsync = async }); Monitor.Exit(this); try { if (async) { if (timeout.IsSet) { var timeLeft = timeout.TimeLeft; if (timeLeft <= TimeSpan.Zero || tcs.Task != await Task.WhenAny(tcs.Task, Task.Delay(timeLeft))) { throw new NpgsqlException($"The connection pool has been exhausted, either raise MaxPoolSize (currently {_max}) or Timeout (currently {Settings.Timeout} seconds)"); } } else { await tcs.Task; } } else { if (timeout.IsSet) { var timeLeft = timeout.TimeLeft; if (timeLeft <= TimeSpan.Zero || !tcs.Task.Wait(timeLeft)) { throw new NpgsqlException($"The connection pool has been exhausted, either raise MaxPoolSize (currently {_max}) or Timeout (currently {Settings.Timeout} seconds)"); } } else { tcs.Task.Wait(); } } } catch { // We're here if the timeout expired or the cancellation token was triggered // Re-lock and check in case the task was set to completed after coming out of the Wait lock (this) { if (!tcs.Task.IsCompleted) { tcs.SetCanceled(); throw; } } } connector = tcs.Task.Result; connector.Connection = conn; return(connector); } // No idle connectors are available, and we're under the pool's maximum capacity. IncrementBusy(); Monitor.Exit(this); try { connector = new NpgsqlConnector(conn) { ClearCounter = _clearCounter }; await connector.Open(timeout, async, cancellationToken); Counters.NumberOfPooledConnections.Increment(); EnsureMinPoolSize(conn); return(connector); } catch { lock (this) DecrementBusy(); throw; } }
public virtual void Execute(NpgsqlConnector context, NpgsqlExecute execute) { throw new InvalidOperationException("Internal Error! " + this); }
internal void Release(NpgsqlConnector connector) { // If Clear/ClearAll has been been called since this connector was first opened, // throw it away. if (connector.ClearCounter < _clearCounter) { try { connector.Close(); } catch (Exception e) { Log.Warn("Exception while closing outdated connector", e, connector.Id); } lock (this) DecrementBusy(); Counters.SoftDisconnectsPerSecond.Increment(); Counters.NumberOfPooledConnections.Decrement(); return; } if (connector.IsBroken) { lock (this) DecrementBusy(); Counters.NumberOfPooledConnections.Decrement(); return; } connector.Reset(); lock (this) { // If there are any pending open attempts in progress hand the connector off to // them directly. while (_waiting.Count > 0) { var waitingOpenAttempt = _waiting.Dequeue(); var tcs = waitingOpenAttempt.TaskCompletionSource; // Some attempts may be in the queue but in cancelled state, since they've already timed out. // Simply dequeue these and move on. if (tcs.Task.IsCanceled) { continue; } // We have a pending open attempt. "Complete" it, handing off the connector. if (waitingOpenAttempt.IsAsync) { // If the waiting open attempt is asynchronous (i.e. OpenAsync()), we can't simply // call SetResult on its TaskCompletionSource, since it would execute the open's // continuation in our thread (the closing thread). Instead we schedule the completion // to run in the TP // We copy tcs2 and especially connector2 to avoid allocations caused by the closure, see // http://stackoverflow.com/questions/41507166/closure-heap-allocation-happening-at-start-of-method var tcs2 = tcs; var connector2 = connector; Task.Run(() => tcs2.SetResult(connector2)); } else { tcs.SetResult(connector); } return; } Idle.Push(connector); DecrementBusy(); EnsurePruningTimerState(); Debug.Assert(Idle.Count <= _max); } }
private void CleanUpConnector(NpgsqlConnection Connection, NpgsqlConnector Connector) { new CleanUpConnectorDel(CleanUpConnectorMethod).BeginInvoke(Connection, Connector, null, null); }
/// <summary> /// Find an available pooled connector in the non-shared pool, or create /// a new one if none found. /// </summary> private NpgsqlConnector GetPooledConnector(NpgsqlConnection Connection) { ConnectorQueue Queue; NpgsqlConnector Connector = null; // We only need to lock all pools when trying to get one pool or create one. lock (locker) { // Try to find a queue. if (!PooledConnectors.TryGetValue(Connection.ConnectionString, out Queue)) { Queue = new ConnectorQueue(); Queue.ConnectionLifeTime = Connection.ConnectionLifeTime; Queue.MinPoolSize = Connection.MinPoolSize; PooledConnectors[Connection.ConnectionString] = Queue; } } // Now we can simply lock on the pool itself. lock (Queue) { if (Queue.Available.Count > 0) { // Found a queue with connectors. Grab the top one. // Check if the connector is still valid. Connector = Queue.Available.Dequeue(); Queue.Busy.Add(Connector, null); } } if (Connector != null) { if (!Connector.IsValid()) { lock (Queue) { Queue.Busy.Remove(Connector); } Connector.Close(); return(GetPooledConnector(Connection)); //Try again } return(Connector); } lock (Queue) { if (Queue.Available.Count + Queue.Busy.Count < Connection.MaxPoolSize) { Connector = new NpgsqlConnector(Connection); Queue.Busy.Add(Connector, null); } } if (Connector != null) { Connector.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate; Connector.CertificateSelectionCallback += Connection.CertificateSelectionCallbackDelegate; Connector.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate; Connector.PrivateKeySelectionCallback += Connection.PrivateKeySelectionCallbackDelegate; try { Connector.Open(); } catch { lock (Queue) { Queue.Busy.Remove(Connector); } Connector.Close(); throw; } // Meet the MinPoolSize requirement if needed. if (Connection.MinPoolSize > 1) { lock (Queue) { while (Queue.Available.Count + Queue.Busy.Count < Connection.MinPoolSize) { NpgsqlConnector Spare = new NpgsqlConnector(Connection); Spare.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate; Spare.CertificateSelectionCallback += Connection.CertificateSelectionCallbackDelegate; Spare.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate; Spare.PrivateKeySelectionCallback += Connection.PrivateKeySelectionCallbackDelegate; Spare.Open(); Spare.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate; Spare.CertificateSelectionCallback -= Connection.CertificateSelectionCallbackDelegate; Spare.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate; Spare.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate; Queue.Available.Enqueue(Spare); } } } } return(Connector); }
public virtual void FunctionCall(NpgsqlConnector context, NpgsqlCommand command) { throw new InvalidOperationException("Internal Error! " + this); }
public virtual void Authenticate(NpgsqlConnector context, byte[] password) { throw new InvalidOperationException("Internal Error! " + this); }
public override void Execute(NpgsqlConnector context, NpgsqlExecute execute) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Execute"); execute.WriteToStream(context.Stream); }
public virtual void Parse(NpgsqlConnector context, NpgsqlParse parse) { throw new InvalidOperationException("Internal Error! " + this); }