2004-11-25 Francisco Figueiredo Jr. <fxjrlists@yahoo.com.br>
[mono.git] / mcs / class / Npgsql / Npgsql / NpgsqlError.cs
1 // created on 12/7/2003 at 18:36
2
3 // Npgsql.NpgsqlError.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
11 //
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.
16 //
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.
21 //
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
25
26 using System;
27 using System.IO;
28 using System.Text;
29
30 namespace Npgsql
31 {
32     /// <summary>
33     /// EventArgs class to send Notice parameters, which are just NpgsqlError's in a lighter context.
34     /// </summary>
35     public class NpgsqlNoticeEventArgs : EventArgs
36     {
37         /// <summary>
38         /// Notice information.
39         /// </summary>
40         public NpgsqlError Notice = null;
41
42         internal NpgsqlNoticeEventArgs(NpgsqlError eNotice)
43         {
44             Notice = eNotice;
45         }
46     }
47
48     /// <summary>
49     /// This class represents the ErrorResponse and NoticeResponse
50     /// message sent from PostgreSQL server.
51     /// </summary>
52     public sealed class NpgsqlError
53     {
54         // Logging related values
55         private static readonly String CLASSNAME = "NpgsqlError";
56
57         private ProtocolVersion protocol_version;
58         private String _severity = "";
59         private String _code = "";
60         private String _message = "";
61         private String _detail = "";
62         private String _hint = "";
63         private String _position = "";
64         private String _where = "";
65         private String _file = "";
66         private String _line = "";
67         private String _routine = "";
68
69         /// <summary>
70         /// Severity code.  All versions.
71         /// </summary>
72         public String Severity
73         {
74             get
75             {
76                 return _severity;
77             }
78         }
79
80         /// <summary>
81         /// Error code.  PostgreSQL 7.4 and up.
82         /// </summary>
83         public String Code
84         {
85             get
86             {
87                 return _code;
88             }
89         }
90
91         /// <summary>
92         /// Terse error message.  All versions.
93         /// </summary>
94         public String Message
95         {
96             get
97             {
98                 return _message;
99             }
100         }
101
102         /// <summary>
103         /// Detailed error message.  PostgreSQL 7.4 and up.
104         /// </summary>
105         public String Detail
106         {
107             get
108             {
109                 return _detail;
110             }
111         }
112
113         /// <summary>
114         /// Suggestion to help resolve the error.  PostgreSQL 7.4 and up.
115         /// </summary>
116         public String Hint
117         {
118             get
119             {
120                 return _hint;
121             }
122         }
123
124         /// <summary>
125         /// Position (one based) within the query string where the error was encounterd.  PostgreSQL 7.4 and up.
126         /// </summary>
127         public String Position
128         {
129             get
130             {
131                 return _position;
132             }
133         }
134
135         /// <summary>
136         /// Trace back information.  PostgreSQL 7.4 and up.
137         /// </summary>
138         public String Where
139         {
140             get
141             {
142                 return _where;
143             }
144         }
145
146         /// <summary>
147         /// Source file (in backend) reporting the error.  PostgreSQL 7.4 and up.
148         /// </summary>
149         public String File
150         {
151             get
152             {
153                 return _file;
154             }
155         }
156
157         /// <summary>
158         /// Source file line number (in backend) reporting the error.  PostgreSQL 7.4 and up.
159         /// </summary>
160         public String Line
161         {
162             get
163             {
164                 return _line;
165             }
166         }
167
168         /// <summary>
169         /// Source routine (in backend) reporting the error.  PostgreSQL 7.4 and up.
170         /// </summary>
171         public String Routine
172         {
173             get
174             {
175                 return _routine;
176             }
177         }
178
179         /// <summary>
180         /// Return a string representation of this error object.
181         /// </summary>
182         public override String ToString()
183         {
184             StringBuilder     B = new StringBuilder();
185
186             if (Severity.Length > 0)
187             {
188                 B.AppendFormat("{0}: ", Severity);
189             }
190             if (Code.Length > 0)
191             {
192                 B.AppendFormat("{0}: ", Code);
193             }
194             B.AppendFormat("{0}", Message);
195             // CHECKME - possibly multi-line, that is yucky
196             //            if (Hint.Length > 0) {
197             //                B.AppendFormat(" ({0})", Hint);
198             //            }
199
200             return B.ToString();
201         }
202
203         internal NpgsqlError(ProtocolVersion protocolVersion)
204         {
205             protocol_version = protocolVersion;
206         }
207         
208         internal NpgsqlError(ProtocolVersion protocolVersion, String errorMessage)
209         {
210             protocol_version = protocolVersion;
211             _message = errorMessage;
212         }
213
214         /// <summary>
215         /// Backend protocol version in use.
216         /// </summary>
217         internal ProtocolVersion BackendProtocolVersion
218         {
219             get
220             {
221                 return protocol_version;
222             }
223         }
224
225         internal void ReadFromStream(Stream inputStream, Encoding encoding)
226         {
227             switch (protocol_version) {
228             case ProtocolVersion.Version2 :
229                 ReadFromStream_Ver_2(inputStream, encoding);
230                 break;
231
232             case ProtocolVersion.Version3 :
233                 ReadFromStream_Ver_3(inputStream, encoding);
234                 break;
235
236             }
237         }
238
239         private void ReadFromStream_Ver_2(Stream inputStream, Encoding encoding)
240         {
241             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ReadFromStream_Ver_2");
242
243             String Raw;
244             String[] Parts;
245
246             Raw = PGUtil.ReadString(inputStream, encoding);
247
248             Parts = Raw.Split(new char[] {':'}, 2);
249
250             if (Parts.Length == 2)
251             {
252                 _severity = Parts[0].Trim();
253                 _message = Parts[1].Trim();
254             }
255             else
256             {
257                 _message = Parts[0].Trim();
258             }
259         }
260
261         private void ReadFromStream_Ver_3(Stream inputStream, Encoding encoding)
262         {
263             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ReadFromStream_Ver_3");
264
265             Int32 messageLength = PGUtil.ReadInt32(inputStream, new Byte[4]);
266
267             // [TODO] Would this be the right way to do?
268             // Check the messageLength value. If it is 1178686529, this would be the
269             // "FATA" string, which would mean a protocol 2.0 error string.
270             if (messageLength == 1178686529)
271             {
272                                                                 String Raw;
273                 String[] Parts;
274
275                 Raw = "FATA" + PGUtil.ReadString(inputStream, encoding);
276
277                 Parts = Raw.Split(new char[] {':'}, 2);
278
279                 if (Parts.Length == 2)
280                 {
281                     _severity = Parts[0].Trim();
282                     _message = Parts[1].Trim();
283                 }
284                 else
285                 {
286                     _message = Parts[0].Trim();
287                 }
288
289                 protocol_version = ProtocolVersion.Version2;
290
291                 return;
292             }
293
294             Char field;
295             String fieldValue;
296
297             field = (Char) inputStream.ReadByte();
298
299             // Now start to read fields.
300             while (field != 0)
301             {
302                 fieldValue = PGUtil.ReadString(inputStream, encoding);
303
304                 switch (field)
305                 {
306                 case 'S':
307                     _severity = fieldValue;
308                     break;
309                 case 'C':
310                     _code = fieldValue;
311                     break;
312                 case 'M':
313                     _message = fieldValue;
314                     break;
315                 case 'D':
316                     _detail = fieldValue;
317                     break;
318                 case 'H':
319                     _hint = fieldValue;
320                     break;
321                 case 'P':
322                     _position = fieldValue;
323                     break;
324                 case 'W':
325                     _where = fieldValue;
326                     break;
327                 case 'F':
328                     _file = fieldValue;
329                     break;
330                 case 'L':
331                     _line = fieldValue;
332                     break;
333                 case 'R':
334                     _routine = fieldValue;
335                     break;
336
337                 }
338
339                 field = (Char) inputStream.ReadByte();
340
341             }
342         }
343     }
344 }