Line data Source code
1 : /**
2 : Copyright (c) 2019-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 "SPCommon.h"
25 : #include "SPDbAdapter.cc"
26 : #include "SPDbContinueToken.cc"
27 :
28 : #include "SPDbFieldExtensions.cc"
29 : #include "SPPqDriver.cc"
30 : #include "SPPqHandle.cc"
31 : #include "SPPqHandleInit.cc"
32 : #include "SPSqlDriver.cc"
33 : #include "SPSqlHandle.cc"
34 : #include "SPSqlHandleObject.cc"
35 : #include "SPSqlHandleProp.cc"
36 : #include "SPSqlQuery.cc"
37 : #include "SPSqliteModuleTextSearch.cc"
38 : #include "SPSqliteModuleUnwrap.cc"
39 : #include "SPSqliteDriver.cc"
40 : #include "SPSqliteHandle.cc"
41 : #include "SPSqliteHandleInit.cc"
42 : #include "SPDbAuth.cc"
43 : #include "SPDbField.cc"
44 : #include "SPDbFile.cc"
45 : #include "SPDbObject.cc"
46 : #include "SPDbQuery.cc"
47 : #include "SPDbQueryList.cc"
48 : #include "SPDbScheme.cc"
49 : #include "SPDbTransaction.cc"
50 : #include "SPDbUser.cc"
51 : #include "SPDbWorker.cc"
52 :
53 : namespace STAPPLER_VERSIONIZED stappler::db {
54 :
55 175 : InputFile::InputFile(String &&name, String && type, String && enc, String && orig, size_t s, int64_t id)
56 175 : : name(std::move(name)), type(std::move(type)), encoding(std::move(enc))
57 350 : , original(std::move(orig)), writeSize(0), headerSize(s), id(id) {
58 175 : file = filesystem::File::open_tmp(config::UPLOAD_TMP_FILE_PREFIX, false);
59 175 : path = file.path();
60 175 : }
61 :
62 300 : InputFile::~InputFile() {
63 300 : close();
64 300 : }
65 :
66 100 : bool InputFile::isOpen() const {
67 100 : return file.is_open();
68 : }
69 :
70 7850 : size_t InputFile::write(const char *s, size_t n) {
71 7850 : auto tmp = s;
72 1975700 : for (size_t i = 0; i < n; ++ i) {
73 1967850 : if (*tmp == 0) {
74 7550 : isBinary = true;
75 : }
76 1967850 : ++ tmp;
77 : }
78 7850 : writeSize += n;
79 7850 : return file.xsputn(s, n);
80 : }
81 :
82 475 : void InputFile::close() {
83 475 : file.close_remove();
84 475 : }
85 :
86 100 : bool InputFile::save(const StringView &ipath) const {
87 100 : return const_cast<filesystem::File &>(file).close_rename(filesystem::cachesPath<Interface>(ipath).data());
88 : }
89 :
90 25 : Bytes InputFile::readBytes() {
91 25 : Bytes ret;
92 25 : ret.resize(writeSize);
93 25 : file.seek(0, stappler::io::Seek::Set);
94 25 : file.xsgetn((char *)ret.data(), ret.size());
95 25 : return ret;
96 0 : }
97 :
98 25 : String InputFile::readText() {
99 25 : if (!isBinary) {
100 25 : String ret;
101 25 : ret.resize(writeSize);
102 25 : file.seek(0, stappler::io::Seek::Set);
103 25 : file.xsgetn((char *)ret.data(), ret.size());
104 25 : return ret;
105 25 : }
106 0 : return String();
107 : }
108 :
109 :
110 42700 : InputValue::InputValue(InputValue &&other) : type(other.type) {
111 42700 : switch (type) {
112 42700 : case Type::Value:
113 42700 : new (&value) db::Value(move(other.value));
114 42700 : break;
115 0 : case Type::File:
116 0 : file = other.file;
117 0 : break;
118 0 : case Type::TSV:
119 0 : new (&tsv) FullTextVector(move(other.tsv));
120 0 : break;
121 0 : case Type::None:
122 0 : break;
123 : }
124 42700 : other.clear();
125 42700 : }
126 :
127 2550 : InputValue &InputValue::operator=(InputValue &&other) {
128 2550 : clear();
129 2550 : type = other.type;
130 2550 : switch (type) {
131 0 : case Type::Value:
132 0 : new (&value) db::Value(move(other.value));
133 0 : break;
134 0 : case Type::File:
135 0 : file = other.file;
136 0 : break;
137 2550 : case Type::TSV:
138 2550 : new (&tsv) FullTextVector(move(other.tsv));
139 2550 : break;
140 0 : case Type::None:
141 0 : break;
142 : }
143 2550 : other.clear();
144 2550 : return *this;
145 : }
146 :
147 0 : InputValue::InputValue(const InputValue &other) : type(other.type) {
148 0 : switch (type) {
149 0 : case Type::Value:
150 0 : new (&value) db::Value(other.value);
151 0 : break;
152 0 : case Type::File:
153 0 : file = other.file;
154 0 : break;
155 0 : case Type::TSV:
156 0 : new (&tsv) FullTextVector(other.tsv);
157 0 : break;
158 0 : case Type::None:
159 0 : break;
160 : }
161 0 : }
162 :
163 0 : InputValue &InputValue::operator=(const InputValue &other) {
164 0 : clear();
165 0 : type = other.type;
166 0 : switch (type) {
167 0 : case Type::Value:
168 0 : new (&value) db::Value(other.value);
169 0 : break;
170 0 : case Type::File:
171 0 : file = other.file;
172 0 : break;
173 0 : case Type::TSV:
174 0 : new (&tsv) FullTextVector(other.tsv);
175 0 : break;
176 0 : case Type::None:
177 0 : break;
178 : }
179 0 : return *this;
180 : }
181 :
182 129575 : void InputValue::clear() {
183 129575 : switch (type) {
184 79225 : case Type::Value:
185 79225 : value.~Value();
186 79225 : break;
187 0 : case Type::File:
188 0 : file = nullptr;
189 0 : break;
190 5100 : case Type::TSV:
191 5100 : tsv.~SearchVector();
192 5100 : break;
193 45250 : case Type::None:
194 45250 : break;
195 : }
196 129575 : type = Type::None;
197 129575 : }
198 :
199 81775 : InputValue::~InputValue() {
200 81775 : clear();
201 81775 : }
202 :
203 300 : static size_t processExtraVarSize(const FieldExtra *s) {
204 300 : size_t ret = 256;
205 1025 : for (auto it : s->fields) {
206 725 : auto t = it.second.getType();
207 725 : if (t == Type::Text || t == Type::Bytes) {
208 400 : auto f = static_cast<const FieldText *>(it.second.getSlot());
209 400 : ret = std::max(f->maxLength, ret);
210 725 : } else if (t == Type::Extra) {
211 0 : auto f = static_cast<const FieldExtra *>(it.second.getSlot());
212 0 : ret = std::max(processExtraVarSize(f), ret);
213 : }
214 725 : }
215 300 : return ret;
216 : }
217 :
218 300 : static size_t updateFieldLimits(const Map<String, Field> &vec) {
219 300 : size_t ret = 256 * vec.size();
220 1025 : for (auto &it : vec) {
221 725 : auto t = it.second.getType();
222 725 : if (t == Type::Text || t == Type::Bytes) {
223 400 : auto f = static_cast<const FieldText *>(it.second.getSlot());
224 400 : ret += std::max(f->maxLength, f->inputSizeHint);
225 725 : } else if (t == Type::Data || t == Type::Array) {
226 125 : ret += std::max(config::FIELD_EXTRA_DEFAULT_HINT_SIZE, it.second.getSlot()->inputSizeHint);
227 200 : } else if (t == Type::Extra) {
228 0 : auto f = static_cast<const FieldExtra *>(it.second.getSlot());
229 0 : ret += updateFieldLimits(f->fields) + f->fields.size() * 8;
230 : } else {
231 200 : ret += 256;
232 : }
233 : }
234 300 : return ret;
235 : }
236 :
237 50 : bool InputConfig::isFileAsDataSupportedForType(StringView type) {
238 50 : return type.starts_with(data::MIME_CBOR) || type.starts_with(data::MIME_JSON);
239 : }
240 :
241 875 : void InputConfig::updateLimits(const Map<String, Field> &fields) {
242 875 : maxRequestSize = 256 * fields.size();
243 6700 : for (auto &it : fields) {
244 5825 : auto t = it.second.getType();
245 5825 : if (t == Type::File) {
246 125 : auto f = static_cast<const FieldFile *>(it.second.getSlot());
247 125 : maxFileSize = std::max(std::max(f->maxSize, f->inputSizeHint), maxFileSize);
248 125 : maxRequestSize += std::max(f->maxSize, f->inputSizeHint) + 256;
249 5700 : } else if (t == Type::Image) {
250 400 : auto f = static_cast<const FieldImage *>(it.second.getSlot());
251 400 : maxFileSize = std::max(std::max(f->maxSize, f->inputSizeHint), maxFileSize);
252 400 : maxRequestSize += std::max(f->maxSize, f->inputSizeHint) + 256;
253 5300 : } else if (t == Type::Text || t == Type::Bytes) {
254 1625 : auto f = static_cast<const FieldText *>(it.second.getSlot());
255 1625 : maxVarSize = std::max(std::max(f->maxLength, f->inputSizeHint), maxVarSize);
256 1625 : maxRequestSize += std::max(f->maxLength, f->inputSizeHint);
257 5300 : } else if (t == Type::Data || t == Type::Array) {
258 525 : maxRequestSize += std::max(config::FIELD_EXTRA_DEFAULT_HINT_SIZE, it.second.getSlot()->inputSizeHint);
259 3150 : } else if (t == Type::Extra) {
260 300 : auto f = static_cast<const FieldExtra *>(it.second.getSlot());
261 300 : maxRequestSize += updateFieldLimits(f->fields) + f->fields.size() * 8;
262 300 : maxVarSize = std::max(processExtraVarSize(f), maxVarSize);
263 : }
264 : }
265 875 : }
266 :
267 : }
|