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 "net/config/ConfigInstanceAPI.hpp"
48
49#ifndef DOXYGEN_SHOULD_SKIP_THIS
50
51#include "log/Logger.h"
52
53#include <cstdlib>
54#include <functional>
55#include <mysql.h>
56#include <string>
57#include <string_view>
58
59#endif /* DOXYGEN_SHOULD_SKIP_THIS */
60
61class ConfigDb {
62public:
63 constexpr static std::string_view name{"db"};
64 constexpr static std::string_view description{"Database connection"};
65
67 : configDbSc(
68 utils::Config::newInstance(net::config::Instance(std::string(name), std::string(description), this), "Database", true)) {
69 hostOpt = configDbSc->add_option("--db-host", "Hostname of IP-Address of Server")
70 ->group(configDbSc->get_formatter()->get_label("Persistent Options"))
71 ->type_name("[hostname|IP-address]")
72 ->configurable()
73 ->required();
74
75 configDbSc->needs(hostOpt)->required();
76 configDbSc->get_parent()->needs(configDbSc);
77 }
78
79 ConfigDb& setHost(const std::string& host) {
80 hostOpt->default_str(host)->clear();
81 hostOpt->required(false);
82
83 configDbSc->remove_needs(hostOpt);
84 configDbSc->required(false);
85 configDbSc->get_parent()->remove_needs(configDbSc);
86
87 return *this;
88 }
89
90 std::string getHost() {
91 return hostOpt->as<std::string>();
92 }
93
94private:
96 CLI::Option* hostOpt;
97};
98
99int main(int argc, char* argv[]) {
100 utils::Config::addInstance<ConfigDb>()->setHost("localhost");
101
102 core::SNodeC::init(argc, argv);
103
104 const database::mariadb::MariaDBConnectionDetails details = {
105 .connectionName = "testconnection",
106 .hostname = utils::Config::getInstance<ConfigDb>()->getHost(),
107 .username = "snodec",
108 .password = "pentium5",
109 .database = "snodec",
110 .port = 3306,
111 .socket = "/run/mysqld/mysqld.sock",
112 .flags = 0,
113 };
114
115 // CREATE DATABASE snodec;
116 // CREATE TABLE snodec (username text NOT NULL, password text NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
117 // CREATE USER 'snodec'@localhost IDENTIFIED BY 'pentium5';
118 // GRANT ALL PRIVILEGES ON *.* TO 'snodec'@localhost;
119 // GRANT ALL PRIVILEGES ON snodec.snodec TO 'snodec'@localhost;
120 // FLUSH PRIVILEGES;
121
122 database::mariadb::MariaDBClient db1(details, [](const database::mariadb::MariaDBState& state) {
123 if (state.error != 0) {
124 VLOG(0) << "MySQL error: " << state.errorMessage << " [" << state.error << "]";
125 } else if (state.connected) {
126 VLOG(0) << "MySQL connected";
127 } else {
128 VLOG(0) << "MySQL disconnected";
129 }
130 });
131
132 int r = 0;
133
134 db1.exec(
135 "DELETE FROM `snodec`",
136 [&db1](void) -> void {
137 VLOG(0) << "********** OnQuery 0;";
138 db1.affectedRows(
139 [](my_ulonglong affectedRows) -> void {
140 VLOG(0) << "********** AffectedRows 1: " << affectedRows;
141 },
142 [](const std::string& errorString, unsigned int errorNumber) -> void {
143 VLOG(0) << "Error 1: " << errorString << " : " << errorNumber;
144 });
145 },
146 [](const std::string& errorString, unsigned int errorNumber) -> void {
147 VLOG(0) << "********** Error 0: " << errorString << " : " << errorNumber;
148 })
149
150 .exec(
151 "INSERT INTO `snodec`(`username`, `password`) VALUES ('Annett','Hallo')",
152 [&db1](void) -> void {
153 VLOG(0) << "********** OnQuery 1: ";
154 db1.affectedRows(
155 [](my_ulonglong affectedRows) -> void {
156 VLOG(0) << "********** AffectedRows 2: " << affectedRows;
157 },
158 [](const std::string& errorString, unsigned int errorNumber) -> void {
159 VLOG(0) << "********** Error 2: " << errorString << " : " << errorNumber;
160 });
161 },
162 [](const std::string& errorString, unsigned int errorNumber) -> void {
163 VLOG(0) << "********** Error 1: " << errorString << " : " << errorNumber;
164 })
165 .query(
166 "SELECT * FROM snodec",
167 [&r](const MYSQL_ROW row) -> void {
168 if (row != nullptr) {
169 VLOG(0) << "********** Row Result 2: " << row[0] << " : " << row[1];
170 r++;
171 } else {
172 VLOG(0) << "********** Row Result 2: " << r;
173 }
174 },
175 [](const std::string& errorString, unsigned int errorNumber) -> void {
176 VLOG(0) << "********** Error 2: " << errorString << " : " << errorNumber;
177 })
178 .query(
179 "SELECT * FROM snodec",
180 [&r](const MYSQL_ROW row) -> void {
181 if (row != nullptr) {
182 VLOG(0) << "********** Row Result 2: " << row[0] << " : " << row[1];
183 r++;
184 } else {
185 VLOG(0) << "********** Row Result 2: " << r;
186 }
187 },
188 [](const std::string& errorString, unsigned int errorNumber) -> void {
189 VLOG(0) << "********** Error 2: " << errorString << " : " << errorNumber;
190 });
191
192 database::mariadb::MariaDBClient db2(details, [](const database::mariadb::MariaDBState& state) {
193 if (state.error != 0) {
194 VLOG(0) << "MySQL error: " << state.errorMessage << " [" << state.error << "]";
195 } else if (state.connected) {
196 VLOG(0) << "MySQL connected";
197 } else {
198 VLOG(0) << "MySQL disconnected";
199 }
200 });
201
202 int r1 = 0;
203 int r2 = 0;
204 {
205 db2.query(
206 "SELECT * FROM snodec",
207 [](const MYSQL_ROW row) -> void {
208 if (row != nullptr) {
209 VLOG(0) << "Row Result 3: " << row[0] << " : " << row[1];
210 } else {
211 VLOG(0) << "Row Result 3:";
212 }
213 },
214 [](const std::string& errorString, unsigned int errorNumber) -> void {
215 VLOG(0) << "Error 3: " << errorString << " : " << errorNumber;
216 });
217
218 db2.query(
219 "SELECT * FROM snodec",
220 [&db2, &r1, &r2](const MYSQL_ROW row) -> void {
221 if (row != nullptr) {
222 VLOG(0) << "Row Result 4: " << row[0] << " : " << row[1];
223 } else {
224 VLOG(0) << "Row Result 4:";
225
226 db2.query(
227 "SELECT * FROM snodec",
228 [&db2, &r1, &r2](const MYSQL_ROW row) -> void {
229 if (row != nullptr) {
230 VLOG(0) << "Row Result 5: " << row[0] << " : " << row[1];
231 } else { // After all results have been fetched
232 VLOG(0) << "Row Result 5:";
233
234 core::timer::Timer dbTimer1 = core::timer::Timer::intervalTimer(
235 [&db2, &r1](const std::function<void()>& stop) -> void {
236 static int i = 0;
237 VLOG(0) << "Tick 2: " << i++;
238
239 r1 = 0;
240 db2.query(
241 "SELECT * FROM snodec",
242 [&r1](const MYSQL_ROW row) -> void {
243 if (row != nullptr) {
244 VLOG(0) << "Row Result 6: " << row[0] << " : " << row[1];
245 r1++;
246 } else {
247 VLOG(0) << "Row Result 6: " << r1;
248 }
249 },
250 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
251 VLOG(0) << "Error 6: " << errorString << " : " << errorNumber;
252 stop();
253 });
254 },
255 2);
256
257 core::timer::Timer dbTimer2 = core::timer::Timer::intervalTimer(
258 [&db2, &r2](const std::function<void()>& stop) -> void {
259 static int i = 0;
260 VLOG(0) << "Tick 0.7: " << i++;
261
262 r2 = 0;
263 db2.query(
264 "SELECT * FROM snodec",
265 [&db2, &r2](const MYSQL_ROW row) -> void {
266 if (row != nullptr) {
267 VLOG(0) << "Row Result 7: " << row[0] << " : " << row[1];
268 r2++;
269 } else {
270 VLOG(0) << "Row Result 7: " << r2;
271 db2.fieldCount(
272 [](unsigned int fieldCount) -> void {
273 VLOG(0) << "************ FieldCount ************ = " << fieldCount;
274 },
275 [](const std::string& errorString, unsigned int errorNumber) -> void {
276 VLOG(0) << "Error 7: " << errorString << " : " << errorNumber;
277 });
278 }
279 },
280 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
281 VLOG(0) << "Error 7: " << errorString << " : " << errorNumber;
282 stop();
283 })
284 .fieldCount(
285 [](unsigned int fieldCount) -> void {
286 VLOG(0) << "************ FieldCount ************ = " << fieldCount;
287 },
288 [](const std::string& errorString, unsigned int errorNumber) -> void {
289 VLOG(0) << "Error 7: " << errorString << " : " << errorNumber;
290 });
291 },
292 0.7);
293 }
294 },
295 [](const std::string& errorString, unsigned int errorNumber) -> void {
296 VLOG(0) << "Error 5: " << errorString << " : " << errorNumber;
297 });
298 }
299 },
300 [](const std::string& errorString, unsigned int errorNumber) -> void {
301 VLOG(0) << "Error 4: " << errorString << " : " << errorNumber;
302 });
303
304 core::timer::Timer dbTimer = core::timer::Timer::intervalTimer(
305 [&db2](const std::function<void()>& stop) -> void {
306 static int i = 0;
307 VLOG(0) << "Tick 0.1: " << i++;
308
309 if (i >= 60000) {
310 VLOG(0) << "Stop Stop";
311 stop();
312 }
313
314 int j = i;
315 db2.startTransactions(
316 [](void) -> void {
317 VLOG(0) << "Transactions activated 10:";
318 },
319 [](const std::string& errorString, unsigned int errorNumber) -> void {
320 VLOG(0) << "Error 8: " << errorString << " : " << errorNumber;
321 })
322 .exec(
323 "INSERT INTO `snodec`(`username`, `password`) VALUES ('Annett','Hallo')",
324 [&db2, j](void) -> void {
325 VLOG(0) << "Inserted 10: " << j;
326 db2.affectedRows(
327 [](my_ulonglong affectedRows) -> void {
328 VLOG(0) << "AffectedRows 11: " << affectedRows;
329 },
330 [](const std::string& errorString, unsigned int errorNumber) -> void {
331 VLOG(0) << "Error 11: " << errorString << " : " << errorNumber;
332 });
333 },
334 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
335 VLOG(0) << "Error 10: " << errorString << " : " << errorNumber;
336 stop();
337 })
338 .rollback(
339 [](void) -> void {
340 VLOG(0) << "Rollback success 11";
341 },
342 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
343 VLOG(0) << "Error 12: " << errorString << " : " << errorNumber;
344 stop();
345 })
346 .exec(
347 "INSERT INTO `snodec`(`username`, `password`) VALUES ('Annett','Hallo')",
348 [&db2, j](void) -> void {
349 VLOG(0) << "Inserted 13: " << j;
350 db2.affectedRows(
351 [](my_ulonglong affectedRows) -> void {
352 VLOG(0) << "AffectedRows 14: " << affectedRows;
353 },
354 [](const std::string& errorString, unsigned int errorNumber) -> void {
355 VLOG(0) << "Error 14: " << errorString << " : " << errorNumber;
356 });
357 },
358 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
359 VLOG(0) << "Error 13: " << errorString << " : " << errorNumber;
360 stop();
361 })
362 .commit(
363 [](void) -> void {
364 VLOG(0) << "Commit success 15";
365 },
366 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
367 VLOG(0) << "Error 15: " << errorString << " : " << errorNumber;
368 stop();
369 })
370 .query(
371 "SELECT COUNT(*) FROM snodec",
372 [&db2, j, stop](const MYSQL_ROW row) -> void {
373 if (row != nullptr) {
374 VLOG(0) << "Row Result count(*) 16: " << row[0];
375 if (std::atoi(row[0]) != j + 1) { // NOLINT
376 VLOG(0) << "Wrong number of rows 16: " << std::atoi(row[0]) << " != " << j + 1; // NOLINT
377 // exit(1);
378 }
379 } else {
380 VLOG(0) << "Row Result count(*) 16: no result:";
381 db2.fieldCount(
382 [](unsigned int fieldCount) -> void {
383 VLOG(0) << "************ FieldCount ************ = " << fieldCount;
384 },
385 [](const std::string& errorString, unsigned int errorNumber) -> void {
386 VLOG(0) << "Error 7: " << errorString << " : " << errorNumber;
387 });
388 }
389 },
390 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
391 VLOG(0) << "Error 16: " << errorString << " : " << errorNumber;
392 stop();
393 })
394 .endTransactions(
395 [](void) -> void {
396 VLOG(0) << "Transactions deactivated 17";
397 },
398 [stop](const std::string& errorString, unsigned int errorNumber) -> void {
399 VLOG(0) << "Error 17: " << errorString << " : " << errorNumber;
400 stop();
401 });
402 },
403 0.1);
404 }
405
406 return core::SNodeC::start();
407}
static constexpr std::string_view name
CLI::Option * hostOpt
static constexpr std::string_view description
CLI::App * configDbSc
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
static CLI::App * newInstance(std::shared_ptr< CLI::App > appWithPtr, const std::string &group, bool final=false)
Definition Config.cpp:736
int main(int argc, char *argv[])
Definition Timer.h:59