2010-04-07 Jb Evain <jbevain@novell.com>
[mcs.git] / class / Npgsql / Npgsql / NpgsqlRowDescription.cs
blob0aa3c2fc63c7a670ac86c9c369672b49f92b8621
1 // created on 12/6/2002 at 20:29
3 // Npgsql.NpgsqlRowDescription.cs
4 //
5 // Author:
6 // Francisco Jr. (fxjrlists@yahoo.com.br)
7 //
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
26 using System;
27 using System.Collections;
28 using System.IO;
29 using System.Text;
30 using System.Net;
31 using System.Globalization;
33 using NpgsqlTypes;
35 namespace Npgsql
39 /// <summary>
40 /// This struct represents the internal data of the RowDescription message.
41 /// </summary>
42 ///
43 // [FIXME] Is this name OK? Does it represent well the struct intent?
44 // Should it be a struct or a class?
45 internal struct NpgsqlRowDescriptionFieldData
47 public String name; // Protocol 2/3
48 public Int32 table_oid; // Protocol 3
49 public Int16 column_attribute_number; // Protocol 3
50 public Int32 type_oid; // Protocol 2/3
51 public Int16 type_size; // Protocol 2/3
52 public Int32 type_modifier; // Protocol 2/3
53 public FormatCode format_code; // Protocol 3. 0 text, 1 binary
54 public NpgsqlBackendTypeInfo type_info; // everything we know about this field type
57 /// <summary>
58 /// This class represents a RowDescription message sent from
59 /// the PostgreSQL.
60 /// </summary>
61 ///
62 internal sealed class NpgsqlRowDescription
64 // Logging related values
65 private static readonly String CLASSNAME = "NpgsqlRowDescription";
68 private NpgsqlRowDescriptionFieldData[] fields_data;
69 private string[] fields_index;
70 private Hashtable field_name_index_table;
72 private ProtocolVersion protocol_version;
74 public NpgsqlRowDescription(ProtocolVersion protocolVersion)
76 protocol_version = protocolVersion;
79 public void ReadFromStream(Stream input_stream, Encoding encoding, NpgsqlBackendTypeMapping type_mapping)
81 switch (protocol_version)
83 case ProtocolVersion.Version2 :
84 ReadFromStream_Ver_2(input_stream, encoding, type_mapping);
85 break;
87 case ProtocolVersion.Version3 :
88 ReadFromStream_Ver_3(input_stream, encoding, type_mapping);
89 break;
94 private void ReadFromStream_Ver_2(Stream input_stream, Encoding encoding, NpgsqlBackendTypeMapping type_mapping)
96 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ReadFromStream_Ver_2");
98 Byte[] input_buffer = new Byte[10]; // Max read will be 4 + 2 + 4
100 // Read the number of fields.
101 input_stream.Read(input_buffer, 0, 2);
102 Int16 num_fields = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(input_buffer, 0));
105 // Temporary FieldData object to get data from stream and put in array.
106 NpgsqlRowDescriptionFieldData fd;
108 fields_data = new NpgsqlRowDescriptionFieldData[num_fields];
109 fields_index = new string[num_fields];
111 field_name_index_table = new Hashtable(num_fields);
114 // Now, iterate through each field getting its data.
115 for (Int16 i = 0; i < num_fields; i++)
117 fd = new NpgsqlRowDescriptionFieldData();
119 // Set field name.
120 fd.name = PGUtil.ReadString(input_stream, encoding);
122 // Read type_oid(Int32), type_size(Int16), type_modifier(Int32)
123 input_stream.Read(input_buffer, 0, 4 + 2 + 4);
125 fd.type_oid = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 0));
126 fd.type_info = type_mapping[fd.type_oid];
127 fd.type_size = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(input_buffer, 4));
128 fd.type_modifier = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 6));
130 // Add field data to array.
131 fields_data[i] = fd;
133 fields_index[i] = fd.name;
135 if (!field_name_index_table.ContainsKey(fd.name))
136 field_name_index_table.Add(fd.name, i);
140 private void ReadFromStream_Ver_3(Stream input_stream, Encoding encoding, NpgsqlBackendTypeMapping type_mapping)
142 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ReadFromStream_Ver_3");
144 Byte[] input_buffer = new Byte[4]; // Max read will be 4 + 2 + 4 + 2 + 4 + 2
146 // Read the length of message.
147 // [TODO] Any use for now?
148 PGUtil.ReadInt32(input_stream, input_buffer);
149 Int16 num_fields = PGUtil.ReadInt16(input_stream, input_buffer);
151 // Temporary FieldData object to get data from stream and put in array.
152 NpgsqlRowDescriptionFieldData fd;
154 fields_data = new NpgsqlRowDescriptionFieldData[num_fields];
155 fields_index = new string[num_fields];
156 field_name_index_table = new Hashtable(num_fields);
158 for (Int16 i = 0; i < num_fields; i++)
160 fd = new NpgsqlRowDescriptionFieldData();
162 fd.name = PGUtil.ReadString(input_stream, encoding);
163 fd.table_oid = PGUtil.ReadInt32(input_stream, input_buffer);
164 fd.column_attribute_number = PGUtil.ReadInt16(input_stream, input_buffer);
165 fd.type_oid = PGUtil.ReadInt32(input_stream, input_buffer);
166 fd.type_info = type_mapping[fd.type_oid];
167 fd.type_size = PGUtil.ReadInt16(input_stream, input_buffer);
168 fd.type_modifier = PGUtil.ReadInt32(input_stream, input_buffer);
169 fd.format_code = (FormatCode)PGUtil.ReadInt16(input_stream, input_buffer);
171 fields_data[i] = fd;
172 fields_index[i] = fd.name;
174 if (!field_name_index_table.ContainsKey(fd.name))
175 field_name_index_table.Add(fd.name, i);
179 public NpgsqlRowDescriptionFieldData this[Int32 index]
183 return fields_data[index];
187 public Int16 NumFields
191 return (Int16)fields_data.Length;
195 public Int16 FieldIndex(String fieldName)
199 // First try to find with hashtable, case sensitive.
201 Object result1 = field_name_index_table[fieldName];
203 if (result1 != null)
204 return (Int16)result1;
207 result1 = field_name_index_table[fieldName.ToLower(CultureInfo.InvariantCulture)];
209 if (result1 != null)
210 return (Int16)result1;
212 // Then the index with IndexOf (case-sensitive)
215 Int16 result = (Int16)Array.IndexOf(fields_index, fieldName, 0, fields_index.Length);
217 if (result != -1)
219 return result;
221 else
224 foreach(string name in fields_index)
226 ++result;
227 if (string.Compare(name, fieldName, true, CultureInfo.InvariantCulture) == 0)
228 return result;
232 return -1;