LCOV - code coverage report
Current view: top level - core/db - SPDbQuery.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 156 359 43.5 %
Date: 2024-05-12 00:16:13 Functions: 54 79 68.4 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2017-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 "SPDbQuery.h"
      25             : 
      26             : namespace STAPPLER_VERSIONIZED stappler::db {
      27             : 
      28       27100 : Query::Field::Field(Field &&f) : name(std::move(f.name)), fields(std::move(f.fields)) { }
      29             : 
      30        1875 : Query::Field::Field(const Field &f) : name(f.name), fields(f.fields) { }
      31             : 
      32           0 : Query::Field &Query::Field::operator=(Field &&f) {
      33           0 :         name = std::move(f.name);
      34           0 :         fields = std::move(f.fields);
      35           0 :         return *this;
      36             : }
      37           0 : Query::Field &Query::Field::operator=(const Field &f) {
      38           0 :         name = f.name;
      39           0 :         fields = f.fields;
      40           0 :         return *this;
      41             : }
      42             : 
      43         100 : void Query::Field::setName(const char *n) {
      44         100 :         name = n;
      45         100 : }
      46        6200 : void Query::Field::setName(const StringView &n) {
      47        6200 :         name = n.str<Interface>();
      48        6200 : }
      49        3575 : void Query::Field::setName(const String &n) {
      50        3575 :         name = n;
      51        3575 : }
      52        3150 : void Query::Field::setName(String &&n) {
      53        3150 :         name = std::move(n);
      54        3150 : }
      55           0 : void Query::Field::setName(const Field &f) {
      56           0 :         name = f.name;
      57           0 :         fields = f.fields;
      58           0 : }
      59           0 : void Query::Field::setName(Field &&f) {
      60           0 :         name = std::move(f.name);
      61           0 :         fields = std::move(f.fields);
      62           0 : }
      63             : 
      64         725 : Query::Select::Select(const StringView & f, Comparation c, Value && v1, Value && v2)
      65         725 : : compare(c), value1(std::move(v1)), value2(std::move(v2)), field(f.str<Interface>()) { }
      66             : 
      67         250 : Query::Select::Select(const StringView & f, Comparation c, int64_t v1, int64_t v2)
      68         250 : : compare(c), value1(v1), value2(v2), field(f.str<Interface>()) { }
      69             : 
      70          25 : Query::Select::Select(const StringView & f, Comparation c, const String & v)
      71          25 : : compare(Comparation::Equal), value1(v), value2(0), field(f.str<Interface>()) { }
      72             : 
      73          75 : Query::Select::Select(const StringView & f, Comparation c, const StringView & v)
      74          75 : : compare(Comparation::Equal), value1(v), value2(0), field(f.str<Interface>()) { }
      75             : 
      76         275 : Query::Select::Select(const StringView & f, Comparation c, FullTextQuery && v)
      77         275 : : compare(Comparation::Equal), field(f.str<Interface>()), textQuery(std::move(v)) { }
      78             : 
      79          75 : Resolve Query::decodeResolve(const StringView &str) {
      80          75 :         if (str == "$all") {
      81           0 :                 return Resolve::All;
      82          75 :         } else if (str == "$files") {
      83          25 :                 return Resolve::Files;
      84          50 :         } else if (str == "$sets") {
      85           0 :                 return Resolve::Sets;
      86          50 :         } else if (str == "$objects" || str == "$objs") {
      87           0 :                 return Resolve::Objects;
      88          50 :         } else if (str == "$arrays") {
      89           0 :                 return Resolve::Arrays;
      90          50 :         } else if (str == "$defaults" || str == "$defs") {
      91           0 :                 return Resolve::Defaults;
      92          50 :         } else if (str == "$basics") {
      93          25 :                 return Resolve::Basics;
      94          25 :         } else if (str == "$ids") {
      95          25 :                 return Resolve::Ids;
      96             :         }
      97           0 :         return Resolve::None;
      98             : }
      99             : 
     100           0 : String Query::encodeResolve(Resolve res) {
     101           0 :         if ((res & Resolve::All) == Resolve::All) {
     102           0 :                 return "$all";
     103           0 :         } else if ((res & Resolve::Files) != Resolve::None) {
     104           0 :                 return "$files";
     105           0 :         } else if ((res & Resolve::Sets) != Resolve::None) {
     106           0 :                 return "$sets";
     107           0 :         } else if ((res & Resolve::Objects) != Resolve::None) {
     108           0 :                 return "$objs";
     109           0 :         } else if ((res & Resolve::Arrays) != Resolve::None) {
     110           0 :                 return "$arrays";
     111           0 :         } else if ((res & Resolve::Defaults) != Resolve::None) {
     112           0 :                 return "$defs";
     113           0 :         } else if ((res & Resolve::Basics) != Resolve::None) {
     114           0 :                 return "$basics";
     115             :         }
     116           0 :         return String();
     117             : }
     118             : 
     119           0 : Query Query::all() { return Query(); }
     120             : 
     121           0 : Query Query::field(int64_t id, const StringView &f) {
     122           0 :         Query q;
     123           0 :         q.queryField = f.str<Interface>();
     124           0 :         q.queryId = id;
     125           0 :         return q;
     126             : }
     127             : 
     128          50 : Query Query::field(int64_t id, const StringView &f, const Query &iq) {
     129          50 :         Query q(iq);
     130          50 :         q.queryField = f.str<Interface>();
     131          50 :         q.queryId = id;
     132          50 :         return q;
     133             : }
     134             : 
     135         300 : Query & Query::select(const StringView &alias) {
     136         300 :         selectIds.clear();
     137         300 :         selectAlias = alias.str<Interface>();
     138         300 :         selectList.clear();
     139         300 :         return *this;
     140             : }
     141             : 
     142        6149 : Query & Query::select(int64_t id) {
     143        6149 :         selectIds.clear();
     144        6149 :         selectIds.push_back(id);
     145        6150 :         selectAlias.clear();
     146        6149 :         selectList.clear();
     147        6149 :         return *this;
     148             : }
     149           0 : Query & Query::select(const Value &val) {
     150           0 :         if (val.isInteger()) {
     151           0 :                 selectIds.clear();
     152           0 :                 selectIds.push_back(val.getInteger());
     153           0 :                 selectAlias.clear();
     154           0 :                 selectList.clear();
     155           0 :         } else if (val.isString()) {
     156           0 :                 selectIds.clear();
     157           0 :                 selectAlias = val.getString();
     158           0 :                 selectList.clear();
     159           0 :         } else if (val.isArray()) {
     160           0 :                 selectIds.clear();
     161           0 :                 selectAlias.clear();
     162           0 :                 selectList.clear();
     163           0 :                 if (val.asArray().size() > 0) {
     164           0 :                         for (auto &it : val.asArray()) {
     165           0 :                                 selectIds.emplace_back(it.asInteger());
     166             :                         }
     167             :                 } else {
     168           0 :                         selectIds = Vector<int64_t>{-1};
     169             :                 }
     170           0 :         } else if (val.isDictionary()) {
     171           0 :                 selectIds.clear();
     172           0 :                 selectAlias.clear();
     173           0 :                 selectList.clear();
     174           0 :                 for (auto &it : val.asDict()) {
     175           0 :                         selectList.emplace_back(it.first, Comparation::Equal, Value(it.second), Value());
     176             :                 }
     177             :         }
     178           0 :         return *this;
     179             : }
     180             : 
     181           0 : Query & Query::select(Vector<int64_t> &&id) {
     182           0 :         if (!id.empty()) {
     183           0 :                 selectIds = std::move(id);
     184             :         } else {
     185           0 :                 selectIds = Vector<int64_t>{-1};
     186             :         }
     187           0 :         selectAlias.clear();
     188           0 :         selectList.clear();
     189           0 :         _selected = true;
     190           0 :         return *this;
     191             : }
     192             : 
     193           0 : Query & Query::select(SpanView<int64_t> id) {
     194           0 :         if (!id.empty()) {
     195           0 :                 selectIds = id.vec<Interface>();
     196             :         } else {
     197           0 :                 selectIds = Vector<int64_t>{-1};
     198             :         }
     199           0 :         selectAlias.clear();
     200           0 :         selectList.clear();
     201           0 :         _selected = true;
     202           0 :         return *this;
     203             : }
     204             : 
     205           0 : Query & Query::select(std::initializer_list<int64_t> &&id) {
     206           0 :         if (id.size() > 0) {
     207           0 :                 selectIds = std::move(id);
     208             :         } else {
     209           0 :                 selectIds = Vector<int64_t>{-1};
     210             :         }
     211           0 :         selectAlias.clear();
     212           0 :         selectList.clear();
     213           0 :         return *this;
     214             : }
     215             : 
     216         550 : Query & Query::select(const StringView &f, Comparation c, const Value & v1, const Value &v2) {
     217         550 :         selectList.emplace_back(f, c, Value(v1), Value(v2));
     218         550 :         return *this;
     219             : }
     220         125 : Query & Query::select(const StringView &f, const Value & v1) {
     221         125 :         selectList.emplace_back(f, Comparation::Equal, Value(v1), Value());
     222         125 :         return *this;
     223             : }
     224           0 : Query & Query::select(const StringView &f, Comparation c, int64_t v1) {
     225           0 :         selectList.emplace_back(f, c, Value(v1), Value());
     226           0 :         return *this;
     227             : }
     228           0 : Query & Query::select(const StringView &f, Comparation c, int64_t v1, int64_t v2) {
     229           0 :         selectList.emplace_back(f, c, Value(v1), Value(v2));
     230           0 :         return *this;
     231             : }
     232           0 : Query & Query::select(const StringView &f, const String & v) {
     233           0 :         selectList.emplace_back(f, Comparation::Equal, Value(v), Value());
     234           0 :         return *this;
     235             : }
     236           0 : Query & Query::select(const StringView &f, String && v) {
     237           0 :         selectList.emplace_back(f, Comparation::Equal, Value(std::move(v)), Value());
     238           0 :         return *this;
     239             : }
     240           0 : Query & Query::select(const StringView &f, const Bytes & v) {
     241           0 :         selectList.emplace_back(f, Comparation::Equal, Value(v), Value());
     242           0 :         return *this;
     243             : }
     244           0 : Query & Query::select(const StringView &f, Bytes && v) {
     245           0 :         selectList.emplace_back(f, Comparation::Equal, Value(std::move(v)), Value());
     246           0 :         return *this;
     247             : }
     248         275 : Query & Query::select(const StringView &f, FullTextQuery && v) {
     249         275 :         selectList.emplace_back(f, Comparation::Equal, std::move(v));
     250         275 :         order(f, Ordering::Descending);
     251         275 :         return *this;
     252             : }
     253             : 
     254         400 : Query & Query::select(Select &&q) {
     255         400 :         selectList.emplace_back(std::move(q));
     256         400 :         return *this;
     257             : }
     258             : 
     259         500 : Query & Query::order(const StringView &f, Ordering o, size_t l, size_t off) {
     260         500 :         orderField = f.str<Interface>();
     261         500 :         ordering = o;
     262         500 :         if (l != stappler::maxOf<size_t>()) {
     263           0 :                 limitValue = l;
     264             :         }
     265         500 :         if (off != 0) {
     266           0 :                 offsetValue = off;
     267             :         }
     268         500 :         return *this;
     269             : }
     270             : 
     271         425 : Query & Query::softLimit(const StringView &field, Ordering ord, size_t limit, Value &&val) {
     272         425 :         orderField = field.str<Interface>();
     273         425 :         ordering = ord;
     274         425 :         limitValue = limit;
     275         425 :         softLimitValue = std::move(val);
     276         425 :         _softLimit = true;
     277         425 :         return *this;
     278             : }
     279             : 
     280           0 : Query & Query::first(const StringView &f, size_t limit, size_t offset) {
     281           0 :         orderField = f.str<Interface>();
     282           0 :         ordering = Ordering::Ascending;
     283           0 :         if (limit != stappler::maxOf<size_t>()) {
     284           0 :                 limitValue = limit;
     285             :         }
     286           0 :         if (offset != 0) {
     287           0 :                 offsetValue = offset;
     288             :         }
     289           0 :         return *this;
     290             : }
     291           0 : Query & Query::last(const StringView &f, size_t limit, size_t offset) {
     292           0 :         orderField = f.str<Interface>();
     293           0 :         ordering = Ordering::Descending;
     294           0 :         if (limit != stappler::maxOf<size_t>()) {
     295           0 :                 limitValue = limit;
     296             :         }
     297           0 :         if (offset != 0) {
     298           0 :                 offsetValue = offset;
     299             :         }
     300           0 :         return *this;
     301             : }
     302             : 
     303         125 : Query & Query::limit(size_t l, size_t off) {
     304         125 :         limitValue = l;
     305         125 :         offsetValue = off;
     306         125 :         return *this;
     307             : }
     308             : 
     309         375 : Query & Query::limit(size_t l) {
     310         375 :         limitValue = l;
     311         375 :         return *this;
     312             : }
     313             : 
     314          50 : Query & Query::offset(size_t l) {
     315          50 :         offsetValue = l;
     316          50 :         return *this;
     317             : }
     318             : 
     319          75 : Query & Query::delta(uint64_t id) {
     320          75 :         deltaToken = id;
     321          75 :         return *this;
     322             : }
     323             : 
     324           0 : Query & Query::delta(const StringView &str) {
     325           0 :         auto b = base64::decode<Interface>(str);
     326           0 :         stappler::BytesViewNetwork r(b);
     327           0 :         switch (r.size()) {
     328           0 :         case 2: deltaToken = r.readUnsigned16(); break;
     329           0 :         case 4: deltaToken = r.readUnsigned32(); break;
     330           0 :         case 8: deltaToken = r.readUnsigned64();  break;
     331             :         }
     332           0 :         return *this;
     333           0 : }
     334             : 
     335       12950 : Query & Query::include(Field &&f) {
     336       12950 :         fieldsInclude.emplace_back(std::move(f));
     337       12950 :         return *this;
     338             : }
     339           0 : Query & Query::exclude(Field &&f) {
     340           0 :         fieldsExclude.emplace_back(std::move(f));
     341           0 :         return *this;
     342             : }
     343             : 
     344         400 : Query & Query::depth(uint16_t d) {
     345         400 :         resolveDepth = std::max(d, resolveDepth);
     346         400 :         return *this;
     347             : }
     348             : 
     349        1925 : Query & Query::forUpdate() {
     350        1925 :         update = true;
     351        1925 :         return *this;
     352             : }
     353             : 
     354          25 : Query & Query::clearFields() {
     355          25 :         fieldsInclude.clear();
     356          25 :         fieldsExclude.clear();
     357          25 :         return *this;
     358             : }
     359             : 
     360        4025 : bool Query::empty() const {
     361        4025 :         return selectList.empty() && selectIds.empty() && selectAlias.empty();
     362             : }
     363             : 
     364       12874 : StringView Query::getQueryField() const {
     365       12874 :         return queryField;
     366             : }
     367             : 
     368          50 : int64_t Query::getQueryId() const {
     369          50 :         return queryId;
     370             : }
     371             : 
     372       29599 : int64_t Query::getSingleSelectId() const {
     373       29599 :         return selectIds.size() == 1 ? selectIds.front() : 0;
     374             : }
     375             : 
     376        6150 : const Vector<int64_t> & Query::getSelectIds() const {
     377        6150 :         return selectIds;
     378             : }
     379             : 
     380        5475 : StringView Query::getSelectAlias() const {
     381        5475 :         return selectAlias;
     382             : }
     383             : 
     384       21250 : const Vector<Query::Select> &Query::getSelectList() const {
     385       21250 :         return selectList;
     386             : }
     387             : 
     388        2500 : const String & Query::getOrderField() const {
     389        2500 :         return orderField;
     390             : }
     391             : 
     392        7525 : Ordering Query::getOrdering() const {
     393        7525 :         return ordering;
     394             : }
     395             : 
     396        1750 : size_t Query::getLimitValue() const {
     397        1750 :         return limitValue;
     398             : }
     399             : 
     400         225 : size_t Query::getOffsetValue() const {
     401         225 :         return offsetValue;
     402             : }
     403             : 
     404        6025 : const Value &Query::getSoftLimitValue() const {
     405        6025 :         return softLimitValue;
     406             : }
     407             : 
     408        3650 : bool Query::hasSelectName() const {
     409        3650 :         return !selectIds.empty() || !selectAlias.empty() || _selected;
     410             : }
     411        1575 : bool Query::hasSelectList() const {
     412        1575 :         return !selectList.empty();
     413             : }
     414             : 
     415       12125 : bool Query::hasSelect() const {
     416       12125 :         if (getSingleSelectId() || !getSelectIds().empty() || !getSelectAlias().empty() || !getSelectList().empty()) {
     417       11750 :                 return true;
     418             :         }
     419         375 :         return false;
     420             : }
     421             : 
     422        9500 : bool Query::hasOrder() const {
     423        9500 :         return !orderField.empty();
     424             : }
     425             : 
     426        9700 : bool Query::hasLimit() const {
     427        9700 :         return limitValue != stappler::maxOf<size_t>();
     428             : }
     429             : 
     430        8325 : bool Query::hasOffset() const {
     431        8325 :         return offsetValue != 0;
     432             : }
     433             : 
     434        3725 : bool Query::hasDelta() const {
     435        3725 :         return deltaToken > 0;
     436             : }
     437           0 : bool Query::hasFields() const {
     438           0 :         return !fieldsExclude.empty() || !fieldsInclude.empty();
     439             : }
     440        6350 : bool Query::isForUpdate() const {
     441        6350 :         return update;
     442             : }
     443        6350 : bool Query::isSoftLimit() const {
     444        6350 :         return _softLimit;
     445             : }
     446             : 
     447         125 : uint64_t Query::getDeltaToken() const {
     448         125 :         return deltaToken;
     449             : }
     450             : 
     451        8400 : uint16_t Query::getResolveDepth() const {
     452        8400 :         return resolveDepth;
     453             : }
     454             : 
     455      125425 : const Query::FieldsVec &Query::getIncludeFields() const {
     456      125425 :         return fieldsInclude;
     457             : }
     458       20125 : const Query::FieldsVec &Query::getExcludeFields() const {
     459       20125 :         return fieldsExclude;
     460             : }
     461             : 
     462           0 : bool Query_Field_isFlat(const Vector<Query::Field> &l) {
     463           0 :         for (auto &it : l) {
     464           0 :                 if (!it.fields.empty()) {
     465           0 :                         return false;
     466             :                 }
     467             :         }
     468           0 :         return true;
     469             : }
     470             : 
     471           0 : void Query_encodeFields(Value &d, const Vector<Query::Field> &fields) {
     472           0 :         if (Query_Field_isFlat(fields)) {
     473           0 :                 for (auto &it : fields) {
     474           0 :                         d.addString(it.name);
     475             :                 }
     476             :         } else {
     477           0 :                 for (auto &it : fields) {
     478           0 :                         if (it.fields.empty()) {
     479           0 :                                 d.setBool(true, it.name);
     480             :                         } else{
     481           0 :                                 Query_encodeFields(d.emplace(it.name), it.fields);
     482             :                         }
     483             :                 }
     484             :         }
     485           0 : }
     486             : 
     487           0 : Value Query::encode() const {
     488           0 :         Value ret;
     489           0 :         if (selectIds.size() == 1) {
     490           0 :                 ret.setInteger(selectIds.front(), "select");
     491           0 :         } else if (!selectIds.empty()) {
     492           0 :                 auto &vals = ret.emplace("select");
     493           0 :                 vals.setArray(Value::ArrayType());
     494           0 :                 vals.asArray().reserve(selectIds.size());
     495           0 :                 for (auto &it : selectIds) {
     496           0 :                         vals.addInteger(it);
     497             :                 }
     498           0 :         } else if (!selectAlias.empty()) {
     499           0 :                 ret.setString(selectAlias, "select");
     500           0 :         } else if (!selectList.empty()) {
     501           0 :                 auto &sel = ret.emplace("select");
     502           0 :                 for (const Select &it : selectList) {
     503           0 :                         auto &s = sel.emplace();
     504           0 :                         s.addString(it.field);
     505           0 :                         bool twoArgs = false;
     506           0 :                         StringView val;
     507           0 :                         std::tie(val, twoArgs) = encodeComparation(it.compare);
     508           0 :                         s.addString(val);
     509           0 :                         s.addValue(it.value1);
     510           0 :                         if (twoArgs) {
     511           0 :                                 s.addValue(it.value2);
     512             :                         }
     513             :                 }
     514             :         }
     515             : 
     516           0 :         if (hasOrder()) {
     517           0 :                 auto &ord = ret.emplace("order");
     518           0 :                 ord.addString(orderField);
     519           0 :                 switch (ordering) {
     520           0 :                 case Ordering::Ascending: ord.addString("asc"); break;
     521           0 :                 case Ordering::Descending: ord.addString("desc"); break;
     522             :                 }
     523           0 :                 if (hasLimit()) {
     524           0 :                         ord.addInteger(limitValue);
     525           0 :                         if (hasOffset()) {
     526           0 :                                 ord.addInteger(offsetValue);
     527             :                         }
     528           0 :                 } else if (hasOffset()) {
     529           0 :                         ret.setInteger(offsetValue, "offset");
     530             :                 }
     531             :         }
     532             : 
     533           0 :         if (hasDelta()) {
     534           0 :                 ret.setInteger(deltaToken, "delta");
     535             :         }
     536             : 
     537           0 :         if (hasFields()) {
     538           0 :                 if (!fieldsInclude.empty()) {
     539           0 :                         Query_encodeFields(ret.emplace("include"), fieldsInclude);
     540             :                 }
     541           0 :                 if (!fieldsExclude.empty()) {
     542           0 :                         Query_encodeFields(ret.emplace("exclude"), fieldsExclude);
     543             :                 }
     544             :         }
     545             : 
     546           0 :         if (update) {
     547           0 :                 ret.setBool(update, "forUpdate");
     548             :         }
     549             : 
     550           0 :         return ret;
     551           0 : }
     552             : 
     553             : }

Generated by: LCOV version 1.14