LCOV - code coverage report
Current view: top level - core/db - SPDbWorker.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 331 715 46.3 %
Date: 2024-05-12 00:16:13 Functions: 65 131 49.6 %

          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             : }

Generated by: LCOV version 1.14