aboutsummaryrefslogtreecommitdiff
path: root/odb/oracle/transaction-impl.cxx
blob: 4751366cb82c1c7e94afc9cd21f56d6b28276588 (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
117
118
119
120
121
122
123
124
125
126
// file      : odb/oracle/transaction-impl.cxx
// author    : Constantin Michael <constantin@codesynthesis.com>
// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
// license   : ODB NCUEL; see accompanying LICENSE file

#include <cassert>

#include <oci.h>

#include <odb/oracle/database.hxx>
#include <odb/oracle/connection.hxx>
#include <odb/oracle/error.hxx>
#include <odb/oracle/exceptions.hxx>
#include <odb/oracle/transaction-impl.hxx>

namespace odb
{
  namespace oracle
  {
    transaction_impl::
    transaction_impl (database_type& db)
        : odb::transaction_impl (db)
    {
    }

    transaction_impl::
    transaction_impl (connection_ptr c)
        : odb::transaction_impl (c->database (), *c), connection_ (c)
    {
    }

    transaction_impl::
    ~transaction_impl ()
    {
    }

    void transaction_impl::
    start ()
    {
      database_type& db (static_cast<database_type&> (database_));

      if (connection_ == 0)
      {
        connection_ = db.connection ();
        odb::transaction_impl::connection_ = connection_.get ();
      }

      OCISvcCtx* h (connection_->handle ());
      OCIError* err (connection_->error_handle ());

      // Allocate a transaction handle if there is none associated with
      // the connection.
      //
      OCITrans* t (0);
      sword s (OCIAttrGet (h,
                           OCI_HTYPE_SVCCTX,
                           reinterpret_cast<void*> (&t),
                           0,
                           OCI_ATTR_TRANS,
                           err));

      if (s == OCI_ERROR || s == OCI_INVALID_HANDLE)
        translate_error (err, s);
      else if (t == 0)
      {
        auto_handle<OCITrans> auto_t;

        s = OCIHandleAlloc (db.environment (),
                            reinterpret_cast<void**> (&t),
                            OCI_HTYPE_TRANS,
                            0,
                            0);

        if (s != OCI_SUCCESS)
          throw invalid_oci_handle ();

        auto_t.reset (t);

        s = OCIAttrSet (h,
                        OCI_HTYPE_SVCCTX,
                        reinterpret_cast<void*> (t),
                        0,
                        OCI_ATTR_TRANS,
                        err);

        if (s == OCI_ERROR || s == OCI_INVALID_HANDLE)
          translate_error (err, s);

        auto_t.release ();
      }

      // We never use OCITransDetach so the timeout parameter is
      // of no consequence.
      //
      s = OCITransStart (h,
                         err,
                         0,
                         OCI_TRANS_NEW);

      if (s == OCI_ERROR || s == OCI_INVALID_HANDLE)
        translate_error (err, s);
    }

    void transaction_impl::
    commit ()
    {
      sword s (OCITransCommit (connection_->handle (),
                               connection_->error_handle (),
                               OCI_DEFAULT));

      if (s == OCI_ERROR || s == OCI_INVALID_HANDLE)
        translate_error (connection_->error_handle (), s);
    }

    void transaction_impl::
    rollback ()
    {
      sword s (OCITransRollback (connection_->handle (),
                                 connection_->error_handle (),
                                 OCI_DEFAULT));

      if (s == OCI_ERROR || s == OCI_INVALID_HANDLE)
        translate_error (connection_->error_handle (), s);
    }
  }
}