disable broken tests on net_4_0
[mcs.git] / class / Npgsql / Npgsql / PGUtil.cs
blob7c6c56739e15c7b7f55142a9c7c761016cfcecff
1 // created on 1/6/2002 at 22:27
3 // Npgsql.PGUtil.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
27 using System;
28 using System.Collections;
29 using System.IO;
30 using System.Text;
31 using System.Net.Sockets;
32 using System.Net;
33 using System.Resources;
35 namespace Npgsql
37 /// <summary>
38 /// Represent the frontend/backend protocol version.
39 /// </summary>
40 public enum ProtocolVersion
42 Unknown,
43 Version2,
44 Version3
47 /// <summary>
48 /// Represent the backend server version.
49 /// </summary>
50 public sealed class ServerVersion
52 public static readonly Int32 ProtocolVersion2 = 2 << 16; // 131072
53 public static readonly Int32 ProtocolVersion3 = 3 << 16; // 196608
55 private Int32 _Major;
56 private Int32 _Minor;
57 private Int32 _Patch;
59 internal ServerVersion(Int32 Major, Int32 Minor, Int32 Patch)
61 _Major = Major;
62 _Minor = Minor;
63 _Patch = Patch;
66 /// <summary>
67 /// Server version major number.
68 /// </summary>
69 public Int32 Major
70 { get { return _Major; } }
72 /// <summary>
73 /// Server version minor number.
74 /// </summary>
75 public Int32 Minor
76 { get { return _Minor; } }
78 /// <summary>
79 /// Server version patch level number.
80 /// </summary>
81 public Int32 Patch
82 { get { return _Patch; } }
84 public static bool operator == (ServerVersion One, ServerVersion TheOther)
86 if (((Object)One == null) || ((Object)TheOther == null))
87 return false;
88 return
89 One._Major == TheOther._Major &&
90 One._Minor == TheOther._Minor &&
91 One._Patch == TheOther._Patch;
94 public static bool operator != (ServerVersion One, ServerVersion TheOther)
96 if (((Object)One == null) || ((Object)TheOther == null))
97 return true;
99 return ! (One == TheOther);
102 public static bool operator > (ServerVersion One, ServerVersion TheOther)
104 return
105 (One._Major > TheOther._Major) ||
106 (One._Major == TheOther._Major && One._Minor > TheOther._Minor) ||
107 (One._Major == TheOther._Major && One._Minor == TheOther._Minor && One._Patch > TheOther._Patch);
110 public static bool operator >= (ServerVersion One, ServerVersion TheOther)
112 return
113 (One._Major > TheOther._Major) ||
114 (One._Major == TheOther._Major && One._Minor > TheOther._Minor) ||
115 (One._Major == TheOther._Major && One._Minor == TheOther._Minor && One._Patch >= TheOther._Patch);
118 public static bool operator < (ServerVersion One, ServerVersion TheOther)
120 return
121 (One._Major < TheOther._Major) ||
122 (One._Major == TheOther._Major && One._Minor < TheOther._Minor) ||
123 (One._Major == TheOther._Major && One._Minor == TheOther._Minor && One._Patch < TheOther._Patch);
126 public static bool operator <= (ServerVersion One, ServerVersion TheOther)
128 return
129 (One._Major < TheOther._Major) ||
130 (One._Major == TheOther._Major && One._Minor < TheOther._Minor) ||
131 (One._Major == TheOther._Major && One._Minor == TheOther._Minor && One._Patch <= TheOther._Patch);
134 public override bool Equals(object O)
136 if (O == null)
137 return false;
139 return (O.GetType() == this.GetType() && this == (ServerVersion)O);
142 public override int GetHashCode()
144 return _Major ^ _Minor ^ _Patch;
147 /// <summary>
148 /// Returns the string representation of this version in three place dot notation (Major.Minor.Patch).
149 /// </summary>
150 public override String ToString()
152 return string.Format("{0}.{1}.{2}", _Major, _Minor, _Patch);
156 internal enum FormatCode:
157 short
159 Text = 0,
160 Binary = 1
163 ///<summary>
164 /// This class provides many util methods to handle
165 /// reading and writing of PostgreSQL protocol messages.
166 /// </summary>
167 internal abstract class PGUtil
169 // Logging related values
170 private static readonly String CLASSNAME = "PGUtil";
171 private static ResourceManager resman = new ResourceManager(typeof(PGUtil));
173 ///<summary>
174 /// This method takes a ProtocolVersion and returns an integer
175 /// version number that the Postgres backend will recognize in a
176 /// startup packet.
177 /// </summary>
178 public static Int32 ConvertProtocolVersion(ProtocolVersion Ver)
180 switch (Ver) {
181 case ProtocolVersion.Version2 :
182 return ServerVersion.ProtocolVersion2;
184 case ProtocolVersion.Version3 :
185 return ServerVersion.ProtocolVersion3;
189 // CHECKME
190 // should we throw?
191 return 0;
194 /// <summary>
195 /// This method takes a version string as returned by SELECT VERSION() and returns
196 /// a valid version string ("7.2.2" for example).
197 /// This is only needed when running protocol version 2.
198 /// This does not do any validity checks.
199 /// </summary>
200 public static string ExtractServerVersion (string VersionString)
202 Int32 Start = 0, End = 0;
204 // find the first digit and assume this is the start of the version number
205 for ( ; Start < VersionString.Length && ! char.IsDigit(VersionString[Start]) ; Start++);
207 End = Start;
209 // read until hitting whitespace, which should terminate the version number
210 for ( ; End < VersionString.Length && ! char.IsWhiteSpace(VersionString[End]) ; End++);
212 return VersionString.Substring(Start, End - Start + 1);
215 /// <summary>
216 /// This method takes a version string ("7.4.1" for example) and produces
217 /// the required integer version numbers (7, 4, and 1).
218 /// </summary>
219 public static ServerVersion ParseServerVersion (string VersionString)
221 String[] Parts;
223 Parts = VersionString.Split('.');
225 if (Parts.Length < 2) {
226 throw new FormatException(String.Format("Internal: Backend sent bad version string: {0}", VersionString));
229 try {
230 if (Parts.Length == 2) {
231 // Coerce it into a 3-part version.
232 return new ServerVersion(ConvertBeginToInt32(Parts[0]), ConvertBeginToInt32(Parts[1]), 0);
233 } else {
234 // If there are more than 3 parts, just ignore the extras, rather than rejecting it.
235 return new ServerVersion(ConvertBeginToInt32(Parts[0]), ConvertBeginToInt32(Parts[1]), ConvertBeginToInt32(Parts[2]));
237 } catch (Exception E) {
238 throw new FormatException(String.Format("Internal: Backend sent bad version string: {0}", VersionString), E);
242 /// <summary>
243 /// Convert the beginning numeric part of the given string to Int32.
244 /// For example:
245 /// Strings "12345ABCD" and "12345.54321" would both be converted to int 12345.
246 /// </summary>
247 private static Int32 ConvertBeginToInt32(String Raw)
249 Int32 Length = 0;
250 for ( ; Length < Raw.Length && Char.IsNumber(Raw[Length]) ; Length++);
251 return Convert.ToInt32(Raw.Substring(0, Length));
254 ///<summary>
255 /// This method gets a C NULL terminated string from the network stream.
256 /// It keeps reading a byte in each time until a NULL byte is returned.
257 /// It returns the resultant string of bytes read.
258 /// This string is sent from backend.
259 /// </summary>
260 public static String ReadString(Stream network_stream, Encoding encoding)
262 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ReadString");
264 ArrayList buffer = new ArrayList();
265 Byte b;
266 String string_read;
268 // [FIXME] Is this cast always safe?
269 b = (Byte)network_stream.ReadByte();
270 while(b != 0)
272 buffer.Add(b);
273 b = (Byte)network_stream.ReadByte();
276 string_read = encoding.GetString((Byte[])buffer.ToArray(typeof(Byte)));
277 NpgsqlEventLog.LogMsg(resman, "Log_StringRead", LogLevel.Debug, string_read);
279 return string_read;
282 ///<summary>
283 /// This method gets a length terminated string from a network stream.
284 /// It returns the resultant string of bytes read.
285 /// This string is sent from backend.
286 /// </summary>
287 public static String ReadString(Stream network_stream, Encoding encoding, Int32 length)
289 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ReadString");
291 ArrayList buffer = new ArrayList();
292 Byte b;
293 String string_read;
295 for (int C = 0 ; C < length ; C++)
297 // [FIXME] Is this cast always safe?
298 b = (Byte)network_stream.ReadByte();
299 buffer.Add(b);
302 string_read = encoding.GetString((Byte[])buffer.ToArray(typeof(Byte)));
303 NpgsqlEventLog.LogMsg(resman, "Log_StringRead", LogLevel.Debug, string_read);
305 return string_read;
308 ///<summary>
309 /// This method writes a C NULL terminated string to the network stream.
310 /// It appends a NULL terminator to the end of the String.
311 /// </summary>
312 public static void WriteString(String the_string, Stream network_stream, Encoding encoding)
314 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "WriteString");
316 NpgsqlEventLog.LogMsg(resman, "Log_StringWritten", LogLevel.Debug, the_string);
318 network_stream.Write(encoding.GetBytes(the_string + '\x00') , 0, encoding.GetByteCount(the_string) + 1);
321 ///<summary>
322 /// This method writes a C NULL terminated string limited in length to the
323 /// backend server.
324 /// It pads the string with null bytes to the size specified.
325 /// </summary>
326 public static void WriteLimString(String the_string, Int32 n, Stream network_stream, Encoding encoding)
328 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "WriteLimString");
330 // [FIXME] Parameters should be validated. And what about strings
331 // larger than or equal to n?
333 // Pad the string to the specified value.
334 String string_padded = the_string.PadRight(n, '\x00');
336 network_stream.Write(encoding.GetBytes(string_padded), 0, n);
339 public static void CheckedStreamRead(Stream stream, Byte[] buffer, Int32 offset, Int32 size)
341 Int32 bytes_from_stream = 0;
342 Int32 total_bytes_read = 0;
346 bytes_from_stream = stream.Read(buffer, offset + total_bytes_read, size);
347 total_bytes_read += bytes_from_stream;
348 size -= bytes_from_stream;
350 while(size > 0);
354 /// <summary>
355 /// Write a 32-bit integer to the given stream in the correct byte order.
356 /// </summary>
357 public static void WriteInt32(Stream stream, Int32 value)
359 stream.Write(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value)), 0, 4);
362 /// <summary>
363 /// Read a 32-bit integer from the given stream in the correct byte order.
364 /// </summary>
365 public static Int32 ReadInt32(Stream stream, Byte[] buffer)
367 CheckedStreamRead(stream, buffer, 0, 4);
368 return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, 0));
372 /// <summary>
373 /// Write a 16-bit integer to the given stream in the correct byte order.
374 /// </summary>
375 public static void WriteInt16(Stream stream, Int16 value)
377 stream.Write(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value)), 0, 2);
380 /// <summary>
381 /// Read a 16-bit integer from the given stream in the correct byte order.
382 /// </summary>
383 public static Int16 ReadInt16(Stream stream, Byte[] buffer)
385 CheckedStreamRead(stream, buffer, 0, 2);
386 return IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, 0));