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_SPDBWORKER_H_
25 : #define STAPPLER_DB_SPDBWORKER_H_
26 :
27 : #include "SPDbField.h"
28 : #include "SPDbQueryList.h"
29 : #include "SPDbTransaction.h"
30 :
31 : namespace STAPPLER_VERSIONIZED stappler::db {
32 :
33 : enum class UpdateFlags : uint32_t {
34 : None = 0,
35 : Protected = 1 << 0,
36 : NoReturn = 1 << 1,
37 : GetAll = 1 << 2,
38 : GetForUpdate = 1 << 3,
39 : Cached = 1 << 4, // cache 'get' result within transaction
40 : };
41 :
42 : SP_DEFINE_ENUM_AS_MASK(UpdateFlags)
43 :
44 : struct Conflict {
45 : enum Flags {
46 : None,
47 : DoNothing,
48 : WithoutCondition,
49 : };
50 :
51 : static Conflict update(StringView);
52 :
53 : String field;
54 : Query::Select condition;
55 : Vector<String> mask;
56 : Flags flags = DoNothing;
57 :
58 : Conflict(Conflict::Flags);
59 : Conflict(StringView field, Query::Select &&, Flags = None);
60 : Conflict(StringView field, Query::Select &&, Vector<String> &&);
61 :
62 : Conflict &setFlags(Flags);
63 : };
64 :
65 : SP_DEFINE_ENUM_AS_MASK(Conflict::Flags)
66 :
67 : class Worker : public AllocBase {
68 : public:
69 : using FieldCallback = stappler::Callback<void(const StringView &name, const Field *f)>;
70 :
71 : struct RequiredFields {
72 : const Scheme *scheme = nullptr;
73 : Vector<const Field *> includeFields;
74 : Vector<const Field *> excludeFields;
75 : bool includeNone = false;
76 : bool includeAll = false;
77 :
78 : void clear();
79 : void reset(const Scheme &);
80 :
81 : void include(std::initializer_list<StringView>);
82 : void include(const Set<const Field *> &);
83 : void include(const StringView &);
84 : void include(const Field *);
85 :
86 : void exclude(std::initializer_list<StringView>);
87 : void exclude(const Set<const Field *> &);
88 : void exclude(const StringView &);
89 : void exclude(const Field *);
90 : };
91 :
92 : struct ConditionData {
93 : Comparation compare = Comparation::Equal;
94 : Value value1;
95 : Value value2;
96 : const Field *field = nullptr;
97 :
98 100 : ConditionData() { }
99 : ConditionData(const Query::Select &, const Field *);
100 : ConditionData(Query::Select &&, const Field *);
101 :
102 : void set(Query::Select &&, const Field *);
103 : void set(const Query::Select &, const Field *);
104 : };
105 :
106 : struct ConflictData {
107 : const Field *field;
108 : ConditionData condition;
109 : Vector<const Field *> mask;
110 : Conflict::Flags flags = Conflict::None;
111 :
112 100 : bool isDoNothing() const { return (flags & Conflict::DoNothing) != Conflict::None; }
113 50 : bool hasCondition() const { return (flags & Conflict::WithoutCondition) == Conflict::None; }
114 : };
115 :
116 : Worker(const Scheme &, const Adapter &);
117 : Worker(const Scheme &, const Transaction &);
118 : explicit Worker(const Worker &);
119 :
120 : Worker(Worker &&) = delete;
121 : Worker& operator=(Worker &&) = delete;
122 : Worker& operator=(const Worker &) = delete;
123 :
124 : ~Worker();
125 :
126 : template <typename Callback>
127 : bool perform(const Callback &) const;
128 :
129 : const Transaction &transaction() const;
130 : const Scheme &scheme() const;
131 :
132 : const ApplicationInterface *getApplicationInterface() const;
133 :
134 : void includeNone();
135 :
136 : template <typename T>
137 175 : Worker& include(T && t) { _required.include(std::forward<T>(t)); return *this; }
138 :
139 : template <typename T>
140 : Worker& exclude(T && t) { _required.exclude(std::forward<T>(t)); return *this; }
141 :
142 : void clearRequiredFields();
143 :
144 : bool shouldIncludeNone() const;
145 : bool shouldIncludeAll() const;
146 :
147 : Worker &asSystem();
148 : bool isSystem() const;
149 :
150 : const RequiredFields &getRequiredFields() const;
151 : const Map<const Field *, ConflictData> &getConflicts() const;
152 : const Vector<ConditionData> &getConditions() const;
153 :
154 : public:
155 : Value get(uint64_t oid, UpdateFlags = UpdateFlags::None);
156 : Value get(const StringView &alias, UpdateFlags = UpdateFlags::None);
157 : Value get(const Value &id, UpdateFlags = UpdateFlags::None);
158 :
159 : Value get(uint64_t oid, StringView, UpdateFlags = UpdateFlags::None);
160 : Value get(const StringView &alias, StringView, UpdateFlags = UpdateFlags::None);
161 : Value get(const Value &id, StringView, UpdateFlags = UpdateFlags::None);
162 :
163 : Value get(uint64_t oid, std::initializer_list<StringView> &&fields, UpdateFlags = UpdateFlags::None);
164 : Value get(const StringView &alias, std::initializer_list<StringView> &&fields, UpdateFlags = UpdateFlags::None);
165 : Value get(const Value &id, std::initializer_list<StringView> &&fields, UpdateFlags = UpdateFlags::None);
166 :
167 : Value get(uint64_t oid, std::initializer_list<const char *> &&fields, UpdateFlags = UpdateFlags::None);
168 : Value get(const StringView &alias, std::initializer_list<const char *> &&fields, UpdateFlags = UpdateFlags::None);
169 : Value get(const Value &id, std::initializer_list<const char *> &&fields, UpdateFlags = UpdateFlags::None);
170 :
171 : Value get(uint64_t oid, std::initializer_list<const Field *> &&fields, UpdateFlags = UpdateFlags::None);
172 : Value get(const StringView &alias, std::initializer_list<const Field *> &&fields, UpdateFlags = UpdateFlags::None);
173 : Value get(const Value &id, std::initializer_list<const Field *> &&fields, UpdateFlags = UpdateFlags::None);
174 :
175 : Value get(uint64_t oid, SpanView<const Field *> fields, UpdateFlags = UpdateFlags::None);
176 : Value get(const StringView &alias, SpanView<const Field *> fields, UpdateFlags = UpdateFlags::None);
177 : Value get(const Value &id, SpanView<const Field *> fields, UpdateFlags = UpdateFlags::None);
178 :
179 : bool foreach(const Query &, const Callback<bool(Value &)> &, UpdateFlags = UpdateFlags::None);
180 :
181 : // returns Array with zero or more Dictionaries with object data or Null value
182 : Value select(const Query &, UpdateFlags = UpdateFlags::None);
183 :
184 : // returns Dictionary with single object data or Null value
185 : Value create(const Value &data, bool isProtected = false);
186 : Value create(const Value &data, UpdateFlags);
187 : Value create(const Value &data, UpdateFlags, const Conflict &);
188 : Value create(const Value &data, UpdateFlags, const Vector<Conflict> &);
189 : Value create(const Value &data, Conflict::Flags);
190 : Value create(const Value &data, const Conflict &);
191 : Value create(const Value &data, const Vector<Conflict> &);
192 :
193 : Value update(uint64_t oid, const Value &data, bool isProtected = false);
194 : Value update(const Value & obj, const Value &data, bool isProtected = false);
195 :
196 : Value update(uint64_t oid, const Value &data, UpdateFlags);
197 : Value update(const Value & obj, const Value &data, UpdateFlags);
198 :
199 : Value update(uint64_t oid, const Value &data, UpdateFlags, const Query::Select &);
200 : Value update(const Value & obj, const Value &data, UpdateFlags, const Query::Select &);
201 : Value update(uint64_t oid, const Value &data, UpdateFlags, const Vector<Query::Select> &);
202 : Value update(const Value & obj, const Value &data, UpdateFlags, const Vector<Query::Select> &);
203 :
204 : Value update(uint64_t oid, const Value &data, const Query::Select &);
205 : Value update(const Value & obj, const Value &data, const Query::Select &);
206 : Value update(uint64_t oid, const Value &data, const Vector<Query::Select> &);
207 : Value update(const Value & obj, const Value &data, const Vector<Query::Select> &);
208 :
209 : bool remove(uint64_t oid);
210 : bool remove(const Value &);
211 :
212 : size_t count();
213 : size_t count(const Query &);
214 :
215 : void touch(uint64_t id);
216 : void touch(const Value & obj);
217 :
218 : public:
219 : Value getField(uint64_t oid, const StringView &, std::initializer_list<StringView> fields);
220 : Value getField(const Value &, const StringView &, std::initializer_list<StringView> fields);
221 : Value getField(uint64_t oid, const StringView &, const Set<const Field *> & = Set<const Field *>());
222 : Value getField(const Value &, const StringView &, const Set<const Field *> & = Set<const Field *>());
223 :
224 : Value setField(uint64_t oid, const StringView &, Value &&);
225 : Value setField(const Value &, const StringView &, Value &&);
226 : Value setField(uint64_t oid, const StringView &, InputFile &);
227 : Value setField(const Value &, const StringView &, InputFile &);
228 :
229 : bool clearField(uint64_t oid, const StringView &, Value && = Value());
230 : bool clearField(const Value &, const StringView &, Value && = Value());
231 :
232 : Value appendField(uint64_t oid, const StringView &, Value &&);
233 : Value appendField(const Value &, const StringView &, Value &&);
234 :
235 : size_t countField(uint64_t oid, const StringView &);
236 : size_t countField(const Value &, const StringView &);
237 :
238 : public:
239 : Value getField(uint64_t oid, const Field &, std::initializer_list<StringView> fields);
240 : Value getField(const Value &, const Field &, std::initializer_list<StringView> fields);
241 : Value getField(uint64_t oid, const Field &, const Set<const Field *> & = Set<const Field *>());
242 : Value getField(const Value &, const Field &, const Set<const Field *> & = Set<const Field *>());
243 :
244 : Value setField(uint64_t oid, const Field &, Value &&);
245 : Value setField(const Value &, const Field &, Value &&);
246 : Value setField(uint64_t oid, const Field &, InputFile &);
247 : Value setField(const Value &, const Field &, InputFile &);
248 :
249 : bool clearField(uint64_t oid, const Field &, Value && = Value());
250 : bool clearField(const Value &, const Field &, Value && = Value());
251 :
252 : Value appendField(uint64_t oid, const Field &, Value &&);
253 : Value appendField(const Value &, const Field &, Value &&);
254 :
255 : size_t countField(uint64_t oid, const Field &);
256 : size_t countField(const Value &, const Field &);
257 :
258 : protected:
259 : friend class Scheme;
260 :
261 : Set<const Field *> getFieldSet(const Field &f, std::initializer_list<StringView> il) const;
262 :
263 : bool addConflict(const Conflict &);
264 : bool addConflict(const Vector<Conflict> &);
265 :
266 : bool addCondition(const Query::Select &);
267 : bool addCondition(const Vector<Query::Select> &);
268 :
269 : Value reduceGetQuery(const Query &query, bool cached);
270 :
271 : Map<const Field *, ConflictData> _conflict;
272 : Vector<ConditionData> _conditions;
273 : RequiredFields _required;
274 : const Scheme *_scheme = nullptr;
275 : Transaction _transaction;
276 : bool _isSystem = false;
277 : };
278 :
279 : struct FieldResolver {
280 : FieldResolver(const Scheme &scheme, const Worker &w, const Query &q);
281 : FieldResolver(const Scheme &scheme, const Worker &w);
282 : FieldResolver(const Scheme &scheme, const Query &q);
283 : FieldResolver(const Scheme &scheme, const Query &q, const Set<const Field *> &);
284 : FieldResolver(const Scheme &scheme);
285 : FieldResolver(const Scheme &scheme, const Set<const Field *> &);
286 :
287 : bool shouldResolveFields() const;
288 : bool hasIncludesOrExcludes() const;
289 : bool shouldIncludeAll() const;
290 : bool shouldIncludeField(const Field &f) const;
291 : bool shouldExcludeField(const Field &f) const;
292 : bool isFieldRequired(const Field &f) const;
293 : Vector<const Field *> getVirtuals() const;
294 : bool readFields(const Worker::FieldCallback &cb, bool isSimpleGet = false);
295 :
296 : void include(StringView);
297 :
298 : const Scheme *scheme = nullptr;
299 : const Worker::RequiredFields *required = nullptr;
300 : const Query *query = nullptr;
301 : Vector<const Field *> requiredFields;
302 : };
303 :
304 : template <typename Callback>
305 9175 : inline bool Worker::perform(const Callback &cb) const {
306 27525 : return _transaction.perform([&, this] () -> bool {
307 9175 : return cb(_transaction);
308 18350 : });
309 : }
310 :
311 : }
312 :
313 : #endif /* STAPPLER_DB_SPDBWORKER_H_ */
|