// 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.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Reflection;
using Npgsql.BackendMessages;
namespace Npgsql
{
///
/// The exception that is thrown when the PostgreSQL backend reports errors.
/// Note that other errors (network issues, Npgsql client-side problems) are reported as regular
/// .NET exceptions.
///
///
/// See http://www.postgresql.org/docs/current/static/errcodes-appendix.html,
/// http://www.postgresql.org/docs/current/static/protocol-error-fields.html
///
public sealed class NpgsqlException : DbException
{
readonly ErrorOrNoticeMessage _msg;
Dictionary _data;
#region Message Fields
///
/// Severity of the error or notice.
/// Always present.
///
public ErrorSeverity Severity { get { return _msg.Severity; } }
///
/// The SQLSTATE code for the error.
///
///
/// Always present.
/// See http://www.postgresql.org/docs/current/static/errcodes-appendix.html
///
public string Code { get { return _msg.Code; } }
///
/// The primary human-readable error message. This should be accurate but terse.
///
///
/// Always present.
///
public string MessageText { get { return _msg.Message; } }
///
/// An optional secondary error message carrying more detail about the problem.
/// May run to multiple lines.
///
public string Detail { get { return _msg.Detail; } }
///
/// 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.
/// May run to multiple lines.
///
public string Hint { get { return _msg.Hint; } }
///
/// 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.
/// 0 means not provided.
///
public int Position { get { return _msg.Position; } }
///
/// This is defined the same as the field, but it is used when the cursor position refers to an internally generated command rather than the one submitted by the client.
/// The field will always appear when this field appears.
/// 0 means not provided.
///
public int InternalPosition { get { return _msg.InternalPosition; } }
///
/// The text of a failed internally-generated command.
/// This could be, for example, a SQL query issued by a PL/pgSQL function.
///
public string InternalQuery { get { return _msg.InternalQuery; } }
///
/// An indication of the context in which the error occurred.
/// Presently this includes a call stack traceback of active PL functions.
/// The trace is one entry per line, most recent first.
///
public string Where { get { return _msg.Where; } }
///
/// If the error was associated with a specific database object, the name of the schema containing that object, if any.
///
/// PostgreSQL 9.3 and up.
public string SchemaName { get { return _msg.SchemaName; } }
///
/// 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.)
///
/// PostgreSQL 9.3 and up.
public string TableName { get { return _msg.TableName; } }
///
/// 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.)
///
/// PostgreSQL 9.3 and up.
public string ColumnName { get { return _msg.ColumnName; } }
///
/// 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.)
///
/// PostgreSQL 9.3 and up.
public string DataTypeName { get { return _msg.DataTypeName; } }
///
/// 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.)
///
/// PostgreSQL 9.3 and up.
public string ConstraintName { get { return _msg.ConstraintName; } }
///
/// The file name of the source-code location where the error was reported.
///
/// PostgreSQL 9.3 and up.
public string File { get { return _msg.File; } }
///
/// The line number of the source-code location where the error was reported.
///
public string Line { get { return _msg.Line; } }
///
/// The name of the source-code routine reporting the error.
///
public string Routine { get { return _msg.Routine; } }
#endregion
internal NpgsqlException(NpgsqlBuffer buf)
{
_msg = new ErrorOrNoticeMessage(buf);
}
///
/// Gets a the PostgreSQL error message and code.
///
public override string Message
{
get { return Code + ": " + MessageText; }
}
///
/// Gets a collection of key/value pairs that provide additional PostgreSQL fields about the exception.
///
public override IDictionary Data
{
get
{
return _data ?? (_data = (
from p in typeof (ErrorOrNoticeMessage).GetProperties(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance)
let k = p.Name
let v = p.GetValue(_msg)
where p.GetValue(_msg) != null
where (k != "Position" && k != "InternalPosition") || ((int)v) != 0
select new {Key = k, Value = v}
).ToDictionary(kv => kv.Key, kv => kv.Value)
);
}
}
[ContractInvariantMethod]
void ObjectInvariants()
{
Contract.Invariant(Severity == ErrorSeverity.Error ||
Severity == ErrorSeverity.Fatal ||
Severity == ErrorSeverity.Panic);
}
}
}