Stroika Library 3.0d18
 
Loading...
Searching...
No Matches
SQL/Transaction.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Database_SQL_Transaction_h_
5#define _Stroika_Foundation_Database_SQL_Transaction_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
13
14/**
15 * \file
16 *
17 * \note Code-Status: <a href="Code-Status.md#Alpha">Alpha</a>
18 */
19
20namespace Stroika::Foundation::Database::SQL {
21
22 using Characters::String;
23
24 /**
25 * \note Transactions are not required. This is for explicit transactions. If you omit
26 * using transactions, sqlite creates mini transactions automatically for each statement.
27 *
28 * \note Nested transactions not supported (for sqlite - add featre for detecting if engine supports)
29 *
30 * \par Example Usage
31 * \code
32 * T DB::AddOrMergeUpdate (ORM::TableConnection<T>* dbConnTable, const T& d)
33 * {
34 * SQL::Transaction t{dbConnTable->connection ()->mkTransaction ()};
35 * std::optional<T> result;
36 * if (auto dbObj = dbConnTable->Get (id)) {
37 * result = T::Merge (*dbObj, d);
38 * dbConnTable->Update (*result);
39 * }
40 * else {
41 * result = d;
42 * dbConnTable->AddNew (d);
43 * }
44 * t.Commit ();
45 * return Memory::ValueOf (result);
46 * }
47 * \endcode
48 *
49 * \note pointless to ever create Transaction and not use, so [[nodiscard]] appropriate
50 */
51 class [[nodiscard]] Transaction {
52 public:
53 class IRep;
54
55 public:
56 /**
57 */
58 Transaction (Transaction&&) = default;
59 Transaction (const Transaction&) = delete;
60
61 protected:
62 Transaction (unique_ptr<IRep>&& rep);
63
64 public:
65 /**
66 * If Commit() has not already been called, this automatically calls Rollback() and suppresses any
67 * exceptions.
68 */
69 ~Transaction ();
70
71 public:
72 /**
73 */
74 nonvirtual Transaction& operator= (const Transaction&) = delete;
75
76 public:
77 /**
78 * Cause the transaction to end successfully, flushing to the database.
79 * It is (an assertion) error to call this multiple times. And calling OMITTING
80 * a call before the destructor causes the transaction to Rollback.
81 */
82 nonvirtual void Commit ();
83
84 public:
85 /**
86 * This cannot be called after a rollback or commit.
87 *
88 * This causes no data to be written for the commands already issued in the transaction.
89 *
90 * This is equivalent to just destroying this object, except that it can propagate
91 * exceptions if needed, whereas a destructor cannot.
92 */
93 nonvirtual void Rollback ();
94
95 public:
96 /**
97 * @see Characters::ToString ()
98 */
99 nonvirtual String ToString () const;
100
101 protected:
102 [[no_unique_address]] Debug::AssertExternallySynchronizedMutex _fThisAssertExternallySynchronized;
103 unique_ptr<IRep> _fRep;
104 };
105
106 /**
107 * Transaction::IRep provides an (abstract) API for transactions, supported by each backend connection type.
108 *
109 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety-For-Envelope-But-Ambiguous-Thread-Safety-For-Letter">C++-Standard-Thread-Safety-For-Envelope-But-Ambiguous-Thread-Safety-For-Letter/a>
110 * But though each Statement can only be accessed from a single thread at a time, the underlying database may be
111 * threadsafe (even if accessed across processes).
112 */
114 public:
115 /**
116 */
117 virtual ~IRep () = default;
118
119 public:
120 /**
121 * Cause the transaction to end successfully, flushing to the database.
122 * It is (an assertion) error to call this multiple times. And calling OMITTING
123 * a call before the destructor causes the transaction to Rollback.
124 */
125 virtual void Commit () = 0;
126
127 public:
128 /**
129 * This cannot be called after a rollback or commit.
130 *
131 * This causes no data to be written for the commands already issued in the transaction.
132 *
133 * This is equivalent to just destroying this object, except that it can propagate
134 * exceptions if needed, whereas a destructor cannot.
135 */
136 virtual void Rollback () = 0;
137
138 public:
139 /**
140 * \note Common::DefaultNames<> supported
141 */
142 enum class Disposition {
143 eNone,
144 eRolledBack,
145 eCompleted,
146 eFailed,
147
148 Stroika_Define_Enum_Bounds (eNone, eFailed)
149 };
150
151 public:
152 /**
153 * Mostly this reports eNone or something else. But extra status could be useful for logging.
154 */
155 virtual Disposition GetDisposition () const = 0;
156
157 protected:
158 [[no_unique_address]] Debug::AssertExternallySynchronizedMutex _fThisAssertExternallySynchronized;
159
160 private:
161 friend class Transaction;
162 };
163
164}
165
166/*
167 ********************************************************************************
168 ***************************** Implementation Details ***************************
169 ********************************************************************************
170 */
171#include "Transaction.inl"
172
173#endif /*_Stroika_Foundation_Database_SQL_Transaction_h_*/
#define Stroika_Define_Enum_Bounds(FIRST_ITEM, LAST_ITEM)
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
NOT a real mutex - just a debugging infrastructure support tool so in debug builds can be assured thr...