SNode.C
Loading...
Searching...
No Matches
testmariadb.cpp
Go to the documentation of this file.
1/*
2 * SNode.C - A Slim Toolkit for Network Communication
3 * Copyright (C) Volker Christian <me@vchrist.at>
4 * 2020, 2021, 2022, 2023, 2024, 2025, 2026
5 * 2021, 2022 Daniel Flockert
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21/*
22 * MIT License
23 *
24 * Permission is hereby granted, free of charge, to any person obtaining a copy
25 * of this software and associated documentation files (the "Software"), to deal
26 * in the Software without restriction, including without limitation the rights
27 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
28 * copies of the Software, and to permit persons to whom the Software is
29 * furnished to do so, subject to the following conditions:
30 *
31 * The above copyright notice and this permission notice shall be included in
32 * all copies or substantial portions of the Software.
33 *
34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
40 * THE SOFTWARE.
41 */
42
43#include "core/SNodeC.h"
44#include "core/timer/Timer.h"
45#include "database/mariadb/MariaDBClient.h"
46#include "database/mariadb/MariaDBCommandSequence.h"
47#include "utils/Config.h"
48#include "utils/SubCommand.h"
49
50#ifndef DOXYGEN_SHOULD_SKIP_THIS
51
52#include "log/Logger.h"
53
54#include <cstdlib>
55#include <functional>
56#include <mysql.h>
57#include <string>
58#include <string_view>
59
60#endif /* DOXYGEN_SHOULD_SKIP_THIS */
61
62class ConfigDb : public utils::SubCommand {
63public:
64 constexpr static std::string_view NAME{"db"};
65 constexpr static std::string_view DESCRIPTION{"Database connection"};
66
68 : SubCommand(parent, this, "Database") {
70 addOption("--db-host", "Hostname or IP-Address of Server", "hostname|IPv4", CLI::TypeValidator<std::string>()), true);
71
72 required(hostOpt);
73 }
74
75 ConfigDb& setHost(const std::string& host) {
76 setDefaultValue(hostOpt, host);
77 required(hostOpt, false);
78
79 return *this;
80 }
81
82 std::string getHost() {
83 return hostOpt->as<std::string>();
84 }
85
86private:
87 CLI::Option* hostOpt;
88};
89
90int main(int argc, char* argv[]) {
91 utils::Config::configRoot.newSubCommand<ConfigDb>()->setHost("localhost");
92
93 core::SNodeC::init(argc, argv);
94
95 const database::mariadb::MariaDBConnectionDetails details = {
96 .connectionName = "testconnection",
97 .hostname = utils::Config::configRoot.getSubCommand<ConfigDb>()->getHost(),
98 .username = "snodec",
99 .password = "pentium5",
100 .database = "snodec",
101 .port = 3306,
102 .socket = "/run/mysqld/mysqld.sock",
103 .flags = 0,
104 };
105
106 // CREATE DATABASE snodec;
107 // CREATE TABLE snodec (username text NOT NULL, password text NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
108 // CREATE USER 'snodec'@localhost IDENTIFIED BY 'pentium5';
109 // GRANT ALL PRIVILEGES ON *.* TO 'snodec'@localhost;
110 // GRANT ALL PRIVILEGES ON snodec.snodec TO 'snodec'@localhost;
111 // FLUSH PRIVILEGES;
112
113 database::mariadb::MariaDBClient db1(details, [](const database::mariadb::MariaDBState& state) {
114 if (state.error != 0) {
115 VLOG(0) << "MySQL error: " << state.errorMessage << " [" << state.error << "]";
116 } else if (state.connected) {
117 VLOG(0) << "MySQL connected";
118 } else {
119 VLOG(0) << "MySQL disconnected";
120 }
121 });
122
123 int r = 0;
124
125 db1.exec(
126 "DELETE FROM `snodec`",
127 [&db1](void) -> void {
128 VLOG(0) << "********** OnQuery 0;";
129 db1.affectedRows(
130 [](my_ulonglong affectedRows) -> void {
131 VLOG(0) << "********** AffectedRows 1: " << affectedRows;
132 },
133 [](const std::string& errorString, unsigned int errorNumber) -> void {
134 VLOG(0) << "Error 1: " << errorString << " : " << errorNumber;
135 });
136 },
137 [](const std::string& errorString, unsigned int errorNumber) -> void {
138 VLOG(0) << "********** Error 0: " << errorString << " : " << errorNumber;
139 })
140
141 .exec(
142 "INSERT INTO `snodec`(`username`, `password`) VALUES ('Annett','Hallo')",
143 [&db1](void) -> void {
144 VLOG(0) << "********** OnQuery 1: ";
145 db1.affectedRows(
146 [](my_ulonglong affectedRows) -> void {
147 VLOG(0) << "********** AffectedRows 2: " << affectedRows;
148 },
149 [](const std::string& errorString, unsigned int errorNumber) -> void {
150 VLOG(0) << "********** Error 2: " << errorString << " : " << errorNumber;
151 });
152 },
153 [](const std::string& errorString, unsigned int errorNumber) -> void {
154 VLOG(0) << "********** Error 1: " << errorString << " : " << errorNumber;
155 })
156 .query(
157 "SELECT * FROM snodec",
158 [&r](const MYSQL_ROW row) -> void {
159 if (row != nullptr) {
160 VLOG(0) << "********** Row Result 2: " << row[0] << " : " << row[1];
161 r++;
162 } else {
163 VLOG(0) << "********** Row Result 2: " << r;
164 }
165 },
166 [](const std::string& errorString, unsigned int errorNumber) -> void {
167 VLOG(0) << "********** Error 2: " << errorString << " : " << errorNumber;
168 })
169 .query(
170 "SELECT * FROM snodec",
171 [&r](const MYSQL_ROW row) -> void {
172 if (row != nullptr) {
173 VLOG(0) << "********** Row Result 2: " << row[0] << " : " << row[1];
174 r++;
175 } else {
176 VLOG(0) << "********** Row Result 2: " << r;
177 }
178 },
179 [](const std::string& errorString, unsigned int errorNumber) -> void {
180 VLOG(0) << "********** Error 2: " << errorString << " : " << errorNumber;
181 });
182
183 database::mariadb::MariaDBClient db2(details, [](const database::mariadb::MariaDBState& state) {
184 if (state.error != 0) {
185 VLOG(0) << "MySQL error: " << state.errorMessage << " [" << state.error << "]";
186 } else if (state.connected) {
187 VLOG(0) << "MySQL connected";
188 } else {
189 VLOG(0) << "MySQL disconnected";
190 }
191 });
192
193 int r1 = 0;
194 int r2 = 0;
195 {
196 db2.query(
197 "SELECT * FROM snodec",
198 [](const MYSQL_ROW row) -> void {
199 if (row != nullptr) {
200 VLOG(0) << "Row Result 3: " << row[0] << " : " << row[1];
201 } else {
202 VLOG(0) << "Row Result 3:";
203 }
204 },
205 [](const std::string& errorString, unsigned int errorNumber) -> void {
206 VLOG(0) << "Error 3: " << errorString << " : " << errorNumber;
207 });
208
209 db2.query(
210 "SELECT * FROM snodec",
211 [&db2, &r1, &r2](const MYSQL_ROW row) -> void {
212 if (row != nullptr) {
213 VLOG(0) << "Row Result 4: " << row[0] << " : " << row[1];
214 } else {
215 VLOG(0) << "Row Result 4:";
216
217 db2.query(
218 "SELECT * FROM snodec",
219 [&db2, &r1, &r2](const MYSQL_ROW row) -> void {
220 if (row != nullptr) {
221 VLOG(0) << "Row Result 5: " << row[0] << " : " << row[1];
222 } else { // After all results have been fetched
223 VLOG(0) << "Row Result 5:";
224
225 core::timer::Timer dbTimer1 = core::timer::Timer::intervalTimer(
226 [&db2, &r1](const std::function<void()>& stop) -> void {
227 static int i = 0;
228 VLOG(0) << "Tick 2: " << i++;
229
230 r1 = 0;
231 db2.query(
232 "SELECT * FROM snodec",
233 [&r1](const MYSQL_ROW row) -> void {
234 if (row != nullptr) {
235 VLOG(0) << "Row Result 6: " << row[0] << " : " << row[1];
236 r1++;
237 } else {
238 VLOG(0) << "Row Result 6: " << r1;
239 }
240 },
241 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
242 VLOG(0) << "Error 6: " << errorString << " : " << errorNumber;
243 stop();
244 });
245 },
246 2);
247
248 core::timer::Timer dbTimer2 = core::timer::Timer::intervalTimer(
249 [&db2, &r2](const std::function<void()>& stop) -> void {
250 static int i = 0;
251 VLOG(0) << "Tick 0.7: " << i++;
252
253 r2 = 0;
254 db2.query(
255 "SELECT * FROM snodec",
256 [&db2, &r2](const MYSQL_ROW row) -> void {
257 if (row != nullptr) {
258 VLOG(0) << "Row Result 7: " << row[0] << " : " << row[1];
259 r2++;
260 } else {
261 VLOG(0) << "Row Result 7: " << r2;
262 db2.fieldCount(
263 [](unsigned int fieldCount) -> void {
264 VLOG(0) << "************ FieldCount ************ = " << fieldCount;
265 },
266 [](const std::string& errorString, unsigned int errorNumber) -> void {
267 VLOG(0) << "Error 7: " << errorString << " : " << errorNumber;
268 });
269 }
270 },
271 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
272 VLOG(0) << "Error 7: " << errorString << " : " << errorNumber;
273 stop();
274 })
275 .fieldCount(
276 [](unsigned int fieldCount) -> void {
277 VLOG(0) << "************ FieldCount ************ = " << fieldCount;
278 },
279 [](const std::string& errorString, unsigned int errorNumber) -> void {
280 VLOG(0) << "Error 7: " << errorString << " : " << errorNumber;
281 });
282 },
283 0.7);
284 }
285 },
286 [](const std::string& errorString, unsigned int errorNumber) -> void {
287 VLOG(0) << "Error 5: " << errorString << " : " << errorNumber;
288 });
289 }
290 },
291 [](const std::string& errorString, unsigned int errorNumber) -> void {
292 VLOG(0) << "Error 4: " << errorString << " : " << errorNumber;
293 });
294
295 core::timer::Timer dbTimer = core::timer::Timer::intervalTimer(
296 [&db2](const std::function<void()>& stop) -> void {
297 static int i = 0;
298 VLOG(0) << "Tick 0.1: " << i++;
299
300 if (i >= 60000) {
301 VLOG(0) << "Stop Stop";
302 stop();
303 }
304
305 int j = i;
306 db2.startTransactions(
307 [](void) -> void {
308 VLOG(0) << "Transactions activated 10:";
309 },
310 [](const std::string& errorString, unsigned int errorNumber) -> void {
311 VLOG(0) << "Error 8: " << errorString << " : " << errorNumber;
312 })
313 .exec(
314 "INSERT INTO `snodec`(`username`, `password`) VALUES ('Annett','Hallo')",
315 [&db2, j](void) -> void {
316 VLOG(0) << "Inserted 10: " << j;
317 db2.affectedRows(
318 [](my_ulonglong affectedRows) -> void {
319 VLOG(0) << "AffectedRows 11: " << affectedRows;
320 },
321 [](const std::string& errorString, unsigned int errorNumber) -> void {
322 VLOG(0) << "Error 11: " << errorString << " : " << errorNumber;
323 });
324 },
325 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
326 VLOG(0) << "Error 10: " << errorString << " : " << errorNumber;
327 stop();
328 })
329 .rollback(
330 [](void) -> void {
331 VLOG(0) << "Rollback success 11";
332 },
333 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
334 VLOG(0) << "Error 12: " << errorString << " : " << errorNumber;
335 stop();
336 })
337 .exec(
338 "INSERT INTO `snodec`(`username`, `password`) VALUES ('Annett','Hallo')",
339 [&db2, j](void) -> void {
340 VLOG(0) << "Inserted 13: " << j;
341 db2.affectedRows(
342 [](my_ulonglong affectedRows) -> void {
343 VLOG(0) << "AffectedRows 14: " << affectedRows;
344 },
345 [](const std::string& errorString, unsigned int errorNumber) -> void {
346 VLOG(0) << "Error 14: " << errorString << " : " << errorNumber;
347 });
348 },
349 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
350 VLOG(0) << "Error 13: " << errorString << " : " << errorNumber;
351 stop();
352 })
353 .commit(
354 [](void) -> void {
355 VLOG(0) << "Commit success 15";
356 },
357 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
358 VLOG(0) << "Error 15: " << errorString << " : " << errorNumber;
359 stop();
360 })
361 .query(
362 "SELECT COUNT(*) FROM snodec",
363 [&db2, j, stop](const MYSQL_ROW row) -> void {
364 if (row != nullptr) {
365 VLOG(0) << "Row Result count(*) 16: " << row[0];
366 if (std::atoi(row[0]) != j + 1) { // NOLINT
367 VLOG(0) << "Wrong number of rows 16: " << std::atoi(row[0]) << " != " << j + 1; // NOLINT
368 // exit(1);
369 }
370 } else {
371 VLOG(0) << "Row Result count(*) 16: no result:";
372 db2.fieldCount(
373 [](unsigned int fieldCount) -> void {
374 VLOG(0) << "************ FieldCount ************ = " << fieldCount;
375 },
376 [](const std::string& errorString, unsigned int errorNumber) -> void {
377 VLOG(0) << "Error 7: " << errorString << " : " << errorNumber;
378 });
379 }
380 },
381 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
382 VLOG(0) << "Error 16: " << errorString << " : " << errorNumber;
383 stop();
384 })
385 .endTransactions(
386 [](void) -> void {
387 VLOG(0) << "Transactions deactivated 17";
388 },
389 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
390 VLOG(0) << "Error 17: " << errorString << " : " << errorNumber;
391 stop();
392 });
393 },
394 0.1);
395 }
396
397 return core::SNodeC::start();
398}
#define VLOG(level)
Definition Logger.h:164
ConfigDb(SubCommand *parent)
CLI::Option * hostOpt
static constexpr std::string_view NAME
static constexpr std::string_view DESCRIPTION
ConfigDb & setHost(const std::string &host)
std::string getHost()
static void init(int argc, char *argv[])
Definition SNodeC.cpp:54
static int start(const utils::Timeval &timeOut={LONG_MAX, 0})
Definition SNodeC.cpp:60
LogMessage(Level level, int verboseLevel=-1, bool withErrno=false)
Definition Logger.cpp:280
static ConfigRoot configRoot
Definition Config.h:116
CLI::Option * setConfigurable(CLI::Option *option, bool configurable) const
int main(int argc, char *argv[])
Definition Timer.h:59