X Tutup
// created on 12/7/2003 at 18:36 // Npgsql.NpgsqlError.cs // // Author: // Francisco Jr. (fxjrlists@yahoo.com.br) // // Copyright (C) 2002 The Npgsql Development Team // npgsql-general@gborg.postgresql.org // http://gborg.postgresql.org/project/npgsql/projdisplay.php // // Permission to use, copy, modify, and distribute this software and its // documentation for any purpose, without fee, and without a written // agreement is hereby granted, provided that the above copyright notice // and this paragraph and the following two paragraphs appear in all copies. // // IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY // FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, // INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS // DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. // // THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS // ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS // TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. using System; using System.IO; using System.Text; namespace Npgsql { /// /// EventArgs class to send Notice parameters, which are just NpgsqlError's in a lighter context. /// public class NpgsqlNoticeEventArgs : EventArgs { /// /// Notice information. /// public NpgsqlError Notice = null; internal NpgsqlNoticeEventArgs(NpgsqlError eNotice) { Notice = eNotice; } } /// /// This class represents the ErrorResponse and NoticeResponse /// message sent from PostgreSQL server. /// [Serializable] public sealed class NpgsqlError { /// /// Error and notice message field codes /// private enum ErrorFieldTypeCodes : byte { /// /// Severity: the field contents are ERROR, FATAL, or PANIC (in an error message), /// or WARNING, NOTICE, DEBUG, INFO, or LOG (in a notice message), or a localized /// translation of one of these. Always present. /// Severity = (byte)'S', /// /// Code: the SQLSTATE code for the error (see Appendix A). Not localizable. Always present. /// Code = (byte)'C', /// /// Message: the primary human-readable error message. This should be accurate /// but terse (typically one line). Always present. /// Message = (byte)'M', /// /// Detail: an optional secondary error message carrying more detail about the problem. /// Might run to multiple lines. /// Detail = (byte)'D', /// /// Hint: an optional suggestion what to do about the problem. This is intended to differ /// from Detail in that it offers advice (potentially inappropriate) rather than hard facts. /// Might run to multiple lines. /// Hint = (byte)'H', /// /// Position: the field value is a decimal ASCII integer, indicating an error cursor /// position as an index into the original query string. The first character has index 1, /// and positions are measured in characters not bytes. /// Position = (byte)'P', /// /// Internal position: this is defined the same as the P field, but it is used when the /// cursor position refers to an internally generated command rather than the one submitted /// by the client. /// The q field will always appear when this field appears. /// InternalPosition = (byte)'p', /// /// Internal query: the text of a failed internally-generated command. /// This could be, for example, a SQL query issued by a PL/pgSQL function. /// InternalQuery = (byte)'q', /// /// Where: an indication of the context in which the error occurred. /// Presently this includes a call stack traceback of active procedural language functions /// and internally-generated queries. The trace is one entry per line, most recent first. /// Where = (byte)'W', /// /// Schema name: if the error was associated with a specific database object, /// the name of the schema containing that object, if any. /// SchemaName = (byte)'s', /// /// Table name: if the error was associated with a specific table, the name of the table. /// (Refer to the schema name field for the name of the table's schema.) /// TableName = (byte)'t', /// /// Column name: if the error was associated with a specific table column, the name of the column. /// (Refer to the schema and table name fields to identify the table.) /// ColumnName = (byte)'c', /// /// Data type name: if the error was associated with a specific data type, the name of the data type. /// (Refer to the schema name field for the name of the data type's schema.) /// DataTypeName = (byte)'d', /// /// Constraint name: if the error was associated with a specific constraint, the name of the constraint. /// Refer to fields listed above for the associated table or domain. /// (For this purpose, indexes are treated as constraints, even if they weren't created with constraint syntax.) /// ConstraintName = (byte)'n', /// /// File: the file name of the source-code location where the error was reported. /// File = (byte)'F', /// /// Line: the line number of the source-code location where the error was reported. /// Line = (byte)'L', /// /// Routine: the name of the source-code routine reporting the error. /// Routine = (byte)'R' } private readonly ProtocolVersion protocol_version; private readonly String _severity = String.Empty; private readonly String _code = String.Empty; private readonly String _message = String.Empty; private readonly String _detail = String.Empty; private readonly String _hint = String.Empty; private readonly String _position = String.Empty; private readonly String _internalPosition = String.Empty; private readonly String _internalQuery = String.Empty; private readonly String _where = String.Empty; private readonly String _file = String.Empty; private readonly String _line = String.Empty; private readonly String _routine = String.Empty; private readonly String _schemaName = String.Empty; private readonly String _tableName = String.Empty; private readonly String _columnName = String.Empty; private readonly String _datatypeName = String.Empty; private readonly String _constraintName = String.Empty; private String _errorSql = String.Empty; /// /// Severity code. All versions. /// public String Severity { get { return _severity; } } /// /// Error code. PostgreSQL 7.4 and up. /// public String Code { get { return _code; } } /// /// Terse error message. All versions. /// public String Message { get { return _message; } } /// /// Detailed error message. PostgreSQL 7.4 and up. /// public String Detail { get { return _detail; } } /// /// Suggestion to help resolve the error. PostgreSQL 7.4 and up. /// public String Hint { get { return _hint; } } /// /// Position (one based) within the query string where the error was encounterd. PostgreSQL 7.4 and up. /// public String Position { get { return _position; } } /// /// Position (one based) within the query string where the error was encounterd. This position refers to an internal command executed for example inside a PL/pgSQL function. PostgreSQL 7.4 and up. /// public String InternalPosition { get { return _internalPosition; } } /// /// Internal query string where the error was encounterd. This position refers to an internal command executed for example inside a PL/pgSQL function. PostgreSQL 7.4 and up. /// public String InternalQuery { get { return _internalQuery; } } /// /// Trace back information. PostgreSQL 7.4 and up. /// public String Where { get { return _where; } } /// /// Source file (in backend) reporting the error. PostgreSQL 7.4 and up. /// public String File { get { return _file; } } /// /// Source file line number (in backend) reporting the error. PostgreSQL 7.4 and up. /// public String Line { get { return _line; } } /// /// Source routine (in backend) reporting the error. PostgreSQL 7.4 and up. /// public String Routine { get { return _routine; } } /// /// Schema name which relates to the error. PostgreSQL 9.3 and up. /// public String SchemaName { get { return _schemaName; } } /// /// Table name which relates to the error. PostgreSQL 9.3 and up. /// public String TableName { get { return _tableName; } } /// /// Column name which relates to the error. PostgreSQL 9.3 and up. /// public String ColumnName { get { return _columnName; } } /// /// Data type of column which relates to the error. PostgreSQL 9.3 and up. /// public String DataTypeName { get { return _datatypeName; } } /// /// Constraint name which relates to the error. PostgreSQL 9.3 and up. /// public String ConstraintName { get { return _constraintName; } } /// /// String containing the sql sent which produced this error. /// public String ErrorSql { set { _errorSql = value; } get { return _errorSql; } } /// /// Return a string representation of this error object. /// public override String ToString() { StringBuilder B = new StringBuilder(); if (Severity.Length > 0) { B.AppendFormat("{0}: ", Severity); } if (Code.Length > 0) { B.AppendFormat("{0}: ", Code); } B.AppendFormat("{0}", Message); // CHECKME - possibly multi-line, that is yucky // if (Hint.Length > 0) { // B.AppendFormat(" ({0})", Hint); // } return B.ToString(); } internal NpgsqlError(ProtocolVersion protocolVersion, Stream stream) { switch (protocol_version = protocolVersion) { case ProtocolVersion.Version2: string[] parts = PGUtil.ReadString(stream).Split(new char[] {':'}, 2); if (parts.Length == 2) { _severity = parts[0].Trim(); _message = parts[1].Trim(); } else { _severity = string.Empty; _message = parts[0].Trim(); } break; case ProtocolVersion.Version3: // Check the messageLength value. If it is 1178686529, this would be the // "FATA" string, which would mean a protocol 2.0 error string. if (PGUtil.ReadInt32(stream) == 1178686529) { string[] v2Parts = ("FATA" + PGUtil.ReadString(stream)).Split(new char[] {':'}, 2); if (v2Parts.Length == 2) { _severity = v2Parts[0].Trim(); _message = v2Parts[1].Trim(); } else { _severity = string.Empty; _message = v2Parts[0].Trim(); } protocol_version = ProtocolVersion.Version2; } else { bool done = false; int fieldCode; while (! done && (fieldCode = stream.ReadByte()) != -1) { switch ((byte)fieldCode) { case 0 : // Null terminator; error message fully consumed. done = true; ; break; case (byte)ErrorFieldTypeCodes.Severity : _severity = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Code : _code = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Message : _message = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Detail : _detail = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Hint : _hint = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Position : _position = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.InternalPosition : _internalPosition = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.InternalQuery : _internalQuery = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Where : _where = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.File : _file = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Line : _line = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Routine : _routine = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.SchemaName : _schemaName = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.TableName : _tableName = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.ColumnName : _columnName = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.DataTypeName : _datatypeName = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.ConstraintName : _constraintName = PGUtil.ReadString(stream); ; break; default: // Unknown error field; consume and discard. PGUtil.ReadString(stream); ; break; } } } break; } } internal NpgsqlError(ProtocolVersion protocolVersion, String errorMessage) { protocol_version = protocolVersion; _message = errorMessage; } /// /// Backend protocol version in use. /// internal ProtocolVersion BackendProtocolVersion { get { return protocol_version; } } } }
X Tutup