// Npgsql.NpgsqlCopyInStream.cs
//
// Author:
// Kalle Hallivuori
//
// Copyright (C) 2007 The Npgsql Development Team
// npgsql-general@gborg.postgresql.org
// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
// Permission to use, copy, modify, and distribute this software and its
// documentation for any purpose, without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph and the following two paragraphs appear in all copies.
//
// IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY
// FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
// INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
// DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//
// THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
// ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
using System;
using System.IO;
namespace Npgsql
{
///
/// Stream for writing data to a table on a PostgreSQL version 7.4 or newer database during an active COPY FROM STDIN operation.
/// Passes data exactly as is and when given, so see to it that you use server encoding, correct format and reasonably sized writes!
///
internal class NpgsqlCopyInStream : Stream
{
private NpgsqlConnector _context;
private long _bytesPassed = 0;
///
/// True while this stream can be used to write copy data to server
///
private bool IsActive
{
get { return _context != null && _context.CurrentState is NpgsqlCopyInState && _context.Mediator.CopyStream == this; }
}
///
/// Created only by NpgsqlCopyInState.StartCopy()
///
internal NpgsqlCopyInStream(NpgsqlConnector context)
{
_context = context;
}
///
/// False
///
public override bool CanRead
{
get { return false; }
}
///
/// True
///
public override bool CanWrite
{
get { return true; }
}
///
/// False
///
public override bool CanSeek
{
get { return false; }
}
///
/// Number of bytes written so far
///
public override long Length
{
get { return _bytesPassed; }
}
///
/// Number of bytes written so far; not settable
///
public override long Position
{
get { return _bytesPassed; }
set { throw new NotSupportedException("Tried to set Position of network stream " + this); }
}
///
/// Successfully completes copying data to server. Returns after operation is finished.
/// Does nothing if this stream is not the active copy operation writer.
///
public override void Close()
{
if (_context != null)
{
if (IsActive)
{
_context.CurrentState.SendCopyDone(_context);
}
if (_context.Mediator.CopyStream == this)
{
_context.Mediator.CopyStream = null;
}
_context = null;
}
}
///
/// Withdraws an already started copy operation. The operation will fail with given error message.
/// Does nothing if this stream is not the active copy operation writer.
///
public void Cancel(string message)
{
if (IsActive)
{
NpgsqlConnector c = _context;
_context = null;
c.Mediator.CopyStream = null;
c.CurrentState.SendCopyFail(_context, message ?? "Cancel Copy");
}
}
///
/// Writes given bytes to server.
/// Fails if this stream is not the active copy operation writer.
///
public override void Write(byte[] buf, int off, int len)
{
if (! IsActive)
{
throw new ObjectDisposedException("Writing to closed " + this);
}
_context.CurrentState.SendCopyData(_context, buf, off, len);
_bytesPassed += len;
}
///
/// Flushes stream contents to server.
/// Fails if this stream is not the active copy operation writer.
///
public override void Flush()
{
if (! IsActive)
{
throw new ObjectDisposedException("Flushing closed " + this);
}
_context.Stream.Flush();
}
///
/// Not readable
///
public override int Read(byte[] buf, int off, int len)
{
throw new NotSupportedException("Tried to read non-readable " + this);
}
///
/// Not seekable
///
public override long Seek(long pos, SeekOrigin so)
{
throw new NotSupportedException("Tried to seek non-seekable " + this);
}
///
/// Not supported
///
public override void SetLength(long len)
{
throw new NotSupportedException("Tried to set length of network stream " + this);
}
}
}