private async Task WriteExecFinishAndProcess <TState, TResult>( TState initialState, Func <TState, TResult> resultFactory, Action <TResult, ReadBuffer, int, int> columnBinder) { await WriteExecFinish(); await _readBuffer.ReceiveAsync(); read: var message = _readBuffer.ReadMessage(); switch (message.Type) { case MessageType.BindComplete: goto read; case MessageType.DataRow: { var result = resultFactory != null ? resultFactory(initialState) : default; var columns = _readBuffer.ReadShort(); for (var i = 0; i < columns; i++) { var length = _readBuffer.ReadInt(); columnBinder(result, _readBuffer, i, length); } goto read; } case MessageType.CommandComplete: return; case MessageType.ErrorResponse: throw new InvalidOperationException(_readBuffer.ReadErrorMessage()); default: throw new NotImplementedException(message.Type.ToString()); } }
private async Task StartSessionAsync(int millisecondsTimeout) { await OpenSocketAsync(millisecondsTimeout); _writeBuffer = new WriteBuffer(_awaitableSocket); _readBuffer = new ReadBuffer(_awaitableSocket); await WriteStartupAsync(); await _readBuffer.ReceiveAsync(); read: var message = _readBuffer.ReadMessage(); switch (message.Type) { case MessageType.AuthenticationRequest: { var authenticationRequestType = (AuthenticationRequestType)_readBuffer.ReadInt(); switch (authenticationRequestType) { case AuthenticationRequestType.AuthenticationOk: { return; } case AuthenticationRequestType.AuthenticationMD5Password: { var salt = _readBuffer.ReadBytes(4); var hash = Hashing.CreateMD5(_password, _user, salt); await _writeBuffer .StartMessage('p') .WriteBytes(hash) .EndMessage() .FlushAsync(); await _readBuffer.ReceiveAsync(); goto read; } default: throw new NotImplementedException(authenticationRequestType.ToString()); } } case MessageType.ErrorResponse: throw new InvalidOperationException(_readBuffer.ReadErrorMessage()); case MessageType.BackendKeyData: case MessageType.EmptyQueryResponse: case MessageType.ParameterStatus: case MessageType.ReadyForQuery: throw new NotImplementedException($"Unhandled MessageType '{message.Type}'"); default: throw new InvalidOperationException($"Unexpected MessageType '{message.Type}'"); } }
public async Task ExecuteAsync <TResult>( string statementName, Func <TResult> resultFactory, Action <TResult, ReadBuffer, int, int> columnBinder) { ThrowIfDisposed(); ThrowIfNotConnected(); await _writeBuffer .StartMessage('B') .WriteNull() .WriteString(statementName) .WriteShort(0) .WriteShort(0) .WriteShort(1) .WriteShort(1) .EndMessage() .StartMessage('E') .WriteNull() .WriteInt(0) .EndMessage() .StartMessage('S') .EndMessage() .FlushAsync(); await _readBuffer.ReceiveAsync(); read: var message = ReadMessage(); switch (message.Type) { case MessageType.BindComplete: goto read; case MessageType.DataRow: { var result = resultFactory != null ? resultFactory() : default; var columns = _readBuffer.ReadShort(); for (var i = 0; i < columns; i++) { var length = _readBuffer.ReadInt(); columnBinder(result, _readBuffer, i, length); } goto read; } case MessageType.CommandComplete: return; case MessageType.ErrorResponse: throw new InvalidOperationException(ReadErrorMessage()); default: throw new NotImplementedException(message.Type.ToString()); } }