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 : #include "SPDbWorker.h"
25 : #include "SPDbFile.h"
26 : #include "SPDbScheme.h"
27 : #include "SPValid.h"
28 :
29 : namespace STAPPLER_VERSIONIZED stappler::db {
30 :
31 0 : Conflict Conflict::update(StringView f) {
32 0 : return Conflict(f, Query::Select(), Conflict::Flags::WithoutCondition);
33 : }
34 :
35 100 : Conflict::Conflict(Conflict::Flags f): flags(f) { }
36 :
37 0 : Conflict::Conflict(StringView field, Query::Select &&cond, Flags f)
38 0 : : field(field.str<Interface>()), condition(std::move(cond)), flags(f) { }
39 :
40 0 : Conflict::Conflict(StringView field, Query::Select &&cond, Vector<String> &&mask)
41 0 : : field(field.str<Interface>()), condition(std::move(cond)), mask(std::move(mask)) { }
42 :
43 0 : Conflict &Conflict::setFlags(Flags f) {
44 0 : flags = f;
45 0 : return *this;
46 : }
47 :
48 3349 : static void prepareGetQuery(Query &query, uint64_t oid, bool forUpdate) {
49 3349 : query.select(oid);
50 3349 : if (forUpdate) {
51 1925 : query.forUpdate();
52 : }
53 3349 : }
54 :
55 250 : static void prepareGetQuery(Query &query, const StringView &alias, bool forUpdate) {
56 250 : query.select(alias);
57 250 : if (forUpdate) {
58 0 : query.forUpdate();
59 : }
60 250 : }
61 :
62 2625 : void Worker::RequiredFields::clear() {
63 2625 : includeFields.clear();
64 2625 : excludeFields.clear();
65 2625 : includeNone = false;
66 2625 : }
67 175 : void Worker::RequiredFields::reset(const Scheme &s) {
68 175 : clear();
69 175 : scheme = &s;
70 175 : }
71 :
72 0 : void Worker::RequiredFields::include(std::initializer_list<StringView> il) {
73 0 : for (auto &it : il) {
74 0 : include(it);
75 : }
76 0 : }
77 175 : void Worker::RequiredFields::include(const Set<const Field *> &f) {
78 775 : for (auto &it : f) {
79 600 : include(it);
80 : }
81 175 : }
82 0 : void Worker::RequiredFields::include(const StringView &name) {
83 0 : if (auto f = scheme->getField(name)) {
84 0 : include(f);
85 : }
86 0 : }
87 600 : void Worker::RequiredFields::include(const Field *f) {
88 600 : auto it = std::lower_bound(includeFields.begin(), includeFields.end(), f);
89 600 : if (it == includeFields.end()) {
90 600 : includeFields.emplace_back(f);
91 0 : } else if (*it != f) {
92 0 : includeFields.emplace(it, f);
93 : }
94 600 : includeNone = false;
95 600 : }
96 :
97 0 : void Worker::RequiredFields::exclude(std::initializer_list<StringView> il) {
98 0 : for (auto &it : il) {
99 0 : exclude(it);
100 : }
101 0 : }
102 0 : void Worker::RequiredFields::exclude(const Set<const Field *> &f) {
103 0 : for (auto &it : f) {
104 0 : exclude(it);
105 : }
106 0 : }
107 0 : void Worker::RequiredFields::exclude(const StringView &name) {
108 0 : if (auto f = scheme->getField(name)) {
109 0 : exclude(f);
110 : }
111 0 : }
112 0 : void Worker::RequiredFields::exclude(const Field *f) {
113 0 : auto it = std::lower_bound(excludeFields.begin(), excludeFields.end(), f);
114 0 : if (it == excludeFields.end()) {
115 0 : excludeFields.emplace_back(f);
116 0 : } else if (*it != f) {
117 0 : excludeFields.emplace(it, f);
118 : }
119 0 : includeNone = false;
120 0 : }
121 :
122 :
123 0 : Worker::ConditionData::ConditionData(const Query::Select &sel, const Field *f) {
124 0 : compare = sel.compare;
125 0 : value1 = sel.value1;
126 0 : value2 = sel.value2;
127 0 : field = f;
128 0 : }
129 :
130 0 : Worker::ConditionData::ConditionData(Query::Select &&sel, const Field *f) {
131 0 : compare = sel.compare;
132 0 : value1 = std::move(sel.value1);
133 0 : value2 = std::move(sel.value2);
134 0 : field = f;
135 0 : }
136 :
137 0 : void Worker::ConditionData::set(Query::Select &&sel, const Field *f) {
138 0 : compare = sel.compare;
139 0 : value1 = std::move(sel.value1);
140 0 : value2 = std::move(sel.value2);
141 0 : field = f;
142 0 : }
143 :
144 0 : void Worker::ConditionData::set(const Query::Select &sel, const Field *f) {
145 0 : compare = sel.compare;
146 0 : value1 = sel.value1;
147 0 : value2 = sel.value2;
148 0 : field = f;
149 0 : }
150 :
151 150 : Worker::Worker(const Scheme &s, const Adapter &a) : _scheme(&s), _transaction(Transaction::acquire(a)) {
152 150 : _required.scheme = _scheme;
153 : // _transaction.retain(); // acquire = retain
154 150 : }
155 13475 : Worker::Worker(const Scheme &s, const Transaction &t) : _scheme(&s), _transaction(t) {
156 13475 : _required.scheme = _scheme;
157 13475 : _transaction.retain();
158 13475 : }
159 350 : Worker::Worker(const Worker &w) : _scheme(w._scheme), _transaction(w._transaction) {
160 350 : _required.scheme = _scheme;
161 350 : _transaction.retain();
162 350 : }
163 13975 : Worker::~Worker() {
164 13975 : if (_transaction) {
165 13975 : _transaction.release();
166 : }
167 13975 : }
168 :
169 15699 : const Transaction &Worker::transaction() const {
170 15699 : return _transaction;
171 : }
172 100746 : const Scheme &Worker::scheme() const {
173 100746 : return *_scheme;
174 : }
175 :
176 200 : const ApplicationInterface *Worker::getApplicationInterface() const {
177 200 : return _transaction.getAdapter().getApplicationInterface();
178 : }
179 :
180 2200 : void Worker::includeNone() {
181 2200 : _required.clear();
182 2200 : _required.includeNone = true;
183 2200 : }
184 0 : void Worker::clearRequiredFields() {
185 0 : _required.clear();
186 0 : }
187 :
188 6225 : bool Worker::shouldIncludeNone() const {
189 6225 : return _required.includeNone;
190 : }
191 :
192 75 : bool Worker::shouldIncludeAll() const {
193 75 : return _required.includeAll;
194 : }
195 :
196 2400 : Worker &Worker::asSystem() {
197 2400 : _isSystem = true;
198 2400 : return *this;
199 : }
200 :
201 1300 : bool Worker::isSystem() const {
202 1300 : return _isSystem;
203 : }
204 :
205 9275 : const Worker::RequiredFields &Worker::getRequiredFields() const {
206 9275 : return _required;
207 : }
208 :
209 3650 : const Map<const Field *, Worker::ConflictData> &Worker::getConflicts() const {
210 3650 : return _conflict;
211 : }
212 :
213 2550 : const Vector<Worker::ConditionData> &Worker::getConditions() const {
214 2550 : return _conditions;
215 : }
216 :
217 900 : Value Worker::get(uint64_t oid, UpdateFlags flags) {
218 900 : Query query;
219 899 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) { _required.includeAll = true; }
220 899 : prepareGetQuery(query, oid, (flags & UpdateFlags::GetForUpdate) != UpdateFlags::None);
221 1799 : return reduceGetQuery(query, (flags & UpdateFlags::Cached) != UpdateFlags::None);
222 900 : }
223 :
224 50 : Value Worker::get(const StringView &alias, UpdateFlags flags) {
225 50 : if (!_scheme->hasAliases()) {
226 0 : return Value();
227 : }
228 50 : Query query;
229 50 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) { _required.includeAll = true; }
230 50 : prepareGetQuery(query, alias, (flags & UpdateFlags::GetForUpdate) != UpdateFlags::None);
231 50 : return reduceGetQuery(query, (flags & UpdateFlags::Cached) != UpdateFlags::None);
232 50 : }
233 :
234 75 : Value Worker::get(const Value &id, UpdateFlags flags) {
235 75 : if (id.isDictionary()) {
236 0 : if (auto oid = id.getInteger("__oid")) {
237 0 : return get(oid, flags);
238 : }
239 : } else {
240 75 : if ((id.isString() && stappler::valid::validateNumber(id.getString())) || id.isInteger()) {
241 75 : if (auto oid = id.getInteger()) {
242 75 : return get(oid, flags);
243 : }
244 : }
245 :
246 0 : auto &str = id.getString();
247 0 : if (!str.empty()) {
248 0 : return get(str, flags);
249 : }
250 : }
251 0 : return Value();
252 : }
253 :
254 100 : Value Worker::get(uint64_t oid, std::initializer_list<StringView> &&fields, UpdateFlags flags) {
255 100 : Query query;
256 100 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) { _required.includeAll = true; }
257 100 : prepareGetQuery(query, oid, (flags & UpdateFlags::GetForUpdate) != UpdateFlags::None);
258 200 : for (auto &it : fields) {
259 100 : if (auto f = _scheme->getField(it)) {
260 100 : query.include(f->getName().str<Interface>());
261 : }
262 : }
263 200 : return reduceGetQuery(query, (flags & UpdateFlags::Cached) != UpdateFlags::None);
264 100 : }
265 0 : Value Worker::get(const StringView &alias, std::initializer_list<StringView> &&fields, UpdateFlags flags) {
266 0 : Query query;
267 0 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) { _required.includeAll = true; }
268 0 : prepareGetQuery(query, alias, (flags & UpdateFlags::GetForUpdate) != UpdateFlags::None);
269 0 : for (auto &it : fields) {
270 0 : if (auto f = _scheme->getField(it)) {
271 0 : query.include(f->getName().str<Interface>());
272 : }
273 : }
274 0 : return reduceGetQuery(query, (flags & UpdateFlags::Cached) != UpdateFlags::None);
275 0 : }
276 0 : Value Worker::get(const Value &id, std::initializer_list<StringView> &&fields, UpdateFlags flags) {
277 0 : if (id.isDictionary()) {
278 0 : if (auto oid = id.getInteger("__oid")) {
279 0 : return get(oid, move(fields), flags);
280 : }
281 : } else {
282 0 : if ((id.isString() && stappler::valid::validateNumber(id.getString())) || id.isInteger()) {
283 0 : if (auto oid = id.getInteger()) {
284 0 : return get(oid, move(fields), flags);
285 : }
286 : }
287 :
288 0 : auto &str = id.getString();
289 0 : if (!str.empty()) {
290 0 : return get(str, move(fields), flags);
291 : }
292 : }
293 0 : return Value();
294 : }
295 :
296 25 : Value Worker::get(uint64_t oid, std::initializer_list<const char *> &&fields, UpdateFlags flags) {
297 25 : Query query;
298 25 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) { _required.includeAll = true; }
299 25 : prepareGetQuery(query, oid, (flags & UpdateFlags::GetForUpdate) != UpdateFlags::None);
300 50 : for (auto &it : fields) {
301 25 : if (auto f = _scheme->getField(it)) {
302 25 : query.include(f->getName().str<Interface>());
303 : }
304 : }
305 50 : return reduceGetQuery(query, (flags & UpdateFlags::Cached) != UpdateFlags::None);
306 25 : }
307 0 : Value Worker::get(const StringView &alias, std::initializer_list<const char *> &&fields, UpdateFlags flags) {
308 0 : Query query;
309 0 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) { _required.includeAll = true; }
310 0 : prepareGetQuery(query, alias, (flags & UpdateFlags::GetForUpdate) != UpdateFlags::None);
311 0 : for (auto &it : fields) {
312 0 : if (auto f = _scheme->getField(it)) {
313 0 : query.include(f->getName().str<Interface>());
314 : }
315 : }
316 0 : return reduceGetQuery(query, (flags & UpdateFlags::Cached) != UpdateFlags::None);
317 0 : }
318 0 : Value Worker::get(const Value &id, std::initializer_list<const char *> &&fields, UpdateFlags flags) {
319 0 : if (id.isDictionary()) {
320 0 : if (auto oid = id.getInteger("__oid")) {
321 0 : return get(oid, move(fields), flags);
322 : }
323 : } else {
324 0 : if ((id.isString() && stappler::valid::validateNumber(id.getString())) || id.isInteger()) {
325 0 : if (auto oid = id.getInteger()) {
326 0 : return get(oid, move(fields), flags);
327 : }
328 : }
329 :
330 0 : auto &str = id.getString();
331 0 : if (!str.empty()) {
332 0 : return get(str, move(fields), flags);
333 : }
334 : }
335 0 : return Value();
336 : }
337 :
338 0 : Value Worker::get(uint64_t oid, std::initializer_list<const Field *> &&fields, UpdateFlags flags) {
339 0 : Query query;
340 0 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) { _required.includeAll = true; }
341 0 : prepareGetQuery(query, oid, (flags & UpdateFlags::GetForUpdate) != UpdateFlags::None);
342 0 : for (auto &it : fields) {
343 0 : query.include(it->getName().str<Interface>());
344 : }
345 0 : return reduceGetQuery(query, (flags & UpdateFlags::Cached) != UpdateFlags::None);
346 0 : }
347 0 : Value Worker::get(const StringView &alias, std::initializer_list<const Field *> &&fields, UpdateFlags flags) {
348 0 : Query query;
349 0 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) { _required.includeAll = true; }
350 0 : prepareGetQuery(query, alias, (flags & UpdateFlags::GetForUpdate) != UpdateFlags::None);
351 0 : for (auto &it : fields) {
352 0 : query.include(it->getName().str<Interface>());
353 : }
354 0 : return reduceGetQuery(query, (flags & UpdateFlags::Cached) != UpdateFlags::None);
355 0 : }
356 0 : Value Worker::get(const Value &id, std::initializer_list<const Field *> &&fields, UpdateFlags flags) {
357 0 : if (id.isDictionary()) {
358 0 : if (auto oid = id.getInteger("__oid")) {
359 0 : return get(oid, move(fields), flags);
360 : }
361 : } else {
362 0 : if ((id.isString() && stappler::valid::validateNumber(id.getString())) || id.isInteger()) {
363 0 : if (auto oid = id.getInteger()) {
364 0 : return get(oid, move(fields), flags);
365 : }
366 : }
367 :
368 0 : auto &str = id.getString();
369 0 : if (!str.empty()) {
370 0 : return get(str, move(fields), flags);
371 : }
372 : }
373 0 : return Value();
374 : }
375 :
376 300 : Value Worker::get(uint64_t oid, SpanView<const Field *> fields, UpdateFlags flags) {
377 300 : Query query;
378 300 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) { _required.includeAll = true; }
379 300 : prepareGetQuery(query, oid, (flags & UpdateFlags::GetForUpdate) != UpdateFlags::None);
380 600 : for (auto &it : fields) {
381 300 : query.include(it->getName().str<Interface>());
382 : }
383 600 : return reduceGetQuery(query, (flags & UpdateFlags::Cached) != UpdateFlags::None);
384 300 : }
385 150 : Value Worker::get(const StringView &alias, SpanView<const Field *> fields, UpdateFlags flags) {
386 150 : Query query;
387 150 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) { _required.includeAll = true; }
388 150 : prepareGetQuery(query, alias, (flags & UpdateFlags::GetForUpdate) != UpdateFlags::None);
389 300 : for (auto &it : fields) {
390 150 : query.include(it->getName().str<Interface>());
391 : }
392 300 : return reduceGetQuery(query, (flags & UpdateFlags::Cached) != UpdateFlags::None);
393 150 : }
394 0 : Value Worker::get(const Value &id, SpanView<const Field *> fields, UpdateFlags flags) {
395 0 : if (id.isDictionary()) {
396 0 : if (auto oid = id.getInteger("__oid")) {
397 0 : return get(oid, fields, flags);
398 : }
399 : } else {
400 0 : if ((id.isString() && stappler::valid::validateNumber(id.getString())) || id.isInteger()) {
401 0 : if (auto oid = id.getInteger()) {
402 0 : return get(oid, fields, flags);
403 : }
404 : }
405 :
406 0 : auto &str = id.getString();
407 0 : if (!str.empty()) {
408 0 : return get(str, fields, flags);
409 : }
410 : }
411 0 : return Value();
412 : }
413 :
414 100 : Value Worker::get(uint64_t oid, StringView it, UpdateFlags flags) {
415 100 : Query query;
416 100 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) { _required.includeAll = true; }
417 100 : prepareGetQuery(query, oid, (flags & UpdateFlags::GetForUpdate) != UpdateFlags::None);
418 100 : if (auto f = _scheme->getField(it)) {
419 100 : query.include(f->getName().str<Interface>());
420 : }
421 200 : return reduceGetQuery(query, (flags & UpdateFlags::Cached) != UpdateFlags::None);
422 100 : }
423 50 : Value Worker::get(const StringView &alias, StringView it, UpdateFlags flags) {
424 50 : Query query;
425 50 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) { _required.includeAll = true; }
426 50 : prepareGetQuery(query, alias, (flags & UpdateFlags::GetForUpdate) != UpdateFlags::None);
427 50 : if (auto f = _scheme->getField(it)) {
428 50 : query.include(f->getName().str<Interface>());
429 : }
430 100 : return reduceGetQuery(query, (flags & UpdateFlags::Cached) != UpdateFlags::None);
431 50 : }
432 0 : Value Worker::get(const Value &id, StringView it, UpdateFlags flags) {
433 0 : if (id.isDictionary()) {
434 0 : if (auto oid = id.getInteger("__oid")) {
435 0 : return get(oid, it, flags);
436 : }
437 : } else {
438 0 : if ((id.isString() && stappler::valid::validateNumber(id.getString())) || id.isInteger()) {
439 0 : if (auto oid = id.getInteger()) {
440 0 : return get(oid, it, flags);
441 : }
442 : }
443 :
444 0 : auto &str = id.getString();
445 0 : if (!str.empty()) {
446 0 : return get(str, it, flags);
447 : }
448 : }
449 0 : return Value();
450 : }
451 :
452 0 : bool Worker::foreach(const Query &query, const Callback<bool(Value &)> &cb, UpdateFlags flags) {
453 0 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) {
454 0 : _required.includeAll = true;
455 : }
456 0 : return _scheme->foreachWithWorker(*this, query, cb);
457 : }
458 :
459 2675 : Value Worker::select(const Query &q, UpdateFlags flags) {
460 2675 : if ((flags & UpdateFlags::GetAll) != UpdateFlags::None) {
461 0 : _required.includeAll = true;
462 : }
463 2675 : return _scheme->selectWithWorker(*this, q);
464 : }
465 :
466 : // returns Dictionary with single object data or Null value
467 3550 : Value Worker::create(const Value &data, bool isProtected) {
468 3550 : return _scheme->createWithWorker(*this, data, isProtected);
469 : }
470 :
471 0 : Value Worker::create(const Value &data, UpdateFlags flags) {
472 0 : if ((flags & UpdateFlags::NoReturn) != UpdateFlags::None) {
473 0 : includeNone();
474 : }
475 0 : return _scheme->createWithWorker(*this, data, (flags & UpdateFlags::Protected) != UpdateFlags::None);
476 : }
477 :
478 100 : Value Worker::create(const Value &data, UpdateFlags flags, const Conflict &c) {
479 100 : if ((flags & UpdateFlags::NoReturn) != UpdateFlags::None) {
480 100 : includeNone();
481 : }
482 100 : if (!addConflict(c)) {
483 0 : return Value();
484 : }
485 200 : return _scheme->createWithWorker(*this, data, (flags & UpdateFlags::Protected) != UpdateFlags::None);
486 : }
487 0 : Value Worker::create(const Value &data, UpdateFlags flags, const Vector<Conflict> &c) {
488 0 : if ((flags & UpdateFlags::NoReturn) != UpdateFlags::None) {
489 0 : includeNone();
490 : }
491 0 : if (!addConflict(c)) {
492 0 : return Value();
493 : }
494 0 : return _scheme->createWithWorker(*this, data, (flags & UpdateFlags::Protected) != UpdateFlags::None);
495 : }
496 0 : Value Worker::create(const Value &data, Conflict::Flags flags) {
497 0 : return create(data, Conflict(flags));
498 : }
499 0 : Value Worker::create(const Value &data, const Conflict &c) {
500 0 : if (!addConflict(c)) {
501 0 : return Value();
502 : }
503 0 : return _scheme->createWithWorker(*this, data, false);
504 : }
505 0 : Value Worker::create(const Value &data, const Vector<Conflict> &c) {
506 0 : if (!addConflict(c)) {
507 0 : return Value();
508 : }
509 0 : return _scheme->createWithWorker(*this, data, false);
510 : }
511 :
512 425 : Value Worker::update(uint64_t oid, const Value &data, bool isProtected) {
513 425 : return _scheme->updateWithWorker(*this, oid, data, isProtected);
514 : }
515 :
516 0 : Value Worker::update(const Value & obj, const Value &data, bool isProtected) {
517 0 : return _scheme->updateWithWorker(*this, obj, data, isProtected);
518 : }
519 :
520 50 : Value Worker::update(uint64_t oid, const Value &data, UpdateFlags flags) {
521 50 : if ((flags & UpdateFlags::NoReturn) != UpdateFlags::None) {
522 25 : includeNone();
523 : }
524 100 : return _scheme->updateWithWorker(*this, oid, data, (flags & UpdateFlags::Protected) != UpdateFlags::None);
525 : }
526 :
527 1750 : Value Worker::update(const Value & obj, const Value &data, UpdateFlags flags) {
528 1750 : if ((flags & UpdateFlags::NoReturn) != UpdateFlags::None) {
529 1725 : includeNone();
530 : }
531 3500 : return _scheme->updateWithWorker(*this, obj, data, (flags & UpdateFlags::Protected) != UpdateFlags::None);
532 : }
533 :
534 0 : Value Worker::update(uint64_t oid, const Value &data, UpdateFlags flags, const Query::Select &sel) {
535 0 : if (!addCondition(sel)) {
536 0 : return Value();
537 : }
538 0 : return update(oid, data, flags);
539 : }
540 0 : Value Worker::update(const Value & obj, const Value &data, UpdateFlags flags, const Query::Select &sel) {
541 0 : if (!addCondition(sel)) {
542 0 : return Value();
543 : }
544 0 : return update(obj, data, flags);
545 : }
546 0 : Value Worker::update(uint64_t oid, const Value &data, UpdateFlags flags, const Vector<Query::Select> &sel) {
547 0 : if (!addCondition(sel)) {
548 0 : return Value();
549 : }
550 0 : return update(oid, data, flags);
551 : }
552 0 : Value Worker::update(const Value & obj, const Value &data, UpdateFlags flags, const Vector<Query::Select> &sel) {
553 0 : if (!addCondition(sel)) {
554 0 : return Value();
555 : }
556 0 : return update(obj, data, flags);
557 : }
558 :
559 0 : Value Worker::update(uint64_t oid, const Value &data, const Query::Select &sel) {
560 0 : if (!addCondition(sel)) {
561 0 : return Value();
562 : }
563 0 : return update(oid, data);
564 : }
565 0 : Value Worker::update(const Value & obj, const Value &data, const Query::Select &sel) {
566 0 : if (!addCondition(sel)) {
567 0 : return Value();
568 : }
569 0 : return update(obj, data);
570 : }
571 0 : Value Worker::update(uint64_t oid, const Value &data, const Vector<Query::Select> &sel) {
572 0 : if (!addCondition(sel)) {
573 0 : return Value();
574 : }
575 0 : return update(oid, data);
576 : }
577 0 : Value Worker::update(const Value & obj, const Value &data, const Vector<Query::Select> &sel) {
578 0 : if (!addCondition(sel)) {
579 0 : return Value();
580 : }
581 0 : return update(obj, data);
582 : }
583 :
584 225 : bool Worker::remove(uint64_t oid) {
585 225 : return _scheme->removeWithWorker(*this, oid);
586 : }
587 :
588 50 : bool Worker::remove(const Value &data) {
589 50 : return _scheme->removeWithWorker(*this, data.getInteger("__oid"));
590 : }
591 :
592 125 : size_t Worker::count() {
593 125 : return _scheme->countWithWorker(*this, Query());
594 : }
595 250 : size_t Worker::count(const Query &q) {
596 250 : return _scheme->countWithWorker(*this, q);
597 : }
598 :
599 325 : void Worker::touch(uint64_t oid) {
600 325 : _scheme->touchWithWorker(*this, oid);
601 325 : }
602 25 : void Worker::touch(const Value & obj) {
603 25 : _scheme->touchWithWorker(*this, obj);
604 25 : }
605 :
606 0 : Value Worker::getField(uint64_t oid, const StringView &s, std::initializer_list<StringView> fields) {
607 0 : if (auto f = _scheme->getField(s)) {
608 0 : return getField(oid, *f, getFieldSet(*f, fields));
609 : }
610 0 : return Value();
611 : }
612 0 : Value Worker::getField(const Value &obj, const StringView &s, std::initializer_list<StringView> fields) {
613 0 : if (auto f = _scheme->getField(s)) {
614 0 : return getField(obj, *f, getFieldSet(*f, fields));
615 : }
616 0 : return Value();
617 : }
618 :
619 0 : Value Worker::getField(uint64_t oid, const StringView &s, const Set<const Field *> &fields) {
620 0 : if (auto f = _scheme->getField(s)) {
621 0 : return getField(oid, *f, fields);
622 : }
623 0 : return Value();
624 : }
625 50 : Value Worker::getField(const Value &obj, const StringView &s, const Set<const Field *> &fields) {
626 50 : if (auto f = _scheme->getField(s)) {
627 50 : return getField(obj, *f, fields);
628 : }
629 0 : return Value();
630 : }
631 :
632 0 : Value Worker::setField(uint64_t oid, const StringView &s, Value &&v) {
633 0 : if (auto f = _scheme->getField(s)) {
634 0 : return setField(oid, *f, std::move(v));
635 : }
636 0 : return Value();
637 : }
638 0 : Value Worker::setField(const Value &obj, const StringView &s, Value &&v) {
639 0 : if (auto f = _scheme->getField(s)) {
640 0 : return setField(obj, *f, std::move(v));
641 : }
642 0 : return Value();
643 : }
644 0 : Value Worker::setField(uint64_t oid, const StringView &s, InputFile &file) {
645 0 : if (auto f = _scheme->getField(s)) {
646 0 : return setField(oid, *f, file);
647 : }
648 0 : return Value();
649 : }
650 0 : Value Worker::setField(const Value &obj, const StringView &s, InputFile &file) {
651 0 : return setField(obj.getInteger(s), s, file);
652 : }
653 :
654 0 : bool Worker::clearField(uint64_t oid, const StringView &s, Value && objs) {
655 0 : if (auto f = _scheme->getField(s)) {
656 0 : return clearField(oid, *f, std::move(objs));
657 : }
658 0 : return false;
659 : }
660 0 : bool Worker::clearField(const Value &obj, const StringView &s, Value && objs) {
661 0 : if (auto f = _scheme->getField(s)) {
662 0 : return clearField(obj, *f, std::move(objs));
663 : }
664 0 : return false;
665 : }
666 :
667 0 : Value Worker::appendField(uint64_t oid, const StringView &s, Value &&v) {
668 0 : auto f = _scheme->getField(s);
669 0 : if (f) {
670 0 : return appendField(oid, *f, std::move(v));
671 : }
672 0 : return Value();
673 : }
674 0 : Value Worker::appendField(const Value &obj, const StringView &s, Value &&v) {
675 0 : auto f = _scheme->getField(s);
676 0 : if (f) {
677 0 : return appendField(obj, *f, std::move(v));
678 : }
679 0 : return Value();
680 : }
681 :
682 0 : size_t Worker::countField(uint64_t oid, const StringView &s) {
683 0 : auto f = _scheme->getField(s);
684 0 : if (f) {
685 0 : return countField(oid, *f);
686 : }
687 0 : return 0;
688 : }
689 :
690 0 : size_t Worker::countField(const Value &obj, const StringView &s) {
691 0 : auto f = _scheme->getField(s);
692 0 : if (f) {
693 0 : return countField(obj, *f);
694 : }
695 0 : return 0;
696 : }
697 :
698 0 : Value Worker::getField(uint64_t oid, const Field &f, std::initializer_list<StringView> fields) {
699 0 : if (auto s = f.getForeignScheme()) {
700 0 : _required.reset(*s);
701 0 : include(fields);
702 : } else {
703 0 : _required.clear();
704 : }
705 0 : return _scheme->fieldWithWorker(Action::Get, *this, oid, f);
706 : }
707 0 : Value Worker::getField(const Value &obj, const Field &f, std::initializer_list<StringView> fields) {
708 0 : if (auto s = f.getForeignScheme()) {
709 0 : _required.reset(*s);
710 0 : include(fields);
711 : } else {
712 0 : _required.clear();
713 : }
714 0 : return _scheme->fieldWithWorker(Action::Get, *this, obj, f);
715 : }
716 :
717 0 : Value Worker::getField(uint64_t oid, const Field &f, const Set<const Field *> &fields) {
718 0 : if (auto s = f.getForeignScheme()) {
719 0 : _required.reset(*s);
720 0 : include(fields);
721 : } else {
722 0 : _required.clear();
723 : }
724 0 : return _scheme->fieldWithWorker(Action::Get, *this, oid, f);
725 : }
726 425 : Value Worker::getField(const Value &obj, const Field &f, const Set<const Field *> &fields) {
727 425 : if (f.isSimpleLayout() && obj.hasValue(f.getName())) {
728 0 : return obj.getValue(f.getName());
729 425 : } else if (f.isFile() && fields.empty()) {
730 0 : return File::getData(_transaction, obj.isInteger() ? obj.asInteger() : obj.getInteger(f.getName()));
731 : }
732 :
733 425 : if (auto s = f.getForeignScheme()) {
734 175 : _required.reset(*s);
735 175 : include(fields);
736 : } else {
737 250 : _required.clear();
738 : }
739 :
740 425 : return _scheme->fieldWithWorker(Action::Get, *this, obj, f);
741 : }
742 :
743 75 : Value Worker::setField(uint64_t oid, const Field &f, Value &&v) {
744 75 : if (v.isNull()) {
745 0 : clearField(oid, f);
746 0 : return Value();
747 : }
748 75 : return _scheme->fieldWithWorker(Action::Set, *this, oid, f, std::move(v));
749 : }
750 0 : Value Worker::setField(const Value &obj, const Field &f, Value &&v) {
751 0 : if (v.isNull()) {
752 0 : clearField(obj, f);
753 0 : return Value();
754 : }
755 0 : return _scheme->fieldWithWorker(Action::Set, *this, obj, f, std::move(v));
756 : }
757 0 : Value Worker::setField(uint64_t oid, const Field &f, InputFile &file) {
758 0 : if (f.isFile()) {
759 0 : return _scheme->setFileWithWorker(*this, oid, f, file);
760 : }
761 0 : return Value();
762 : }
763 0 : Value Worker::setField(const Value &obj, const Field &f, InputFile &file) {
764 0 : return setField(obj.getInteger("__oid"), f, file);
765 : }
766 :
767 75 : bool Worker::clearField(uint64_t oid, const Field &f, Value &&objs) {
768 75 : if (!f.hasFlag(Flags::Required)) {
769 75 : return _scheme->fieldWithWorker(Action::Remove, *this, oid, f, std::move(objs)).asBool();
770 : }
771 0 : return false;
772 : }
773 0 : bool Worker::clearField(const Value &obj, const Field &f, Value &&objs) {
774 0 : if (!f.hasFlag(Flags::Required)) {
775 0 : return _scheme->fieldWithWorker(Action::Remove, *this, obj, f, std::move(objs)).asBool();
776 : }
777 0 : return false;
778 : }
779 :
780 200 : Value Worker::appendField(uint64_t oid, const Field &f, Value &&v) {
781 200 : if (f.getType() == Type::Array || (f.getType() == Type::Set && f.isReference())) {
782 200 : return _scheme->fieldWithWorker(Action::Append, *this, oid, f, std::move(v));
783 : }
784 0 : return Value();
785 : }
786 0 : Value Worker::appendField(const Value &obj, const Field &f, Value &&v) {
787 0 : if (f.getType() == Type::Array || (f.getType() == Type::Set && f.isReference())) {
788 0 : return _scheme->fieldWithWorker(Action::Append, *this, obj, f, std::move(v));
789 : }
790 0 : return Value();
791 : }
792 :
793 0 : size_t Worker::countField(uint64_t oid, const Field &f) {
794 0 : auto d = _scheme->fieldWithWorker(Action::Count, *this, oid, f);
795 0 : if (d.isInteger()) {
796 0 : return size_t(d.asInteger());
797 : }
798 0 : return 0;
799 0 : }
800 :
801 0 : size_t Worker::countField(const Value &obj, const Field &f) {
802 0 : auto d = _scheme->fieldWithWorker(Action::Count, *this, obj, f);
803 0 : if (d.isInteger()) {
804 0 : return size_t(d.asInteger());
805 : }
806 0 : return 0;
807 0 : }
808 :
809 0 : Set<const Field *> Worker::getFieldSet(const Field &f, std::initializer_list<StringView> il) const {
810 0 : Set<const Field *> ret;
811 0 : auto target = f.getForeignScheme();
812 0 : for (auto &it : il) {
813 0 : ret.emplace(target->getField(it));
814 : }
815 0 : return ret;
816 0 : }
817 :
818 200 : bool Worker::addConflict(const Conflict &c) {
819 200 : if (c.field.empty()) {
820 : // add for all unique fields
821 100 : auto tmpC = c;
822 1400 : for (auto &it : scheme().getFields()) {
823 1300 : if (it.second.isIndexed() && it.second.hasFlag(Flags::Unique)) {
824 100 : tmpC.field = it.first;
825 100 : addConflict(tmpC);
826 : }
827 : }
828 100 : return true;
829 100 : } else {
830 100 : auto f = scheme().getField(c.field);
831 100 : if (!f || !f->hasFlag(Flags::Unique)) {
832 0 : _transaction.getAdapter().getApplicationInterface()->error("db::Worker", "Invalid ON CONFLICT field - no unique constraint");
833 0 : return false;
834 : }
835 :
836 100 : const Field *selField = nullptr;
837 :
838 100 : ConflictData d;
839 100 : if (c.condition.field.empty()) {
840 100 : d.flags = Conflict::WithoutCondition;
841 : } else {
842 0 : selField = scheme().getField(c.condition.field);
843 0 : if (!selField || !selField->isIndexed()
844 0 : || !checkIfComparationIsValid(selField->getType(), c.condition.compare, selField->getFlags()) || !c.condition.textQuery.empty()) {
845 0 : _transaction.getAdapter().getApplicationInterface()->error("db::Worker", "Invalid ON CONFLICT condition - not applicable");
846 0 : return false;
847 : }
848 : }
849 :
850 100 : d.field = f;
851 100 : if (selField) {
852 0 : d.condition.set(std::move(c.condition), selField);
853 : }
854 :
855 100 : for (auto &it : c.mask) {
856 0 : if (auto field = scheme().getField(it)) {
857 0 : d.mask.emplace_back(field);
858 : }
859 : }
860 :
861 100 : d.flags |= c.flags;
862 :
863 100 : _conflict.emplace(f, std::move(d));
864 100 : return true;
865 100 : }
866 : }
867 :
868 0 : bool Worker::addConflict(const Vector<Conflict> &c) {
869 0 : for (auto &it : c) {
870 0 : if (!addConflict(it)) {
871 0 : return false;
872 : }
873 : }
874 0 : return true;
875 : }
876 :
877 0 : bool Worker::addCondition(const Query::Select &sel) {
878 0 : auto selField = scheme().getField(sel.field);
879 0 : if (!selField || !checkIfComparationIsValid(selField->getType(), sel.compare, selField->getFlags()) || !sel.textQuery.empty()) {
880 0 : _transaction.getAdapter().getApplicationInterface()->error("db::Worker", "Invalid ON CONFLICT condition - not applicable");
881 0 : return false;
882 : }
883 :
884 0 : _conditions.emplace_back(sel, selField);
885 0 : return true;
886 : }
887 :
888 0 : bool Worker::addCondition(const Vector<Query::Select> &sel) {
889 0 : for (auto &it : sel) {
890 0 : if (!addCondition(it)) {
891 0 : return false;
892 : }
893 : }
894 0 : return true;
895 : }
896 :
897 3599 : Value Worker::reduceGetQuery(const Query &query, bool cached) {
898 3599 : if (auto id = query.getSingleSelectId()) {
899 3225 : if (cached && !_scheme->isDetouched()) {
900 75 : if (auto v = _transaction.getObject(id)) {
901 0 : return v;
902 75 : }
903 : }
904 3225 : auto ret = _scheme->selectWithWorker(*this, query);
905 3225 : if (ret.isArray() && ret.size() >= 1) {
906 3225 : if (cached && !_scheme->isDetouched()) {
907 75 : _transaction.setObject(id, Value(ret.getValue(0)));
908 : }
909 3225 : return ret.getValue(0);
910 : }
911 3225 : } else {
912 374 : auto ret = _scheme->selectWithWorker(*this, query);
913 375 : if (ret.isArray() && ret.size() >= 1) {
914 250 : return ret.getValue(0);
915 : }
916 375 : }
917 :
918 125 : return Value();
919 : }
920 :
921 6350 : FieldResolver::FieldResolver(const Scheme &scheme, const Worker &w, const Query &q)
922 6350 : : scheme(&scheme), required(&w.getRequiredFields()), query(&q) { }
923 :
924 2825 : FieldResolver::FieldResolver(const Scheme &scheme, const Worker &w)
925 2825 : : scheme(&scheme), required(&w.getRequiredFields()) { }
926 :
927 1125 : FieldResolver::FieldResolver(const Scheme &scheme, const Query &q)
928 1125 : : scheme(&scheme), query(&q) { }
929 :
930 1075 : FieldResolver::FieldResolver(const Scheme &scheme, const Query &q, const Set<const Field *> &set)
931 1075 : : scheme(&scheme), query(&q) {
932 11525 : for (auto &it : set) {
933 10450 : emplace_ordered(requiredFields, it);
934 : }
935 1075 : }
936 :
937 50 : FieldResolver::FieldResolver(const Scheme &scheme) : scheme(&scheme) { }
938 :
939 125 : FieldResolver::FieldResolver(const Scheme &scheme, const Set<const Field *> &set) : scheme(&scheme) {
940 500 : for (auto &it : set) {
941 375 : emplace_ordered(requiredFields, it);
942 : }
943 125 : }
944 :
945 8275 : bool FieldResolver::shouldResolveFields() const {
946 8275 : if (!required) {
947 1200 : return true;
948 7075 : } else if (required->includeNone || (required->scheme != nullptr && required->scheme != scheme)) {
949 250 : return false;
950 : }
951 6825 : return true;
952 : }
953 :
954 23350 : bool FieldResolver::hasIncludesOrExcludes() const {
955 23350 : bool hasFields = false;
956 23350 : if (required) {
957 20925 : hasFields = !required->excludeFields.empty() || !required->includeFields.empty();
958 : }
959 23350 : if (!hasFields && query) {
960 19600 : hasFields = !query->getIncludeFields().empty() || !query->getExcludeFields().empty();
961 : }
962 23350 : return hasFields;
963 : }
964 :
965 150 : bool FieldResolver::shouldIncludeAll() const {
966 150 : return required && required->includeAll;
967 : }
968 :
969 58475 : bool FieldResolver::shouldIncludeField(const Field &f) const {
970 58475 : if (query) {
971 179400 : for (auto &it : query->getIncludeFields()) {
972 134025 : if (it.name == f.getName()) {
973 12500 : return true;
974 : }
975 : }
976 : }
977 45975 : if (required) {
978 45975 : auto it = std::lower_bound(required->includeFields.begin(), required->includeFields.end(), &f);
979 45975 : if (it != required->includeFields.end() && *it == &f) {
980 525 : return true;
981 : }
982 : }
983 45450 : if (query && required) {
984 45375 : return query->getIncludeFields().empty() && required->includeFields.empty();
985 75 : } else if (query) {
986 0 : return query->getIncludeFields().empty();
987 75 : } else if (required) {
988 75 : return required->includeFields.empty();
989 : }
990 0 : return false;
991 : }
992 :
993 13025 : bool FieldResolver::shouldExcludeField(const Field &f) const {
994 13025 : if (query) {
995 12500 : for (auto &it : query->getExcludeFields()) {
996 0 : if (it.name == f.getName()) {
997 0 : return true;
998 : }
999 : }
1000 : }
1001 13025 : if (required) {
1002 13025 : auto it = std::lower_bound(required->excludeFields.begin(), required->excludeFields.end(), &f);
1003 13025 : if (it != required->excludeFields.end() && *it == &f) {
1004 0 : return true;
1005 : }
1006 : }
1007 13025 : return false;
1008 : }
1009 :
1010 59025 : bool FieldResolver::isFieldRequired(const Field &f) const {
1011 59025 : auto it = std::lower_bound(requiredFields.begin(), requiredFields.end(), &f);
1012 59025 : if (it == requiredFields.end() || *it != &f) {
1013 58650 : return false;
1014 : }
1015 375 : return true;
1016 : }
1017 :
1018 15325 : Vector<const Field *> FieldResolver::getVirtuals() const {
1019 15325 : Vector<const Field *> virtuals;
1020 15325 : if (!hasIncludesOrExcludes()) {
1021 66850 : for (auto &it : scheme->getFields()) {
1022 61475 : auto type = it.second.getType();
1023 61475 : if (type == Type::Virtual && (!it.second.hasFlag(Flags::ForceExclude) || shouldIncludeAll())) {
1024 50 : emplace_ordered(virtuals, &it.second);
1025 : }
1026 : }
1027 : } else {
1028 9950 : auto &forceInclude = scheme->getForceInclude();
1029 139350 : for (auto &it : scheme->getFields()) {
1030 129400 : auto type = it.second.getType();
1031 129400 : if (type == Type::Virtual) {
1032 200 : if (it.second.hasFlag(Flags::ForceInclude) || forceInclude.find(&it.second) != forceInclude.end()) {
1033 0 : emplace_ordered(virtuals, &it.second);
1034 200 : } else if (shouldIncludeField(it.second)) {
1035 100 : if (!shouldExcludeField(it.second)) {
1036 100 : emplace_ordered(virtuals, &it.second);
1037 : }
1038 : }
1039 : }
1040 : }
1041 : }
1042 :
1043 15325 : return virtuals;
1044 0 : }
1045 :
1046 8275 : bool FieldResolver::readFields(const Worker::FieldCallback &cb, bool isSimpleGet) {
1047 8275 : if (!shouldResolveFields()) {
1048 250 : return false;
1049 8025 : } else if (!hasIncludesOrExcludes()) {
1050 : // no includes/excludes
1051 3050 : if (!scheme->hasForceExclude() || shouldIncludeAll()) {
1052 : // no force-excludes or all fields are required, so, return *
1053 3050 : cb("*", nullptr);
1054 : } else {
1055 : // has force-excludes, iterate through fields
1056 :
1057 0 : cb("__oid", nullptr);
1058 0 : for (auto &it : scheme->getFields()) {
1059 0 : if (it.second.hasFlag(Flags::ForceExclude)) {
1060 0 : continue;
1061 : }
1062 :
1063 0 : auto type = it.second.getType();
1064 0 : if (type == Type::Set || type == Type::Array || type == Type::View
1065 0 : || type == Type::FullTextView || type == Type::Virtual) {
1066 0 : continue;
1067 : }
1068 :
1069 0 : cb(it.second.getName(), &it.second);
1070 : }
1071 : }
1072 : } else {
1073 : // has excludes or includes
1074 4975 : cb("__oid", nullptr);
1075 :
1076 4975 : auto &forceInclude = scheme->getForceInclude();
1077 :
1078 4975 : Vector<const Field *> virtuals = getVirtuals();
1079 5025 : for (auto &it : virtuals) {
1080 50 : auto slot = it->getSlot<FieldVirtual>();
1081 100 : for (auto &iit : slot->requireFields) {
1082 50 : if (auto f = scheme->getField(iit)) {
1083 50 : emplace_ordered(requiredFields, f);
1084 : }
1085 : }
1086 : }
1087 :
1088 69675 : for (auto &it : scheme->getFields()) {
1089 64700 : auto type = it.second.getType();
1090 64700 : if (type == Type::Set || type == Type::Array || type == Type::View || type == Type::FullTextView || type == Type::Virtual) {
1091 5675 : continue;
1092 : }
1093 :
1094 59025 : if (it.second.hasFlag(Flags::ForceInclude) || isFieldRequired(it.second) || (!isSimpleGet && forceInclude.find(&it.second) != forceInclude.end())) {
1095 475 : cb(it.second.getName(), &it.second);
1096 58550 : } else if (!isSimpleGet && shouldIncludeField(it.second)) {
1097 12925 : if (!shouldExcludeField(it.second)) {
1098 12925 : cb(it.second.getName(), &it.second);
1099 : }
1100 : }
1101 : }
1102 4975 : }
1103 8025 : return true;
1104 : }
1105 :
1106 650 : void FieldResolver::include(StringView mem) {
1107 650 : if (auto f = scheme->getField(mem)) {
1108 650 : emplace_ordered(requiredFields, f);
1109 : }
1110 650 : }
1111 :
1112 : }
|