public override int Read(byte[] buffer, int offset, int count) { CheckDisposed(); if (!CanRead) { throw new InvalidOperationException("Stream not open for reading"); } if (_isConsumed) { return(0); } if (_leftToReadInDataMsg == 0) { // We've consumed the current DataMessage (or haven't yet received the first), // read the next message var msg = _connector.ReadMessage(); switch (msg.Code) { case BackendMessageCode.CopyData: _leftToReadInDataMsg = ((CopyDataMessage)msg).Length; break; case BackendMessageCode.CopyDone: _connector.ReadExpecting <CommandCompleteMessage>(); _connector.ReadExpecting <ReadyForQueryMessage>(); _isConsumed = true; return(0); default: throw _connector.UnexpectedMessageReceived(msg.Code); } } Debug.Assert(_leftToReadInDataMsg > 0); // If our buffer is empty, read in more. Otherwise return whatever is there, even if the // user asked for more (normal socket behavior) if (_readBuf.ReadBytesLeft == 0) { _readBuf.ReadMore(false).GetAwaiter().GetResult(); } Debug.Assert(_readBuf.ReadBytesLeft > 0); var maxCount = Math.Min(_readBuf.ReadBytesLeft, _leftToReadInDataMsg); if (count > maxCount) { count = maxCount; } _leftToReadInDataMsg -= count; _readBuf.ReadBytes(buffer, offset, count); return(count); }
internal NpgsqlRawCopyStream(NpgsqlConnector connector, string copyCommand) { _connector = connector; _readBuf = connector.ReadBuffer; _writeBuf = connector.WriteBuffer; _connector.SendQuery(copyCommand); var msg = _connector.ReadMessage(); switch (msg.Code) { case BackendMessageCode.CopyInResponse: var copyInResponse = (CopyInResponseMessage)msg; IsBinary = copyInResponse.IsBinary; _canWrite = true; _writeBuf.StartCopyMode(); break; case BackendMessageCode.CopyOutResponse: var copyOutResponse = (CopyOutResponseMessage)msg; IsBinary = copyOutResponse.IsBinary; _canRead = true; break; case BackendMessageCode.CompletedResponse: throw new InvalidOperationException( "This API only supports import/export from the client, i.e. COPY commands containing TO/FROM STDIN. " + "To import/export with files on your PostgreSQL machine, simply execute the command with ExecuteNonQuery. " + "Note that your data has been successfully imported/exported."); default: throw _connector.UnexpectedMessageReceived(msg.Code); } }
internal NpgsqlBinaryExporter(NpgsqlConnector connector, string copyToCommand) { _connector = connector; _buf = connector.ReadBuffer; _typeMapper = connector.TypeMapper; _columnLen = int.MinValue; // Mark that the (first) column length hasn't been read yet _column = -1; try { _connector.SendQuery(copyToCommand); CopyOutResponseMessage copyOutResponse; var msg = _connector.ReadMessage(); switch (msg.Code) { case BackendMessageCode.CopyOutResponse: copyOutResponse = (CopyOutResponseMessage)msg; if (!copyOutResponse.IsBinary) { throw new ArgumentException("copyToCommand triggered a text transfer, only binary is allowed", nameof(copyToCommand)); } break; case BackendMessageCode.CompletedResponse: throw new InvalidOperationException( "This API only supports import/export from the client, i.e. COPY commands containing TO/FROM STDIN. " + "To import/export with files on your PostgreSQL machine, simply execute the command with ExecuteNonQuery. " + "Note that your data has been successfully imported/exported."); default: throw _connector.UnexpectedMessageReceived(msg.Code); } NumColumns = copyOutResponse.NumColumns; _typeHandlerCache = new NpgsqlTypeHandler[NumColumns]; ReadHeader(); } catch { _connector.Break(); throw; } }
internal NpgsqlBinaryImporter(NpgsqlConnector connector, string copyFromCommand) { _connector = connector; _buf = connector.WriteBuffer; _column = -1; try { _connector.SendQuery(copyFromCommand); CopyInResponseMessage copyInResponse; var msg = _connector.ReadMessage(); switch (msg.Code) { case BackendMessageCode.CopyInResponse: copyInResponse = (CopyInResponseMessage)msg; if (!copyInResponse.IsBinary) { throw new ArgumentException("copyFromCommand triggered a text transfer, only binary is allowed", nameof(copyFromCommand)); } break; case BackendMessageCode.CompletedResponse: throw new InvalidOperationException( "This API only supports import/export from the client, i.e. COPY commands containing TO/FROM STDIN. " + "To import/export with files on your PostgreSQL machine, simply execute the command with ExecuteNonQuery. " + "Note that your data has been successfully imported/exported."); default: throw _connector.UnexpectedMessageReceived(msg.Code); } NumColumns = copyInResponse.NumColumns; _params = new NpgsqlParameter[NumColumns]; _buf.StartCopyMode(); WriteHeader(); } catch { _connector.Break(); throw; } }
void Cancel() { _state = ImporterState.Cancelled; _buf.Clear(); _buf.EndCopyMode(); _connector.SendMessage(new CopyFailMessage()); try { var msg = _connector.ReadMessage(); // The CopyFail should immediately trigger an exception from the read above. _connector.Break(); throw new NpgsqlException("Expected ErrorResponse when cancelling COPY but got: " + msg.Code); } catch (PostgresException e) { if (e.SqlState != "57014") { throw; } } }