aboutsummaryrefslogtreecommitdiff
path: root/odb/pgsql/error.cxx
blob: f65cbee010c1a71209598c6ec893efcf7b0ddff2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// file      : odb/pgsql/errors.cxx
// author    : Constantin Michael <constantin@codesynthesis.com>
// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC
// license   : GNU GPL v2; see accompanying LICENSE file

#include <string>
#include <cassert>

#include <odb/pgsql/error.hxx>
#include <odb/pgsql/exceptions.hxx>
#include <odb/pgsql/connection.hxx>

using namespace std;

namespace odb
{
  namespace pgsql
  {
    void
    translate_connection_error (connection& c)
    {
      PGconn* h (c.handle ());

      assert (CONNECTION_BAD == PQstatus (h));

      if (const char* m = PQerrorMessage (h))
        throw database_exception (m);
      else
        throw database_exception ("unknown error");
    }

    void
    translate_result_error_ (connection& c,
                             ExecStatusType status = PGRES_EMPTY_QUERY,
                             const char* sqlstate = 0,
                             const char* error_message = 0)
    {
      PGconn* h (c.handle ());

      switch (status)
      {
      case PGRES_BAD_RESPONSE:
        {
          if (error_message != 0)
            throw database_exception (error_message);
          else
            throw database_exception ("bad server response");
        }

      case PGRES_FATAL_ERROR:
        {
          assert (sqlstate);
          assert (error_message);

          // Deadlock detected.
          //
          if (std::string ("40P01") == sqlstate)
            throw deadlock ();

          else if (CONNECTION_BAD == PQstatus (h))
            throw connection_lost ();

          else
            throw database_exception (sqlstate, error_message);
        }

      default:
        {
          if (CONNECTION_BAD == PQstatus (h))
            throw connection_lost ();
          else
            throw bad_alloc ();
        }
      };
    }

    bool
    is_good_result (PGresult* r, ExecStatusType* s)
    {
      if (r != 0)
      {
        ExecStatusType status (PQresultStatus (r));

        if (s != 0)
          *s = status;

        return
          *s != PGRES_BAD_RESPONSE &&
          *s != PGRES_NONFATAL_ERROR &&
          *s != PGRES_FATAL_ERROR;
      }

      return false;
    }

    void
    translate_result_error (connection& c,
                            PGresult* r,
                            ExecStatusType s,
                            bool clear_result)
    {
      if (!r)
        translate_result_error_ (c);
      else
      {
        const char* ss (PQresultErrorField (r, PG_DIAG_SQLSTATE));
        const char* m (PQresultErrorMessage (r));

        if (clear_result)
          PQclear (r);

        translate_result_error_ (c, s, ss, m);
      }
    }
  }
}