X Tutup
// created on 13/6/2002 at 21:06 // Npgsql.NpgsqlAsciiRow.cs // // Author: // Francisco Jr. (fxjrlists@yahoo.com.br) // // Copyright (C) 2002 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.Data; using System.IO; using NpgsqlTypes; namespace Npgsql { /// /// Implements for version 3 of the protocol. /// internal sealed class StringRowReader : RowReader { private readonly int _messageSize; private int? _nextFieldSize = null; public StringRowReader(Stream inputStream) : base(inputStream) { _messageSize = PGUtil.ReadInt32(inputStream); } public override void SetRowDescription(NpgsqlRowDescription rowDesc) { if (PGUtil.ReadInt16(Stream) != rowDesc.NumFields) { throw new DataException(); } _rowDesc = rowDesc; } protected override object ReadNext() { int fieldSize = GetThisFieldCount(); if (fieldSize >= _messageSize) { AbandonShip(); } _nextFieldSize = null; // Check if this field is null if (fieldSize == -1) // Null value { return DBNull.Value; } NpgsqlRowDescription.FieldData field_descr = FieldData; byte[] buffer = new byte[fieldSize]; PGUtil.CheckedStreamRead(Stream, buffer, 0, fieldSize); try { if (field_descr.FormatCode == FormatCode.Text) { return NpgsqlTypesHelper.ConvertBackendStringToSystemType(field_descr.TypeInfo, buffer, field_descr.TypeSize, field_descr.TypeModifier); } else { return NpgsqlTypesHelper.ConvertBackendBytesToSystemType(field_descr.TypeInfo, buffer, fieldSize, field_descr.TypeModifier); } } catch (InvalidCastException ice) { return ice; } catch (Exception ex) { return new InvalidCastException(ex.Message, ex); } } private void AbandonShip() { //field size will always be smaller than message size //but if we fall out of sync with the stream due to an error then we will probably hit //such a situation soon as bytes from elsewhere in the stream get interpreted as a size. //so if we see this happens, we know we've lost the stream - our best option is to just give up on it, //and have the connector recovered later. try { Stream .WriteBytes((byte)FrontEndMessageCode.Termination) .WriteInt32(4) .Flush(); } catch { } try { Stream.Close(); } catch { } throw new DataException(); } protected override void SkipOne() { int fieldSize = GetThisFieldCount(); if (fieldSize >= _messageSize) { AbandonShip(); } _nextFieldSize = null; PGUtil.EatStreamBytes(Stream, fieldSize); } public override bool IsNextDBNull { get { return GetThisFieldCount() == -1; } } private int GetThisFieldCount() { return (_nextFieldSize = _nextFieldSize ?? PGUtil.ReadInt32(Stream)).Value; } protected override int GetNextFieldCount() { int ret = GetThisFieldCount(); _nextFieldSize = null; return ret; } public override void Dispose() { if (_rowDesc == null) { // If _rowdesc is null, then only the message length integer has been read; // read the entire message and disgard it. PGUtil.EatStreamBytes(Stream, this._messageSize - 4); } else { CurrentStreamer = null; Skip(_rowDesc.NumFields - _currentField - 1); } } } }
X Tutup