X Tutup
// created on 12/6/2002 at 20:29 // Npgsql.NpgsqlRowDescription.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.Collections.Generic; using System.Globalization; using System.IO; using System.Text; using NpgsqlTypes; namespace Npgsql { /// /// This class represents a RowDescription message sent from /// the PostgreSQL. /// /// internal sealed class NpgsqlRowDescription : IServerMessage { private abstract class KanaWidthConverter { protected static readonly CompareInfo COMPARE_INFO = System.Globalization.CultureInfo.InvariantCulture.CompareInfo; } private sealed class KanaWidthInsensitiveComparer : KanaWidthConverter, IEqualityComparer { public static readonly KanaWidthInsensitiveComparer INSTANCE = new KanaWidthInsensitiveComparer(); private KanaWidthInsensitiveComparer(){} public bool Equals(string x, string y) { return COMPARE_INFO.Compare(x, y, CompareOptions.IgnoreWidth) == 0; } public int GetHashCode(string obj) { return COMPARE_INFO.GetSortKey(obj, CompareOptions.IgnoreWidth).GetHashCode(); } } private sealed class KanaWidthCaseInsensitiveComparator : KanaWidthConverter, IEqualityComparer { public static readonly KanaWidthCaseInsensitiveComparator INSTANCE = new KanaWidthCaseInsensitiveComparator(); private KanaWidthCaseInsensitiveComparator(){} public bool Equals(string x, string y) { return COMPARE_INFO.Compare(x, y, CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase) == 0; } public int GetHashCode(string obj) { return COMPARE_INFO.GetSortKey(obj, CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase).GetHashCode(); } } /// /// This struct represents the internal data of the RowDescription message. /// public sealed class FieldData { private string _name; // Protocol 2/3 private int _typeOID; // Protocol 2/3 private short _typeSize; // Protocol 2/3 private int _typeModifier; // Protocol 2/3 private int _tableOID; // Protocol 3 private short _columnAttributeNumber; // Protocol 3 private FormatCode _formatCode; // Protocol 3. 0 text, 1 binary private NpgsqlBackendTypeInfo _typeInfo; // everything we know about this field type public FieldData(Stream stream, NpgsqlBackendTypeMapping typeMapping) { Name = stream.ReadString(); TableOID = stream.ReadInt32(); ColumnAttributeNumber = stream.ReadInt16(); TypeInfo = typeMapping[TypeOID = stream.ReadInt32()]; TypeSize = stream.ReadInt16(); TypeModifier = stream.ReadInt32(); FormatCode = (FormatCode) stream.ReadInt16(); } public string Name { get { return _name; } private set { _name = value; } } public int TypeOID { get { return _typeOID; } private set { _typeOID = value; } } public short TypeSize { get { return _typeSize; } private set { _typeSize = value; } } public int TypeModifier { get { return _typeModifier; } private set { _typeModifier = value; } } public int TableOID { get { return _tableOID; } private set { _tableOID = value; } } public short ColumnAttributeNumber { get { return _columnAttributeNumber; } private set { _columnAttributeNumber = value; } } public FormatCode FormatCode { get { return _formatCode; } internal set { _formatCode = value; } } public NpgsqlBackendTypeInfo TypeInfo { get { return _typeInfo; } private set { _typeInfo = value; } } } private readonly FieldData[] fields_data; private readonly Dictionary field_name_index_table; private readonly Dictionary caseInsensitiveNameIndexTable; private readonly Version _compatVersion; public NpgsqlRowDescription(Stream stream, NpgsqlBackendTypeMapping type_mapping) { int num = ReadNumFields(stream); fields_data = new FieldData[num]; field_name_index_table = new Dictionary(num, KanaWidthInsensitiveComparer.INSTANCE); caseInsensitiveNameIndexTable = new Dictionary(num, KanaWidthCaseInsensitiveComparator.INSTANCE); for (int i = 0; i != num; ++i) { FieldData fd = BuildFieldData(stream, type_mapping); fields_data[i] = fd; if (!field_name_index_table.ContainsKey(fd.Name)) { field_name_index_table.Add(fd.Name, i); if (!caseInsensitiveNameIndexTable.ContainsKey(fd.Name)) { caseInsensitiveNameIndexTable.Add(fd.Name, i); } } } } private FieldData BuildFieldData(Stream stream, NpgsqlBackendTypeMapping typeMapping) { return new FieldData(stream, typeMapping); } private int ReadNumFields(Stream stream) { stream.EatStreamBytes(4); return stream.ReadInt16(); } public FieldData this[int index] { get { return fields_data[index]; } } public int NumFields { get { return (Int16) fields_data.Length; } } public bool HasOrdinal(string fieldName) { return caseInsensitiveNameIndexTable.ContainsKey(fieldName); } public int TryFieldIndex(string fieldName) { return HasOrdinal(fieldName) ? FieldIndex(fieldName) : -1; } public int FieldIndex(String fieldName) { int ret = -1; if(field_name_index_table.TryGetValue(fieldName, out ret) || caseInsensitiveNameIndexTable.TryGetValue(fieldName, out ret)) return ret; else throw new IndexOutOfRangeException("Field not found"); } } }
X Tutup