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
;
31 using System
.Globalization
;
40 /// This struct represents the internal data of the RowDescription message.
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
58 /// This class represents a RowDescription message sent from
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
);
87 case ProtocolVersion
.Version3
:
88 ReadFromStream_Ver_3(input_stream
, encoding
, type_mapping
);
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();
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.
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
);
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
];
204 return (Int16
)result1
;
207 result1
= field_name_index_table
[fieldName
.ToLower(CultureInfo
.InvariantCulture
)];
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
);
224 foreach(string name
in fields_index
)
227 if (string.Compare(name
, fieldName
, true, CultureInfo
.InvariantCulture
) == 0)