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;
            }
        }
Ejemplo n.º 3
0
        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;
         }
     }
 }
Ejemplo n.º 6
0
        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;
            }
        }