1 // created on 12/6/2002 at 20:29
3 // Npgsql.NpgsqlRowDescription.cs
6 // Francisco Jr. (fxjrlists@yahoo.com.br)
8 // Copyright (C) 2002 The Npgsql Development Team
9 // npgsql-general@gborg.postgresql.org
10 // http://gborg.postgresql.org/project/npgsql/projdisplay.php
12 // This library is free software; you can redistribute it and/or
13 // modify it under the terms of the GNU Lesser General Public
14 // License as published by the Free Software Foundation; either
15 // version 2.1 of the License, or (at your option) any later version.
17 // This library is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 // Lesser General Public License for more details.
22 // You should have received a copy of the GNU Lesser General Public
23 // License along with this library; if not, write to the Free Software
24 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 using System.Collections;
39 /// This struct represents the internal data of the RowDescription message.
42 // [FIXME] Is this name OK? Does it represent well the struct intent?
43 // Should it be a struct or a class?
44 internal struct NpgsqlRowDescriptionFieldData
46 public String name; // Protocol 2/3
47 public Int32 table_oid; // Protocol 3
48 public Int16 column_attribute_number; // Protocol 3
49 public Int32 type_oid; // Protocol 2/3
50 public Int16 type_size; // Protocol 2/3
51 public Int32 type_modifier; // Protocol 2/3
52 public FormatCode format_code; // Protocol 3. 0 text, 1 binary
53 public NpgsqlBackendTypeInfo type_info; // everything we know about this field type
57 /// This class represents a RowDescription message sent from
61 internal sealed class NpgsqlRowDescription
63 // Logging related values
64 private static readonly String CLASSNAME = "NpgsqlRowDescription";
67 private NpgsqlRowDescriptionFieldData[] fields_data;
68 private string[] fields_index;
70 private ProtocolVersion protocol_version;
72 public NpgsqlRowDescription(ProtocolVersion protocolVersion)
74 protocol_version = protocolVersion;
77 public void ReadFromStream(Stream input_stream, Encoding encoding, NpgsqlBackendTypeMapping type_mapping)
79 switch (protocol_version)
81 case ProtocolVersion.Version2 :
82 ReadFromStream_Ver_2(input_stream, encoding, type_mapping);
85 case ProtocolVersion.Version3 :
86 ReadFromStream_Ver_3(input_stream, encoding, type_mapping);
92 private void ReadFromStream_Ver_2(Stream input_stream, Encoding encoding, NpgsqlBackendTypeMapping type_mapping)
94 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ReadFromStream_Ver_2");
96 Byte[] input_buffer = new Byte[10]; // Max read will be 4 + 2 + 4
98 // Read the number of fields.
99 input_stream.Read(input_buffer, 0, 2);
100 Int16 num_fields = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(input_buffer, 0));
103 // Temporary FieldData object to get data from stream and put in array.
104 NpgsqlRowDescriptionFieldData fd;
106 fields_data = new NpgsqlRowDescriptionFieldData[num_fields];
107 fields_index = new string[num_fields];
108 // Now, iterate through each field getting its data.
109 for (Int16 i = 0; i < num_fields; i++)
111 fd = new NpgsqlRowDescriptionFieldData();
114 fd.name = PGUtil.ReadString(input_stream, encoding);
116 // Read type_oid(Int32), type_size(Int16), type_modifier(Int32)
117 input_stream.Read(input_buffer, 0, 4 + 2 + 4);
119 fd.type_oid = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 0));
120 fd.type_info = type_mapping[fd.type_oid];
121 fd.type_size = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(input_buffer, 4));
122 fd.type_modifier = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 6));
124 // Add field data to array.
127 fields_index[i] = fd.name;
131 private void ReadFromStream_Ver_3(Stream input_stream, Encoding encoding, NpgsqlBackendTypeMapping type_mapping)
133 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ReadFromStream_Ver_3");
135 Byte[] input_buffer = new Byte[4]; // Max read will be 4 + 2 + 4 + 2 + 4 + 2
137 // Read the length of message.
138 // [TODO] Any use for now?
139 PGUtil.ReadInt32(input_stream, input_buffer);
140 Int16 num_fields = PGUtil.ReadInt16(input_stream, input_buffer);
142 // Temporary FieldData object to get data from stream and put in array.
143 NpgsqlRowDescriptionFieldData fd;
145 fields_data = new NpgsqlRowDescriptionFieldData[num_fields];
146 fields_index = new string[num_fields];
147 for (Int16 i = 0; i < num_fields; i++)
149 fd = new NpgsqlRowDescriptionFieldData();
151 fd.name = PGUtil.ReadString(input_stream, encoding);
152 fd.table_oid = PGUtil.ReadInt32(input_stream, input_buffer);
153 fd.column_attribute_number = PGUtil.ReadInt16(input_stream, input_buffer);
154 fd.type_oid = PGUtil.ReadInt32(input_stream, input_buffer);
155 fd.type_info = type_mapping[fd.type_oid];
156 fd.type_size = PGUtil.ReadInt16(input_stream, input_buffer);
157 fd.type_modifier = PGUtil.ReadInt32(input_stream, input_buffer);
158 fd.format_code = (FormatCode)PGUtil.ReadInt16(input_stream, input_buffer);
161 fields_index[i] = fd.name;
165 public NpgsqlRowDescriptionFieldData this[Int32 index]
169 return fields_data[index];
173 public Int16 NumFields
177 return (Int16)fields_data.Length;
181 public Int16 FieldIndex(String fieldName)
183 // First try to find the index with IndexOf (case-sensitive)
184 Int16 result = (Int16)Array.IndexOf(fields_index, fieldName, 0, fields_index.Length);
192 foreach(string name in fields_index)
195 if (string.Compare(name, fieldName, true) == 0)
200 throw new ArgumentOutOfRangeException("fieldName", fieldName, "Field name not found");