aboutsummaryrefslogtreecommitdiff
path: root/odb/pgsql/error.cxx
blob: 3dfb365b4fd1ec48408312a718fcadd797d398ea (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
// file      : odb/pgsql/error.cxx
// copyright : Copyright (c) 2005-2019 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_error (connection& c, PGresult* r)
    {
      if (!r)
      {
        if (CONNECTION_BAD == PQstatus (c.handle ()))
        {
          c.mark_failed ();
          throw connection_lost ();
        }
        else
          throw bad_alloc ();
      }

      string msg;
      {
        // Can be NULL in case of PGRES_BAD_RESPONSE.
        //
        const char* m (PQresultErrorMessage (r));
        msg = (m != 0 ? m : "bad server response");

        // Get rid of a trailing newline if there is one.
        //
        string::size_type n (msg.size ());
        if (n != 0 && msg[n - 1] == '\n')
          msg.resize (n - 1);
      }

      switch (PQresultStatus (r))
      {
      case PGRES_BAD_RESPONSE:
        {
          throw database_exception (msg);
        }
      case PGRES_FATAL_ERROR:
        {
          string ss;
          {
            const char* s (PQresultErrorField (r, PG_DIAG_SQLSTATE));
            ss = (s != 0 ? s : "?????");
          }

          // Deadlock detected.
          //
          if (ss == "40001" || ss == "40P01")
            throw deadlock ();
          else if (CONNECTION_BAD == PQstatus (c.handle ()))
          {
            c.mark_failed ();
            throw connection_lost ();
          }
          else
            throw database_exception (ss, msg);
        }
      default:
        assert (false);
        break;
      }
    }
  }
}