LCOV - code coverage report
Current view: top level - core/db - SPDbTransaction.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 46 51 90.2 %
Date: 2024-05-12 00:16:13 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2018-2022 Roman Katuntsev <sbkarr@stappler.org>
       3             : Copyright (c) 2023-2024 Stappler LLC <admin@stappler.dev>
       4             : 
       5             : Permission is hereby granted, free of charge, to any person obtaining a copy
       6             : of this software and associated documentation files (the "Software"), to deal
       7             : in the Software without restriction, including without limitation the rights
       8             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             : copies of the Software, and to permit persons to whom the Software is
      10             : furnished to do so, subject to the following conditions:
      11             : 
      12             : The above copyright notice and this permission notice shall be included in
      13             : all copies or substantial portions of the Software.
      14             : 
      15             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             : THE SOFTWARE.
      22             : **/
      23             : 
      24             : #ifndef STAPPLER_DB_SPDBTRANSACTION_H_
      25             : #define STAPPLER_DB_SPDBTRANSACTION_H_
      26             : 
      27             : #include "SPDbAdapter.h"
      28             : #include "SPDbField.h"
      29             : #include "SPDbQueryList.h"
      30             : 
      31             : namespace STAPPLER_VERSIONIZED stappler::db {
      32             : 
      33             : enum class AccessRoleId {
      34             :         Nobody = 0,
      35             :         Authorized = 1,
      36             :         UserDefined1,
      37             :         UserDefined2,
      38             :         UserDefined3,
      39             :         UserDefined4,
      40             :         UserDefined5,
      41             :         UserDefined6,
      42             :         UserDefined7,
      43             :         UserDefined8,
      44             :         UserDefined9,
      45             :         UserDefined10,
      46             :         UserDefined11,
      47             :         Admin,
      48             :         System,
      49             :         Default,
      50             :         Max = 16,
      51             : };
      52             : 
      53             : class Transaction : public AllocBase {
      54             : public:
      55             :         enum Op {
      56             :                 None = 0,
      57             :                 Id,
      58             :                 Select,
      59             :                 Count,
      60             :                 Remove,
      61             :                 Create,
      62             :                 Save,
      63             :                 Patch,
      64             :                 FieldGet,
      65             :                 FieldSet,
      66             :                 FieldAppend,
      67             :                 FieldClear,
      68             :                 FieldCount,
      69             :                 Delta,
      70             :                 DeltaView,
      71             :                 RemoveFromView,
      72             :                 AddToView,
      73             :                 Max,
      74             :         };
      75             : 
      76             :         struct Data : AllocPool {
      77             :                 Adapter adapter;
      78             :                 pool_t * pool;
      79             :                 Map<String, Value> data;
      80             :                 int status = 0;
      81             : 
      82             :                 mutable Map<int64_t, Value> objects;
      83             :                 mutable AccessRoleId role = AccessRoleId::Nobody;
      84             : 
      85             :                 Data(const Adapter &, memory::pool_t * = nullptr);
      86             :         };
      87             : 
      88             :         struct Stack : AllocPool {
      89             :                 Vector<Data *> stack;
      90             :         };
      91             : 
      92             :         static Op getTransactionOp(Action);
      93             : 
      94             :         static Transaction acquire(const Adapter &);
      95             : 
      96             :         static Transaction acquireIfExists();
      97             :         static Transaction acquireIfExists(memory::pool_t *);
      98             : 
      99             :         Transaction(nullptr_t);
     100             : 
     101             :         void setRole(AccessRoleId) const;
     102             :         AccessRoleId getRole() const;
     103             : 
     104             :         void setStatus(int);
     105             :         int getStatus() const;
     106             : 
     107             :         const Value &setValue(const StringView &, Value &&);
     108             :         const Value &getValue(const StringView &) const;
     109             : 
     110             :         Value setObject(int64_t, Value &&) const;
     111             :         Value getObject(int64_t) const;
     112             : 
     113             :         void setAdapter(const Adapter &);
     114             :         const Adapter &getAdapter() const;
     115             : 
     116       21822 :         explicit operator bool () const { return _data != nullptr && _data->adapter; }
     117             : 
     118             :         Value acquireObject(const Scheme &, uint64_t oid) const;
     119             : 
     120             :         bool perform(const Callback<bool()> & cb) const;
     121             :         bool performAsSystem(const Callback<bool()> & cb) const;
     122             : 
     123             :         bool isInTransaction() const;
     124             :         TransactionStatus getTransactionStatus() const;
     125             : 
     126             :         bool foreach(Worker &, const Query &, const Callback<bool(Value &)> &) const;
     127             : 
     128             :         // returns Array with zero or more Dictionaries with object data or Null value
     129             :         Value select(Worker &, const Query &) const;
     130             : 
     131             :         size_t count(Worker &, const Query &) const;
     132             : 
     133             :         bool remove(Worker &t, uint64_t oid) const;
     134             : 
     135             :         Value create(Worker &, Value &data) const;
     136             :         Value save(Worker &, uint64_t oid, Value &obj, Value &patch, Set<const Field *> &fields) const;
     137             :         Value patch(Worker &, uint64_t oid, Value &data) const;
     138             : 
     139             :         Value field(Action, Worker &, uint64_t oid, const Field &, Value && = Value()) const;
     140             :         Value field(Action, Worker &, const Value &, const Field &, Value && = Value()) const;
     141             : 
     142             :         bool removeFromView(const Scheme &, const FieldView &, uint64_t oid, const Value &obj) const;
     143             :         bool addToView(const Scheme &, const FieldView &, uint64_t oid, const Value &obj, const Value &viewObj) const;
     144             : 
     145             :         int64_t getDeltaValue(const Scheme &); // scheme-based delta
     146             :         int64_t getDeltaValue(const Scheme &, const FieldView &, uint64_t); // view-based delta
     147             : 
     148             :         Vector<int64_t> performQueryListForIds(const QueryList &, size_t count = stappler::maxOf<size_t>()) const;
     149             :         Value performQueryList(const QueryList &, size_t count = stappler::maxOf<size_t>(), bool forUpdate = false) const;
     150             :         Value performQueryListField(const QueryList &, const Field &) const;
     151             : 
     152             :         void scheduleAutoField(const Scheme &, const Field &, uint64_t id) const;
     153             : 
     154             :         void retain() const;
     155             :         void release() const;
     156             : 
     157             : protected:
     158             :         struct TransactionGuard {
     159       15500 :                 TransactionGuard(const Transaction &t) : _t(&t) { _t->retain(); }
     160       15500 :                 ~TransactionGuard() { _t->release(); }
     161             : 
     162             :                 const Transaction *_t;
     163             :         };
     164             : 
     165             :         friend struct TransactionGuard;
     166             :         friend class Worker; // for transaction start|stop and role redefinition
     167             : 
     168             :         bool beginTransaction() const;
     169             :         bool endTransaction() const;
     170             :         void cancelTransaction() const;
     171             : 
     172             :         void clearObjectStorage() const;
     173             : 
     174             :         bool processReturnObject(const Scheme &, Value &) const;
     175             :         bool processReturnField(const Scheme &, const Value &obj, const Field &, Value &) const;
     176             : 
     177             :         bool isOpAllowed(const Scheme &, Op, const Field * = nullptr) const;
     178             : 
     179             :         Transaction(Data *);
     180             : 
     181             :         Data *_data = nullptr;
     182             : };
     183             : 
     184       15500 : inline bool Transaction::perform(const Callback<bool()> &cb) const {
     185       15500 :         TransactionGuard g(*this);
     186             : 
     187       15500 :         if (isInTransaction()) {
     188       12875 :                 if (!cb()) {
     189           0 :                         cancelTransaction();
     190             :                 } else {
     191       12875 :                         return true;
     192             :                 }
     193             :         } else {
     194        2625 :                 if (beginTransaction()) {
     195        2625 :                         if (!cb()) {
     196           0 :                                 cancelTransaction();
     197             :                         }
     198        2625 :                         return endTransaction();
     199             :                 }
     200             :         }
     201           0 :         return false;
     202       15500 : }
     203             : 
     204        4975 : inline bool Transaction::performAsSystem(const Callback<bool()> &cb) const {
     205        4975 :         auto tmpRole = getRole();
     206        4975 :         setRole(AccessRoleId::System);
     207        4975 :         auto ret = perform(cb);
     208        4975 :         setRole(tmpRole);
     209        4975 :         return ret;
     210             : }
     211             : 
     212             : struct AccessRole : public AllocBase {
     213             :         using OnSelect = stappler::ValueWrapper<Function<bool(Worker &, const Query &)>, class OnSelectTag>;
     214             :         using OnCount = stappler::ValueWrapper<Function<bool(Worker &, const Query &)>, class OnCountTag>;
     215             :         using OnCreate = stappler::ValueWrapper<Function<bool(Worker &, Value &obj)>, class OnCreateTag>;
     216             :         using OnPatch = stappler::ValueWrapper<Function<bool(Worker &, int64_t id, Value &obj)>, class OnPatchTag>;
     217             :         using OnSave = stappler::ValueWrapper<Function<bool(Worker &, const Value &obj, Value &patch, Set<const Field *> &fields)>, class OnSaveTag>;
     218             :         using OnRemove = stappler::ValueWrapper<Function<bool(Worker &, const Value &)>, class OnRemoveTag>;
     219             :         using OnField = stappler::ValueWrapper<Function<bool(Action, Worker &, const Value &, const Field &, Value &)>, class OnFieldTag>;
     220             :         using OnReturn = stappler::ValueWrapper<Function<bool(const Scheme &, Value &)>, class OnReturnTag>;
     221             :         using OnReturnField = stappler::ValueWrapper<Function<bool(const Scheme &, const Field &, Value &)>, class OnReturnFieldTag>;
     222             : 
     223             :         template <typename ... Args>
     224             :         static AccessRole Empty(Args && ... args);
     225             : 
     226             :         template <typename ... Args>
     227             :         static AccessRole Default(Args && ... args);
     228             : 
     229             :         template <typename ... Args>
     230             :         static AccessRole Admin(Args && ... args);
     231             : 
     232             :         template <typename T, typename ... Args>
     233             :         AccessRole &define(T &&, Args && ... args);
     234             : 
     235             :         AccessRole &define();
     236             :         AccessRole &define(AccessRoleId);
     237             :         AccessRole &define(Transaction::Op);
     238             :         AccessRole &define(OnSelect &&);
     239             :         AccessRole &define(OnCount &&);
     240             :         AccessRole &define(OnCreate &&);
     241             :         AccessRole &define(OnPatch &&);
     242             :         AccessRole &define(OnSave &&);
     243             :         AccessRole &define(OnRemove &&);
     244             :         AccessRole &define(OnField &&);
     245             :         AccessRole &define(OnReturn &&);
     246             :         AccessRole &define(OnReturnField &&);
     247             : 
     248             :         std::bitset<stappler::toInt(AccessRoleId::Max)> users;
     249             :         std::bitset<stappler::toInt(Transaction::Op::Max)> operations;
     250             : 
     251             :         Function<bool(Worker &, const Query &)> onSelect;
     252             :         Function<bool(Worker &, const Query &)> onCount;
     253             : 
     254             :         Function<bool(Worker &, Value &obj)> onCreate;
     255             :         Function<bool(Worker &, int64_t id, Value &obj)> onPatch;
     256             :         Function<bool(Worker &, const Value &obj, Value &patch, Set<const Field *> &fields)> onSave;
     257             :         Function<bool(Worker &, const Value &)> onRemove;
     258             : 
     259             :         Function<bool(Action, Worker &, const Value &, const Field &, Value &)> onField;
     260             : 
     261             :         Function<bool(const Scheme &, Value &)> onReturn;
     262             :         Function<bool(const Scheme &, const Field &, Value &)> onReturnField;
     263             : };
     264             : 
     265             : template <typename T, typename ... Args>
     266         150 : inline AccessRole &AccessRole::define(T &&v, Args && ... args) {
     267         150 :         define(std::forward<T>(v));
     268         150 :         define(std::forward<Args>(args)...);
     269         150 :         return *this;
     270             : }
     271             : 
     272             : template <typename ... Args>
     273          50 : AccessRole AccessRole::Empty(Args && ... args) {
     274          50 :         AccessRole ret;
     275          50 :         ret.define(std::forward<Args>(args)...);
     276          50 :         return ret;
     277           0 : }
     278             : 
     279             : template <typename ... Args>
     280             : AccessRole AccessRole::Default(Args && ... args) {
     281             :         AccessRole ret;
     282             : 
     283             :         ret.operations.set(Transaction::Op::Id);
     284             :         ret.operations.set(Transaction::Op::Select);
     285             :         ret.operations.set(Transaction::Op::Count);
     286             :         ret.operations.set(Transaction::Op::Delta);
     287             :         ret.operations.set(Transaction::Op::DeltaView);
     288             :         ret.operations.set(Transaction::Op::FieldGet);
     289             :         ret.operations.set(Transaction::Op::FieldCount);
     290             : 
     291             :         ret.define(std::forward<Args>(args)...);
     292             : 
     293             :         return ret;
     294             : }
     295             : 
     296             : template <typename ... Args>
     297         125 : AccessRole AccessRole::Admin(Args && ... args) {
     298         125 :         AccessRole ret;
     299             : 
     300         125 :         ret.operations.set(Transaction::Op::Id);
     301         125 :         ret.operations.set(Transaction::Op::Select);
     302         125 :         ret.operations.set(Transaction::Op::Count);
     303         125 :         ret.operations.set(Transaction::Op::Delta);
     304         125 :         ret.operations.set(Transaction::Op::DeltaView);
     305         125 :         ret.operations.set(Transaction::Op::FieldGet);
     306             : 
     307         125 :         ret.operations.set(Transaction::Op::Remove);
     308         125 :         ret.operations.set(Transaction::Op::Create);
     309         125 :         ret.operations.set(Transaction::Op::Save);
     310         125 :         ret.operations.set(Transaction::Op::Patch);
     311         125 :         ret.operations.set(Transaction::Op::FieldSet);
     312         125 :         ret.operations.set(Transaction::Op::FieldAppend);
     313         125 :         ret.operations.set(Transaction::Op::FieldClear);
     314         125 :         ret.operations.set(Transaction::Op::FieldCount);
     315         125 :         ret.operations.set(Transaction::Op::RemoveFromView);
     316         125 :         ret.operations.set(Transaction::Op::AddToView);
     317             : 
     318         125 :         ret.define(std::forward<Args>(args)...);
     319             : 
     320         125 :         return ret;
     321           0 : }
     322             : 
     323             : }
     324             : 
     325             : #endif /* STAPPLER_DB_SPDBTRANSACTION_H_ */

Generated by: LCOV version 1.14