X Tutup
using System; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; using System.Text; using JetBrains.Annotations; using Npgsql.BackendMessages; #pragma warning disable CA1032 namespace Npgsql { /// /// The exception that is thrown when the PostgreSQL backend reports errors (e.g. query /// SQL issues, constraint violations). /// /// /// This exception only corresponds to a PostgreSQL-delivered error. /// Other errors (e.g. network issues) will be raised via , /// and purely Npgsql-related issues which aren't related to the server will be raised /// via the standard CLR exceptions (e.g. ArgumentException). /// /// See http://www.postgresql.org/docs/current/static/errcodes-appendix.html, /// http://www.postgresql.org/docs/current/static/protocol-error-fields.html /// [Serializable] public sealed class PostgresException : NpgsqlException { /// /// Creates a new instance. /// /// /// Exists for backwards compat with 4.0, has been removed for 5.0. /// [Obsolete] public PostgresException() : this(string.Empty, string.Empty, string.Empty, string.Empty) {} /// /// Creates a new instance. /// public PostgresException(string messageText, string severity, string invariantSeverity, string sqlState) { MessageText = messageText; Severity = severity; InvariantSeverity = invariantSeverity; SqlState = sqlState; } PostgresException(ErrorOrNoticeMessage msg) { Severity = msg.Severity; InvariantSeverity = msg.InvariantSeverity; SqlState = msg.Code; MessageText = msg.Message; Detail = msg.Detail; Hint = msg.Hint; Position = msg.Position; InternalPosition = msg.InternalPosition; InternalQuery = msg.InternalQuery; Where = msg.Where; SchemaName = msg.SchemaName; TableName = msg.TableName; ColumnName = msg.ColumnName; DataTypeName = msg.DataTypeName; ConstraintName = msg.ConstraintName; File = msg.File; Line = msg.Line; Routine = msg.Routine; AddData(nameof(Severity), Severity); AddData(nameof(InvariantSeverity), InvariantSeverity); AddData(nameof(SqlState), SqlState); AddData(nameof(MessageText), MessageText); AddData(nameof(Detail), Detail); AddData(nameof(Hint), Hint); AddData(nameof(Position), Position); AddData(nameof(InternalPosition), InternalPosition); AddData(nameof(InternalQuery), InternalQuery); AddData(nameof(Where), Where); AddData(nameof(SchemaName), SchemaName); AddData(nameof(TableName), TableName); AddData(nameof(ColumnName), ColumnName); AddData(nameof(DataTypeName), DataTypeName); AddData(nameof(ConstraintName), ConstraintName); AddData(nameof(File), File); AddData(nameof(Line), Line); AddData(nameof(Routine), Routine); void AddData(string key, T value) { if (!EqualityComparer.Default.Equals(value, default!)) Data.Add(key, value); } } internal static PostgresException Load(NpgsqlReadBuffer buf) => new PostgresException(ErrorOrNoticeMessage.Load(buf)); internal PostgresException(SerializationInfo info, StreamingContext context) : base(info, context) { Severity = GetValue(nameof(Severity)); InvariantSeverity = GetValue(nameof(InvariantSeverity)); SqlState = GetValue(nameof(SqlState)); MessageText = GetValue(nameof(MessageText)); Detail = GetValue(nameof(Detail)); Hint = GetValue(nameof(Hint)); Position = GetValue(nameof(Position)); InternalPosition = GetValue(nameof(InternalPosition)); InternalQuery = GetValue(nameof(InternalQuery)); Where = GetValue(nameof(Where)); SchemaName = GetValue(nameof(SchemaName)); TableName = GetValue(nameof(TableName)); ColumnName = GetValue(nameof(ColumnName)); DataTypeName = GetValue(nameof(DataTypeName)); ConstraintName = GetValue(nameof(ConstraintName)); File = GetValue(nameof(File)); Line = GetValue(nameof(Line)); Routine = GetValue(nameof(Routine)); T GetValue(string propertyName) => (T)info.GetValue(propertyName, typeof(T))!; } /// /// Populates a with the data needed to serialize the target object. /// /// The to populate with data. /// The destination (see ) for this serialization. public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue(nameof(Severity), Severity); info.AddValue(nameof(InvariantSeverity), InvariantSeverity); info.AddValue(nameof(SqlState), SqlState); info.AddValue(nameof(MessageText), MessageText); info.AddValue(nameof(Detail), Detail); info.AddValue(nameof(Hint), Hint); info.AddValue(nameof(Position), Position); info.AddValue(nameof(InternalPosition), InternalPosition); info.AddValue(nameof(InternalQuery), InternalQuery); info.AddValue(nameof(Where), Where); info.AddValue(nameof(SchemaName), SchemaName); info.AddValue(nameof(TableName), TableName); info.AddValue(nameof(ColumnName), ColumnName); info.AddValue(nameof(DataTypeName), DataTypeName); info.AddValue(nameof(ConstraintName), ConstraintName); info.AddValue(nameof(File), File); info.AddValue(nameof(Line), Line); info.AddValue(nameof(Routine), Routine); } /// public override string ToString() { var builder = new StringBuilder(base.ToString()) .AppendLine().Append(" Exception data:"); AppendLine(nameof(Severity), Severity); AppendLine(nameof(SqlState), SqlState); AppendLine(nameof(MessageText), MessageText); AppendLine(nameof(Detail), Detail); AppendLine(nameof(Hint), Hint); AppendLine(nameof(Position), Position); AppendLine(nameof(InternalPosition), InternalPosition); AppendLine(nameof(InternalQuery), InternalQuery); AppendLine(nameof(Where), Where); AppendLine(nameof(SchemaName), SchemaName); AppendLine(nameof(TableName), TableName); AppendLine(nameof(ColumnName), ColumnName); AppendLine(nameof(DataTypeName), DataTypeName); AppendLine(nameof(ConstraintName), ConstraintName); AppendLine(nameof(File), File); AppendLine(nameof(Line), Line); AppendLine(nameof(Routine), Routine); return builder.ToString(); void AppendLine(string propertyName, T propertyValue) { if (!EqualityComparer.Default.Equals(propertyValue, default!)) builder.AppendLine().Append(" ").Append(propertyName).Append(": ").Append(propertyValue); } } /// /// Gets a the PostgreSQL error message and code. /// public override string Message => SqlState + ": " + MessageText; /// /// Specifies whether the exception is considered transient, that is, whether retrying to operation could /// succeed (e.g. a network error). Check . /// public override bool IsTransient { get { switch (SqlState) { case PostgresErrorCodes.InsufficientResources: case PostgresErrorCodes.DiskFull: case PostgresErrorCodes.OutOfMemory: case PostgresErrorCodes.TooManyConnections: case PostgresErrorCodes.ConfigurationLimitExceeded: case PostgresErrorCodes.CannotConnectNow: case PostgresErrorCodes.SystemError: case PostgresErrorCodes.IoError: case PostgresErrorCodes.SerializationFailure: case PostgresErrorCodes.LockNotAvailable: case PostgresErrorCodes.ObjectInUse: case PostgresErrorCodes.ObjectNotInPrerequisiteState: case PostgresErrorCodes.ConnectionException: case PostgresErrorCodes.ConnectionDoesNotExist: case PostgresErrorCodes.ConnectionFailure: case PostgresErrorCodes.SqlClientUnableToEstablishSqlConnection: case PostgresErrorCodes.SqlServerRejectedEstablishmentOfSqlConnection: case PostgresErrorCodes.TransactionResolutionUnknown: return true; default: return false; } } } /// /// Returns the statement which triggered this exception. /// public NpgsqlStatement? Statement { get; internal set; } #region Message Fields /// /// Severity of the error or notice. /// Always present. /// [PublicAPI] public string Severity { get; } /// /// Severity of the error or notice, not localized. /// Always present since PostgreSQL 9.6. /// [PublicAPI] public string InvariantSeverity { get; } /// /// The SQLSTATE code for the error. /// /// /// Always present. /// Constants are defined in . /// See http://www.postgresql.org/docs/current/static/errcodes-appendix.html /// [PublicAPI] public string SqlState { get; } /// /// The SQLSTATE code for the error. /// /// /// Always present. /// Constants are defined in . /// See http://www.postgresql.org/docs/current/static/errcodes-appendix.html /// [PublicAPI, Obsolete("Use SqlState instead")] public string Code => SqlState; /// /// The primary human-readable error message. This should be accurate but terse. /// /// /// Always present. /// [PublicAPI] public string MessageText { get; } /// /// An optional secondary error message carrying more detail about the problem. /// May run to multiple lines. /// [PublicAPI] public string? Detail { get; } /// /// 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. /// [PublicAPI] public string? Hint { get; } /// /// 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. /// [PublicAPI] public int Position { get; } /// /// 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. /// [PublicAPI] public int InternalPosition { get; } /// /// The text of a failed internally-generated command. /// This could be, for example, a SQL query issued by a PL/pgSQL function. /// [PublicAPI] public string? InternalQuery { get; } /// /// 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. /// [PublicAPI] public string? Where { get; } /// /// 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. [PublicAPI] public string? SchemaName { get; } /// /// 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. [PublicAPI] public string? TableName { get; } /// /// 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. [PublicAPI] public string? ColumnName { get; } /// /// 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. [PublicAPI] public string? DataTypeName { get; } /// /// 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. [PublicAPI] public string? ConstraintName { get; } /// /// The file name of the source-code location where the error was reported. /// /// PostgreSQL 9.3 and up. [PublicAPI] public string? File { get; } /// /// The line number of the source-code location where the error was reported. /// [PublicAPI] public string? Line { get; } /// /// The name of the source-code routine reporting the error. /// [PublicAPI] public string? Routine { get; } #endregion } }
X Tutup