async Task EnsureLong(int count, bool async, bool dontBreakOnTimeouts = false) { Debug.Assert(count <= Size); Debug.Assert(count > ReadBytesLeft); count -= ReadBytesLeft; if (count <= 0) { return; } if (ReadPosition == _filledBytes) { Clear(); } else if (count > Size - _filledBytes) { Array.Copy(Buffer, ReadPosition, Buffer, 0, ReadBytesLeft); _filledBytes = ReadBytesLeft; ReadPosition = 0; } try { while (count > 0) { var toRead = Size - _filledBytes; var read = async ? await Underlying.ReadAsync(Buffer, _filledBytes, toRead) : Underlying.Read(Buffer, _filledBytes, toRead); if (read == 0) { throw new EndOfStreamException(); } count -= read; _filledBytes += read; } } // We have a special case when reading async notifications - a timeout may be normal // shouldn't be fatal // Note that mono throws SocketException with the wrong error (see #1330) catch (IOException e) when( dontBreakOnTimeouts && (e.InnerException as SocketException)?.SocketErrorCode == (Type.GetType("Mono.Runtime") == null ? SocketError.TimedOut : SocketError.WouldBlock) ) { throw new TimeoutException("Timeout while reading from stream"); } catch (Exception e) { Connector.Break(); throw new NpgsqlException("Exception while reading from stream", e); } }
public override void Write(byte[] buffer, int offset, int count) { CheckDisposed(); if (!CanWrite) { throw new InvalidOperationException("Stream not open for writing"); } if (count == 0) { return; } if (count <= _writeBuf.WriteSpaceLeft) { _writeBuf.WriteBytes(buffer, offset, count); return; } try { // Value is too big, flush. Flush(); if (count <= _writeBuf.WriteSpaceLeft) { _writeBuf.WriteBytes(buffer, offset, count); return; } // Value is too big even after a flush - bypass the buffer and write directly. _writeBuf.DirectWrite(buffer, offset, count); } catch { _connector.Break(); Cleanup(); throw; } }
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; } } }
T DoRead <T>(NpgsqlTypeHandler handler) { try { ReadColumnLenIfNeeded(); if (_columnLen == -1) { throw new InvalidCastException("Column is null"); } // If we know the entire column is already in memory, use the code path without async var result = _columnLen <= _buf.ReadBytesLeft ? handler.Read <T>(_buf, _columnLen) : handler.Read <T>(_buf, _columnLen, false).GetAwaiter().GetResult(); _leftToReadInDataMsg -= _columnLen; _columnLen = int.MinValue; // Mark that the (next) column length hasn't been read yet _column++; return(result); } catch { _connector.Break(); Cleanup(); throw; } }