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_SPSQLINSERT_HPP_
28 : #define STAPPLER_SQL_SPSQLINSERT_HPP_
29 :
30 : #include "SPSql.h"
31 :
32 : namespace STAPPLER_VERSIONIZED stappler::sql {
33 :
34 : template <typename Binder, typename Interface>
35 : template <typename ...Args>
36 4400 : auto Query<Binder, Interface>::Insert::values(Args && ... args) -> InsertValues {
37 4400 : switch (this->state) {
38 0 : case State::None: this->query->stream << " VALUES"; break;
39 4400 : case State::Some: this->query->stream << ")VALUES"; break;
40 0 : case State::Init: break;
41 : }
42 :
43 4400 : InsertValues v(this->query, State::Init);
44 4400 : Expand<InsertValues>::values(v, forward<Args>(args)...);
45 4400 : return v;
46 : }
47 :
48 : template <typename Binder, typename Interface>
49 : template <typename ...Args>
50 550 : auto Query<Binder, Interface>::InsertValues::values(Args && ... args) -> InsertValues & {
51 550 : if (this->state == State::Some) {
52 225 : this->query->stream << ")";
53 225 : this->state = State::None;
54 225 : this->query->finalization = FinalizationState::None;
55 : }
56 :
57 550 : Expand<InsertValues>::values(*this, forward<Args>(args)...);
58 :
59 550 : return *this;
60 : }
61 :
62 : template <typename Binder, typename Interface>
63 : template <typename Value>
64 33350 : auto Query<Binder, Interface>::InsertValues::value(Value &&val) -> InsertValues & {
65 33350 : switch (this->state) {
66 250 : case State::None:
67 250 : this->query->stream << ",(";
68 250 : this->state = State::Some;
69 250 : this->query->finalization = FinalizationState::Parentesis;
70 250 : break;
71 4400 : case State::Init:
72 4400 : this->query->stream << "(";
73 4400 : this->state = State::Some;
74 4400 : this->query->finalization = FinalizationState::Parentesis;
75 4400 : break;
76 28700 : case State::Some:
77 28700 : this->query->stream << ",";
78 28700 : break;
79 : }
80 :
81 33350 : this->query->writeBind(forward<Value>(val));
82 33350 : return *this;
83 : }
84 :
85 : template <typename Binder, typename Interface>
86 0 : auto Query<Binder, Interface>::InsertValues::def() -> InsertValues & {
87 0 : switch (this->state) {
88 0 : case State::None:
89 0 : this->query->stream << ",(";
90 0 : this->state = State::Some;
91 0 : this->query->finalization = FinalizationState::Parentesis;
92 0 : break;
93 0 : case State::Init:
94 0 : this->query->stream << "(";
95 0 : this->state = State::Some;
96 0 : this->query->finalization = FinalizationState::Parentesis;
97 0 : break;
98 0 : case State::Some:
99 0 : this->query->stream << ",";
100 0 : break;
101 : }
102 :
103 0 : switch (this->query->profile) {
104 0 : case Profile::Postgres:
105 0 : this->query->stream << "DEFAULT";
106 0 : break;
107 0 : case Profile::Sqlite:
108 0 : this->query->stream << "NULL";
109 0 : break;
110 : }
111 0 : return *this;
112 : }
113 :
114 : template <typename Binder, typename Interface>
115 250 : auto Query<Binder, Interface>::InsertValues::onConflict(const StringView &field) -> InsertConflict {
116 250 : switch (this->state) {
117 0 : case State::None: break;
118 0 : case State::Init: break;
119 250 : case State::Some:
120 250 : this->query->stream << ")";
121 250 : this->query->finalization = FinalizationState::None;
122 250 : break;
123 : }
124 :
125 250 : this->state = State::None;
126 250 : this->query->stream << "ON CONFLICT(\"" << field << "\")";
127 250 : return InsertConflict(this->query);
128 : }
129 :
130 : template <typename Binder, typename Interface>
131 350 : auto Query<Binder, Interface>::InsertValues::onConflictDoNothing() -> InsertPostConflict {
132 350 : switch (this->state) {
133 0 : case State::None: break;
134 0 : case State::Init: break;
135 350 : case State::Some:
136 350 : this->query->stream << ")";
137 350 : this->query->finalization = FinalizationState::None;
138 350 : break;
139 : }
140 350 : this->query->stream << "ON CONFLICT DO NOTHING";
141 350 : return InsertPostConflict(this->query);
142 : }
143 :
144 : template <typename Binder, typename Interface>
145 3650 : auto Query<Binder, Interface>::InsertValues::returning() -> Returning {
146 3650 : switch (this->state) {
147 125 : case State::None: break;
148 0 : case State::Init: break;
149 3525 : case State::Some:
150 3525 : this->query->stream << ")";
151 3525 : this->query->finalization = FinalizationState::None;
152 3525 : break;
153 : }
154 3650 : this->query->stream << " RETURNING";
155 3650 : return Returning(this->query);
156 : }
157 :
158 : template <typename Binder, typename Interface>
159 50 : auto Query<Binder, Interface>::InsertValues::next() -> InsertValues {
160 50 : switch (this->state) {
161 0 : case State::None:
162 : case State::Init:
163 0 : this->query->stream << "\n";
164 0 : break;
165 50 : case State::Some:
166 50 : this->query->stream << ")\n";
167 50 : break;
168 : }
169 :
170 50 : this->query->finalization = FinalizationState::None;
171 50 : InsertValues v(this->query, State::None);
172 50 : return v;
173 : }
174 :
175 : template <typename Binder, typename Interface>
176 50 : auto Query<Binder, Interface>::InsertConflict::doNothing() -> InsertPostConflict {
177 50 : this->query->stream << " DO NOTHING ";
178 50 : return InsertPostConflict(this->query);
179 : }
180 :
181 : template <typename Binder, typename Interface>
182 200 : auto Query<Binder, Interface>::InsertConflict::doUpdate() -> InsertUpdateValues {
183 200 : this->query->stream << " DO UPDATE SET";
184 200 : return InsertUpdateValues(this->query);
185 : }
186 :
187 : template <typename Binder, typename Interface>
188 900 : auto Query<Binder, Interface>::InsertUpdateValues::excluded(StringView f) -> InsertUpdateValues & {
189 900 : if (this->state == State::None) { this->state = State::Some; } else { this->query->stream << ","; }
190 900 : this->query->stream << " \"" << f << "\"=EXCLUDED.\"" << f << "\"";
191 900 : return *this;
192 : }
193 :
194 : template <typename Binder, typename Interface>
195 : auto Query<Binder, Interface>::InsertUpdateValues::excluded(StringView f, StringView v) -> InsertUpdateValues & {
196 : if (this->state == State::None) { this->state = State::Some; } else { this->query->stream << ","; }
197 : this->query->stream << " \"" << f << "\"=EXCLUDED.\"" << v << "\"";
198 : return *this;
199 : }
200 :
201 : template <typename Binder, typename Interface>
202 : template <typename ... Args>
203 25 : auto Query<Binder, Interface>::InsertUpdateValues::where(Args && ... args) -> InsertWhereValues {
204 25 : this->query->stream << " WHERE";
205 25 : InsertWhereValues q(this->query);
206 25 : q.where(sql::Operator::And, forward<Args>(args)...);
207 25 : return q;
208 : };
209 :
210 : template <typename Binder, typename Interface>
211 0 : auto Query<Binder, Interface>::InsertUpdateValues::where() -> InsertWhereValues {
212 0 : this->query->stream << " WHERE";
213 0 : return InsertWhereValues(this->query);
214 : };
215 :
216 : template <typename Binder, typename Interface>
217 : auto Query<Binder, Interface>::InsertUpdateValues::returning() -> Returning {
218 : this->query->stream << " RETURNING";
219 : return Returning(this->query);
220 : }
221 :
222 : template <typename Binder, typename Interface>
223 25 : auto Query<Binder, Interface>::InsertWhereValues::returning() -> Returning {
224 25 : this->query->stream << " RETURNING";
225 25 : return Returning(this->query);
226 : }
227 :
228 : template <typename Binder, typename Interface>
229 25 : auto Query<Binder, Interface>::InsertPostConflict::returning() -> Returning {
230 25 : this->query->stream << " RETURNING";
231 25 : return Returning(this->query);
232 : }
233 :
234 : template <typename Binder, typename Interface>
235 100 : auto Query<Binder, Interface>::Returning::all() -> Returning & {
236 100 : if (this->state == State::None) { this->state = State::Some; } else { this->query->stream << ","; }
237 100 : this->query->stream << " *";
238 100 : return *this;
239 : }
240 :
241 : template <typename Binder, typename Interface>
242 : auto Query<Binder, Interface>::Returning::count() -> Returning & {
243 : if (this->state == State::None) { this->state = State::Some; } else { this->query->stream << ","; }
244 : this->query->stream << " COUNT(*)";
245 : return *this;
246 : }
247 :
248 : template <typename Binder, typename Interface>
249 : auto Query<Binder, Interface>::Returning::count(const StringView &alias) -> Returning & {
250 : if (this->state == State::None) { this->state = State::Some; } else { this->query->stream << ","; }
251 : this->query->stream << " COUNT(*) AS \"" << alias << "\"";
252 : return *this;
253 : }
254 :
255 : template <typename Binder, typename Interface>
256 4400 : auto Query<Binder, Interface>::insert(const StringView & field) -> Insert {
257 4400 : stream << "INSERT INTO " << field;
258 4400 : target = field;
259 4400 : return Insert(this, State::Init);
260 : }
261 :
262 : template <typename Binder, typename Interface>
263 : auto Query<Binder, Interface>::insert(const StringView &field, const StringView &alias) -> Insert {
264 : stream << "INSERT INTO " << field << " AS " << alias;
265 : target = field;
266 : return Insert(this, State::Init);
267 : }
268 :
269 : }
270 :
271 : #endif /* STAPPLER_SQL_SPSQLINSERT_HPP_ */
|