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 : // Excluded from documentation/codegen tool
25 : ///@ SP_EXCLUDE
26 :
27 : #ifndef STAPPLER_SQL_SPSQLWHERE_HPP_
28 : #define STAPPLER_SQL_SPSQLWHERE_HPP_
29 :
30 : #include "SPSql.h"
31 :
32 : namespace STAPPLER_VERSIONIZED stappler::sql {
33 :
34 : template <typename Stream>
35 2950 : static inline void Query_writeOperator(Stream &stream, Operator op) {
36 2950 : switch (op) {
37 2825 : case Operator::And: stream << "AND"; break;
38 125 : case Operator::Or: stream << "OR"; break;
39 : }
40 2950 : }
41 :
42 : template <typename Interface>
43 18025 : static inline auto Query_writeFieldName(typename Interface::StringStreamType &stream, const StringView &cmp, bool plain)
44 : -> typename Interface::StringStreamType & {
45 18025 : if (!plain) { stream << '"'; }
46 18025 : stream << cmp;
47 18025 : if (!plain) { stream << '"'; }
48 18025 : return stream;
49 : }
50 :
51 : template <typename Binder, typename Interface, typename Value1>
52 17275 : static inline void Query_writeComparationStr(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
53 : const typename Query<Binder, Interface>::Field &f, const StringView &cmp, Value1 &&v1) {
54 17275 : stream << "(";
55 17275 : if (!f.source.empty()) { stream << "\"" << f.source << "\"."; }
56 17275 : Query_writeFieldName<Interface>(stream, f.name, f.plain) << cmp;
57 17275 : q.writeBind(forward<Value1>(v1));
58 17275 : stream << ")";
59 17275 : }
60 :
61 : template <typename Binder, typename Interface, typename Value1>
62 25 : static inline void Query_writeComparationStrArray(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
63 : const typename Query<Binder, Interface>::Field &f, const StringView &cmp, Value1 &&v1) {
64 25 : stream << "(";
65 25 : if (!f.source.empty()) { stream << "\"" << f.source << "\"."; }
66 25 : Query_writeFieldName<Interface>(stream, f.name, f.plain) << cmp;
67 25 : q.writeBindArray(forward<Value1>(v1));
68 25 : stream << ")";
69 25 : }
70 :
71 : template <typename Binder, typename Interface, typename Value1, typename Value2>
72 50 : static inline void Query_writeComparationStr(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
73 : const typename Query<Binder, Interface>::Field &f, const StringView &cmp1, Value1 &&v1, const StringView &cmp2, Value2 &&v2, const StringView &op) {
74 50 : stream << "(";
75 50 : if (!f.source.empty()) { stream << f.source << "."; }
76 50 : Query_writeFieldName<Interface>(stream, f.name, f.plain) << cmp1;
77 50 : q.writeBind(forward<Value1>(v1));
78 50 : stream << " " << op << " ";
79 50 : if (!f.source.empty()) { stream << f.source << "."; }
80 50 : Query_writeFieldName<Interface>(stream, f.name, f.plain) << cmp2;
81 50 : q.writeBind(forward<Value2>(v2));
82 50 : stream << ")";
83 50 : }
84 :
85 : template <typename Binder, typename Interface, typename Value1, typename Value2>
86 0 : static inline void Query_writeComparationBetween(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
87 : const typename Query<Binder, Interface>::Field &f, Value1 &&v1, Value2 &&v2) {
88 0 : if (!f.source.empty()) { stream << f.source << "."; }
89 0 : Query_writeFieldName<Interface>(stream, f.name, f.plain) << " BETWEEN ";
90 0 : q.writeBind(forward<Value1>(v1));
91 0 : stream << " AND ";
92 0 : q.writeBind(forward<Value2>(v2));
93 0 : }
94 :
95 : template <typename Binder, typename Interface>
96 625 : static inline void Query_writeComparationStrNoArg(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
97 : const typename Query<Binder, Interface>::Field &f, const StringView &cmp) {
98 625 : stream << "(";
99 625 : if (!f.source.empty()) { stream << f.source << "."; }
100 625 : Query_writeFieldName<Interface>(stream, f.name, f.plain) << cmp << ")";
101 625 : }
102 :
103 : template <typename Binder, typename Interface, typename Value1>
104 16725 : inline void Query_writeComparation(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
105 : const typename Query<Binder, Interface>::Field &f, Comparation cmp, Value1 &&v1) {
106 16725 : switch (cmp) {
107 125 : case Comparation::LessThen: Query_writeComparationStr(q, stream, f, "<", std::forward<Value1>(v1)); break;
108 0 : case Comparation::LessOrEqual: Query_writeComparationStr(q, stream, f, "<=", std::forward<Value1>(v1)); break;
109 14925 : case Comparation::Equal: Query_writeComparationStr(q, stream, f, "=", std::forward<Value1>(v1)); break;
110 75 : case Comparation::NotEqual: Query_writeComparationStr(q, stream, f, "!=", std::forward<Value1>(v1)); break;
111 0 : case Comparation::GreatherOrEqual: Query_writeComparationStr(q, stream, f, ">=", std::forward<Value1>(v1)); break;
112 1425 : case Comparation::GreatherThen: Query_writeComparationStr(q, stream, f, ">", std::forward<Value1>(v1)); break;
113 50 : case Comparation::Includes: Query_writeComparationStr(q, stream, f, "@@", std::forward<Value1>(v1)); break;
114 125 : case Comparation::In: Query_writeComparationStr(q, stream, f, " IN ", std::forward<Value1>(v1)); break;
115 0 : case Comparation::NotIn: Query_writeComparationStr(q, stream, f, " NOT IN ", std::forward<Value1>(v1)); break;
116 0 : case Comparation::IsNull: Query_writeComparationStrNoArg(q, stream, f, " IS NULL"); break;
117 0 : case Comparation::IsNotNull: Query_writeComparationStrNoArg(q, stream, f, " IS NOT NULL"); break;
118 0 : default: break;
119 : }
120 16725 : }
121 :
122 : template <typename T>
123 0 : auto makePatternComparator(Comparation cmp, T &&value) -> PatternComparator<T> {
124 0 : return PatternComparator<T>{cmp, &value};
125 : }
126 :
127 : template <typename Binder, typename Interface, typename Value1, typename Value2>
128 1150 : inline void Query_writeComparation(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
129 : const typename Query<Binder, Interface>::Field &f, Comparation cmp, Value1 &&v1, Value2 &&v2) {
130 1150 : stream << "(";
131 1150 : switch (cmp) {
132 0 : case Comparation::Invalid: break;
133 50 : case Comparation::LessThen: Query_writeComparationStr(q, stream, f, "<", std::forward<Value1>(v1)); break;
134 0 : case Comparation::LessOrEqual: Query_writeComparationStr(q, stream, f, "<=", std::forward<Value1>(v1)); break;
135 375 : case Comparation::Equal: Query_writeComparationStr(q, stream, f, "=", std::forward<Value1>(v1)); break;
136 0 : case Comparation::NotEqual: Query_writeComparationStr(q, stream, f, "!=", std::forward<Value1>(v1)); break;
137 0 : case Comparation::GreatherOrEqual: Query_writeComparationStr(q, stream, f, ">=", std::forward<Value1>(v1)); break;
138 25 : case Comparation::GreatherThen: Query_writeComparationStr(q, stream, f, ">", std::forward<Value1>(v1)); break;
139 50 : case Comparation::BetweenValues: Query_writeComparationStr(q, stream, f, ">", std::forward<Value1>(v1), "<", std::forward<Value2>(v2), "AND"); break;
140 0 : case Comparation::BetweenEquals: Query_writeComparationStr(q, stream, f, ">=", std::forward<Value1>(v1), "<=", std::forward<Value2>(v2), "AND"); break;
141 0 : case Comparation::NotBetweenValues: Query_writeComparationStr(q, stream, f, "<=", std::forward<Value1>(v1), ">=", std::forward<Value2>(v2), "OR"); break;
142 0 : case Comparation::NotBetweenEquals: Query_writeComparationStr(q, stream, f, "<", std::forward<Value1>(v1), ">", std::forward<Value2>(v2), "OR"); break;
143 0 : case Comparation::Includes: Query_writeComparationStr(q, stream, f, "@@", std::forward<Value1>(v1)); break;
144 0 : case Comparation::Between: Query_writeComparationBetween(q, stream, f, std::forward<Value1>(v1), std::forward<Value2>(v2)); break;
145 25 : case Comparation::In: Query_writeComparationStrArray(q, stream, f, " IN ", std::forward<Value1>(v1)); break;
146 0 : case Comparation::NotIn: Query_writeComparationStrArray(q, stream, f, " NOT IN ", std::forward<Value1>(v1)); break;
147 0 : case Comparation::IsNull: Query_writeComparationStrNoArg(q, stream, f, " IS NULL"); break;
148 625 : case Comparation::IsNotNull: Query_writeComparationStrNoArg(q, stream, f, " IS NOT NULL"); break;
149 0 : case Comparation::Prefix: Query_writeComparationStr(q, stream, f, " LIKE ", makePatternComparator(cmp, std::forward<Value1>(v1))); break;
150 0 : case Comparation::Suffix: Query_writeComparationStr(q, stream, f, " LIKE ", makePatternComparator(cmp, std::forward<Value1>(v1))); break;
151 0 : case Comparation::WordPart: Query_writeComparationStr(q, stream, f, " LIKE ", makePatternComparator(cmp, std::forward<Value1>(v1))); break;
152 : }
153 1150 : stream << ")";
154 1150 : }
155 :
156 : template <typename Binder, typename Interface>
157 : template <typename Clause>
158 : template <typename Value>
159 16725 : auto Query<Binder, Interface>::WhereClause<Clause>::where(Operator op, const Field &field, Comparation cmp, Value &&val) -> Clause & {
160 16725 : if (this->state == State::None) { this->state = State::Some; } else { Query_writeOperator(this->query->stream, op); }
161 16725 : Query_writeComparation(*(this->query), this->query->stream, field, cmp, std::forward<Value>(val));
162 16725 : return (Clause &)*this;
163 : }
164 :
165 : template <typename Binder, typename Interface>
166 : template <typename Clause>
167 : template <typename Value>
168 100 : auto Query<Binder, Interface>::WhereClause<Clause>::where(Operator op, const Field &field, const StringView &cmp, Value &&val) -> Clause & {
169 100 : if (this->state == State::None) { this->state = State::Some; } else { Query_writeOperator(this->query->stream, op); }
170 100 : Query_writeComparationStr(*(this->query), this->query->stream, field, cmp, std::forward<Value>(val));
171 100 : return (Clause &)*this;
172 : }
173 :
174 : template <typename Binder, typename Interface>
175 : template <typename Clause>
176 : template <typename Value>
177 1150 : auto Query<Binder, Interface>::WhereClause<Clause>::where(Operator op, const Field &field, Comparation cmp, Value &&val1, Value &&val2) -> Clause & {
178 1150 : if (this->state == State::None) { this->state = State::Some; } else { Query_writeOperator(this->query->stream, op); }
179 1150 : Query_writeComparation(*(this->query), this->query->stream, field, cmp, std::forward<Value>(val1), std::forward<Value>(val2));
180 1150 : return (Clause &)*this;
181 : }
182 :
183 : template <typename Binder, typename Interface>
184 : template <typename Clause>
185 : template <typename Value>
186 : auto Query<Binder, Interface>::WhereClause<Clause>::where(Operator op, const Field &field, const StringView &cmp1, Value &&val1, const StringView &cmp2, Value &&val2) -> Clause & {
187 : if (this->state == State::None) { this->state = State::Some; } else { Query_writeOperator(this->query->stream, op); }
188 : Query_writeComparationStr(*(this->query), this->query->stream, field, cmp1, std::forward<Value>(val1), cmp2, std::forward<Value>(val2));
189 : return (Clause &)*this;
190 : }
191 :
192 : template <typename Binder, typename Interface>
193 : template <typename Clause>
194 : template <typename Callback>
195 1800 : auto Query<Binder, Interface>::WhereClause<Clause>::parenthesis(Operator op, const Callback &cb) -> Clause & {
196 1800 : if (this->state == State::None) { this->state = State::Some; } else { Query_writeOperator(this->query->stream, op); }
197 1800 : this->query->stream << "(";
198 1800 : auto state = this->state;
199 1800 : this->state = State::None;
200 1800 : WhereBegin tmp(this->query);
201 1800 : cb(tmp);
202 1800 : this->state = state;
203 1800 : this->query->stream << ")";
204 1800 : return (Clause &)*this;
205 : }
206 :
207 : template <typename Binder, typename Interface>
208 : template <typename ... Args>
209 1625 : auto Query<Binder, Interface>::WhereBegin::where(Args && ... args) -> WhereContinue {
210 1625 : WhereContinue q(this->query);
211 1625 : q.where(sql::Operator::And, std::forward<Args>(args)...);
212 1625 : return q;
213 : }
214 :
215 : template <typename Binder, typename Interface>
216 1775 : auto Query<Binder, Interface>::WhereBegin::where() -> WhereContinue {
217 1775 : return WhereContinue(this->query);
218 : }
219 :
220 : template <typename Binder, typename Interface>
221 : template <typename Callback>
222 : auto Query<Binder, Interface>::WhereBegin::whereParentesis(const Callback &cb) -> WhereContinue {
223 : WhereContinue q(this->query);
224 : q.parenthesis(sql::Operator::And, cb);
225 : return q;
226 : }
227 :
228 : template <typename Binder, typename Interface>
229 : template <typename Clause>
230 : template <typename Value>
231 6100 : auto Query<Binder, Interface>::SetClause<Clause>::set(const StringView &f, Value &&v) -> Clause & {
232 6100 : if (this->state == State::None) { this->state = State::Some; } else { this->query->stream << ","; }
233 6100 : this->query->stream << " \"" << f << "\"=";
234 6100 : this->query->writeBind(forward<Value>(v));
235 6100 : return (Clause &)*this;
236 : }
237 :
238 : template <typename Binder, typename Interface>
239 : template <typename Clause>
240 : template <typename Value>
241 : auto Query<Binder, Interface>::SetClause<Clause>::set(const StringView &t, const StringView &f, Value && v) -> Clause & {
242 : if (this->state == State::None) { this->state = State::Some; } else { this->query->stream << ","; }
243 : this->query->stream << " " << t << ".\"" << f << "\"=";
244 : this->query->writeBind(forward<Value>(v));
245 : return (Clause &)*this;
246 : }
247 :
248 : template <typename Binder, typename Interface>
249 : template <typename Clause>
250 25 : auto Query<Binder, Interface>::SetClause<Clause>::def(const StringView &f) -> Clause & {
251 25 : if (this->state == State::None) { this->state = State::Some; } else { this->query->stream << ","; }
252 25 : this->query->stream << " \"" << f << "\"=DEFAULT";
253 25 : return (Clause &)*this;
254 : }
255 :
256 : }
257 :
258 : #endif /* STAPPLER_SQL_SPSQLWHERE_HPP_ */
|