// 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
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections;
using System.IO;
using System.Text;
using System.Net;
namespace Npgsql
{
///
/// This struct represents the internal data of the RowDescription message.
///
///
// [FIXME] Is this name OK? Does it represent well the struct intent?
// Should it be a struct or a class?
internal struct NpgsqlRowDescriptionFieldData
{
public String name; // Protocol 2/3
public Int32 table_oid; // Protocol 3
public Int16 column_attribute_number; // Protocol 3
public Int32 type_oid; // Protocol 2/3
public Int16 type_size; // Protocol 2/3
public Int32 type_modifier; // Protocol 2/3
public FormatCode format_code; // Protocol 3. 0 text, 1 binary
}
///
/// This class represents a RowDescription message sent from
/// the PostgreSQL.
///
///
internal sealed class NpgsqlRowDescription
{
// Logging related values
private static readonly String CLASSNAME = "NpgsqlRowDescription";
private ArrayList fields_data = new ArrayList();
private ArrayList fields_index = new ArrayList();
private Int32 protocol_version;
public NpgsqlRowDescription(Int32 protocolVersion)
{
protocol_version = protocolVersion;
}
public void ReadFromStream(Stream input_stream, Encoding encoding)
{
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ReadFromStream");
if (protocol_version == ProtocolVersion.Version2)
{
Byte[] input_buffer = new Byte[10]; // Max read will be 4 + 2 + 4
// Read the number of fields.
input_stream.Read(input_buffer, 0, 2);
Int16 num_fields = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(input_buffer, 0));
// Temporary FieldData object to get data from stream and put in array.
NpgsqlRowDescriptionFieldData fd;
// Now, iterate through each field getting its data.
for (Int16 i = 0; i < num_fields; i++)
{
fd = new NpgsqlRowDescriptionFieldData();
// Set field name.
fd.name = PGUtil.ReadString(input_stream, encoding);
// Read type_oid(Int32), type_size(Int16), type_modifier(Int32)
input_stream.Read(input_buffer, 0, 4 + 2 + 4);
fd.type_oid = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 0));
fd.type_size = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(input_buffer, 4));
fd.type_modifier = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 6));
// Add field data to array.
fields_data.Add(fd);
fields_index.Add(fd.name);
}
}
else
{
Byte[] input_buffer = new Byte[4]; // Max read will be 4 + 2 + 4 + 2 + 4 + 2
// Read the length of message.
// [TODO] Any use for now?
PGUtil.ReadInt32(input_stream, input_buffer);
Int16 num_fields = PGUtil.ReadInt16(input_stream, input_buffer);
// Temporary FieldData object to get data from stream and put in array.
NpgsqlRowDescriptionFieldData fd;
for (Int16 i = 0; i < num_fields; i++)
{
fd = new NpgsqlRowDescriptionFieldData();
fd.name = PGUtil.ReadString(input_stream, encoding);
fd.table_oid = PGUtil.ReadInt32(input_stream, input_buffer);
fd.column_attribute_number = PGUtil.ReadInt16(input_stream, input_buffer);
fd.type_oid = PGUtil.ReadInt32(input_stream, input_buffer);
fd.type_size = PGUtil.ReadInt16(input_stream, input_buffer);
fd.type_modifier = PGUtil.ReadInt32(input_stream, input_buffer);
fd.format_code = (FormatCode)PGUtil.ReadInt16(input_stream, input_buffer);
fields_data.Add(fd);
fields_index.Add(fd.name);
}
}
}
public NpgsqlRowDescriptionFieldData this[Int32 index]
{
get
{
return (NpgsqlRowDescriptionFieldData)fields_data[index];
}
}
public Int16 NumFields
{
get
{
return (Int16)fields_data.Count;
}
}
public Int16 FieldIndex(String fieldName)
{
Int16 result = 0;
foreach (String name in fields_index)
{
if (name.Equals(fieldName))
{
return result;
}
result++;
}
return -1;
}
}
}