Line data Source code
1 : /**
2 : Copyright (c) 2017-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_SQL_SQLQUERY_H_
25 : #define STAPPLER_SQL_SQLQUERY_H_
26 :
27 : #include "SPString.h"
28 : #include "SPMemory.h"
29 : #include "SPData.h"
30 :
31 : namespace STAPPLER_VERSIONIZED stappler::sql {
32 :
33 : enum class Profile {
34 : Postgres,
35 : Sqlite
36 : };
37 :
38 : enum class Comparation {
39 : Invalid,
40 : LessThen, // lt
41 : LessOrEqual, // le
42 : Equal, // eq
43 : NotEqual, // neq
44 : GreatherOrEqual, // ge
45 : GreatherThen, // gt
46 : BetweenValues, // bw field > v1 AND field < v2
47 : BetweenEquals, // be field >= v1 AND field <= v2
48 : NotBetweenValues, // nbw field < v1 OR field > v2
49 : NotBetweenEquals, // nbe field <= v1 OR field >= v2
50 : Includes, // @@ - operation
51 : Between, // customized BETWEEN ... AND ...
52 : In,
53 : NotIn,
54 : IsNull,
55 : IsNotNull,
56 : Prefix, // LIKE 'text%'
57 : Suffix, // LIKE '%text'
58 : WordPart, // LIKE '%text%'
59 : };
60 :
61 : enum class Ordering {
62 : Ascending,
63 : Descending,
64 : };
65 :
66 : enum class Nulls {
67 : None,
68 : First,
69 : Last,
70 : };
71 :
72 : enum class Operator {
73 : And,
74 : Or,
75 : };
76 :
77 : Pair<StringView, bool> encodeComparation(Comparation);
78 : Pair<Comparation, bool> decodeComparation(StringView);
79 :
80 : template <typename T>
81 : struct PatternComparator {
82 : using Type = typename std::remove_reference<T>::type;
83 : Comparation cmp = Comparation::Prefix;
84 : const Type *value = nullptr;
85 : };
86 :
87 : template <typename Interface>
88 : struct SimpleBinder : public Interface::AllocBaseType {
89 150 : void writeBind(std::ostream &stream, const data::ValueTemplate<Interface> &val) {
90 150 : stream << data::toString(val);
91 150 : }
92 400 : void writeBind(std::ostream &stream, const typename Interface::StringType &val) {
93 400 : stream << val;
94 400 : }
95 : void writeBind(std::ostream &stream, const typename Interface::BytesType &val) {
96 : base16::encode(stream, val);
97 : }
98 0 : void writeBind(std::ostream &stream, const PatternComparator<data::ValueTemplate<Interface>> &val) {
99 0 : switch (val.cmp) {
100 0 : case Comparation::Prefix:
101 0 : stream << val.value->asString() << "%";
102 0 : break;
103 0 : case Comparation::Suffix:
104 0 : stream << "&" << val.value->asString();
105 0 : break;
106 0 : case Comparation::WordPart:
107 0 : stream << "&" << val.value->asString() << "%";
108 0 : break;
109 0 : default:
110 0 : break;
111 : }
112 0 : }
113 0 : void writeBindArray(std::ostream &stream, const data::ValueTemplate<Interface> &val) {
114 0 : stream << "(";
115 0 : bool first = true;
116 0 : if (val.isArray()) {
117 0 : for (auto &it : val.asArray()) {
118 0 : if (first) { first = false; } else { stream << ","; }
119 0 : stream << it;
120 : }
121 : }
122 0 : stream << ")";
123 0 : }
124 : };
125 :
126 : template <typename Binder, typename Interface>
127 : class Query : public Interface::AllocBaseType {
128 : public:
129 : using Stream = typename Interface::StringStreamType;
130 : using String = typename Interface::StringType;
131 :
132 : struct Select;
133 : struct SelectFrom;
134 : struct SelectWhere;
135 : struct SelectGroup;
136 : struct SelectOrder;
137 : struct SelectPost;
138 :
139 : struct Insert;
140 : struct InsertValues;
141 : struct InsertConflict;
142 : struct InsertUpdateValues;
143 : struct InsertWhereValues;
144 : struct InsertPostConflict;
145 :
146 : struct Update;
147 : struct UpdateWhere;
148 :
149 : struct Delete;
150 : struct DeleteWhere;
151 :
152 : struct Returning;
153 : struct WhereBegin;
154 : struct WhereContinue;
155 :
156 : enum class Distinct {
157 : Distinct,
158 : None,
159 : };
160 :
161 : enum class State {
162 : None,
163 : Init,
164 : Some,
165 : };
166 :
167 : enum class FinalizationState {
168 : None,
169 : Parentesis,
170 : Quote,
171 : DoubleQuote,
172 : Finalized,
173 : };
174 :
175 : struct RawString {
176 : String data;
177 : };
178 :
179 : struct RawStringView {
180 : StringView data;
181 : };
182 :
183 : struct Field {
184 : enum Flags {
185 : None,
186 : PlainText
187 : };
188 : static Field all() { return Field("*"); }
189 0 : static Field all(const StringView & t) { return Field(t, "*"); }
190 :
191 61300 : Field(const StringView &str) : name(str) { }
192 22700 : Field(const char *str) : name(str) { }
193 : Field(const std::string &str) : name(str) { }
194 2475 : Field(const memory::string &str) : name(str) { }
195 :
196 250 : Field(const StringView &str, Flags f) : name(str), plain(f == PlainText) { }
197 :
198 12675 : Field(const StringView &t, const StringView &f) : source(t), name(f) { }
199 :
200 6325 : Field & as(const char *str) { alias = StringView(str); return *this; }
201 : Field & as(const std::string &str) { alias = StringView(str); return *this; }
202 375 : Field & as(const memory::string &str) { alias = StringView(str); return *this; }
203 :
204 : Field & from(const char *str) { source = StringView(str); return *this; }
205 : Field & from(const std::string &str) { source = StringView(str); return *this; }
206 : Field & from(const memory::string &str) { source = StringView(str); return *this; }
207 :
208 : StringView source;
209 : StringView name;
210 : StringView alias;
211 : bool plain = false;
212 : };
213 :
214 : template <typename Clause>
215 : struct Expand {
216 : template <typename ... VArgs>
217 1500 : static void fields(Clause &c, const Field &f, VArgs && ... args) {
218 1500 : c.field(f);
219 1500 : fields(c, forward<VArgs>(args)...);
220 1500 : }
221 1275 : static void fields(Clause &c, const Field &f) {
222 1275 : c.field(f);
223 1275 : }
224 :
225 : template <typename ... VArgs>
226 1125 : static void from(Clause &c, const Field &f, VArgs && ... args) {
227 1125 : c.from(f);
228 1125 : from(c, forward<VArgs>(args)...);
229 1125 : }
230 1125 : static void from(Clause &c, const Field &f) {
231 1125 : c.from(f);
232 1125 : }
233 :
234 : template <typename Value, typename ... VArgs>
235 1300 : static void values(Clause &c, Value &&v, VArgs && ... args) {
236 1300 : c.value(forward<Value>(v));
237 1300 : values(c, forward<VArgs>(args)...);
238 1300 : }
239 :
240 : template <typename Value>
241 750 : static void values(Clause &c, Value &&v) {
242 750 : c.value(forward<Value>(v));
243 750 : }
244 :
245 4200 : static void values(Clause &c) { }
246 : };
247 :
248 : struct QueryHandle {
249 : Query *query = nullptr;
250 : State state = State::None;
251 :
252 : void finalize();
253 :
254 83125 : QueryHandle(Query *q, State s = State::None) : query(q), state(s) { }
255 : };
256 :
257 : template <typename Clause>
258 : struct WhereClause : QueryHandle {
259 : template <typename Value>
260 : auto where(Operator, const Field &field, Comparation, Value &&) -> Clause &;
261 :
262 : template <typename Value>
263 : auto where(Operator, const Field &field, const StringView &, Value &&) -> Clause &;
264 :
265 : template <typename Value>
266 : auto where(Operator, const Field &field, Comparation, Value &&, Value &&) -> Clause &;
267 :
268 : template <typename Value>
269 : auto where(Operator, const Field &field, const StringView &, Value &&, const StringView &, Value &&) -> Clause &;
270 :
271 : template <typename Callback>
272 : auto parenthesis(Operator, const Callback &) -> Clause &;
273 :
274 : using QueryHandle::QueryHandle;
275 : };
276 :
277 : struct WhereBegin : QueryHandle {
278 : template <typename ... Args>
279 : auto where(Args && ... args) -> WhereContinue;
280 : auto where() -> WhereContinue;
281 :
282 : template <typename Callback>
283 : auto whereParentesis(const Callback &) -> WhereContinue;
284 :
285 : using QueryHandle::QueryHandle;
286 : };
287 :
288 : struct WhereContinue : WhereClause<WhereContinue> {
289 : using WhereClause<WhereContinue>::WhereClause;
290 : };
291 :
292 : template <typename Clause>
293 : struct SetClause : QueryHandle {
294 : template <typename Value>
295 : auto set(const StringView &f, Value && v) -> Clause &;
296 :
297 : template <typename Value>
298 : auto set(const StringView &t, const StringView &f, Value && v) -> Clause &;
299 :
300 : auto def(const StringView &f) -> Clause &;
301 :
302 : using QueryHandle::QueryHandle;
303 : };
304 :
305 : template <typename Clause>
306 : struct FieldsClause : QueryHandle {
307 : template <typename ...Args>
308 : auto fields(const Field &f, Args && ... args) -> Clause &;
309 : auto field(const Field &f) -> Clause &;
310 : auto aggregate(const StringView &, const Field &f) -> Clause &;
311 :
312 : using QueryHandle::QueryHandle;
313 : };
314 :
315 : struct GenericQuery : QueryHandle {
316 : template <typename Callback>
317 : auto with(const StringView &alias, const Callback &) -> GenericQuery &;
318 :
319 : Select select(Distinct = Distinct::None);
320 :
321 : template <typename ... Args>
322 : Select select(const Field &, Args && ... args);
323 :
324 : template <typename ... Args>
325 : Select select(Distinct, const Field &, Args && ... args);
326 :
327 : Insert insert(const StringView &);
328 : Insert insert(const StringView &, const StringView &alias);
329 :
330 : Update update(const StringView &);
331 : Update update(const StringView &, const StringView &alias);
332 :
333 : Delete remove(const StringView &);
334 : Delete remove(const StringView &, const StringView &alias);
335 :
336 : using QueryHandle::QueryHandle;
337 : };
338 :
339 : struct Select : FieldsClause<Select> {
340 : auto all() -> Select &;
341 : auto count() -> Select &;
342 : auto count(const String &alias) -> Select &;
343 : auto from() -> SelectFrom;
344 : auto from(const Field &field) -> SelectFrom;
345 : template <typename ... Args>
346 : auto from(const Field &field, Args && ... args) -> SelectFrom;
347 :
348 : using FieldsClause<Select>::FieldsClause;
349 : };
350 :
351 : struct SelectFrom : QueryHandle {
352 : auto from(const Field &field) -> SelectFrom &;
353 : template <typename ... Args>
354 : auto from(const Field &field, Args && ... args) -> SelectFrom &;
355 :
356 : template <typename Callback>
357 : auto innerJoinOn(const StringView &s, const Callback &cb) -> SelectFrom &;
358 :
359 : template <typename Callback>
360 : auto leftJoinOn(const StringView &s, const Callback &cb) -> SelectFrom &;
361 :
362 : template <typename Callback>
363 : auto rightJoinOn(const StringView &s, const Callback &cb) -> SelectFrom &;
364 :
365 : template <typename Callback>
366 : auto fullJoinOn(const StringView &s, const Callback &cb) -> SelectFrom &;
367 :
368 : template <typename ... Args>
369 : auto where(Args && ... args) -> SelectWhere;
370 : auto where() -> SelectWhere;
371 : auto group(const Field &) -> SelectGroup;
372 : auto order(Ordering, const Field &, Nulls = Nulls::None) -> SelectOrder;
373 : void forUpdate();
374 :
375 : using QueryHandle::QueryHandle;
376 : };
377 :
378 : struct SelectGroup : QueryHandle {
379 : template <typename ...Args>
380 : auto fields(const Field &f, Args && ... args) -> SelectGroup &;
381 : auto field(const Field &) -> SelectGroup &;
382 : auto order(Ordering, const Field &, Nulls = Nulls::None) -> SelectOrder;
383 :
384 : using QueryHandle::QueryHandle;
385 : };
386 :
387 : struct SelectWhere : WhereClause<SelectWhere> {
388 : auto group(const Field &) -> SelectGroup;
389 : auto order(Ordering, const Field &, Nulls = Nulls::None) -> SelectOrder;
390 : void forUpdate();
391 :
392 : using WhereClause<SelectWhere>::WhereClause;
393 : };
394 :
395 : struct SelectOrder : QueryHandle {
396 : auto limit(size_t limit, size_t offset) -> SelectPost;
397 : auto limit(size_t limit) -> SelectPost;
398 : auto offset(size_t offset) -> SelectPost;
399 : void forUpdate();
400 :
401 : using QueryHandle::QueryHandle;
402 : };
403 :
404 : struct SelectPost : QueryHandle {
405 : void forUpdate();
406 :
407 : using QueryHandle::QueryHandle;
408 : };
409 :
410 : struct Insert : FieldsClause<Insert> {
411 : template <typename ...Args>
412 : auto values(Args && ... args) -> InsertValues;
413 :
414 : using FieldsClause<Insert>::FieldsClause;
415 : };
416 :
417 : struct InsertValues : QueryHandle {
418 : template <typename Value>
419 : auto value(Value &&) -> InsertValues &;
420 : auto def() -> InsertValues &;
421 :
422 : template <typename ...Args>
423 : auto values(Args && ... args) -> InsertValues &;
424 :
425 : auto onConflict(const StringView &) -> InsertConflict;
426 : auto onConflictDoNothing() -> InsertPostConflict;
427 : auto returning() -> Returning;
428 :
429 : auto next() -> InsertValues;
430 :
431 : using QueryHandle::QueryHandle;
432 : };
433 :
434 : struct InsertConflict : QueryHandle {
435 : auto doNothing() -> InsertPostConflict;
436 : auto doUpdate() -> InsertUpdateValues;
437 : using QueryHandle::QueryHandle;
438 : };
439 :
440 : struct InsertUpdateValues : SetClause<InsertUpdateValues> {
441 : auto excluded(StringView f) -> InsertUpdateValues &;
442 : auto excluded(StringView f, StringView v) -> InsertUpdateValues &;
443 : template <typename ... Args>
444 : auto where(Args && ... args) -> InsertWhereValues;
445 : auto where() -> InsertWhereValues;
446 : auto returning() -> Returning;
447 : using SetClause<InsertUpdateValues>::SetClause;
448 : };
449 :
450 : struct InsertWhereValues : WhereClause<InsertWhereValues> {
451 : auto returning() -> Returning;
452 : using WhereClause<InsertWhereValues>::WhereClause;
453 : };
454 :
455 : struct InsertPostConflict : QueryHandle {
456 : auto returning() -> Returning;
457 : using QueryHandle::QueryHandle;
458 : };
459 :
460 : struct Update : SetClause<Update> {
461 : template <typename ... Args>
462 : auto where(Args && ... args) -> UpdateWhere;
463 : auto where() -> UpdateWhere;
464 : auto returning() -> Returning;
465 : using SetClause<Update>::SetClause;
466 : };
467 :
468 : struct UpdateWhere : WhereClause<UpdateWhere> {
469 : auto returning() -> Returning;
470 : using WhereClause<UpdateWhere>::WhereClause;
471 : };
472 :
473 : struct Delete : QueryHandle {
474 : template <typename ... Args>
475 : auto where(Args && ... args) -> DeleteWhere;
476 : auto where() -> DeleteWhere;
477 : auto returning() -> Returning;
478 : using QueryHandle::QueryHandle;
479 : };
480 :
481 : struct DeleteWhere : WhereClause<DeleteWhere> {
482 : auto returning() -> Returning;
483 : using WhereClause<DeleteWhere>::WhereClause;
484 : };
485 :
486 : struct Returning : FieldsClause<Returning> {
487 : auto all() -> Returning &;
488 : auto count() -> Returning &;
489 : auto count(const StringView &alias) -> Returning &;
490 : using FieldsClause<Returning>::FieldsClause;
491 : };
492 :
493 17825 : Query() = default;
494 :
495 13775 : void setProfile(Profile p) { profile = p; }
496 :
497 : template <typename Callback>
498 : GenericQuery with(const StringView &alias, const Callback &);
499 :
500 : Select select(Distinct = Distinct::None);
501 :
502 : template <typename ... Args>
503 : Select select(const Field &, Args && ... args);
504 :
505 : template <typename ... Args>
506 : Select select(Distinct, const Field &, Args && ... args);
507 :
508 : Insert insert(const StringView &);
509 : Insert insert(const StringView &, const StringView &alias);
510 :
511 : Update update(const StringView &);
512 : Update update(const StringView &, const StringView &alias);
513 :
514 : Delete remove(const StringView &);
515 : Delete remove(const StringView &, const StringView &alias);
516 :
517 : void finalize();
518 :
519 : template <typename Value>
520 : void writeBind(Value &&);
521 :
522 : template <typename Value>
523 : void writeBindArray(Value &&);
524 :
525 : void writeBind(const RawString &);
526 : void writeBind(const RawStringView &);
527 : void writeBind(const Callback<void(Select &)> &);
528 : void writeBind(const Field &);
529 : void writeBind(const Field &, bool withAlias);
530 : void writeBind(const StringView &func, const Field &f);
531 :
532 : Stream &getStream();
533 : Binder &getBinder();
534 :
535 : StringView getTarget() const;
536 :
537 : protected:
538 : FinalizationState finalization = FinalizationState::None;
539 : Binder binder;
540 : Stream stream;
541 : StringView target;
542 : bool subquery = false;
543 : Profile profile = Profile::Postgres;
544 : };
545 :
546 : template <typename Binder, typename Interface, typename Value>
547 : struct BinderTraits {
548 : template <typename V>
549 55475 : static void writeBind(Query<Binder, Interface> &q, Binder &b, V &&val) {
550 55475 : b.writeBind(q.getStream(), forward<V>(val));
551 55475 : }
552 :
553 : template <typename V>
554 25 : static void writeBindArray(Query<Binder, Interface> &q, Binder &b, V &&val) {
555 25 : b.writeBindArray(q.getStream(), forward<V>(val));
556 25 : }
557 : };
558 :
559 : template <typename Binder, typename Interface>
560 : struct BinderTraits<Binder, Interface, typename Query<Binder, Interface>::Field> {
561 1650 : static void writeBind(Query<Binder, Interface> &q, Binder &b, const typename Query<Binder, Interface>::Field &val) {
562 1650 : q.writeBind(val);
563 1650 : }
564 : };
565 :
566 : template <typename Binder, typename Interface>
567 : struct BinderTraits<Binder, Interface, typename Query<Binder, Interface>::RawString> {
568 0 : static void writeBind(Query<Binder, Interface> &q, Binder &b, const typename Query<Binder, Interface>::RawString &val) {
569 0 : q.writeBind(val);
570 0 : }
571 : };
572 :
573 : template <typename Binder, typename Interface>
574 : struct BinderTraits<Binder, Interface, typename Query<Binder, Interface>::RawStringView> {
575 300 : static void writeBind(Query<Binder, Interface> &q, Binder &b, const typename Query<Binder, Interface>::RawStringView &val) {
576 300 : q.writeBind(val);
577 300 : }
578 : };
579 :
580 : template <typename Binder, typename Interface>
581 : struct BinderTraits<Binder, Interface, Callback<void(typename Query<Binder, Interface>::Select &)>> {
582 0 : static void writeBind(Query<Binder, Interface> &q, Binder &b, const Callback<void(typename Query<Binder, Interface>::Select &)> &val) {
583 0 : q.writeBind(val);
584 0 : }
585 : };
586 :
587 :
588 : template <typename Binder, typename Interface>
589 16250 : void Query<Binder, Interface>::QueryHandle::finalize() {
590 16250 : this->query->finalize();
591 16250 : }
592 :
593 : template <typename Binder, typename Interface>
594 : template <typename Value>
595 57425 : void Query<Binder, Interface>::writeBind(Value &&val) {
596 57425 : BinderTraits<Binder, Interface, typename std::remove_reference<Value>::type>::writeBind(*this, this->binder, forward<Value>(val));
597 57425 : }
598 :
599 : template <typename Binder, typename Interface>
600 : template <typename Value>
601 25 : void Query<Binder, Interface>::writeBindArray(Value &&val) {
602 25 : BinderTraits<Binder, Interface, typename std::remove_reference<Value>::type>::writeBindArray(*this, this->binder, forward<Value>(val));
603 25 : }
604 :
605 : template <typename Binder, typename Interface>
606 0 : void Query<Binder, Interface>::writeBind(const RawString &data) {
607 0 : stream << data.data;
608 0 : }
609 :
610 : template <typename Binder, typename Interface>
611 300 : void Query<Binder, Interface>::writeBind(const RawStringView &data) {
612 300 : stream << data.data;
613 300 : }
614 :
615 : template <typename Binder, typename Interface>
616 0 : void Query<Binder, Interface>::writeBind(const Callback<void(Select &)> &cb) {
617 0 : stream << "(";
618 0 : auto fin = finalization;
619 0 : finalization = FinalizationState::Finalized;
620 0 : auto sel = select();
621 0 : cb(sel);
622 0 : finalization = fin;
623 0 : stream << ")";
624 0 : }
625 :
626 : template <typename Binder, typename Interface>
627 63925 : void Query<Binder, Interface>::writeBind(const Field &f) {
628 63925 : writeBind(f, true);
629 63925 : }
630 :
631 : template <typename Binder, typename Interface>
632 66550 : void Query<Binder, Interface>::writeBind(const Field &f, bool withAlias) {
633 66550 : if (!f.source.empty()) {
634 6550 : stream << f.source << ".";
635 : }
636 66550 : if (f.name == "*") {
637 3050 : stream << "*";
638 : } else {
639 63500 : stream << "\"" << f.name << "\"";
640 : }
641 66550 : if (withAlias && !f.alias.empty()) {
642 5125 : stream << " AS \"" << f.alias << "\"";
643 : }
644 66550 : }
645 :
646 : template <typename Binder, typename Interface>
647 1075 : void Query<Binder, Interface>::writeBind(const StringView &func, const Field &f) {
648 1075 : stream << func << "(";
649 1075 : writeBind(f, false);
650 1075 : stream << ")";
651 1075 : if (!f.alias.empty()) {
652 750 : stream << " AS \"" << f.alias << "\"";
653 : }
654 1075 : }
655 :
656 : template <typename Binder, typename Interface>
657 55974 : auto Query<Binder, Interface>::getStream() -> typename Query<Binder, Interface>::Stream & {
658 55974 : return stream;
659 : }
660 :
661 : template <typename Binder, typename Interface>
662 100 : auto Query<Binder, Interface>::getBinder() -> Binder & {
663 100 : return binder;
664 : }
665 :
666 : template <typename Binder, typename Interface>
667 : auto Query<Binder, Interface>::getTarget() const -> StringView {
668 : return target;
669 : }
670 :
671 : template <typename Binder, typename Interface>
672 18700 : void Query<Binder, Interface>::finalize() {
673 18700 : if (subquery) {
674 0 : return;
675 : }
676 :
677 18700 : switch (finalization) {
678 17350 : case FinalizationState::None: stream << ";"; break;
679 250 : case FinalizationState::Parentesis: stream << ");"; break;
680 0 : case FinalizationState::Quote: stream << "';"; break;
681 0 : case FinalizationState::DoubleQuote: stream << "\";"; break;
682 1100 : case FinalizationState::Finalized: break;
683 : }
684 18700 : finalization = FinalizationState::Finalized;
685 : }
686 :
687 :
688 : template <typename Binder, typename Interface>
689 : template <typename Callback>
690 1275 : auto Query<Binder, Interface>::with(const StringView &alias, const Callback &cb) -> GenericQuery {
691 1275 : GenericQuery q(this);
692 1275 : q.with(alias, cb);
693 1275 : return q;
694 : }
695 :
696 : template <typename Binder, typename Interface>
697 : template <typename Callback>
698 2775 : auto Query<Binder, Interface>::GenericQuery::with(const StringView &alias, const Callback &cb) -> GenericQuery & {
699 2775 : switch (this->state) {
700 1575 : case State::None:
701 1575 : this->query->stream << "WITH ";
702 1575 : this->state = State::Some;
703 1575 : break;
704 1200 : case State::Some:
705 1200 : this->query->stream << ", ";
706 1200 : break;
707 0 : default:
708 0 : break;
709 : }
710 2775 : this->query->stream << alias << " AS (";
711 :
712 2775 : auto sq = this->query->subquery;
713 2775 : this->query->subquery = true;
714 2775 : GenericQuery q(this->query, State::None);
715 2775 : cb(q);
716 2775 : this->query->subquery = sq;
717 :
718 2775 : this->query->stream << ")";
719 2775 : return *this;
720 : }
721 :
722 : template <typename Binder, typename Interface>
723 5850 : auto Query<Binder, Interface>::GenericQuery::select(Distinct d) -> Select {
724 5850 : return this->query->select(d);
725 : }
726 :
727 : template <typename Binder, typename Interface>
728 : template <typename ... Args>
729 25 : auto Query<Binder, Interface>::GenericQuery::select(const Field &f, Args && ... args) -> Select {
730 25 : return this->query->select(f, forward<Args>(args)...);
731 : }
732 :
733 : template <typename Binder, typename Interface>
734 : template <typename ... Args>
735 125 : auto Query<Binder, Interface>::GenericQuery::select(Distinct d, const Field &f, Args && ... args) -> Select {
736 125 : return this->query->select(d, f, forward<Args>(args)...);
737 : }
738 :
739 : template <typename Binder, typename Interface>
740 : auto Query<Binder, Interface>::GenericQuery::insert(const StringView & field) -> Insert {
741 : return this->query->insert(field);
742 : }
743 :
744 : template <typename Binder, typename Interface>
745 : auto Query<Binder, Interface>::GenericQuery::insert(const StringView &field, const StringView &alias) -> Insert {
746 : return this->query->insert(field, alias);
747 : }
748 :
749 : template <typename Binder, typename Interface>
750 : auto Query<Binder, Interface>::GenericQuery::update(const StringView & field) -> Update {
751 : return this->query->update(field);
752 : }
753 :
754 : template <typename Binder, typename Interface>
755 : auto Query<Binder, Interface>::GenericQuery::update(const StringView &field, const StringView &alias) -> Update {
756 : return this->query->update(field, alias);
757 : }
758 :
759 : template <typename Binder, typename Interface>
760 : auto Query<Binder, Interface>::GenericQuery::remove(const StringView & field) -> Delete {
761 : return this->query->remove(field);
762 : }
763 :
764 : template <typename Binder, typename Interface>
765 : auto Query<Binder, Interface>::GenericQuery::remove(const StringView &field, const StringView &alias) -> Delete {
766 : return this->query->remove(field, alias);
767 : }
768 :
769 : }
770 :
771 : #include "SPSqlInsert.hpp"
772 : #include "SPSqlUpdate.hpp"
773 : #include "SPSqlSelect.hpp"
774 : #include "SPSqlWhere.hpp"
775 :
776 : #endif /* STAPPLER_SQL_SQLQUERY_H_ */
|