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